自动波特率检测STM32L0 [英] Auto baud rate detect for STM32L0

查看:421
本文介绍了自动波特率检测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 ..等

0x68 = 0b01101000
0x0B = 0b00001011
0xFD = 0b11111101< - 以1开头的字符,应检测波特率


0xFD:
开始1 1 .....
___位__________
| ______ |
...

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



UART_ADVFEATURE_AUTOBAUDRATE_ONSTARTBIT UART_ADVFEATURE_AUTOBAUDRATE_ONFALLINGEDGE / p>

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

  / *如果需要,配置自动波特率检测方案* / 
if(HAL_IS_BIT_SET(huart-> AdvancedInit.AdvFeatureInit,UART_ADVFEATURE_AUTOBAUDRATE_INIT))
{
assert_param(IS_UART_ADVFEATURE_AUTOBAUDRATE - > AdvancedInit.AutoBaudRateEnable));
MODIFY_REG(huart-> Instance-> CR2,USART_CR2_ABREN,huart-> AdvancedInit.AutoBaudRateEnable);
/ *设置检测启用时的自动波特率检测参数* /
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);
}
}



pre> / *如果需要,配置自动波特率检测方案* /
if(HAL_IS_BIT_SET(huart-> AdvancedInit.AdvFeatureInit,UART_ADVFEATURE_AUTOBAUDRATE_INIT))
{
assert_param(IS_UART_ADVFEATURE_AUTOBAUDRATE(huart-
/ *设置检测启用时设置自动波特率检测参数* /
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);
}

不做任何事情。



另外以下似乎很好:


时钟源频率必须与预期的通信速度
兼容(当过采样16时,波特率在fCK / 65535和fCK / 16之间。当
过采样8时,波特率在fCK / 65535和fCK / 8之间)。


我是过采样16,所以

  fCK = 16000000 

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

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

解决方案

如果您无法指定单个字节由STM32L0的自动波特率检测硬件检查,您可能仍然可以滚动自己的自动波特率检测方案,如果可以为您的系统做出以下假设:




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


  • 在接收多个字符的任意间隔期间,可以假定比特序列 010 101 是相对常见的情况。


  • 该器件具有可用的通用定时器外设,可以映射到与USART Rx信号相同的器件引脚。 / p>




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



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

 波特微秒62.5-nS时钟
---- --------- --- --------------
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.等等。



在此过程中,在将Timer分配给引脚时,USART被禁用。在确定正确的波特率使用后,重新配置引脚将其分配给USART Rx外设功能。


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

解决方案

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.

这篇关于自动波特率检测STM32L0的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆