对于串口通信来讲最常用的是方式1,以下以串口的模式1来分析。由串口发送原理知,串口发送一次,实际上要发,1位起始位,8位数据位,1位结束位。由于使用模式1没有第9位数据位,所以,串口发送一次,一共要发10位数据,有一点要注意,在串口发送数据时,两次发送之间是没有累计误差的。
我们这里以不加倍,即SMOD = 0为例。
有几点注意一下,由图知:
51单片机串口工作在方式1,上时,给串口使用的时钟频率要先除2,再除16,为什么要除2呢?因为实际上对于单片机的串口及外部的通信模块来说,单片机的晶振频率即使在12分频后,依然太快,所以先除2,降低串口模块所使用的的时钟频率。为什么要除16呢?因为在串口通信中为了保证所接收的数据的正确性,先对每位信号采集16次,再取其中的7、8、9次,如果有两次是高电平,就认定这一位是1,如果有2位是低电平,就认定这一位是0,所以,公式中频率要除16,。至于为什么要除12是因为公式中的频率Fosc是晶振频率,但是单片机所使用的的频率是经过了12分频的。所以对单片机而言一个机器周期等于12个时钟周期,为了理解上诉公式,有以下知识点需了解:
1个时钟周期 =1/晶振周期 = 1/Fosc
1个机器周期 = 12*(1/Fosc)
定时器T1的计数值每经过一个机器周期加1,即每经过12*(1/Fosc)秒,TL1加1,当TL1等于256就溢出,TH1将值重新赋给TL1,TL1开始重新计数。
如此我们设经过Y个机器周期TL1溢出,则:
Y*(12/Fosc) = (1/Baud)/2/16
Y =Fosc/Baud/32/12
由于使用T1的模式2,所以,设自动重装载值为RELOAD,则:
RELOAD= 256 – Y
= 256- (Fosc/Baud/32/12)
Baud =Fosc/(256 - RELOAD)/32/12
由高中物理知识知,误差等于实际值减理论值,再除理论值,再乘以100%,所以误差计算公式为:
Error= ((Baud – Baud0)/Baud0 )*100%
Baud0= 标准波特率
Baud =实际波特率
综上所述,可以得到以下公式:
RELAOD= 256 – INF(Fosc/Baud0/32/12 + 0.5)
Baud =Fosc/(256 - RELOAD)/32/12
Error= (Baud – Baud0)/Baud0 * 100%
RELOAD= 自动重装载值
Baud0= 标准波特率
Baud =实际波特率
Fosc =晶振频率
Error = 偏差
INF()表示取整运算(RELOAD只能为整数),即去掉小数,0.5可以达到四舍五入的目的。
当Baud0 =9600时,使用12MHz晶振:
RELOAD= 256 – INF(Fosc/Baud0/32/12 + 0.5)
= 256 - 3
= 253
Buad =Fosc/(256 - RELOAD)/32/12
= 12 * 10^6/3/32/12
= 10416.67
Error= (Buad – Buad0)/Buad0 * 100%
=8.51%
当Baud0 =9600时,使用11.059200MHz晶振:
RELOAD= 256 – INF(Fosc/Baud0/32/12 + 0.5)
= 253
Buad =Fosc/(256 -RELOAD)/32/12
= 9600
Error = 0
由上图知,理论上,要使采集的数为正确的,则第8位必须正确,则允许发送一字节累加误差不能超过50%,单个的位误差不能超过50/10*100% = 5%,由此可知在9600的波特率下,使用12MHz的晶振时,单个位超过5%,必定会出现传错的位。
实际上,单位误差控制在2%以内可以比较可靠的通信,超过5%串口通信就不可靠了,附上常用波特率使用12MHz晶振和11.0592MHz晶振的误差表:
由表知,使用12MHz的晶振在2400波特率下还是可以忍受的,但是超过2400后通信变得极不可靠。
2018/4/1 青岛理工大学琴岛学院计算机工程系 -- 离远,本文为原创,转载请注明出处。