为了正常的体验网站,请在浏览器设置里面开启Javascript功能!

利用 C51实现T0精确定时

2019-08-31 7页 doc 20KB 24阅读

用户头像

is_682974

暂无简介

举报
利用 C51实现T0精确定时Keil C51实现T0精确定时 (通过对定时器的误差分析和校正) 利用89C51设计一个简易日历时钟系统,时钟系统硬件主要由单片机控制的计时电路、复位等辅助电路、按键电路、数码管显示电路、电源系统等组成。日历时钟可以显示年、月、时、分、秒;可以设置年、月、时、分其中计时控制电路由AT89C51单片机控制;按键电路包含时间设置;时间显示屏电路由7个数码管组成;电源系统由小功率整流滤波稳压电路组成,输出直流电压5 V,向主电路及显示电路供电。系统框图如图1所示。 图1 日历时钟系统框图 在计时过程中,系统利用89C51...
利用 C51实现T0精确定时
Keil C51实现T0精确定时 (通过对定时器的误差分析和校正) 利用89C51一个简易日历时钟系统,时钟系统硬件主要由单片机控制的计时电路、复位等辅助电路、按键电路、数码管显示电路、电源系统等组成。日历时钟可以显示年、月、时、分、秒;可以设置年、月、时、分其中计时控制电路由AT89C51单片机控制;按键电路包含时间设置;时间显示屏电路由7个数码管组成;电源系统由小功率整流滤波稳压电路组成,输出直流电压5 V,向主电路及显示电路供电。系统框图如图1所示。 图1 日历时钟系统框图 在计时过程中,系统利用89C51自身的计时器T0作为时钟基准,计时器中断的准确度直接关系到整个系统的精度,因此获取精确的定时时钟信号成为该系统的关键。MCS-51单片机内有2个可编程的16位定时器/计数器,在本系统设计中采用AT89C51的定时器T0,并工作在方式1下,晶振频率为12 MHz。 1 T0定时中断 定时器/计数器T0工作方式1的电路逻辑结构如图2所示。T0定时特性功能寄存器由TL0(低8位)和TH0(高8位)构成。特殊功能寄存器TMOD控制定时寄存器的工作方式; TCON则用于控制定时器T0和T1的启动和停止计数,同时管理定时器T0和T1的溢出标志等。程序开始时需对TL0和TH0进行初始化编程,以定义它们的工作方式,并控制T0和T1的计数。在系统的设计中,计时单位以s为基准,并要求日误差≤10 s,如果用循环去做,无法满足精度要求。选用12 MHz的晶体可得到1 s的精度,经分析确定使用定时器0的方式1。这个方式下,定时器0是16位定时器,也就是最大定时值为FFFFH,12 MHz 晶体的每个定时周期为1 s,最多可以定时FFFFH×1 s=65635 us,即使使用最大值也无法一次定时1 s,设计中使用1次定时20 ms,50次定时中断得到1 s。20 ms定时中断的定时值为:FFFFH-20 ms/1 s= B1DFH。 图2 定时器/计数器工作方式1逻辑结构 2 程序测试与调整 在Keil uVision3平台下利用C语言实现如下代码: #include #define uchar unsigned char uchar data MScond= 0;//ms uchar data Scond= 0;//s uehar data M inute= 0;//min uchar data Hour= 0;//h void main(void){ EA =1; //允许CPU中断 ET0 = 1; //定时器0中断打开 TMOD =0x1; //设定时器0为方式1 TH0= 0xB1; TL0= 0xDF; //设定时值为20 000 us(20 ms) TR0 = 1; //开始定时 while(1); } void Time0(void) interrupt 1 using 1 { TH0=0xB1; //20 ms断点(1) TL0=0xDF; //设定时值 MScond= MScond+ 1; if(MScond == 50) {MScond=0; Scond= Scond+ 1; if(Scond == 60) {Scond=0; Minute=Minute+1; //分断点(2) if(Minute == 60) {Minute=0; Hour=Hour+1; //d,时断点(3) if(Hour == 24) { Hour=0; }}}} 首先调试每20 ms中断时的精度,在选项中设定调试晶振为12 MHz,在(1)处设置一个断点再运行,这时记录下每次中断时的时间,如图3所示。在初始化中费时为551 s,每一次中断时间应该考虑该项的影响。在实际处理中可以利用两次中断时间的差来作为定时器的中断时 间间隔。 通过测试,得到第一次为0.020 568 00 s,第二次为0.040 580 00 s,第三次为0.060 592 00 s。可以看出,每中断一次会比定时值长了12 s。如果将断点设定在(2)处,并通过Logic Analyzer tool,得到分钟第一次中断的时间为60.036 57 S,第二次中断的时间为120.072 57 s,则每分钟的实际时间为60.036 S。再将断点设定在(3)处,得到小时第一次中断的时间为3 602.160 576 S,第二次中断的时间为7204.320 576 S,可以得到小时的实际时间为 3602.16 S,如图4所示。 为什么会产生这些误差呢?通过对中断程序的汇编源码进行分析,实际上中断程序入堆栈时使用了两条语句:PUSH ACC和PUSH PSW。执行人栈指令花费了4个机器周期,加上重新对TH0和TL0的加载又用去2个机器周期,计数值加1花费了2个机器周期,中断返回约4个机器周期共约12个机器周期。为了消除这些因素的影响,需要在对T0设置计数值时减去12个机器周期,将计算得到的初始值B1DFH加上12(0CH)得到: B1DFH+12=B1EBH作为新的定时器初值,修改后的程序为: #include #define uchar unsigned char uchar data MScond=0; //ms uchar data Scond=0; //s uchar data Minute=0; //min uchar data Hour=0; //h void main(void){ EA = 1; //允许CPU 中断 ET0= 1; //定时器0中断打开 TMOD = 0x1; //设定时器0为方式1 TH0= 0xB1; TL0=0xEB; //设定时值为20 000 (20 ms)减去12 TR0= 1; //开始定时 while(1); } void Time0(void) interrupt 1 using 1 {TH0=0xB1; //20 ms断点(1) TL0=0xDF; //设定时值 MScond= MScond+ 1; if(MScond == 50) {MScond=0; Scond= Scond+ 1; if rScond == 60) {Scond=0; Minute=Minute+1; //分断点(2) if(Minute == 60) {Minute=0; Hour=Hour+1; //时断点(3) if(Hour == 24) { Hour=0;}}}} 重新调试程序,仍然在选项中设定调试晶振为12 MHz,重新测试20 ms定时器的实际 时间,在(1)处设置一个断点后运行,重新记录下每次中断时的时间,如图5所示。初始化 时间为556 s,为消除其影响,使用两次中断时间间隔来作为定时器实际获得的基准时钟。得到一次中断时的时间为0.020 556 00 S,第二次为0.040 556 000,第二次为0.060 556 00 s,可以看出每次中断间隔刚好20 ms。如果将断点设定在(2)处.并通过Logic Analyzer tool,得到第一次中断时时间为60.000 57 s,第二次为120.000 57 s,间隔刚好60 s。将断点设定在(3)处,得到第一次中断的时间为3600.000 578 s,第二次中断时间为7200.000 578 s,时间间隔为3 600 s,测试结果如图6所示,完全可以满足系统设计的需要。 3 通过对定时器的误差分析和校正.可以提高系统的精确度。当然.上面的分析是在软环 境下理想晶振频率下实现的,在现实中会因晶振偏差等因素而造成误差。在该测试中,主程序没有进行其他处理,而在日历设计中还要涉及到计时器T1的中断来完成对扫描显示电路的处理,还包括外部中断对时钟进行了调整,加上一些闹钟功能,这必然会对T0的定时精确性产生影响。另外.当中断程序中语句越多,占用的机器周期也越多,因此在设计中应充 分利用Keil uVision3的分析工具,通过多次调整计数初值以获取精确的时钟信号,这对于 要求精确时钟信号的应用具有重要的意义。
/
本文档为【利用 C51实现T0精确定时】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑, 图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。 本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。 网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。

历史搜索

    清空历史搜索