MrYuran 29 3 марта, 2011 Опубликовано 3 марта, 2011 · Жалоба Так где я не прав? Покажите ещё СВ-функцию чтения регистров Далее, ReadOutputRegisters - это какая функция? (код функции) Вообще-то, при чтении Input регистров как бы нужна функция ReadInput, но точно можно определить по коду. Ну или пакет запроса приведите. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dimoza 0 3 марта, 2011 Опубликовано 3 марта, 2011 · Жалоба В разных реализациях по разному отсчитываются адреса. Holding начинаются с 40000 по терминологии modbus, а в вызове функции может быть отсчёт и от 0, и от 1. Попробуйте вот этой утилитой потестить: http://www.chipkin.com/cas-modbus-scanner В ней, например, для чтения holding register 9 нужно задать такие настройки (см аттач). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 3 марта, 2011 Опубликовано 3 марта, 2011 · Жалоба Со стороны мастера (ПК) //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 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 29 3 марта, 2011 Опубликовано 3 марта, 2011 · Жалоба Сдаётся мне, вы холдинги хотите прочитать вместо инпутов. Проверьте тогда ещё константы REG_HOLDING_START и REG_HOLDING_NREGS Для чтения Input регистров функция 04 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 3 марта, 2011 Опубликовано 3 марта, 2011 · Жалоба со стороны мастера изменил запрос на 01 04 03 E8 00 01 B1 BA ответ уже без ошибки: 01 04 02 00 00 B9 30 но это не то, что я ожидаю получить. Я должен получить инкрементированное значение usRegInputBuf[0]++; Что еще не так? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 29 3 марта, 2011 Опубликовано 3 марта, 2011 · Жалоба но это не то, что я ожидаю получить. Я должен получить инкрементированное значение usRegInputBuf[0]++; Что еще не так? А вот тут уже возможно играет смещение на 1. Попробуйте ещё соседний регистр поменять. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dimoza 0 3 марта, 2011 Опубликовано 3 марта, 2011 · Жалоба Если я ничего не путаю, в ответе должно быть два байта ячейки usRegInputBuf[0]. Если вы её никак не инициализируете, то будет возвращаться неопределённое значение. Скорее всего именно нули. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 3 марта, 2011 Опубликовано 3 марта, 2011 · Жалоба в ответе должно быть два байта ячейки usRegInputBuf[0]. Если вы её никак не инициализируете, то будет возвращаться неопределённое значение. Скорее всего именно нули. Глобальная переменная инициализируется нулем. Дальше в цикле она инкрементируется: usRegInputBuf[0]++; Т.е. я должен увидеть на приеме 0,1,2,3... А вот тут уже возможно играет смещение на 1. Попробуйте ещё соседний регистр поменять. а вот так: usRegInputBuf[1]++; уже отвечает то, что нужно! А где необходимо добавить это смещение на 1 ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 29 4 марта, 2011 Опубликовано 4 марта, 2011 · Жалоба А где необходимо добавить это смещение на 1 ? Ну, чтобы не лезть в глубины, можно в CB-функции подправить вычисление iRegIndex Хотя, идеологически более правильно залезть внутрь и разобраться, почему так. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 4 марта, 2011 Опубликовано 4 марта, 2011 · Жалоба Вот ответ автора 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? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Dimoza 0 4 марта, 2011 Опубликовано 4 марта, 2011 · Жалоба Насколько я уяснил это для себя, "по-простому", в modbus нумерация регистров и койлов начинается с 1. Так для пользователя оборудования будет проще: сложно обычному человеку понять, что такое нулевой датчик. А вот 1, 2, 3 и так далее - уже проще. НО! В передаваемом пакете modbus этому самому 1-му датчику будет соответствовать адрес 0. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 5 марта, 2011 Опубликовано 5 марта, 2011 · Жалоба Как правильно передать код ошибки 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; Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 29 5 марта, 2011 Опубликовано 5 марта, 2011 · Жалоба Я вижу выход такой: Ну да, как-то так. Я, кстати, смещение на 1 тоже задал в дефайне, не долго думая :) (заглянул по случаю, освежил память) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
alux 0 7 марта, 2011 Опубликовано 7 марта, 2011 · Жалоба Еще для полного счастья нужно использовать функции для записи\чтения битов 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) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 29 7 марта, 2011 Опубликовано 7 марта, 2011 · Жалоба Еще для полного счастья нужно использовать функции для записи\чтения битов ForceSingleCoil (0x05), ReadSingleCoil(0x01). Не пробовал, т.к. особого смысла не вижу. Не проще ли все флаги оптом передать в регистре статуса, например? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться