Auto baud rate detect for STM32L0

江枫思渺然 提交于 2019-12-10 14:55:51

问题


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

My initilization 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 is :

        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 chronology 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 anyhing.

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


回答1:


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.




回答2:


From the datasheet (This one, page 759). "Before activating the auto baud rate detection, the auto baud rate detection mode must be chosen". --> Try switching your lines to:

huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_AUTOBAUDRATE_INIT; huart1.AdvancedInit.AutoBaudRateMode = UART_ADVFEATURE_AUTOBAUDRATE_ONSTARTBIT; huart1.AdvancedInit.AutoBaudRateEnable = UART_ADVFEATURE_AUTOBAUDRATE_ENABLE; `

I don't think it will make a big difference as you start the init process with HAL_UART_Init(&huart1); anyways. But it's worth a try. You can check your clock source frequency also.




回答3:


Since you are using ABRMOD[1:0] = UART_ADVFEATURE_AUTOBAUDRATE_ONSTARTBIT (auto baud rate Mode 0), the very first character received after initialization must have a high MSB in order for the auto baud mechanism to work properly. But you say that your sequence of data bytes is

68  0B  0B  68  53  FD  52  FF  FF  .. etc.

The first byte in this sequence is 0x68, which has a low MSB. Therefore, the auto baud detection hardware will write an incorrect value to the BRR. Change your first byte to have a high MSB, and this should solve your problem.


Edit

The STM32L0 has 4 auto baud rate detection modes, allowing you to specify different characteristics of the byte that is measured. From the RM0367 Reference manual:

These modes are:

  • Mode 0: Any character starting with a bit at 1. In this case the USART measures the duration of the Start bit (falling edge to rising edge).

  • Mode 1: Any character starting with a 10xx bit pattern. In this case, the USART measures the duration of the Start and of the 1st data bit. The measurement is done falling edge to falling edge, ensuring better accuracy in the case of slow signal slopes.

  • Mode 2: A 0x7F character frame (it may be a 0x7F character in LSB first mode or a 0xFE in MSB first mode). In this case, the baudrate is updated first at the end of the start bit (BRs), then at the end of bit 6 (based on the measurement done from falling edge to falling edge: BR6). Bit 0 to bit 6 are sampled at BRs while further bits of the character are sampled at BR6.

  • Mode 3: A 0x55 character frame. In this case, the baudrate is updated first at the end of the start bit (BRs), then at the end of bit 0 (based on the measurement done from falling edge to falling edge: BR0), and finally at the end of bit 6 (BR6). Bit 0 is sampled at BRs, bit 1 to bit 6 are sampled at BR0, and further bits of the character are sampled at BR6. In parallel, another check is performed for each intermediate transition of RX line. An error is generated if the transitions on RX are not sufficiently synchronized with the receiver (the receiver being based on the baud rate calculated on bit 0).

If you can't ensure that the first byte received after enabling auto baud detection fits one of the above modes, then I'm afraid the built-in auto baud detection feature won't work for you.

All may not be lost, though. See my second answer to your question.



来源:https://stackoverflow.com/questions/34874020/auto-baud-rate-detect-for-stm32l0

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!