|
|
  |
FreeModbus |
|
|
|
Mar 3 2011, 08:28
|

Беспросветный оптимист
     
Группа: Свой
Сообщений: 4 640
Регистрация: 26-12-07
Из: Н.Новгород
Пользователь №: 33 646

|
Цитата(alux @ Mar 3 2011, 10:44)  Так где я не прав? Покажите ещё СВ-функцию чтения регистров Далее, ReadOutputRegisters - это какая функция? (код функции) Вообще-то, при чтении Input регистров как бы нужна функция ReadInput, но точно можно определить по коду. Ну или пакет запроса приведите.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Mar 3 2011, 08:28
|
Частый гость
 
Группа: Свой
Сообщений: 120
Регистрация: 21-08-06
Из: СПб
Пользователь №: 19 701

|
В разных реализациях по разному отсчитываются адреса. Holding начинаются с 40000 по терминологии modbus, а в вызове функции может быть отсчёт и от 0, и от 1. Попробуйте вот этой утилитой потестить: http://www.chipkin.com/cas-modbus-scannerВ ней, например, для чтения holding register 9 нужно задать такие настройки (см аттач).
Эскизы прикрепленных изображений
|
|
|
|
|
Mar 3 2011, 08:47
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
Со стороны мастера (ПК) Код //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
|
|
|
|
|
Mar 3 2011, 09:59
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
со стороны мастера изменил запрос на Код 01 04 03 E8 00 01 B1 BA ответ уже без ошибки: Код 01 04 02 00 00 B9 30 но это не то, что я ожидаю получить. Я должен получить инкрементированное значение usRegInputBuf[0]++; Что еще не так?
|
|
|
|
|
Mar 3 2011, 10:27
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
Цитата(Dimoza @ Mar 3 2011, 14:17)  в ответе должно быть два байта ячейки usRegInputBuf[0]. Если вы её никак не инициализируете, то будет возвращаться неопределённое значение. Скорее всего именно нули. Глобальная переменная инициализируется нулем. Дальше в цикле она инкрементируется: Код usRegInputBuf[0]++; Т.е. я должен увидеть на приеме 0,1,2,3... Цитата(MrYuran @ Mar 3 2011, 14:10)  А вот тут уже возможно играет смещение на 1. Попробуйте ещё соседний регистр поменять. а вот так: Код usRegInputBuf[1]++; уже отвечает то, что нужно! А где необходимо добавить это смещение на 1 ?
|
|
|
|
|
Mar 4 2011, 22:35
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
Вот ответ автора 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?
|
|
|
|
|
Mar 5 2011, 10:26
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
Как правильно передать код ошибки 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;
|
|
|
|
|
Mar 7 2011, 11:47
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
Еще для полного счастья нужно использовать функции для записи\чтения битов 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)
|
|
|
|
|
  |
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|