51单片机硬件系统设计时,为什么用11.0592MHz的晶振而不用12MHz晶振的原因及串口波特率误差分析

时间:2024-02-29 21:39:10
        在设计51系列的单片机系统时,一般选用11.0592MHz的晶振而不选用12MHz的晶振,为什么?12M的晶振,振荡频率明显高于11.0592M的,按理说12MHz的晶振可以提高单片机的性能,那么我们为什么不用12M的呢?这个问题与单片机的串口波特率有关。


        51单片机的串口工作方式有4种,方式0、方式2的波特率是固定的,只与单片机的系统晶振频率有关。方式1、方式3波特率是可变的,不止与系统晶振频率有关,还与定时器T1有关(为什么是T1呢?因为51单片机的波特率发生器只能由定时器T1或定时器T2产生,由于我们使用的是STC98C52单片机,是标准51架构的单片机没有T2模块。)


        对于串口通信来讲最常用的是方式1,以下以串口的模式1来分析。由串口发送原理知,串口发送一次,实际上要发,1位起始位,8位数据位,1位结束位。由于使用模式1没有第9位数据位,所以,串口发送一次,一共要发10位数据,有一点要注意,在串口发送数据时,两次发送之间是没有累计误差的。


串口工作在方式1下的波特率计算公式为:
Baud = ((2^SMOD)/32)*(T1定时器溢出率)
其中SMOD为寄存器PCON的最高位,当SMOD = 0时,串口通信方式1、2、3波特率正常;当SMOD = 1时,串口通信方式1、2、3波特率加倍。

我们这里以不加倍,即SMOD = 0为例。


还有一个问题,由于串口方式1要用到T1定时器,而T1定时器也有4种工作方式,那么用哪一种工作方式呢?
方式0,兼容8048单片机的13位定时器,现在很少用到了,不予考虑;方式3,禁用定时器1,自然也不行;方式1、2都可以使用,那么用哪个更好呢?答案是用方式2,因为如果使用方式1,在中断中手动装载初值的方法来求溢出率的话,由于在进入中断、装值、出中断这个过程中,很容易产生时间上的微小误差,当多次操作时微小误差不断累积,终会产生错误。而方式2,由于当定时器计满溢出后单片机自动为其装载初值,并且无需进入中断服务程序进行任何处理,这样定时器溢出的速率就会相对更稳定。
综上所述,我们这里使用串口模式1、定时器模式2、SMOD = 0,由此查阅数据手册,得到以下计算公式:
Baud = Fosc/(256 - REDLOAD)/32/12
Fosc = 晶振频率
RELOAD = 自动重装载值
上述公式可以改写为
Baud = Fosc/(256 - RELOAD)/2/16/12

有几点注意一下,由图知:



        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后通信变得极不可靠。


注:
        关于通信波特率为什么要用4800、9600、19200等类似的数,有一种说法是,根据电、传输介质等的物理特性给串口设备的要求:
        为了保证有效通讯,根据电、传输介质等的物理特性结合串口设备的使用要求,确定RS232最大传输速率只能是115200,然后逐级二分得到57600、28800、19200。。。。为适应这些速率设计的相应的晶振频率。
另一种说法是,这是由电信线路特性决定的:
电话线路的带通是300—3KHz,当时HAYES先搞得modem,所以用的2400Hz信号,对应波特率是2400,由于基本频率确定了,以后采用的提高通信速率的方法都是2400基础上倍频的,所以形成了9600、19200。。。。
不管哪种说法都是先有波特率在有晶振频率的,也就是,波特率是前人在试验下得出的最佳的通信速率,我们使用的时候直接用现有的通信速率就行,但是要注意单片机使用的晶振频率,使用时会不会使串口产生误差,如果误差太大就会产生通信错误。


2018/4/1 青岛理工大学琴岛学院计算机工程系 -- 离远,本文为原创,转载请注明出处。


参考文献:
《手把手教你学51单片机(C语言版)》清华大学出版社,宋雪松、李冬明、崔长胜编著
《51单片机C语言教程——入门、提高、开发、拓展全攻略》电子工业出版社,郭天祥编著
STC89C52的数据手册
参考网络资料:


https://wenku.baidu.com/view/c1ca295684868762cbaed597.html
http://blog.sina.com.cn/s/blog_6202cb4101011udd.html
http://bbs.21ic.com/icview-207428-1-1.html