UART通信的误差计算:
接收方与发送方频率不准,可能引起累积误差?
晶振时间积累误差
比如发送器和接收器,两边的晶振,发生了最大的相反方向的漂移,内置8MHz晶振误差精度0.5% ,两边累积最大误差达到1%
内置8MHz晶振,实际则为 8 MHz*(+ -1.005) = 7.96MHz~ 8.04MHz 接收方和发送方,晶振都不准,这将对通信产生不确定影响。
下图是两个晶振的误差对比
晶振 |
频率精度 |
60s误差 |
ms误差 |
us误差 |
通信误差 通信速度230400bit/s |
内部8Mhz |
+-5000ppm (0.5%) |
60s ±0.3s |
1000ms ±5ms |
1 000 000 us ± 5000us |
4.34us ±0.0217us |
外部8MHz |
+-30ppm (0.003%) |
60s ± 0.0018s |
1 000 000 us ± 30us |
从上面表格可以看出晶振误差对单片机系统时间的影响。
假设,通信速度230400bit/s , 则发送1bit数据的时间 = 1000000us / 230400bit = 4.34±0.0217us
每发1bit 数据时间消耗为 4.34±0.0217us 误差为±0.5%
可以想象,如果连续发100个bit,误差时间会积累到2.17us!当误差积累到1/2bit的时候,接收器的这个位就错开了。 导致数据偏移 ,发生错误。
不过,我们的UART有开始位,停止位,每10bit数据发完,都会重新从开始位、停止位、来重新检测边沿信号。再确定开始点。
因此这部分的积累误差,没有影响!因为UART的数据帧最多也就是10bit左右
晶振不准导致配置出来产生误差?
如果你知道真实频率就不会,因为可以调节分频值,最后达到标准频率
但,如果你不知道晶振发生了漂移,想当然,仍然使用标准频率进行计算,那就会有较大误差。
我们用最坏的情况做一个假设
在这个设置下 230400bps 8n1
不准的两个晶振( 8MHz ±1% ):
->内置7.92MHz不准晶振的发送设备1
->内置8.08MHz不准晶振的接收设备2
导致不准的外设频率:
发送设备1的外设频率 PCLK1 = PLL1 = (IRC7.92M/2) * 4 = 15.84 MHz
接收设备2的外设频率 PCLK2 = PLL2 = (IRC8.08M/2) * 4 = 16.16 MHz
最多分配频率 : 每1bit数据,能分配的频率数 ( PCLK / 波特率):
发送设备1 每1bit数据最多分配的时钟个数 = 15,840,000 / 230400 = 68.75 Hz/bit
接收设备2 每1bit数据最多分配的时钟个数 = 16,160,000 / 230400 = 70.14 Hz/bit
过采样设置:
由于过采样技术要求,1bit数据最少分配x8个采样时钟!默认一般是x16个采样时钟!
所以上面我们给每bit分配的频率,还要再除上16或者8
除出来这个数(也就是USARTDIV)>1 ,时钟才能完全撑得起这个采样率。
(否则,时钟频率都没那么快,1bit数据怎么采样16次?)
过采样数,也就是手册中常看到的。过采样倍率 = (8*(2-OVER8))
OVER8寄存器的值 =0表示 x16采样,
OVER8寄存器的值 =1表示 x8采样
对于GD32这种,带入进去算出来,就是x8或者x16倍过采样。
计算期望中的分频系数:
此时熟悉的公式就出来了:USARTDIV = PCLK1 / (波特率*(8*(2-OVER8)) )
正常PCLK= 36.00 MHz设备 USARTDIV = 36,000,000 / ( 230400 *16 ) = 9.765625 (100%)
正常PCLK= 16.00 MHz设备 USARTDIV = 16,000,000 / ( 230400 *16 ) = 4.340278 (100%)
晶振发生偏移的 发送设备1 USARTDIV1 = 15,840,000 / ( 230400 *16 ) = 4.297 (98.9999%)
晶振发生偏移的 接收设备2 USARTDIV2 = 16,160,000 / ( 230400 *16 ) = 4.384 (101.00159%)
只要USARTDIV >1,则表明MCU的运行频率,可以撑得起来这个采样率。
根据期望的分频系数,再设置USART_BAUD 寄存器 :
根据上面算出的带小数点的分频系数 USARTDIV,需把整数部分和小数部分分开。
小数部分*16,然后四舍五入,取整填入到小数部分的位中。如果这个值超过16要进位到整数部分。
而整数部分,则直接转换成16进制。最后将两部分用 " | "拼起来,就是USART_BAUD 寄存器的值了。
下面是实际的转换过程:
比如:
正常PCLK= 36.00 MHz 的设备算出 USARTDIV = 9.765625 四舍五入下 9.77
然后把9 和 0.77分别处理。9就是0x9, 0.77先要乘以16 =12.32 取整数=12 ,那么12就是0xC
所以配置寄存器USART_BAUD = 0x9| 0xC =0x9C
同理:
正常PCLK= 16.00 MHz设备 USARTDIV = 4.340 ≈ 4.30
配置寄存器USART_BAUD = 0x4 | 0x5 (0.34*16 = 5.44 ≈ 5 ) = 0x45
晶振发生偏移的 发送设备1 USARTDIV1 = 4.297 ≈ 4.30
寄存器配置USART_BAUD = 0x4 | 0x5 (0.30*16 = 4.8 ≈ 5 ) = 0x45
晶振发生偏移的 接收设备2 USARTDIV2 = 4.384 ≈ 4.38
寄存器配置USART_BAUD = 0x4 | 0x6 (0.38*16 = 6.08 ≈ 6 ) = 0x46
根据实际的寄存器设置,这里反算出了,实际中的分频系数
正常PCLK= 36.00 MHz设备 实际USARTDIV = 9 + ( 12/ 16) = 9.75
正常PCLK= 16.00 MHz设备 实际USARTDIV = 4 + ( 5/ 16 ) = 4.3125
发送设备1 实际USARTDIV1 = 4 + ( 5/ 16 ) = 4.3125
接收设备2 实际USARTDIV2 = 4 + ( 6 /16 ) = 4.375
由于:USARTDIV = PCLK / ( 实际波特率*16)
则:实际波特率 = PCLK /( USARTDIV *16)
这样就算出了实际的波特率了。 这样对比标准的波特率,就知道误差了。
编写了一个计算器,有兴趣的朋友可以试试。
GD32、STM32串口波特率计算器USART误差计算器预分频计算器_gd32波特率,stm32串口通信计算器-C文档类资源-CSDN下载编写了一个计算器,有兴趣的朋友可以试试。可以计算串口通信USART、UART的波特率,通信误差,预分gd32波特率更多下载资源、学习资料请访问CSDN下载频道.https://download.csdn.net/download/weixin_46801290/85256363?spm=1001.2014.3001.5501
PCLK Hz |
PCLK MHz |
过采样 |
标准波特率 |
波特率误差 |
实际波特率 |
期望分频系数 |
实际分频系数 |
15840000 |
15.84 |
16 |
230400 |
-0.36% |
229565 |
4.297 |
4.3125 |
16160000 |
16.16 |
16 |
230400 |
0.20% |
230857 |
4.384 |
4.375 |
16000000 |
16 |
16 |
115200 |
-0.08% |
115108 |
8.681 |
8.6875 |
16000000 |
16 |
16 |
230400 |
0.64% |
231884 |
4.340 |
4.3125 |
16000000 |
16 |
16 |
460800 |
-0.79% |
457143 |
2.170 |
2.1875 |
16000000 |
16 |
16 |
921600 |
2.12% |
941176 |
1.085 |
1.0625 |
36000000 |
36 |
16 |
230400 |
0.16% |
230769 |
9.766 |
9.75 |
72000000 |
72 |
16 |
921600 |
0.16% |
923077 |
4.883 |
4.875 |
72000000 |
72 |
16 |
115200 |
0.00% |
115200 |
39.063 |
39.0625 |
72000000 |
72 |
16 |
2250000 |
0.00% |
2250000 |
2.000 |
2 |
72000000 |
72 |
16 |
230400 |
0.16% |
230769 |
19.531 |
19.5 |
72000000 |
72 |
16 |
115200 |
0.00% |
115200 |
39.063 |
39.0625 |
8000000 |
8 |
16 |
230400 |
-0.79% |
228571 |
2.170 |
2.1875 |
4000000 |
4 |
16 |
115200 |
-0.79% |
114286 |
2.170 |
2.1875 |
16MHz的外设频率 ,设置成921600bps 误差2.12%,有点大,但我赌它能勉强通信。
总误差在<2.5% 都可以通讯,但可靠的角度来看误差<1%,甚至更小才好!
这个下面的表,是从官方手册里面截的, 和我上面Excel表格里计算出来的一致。
波特率 |
PCLK 36MHz |
PCLK 72MHz |
|||||
序号 |
标准波特率 Kbps |
实际波特率 |
实际分频系数USARTDIV |
误差% |
实际波特率 |
实际分频系数USARTDIV |
误差% |
1 |
2.4 |
2.400 |
937.5 |
0% |
2.4 |
1875 |
0% |
2 |
9.6 |
9.600 |
234.375 |
0% |
9.6 |
468.75 |
0% |
3 |
19.2 |
19.2 |
117.1875 |
0% |
19.2 |
234.375 |
0% |
4 |
57.6 |
57.6 |
39.0625 |
0% |
57.6 |
78.125 |
0% |
5 |
115.2 |
115.384 |
19.5 |
0.15% |
115.2 |
39.0625 |
0% |
6 |
230.4 |
230.769 |
9.75 |
0.16% |
230.769 |
19.5 |
0.16% |
7 |
460.8 |
461.538 |
4.875 |
0.16% |
461.538 |
9.75 |
0.16% |
8 |
921.6 |
923.076 |
2.4375 |
0.16% |
923.076 |
4.875 |
0.16% |
9 |
2250 |
2250 |
1 |
0% |
2250 |
2 |
0% |
10 |
4500 |
不可能 |
不可能 |
不可能 |
4500 |
1 |
0% |
如果晶振频率偏移了1%,并且我们不知道它偏移了,仍然设置正常晶振的值会怎样?
回到最初的问题,以上都是基于,我们知道晶振的具体频率才能准确设置分频的。
但,如果我们误以为晶振是16MHz但它实际上是15.84MHz,或者16.16MHz,它会增加多少差多少呢?
PCLK Hz |
PCLK MHz |
过采样 |
标准波特率 |
波特率误差 |
实际波特率 |
期望分频系数 |
实际分频系数 |
15840000 |
15.84 |
16 |
230400 |
-0.36% |
229565 |
4.297 |
4.3125(误以为PCLK =16MHz 所以设置这个值) |
16160000 |
16.16 |
16 |
230400 |
1.65% |
234203 |
4.384 |
4.3125(误以为PCLK =16MHz 所以设置这个值) |
16000000 |
16 |
16 |
230400 |
0.64% |
231884 |
4.340 |
4.3125 |
看到上表中,误差明显增大了, 1.65 % + 0.36% = 2.01% 总偏差 > 2%了。
所以如果晶振发生了漂移,对通信是有影响的。收发两边的晶振如果频率相差>2%,那就要考虑晶振引起的通信误差问题了。
如果是±0.5%以内的误差是可以接受的, 如果使用稳定的外部晶振,那晶振的误差仅为±0.003%,则无需担心晶振引起的误差。