cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 UART/USART RX message terminator detection with LIN Mode

mauro2399
Associate II
Posted on September 01, 2015 at 09:32

Hi everybody,

I am using several flavours of STM32: STM32F407, STM32F030, STM32F071, STM32F303 (soon).

Concerning UART, I want to set up a protocol using variable-length messages.

In order to minimize the CPU overhead, I want to use the TX with DMA and interrupt at the end of the transmitted message, and RX with DMA and interrupt at the end of the received message.

  • On the TX side I can fire an IRQ with TXE or TC status bits, that's fine.
  • On the RX side I want to fire an IRQ at the end of the received message. Since the protocol uses variable-length messages, how can the RX tell the received message has ended?
At first I thought I might exploit a scheme for few-char idle line detection:

  • RTOF (RX timeout)
  • CMF (Character match)
  • I don't like using IDLE because it would fire and IRQ as soon as the TX leaves the line idle for just 1 char, no mercy for the TX being a little busy sometimes...
But I discovered that the USART of the STM32F407, which is the richest MCU of the ones I am using, doesn't implement RTOF and CMF. Sounds strange...

Anyway, I thought I could use the Break character as a message terminator.

According to the Reference manuals, on the RX side the Break character is treated as a Framing error. Uhm... I don't like using this as a message terminator, as there's no way to distinguish it from a real error.

But the LIN mode seems to handle it slightly different, requiring *all* received bits as 0 (mark). The Break character used in LIN Mode sounds like a viable message terminator, although STM32F030 doesn't implement the LIN Mode.

I have no experience with

LIN mode

, can you give me some advice?

Q1: On the TX side, is there any difference with UART mode @ 8-bit data length?

Q2: On the RX side, apart from the Break character handling, is there any difference with UART mode @ 8-bit data length?

Q3: Any other caveats or constraints with LIN mode?

Best regards,

Mauro

#stm32-uart-lin-break

Note: this post was migrated and contained many threaded conversations, some content may be missing.
11 REPLIES 11
Nesrine M_O
Lead II
Posted on September 22, 2015 at 13:05

Hi Mauro,

Q1 & Q2: you are right there is no difference with UART mode @ 8-bit data length

Q3: no constraints with LIN mode apart of ones mentioned in specification 

I'd highly recommend to have a look to LIN (local interconnection network) mode paragraph in the USART section of any STM32 reference manual.

-Syrine –

Posted on May 08, 2017 at 18:00

Hi Mauro,

did you ever find a solution for end of message termination over uart? I have a similar problem and LIN mode doesn't appear to do anything, I was hoping it would start a new write to the buffer on being triggered but it doesn't appear to.

I tried initializing the handle with: 

HAL_LIN_Init(&UartHandle,UART_LINBREAKDETECTLENGTH_10B);

then calling;

HAL_UART_Receive_IT(&UartHandle,(uint8_t *)buffer,sizebuf);

but no luck or clue. I'm just using a simple bluetooth module and trying to tx commands of different leghths.

Even if I used same size command leghths , they arrive in the buffer as if in a circular buffer !!

my simple bluetooth module just works on any other micro I have used it with without trouble since the end of line is detected.

howard n2wx
Senior
Posted on May 08, 2017 at 22:37

I don't like using this as a message terminator, as there's no way to distinguish it from a real error.

This attitude is wise and prudent. Do you have enough bandwidth to accommodate a CRC?

Posted on May 11, 2017 at 16:04

Thanks Syrine,

actually I never had a chance to try it out, since I shifted to other projects.

But I'll keep it in mind.

Mauro

Posted on May 11, 2017 at 16:31

Ben,

I never had a chance to experiment with the msg termination over UART by using the Break in LIN mode.

I don't understand your case, though.

You mention you want to transmit commands to a Bluetooth module, but you call HAL_UART_Receive_IT (), which is what you call when you are receiving.

I don't understand what you mean with 'arrive in the buffer as if in a circular buffer'. Can you make an example?

My case with variable msg lengths and Break in LIN mode was a case for the Receiver side, but you appear to be dealing with a Transmitter.

I guess a Receiver would call HAL_UART_Receive_IT () and await for the ISR to call HAL_UART_RxCpltCallback() if no errors occurred, or HAL_UART_ErrorCallback() if any errors occurred, including the Break detection error, which should be treated as a Message Termination case.

Cheers,

Mauro

Posted on May 11, 2017 at 18:07

Hi Mauro, thanks for the reply. I should say recieve command, sorry. I am transmitting a command of differnt character leghth from an android app. The bluetooth reciever HC-05 spits out the recieved text over UART.

I am recieving the text over the uart to ARM32F7 with HAL_UART_Receive_IT (); succecfully.

As the text arrives over HAL UART it just fills the buffer in a loop ( circular buffer I think ) This is fine for a console  but I just want to copy (uint8_t *)buffer at line break to another buffer and then wait for the next mesage & repeat.

sorry for this begginer question , I'm fairly new to C / arm32. How would I check the HAL_UART_RxCpltCallback(); for a line break ? something like this ?

uint8_t data = HAL_UART_RxCpltCallback();

if ( data != 0 )

{

copy the buffer;

break;

}

Posted on May 18, 2017 at 15:17

Ben,

there are some misunderstandings:

  1. The Break character I mentioned in my post is not the 'line break' (which in ASCII turns out to be character 0x0A, sometimes preceded by 0x0D). It is the Break character transmitted serially by the UART. If you read the UART specs, you find that each byte is physically transmitted STARTing with a 0, then 8 bits, then (optionally) the Parity bit, then a 1 called STOP bit. The Break character instead is an intentionally invalid sequence, STARTing with a 0, then eight 0 bits, then (optionally) a 0 as Parity bit, then 0 instead of the STOP bit, then two 1 bits as STOP bits. This results in an invalid frame, which is supposed to fire an interrupt, but can be detected as a specially invalid frame because all payload bits are 0 and the STOP bits are 2 instead of 1, and delayed by 1 bit position.
  2. The HAL method expects that you call HAL_UART_Receive_IT () to start the reception of a given number of bytes. This call returns immediately, not waiting for the bytes to be received (so your system is not stuck). Every time a character is received, an IRQ will take care of storing it into the buffer you provided as argument of HAL_UART_Receive_IT (). How do you know that the data have been received from the UART? When the given number of bytes has been received (i.e. the buffer is full), the ISR which is storing the received character will also call HAL_UART_RxCpltCallback(). HAL_UART_RxCpltCallback() is a function you are supposed to define, which typically asserts a flag 'Hey, UART RX buffer full!' and exits. Your system must periodically check for that flag, when asserted you know that the buffer is full with the received characters, and the UART RX must be restarted with HAL_UART_Receive_IT () because it has stopped for buffer completion.

    When a receiver error occurs, the ISR which is storing the received character will call HAL_UART_ErrorCallback(), which you must define like HAL_UART_RxCpltCallback().
  3. The scheme using HAL_UART_Receive_IT(), HAL_UART_RxCpltCallback() doesn't tell you that a 'line break' has been received before reaching the end of buffer. To do this, you can add your own code in source file stm32f7xx_it.c, inside USARTx_IRQHandler(), between USER CODE BEGIN USART2_IRQn 1 and USER CODE END USART2_IRQn 1. This code can fetch the last received character from the buffer, compare it with 0x0A and assert a flag if equal.

My initial question implied that the Transmitter after transmitting the 'line break' also transmits a Break character, which the HAL ISR can recognize and signal by calling HAL_UART_ErrorCallback().

Cheers,

Mauro

Posted on May 18, 2017 at 15:19

Probably no, but I'll keep this as an option.

Posted on May 23, 2017 at 16:09

Hi Mauro !

Thanks for this in depth answer

' This code can fetch the last received character from the buffer '

probably a stupid question , but how do I read last character received in the buffer if the command messages are different lengths?

I can't predict how long the commands will be so how do I know where in the buffer the last character will be ?

I have something working , but it would be much better just to check for the 0x0A line break !

void USARTx_IRQHandler(void)

{

    

  HAL_UART_IRQHandler(&UartHandle);

    // receive bytes when they are ready ??

    

    HAL_UART_Receive(&UartHandle,(uint8_t *)bbboxBlueRx,8,1);  // RX

    

    // get the command name

    if ( bbboxBlueRx[0] ==  '♯' )

        {

        for (int a=0; a<7; a++) {

        if (bbboxBlueRx[a+1] == '@' ) {break;}

        if (bbboxBlueRx[a+1] == '*' ) {break;}

        bbboxBlueRxCommand[a] = bbboxBlueRx[a+1];

       }

  BSP_LCD_ClearStringLine(28);

    BSP_LCD_DisplayStringAtLine(28, (uint8_t *)&bbboxBlueRxCommand);

        }

    

    // get the command value

    if ( bbboxBlueRx[0] ==  '@' )

        

    {

      for (int b=0; b<7; b++) {

      if (bbboxBlueRx[b+1] == '*' ) {break;}

        bbboxBlueRxValue[b] = bbboxBlueRx[b+1];

    }

    BSP_LCD_ClearStringLine(30);

    BSP_LCD_DisplayStringAtLine(30, (uint8_t *)&bbboxBlueRxValue);

    }        

UARTbbboxready = 1; // command and value ready to be prcessed flag    

    }