串口波特率误差产生的原因

描述

1、UART接口

UART全称Universal Asynchronous Receiver/Transmitter,通用异步收发器,是一种非常常见的异步收发协议,在嵌入式领域应用十分广泛。收发双方按照约定好通讯波特率进行配置,如果波特率不匹配会导致失败。

2、分频与波特率

使用单片机的朋友,经常使用4800、9600、38400、115200等波特率。设计电路时经常采用11.0592Mhz这样“不规则”晶振,看起来不规则,实际上很规则,原因是可以精确分频成常用波特率。

11.0592MHz=11059200=115200*96

11.0592MHz=11059200=57600*192

11.0592MHz=11059200=19200*576

有细心的朋友经常采用11.0592Mhz晶体设计电路,调试完串口通讯之后更换为12MHz后单片机依然能够正常通讯,并没有出现通讯异常。可见波特率有少许误差也是能够容忍的。

3、串口如何采样

串口接收方,在收到起始位后,延时1.5个位周期进行第1位采样,然后依次隔一个位周期采样一位,直至把所有数据位采样完成。如果接收方采样位置正好在数据位的中间位置,那么采样非常完美,不会出现问题。以下是8bit串口通讯数据格式示意图。

注意,这里的采样并不是只采样一次,有些芯片会采样多次,这里仅做示意。

晶振

4、误差原因

如果接收方位周期略微大于发送方位周期,就会出现下图所示的情况。采样位置逐渐偏移数据位中心,bit7采样位置偏移最严重。这就是波特率误差。采样点移位过多就会导致位错误,导致通讯失败。当然如果接收方位周期略微小于发送方位周期,也是同样道理。一般测特率误差2%-3%是没有问题的。

晶振

5、举例

笔者正在使用的某款cortex-M3内核芯片,需求的波特率是460800bps。串口时钟频率是36MHz。此款芯片波特率配置方法是串口时钟频率除以16,再除以分频因子。计算出分频因子(分频因子只能是整数),然后写入相应寄存器即可。算来算去,无论如何计算都不能准确分频出460800bps。按照如下代码计算出的分频因子是4。然后反推出波特率是562500bps,整除失去了小数位,导致差距巨大,根本无法通讯。

// baud rate = (serial clock freq) / (16 * divisor).
  tmpBaudRateDiv = (clocks.PCLK_Frequency / 16) / UART_InitStruct->UART_BaudRate;

于是乎做了个优化,如下代码,计算出的分频因子是5。然后反推出波特率是450,000bps,差距比较小,测试了一下通讯性能没问题。

// baud rate = (serial clock freq) / (16 * divisor).
  tmpBaudRateDiv = ((clocks.PCLK_Frequency / 16) + UART_InitStruct->UART_BaudRate / 2) / UART_InitStruct->UART_BaudRate;

6、不建议串口高速使用

串口毕竟是一个低速的数据传输协议,这种异步传输,没有时钟同步信号,在传输的每个字节中采样有误差积累,不建议高速使用,笔者使用过几种高波特率460800、921600、1500000等。原因是低端的单片机主频速率较低,处理高速数据流效率低下,如需高速使用,可根据自己需求开启串口FIFO、串口DMA、串口流控等。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分