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

不做任何事。

以下似乎很好:

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

我过了16分,所以

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

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

如果您无法指定STM32L0的自动波特率检测硬件要检查的单个字节的精确内容,如果可以进行以下假设,您仍然可以“自行设置”自动波特率检测方案。你的系统:

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

  • 在接收多个字符的任意间隔期间,可以假设比特序列010101是相对常见的事件。

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

如果满足以上所有条件,则可以使用芯片上某个通用定时器外设的输入捕捉function创建自己的自动波特率检测方案。 这些定时器可配置为使用内部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。 确定要使用的正确波特率后,重新配置引脚以将其分配给USART Rx外设function。

从数据表( 这一页,第759页)。 “在激活自动波特率检测之前,必须选择自动波特率检测模式” 。 – >尝试将您的行切换为:

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进程时,我认为它不会产生很大的不同HAL_UART_Init(&huart1); 无论如何。 但值得一试。 您也可以检查您的时钟源频率。

由于您使用的是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参考手册 :

这些模式是:

  • 模式0:任何以1位开头的字符。在这种情况下,USART测量起始位的持续时间(下降沿到上升沿)。

  • 模式1:任何以10xx位模式开头的字符。 在这种情况下,USART测量Start和第1个数据位的持续时间。 测量在下降沿到下降沿进行,确保在信号斜率缓慢的情况下具有更好的精度。

  • 模式2:0x7F字符帧(在LSB优先模式下可以是0x7F字符,在MSB优先模式下可以是0xFE)。 在这种情况下,波特率首先在起始位(BRs)结束时更新,然后在第6位结束时更新(基于从下降沿到下降沿的测量:BR6)。 在BR处对位0到位6进行采样,而在BR6处对字符的其他位进行采样。

  • 模式3:0x55字符帧。 在这种情况下,波特率首先在起始位(BRs)结束时更新,然后在位0结束时更新(基于从下降沿到下降沿的测量:BR0),最后在位结束时更新6(BR6)。 在BR处对位0进行采样,在BR0处对位1至位6进行采样,并且在BR6处对该字符的其他位进行采样。 并行地,对RX线的每个中间转换执行另一检查。 如果RX上的转换与接收器没有充分同步(接收器基于在位0上计算的波特率),则会产生错误。

如果你不能确保启用自动波特率检测后收到的第一个字节符合上述模式之一,那么我担心内置的自动波特率检测function对你不起作用。

但是,所有这些都可能不会丢失。 请参阅我对您问题的第二个答案。