cancel
Showing results for 
Search instead for 
Did you mean: 

UART receive data problem

er3481
Senior

Hi,

I am using stm32f103 mcu for UART data transmit and receive. I am using UART interrupt for both receiving and transmitting. Sometimes received data takes a different value than it should be. This occurs when i send some data from stm32 to serial port at the same time. All data can be received normally but sometimes some of 10-byte data is changed to a different value. Any advise ?

Thanks...

void USART1_IRQHandler(void)
{
    if((USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) && (USART_GetITStatus(USART1, USART_IT_TXE) == RESET))
    {        
        USART_ClearITPendingBit(USART1, USART_IT_RXNE);        
        unsigned char data;
 
        data = USART_ReceiveData(USART1);
        uart_buffer[uart_buffer_index] = data;
        uart_buffer_index++;   
        //do some stuff with uart_buffer[]     
    }
 
    if( (USART_GetITStatus(USART1, USART_IT_TXE) != RESET ) && (USART_GetITStatus(USART1, USART_IT_RXNE) == RESET))	// TX buffer not empty
	{
        
		if(byte_counter != 0)//if there is any data in data_buff array
        {            
            USART_SendData(USART1, (uint16_t)*out_pointer);//send buffer data            
            out_pointer++;	//inc pointer for next data in data_buff array
            byte_counter--;
            if(out_pointer >= &data_buff[0] + TX_BUFFER_SIZE)
            {                
                out_pointer = &data_buff[0];
            }
        }
        else
        {
            USART_ClearITPendingBit(USART1, USART_IT_TC);
            USART_ClearITPendingBit(USART1, USART_IT_TXE);
            USART_ITConfig(USART1, USART_IT_TXE, DISABLE);//UC1IE &= ~ UCA1TXIE; // Disable USCI_A1 TX interrupt
 
        }
	}
 
	if(USART_GetFlagStatus(USART1,USART_FLAG_ORE) != RESET)
    {       
        (void)USART_ReceiveData(USART1);
 
    }
}

4 REPLIES 4
KnarfB
Principal III

When both interrupt flags are set, none of the if instruction bodies will be executed and possibly a char can be missed.

I would only test for each flag separately

if((USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
  ...
}
 
if( (USART_GetITStatus(USART1, USART_IT_TXE) != RESET )  {
  ...
}

and ideally also for error conditions.

if((USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) && (USART_GetITStatus(USART1, USART_IT_TXE) == RESET)) // WHY? These bits are independent, DR acts differently for Read vs Write, it is NOT a memory cell, but TWO different holding registers

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Hi, @Community member​ 

when i use the if instructions seperately, the same problem also occurs.

if((USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) {
  ...
}
 
if( (USART_GetITStatus(USART1, USART_IT_TXE) != RESET )  {
  ...
}

What do you advise ?

vik1970va
Associate II

The first is not a match in the code that I saw is if (byte_counter! = 0) and else upon exit from the interrupt flags are not always reset

USART_IT_TC, USART_IT_TXE

I would write like this:

else
        {
            USART_ITConfig(USART1, USART_IT_TXE, DISABLE);//UC1IE &= ~ UCA1TXIE; // Disable USCI_A1 TX interrupt 
        } 
           USART_ClearITPendingBit(USART1, USART_IT_TC);
           USART_ClearITPendingBit(USART1, USART_IT_TXE);
	} //EXIT  TX buffer not empty

If you entered // TX buffer not empty, then it is necessary to reset the flags, but they do not always reset ....