STM32L0的自动波特率检测

Auto baud rate detect for STM32L0

我无法在 STM32L0 上进行自动波特率检测。我正在使用硬件抽象层 (HAL)。

我的初始化代码是:

/* 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);
  

}

我通过 UART1 发送的字节是:

        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   __________
   ¦______¦
...
                                            

为什么没有检测到波特率?我试过:

UART_ADVFEATURE_AUTOBAUDRATE_ONSTARTBITUART_ADVFEATURE_AUTOBAUDRATE_ONFALLINGEDGE

所以我调整了驱动程序中模式设置和启用的顺序:

  /* 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);
    }
  }

  /* 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);
  }

什么都不做。

此外,以下似乎还不错:

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).

我过采样 16,所以

fCK= 16000000

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

我选择的波特率是:19200/ 9600 /2400 /300

来自数据表(This one,第 759 页)。 "Before activating the auto baud rate detection, the auto baud rate detection mode must be chosen"。 --> 尝试将您的行切换为:

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

无论如何,我认为当您使用 HAL_UART_Init(&huart1); 启动 init 进程时不会有太大的不同。但值得一试。 您也可以检查您的时钟源频率。

由于您正在使用 ABRMOD[1:0] = UART_ADVFEATURE_AUTOBAUDRATE_ONSTARTBIT(自动波特率模式 0),初始化后接收到的第一个字符必须具有高 MSB,以便自动波特率机制正常工作。但是你说你的数据字节序列是

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

此序列中的第一个字节是 0x68,它的 MSB 较低。因此,自动波特率检测硬件将不正确的值写入 BRR。将您的第一个字节更改为具有高 MSB,这应该可以解决您的问题。


编辑

STM32L0有4种波特率自动检测模式,可以指定被测字节的不同特性。来自RM0367 参考手册:

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).

如果您不能确保启用自动波特率检测后接收到的第一个字节符合上述模式之一,那么恐怕built-in自动波特率检测功能将不适合您。

不过,可能不会全部丢失。请参阅我对您问题的第二个回答。

如果您无法指定要由 STM32L0 的自动波特率检测硬件检查的单个字节的精确内容,您仍然可以 "roll your own" 自动波特率检测方案,如果满足以下条件可以为您的系统做出假设:

  • 允许在自动波特率检测过程中丢弃任意数量的连续接收字符。

  • 在接收多个字符的任意时间间隔内,可以假设位序列010101是相对常见的。

  • 设备有一个可用的通用定时器外设,可以映射到与 USART Rx 信号相同的设备引脚。

如果以上都成立,那么您可以使用芯片上通用定时器外设之一的输入捕捉功能来创建您自己的自动波特率检测方案。这些定时器可以配置为使用内部 16 MHz 时钟作为它们的时钟源。每个定时器包含一个 16 位计数器。使用 16 MHz 时钟时,定时器具有 (1/16,000,000 Hz) = 62.5 nS 脉冲测量分辨率。

在您首选的波特率下,单个位的持续时间如下:

 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

您可以在输入捕获模式下设置定时器,并让它计算两个相邻边沿转换之间的时钟数。对相对较多的样本(例如 100)执行此操作。这些样本中的许多将表示两个或多个相邻零或两个或多个相邻零的宽度。但您正在寻找 最短 样本。如果您找到一个介于 831 和 835 之间的计数,那么您可以有理由相信波特率为 19200。在 100 个样本之后,如果您找到的最短的计数介于 1665 和 1669 之间,那么您可以假设波特率为9600.等等

在此过程中,USART 被禁用,而定时器被分配给引脚。确定要使用的正确波特率后,re-configure 将其分配给 USART Rx 外设功能的引脚。