|
FreeModbus |
|
|
|
 |
Ответов
(1 - 64)
|
Feb 3 2011, 09:18
|

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

|
Цитата(andrewlekar @ Feb 3 2011, 12:13)  Что происходит то? Как побороть? Как обычно. Включить все модули в проект или в пути поиска, если свой мэйкфайл. У меня так сделано: Код ... MODULES += modbus MODULES += modbus/RTU MODULES += modbus/Port MODULES += modbus/Functions MODULES += modbus/system
...
SRCDIRS = $(PROJECT_ROOT)/ SRCDIRS += $(addprefix $(PROJECT_ROOT)/,$(MODULES))
#INCLUDES = -I$(PROJECT_ROOT)/ INCLUDES = $(addprefix -I$(PROJECT_ROOT)/,$(MODULES))
CSRC = $(wildcard $(addsuffix /*.c,$(SRCDIRS))) CPPSRC = $(wildcard $(addsuffix /*.cpp,$(SRCDIRS))) ASRC = $(wildcard $(addsuffix /*.s,$(SRCDIRS))) Ну и не забыть подключить: Код /* ----------------------- Modbus includes ----------------------------------*/ #include "../modbus/include/mb.h" #include "../modbus/include/mbport.h" #include "../modbus/port/port.h"
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Feb 3 2011, 10:16
|

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

|
Цитата(andrewlekar @ Feb 3 2011, 12:59)  Ничего не пойму - сколько на си пишу, такого безобразия не встречал. Нет там никакого безобразия, библиотека сделана очень чётко и грамотно. Подключается буквально в три шага, в документации расписано. Возьмите для начала готовый пример. Чтобы не гадать, выкладывайте, что именно не получается и какие ошибки.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Feb 3 2011, 10:40
|
Знающий
   
Группа: Участник
Сообщений: 837
Регистрация: 8-02-07
Пользователь №: 25 163

|
Ну вот, стало сильно лучше. Помогло волшебное добавление именно в таком порядке Код /* ----------------------- Modbus includes ----------------------------------*/ #include "../modbus/include/mb.h" #include "../modbus/include/mbport.h" #include "../modbus/port/port.h" Причем добавление во все без исключения модули модбаса - иначе нет-нет да поругивалось.
|
|
|
|
|
Feb 24 2011, 07:44
|
Частый гость
 
Группа: Свой
Сообщений: 120
Регистрация: 21-08-06
Из: СПб
Пользователь №: 19 701

|
Цитата(andrewlekar @ Feb 3 2011, 12:59)  версию модбаса использовал 1.3 - может с 1.5 лучше покатит. Собирал недавно проект ModbusTCP на Freemodbus 1.5 - с заголовками такой фигни не было, зато обнаружился другой небольшой глючок: не для всех функций корректно вычислялась длина возвращаемого пакета. Для большинства modbus-мастеров это не принципиально (там длина в пакете двух местах присутствует), но товарищ делал мастера на питоне под линуксом и у него мастер, собранный из готовой библиотеки, ругался на некорректность данных.
|
|
|
|
|
Mar 2 2011, 21:45
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
При сборке проекта были ошибки линкера, пока не подключил #include "mbfunc.h" в некоторых модулях. Проект скомпилировал в IAR v.5.50.0. Безуспешно пытаюсь запустить freemodbus-v1.5. Пробую на разных контроллерах (сейчас на Меге324P 20MHz). Код int main( void ) { eMBErrorCode eStatus;
eStatus = eMBInit( MB_RTU, 0x01, 0, 9600UL, MB_PAR_NONE );
__enable_interrupt();
/* Enable the Modbus Protocol Stack. */ eStatus = eMBEnable( );
for(;; ) { ( void )eMBPoll( );
/* Here we simply count the number of poll cycles. */ usRegInputBuf[0]++; } На запрос чтения одного регистра по адресу 1000 отвечает ошибкой. В чем может быть проблема?
|
|
|
|
|
Mar 2 2011, 22:15
|
Частый гость
 
Группа: Свой
Сообщений: 120
Регистрация: 21-08-06
Из: СПб
Пользователь №: 19 701

|
Цитата(alux @ Mar 3 2011, 00:45)  На запрос чтения одного регистра по адресу 1000 отвечает ошибкой. В чем может быть проблема? В возвращаемом пакете что передаёт? Там ведь пусть небогатая , но есть информация об ошибке.
|
|
|
|
|
Mar 3 2011, 06:31
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
Код 01 83 02 C0 Это ответ на запрос чтения (код 0x03) с устройства №1 одного регистра по адресу 1000. Почему, никак не могу понять? Проект компилируется, правда в IARе, без ошибок.
|
|
|
|
|
Mar 3 2011, 07:28
|
Частый гость
 
Группа: Свой
Сообщений: 120
Регистрация: 21-08-06
Из: СПб
Пользователь №: 19 701

|
Цитата(alux @ Mar 3 2011, 09:31)  То есть возвращает код ошибки - 2. А это означает (см. рисунок), что вы пытаетесь прочитать несуществующий регистр. Обработчик у вас этот адрес обрабатывает?
Эскизы прикрепленных изображений
|
|
|
|
|
Mar 3 2011, 07:44
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
Это из примера freemodbus Код #define REG_INPUT_START 1000 #define REG_INPUT_NREGS 4
static USHORT usRegInputStart = REG_INPUT_START; static USHORT usRegInputBuf[REG_INPUT_NREGS]; Со стороны мастера (ПК) периодически даю запрос на чтение: Код wError = mb.ReadOutputRegisters(1, 1000, 1, wTempData); //адр. устройства, адрес считывания, кол-во считываемых регистров, буфер Так где я не прав?
|
|
|
|
|
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)
|
|
|
|
|
Mar 7 2011, 16:50
|
;
     
Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509

|
Цитата(alux @ Mar 7 2011, 14:47)  Еще для полного счастья нужно использовать функции для записи\чтения битов ForceSingleCoil (0x05), ReadSingleCoil(0x01). Приведите, пожалуйста, пример с использованием этих функций. Флаги, битовое поле в области ввода-вывода ниже 0x1f. А какой гешефт их так описывать? При адресации можно использовать offsetof()/8, биты задавать перечислениями. Получится Код extern #ifdef CORE_32 #define CORE_WD 32 char #else #define CORE_WD 8 int #endif mb_coils[]; enum coils {foo,bar}; static inline bool coil_r(enum coils coil); static inline void coil_w(enum coils coil , bool val); bool coil_r(enum coils coil) { return (mb_coils[coil / CORE_WD] & (1 << coil & (CORE_WD-1)))?true:false; }
|
|
|
|
|
Mar 20 2011, 21:37
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
При использовании функции 0x10 PresetMultipleRegisters запрос от мастера идет как положено (проверяю в Serial Port Monitor), а ответа от слева не поступает. Функция 0x06 PresetSingleRegister работает как положено. В mbconfig.h функция 0x10 разрешена : Код #define MB_FUNC_WRITE_MULTIPLE_HOLDING_ENABLED ( 1 ) В чем может быть проблема?
|
|
|
|
|
Mar 21 2011, 07:09
|
Знающий
   
Группа: Свой
Сообщений: 589
Регистрация: 24-04-05
Пользователь №: 4 447

|
как выяснилось, проблема не в этой функции (0x10), а в адресе регистров, в которые нужно писать. У меня регистры (переменные типа int) упакованы в структуру : Код typedef struct { int NumSensorsDS; int TemperatureTC[NUM_SENSORS]; int Parameter[2][NUM_SENSORS]; int Temperature[2]; int NumSensorsTC; int Cable; int Average; int Data; long Accum; }TValue; В регистры Cable, Average записываются значения и отдается нормальный ответ от устройства при помощи ф-ций PresetSingleRegister,PresetMultipleRegisters, а если указать адрес записываемого регистра в NumSensorsTC, то запрос остается без ответа. Почему, не пойму никак?.. PS. Callback-функции написаны и работают. PS2. Вроде нашел... В Callback-функции использую ф-ции записи во флеш. Код WriteFlashByte(FLASH_PARAMETER_LOCATION + 2 + 1, *(pucRegBuffer)); WriteFlashByte(FLASH_PARAMETER_LOCATION + 2, *(pucRegBuffer + 1)); Если закоментировать эти строки, то ответ нормальный появляется. Наверно, правильно сделать так : в колбэк-функции устанавливать флаг, а в главном цикле по этому флагу писать во флеш.
|
|
|
|
|
May 14 2011, 09:03
|
Участник

Группа: Участник
Сообщений: 60
Регистрация: 31-08-10
Из: Минск-Витебск
Пользователь №: 59 203

|
Цитата который адресован ему и имеет правильный CRC, но не имеет ни функции, ни данных Если вместо функции и данных просто нули, то при проверки кода функции, если он данную ф-цию не поодерживает, должен вернуть ошибку с номером 1 (ILLEGAL FUNCTION).
|
|
|
|
|
May 17 2011, 05:04
|
Участник

Группа: Участник
Сообщений: 60
Регистрация: 31-08-10
Из: Минск-Витебск
Пользователь №: 59 203

|
По хорошему проверка должна идти в следующей очередности: 1. Длина пакета 2. CRC 3. Адрес 4. Функция 5. Данные
|
|
|
|
|
May 17 2011, 05:17
|
Участник

Группа: Участник
Сообщений: 60
Регистрация: 31-08-10
Из: Минск-Витебск
Пользователь №: 59 203

|
Для простых случаев может и можно не проверять. А если сеть протяженная, с большим количеством слейвов, помеховая обстановка серьезная - вероятность ошибок в пакете приличная, проверка crc становится обязательной.
|
|
|
|
|
May 17 2011, 06:01
|
Участник

Группа: Участник
Сообщений: 60
Регистрация: 31-08-10
Из: Минск-Витебск
Пользователь №: 59 203

|
Да согласен
Хотя у некторых есть счетчики которые считают ошибки в линии т.к. если есть ошибка, то не известно где именно и кому предназначен пакет.
Сообщение отредактировал yashok - May 17 2011, 05:39
|
|
|
|
|
Oct 17 2012, 07:26
|
Группа: Новичок
Сообщений: 3
Регистрация: 28-09-12
Из: Новосибирск
Пользователь №: 73 716

|
Доброго дня всем. Пытаюсь поднять FreeRTOS(7.2)+lwip(1.4)+FreeModbus(1.5)(TCP), FreeRTOS+lwip на LM3S9B95(board EVB-9B95) худо-бедно справился, пинги идут, httpserver_raw запустился, пробную страничку получил. А вот с modbus справится не могу. Для теста взял qModMaster, т.к. работать легко с ней(основные шаги connect->read data->disconnect я выполняю по кнопками, что упрощает тест), и параллельно для надежности нечто более сложное NI OPC Server. Connect, Disconnect работают отлично, вызываются prvxMBTCPPortAccept() и prvxMBTCPPortReceive()(здесь он уходит в prvvMBPortReleaseClient и закрывает соединение). А вот с чтением данных у меня возникли проблемы, при чтении попадаю я в prvxMBTCPPortReceive(), далее по функции доходит до (void)xMBPortEventPost(EV_FRAME_RECEIVED); и из нее не возвращается, ползу по ней дебагером Код //portevent.c BOOL xMBPortEventPost( eMBEventType eEvent ) { eMailBoxEvent = eEvent; sys_mbox_post( xMailBox, &eMailBoxEvent ); return TRUE; } он уходит в sys_mbox_post(); Код //sys_arch.c void sys_mbox_post( sys_mbox_t *pxMailBox, void *pxMessageToPost ) { while( xQueueSendToBack( *pxMailBox, &pxMessageToPost, portMAX_DELAY ) != pdTRUE ); } и на сколько я понимаю крутится внутри xQueueGenericSend(). После чего отваливается ethernet, т.е. пинги не проходят вообще, да и походу роутер не видит плату, FreeRTOS в это время работает Task'и переключает исправно. Я уже даже не знаю в какую сторону копать. Порт modbus взят из демки MCF5235TCP, а LWIP где-то на просторах интернета [attachment=72049:ports_lwip.zip] [attachment=72050:port_modbus.zip]
|
|
|
|
|
Oct 18 2012, 06:25
|
Группа: Новичок
Сообщений: 3
Регистрация: 28-09-12
Из: Новосибирск
Пользователь №: 73 716

|
в sys_mbox_post() убрал цикл, заменил portMAX_DELAY на 1000(т.е. на 1 секунду). Ethernet перестал отваливаться, обнаружил, что функция xQueueSendToBack возвращает ошибку errQUEUE_FULL.
|
|
|
|
|
Oct 22 2012, 04:37
|
Группа: Новичок
Сообщений: 3
Регистрация: 28-09-12
Из: Новосибирск
Пользователь №: 73 716

|
обнаружил, что структура pxQueue не подгружалась при работе с модбасом у меня еще не пришло полное понимание & и *, поэтому решил поиграться с ними в порте freemodbus (portevent.c) Код sys_mbox_post( xMailBox, &eMailBoxEvent ); заменил на Код sys_mbox_post( &xMailBox, &eMailBoxEvent ); структура подгрузилась и функция xQueueSendToBack перестала выдавать ошибку errQUEUE_FULL, но что-то я сильно сомневаюсь, что в порте была ошибка Больше не сомневаюсь, это реально ошибка в порте, изменил на &xMailBox во всех функциях portevent.c и freemodbus заработал. Большое спасибо разработчикам freemodbus, так и без работы можно оставить, яж на испытательном сроке еще  но все равно им спасибо за труд
Сообщение отредактировал leshij - Oct 22 2012, 04:40
|
|
|
|
|
Sep 30 2013, 11:02
|
Группа: Новичок
Сообщений: 4
Регистрация: 30-09-13
Пользователь №: 78 547

|
Помогите реализовать Modbus-slave на базе Atmega32A. Условие: применяемый на freemodbus 16-разрядный таймер1 использовать нельзя - он нужен мне для реализации 16-разрядного аппаратного ШИМа. Что уже сделано: 1) Материалы на freemodbus.org изучил (хотя и не во всем разобрался). 2) Нашел http://forum.easyelectronics.ru/viewtopic....mp;hilit=modbus - во втором посте выложено решение для 168й атмеги по замене таймера 1 на таймер 0. Скачал, собрал в свой проект, откомпилировал для 168й атмеги. 2) Заменил ссылки на таймер 0А (для 168й меги) на таймер 0 для 32й меги. 3) 2) Заменил ссылки на таймер 0В (для 168й меги) на таймер 2 для 32й меги. 4) Откомпилировал в AtmelStudio6 без ошибок. 5) Подключил контроллер через мах485 и конвертер i-7561 (485/usb) к компьютеру. 6) ОРС-сервером Lectus отправляю запрос 01 03 00 01 00 01 D5 CA, осциллографом наблюдаю соответствующую последовательность на ножке микроконтроллера, НО сам контроллер молчит и в ответ никаких сообщений не выдает. Предполагаю два варианта проблемы: 1) Простая замена таймеров оказалась некорректной. 2) Неверно "привязаны" регистры usRegInputBuf и usRegHoldingBuf. Помогите пожалуйста разобраться
|
|
|
|
|
Sep 30 2013, 11:31
|

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

|
Цитата(veskon @ Sep 30 2013, 14:02)  Помогите пожалуйста разобраться Для начала, RTFM - Related Pages -> Porting for RTU/ASCII Ну а дальше тщательная трассировка. Самое простое, это банальный бит четности (проверка на четность по стандарту Modbus RTU/ASCII). Если прерывания ловятся и пакет принимается, должен выставляться эвент и функция поллинга перенаправляет в нужный коллбэк. Дальше убеждаемся, что формируется ответный пакет, и вот тут может всплыть 485-й с переключением потока.
--------------------
Программирование делится на системное и бессистемное. ©Моё :) — а для кого-то БГ — это Bill Gilbert =)
|
|
|
|
|
Sep 30 2013, 12:12
|
Группа: Новичок
Сообщений: 4
Регистрация: 30-09-13
Пользователь №: 78 547

|
Цитата(Lagman @ Sep 30 2013, 15:06)  А может слейв адрес не тот? Спасибо. С принципом работы самого модбаса рту мне все ясно. Проблема возникла с его конкретной реализацией. В частности с заменой таймера в стандарном "австрийском" варианте. Адрес тот, регистры те...
|
|
|
|
|
Sep 30 2013, 13:05
|
Знающий
   
Группа: Свой
Сообщений: 875
Регистрация: 28-10-05
Пользователь №: 10 245

|
Цитата(veskon @ Sep 30 2013, 16:12)  Спасибо. С принципом работы самого модбаса рту мне все ясно. Проблема возникла с его конкретной реализацией. В частности с заменой таймера в стандарном "австрийском" варианте. Я с AVR не работал, но думаю если вы выложите свои исходники из /port то знающие люди помогут. А последовательность действий при отладке очень хорошо описал MrYuran.
|
|
|
|
|
Sep 30 2013, 14:21
|
Группа: Новичок
Сообщений: 4
Регистрация: 30-09-13
Пользователь №: 78 547

|
Цитата(_Pasha @ Sep 30 2013, 17:06)  Дык покажите свой porttimer.c и portserial.c и еще чего там меняли по сравнению с базовой демкой. Там же всё элементарно...  файл добавить не получается, поэтому пишу сам листинг. Примечание: исходные строчки не удалены, а закомментированы. Следом идут мои. /* * FreeModbus Libary: ATMega168 Port * Copyright © 2006 Christian Walter <wolti@sil.at> * Modified in 2010 by drvlas: * Only RTU mode. * Use T0 instead of T1. Implemented only on ATmega168 */ /* ----------------------- AVR includes -------------------------------------*/ #include <avr/io.h> #include <avr/interrupt.h> //#include <avr/signal.h> /* ----------------------- Platform includes --------------------------------*/ #include "../include/port.h" /* ----------------------- Modbus includes ----------------------------------*/ #include "../include/mb.h" #include "../include/mbport.h" /* ----------------------- Defines ------------------------------------------*/ #define MB_TIMER_PRESCALER ( 1024UL ) #define MB_TIMER_TICKS ( F_CPU / MB_TIMER_PRESCALER ) #define MB_50US_TICKS ( 20000UL ) /* ----------------------- Static variables ---------------------------------*/ static USHORT usTimerOCRADelta; //static USHORT usTimerOCRBDelta; /* ----------------------- Start implementation -----------------------------*/ BOOL xMBPortTimersInit( USHORT usTimerout50us ) { /* Calculate overflow counter an OCR values for Timer0. */ usTimerOCRADelta = ( MB_TIMER_TICKS * usTimerout50us ) / ( MB_50US_TICKS ); if( usTimerOCRADelta > 255) return FALSE; //TCCR0A = 0x00; // Normal Mode + Output Compare interrupt TCCR0 = 0x00; // Normal Mode + Output Compare interrupt //TCCR0B = 0x00; TCCR2 = 0x00; // TCCR1C = 0x00; vMBPortTimersDisable( ); return TRUE; } inline void vMBPortTimersEnable( ) { TCNT0 = 0x0000; if( usTimerOCRADelta > 0 ) { //TIMSK0 |= _BV( OCIE0A ); TIMSK |= _BV( OCIE0 ); //OCR0A = usTimerOCRADelta; // MUST be < 256 OCR0 = usTimerOCRADelta; // MUST be < 256 } //TCCR0B |= _BV( CS12 ) | _BV( CS10 ); // Fosc/1024 TCCR2 |= _BV( CS12 ) | _BV( CS10 ); // Fosc/1024 } inline void vMBPortTimersDisable( ) { /* Disable the timer. */ //TCCR0B &= ~( _BV( CS12 ) | _BV( CS10 ) ); TCCR2 &= ~( _BV( CS12 ) | _BV( CS10 ) ); /* Disable the output compare interrupts for channel A */ //TIMSK0 &= ~( _BV( OCIE0A ) ); TIMSK &= ~( _BV( OCIE0 ) ); /* Clear output compare flags for channel A/B. */ //TIFR0 |= _BV( OCF0A ) ; TIFR |= _BV( OCF0 ) ; } //SIGNAL( SIG_OUTPUT_COMPARE0A ) SIGNAL( SIG_OUTPUT_COMPARE0 ) { ( void )pxMBPortCBTimerExpired( ); }
|
|
|
|
|
Oct 1 2013, 06:11
|
Группа: Новичок
Сообщений: 4
Регистрация: 30-09-13
Пользователь №: 78 547

|
Цитата(_Pasha @ Sep 30 2013, 19:36)  Помогать так уж буквально не буду. Почитайте стр.84 даташита Ошибки: 1. TCCR2 тут никаким боком. Работаем с TCCR0. Это в тексте vMBPortTimersEnable( ) 2. Стесняюсь спросить, чему у Вас равно F_CPU ?Очень может быть, тик 100мкс неправильно посчитан. -- Вообще, при наличии протеуса хоть 7.8 - такие ошибки симулем выловить как два пальца. Даже рисовать ничего не надо - поставили МК, питания и виртуал терминал, настроили - и поехали. Имхо получше чем студия. Да, наверное Вы правы,- попробую разобраться с Протеусом.
|
|
|
|
|
Apr 18 2014, 13:01
|
Местный
  
Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041

|
Ребят удалось портировать? Никак не могу разобраться как прерывание описать надо, чтобы либа поняла, что прерыание случилось (прерывание по приему я имею ввиду). Что нужно засунуть в обработчик прерывания, какую функцию либы? Вот тут что то вообще непонятное: Код static void prvvUARTTxReadyISR( void ) { CHAR cByte; ( void )xMBPortSerialGetByte( &cByte ); /* Now cByte should contain the character received. */ } Я пишу порт на IAR для at90can32. Перерыл весь manual, сказано надо описать прерывание, а что туда писать непонятно. Подскажите будьте добры
|
|
|
|
|
Apr 22 2014, 05:14
|
Местный
  
Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041

|
Вообщем портировать удалось, кажется все по правилам, но пока ничего не заработало. Буду крайне признателен, если поможете. Написал portserial.c и porttimer.c. Объявил eMBRegHoldingCB(), eMBRegCoilsCB(), eMBRegDiscreteCB(), eMBRegInputCB(). Компилю, зашиваю, запускаю и наблюдаю следующее: при запросе от мастера read holding register (0x03) вызывается функция eMBRegHoldingCB(), и после ее отработки стек перестает работать (в ответ мастер не получает ни ответа ни привета), прерывания по приему после этого перестают срабатывать (хотя первые 8 байт из первого запроса прерывание вызывают). Но проц не зависает, все продолжает крутиться, ошибок никаких eMBPoll() не возвращает. Я уже кажется перечитал все форумы и темы, чего то похоже не понимаю. Запрос от мастера: Код 01 03 03 E9 00 04 95 B9 portserial.cporttimer.cmain.cСам проект, если что-то непонятно. Вот, надеюсь на вашу помощь...
|
|
|
|
|
Apr 22 2014, 11:29
|
Местный
  
Группа: Свой
Сообщений: 321
Регистрация: 23-12-11
Из: Уфа
Пользователь №: 69 041

|
Люди, я может чего не понимаю, но получается следующее: отправкой исходящих пакетов занимается функция pxMBFrameCBTransmitterEmpty(), которая по-сути переадресована в случае с протоколом modbus RTU на функцию xMBRTUTransmitFSM(). А поскольку эта функция вызывается из прерывания по окончанию отправки, то выходит, чтобы стек ответил на входящий запрос от мастера, нужно после того как входящий запрос был распарсен, нужно "пинуть" стек и один раз вызвать xMBRTUTransmitFSM(). Я добавил этот вызов в функции eMBRTUSend() в файле mbrtu.c. Когда я так сделал стек заработал. CODE eMBRTUSend( UCHAR ucSlaveAddress, const UCHAR * pucFrame, USHORT usLength ) { eMBErrorCode eStatus = MB_ENOERR; USHORT usCRC16; ENTER_CRITICAL_SECTION( );
/* Check if the receiver is still in idle state. If not we where to * slow with processing the received frame and the master sent another * frame on the network. We have to abort sending the frame. */ if( eRcvState == STATE_RX_IDLE ) { /* First byte before the Modbus-PDU is the slave address. */ pucSndBufferCur = ( UCHAR * ) pucFrame - 1; usSndBufferCount = 1;
/* Now copy the Modbus-PDU into the Modbus-Serial-Line-PDU. */ pucSndBufferCur[MB_SER_PDU_ADDR_OFF] = ucSlaveAddress; usSndBufferCount += usLength;
/* Calculate CRC16 checksum for Modbus-Serial-Line-PDU. */ usCRC16 = usMBCRC16( ( UCHAR * ) pucSndBufferCur, usSndBufferCount ); ucRTUBuf[usSndBufferCount++] = ( UCHAR )( usCRC16 & 0xFF ); ucRTUBuf[usSndBufferCount++] = ( UCHAR )( usCRC16 >> 8 );
/* Activate the transmitter. */ eSndState = STATE_TX_XMIT; vMBPortSerialEnable( FALSE, TRUE ); fledGreen();
/** * ВОТ ЭТО Я ДОБАВИЛ, ЧТОБЫ ПИНУТЬ СТЕК ! */
xMBRTUTransmitFSM();
} else { eStatus = MB_EIO; } EXIT_CRITICAL_SECTION( ); return eStatus; }
Почему он сразу не работает?!! P.S: В указанных выше исходниках у меня НЕ включено прерывание по отправке, сейчас это исправлено.
|
|
|
|
|
Mar 24 2015, 06:40
|
Группа: Участник
Сообщений: 8
Регистрация: 2-07-10
Пользователь №: 58 255

|
Доброго всем дня. Портирую freemodbus на stm32. Holding регистры читаются и записываются нормально, но вот Discrete читаются только 8 бит. В чем может быть проблема? Код #define REG_DISCRETE_START 1 #define REG_DISC_SIZE 24
unsigned char ucRegDiscBuf[REG_DISC_SIZE / 8];
eMBErrorCode eMBRegDiscreteCB( UCHAR * pucRegBuffer, USHORT usAddress, USHORT usNDiscrete ) { eMBErrorCode eStatus = MB_ENOERR; short iNDiscrete = ( short )usNDiscrete; unsigned short usBitOffset = 0;
if( ( usAddress >= REG_DISCRETE_START ) && ( usAddress + usNDiscrete <= REG_DISCRETE_START + REG_DISC_SIZE ) ) { usBitOffset = ( unsigned short )( usAddress - REG_DISCRETE_START ); while( iNDiscrete > 0 ) { *pucRegBuffer++ = xMBUtilGetBits( ucRegDiscBuf, usBitOffset, ( unsigned char )( iNDiscrete > 8 ? 8 : iNDiscrete ) ); iNDiscrete -= 8; usBitOffset += 8; } } else { eStatus = MB_ENOREG; }
return eStatus; }
|
|
|
|
|
Mar 24 2015, 13:35
|
Группа: Участник
Сообщений: 8
Регистрация: 2-07-10
Пользователь №: 58 255

|
Цитата(smalcom @ Mar 24 2015, 16:04)  сколько задаёте, столько и считывается. Задано 24 бита. Пытаюсь считать 24, считывается только 8 бит, оставшиеся 16 считываются как false хотя имеют значение true. Считываю программой Modbus Master V2.2
|
|
|
|
|
Mar 25 2015, 05:42
|
Группа: Участник
Сообщений: 8
Регистрация: 2-07-10
Пользователь №: 58 255

|
Цитата(smalcom @ Mar 24 2015, 17:55)  вы разницу между "не считывается" и "считываются как false" не ощущаете что ли? ну так это повод грустить.
раз считываются как false значит так оно и есть. проверяйте свой код который обслуживает эти биты. В моем случае они все таки не считываются если длина больше чем 8. У меня 24 регистра начиная с 1 адреса. Если считывать их по 8 бит, то читаются все биты. То есть можно прочесть с 1 по 8, с 9 по 16 и с 17 по 24. Причем адрес можно выставить не кратный 8 и считать скажем с 13 по 20, но если читать с 13 по 21 то 21 уже будет читаться некорректно.
|
|
|
|
|
Jul 2 2015, 07:35
|
Участник

Группа: Участник
Сообщений: 43
Регистрация: 23-01-13
Пользователь №: 75 313

|
У кого нибудь есть описание реализации Freemodbus хотя бы бедно на русском, либо полное объяснение на английском?
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|