Перейти к содержанию
    

Так где я не прав?

Покажите ещё СВ-функцию чтения регистров

Далее, ReadOutputRegisters - это какая функция? (код функции)

Вообще-то, при чтении Input регистров как бы нужна функция ReadInput, но точно можно определить по коду.

Ну или пакет запроса приведите.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В разных реализациях по разному отсчитываются адреса. Holding начинаются с 40000 по терминологии modbus, а в вызове функции может быть отсчёт и от 0, и от 1. Попробуйте вот этой утилитой потестить:

http://www.chipkin.com/cas-modbus-scanner

В ней, например, для чтения holding register 9 нужно задать такие настройки (см аттач).

post-19701-1299140852_thumb.jpg

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Со стороны мастера (ПК)

//Modbus Functions 
const BYTE CModbus::READ_OUTPUT_REGISTERS      = 3;

 

из примера freemodbus:

eMBErrorCode
eMBRegInputCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNRegs )
{
    eMBErrorCode    eStatus = MB_ENOERR;
    int             iRegIndex;

    if( ( usAddress >= REG_INPUT_START )
        && ( usAddress + usNRegs <= REG_INPUT_START + REG_INPUT_NREGS ) )
    {
        iRegIndex = ( int )( usAddress - usRegInputStart );
        while( usNRegs > 0 )
        {
            *pucRegBuffer++ =
                ( unsigned char )( usRegInputBuf[iRegIndex] >> 8 );
            *pucRegBuffer++ =
                ( unsigned char )( usRegInputBuf[iRegIndex] & 0xFF );
            iRegIndex++;
            usNRegs--;
        }
    }
    else
    {
        eStatus = MB_ENOREG;
    }

    return eStatus;
}

 

пакет запроса:

 01 03 03 E8 00 01 04 7A

ответ:

01 83 04 40

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Сдаётся мне, вы холдинги хотите прочитать вместо инпутов.

Проверьте тогда ещё константы

REG_HOLDING_START и REG_HOLDING_NREGS

 

Для чтения Input регистров функция 04

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

со стороны мастера изменил запрос на

 01 04 03 E8 00 01 B1 BA

 

ответ уже без ошибки:

01 04 02 00 00 B9 30

 

но это не то, что я ожидаю получить. Я должен получить инкрементированное значение usRegInputBuf[0]++;

Что еще не так?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

но это не то, что я ожидаю получить. Я должен получить инкрементированное значение usRegInputBuf[0]++;

Что еще не так?

А вот тут уже возможно играет смещение на 1.

Попробуйте ещё соседний регистр поменять.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Если я ничего не путаю, в ответе должно быть два байта ячейки usRegInputBuf[0]. Если вы её никак не инициализируете, то будет возвращаться неопределённое значение. Скорее всего именно нули.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

в ответе должно быть два байта ячейки usRegInputBuf[0]. Если вы её никак не инициализируете, то будет возвращаться неопределённое значение. Скорее всего именно нули.

Глобальная переменная инициализируется нулем. Дальше в цикле она инкрементируется:

usRegInputBuf[0]++;

Т.е. я должен увидеть на приеме 0,1,2,3...

 

А вот тут уже возможно играет смещение на 1.

Попробуйте ещё соседний регистр поменять.

а вот так:

usRegInputBuf[1]++;

уже отвечает то, что нужно!

 

А где необходимо добавить это смещение на 1 ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А где необходимо добавить это смещение на 1 ?

Ну, чтобы не лезть в глубины, можно в CB-функции подправить вычисление iRegIndex

Хотя, идеологически более правильно залезть внутрь и разобраться, почему так.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вот ответ автора freemodbus на проблему смещения адреса:

MODBUS protocol address (Base0) is Address 1 in the FreeMODBUS stack. The term PLC address is no longer correct.
The MODBUS PDU addresses registers at 0. The MODBUS application protocol start address at 1.
For MODBUS POLL testing simply add 1 to the register you set when you use Base 0 and you should get the address which FreeMODBUS uses.

 

т.е. нужно добавить 1 в определении

#define REG_HOLDING_START 1001

 

PS. А вопрос был такой:

I’m using Modbus Poll to debug he FreeModbus programs. If REG_HOLDING_START is set to be 1000, the valid address of Modbus Poll looks like this:
PLC Addresses (Base1) = 31000
Protocol Addresses (Base0) = 00999
But if REG_HOLDING_START is set to be 0, the first address of Protocol Addresses cannot be found because the address cannot be -1.
Do you recommend not to use REG_HOLDING_START = 0 in this case?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Насколько я уяснил это для себя, "по-простому", в modbus нумерация регистров и койлов начинается с 1. Так для пользователя оборудования будет проще: сложно обычному человеку понять, что такое нулевой датчик. А вот 1, 2, 3 и так далее - уже проще. НО! В передаваемом пакете modbus этому самому 1-му датчику будет соответствовать адрес 0.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как правильно передать код ошибки MB_EX_SLAVE_BUSY = 0х06 , в случае, если SLAVE занят вычислениями, т.е. результат еще не готов?

Функцию опроса ModBus я поместил в другую функцию, которую периодически вызываю по таймеру:

void MBPoll()
{
  (void)eMBPoll();
}

Я вижу выход такой:

в функции eMBErrorCode eMBRegHoldingCB(...) по глобальному флагу Busy,

if(Busy) eStatus = MB_ETIMEDOUT;
else
...

, возвращаемое значение из этой функции преобразуется в исключение MB_EX_SLAVE_BUSY;

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Я вижу выход такой:

Ну да, как-то так.

Я, кстати, смещение на 1 тоже задал в дефайне, не долго думая :)

(заглянул по случаю, освежил память)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Еще для полного счастья нужно использовать функции для записи\чтения битов ForceSingleCoil (0x05), ReadSingleCoil(0x01).

Приведите, пожалуйста, пример с использованием этих функций. Флаги, битовое поле в области ввода-вывода ниже 0x1f.

// Flags
typedef union
{
    unsigned char Complete;   // Access all 8 bits
    
    struct
    {
        bool IsTestCompleted   : 1;    
        bool IsDataReady      : 1;      
        bool IsRelayOn          : 1;  
        bool IsReset          : 1;   
        bool IsOverheat          : 1;   
        bool IsKeyPressed      : 1; 
        bool IsOpenoff              : 1;  
        bool IsShortcut          : 1;  
    };
} FLAGS;
__no_init volatile FLAGS Flags@0x28; // Флаги, битовое поле в области ввода-вывода ниже 0x1f (ACSR Register)

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Еще для полного счастья нужно использовать функции для записи\чтения битов ForceSingleCoil (0x05), ReadSingleCoil(0x01).

Не пробовал, т.к. особого смысла не вижу.

Не проще ли все флаги оптом передать в регистре статуса, например?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...