LeLLIuj 0 18 октября, 2012 Опубликовано 18 октября, 2012 · Жалоба в sys_mbox_post() убрал цикл, заменил portMAX_DELAY на 1000(т.е. на 1 секунду). Ethernet перестал отваливаться, обнаружил, что функция xQueueSendToBack возвращает ошибку errQUEUE_FULL. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
LeLLIuj 0 22 октября, 2012 Опубликовано 22 октября, 2012 (изменено) · Жалоба обнаружил, что структура pxQueue не подгружалась при работе с модбасом у меня еще не пришло полное понимание & и *, поэтому решил поиграться с ними в порте freemodbus (portevent.c) sys_mbox_post( xMailBox, &eMailBoxEvent ); заменил на sys_mbox_post( &xMailBox, &eMailBoxEvent ); структура подгрузилась и функция xQueueSendToBack перестала выдавать ошибку errQUEUE_FULL, но что-то я сильно сомневаюсь, что в порте была ошибка Больше не сомневаюсь, это реально ошибка в порте, изменил на &xMailBox во всех функциях portevent.c и freemodbus заработал. Большое спасибо разработчикам freemodbus, так и без работы можно оставить, яж на испытательном сроке еще:) но все равно им спасибо за труд:) Изменено 22 октября, 2012 пользователем leshij Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
veskon 0 30 сентября, 2013 Опубликовано 30 сентября, 2013 · Жалоба Помогите реализовать 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. Помогите пожалуйста разобраться Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
MrYuran 29 30 сентября, 2013 Опубликовано 30 сентября, 2013 · Жалоба Помогите пожалуйста разобраться Для начала, RTFM - Related Pages -> Porting for RTU/ASCII Ну а дальше тщательная трассировка. Самое простое, это банальный бит четности (проверка на четность по стандарту Modbus RTU/ASCII). Если прерывания ловятся и пакет принимается, должен выставляться эвент и функция поллинга перенаправляет в нужный коллбэк. Дальше убеждаемся, что формируется ответный пакет, и вот тут может всплыть 485-й с переключением потока. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Lagman 1 30 сентября, 2013 Опубликовано 30 сентября, 2013 · Жалоба Помогите пожалуйста разобраться А может слейв адрес не тот? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
veskon 0 30 сентября, 2013 Опубликовано 30 сентября, 2013 · Жалоба А может слейв адрес не тот? Спасибо. С принципом работы самого модбаса рту мне все ясно. Проблема возникла с его конкретной реализацией. В частности с заменой таймера в стандарном "австрийском" варианте. Адрес тот, регистры те... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Lagman 1 30 сентября, 2013 Опубликовано 30 сентября, 2013 · Жалоба Спасибо. С принципом работы самого модбаса рту мне все ясно. Проблема возникла с его конкретной реализацией. В частности с заменой таймера в стандарном "австрийском" варианте. Я с AVR не работал, но думаю если вы выложите свои исходники из /port то знающие люди помогут. А последовательность действий при отладке очень хорошо описал MrYuran. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 30 сентября, 2013 Опубликовано 30 сентября, 2013 · Жалоба Помогите пожалуйста разобраться Дык покажите свой porttimer.c и portserial.c и еще чего там меняли по сравнению с базовой демкой. Там же всё элементарно... :laughing: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
veskon 0 30 сентября, 2013 Опубликовано 30 сентября, 2013 · Жалоба Дык покажите свой porttimer.c и portserial.c и еще чего там меняли по сравнению с базовой демкой. Там же всё элементарно... :laughing: файл добавить не получается, поэтому пишу сам листинг. Примечание: исходные строчки не удалены, а закомментированы. Следом идут мои. /* * FreeModbus Libary: ATMega168 Port * Copyright © 2006 Christian Walter <[email protected]> * 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( ); } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
_Pasha 0 30 сентября, 2013 Опубликовано 30 сентября, 2013 · Жалоба Помогать так уж буквально не буду. Почитайте стр.84 даташита Ошибки: 1. TCCR2 тут никаким боком. Работаем с TCCR0. Это в тексте vMBPortTimersEnable( ) 2. Стесняюсь спросить, чему у Вас равно F_CPU ?Очень может быть, тик 100мкс неправильно посчитан. -- Вообще, при наличии протеуса хоть 7.8 - такие ошибки симулем выловить как два пальца. Даже рисовать ничего не надо - поставили МК, питания и виртуал терминал, настроили - и поехали. Имхо получше чем студия. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
veskon 0 1 октября, 2013 Опубликовано 1 октября, 2013 · Жалоба Помогать так уж буквально не буду. Почитайте стр.84 даташита Ошибки: 1. TCCR2 тут никаким боком. Работаем с TCCR0. Это в тексте vMBPortTimersEnable( ) 2. Стесняюсь спросить, чему у Вас равно F_CPU ?Очень может быть, тик 100мкс неправильно посчитан. -- Вообще, при наличии протеуса хоть 7.8 - такие ошибки симулем выловить как два пальца. Даже рисовать ничего не надо - поставили МК, питания и виртуал терминал, настроили - и поехали. Имхо получше чем студия. Да, наверное Вы правы,- попробую разобраться с Протеусом. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yanvasilij 0 18 апреля, 2014 Опубликовано 18 апреля, 2014 · Жалоба Ребят удалось портировать? Никак не могу разобраться как прерывание описать надо, чтобы либа поняла, что прерыание случилось (прерывание по приему я имею ввиду). Что нужно засунуть в обработчик прерывания, какую функцию либы? Вот тут что то вообще непонятное: static void prvvUARTTxReadyISR( void ) { CHAR cByte; ( void )xMBPortSerialGetByte( &cByte ); /* Now cByte should contain the character received. */ } Я пишу порт на IAR для at90can32. Перерыл весь manual, сказано надо описать прерывание, а что туда писать непонятно. Подскажите будьте добры Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yanvasilij 0 22 апреля, 2014 Опубликовано 22 апреля, 2014 · Жалоба Вообщем портировать удалось, кажется все по правилам, но пока ничего не заработало. Буду крайне признателен, если поможете. Написал portserial.c и porttimer.c. Объявил eMBRegHoldingCB(), eMBRegCoilsCB(), eMBRegDiscreteCB(), eMBRegInputCB(). Компилю, зашиваю, запускаю и наблюдаю следующее: при запросе от мастера read holding register (0x03) вызывается функция eMBRegHoldingCB(), и после ее отработки стек перестает работать (в ответ мастер не получает ни ответа ни привета), прерывания по приему после этого перестают срабатывать (хотя первые 8 байт из первого запроса прерывание вызывают). Но проц не зависает, все продолжает крутиться, ошибок никаких eMBPoll() не возвращает. Я уже кажется перечитал все форумы и темы, чего то похоже не понимаю. Запрос от мастера: 01 03 03 E9 00 04 95 B9 portserial.c porttimer.c main.c Сам проект, если что-то непонятно. Вот, надеюсь на вашу помощь... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
yanvasilij 0 22 апреля, 2014 Опубликовано 22 апреля, 2014 · Жалоба Люди, я может чего не понимаю, но получается следующее: отправкой исходящих пакетов занимается функция pxMBFrameCBTransmitterEmpty(), которая по-сути переадресована в случае с протоколом modbus RTU на функцию xMBRTUTransmitFSM(). А поскольку эта функция вызывается из прерывания по окончанию отправки, то выходит, чтобы стек ответил на входящий запрос от мастера, нужно после того как входящий запрос был распарсен, нужно "пинуть" стек и один раз вызвать xMBRTUTransmitFSM(). Я добавил этот вызов в функции eMBRTUSend() в файле mbrtu.c. Когда я так сделал стек заработал. 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: В указанных выше исходниках у меня НЕ включено прерывание по отправке, сейчас это исправлено. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergey.saratov 0 24 марта, 2015 Опубликовано 24 марта, 2015 · Жалоба Доброго всем дня. Портирую 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; } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться