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、串口流控等。
全部0条评论
快来发表一下你的评论吧 !