足球比分直播

定时器深入研究.doc

返回
定时器深入研究.doc_第1页
第1页 / 共8页
定时器深入研究.doc_第2页
第2页 / 共8页
定时器深入研究.doc_第3页
第3页 / 共8页
定时器深入研究.doc_第4页
第4页 / 共8页
定时器深入研究.doc_第5页
第5页 / 共8页
点击查看更多>>
资源描述:
定时器/计数器的深入研究-精确定时 作者佚名 发布时间2009-10-9 阅读次数1372 字体大小 【小】 【中】【大】 今天结合救火车单片机实验室编写的小软件定时器时间计算工具 1.0,来讲述定时器的工作过程。请到 www.qm999.cn 免费下载。我编这个小软件尽可能的模拟了 51 的定时器结构,相信你用过以后,一定会加深对定时器的理解。一、定时器相关寄存器与定时器有关的寄存器都在下面了。TCON 的高 4 位 TF1 TR1 TF0 TR0 TF1(TCON.7)定时器 1 的溢出中断标志位TR1(TCON.6)定时器 1 的运行控制位TF0(TCON.5)定时器 0 的溢出中断标志位TR0(TCON.4)定时器 0 的运行控制位TMODGATE1 C/T1 M1 M0 GATE0 C/T0 M1 M0 定时器 1 | 定时器 0 TH0、TL0、TH1、TL1这个不用说了吧中断允许控制寄存器 IE 中的三位。ET0IE.1、ET1IE.4、EAIE.7定时器的结构(以 T0 为例)把定时器分为六个部分来研究。脉冲源 控制端 计数器 中断请求位 中断允许控制 中断服务程序晶振或 T0 TH0、TL0 TF0 ET0 EA void Tm0 interrup1 using 1 脉冲源用作定时器时,取晶振作为脉冲源。每 12 个振荡周期(即一个机器周期)计数器(即TH0、TL0)加一。用作计数器时 T0 脚出现下降沿(管脚从 1 到 0)跳变时,计数器加一。定时器和计数器的区别就是脉冲源不同,除此之外其他的工作过程完全相同。配置 TMOD 的 C/T0 可以选择脉冲源。置 0 是定时器,置 1 是计数器。控制端相当于一个开关,开关打开时,脉冲源的信号才能传到计数器(TH0,TL0)中,计数器会不断增一。关闭这个开关,脉冲源的信号不能使计数器(TH0,TL0 )增一。控制端的开启和关闭状态由TR0、GATE0 和 INT0 脚电平决定。控制端的开启条件是 TR0TIMER0 中断服务程序PUSH ACCPUSH PSWMOV TH0,0EEH。。。其他程序POP PSWPOP ACCRETIinclude //11.0592Mvoid timer0 interrupt 1 using 1 //5ms 中断一次定时器中断处理函数{TH00 xEE; //重置定时初始值。。。其他程序}void main void{TMOD|0 x01; //选择定时器 0,工作模式 1,16 位定时器TH00 xEE; //置定时初始值TL00 x00;ET01; //开启定时器 0 中断允许,允许定时器 0 中断。EA1; //开启全局中断允许。允许所有中断TR01; //开启控制端 while1{。。。主程序}}顺便把其他中断源的向量表也写出来。中断源 汇编语言 C 语言 中断向量 例子 中断序号 例子 外部中断 0(INT0) 0003H ORG 0003H 0 void _INT0 interrupt 0 using 1 定时器 T0 中断 000BH ORG 000BH 1 void _T0 interrupt 1 using 1 外部中断 1(INT1) 0013H ORG 0013H 2 void _INT1 interrupt 2 using 1 定时器 T1 中断 001BH ORG 001BH 3 void _T1 interrupt 3 using 1 串行口中断 0023H ORG 0023H 4 void _UART interrupt 4 using 1 定时器 T2 中断 002BH ORG 002BH 5 void _T2 interrupt 5 using 1 定时器例程之一精确定时 1 秒钟我使用的硬件是救火车单片机工作室的 JHC-51-A 型学习板。晶振频率 11.0592M。用定时器 0 的工作方式 1 实验。因为工作方式 1,最大的计数是 65536 个机器周期。晶振是 11.0592M 时,最长溢出时间是 71111.1111111111 微秒,远远不够 1 秒,所以我把定时器 溢出时间定成 5 毫秒。在定时器工具中输入 5000,点 [计算 TH0 TL0] 计算出 TH0 0 xEF ,TL0 0 x00.溢出时间是 5 毫秒,相当 1 秒的 200 分之一。在定时器工具中输入 5000,点 [计算 TH0 TL0] 计算出 TH0 0 xEF ,TL0 0 x00.溢出时间是 5 毫秒,相当 1 秒的 200 分之一。在程序中声时一个外部变量,计 200 次中断,就是 1 秒。unsigned char ms_50;void timer0 interrupt 1 using 1 //5ms 中断一次定时器中断处理函数{TH00 xEE; //重置定时初始值if ms_5200{ms_50;//程序每 1 秒钟进入这里一次。}}//主程序如下void main void{TMOD|0 x01; //选择定时器 0,工作模式 1,16 位定时器TH00 xEE; //置定时初始值TL00 x00;ET01; //开启定时器 0 中断允许,允许定时器 0 中断。EA1; //开启全局中断允许。允许所有中断TR01; //开启控制端 到这里我们把定时器 0 做成了一秒钟的程序完成了。有很多朋友会有这样的疑问,这样做的 1 秒钟到底准不准有多大误差我可以负责任的告诉你,有误差,但可以控制到极其微小的程度。下面我们发析一下误差的产生,以及控制方法。晶振的误差我们的晶振一般误差都是 20PPM 的,百万分之二十。想提高精度,只能选择误差更小的晶振,但它毕竟不是为精确定时设计的,很难达到时钟芯片晶振的精度。单片机中断系统的误差。定时器产生中断请求以后,并不一定能马上响应这个中断。单片机要把当前的指令执行完。51 的指令是 1 到 4 个周期。如果赶上两周期指令,就会延误一个指令周期。最慢的情况会延误 3 个周期响应中断。这点误差倒是没什么关系。但是如果单片机正处理其他的中断(同级或更高级)。要等其执行完其他中断,再执行一条主程序指令,才会响应定时器 0 中断。因为程序千差万别,所以其他中断占用的时间,就没准儿了。更要命的是,这类影响是随机的,你根本无法纠正。看起来好像没有办法了,但是你深入研究定时器的工作原理以后,你会发现这个问题还是有可能解决的。请仔细看一下,我上面的中断程序,“TH00 xEE;” 你是否注意到,我没有给 TL0 重新赋值。这可不是疏忽忘了。我们知道定时器只要开着,TH0 和 TL0 就会不断的增一,增到 FF FF,再增一就溢出,这时 TF0 被硬件置 1(也就是中断请求)。我们要注意的就是不管定时器中断是否被响应,TH0 和 TL0仍然会不断增一,FF FF 增一 00 00 再增一 00 01 再增一 00 02 。这就是我为什么要选择 5 毫秒作为定时长度的原因。因为 TH0EE TL000。最主要的就是 TL000。定时器在溢出产生中断以后,不论响应还是不响应,TL0 并不停止计数。虽然中断响应有可能被延迟,但是延迟的时间仍然被计算。延迟的时间在下一次中断时会“补上” 。这就是只对 TH0 重赋值的原因。从理论上说,真正是一个微秒都不差。研究出这个用法以后,着实让我兴奋了好长时间。呵呵。还有一点需要注意。其他的中断占用的时间太长,TL0 增数超过 256,定时器中断响应时 TH0 已经大于 0 了,直接写 TH00 xEE;就有误差了.可以改成 TH0TH00 xEE;但这样也会有一点点问题,我们不在这里详细讨论。最好还是控制其他的中断占用时间不要超过 240 个机器周期。每秒钟最后一次入中断的误差。原因和上面说的相同,误差在下一秒也会“补上” 。定时器例程之二 模拟时钟这也是 JHC-51-A 的实验 6-1 的内容。以下是部分程序void init_timer0void{//以下为初始化定时器TMOD|0 x01; //选择定时器 0,工作模式 116 位定时器TH00 xEE; //置定时初始值TL00 x00;//初始化完毕。ET01; //开定时器 0 中断,允许定时器 0 中断。EA1; //开全局中断。允许所有中断TR01; //开始计数 }unsigned char time_allow; //整点报时标志unsigned char time_num; //报时的次数 ,unsigned char fmq_times; //整点报时 蜂鸣器声音维持时间计数unsigned char set_kk_times; unsigned char ms5_times; //5ms 中断计次unsigned char hour,min,sec; //定义时,分,秒。void timer0 interrupt 1 using 1 //5ms 中断一次定时器中断处理函数{//重新置位计数初始值 在工作方式 1 下,需要重新置位定时初始值,程序才会再一次进入中断,//工作方式 0,3 也是如此,只有工作方式 2 不需要重新置位初始值。TH00 xEE; //置定时初始值ifms5_times200 //5ms 中断一次,计数 200 次 达到 1s{ms5_times0;dc10; //处理小数点 点亮sec; //时钟 秒1ifsec60 //秒计数达到 60{sec0;min; //分钟1ifmin60 //分钟计数达到 60 {min0;hour; //小时1ifhour23 hour0; //24 小时制,计数达到 24,清零}}}if0sec{if0min //如果时间达到整点。允许报时功能{ifhour12 time_numhour-12; //如果时间超过 12 点,报时声音次数相应减 12else if0hour time_num12; //如果时间为零点。报时声音为 12 次 else time_numhour; //报时次数为时间值time_allow1; //报时允许标志置位}if30min //如果时间达到半点,允许报时功能{time_allow1; //报时标志置位time_num1; //报时次数 1 次}}if1time_allow //如果报时允许{iffmq_times200 {fmq_times0;spk1; //蜂鸣器停止发声time_num--; //报时次数减 1 } if100fmq_times spk0; //蜂鸣器发声 if0time_num time_allow0; //报时结束 清零报时标志位}ifms5_times80 dc11; //处理小数点 熄灭ifset_kk_times200 set_kk_times0; disp_LEDdisplay; //刷新数码管}
展开阅读全文
收藏
下载资源

加入会员免费下载





足球比分直播