Skip to main content
Birdym
Associate II
April 3, 2020
Solved

How can I filter received data from UART to act when it reads one, or multiple specific characters?

  • April 3, 2020
  • 4 replies
  • 3800 views

..

This topic has been closed for replies.
Best answer by Guenael Cadier

Hello @Birdym​ 

No big added value compared to already suggested method. Just to mention another option could be to use the Character Match feature of your UART instance. Goal is to raise a specific flag in ISR (the CMF flag), when received character (8 bits) value corresponds to the value stored in ADD field of the CR2 register. Could work for example in case you wait for a specific character as a "start" sequence for something to do further.

No specific HAL API exists for this feature, but using LL services, and interrupt mode, this could be something like :

main() :

 /* UART instance initialisation as usual : baudrate, parity ...*/
 ...
 
 /* Disable USART */
 LL_USART_Disable(USARTx_INSTANCE);
 
 /* Set value of expected character for matching */
 LL_USART_ConfigNodeAddress(USARTx_INSTANCE , LL_USART_ADDRESS_DETECT_7B, 0x31);
 
 /* Enable USART */
 LL_USART_Enable(USARTx_INSTANCE);
 
 /* Enable RXNE and Error interrupts */
 LL_USART_EnableIT_RXNE(USARTx_INSTANCE);
 
 /* Enable the UART Character Match interrupt */
 LL_USART_EnableIT_CM(USARTx_INSTANCE);
 
 LL_USART_EnableIT_ERROR(USARTx_INSTANCE);

USART IRQ Handler :

 /* Check RXNE flag value in ISR register */
 if(LL_USART_IsActiveFlag_RXNE(USARTx_INSTANCE))
 {
 /* Read Received character. RXNE flag is cleared by reading of RDR register */
 received_char = LL_USART_ReceiveData8(USARTx_INSTANCE);
 }
 
 /* Check CMF flag value in ISR register */
 if(LL_USART_IsActiveFlag_CM(USARTx_INSTANCE))
 {
 /* Clear CMF flag */
 LL_USART_ClearFlag_CM(USARTx_INSTANCE);
 
 <<<==== Specific treatment in case of expected specific char value could be added here
 }

Please note that even if received character does not match the expected specific value, it will be stored in RDR and RXNE flag will raise. So it must ne read (and stored if to be used later) in order to prevent Overrun errors.

Hope this helps.

Guenael

4 replies

Tesla DeLorean
Guru
April 3, 2020

Use a simple​ state machine to process characters as they arrive, accumulate into a buffer and synchronize as needed.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Birdym
BirdymAuthor
Associate II
April 3, 2020

Do you maybe have a code example where a state machine is implemented and accumulated into a a buffer? I don't understand it yet

Tesla DeLorean
Guru
April 3, 2020

I've posted examples of processing GPS NMEA Sentences in the past. Sync on a $ character and dispatches the whole line to a parser at the end of the line.

Dig via site search, not on a computer currently.​

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Guenael Cadier
Guenael CadierBest answer
ST Employee
April 3, 2020

Hello @Birdym​ 

No big added value compared to already suggested method. Just to mention another option could be to use the Character Match feature of your UART instance. Goal is to raise a specific flag in ISR (the CMF flag), when received character (8 bits) value corresponds to the value stored in ADD field of the CR2 register. Could work for example in case you wait for a specific character as a "start" sequence for something to do further.

No specific HAL API exists for this feature, but using LL services, and interrupt mode, this could be something like :

main() :

 /* UART instance initialisation as usual : baudrate, parity ...*/
 ...
 
 /* Disable USART */
 LL_USART_Disable(USARTx_INSTANCE);
 
 /* Set value of expected character for matching */
 LL_USART_ConfigNodeAddress(USARTx_INSTANCE , LL_USART_ADDRESS_DETECT_7B, 0x31);
 
 /* Enable USART */
 LL_USART_Enable(USARTx_INSTANCE);
 
 /* Enable RXNE and Error interrupts */
 LL_USART_EnableIT_RXNE(USARTx_INSTANCE);
 
 /* Enable the UART Character Match interrupt */
 LL_USART_EnableIT_CM(USARTx_INSTANCE);
 
 LL_USART_EnableIT_ERROR(USARTx_INSTANCE);

USART IRQ Handler :

 /* Check RXNE flag value in ISR register */
 if(LL_USART_IsActiveFlag_RXNE(USARTx_INSTANCE))
 {
 /* Read Received character. RXNE flag is cleared by reading of RDR register */
 received_char = LL_USART_ReceiveData8(USARTx_INSTANCE);
 }
 
 /* Check CMF flag value in ISR register */
 if(LL_USART_IsActiveFlag_CM(USARTx_INSTANCE))
 {
 /* Clear CMF flag */
 LL_USART_ClearFlag_CM(USARTx_INSTANCE);
 
 <<<==== Specific treatment in case of expected specific char value could be added here
 }

Please note that even if received character does not match the expected specific value, it will be stored in RDR and RXNE flag will raise. So it must ne read (and stored if to be used later) in order to prevent Overrun errors.

Hope this helps.

Guenael

Birdym
BirdymAuthor
Associate II
April 6, 2020

What are LL services? Is there a library I need for this?

Guenael Cadier
ST Employee
April 6, 2020

Hi @Birdym​ 

The Low Layer (LL) drivers are part of the STM32Cube firmware HAL that provide basic set of optimized and one shot services. You could find corresponding H files in same place than HAL H files.

If you are using a STM32Cube FW package that supports LL, you should be able to find them in \Drivers\STM32YYxx_HAL_Driver\Inc directory (YY = your STM32 serie as F4, G0, H7, ...).

STM32Cube Firmware packages also provides LL usage example : Please check in Projects\<board name>\Examples_LL directories.

Guenael

Birdym
BirdymAuthor
Associate II
April 6, 2020

Update; in CubeMX under project manager and then to advanced settings, you can change HAL to LL. Thank you for the help!

Guenael Cadier
ST Employee
April 6, 2020

Exactly, CubeMx is the easiest way to download up-to data STM32CUbe package.

Otherwise, you could still go to ST website : https://www.st.com/en/microcontrollers-microprocessors/stm32l0-series.html#tools-software

Then select : Embedded Software / MCU & MPU Embedded Software / STM32 MCU & MPU packages / STM32CubeL0 / Open Software page