cancel
Showing results for 
Search instead for 
Did you mean: 

Multiple USART Issue

gada
Associate III
Posted on March 29, 2013 at 09:23

Hello, I have been trying to use multiple usarts with receive on interrupts. Some part of the communication takes place between a PC Com and STM, while some communications is taking place with STM to another STM device. The setup comprises of 2 STMs and a PC.

During reception I store received data in a array. there are many functions that use this facility (Interrupt Handler for RX).

void
USART1_IRQHandler (
void
) {
if
(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
{
if
(CYCLE_DATA_FLAG) {
CYCLE_DATA[CYCLE_RxCounter++] = USART_ReceiveData(USART1);
}
else
if
(CYCLE_NUMBER_FLAG == 1) {
CycleNumber_RxBuffer[CycleNumber_RxCounter++] = USART_ReceiveData(USART1);
}
else
{
/* Read one byte from the receive data register */
Modbus_RxBuffer[Modbus_RxCounter++] = USART_ReceiveData(USART1);
}
}
}
void
USART2_IRQHandler (
void
) {
if
(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET)
{
if
(CYCLE_NUMBER_FLAG == 1)
/* Disable the USARTz Receive interrupt */
CycleNumber_RxBuffer[CycleNumber_RxCounter++] = USART_ReceiveData(USART2);
RxBuffer[RxCounter++] = USART_ReceiveData(USART2);
} 
}
void
USART3_IRQHandler (
void
) {
if
(USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
{
CycleAccept_RxBuffer[CycleAccept_RxCounter++] = USART_ReceiveData(USART3);
if
(CycleAccept_RxCounter ==4) {
if
( (CycleAccept_RxBuffer[0] == 0x05) && (CycleAccept_RxBuffer[1] == 0x05) ) {
POSTING_FLAG = 0;
}
}
}
}

The issue is that some times the data received in this array is jumbled. For Example if i was sent 1 4 5 6 on the usart the array would reflect data received as 5 6 1 4 Please request for more details if you cannot catch my point.
5 REPLIES 5
frankmeyer9
Associate II
Posted on March 29, 2013 at 12:48

One thing that strikes my eye immediately - I don't see where you reset your receive buffer indices, or check them not to exceed array bounds.

Second thing is the nature of UART communication in general.

It is best seen as a (more or less) regular stream, with no beginning and no end, with characters arriving in an indeterministic manner.

If you want some structure and safety, you need to define a protocol (or use a defined) having some redundancy.

A good example is NMEA 183, the GPS receiver protocol.

It has a start character, that is not allowed in the rest of the sentence, and the same hold true for the end character. It has a maximal sentence length, which lets you define save buffer sizes.

Using such kind of protocol allows you to resync your receivers, sort out invalid data, and avoid buffer overflow or corruption.

I have used multiple (say, 2) UARTs in one application, and didn't experience such problems. So I guess it might come from your buffer handling.

Posted on March 29, 2013 at 12:58

With your example is the data sent on one port?

I'm not sure I'd be switching between buffers in this fashion. The USART2 routine reads the receive register twice, if this is the goal you should read the register into a variable, then write that into two buffers. There is the potential for the buffers to be exceeded, so you might want to do some bounds checking.

How are you setting up the NVIC here? The routines would be prone to preemption issues.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on March 29, 2013 at 13:04

I also have at least 3 USARTs working in most of my applications, but I'm not changing the receive pointers outside of the interrupt.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
gada
Associate III
Posted on March 29, 2013 at 14:32

I have much more code which i have not posted where I do reset these buffers. 

gada
Associate III
Posted on March 29, 2013 at 14:38

There is a condition in Uart 2 handler. at a time only one read from uart2 would be done, i feel its wrong i should add else statement there. Thanks clive. I feel there can be preemtion issue as well

void
NVIC_Configuration(
void
)
{ 
NVIC_InitTypeDef NVIC_InitStructure;
#ifdef VECT_TAB_RAM 
/* Set the Vector Table base location at 0x20000000 */
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0); 
#else /* VECT_TAB_FLASH */
/* Set the Vector Table base location at 0x08000000 */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0); 
#endif
/* Configure and enable ADC interrupt */
NVIC_InitStructure.NVIC_IRQChannel = ADC1_2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}