Jump to content

    
Sign in to follow this  
zaicev_ekb

STM32F103 USAR3 обмен по ModBus

Recommended Posts

Доброго времени суток всем.

Столкнулся с непонятным явлением

USART сконфигурированный с одними параметрами связи, отвечает на запросы с другими параметрами связи

Куда копать уже не знаю

Ни кто не сталкивался с подобным?

Modbus RTU Scaner.jpg

Edited by zaicev_ekb

Share this post


Link to post
Share on other sites
1 hour ago, zaicev_ekb said:

Ни кто не сталкивался с подобным?

Логический анализатор на линии? Всё покажет сразу.

1 hour ago, zaicev_ekb said:

Куда копать уже не знаю

Только на уровень физики и канала (по модели OSI);

Share this post


Link to post
Share on other sites
2 часа назад, zaicev_ekb сказал:

Куда копать уже не знаю

В сторону обработки ошибок по приему, например. Биты данных во всех посылках совпадают, биты четности для приемника с отключенной проверкой четности должны вызывать ошибку приема стопового бита (framing error). В вышей программе эта ошибка, вероятно, не обрабатывается. А поскольку биты данных во всех форматах совпадают - посылка принимается правильно.

Share this post


Link to post
Share on other sites
29 minutes ago, Сергей Борщ said:

В сторону обработки ошибок по приему, например. Биты данных во всех посылках совпадают, биты четности для приемника с отключенной проверкой четности должны вызывать ошибку приема стопового бита (framing error). В вышей программе эта ошибка, вероятно, не обрабатывается. А поскольку биты данных во всех форматах совпадают - посылка принимается правильно.

Спасибо за волщебный пендель

буду копать

Share this post


Link to post
Share on other sites
On 7/7/2020 at 10:09 AM, haker_fox said:

Логический анализатор на линии? Всё покажет сразу.

Только на уровень физики и канала (по модели OSI);

Сергей вопрос в продолжение

Конфиг USART

 

    rs485_data.delay = br9600_timeout;
    USART_InitStructure.USART_BaudRate = br9600;
    USART_InitStructure.USART_WordLength          = USART_WordLength_9b;
    USART_InitStructure.USART_StopBits            = USART_StopBits_1;
    USART_InitStructure.USART_Parity              = USART_Parity_Even;     
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode                = USART_Mode_Rx | USART_Mode_Tx;
    
    USART_Init ( USART1, &USART_InitStructure );
    
    USART1->CR1 |= ( 1 << 10 ) | ( 1 << 8 );
    
    USART_ITConfig ( USART1, USART_IT_RXNE, ENABLE );
    USART_ITConfig ( USART1, USART_IT_NE, ENABLE );
    USART_ITConfig ( USART1, USART_IT_FE, ENABLE );
    USART_ITConfig ( USART1, USART_IT_ERR, ENABLE );

обработка прерывания

 

    if ( USART_GetITStatus ( USART1, USART_IT_RXNE ) != RESET ) {
        USART_ClearITPendingBit ( USART1, USART_IT_RXNE );
        
        rs485_data.rxtimer = 0;
        if ( rs485_data.rxcnt - 2 > ( RX_BUF_SIZE ) ) {
            rs485_data.rxcnt = 0;
        }
        rs485_data.buffer_rx[rs485_data.rxcnt] =  USART1->DR & (uint16_t)0x01FF;
        
        rs485_data.rxcnt++;
        rs485_data.symbol_first = 1;
        rs485_data.rxtimer = rs485_data.delay ;
    }
    
    if ( USART_GetITStatus ( USART1, USART_IT_TC ) != RESET ) {
        USART_ClearITPendingBit ( USART1, USART_IT_TC );
        rs485_dir_off();
        rs485_data.txend = 0;
        USART_ITConfig ( USART1, USART_IT_TC, DISABLE );
        rs485_data.Status_Tx = Tx_End;
    }
    
    if ( USART_GetITStatus ( USART1, USART_IT_TXE ) != RESET ) {
        USART_ClearITPendingBit ( USART1, USART_IT_TXE );
        
    }
    
    if ( USART_GetITStatus ( USART1, USART_IT_LBD ) != RESET ) {
        USART_ClearITPendingBit ( USART1, USART_IT_LBD );
        rs485_data.Status_Rx = Rx_Error;
    }
    
    if ( USART_GetITStatus ( USART1, USART_IT_ORE  ) != RESET ) {
        USART_ClearITPendingBit ( USART1, USART_IT_ORE  );
        rs485_data.Status_Rx = Rx_Error;
        rs485_data.buffer_rx[rs485_data.rxcnt] = USART_ReceiveData ( USART1 );
        rs485_data.rxcnt++;
    }
    
    if ( USART_GetITStatus ( USART1, USART_IT_FE ) != RESET ) {
        USART_ClearITPendingBit ( USART1, USART_IT_FE );
        USART_ClearITPendingBit ( USART1, USART_IT_PE );
        rs485_data.Status_Rx = Rx_Error;
        rs485_data.symbol_first = 0;
    }
    
    if ( USART_GetITStatus ( USART1, USART_IT_PE ) != RESET ) {
        USART_ClearITPendingBit ( USART1, USART_IT_PE );
        rs485_data.Status_Rx = Rx_Error;
        rs485_data.symbol_first = 0;
    }

При приеме байта в прерывание заходим но соответсвующий флаг PE не выставляется в регистре SR не выставляется

Share this post


Link to post
Share on other sites
4 часа назад, zaicev_ekb сказал:

но соответсвующий флаг PE в регистре SR не выставляется

Не выставляется или вы не попадаете в последнее условие, потому что флаг сбрасывается после чтения SR и DR в первом условии? Полагаю, что все же второе. Я не знаком с кубом, но внимательно читаю документацию на контроллер и его регистры. Из этой документации становится понятно, что ваш обработчик написан неправильно:

1) Нужно один раз в начале обработчика считать регистр статуса и потом во всех условиях работать со считанным значением, а не теребить SR при проверке каждого флага, как это делают недалекие авторы куба.

2) Многие биты в этом регистре сбрасываются автоматически чтением DR после чтения SR и вызов USART_ClearITPendingBit на них никоим образом не влияет.

Читайте справочное руководство (reference manual) на контроллер, а не только названия функций в кубе.

 

Share this post


Link to post
Share on other sites
1 hour ago, Сергей Борщ said:

как это делают недалекие авторы куба

О, а я не один) Но ругают на форуме почему-то только меня за то, что я ругаю куб))) Хотя, может быть и вам доставалось)

Share this post


Link to post
Share on other sites
13 минут назад, haker_fox сказал:

О, а я не один) Но ругают на форуме почему-то только меня за то, что я ругаю куб))) Хотя, может быть и вам доставалось)

Да на этот "исходник" без слёз смотреть невозможно!  :cray2:

До чего доводит кубокодерство, что простейший ISR так обезобразить позволяет. :shok:

А ведь там всего-то ничего нужно (для этого самого "народного" F103):

__no_init struct {
  char tx[200];
  char rx[80];
} static bufService @ ".dma";

u8 volatile rxw = 0, rxr = 0;
static OsFlag txNoFull = OS_FLAG_STATE_RESET, rxNoEmpty = OS_FLAG_STATE_RESET;

extern "C" void concat(isrUART, nUART_serv)()
{
  uint c, i0, i1, i2;
  HwRegsUART volatile *io = &concat(UART, nUART_serv);
  if ((i0 = io->SR) & (1 << UART_SR_NE | 1 << UART_SR_FE)) c = io->DR;
  else if (i0 & 1 << UART_SR_RXNE) {
    c = io->DR;
    if (i0 & (1 << UART_SR_PE | 1 << UART_SR_ORE)) return;
    i0 = rxw;
    if ((i1 = i0 + 1) >= sizeof(bufService.rx)) i1 = 0;
    if (i1 == (i2 = rxr)) return;
    bufService.rx[i0] = c;
    rxw = i1;
    if (i0 == i2) OsFlagSet(&rxNoEmpty);
  }
}

и всех делов....

Share this post


Link to post
Share on other sites
24 минуты назад, haker_fox сказал:

Но ругают на форуме почему-то только меня за то, что я ругаю куб)

Я отношусь к кубу философски: хотят мыши жрать кактус - пусть плачут и колятся, поэтому просто чаще всего молча прохожу мимо тем про куб. 

Share this post


Link to post
Share on other sites
46 minutes ago, jcxz said:

и всех делов....

Кратко. А мне понравилось больше передавать через ПДП: количество байт на передачу известно. Принимаю по прерываниям. Хотя тоже можно по ПДП, но для пакетной передачи. А если принять с текстовой консоли, то, ИМХО, прерывания не обременяют.

Share this post


Link to post
Share on other sites
15 минут назад, haker_fox сказал:

Кратко. А мне понравилось больше передавать через ПДП: количество байт на передачу известно. Принимаю по прерываниям.

В приведённом ISR только приём. Передача сделана как раз через DMA.

Share this post


Link to post
Share on other sites
16 hours ago, Сергей Борщ said:

Не выставляется или вы не попадаете в последнее условие, потому что флаг сбрасывается после чтения SR и DR в первом условии? Полагаю, что все же второе. Я не знаком с кубом, но внимательно читаю документацию на контроллер и его регистры. Из этой документации становится понятно, что ваш обработчик написан неправильно:

1) Нужно один раз в начале обработчика считать регистр статуса и потом во всех условиях работать со считанным значением, а не теребить SR при проверке каждого флага, как это делают недалекие авторы куба.

2) Многие биты в этом регистре сбрасываются автоматически чтением DR после чтения SR и вызов USART_ClearITPendingBit на них никоим образом не влияет.

Читайте справочное руководство (reference manual) на контроллер, а не только названия функций в кубе.

 

Сергей спасибо за критику. Го это не HAL а SPL.

Сделано как описывают сами ST в своем референсе.

Даташит тоже читаю, и еррату тоже.

За замечание еще раз спасибо.

Буду пробовать.

И в Кале перед функциями стоит префикс HAL. Халом я тоже не пользуюсь.

 

Share this post


Link to post
Share on other sites
6 hours ago, zaicev_ekb said:

это не HAL а SPL.

Оно же вообще deprecated уже давно!

Если вам так хочется пользоваться чужими библиотеками "абстракций" и добавлять в свой код лютый оверхед, лучше попробуйте opencm3. Она по крайней мере не страдает ТАКИМ оверхедом, как SPL.

Share this post


Link to post
Share on other sites
On 7/7/2020 at 5:31 AM, zaicev_ekb said:

Доброго времени суток всем.

Столкнулся с непонятным явлением

USART сконфигурированный с одними параметрами связи, отвечает на запросы с другими параметрами связи

 

Здесь специалисты уже посоветовали. Я вставлю свои пять копеек.

Отлаживая UART коммуникацию, я начал сталкиваться со спорадическими потерями байтов как на STM32F10x, так и (и особенно) на STM32F0xx. В процессе отладки, когда я хотел глянуть по шагам, что там с битами в SR происходит, я вставил команду чтения SR сразу на входе в прерывание:

void STDIO_IRQHandler(void)
{
    STDIO_DEVICE->SR;           // unbelievable but reading SR before 
    bufio_IRQHandler(&FIFO);    // helps to avoid byte loss. 28.04.14.  
}

И о, чудо! - ошибки ушли навсегда!

Я не стал глубоко копать, почему так происходит, и объяснить не смогу. Работает, и работает (и весьма надежно). Чистая эмпирика и удача, я и оставил, как есть. F10x вообще, как первая Cortex серия от STM, имеет весьма глючную периферию. Например, запустить разумно I2C на нем весьма нетривиально, о чем писано-переписано на форуме, в том числе и мной.

 

Попробуйте трюк 17. Хотя проблема в TX? Может быть, немного не совпадают скорости? RC генератор (HSI) не точный, или где-то +/-1 в делителе...

Edited by KnightIgor

Share this post


Link to post
Share on other sites
14 минут назад, KnightIgor сказал:

я вставил команду чтения SR сразу на входе в прерывание:

А где-ж ещё её вставлять? Вроде в начале - это как бы само собой разумеется.

Цитата

RC генератор (HSI) не точный, или где-то +/-1 в делителе...

"Не точный" - это мягко сказано. У меня на плате с али (STM32F103R8T6) частота HSI по дефолту == ~6.326 МГц.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Sign in to follow this