cancel
Showing results for 
Search instead for 
Did you mean: 

How do i set my UART to receive until a carriage return (\n)... **then do something**... then start receiving

MikeP
Associate III

Hello,

I am struggling to understand how i would set up my uart to receive data until it sees a carriage return (\n) then to check this the rx and then to act on it. For example if i sent " on\r" it would turn an LED on

I am using the STM32Cube, Nucleo-103RB and Keil IDE

I have set up HAL_UART_Receive_IT so i can see the data being stored from the Tx, once 5 characters it will call HAL_UART_RxCpltCallback where this will toggle my LED and restart the interrupt reception. i did try and use strcmp() to compare strings but i couldn't get this to work.

i did read about setting up a idle line interrupt but ,again, i didn't understand it.

is there a simple way for receiving uart messages without knowing the length?

(im looking to use the HAL Drivers)

any help or guidance would be appreciated!

Kind regards,

Mike

7 REPLIES 7

Got to receive one byte at a time. STM32F1 going to interrupt for every byte any how, callback can be done in a decimated form.

Make a simple line parser/accumulator that buffers until CR or LF, and then copy to a holding buffer, and dispatch for processing.

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

Hi, Thank you for your fast response. Would i put this in my HAL_UART_RxCpltCallback?

Do you have an example of this or a webpage i could follow?

Kind Regards,

Mike

I guess you could, I prefer just to put such things in the interrupt handler. Have posted code previously showing capture of ASCII NMEA sentences from a GPS receiver.

Callbacks occur under interrupt context, one needs to be quick processing anything within a single byte time so you don't miss subsequent bytes.

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

Hello,

I really appreciate your help! I did find your code previously but i don't quite understand it. I'm sure that your code below is what I'm after.

From what i can understand you're storing the received data in and array called rx_buffer which gets stored into line_buffer[rx_index]. i don't understand how rx_index gets incremented nor how i would implement this into my own.

#define LINEMAX 200 // Maximal allowed/expected line length
 
volatile char line_buffer[LINEMAX + 1]; // Holding buffer with space for terminating NUL
volatile int line_valid = 0;
 
//****************************************************************************
void USART_GPS_IRQHandler(void) // Sync and Queue NMEA Sentences
{
  static char rx_buffer[LINEMAX];   // Local holding buffer to build line
  static int rx_index = 0;
 
  if (USART_GPS->ISR & USART_ISR_RXNE) // Received character?
  {
    char rx = (char)(USART_GPS->RDR & 0xFF);                                      //** i dont understand this line**//
 
    if ((rx == '\r') || (rx == '\n')) // Is this an end-of-line condition, either will suffice?
    {
      if (rx_index != 0) // Line has some content
      {
        memcpy((void *)line_buffer, rx_buffer, rx_index); // Copy to static line buffer from dynamic receive buffer
        line_buffer[rx_index] = 0; // Add terminating NUL
        line_valid = 1; // flag new line valid for processing
 
        rx_index = 0; // Reset content pointer
      }
    }
    else
    {
      if ((rx == '$') || (rx_index == LINEMAX)) // If resync or overflows pull back to start
        rx_index = 0;
 
      rx_buffer[rx_index++] = rx; // Copy to buffer and increment
    }
  }
}

Kind Regards,

Mike

rx_index gets incremented in the collection of characters, that aren't CR/LF.

rx is loaded ONCE, with the current character in the USART's Received Data Register. I'm masking it because it's 16-bit wide, and I'm only interested in the lower 8-bits. The RXNE bit in the ISR says there's data available in the RDR.

A GPS NMEA sentence takes the form

$GPGLL,...,..,....,....,......*XX<CR><LF>

I'm interested in the content of the line once the delimiting character(s) are encountered. We don't know how long the line is going in, you have to inspect the stream as it arrives, a character at a time.

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

You are a legend! Thank you so much for your help! i have implemented some of your code and modified it slightly to my template but overall it works.

i just have to figure out how to put in actions when I've received a specific string. but thank you!

Kind Regards,

Mike

In this case the processing of the line is handled in the main() loop, and the data is in a secondary buffer so you have a complete-line-time in which to process it. In other types of system you could queue it for processing in another thread. But main point is to avoid doing processing of indeterminate duration while being bounded by reception-byte-time.

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