引言
在对时间的精度要求比较高的场合,一般要求对采用单片机做控制器的系统进行精确的时间计算。有人对此问题做了研究并提出了很好的解决方法[13],但是他们有的是针对单片机使用频率为12 MHz晶振下汇编语言的特点作出的分析,有的是针对特定的使用条件或环境下的分析,不适合晶振频率为11.059 2 MHz的情况。为此,针对单片机定时器的特点,在此晶振频率下,利用TKStudio对定时器T0方式2进行分析仿真,取得了精确的定时时间,合理地解决了定时常数为小数的问题,为单片机定时提出了一种新思路。
1 理论分析
单片机有4种定时方式。方式0、方式1、方式3有一个共同点是有定时器溢出中断的响应时间误差,而方式2具有自动重载功能,没有这些误差。
产生中断溢出的响应时间误差的原因有3个:一是中断响应时间;二是定时器溢出中断信号时,CPU正在执行某指令;三是定时器溢出中断信号时,CPU正在执行某中断服务程序[4]。由于每条指令的执行时间不同且中断时不知道CPU会执行哪一条指令,这就导致中断溢出的响应时间不确定。
方式2是自动重载的,可以很好地免去上面的不确定时间。方式2的定时时间为T=12×(256-a)/fosc[5]。
以频率为11.059 2 MHz的晶振为例,定时250 μs分析,易得a=25.6。通常情况下,使用定时器时装的初值为常数,但是此处为小数,要想得到准确的250 μs,还必须要用a=25.6。下面为解决小数问题的分析:若a=25,则25-25.6=-0.6;若a=26,则26-25.6=0.4。那么以25.6为常数中断40次便是10 ms,试想前16次中断用a=25,误差为16×(-0.6)=-9.6,后24次中断用a=26,误差为24×0.4=9.6,可以看出,经过40次的中断便没有误差了,10 ms是准确值。这样,便可以用10 ms为基数产生出秒、分、时等。
2 程序仿真
编写一个计时程序,对其进行分析仿真。代码如下:
#include<reg52.h>
#define uchar unsigned char
uchar data Second=0;//秒
uchar data Minute=0;//分
uchar data Hour=0;//时
uchar data timecount=0;//中断次数计数
uchar data timeflag=0;//10ms标志位
void main (void){
EA=1;//允许CPU中断
ET0=1;//定时器T0中断打开
TMOD=0x02;//设定时器T0的方式2
TH0=0x19;//设置初值
TL0=0x19;//设置初值
TR0=1;//开始定时
while(1);//等待中断
}
void Time0(void) interrupt 1 using 1{
timecount+=1;//中断计数
if(timecount>=16)
TH0=0x1A;//计数16次之后改变初值
if(timecount>=40){
TH0=0x19; //改回到原来的初值
timecount=0;//计数清零
timeflag+=1;//设置10ms断点1
if(timeflag==100){
Second=Second+1;//设置秒断点2
timeflag=0; //清零10ms
if(Second==60){
Second=0;
Minute=Minute+1; //设置分断点3
if(Minute==60){
Minute=0;
Hour=Hour+1;//设置小时断点4
if(Hour==24)
Hour=0;
}
}
}
}
}
把程序放到TKStudio中进行仿真,在配置目标工程中填写11.059 2 MHz的晶振频率进行软件仿真。编译后开始调试,按程序标记分别对各个断点进行调试。
首先在第一个断点处调试,单击启动/停止按钮后,程序初始化,可以看出初始化时间为639.106 μs(如图1所示);然后单击运行按钮,运行到断点处会自动停止并显示运行的时间为10.037 977 ms(如图2所示),这里包括运行主函数其他指令的时间和执行一次timeflag变化的时间;然后再单击一次运行按钮,显示时间为10 ms(如图3所示),这一次为执行一次timeflag变化的时间,即中断40次250 μs的时间;
图1 断点1程序单击启动/停止调试按钮后初始化时间
图2 在断点1处运行第一次显示的数据
图3 在断点1处运行第二次显示的数据
继续按运行操作,可以发现以后的delta_s均是10 ms。取消断点1处的断点,在断点2处设断点,执行与断点1处相同的操作步骤得到的结果如图4~图6所示,其后的执行结果delta_s均为1 s。
图4 断点2程序单击启动/停止调试按钮后初始化时间
图5 在断点2处运行第一次显示的数据
图6 在断点2处运行第二次显示的数据
同样,在断点3处设断点运行,结果如图7~图9所示,以后的每次delta_s均为60 s。断点4处运行结果如图10~图12所示,以后每次delta_s均为3 600 s。
图7 断点3程序单击启动/停止调试按钮后初始化时间
图8 在断点3处运行第一次显示的数据
图9 在断点3处运行第二次显示的数据
图10 断点4程序单击启动/停止调试按钮后初始化时间
图11 在断点4处运行第一次显示的数据
图12 在断点4处运行第二次显示的数据
结语
本文对常用的频率为11.059 2 MHz的晶振在定时器T0方式2下做了分析,仿真结果良好;同时,提出了一种解决定时常数为小数问题的办法,能够推广应用于其他情况。