Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Auto baud rate detect for STM32L0

I can't get auto-baud rate detection to work on the STM32L0. I'm using the hardware abstraction layer (HAL).

My initialization code is:

/* USART1 init function */
void MX_USART1_UART_Init(void)
{

  huart1.Instance = USART1;
  huart1.Init.BaudRate = 300;
  huart1.Init.WordLength = UART_WORDLENGTH_9B;
  huart1.Init.StopBits = UART_STOPBITS_1;
  huart1.Init.Parity = UART_PARITY_EVEN;
  huart1.Init.Mode = UART_MODE_TX_RX;
  huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart1.Init.OverSampling = UART_OVERSAMPLING_16;
  huart1.Init.OneBitSampling = UART_ONEBIT_SAMPLING_DISABLED;
  huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_AUTOBAUDRATE_INIT;
  huart1.AdvancedInit.AutoBaudRateEnable = UART_ADVFEATURE_AUTOBAUDRATE_ENABLE;
  huart1.AdvancedInit.AutoBaudRateMode = UART_ADVFEATURE_AUTOBAUDRATE_ONSTARTBIT;
  HAL_UART_Init(&huart1);
  

}

The bytes I'm sending over the UART1 are :

        0   1   2   3   4   5   6   7   8   
000x    68  0B  0B  68  53  FD  52  FF  FF  .. etc.

0x68 = 0b01101000
0x0B = 0b00001011
0xFD = 0b11111101  <-- Character starting with 1, baudrate should be detected


0xFD : 
     start  1  1 .....
___  bit   __________
   ¦______¦
...
                                            

Why is the baudrate not being detected? I've tried:

UART_ADVFEATURE_AUTOBAUDRATE_ONSTARTBIT and UART_ADVFEATURE_AUTOBAUDRATE_ONFALLINGEDGE

So I adjusted the order of mode setting and the enabling in the driver from:

  /* if required, configure auto Baud rate detection scheme */              
  if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_AUTOBAUDRATE_INIT))
  {
    assert_param(IS_UART_ADVFEATURE_AUTOBAUDRATE(huart->AdvancedInit.AutoBaudRateEnable));
    MODIFY_REG(huart->Instance->CR2, USART_CR2_ABREN, huart->AdvancedInit.AutoBaudRateEnable);
    /* set auto Baudrate detection parameters if detection is enabled */
    if(huart->AdvancedInit.AutoBaudRateEnable == UART_ADVFEATURE_AUTOBAUDRATE_ENABLE)
    {
      assert_param(IS_UART_ADVFEATURE_AUTOBAUDRATEMODE(huart->AdvancedInit.AutoBaudRateMode));
      MODIFY_REG(huart->Instance->CR2, USART_CR2_ABRMODE, huart->AdvancedInit.AutoBaudRateMode);
    }
  }

to

  /* if required, configure auto Baud rate detection scheme */              
  if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_AUTOBAUDRATE_INIT))
  {
    assert_param(IS_UART_ADVFEATURE_AUTOBAUDRATE(huart-
    /* set auto Baudrate detection parameters if detection is enabled */
    if(huart->AdvancedInit.AutoBaudRateEnable == UART_ADVFEATURE_AUTOBAUDRATE_ENABLE)
    {
      assert_param(IS_UART_ADVFEATURE_AUTOBAUDRATEMODE(huart->AdvancedInit.AutoBaudRateMode));
      MODIFY_REG(huart->Instance->CR2, USART_CR2_ABRMODE, huart->AdvancedInit.AutoBaudRateMode);
    }
    MODIFY_REG(huart->Instance->CR2, USART_CR2_ABREN, huart->AdvancedInit.AutoBaudRateEnable);
  }

Doesn't do anything.

Also, the following seems fine:

The clock source frequency must be compatible with the expected communication speed (when oversampling by 16, the baud rate is between fCK/65535 and fCK/16. when oversampling by 8, the baudrate is between fCK/65535 and fCK/8).

I'm oversampling by 16, so

fCK= 16000000

fCK >  16000000 / 65535 = 244     = 244  Hz
fCK <  16000000 / 16    = 1000000 = 1   MHz

My Baudrate of choice are : 19200/ 9600 /2400 /300

like image 362
Flying Swissman Avatar asked Jan 19 '16 10:01

Flying Swissman


1 Answers

If you are unable to specify the precise contents of a single byte to be examined by the STM32L0's auto baud rate detection hardware, you might still be able to "roll your own" auto baud rate detection scheme, if the following assumptions can be made for your system:

  • It is permissible to discard an arbitrary number of contiguous received characters during the auto baud detection process.

  • During any arbitrary interval where multiple characters are being received, it can be assumed that the bit sequence 010 or 101 is a relatively common occurrence.

  • The device has an available General Purpose Timer peripheral that can be mapped to the same device pin as the USART Rx signal.

If all of the above are true, then you can create your own auto baud rate detection scheme by using the Input Capture feature of one of the General Purpose Timer peripherals on the chip. These timers can be configured to use the internal 16 MHz clock as their clock source. Each timer contains a 16-bit counter. With a 16 MHz clock, the timer has a (1/16,000,000 Hz) = 62.5 nS pulse measurement resolution.

The duration of a single bit at your preferred baud rates is as follows:

 Baud   Microseconds   62.5-nS Clocks
 ----   ------------   --------------
  300      3,333.3         53,333
 2400        416.7          6,667  
 9600        104.2          1,667
19200         52.1            833

You would set up the timer in Input Capture mode, and have it count the number of clocks between two adjacent edge transitions. Perform this operation for a relatively high number of samples, say 100. Many of those samples will represent the width of two or more adjacent zeroes, or two or more adjacent ones. But you're looking for the shortest sample. If you find one that is between 831 and 835 counts, then you can be reasonably confident that the baud rate is 19200. After 100 samples, if the shortest one you found was between 1665 and 1669 counts, then you can assume the baud rate is 9600. And so on.

During this process, the USART is disabled while the Timer is assigned to the pin. After determining the right baud rate to use, re-configure the pin to assign it to the USART Rx peripheral function.

like image 128
sifferman Avatar answered Sep 20 '22 14:09

sifferman