Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Непонятный глюк с прерыванием во Freemodbus
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему
ZAA
Нужно реализовать протокол Modbus RTU (в режиме мастера) на AT91SAM7x256. Поначалу пробовала писать свои функции отправки и приема. Но долго мучилась с прерываниями по таймеру и уарту. В конце концов вроде разобралась с ними, но к тому времени пошарила в инете и нашла FreeModbus (для слэйва). Прикрутила к FreeRTOSу. Все отлично работало. Контроллер и принимал, и отсылал назад фрэймы. И прием и передача там организованы на основе перываний от RxD и TxD. Потом стала пытаться преобразовать код для мастера, то бишь сначала отправлять сообщение, а потом ждать ответа. При таком раскладе происходило прерывание на передачу, но только ОДИН раз (и контроллер зависал). Дело, похоже, в том что вызов ф-ии отправки в исходном коде происходит только после приема фрэйма, и массив там используется один, короче, штука вся в указателях... Но не в этом глюк. В один "прекрасный" момент при попытке вернуть все в исходное состояние (то есть обратно в исходный режим слэйва) контроллер стал зависать и после приема фрэйма, то есть там, где раньше работал отлично.
Может, кто-то сталкивался с подобным? Может кто-нить пользовался FreeModbus'ом или переделывал его под себя. А использовать его удобно, т к ф-ии все есть и организовано в виде TASK отдельного!
ЛЮДИ, ПОМОГИТЕ!!! ВРЕМЯ УТЕКАЕТ, А ПРОБЛЕМА ОСТАЕТСЯ. crying.gif
Amper25
Боже, неужели девушки этим занимаются? smile.gif

Для полноты оказываемой помощи желательно хотябы привести код.
MrYuran
Я колупался с freemodbus.

Действительно, очень удобная штука, вешается на что угодно (я вешал на msp430) и написана очень грамотно (для себя много почерпнул).
Цитата
Дело, похоже, в том что вызов ф-ии отправки в исходном коде происходит только после приема фрэйма

Насколько я понял, по приёму байта он просто пишется в буфер. По таймауту приёма (переполнение таймера) вызывается функция первичного анализа фрейма, по результату выставляются флаги.

Потом вы вызываете функцию poll() , которая обрабатывает пакет, вызывает соответствующие функции (read/write register/coil etc.), формирует ответный пакет и запускает передачу.

Мастер я не делал, но там всё должно быть несколько по другому. Отправляете пакет, запоминаете какой и кому. по приёму пакета опять та же первичная обработка (CRC и структура пакета), вызов poll(), которую надо переделать. она должна анализировать ответ на предмет соответствия запросу (адрес, команда), и если всё нормально, производить необходимые действия.

В целом, ИМХО, нужно переделать только poll() и добавить функцию отправки мастер-пакета. Ну и ещё учесть тайм-аут приёма пакета.
ZAA
Цитата(MrYuran @ Jun 14 2008, 08:39) *


Дело в том, что я понимаю, как работает эта штука, и все работало, а щас виснет в одном и том же место - по-моему, в прерывании на передачу. То есть фрэйм принимается, обрабатыватся, а вот обратно передаваться не хочет - пишет только первый байт, то бишь адрес, и капут - контроллер зависает. С контроллером ничего не могло произойти - это конечно глупое предположение, но мало ли crying.gif
А может, тут конфликт с прерываниями FreeRTOSа?

Цитата(Amper25 @ Jun 14 2008, 00:45) *
Боже, неужели девушки этим занимаются? smile.gif

Для полноты оказываемой помощи желательно хотябы привести код.


Код я собственно и не меняла - как был в исходниках, так и остался, потому что дело дальше не пошло из-за описанного выше глюка. Привожу 4 файла - main.c, где собственно запускается задача опроса, mb.c, где эта ф-ия (poll) написана, mbrtu - там ф-ии посылки-приема, portserial - настройка UART и обработчики прерывания
Простите за длинные выкладки - что-то файлики не хотят присоединяться((

Moderator:
Обширные включения кода исключены. Учитесь пользоваться архиваторами.
aaarrr
Файлы забыли.
ZAA
Цитата(aaarrr @ Jun 15 2008, 16:28) *
Файлы забыли.

У меня там везде понапиханы AT91F_. Хотя я отлично помню Ваши советы их не использовать. Просто времени на самом деле очень в обрез - потом сделаю по-человечески
aaarrr
Цитата(ZAA @ Jun 15 2008, 17:24) *
Простите за длинные выкладки - что-то файлики не хотят присоединяться((

В архив тогда можно было бы уложить. В сообщении что-то убилось.

Цитата(ZAA @ Jun 15 2008, 17:44) *
У меня там везде понапиханы AT91F_. Хотя я отлично помню Ваши советы их не использовать. Просто времени на самом деле очень в обрез - потом сделаю по-человечески

Ну ничего, иногда это простительно smile.gif
spf
Цитата(ZAA @ Jun 13 2008, 21:52) *
В конце концов вроде разобралась с ними, но к тому времени пошарила в инете и нашла FreeModbus (для слэйва). Прикрутила к FreeRTOSу.

Почему версию не сообщаете?
Там же вроде уже все прикручено.
showfiles
ZAA
Цитата(spf @ Jun 15 2008, 17:56) *
Почему версию не сообщаете?
Там же вроде уже все прикручено.
showfiles

ДА-да, именно версия 1.4
А под словом прикручивать я имела ввиду в мэйкфайле прописать, ну и в свой проект включить некоторые файлы

Цитата(aaarrr @ Jun 15 2008, 16:55) *
В архив тогда можно было бы уложить. В сообщении что-то убилось.

ПРисоединяюsmile.gif
ZAA
Цитата(aaarrr @ Jun 15 2008, 16:55) *
В архив тогда можно было бы уложить. В сообщении что-то убилось.

ПРисоединяюsmile.gifНажмите для просмотра прикрепленного файла
Нажмите для просмотра прикрепленного файла
ZAA
Товарищи!!! Уже неоднократно поднимала эту тему (в посте "Непонятный глюк с прерываниями во FreeModbus"). Ну не могу я косяк найти в программе.
Крутится задача модбаса (фактически ф-ия Poll в цикле). Если контроллеру разрешить прерывания по TxRDY, и что-нить в обработчике прерывания делать - ну например поставить счетчик, отправлять байты и отсчитывать кол-во отправленных байтов, то постоянно происходят прерывания и в буфер пишется все, что нужно. Если же при отправке определенного кол-ва байт запрещаю прерывания по TXRDY и разрешаю по RXRDY, то происходит следующее. Контроллер принимает байты (определенное кол-во - например по счетчику, к-рый инкрементируется при каждом прерывании), затем я запрещаю прерывание на прием и снова разрешаю на передачу. И вот тут-то вместо отправки всего сообщения контролллер отправляет один байт и намертво виснет.
Были подозрения, что как-то конфликтуют эти прерывания с FreeRTOSовскими. Хотя вроде в самой системе кроме счётчика тиков (PIT-таймер) больше ничего и не используется. А может я ошибаюсь?

Чем может быть вызвана подобная проблема!!! Буду рада любым советам!
MrYuran
ну а зачем прерывания-то дёргать? пусть себе живут, принимают и отправляют байты
zltigo
Цитата(ZAA @ Jun 23 2008, 18:36) *
Уже неоднократно...

Moderator:
И по этой причине решили завалить вопросом весь форум?
Темы объединил.
aaarrr
Цитата(ZAA @ Jun 23 2008, 20:36) *
...Если же при отправке определенного кол-ва байт запрещаю прерывания по TXRDY и разрешаю по RXRDY, то происходит следующее. Контроллер принимает байты (определенное кол-во - например по счетчику, к-рый инкрементируется при каждом прерывании), затем я запрещаю прерывание на прием и снова разрешаю на передачу. И вот тут-то вместо отправки всего сообщения контролллер отправляет один байт и намертво виснет.

Как именно запрещаете прерывания? Приведите кусочек кода, в котором проявляется проблема.
Просто так перелопатить несколько сотен килобайт чужих исходников желающих найдется немного.
ZAA
Цитата(aaarrr @ Jun 23 2008, 22:02) *
Как именно запрещаете прерывания? Приведите кусочек кода, в котором проявляется проблема.
Просто так перелопатить несколько сотен килобайт чужих исходников желающих найдется немного.

Ф-ия MAIN
Код
int main( void )
{
    prvSetupHardware();
    
            xTaskCreate( vModbus_Task, "modbus", (configMINIMAL_STACK_SIZE*6), NULL, tskIDLE_PRIORITY, NULL );

    vTaskStartScheduler();

      return 0;
}

Ф-ия разрешения прерываний по UART
Код
void UART_INTERRUPT_ENABLE (int RXRDY, int TXRDY)
{
    portENTER_CRITICAL();
    if ((RXRDY == 1)&&(TXRDY == 0))
    {
        *AT91C_US0_IER = AT91C_US_RXRDY;
        *AT91C_US0_IDR = AT91C_US_TXRDY;
    }
    else if ((RXRDY == 0)&& (TXRDY == 1))
    {
        *AT91C_US0_IER = AT91C_US_TXRDY;
        *AT91C_US0_IDR = AT91C_US_RXRDY;
    }
    
    portEXIT_CRITICAL();
}

Обработчик прерывания по UART
Код
void vUART_ISR_Handler( void )
{
       unsigned int status;

            status = AT91C_BASE_US0->US_CSR & AT91C_BASE_US0->US_IMR;
      
            if(status & AT91C_US_RXRDY)
           {
                if (counter_rcv != 4 )
                {
                 massiv[counter_rcv] = uart0_getc();
                        counter_rcv++;
                }
        
                else
               {
                        counter_rcv = 0;
                     UART_INTERRUPT_ENABLE(0,1);  //Разрешаю прерывание по TXRDY
                }
  
            }
    
           if(status & AT91C_US_TXRDY)
          {
        
                if (counter_trsm !=4)
               {
                        uart0_putc((char) massiv[counter_trsm]);
                   counter_trsm++;
                }
          else
         {
              counter_trsm = 0;
              UART_INTERRUPT_ENABLE(1,0);          //Разрешаю прерывание по RXRDY
          }
     }
        
    AT91C_BASE_AIC->AIC_EOICR = 0;  

}
aaarrr
Несмотря на некоторую общую кривизну идеи (уж простите), явного криминала я не вижу. Если только AIC_EOICR пишется не в одном месте...
ZAA
Цитата(aaarrr @ Jun 24 2008, 07:44) *
Несмотря на некоторую общую кривизну идеи (уж простите)

Ничего ,спасибо. проверю
Цырен
Народ помогите!

Если вы смогли победить freeModbus, помогите пож. и мне. Нужно переделать код freeMODBUS 1.5 под мастера для Mega64. Код как слэйв работает отлично (RTU).
Потом решил посмотреть что шлет прибор и воспользовался функцией peMBFrameSendCur(...). Включил на компе снифер (Free Serial Port Monitor).
Код
eMBErrorCode
eMBPoll( void )
{
    static UCHAR   *ucMBFrame;
    static USHORT   usLength;
    eMBErrorCode    eStatus = MB_ENOERR;
    eMBEventType    eEvent;
    
    /* Check if the protocol stack is ready. */
    if( eMBState != STATE_ENABLED )
    {
        return MB_EILLSTATE;
    }
    
    ucMBFrame[0] = 0x11;
    usLength = 1; // Длина сообщения PDU - без адреса(1 байт) и CRC16(2 байта)
    
    eStatus = peMBFrameSendCur( 1, ucMBFrame, usLength );
    
    while(!( (xMBPortEventGet( &eEvent ) == TRUE) && (eEvent == EV_FRAME_SENT) )){};
}


Прибор шлет FF 21 00 01 вместо положенных 01 11 C0 2C.
Скорость, паритет, стоп-биты установил верно.
Может я неправильно использую функцию? Подскажите.
Спс.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.