2018-12-06 11:16 PM
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);
}
2018-12-06 11:29 PM
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.
2018-12-06 11:35 PM
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.
2018-12-07 12:26 AM
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?
2018-12-07 12:48 AM
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.
2018-12-07 12:54 AM
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/
2018-12-07 01:13 AM
so should I check '\r' instead of '\n' ???
Also Thanks for the link, I will try to configure using DMA.
2018-12-07 06:41 AM
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
2018-12-09 07:54 PM
@Community member Thank you. I will try today with increasing the delay between 2 frames.
2018-12-12 01:36 AM
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. :)