Skip to main content
sne_123
Associate III
December 7, 2018
Question

Usart received data misaligned in buffer when I try to receive data from 2 modbus slaves. It works fine with 1 slave but when both the slaves are connected, after a period of time, usart stars misaligning received data. Can someone help?

  • December 7, 2018
  • 9 replies
  • 1658 views

This is my usart handler

 Also I clear the 1st received frame before receiving the 2nd modbus frame.

void HAL_UART_IRQHandler1(UART_HandleTypeDef *huart)

{

__HAL_UART_CLEAR_PEFLAG(huart);

__HAL_UART_ENABLE_IT(huart, UART_IT_ERR);

__HAL_UART_ENABLE_IT(huart,UART_IT_LBD);

__HAL_UART_ENABLE_IT(huart, UART_IT_PE);

__HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);

__HAL_UART_CLEAR_OREFLAG(huart); 

// check if the USART1 receive interrupt flag was set

if( __HAL_UART_GET_IT_SOURCE(huart, UART_IT_RXNE) )

t = (uint8_t)(huart->Instance->DR );

if (t != '\n')

{

// Concat char to buffer

if (k < 13 -1)

{

received_string[k] = t;

k++;

}

else

{

received_string[k] = t;

k = 0;

}

}

}

__HAL_UART_CLEAR_PEFLAG(huart);

__HAL_UART_DISABLE_IT(huart, UART_IT_PE);

__HAL_UART_DISABLE_IT(huart, UART_IT_ERR);

__HAL_UART_DISABLE_IT(huart,UART_IT_LBD);

HAL_NVIC_ClearPendingIRQ(USART3_IRQn);

}

This topic has been closed for replies.

9 replies

AvaTar
Senior III
December 7, 2018

I don't do Cube code.

Do you speak about Modbus ASCII, or RTU ?

Check if characters get lost, perhaps the OV flag is set.

If slaves misbehave, you application needs to deal with such a scenario in a robust manner.

sne_123
sne_123Author
Associate III
December 7, 2018

I am speaking about Modbus RTU. I tried to check OV flag in debug mode. It is not set.

None of the error flags are set.

T B
Associate III
December 7, 2018

May you have a simple buffer overflow after the 13 character.

is k=0 in the correct else path?

BTW1 : this is not MODBUS RTU.

Why to the hell you configure the ISR in the ISR handler?

sne_123
sne_123Author
Associate III
December 7, 2018

when I say Modbus RTU ,it means I am receiving frames from modbus slave in RTU mode. That means I am receiving hex frames from slave !!!

"k" is just the byte count and received buffer is of 13bytes. So i will have to reset the k count if there are no more characters to be received.

T B
Associate III
December 7, 2018

In RTU mode ‚\n‘ is a normal byte.

In RTU you need the IDLE condition the detect the frame end.

May this helps:

https://stm32f4-discovery.net/2017/07/stm32-tutorial-efficiently-receive-uart-data-using-dma/

sne_123
sne_123Author
Associate III
December 7, 2018

so should I check '\r' instead of '\n' ???

Also Thanks for the link, I will try to configure using DMA.

Jack Peacock_2
Associate II
December 7, 2018

If you use RTU the end of a frame is defined as a gap, multiple/fractional character times, before the next frame starts. IDLE may or may not work, depending on how your remote node responds. PCs, for instance, have a hard time meeting the inter-character and inter-message gap times with RTU, which is why ASCII mode is so common. Same problem if your remote node has interrupt driven TX out. The interrupt latency, especially if there are higher priorities, can unexpectedly insert gap times inside a frame.

If your remote node inserts gaps between bytes in excess of the IDLE timer you get broken frames. Some STM32s have a fixed IDLE period, which is all but useless. Newer versions do allow for programming the IDLE timer period.

Address match can be used to detect a frame start in RTU, but never the end. It works best if there are long pauses between frames, otherwise you have to disable the IRQ as soon as a frame starts, and enable the moment a frame ends (that gets complicated, especially at high data rates).

Jack Peacock

sne_123
sne_123Author
Associate III
December 10, 2018

@Community member​  Thank you. I will try today with increasing the delay between 2 frames.

sne_123
sne_123Author
Associate III
December 12, 2018

I figured out the issue. The problem was modbus slave sends me incomplete frame at times (last byte was missing in the frame). So the when new frame was received it used to store data in the last byte of buffer as it was empty...the counter 'k' was not resetting itself because of which rest all frames which were received got misaligned and CRC check failed.

So now before receiving a new frame, every time I am resetting the count 'k'. I Also inserted a delay between receiving frames from 2 modbus slaves.

@Community member​ @Community member​ @Bacteriuslocher​  Thanks for helping. :)

AvaTar
Senior III
December 12, 2018

> The problem was modbus slave sends me incomplete frame at times (last byte was missing in the frame).

> So now before receiving a new frame, every time I am resetting the count 'k'. I Also inserted a delay between receiving frames from 2 modbus slaves.

A proper and robust device must be able to handle corrupted frame.

With Modbus RTU, the spec. defines an inter-frame delay where the bus is idle.

If this period is up (including a grace tolerance of some percent), process the frame, or discard it if invalid.

sne_123
sne_123Author
Associate III
December 12, 2018

Okay. ..