自动波特率检测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 ..等
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
or101
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屋!