任务3.5定时器的初步认识_第1页
任务3.5定时器的初步认识_第2页
任务3.5定时器的初步认识_第3页
任务3.5定时器的初步认识_第4页
任务3.5定时器的初步认识_第5页
已阅读5页,还剩6页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、任务3.5 定时器的初步认识 任务五 定时器的初步认识3.5.1 任务介绍在动态数码管的学习中,我们已经用DelayMs()延时函数实现了数字钟的走时,但是这种方式下的数字钟走时不够准确。生活中,我们需要精确计量时间时,通常会借助于走时准确的秒表,51单片机内部也有一个类似于秒表的装置,我们称之为定时器,借助于定时器,我们可以实现走时准确的数字钟。本节的任务是:利用单片机定时器完成走时准确的数字钟,另外在程序中,数码管扫描也由定时器来驱动。3.5.2知识准备1、定时器的引入在讲述定时器的原理之前,我们先看一下图3.5.1中的水龙头向水盆滴水的画面。在画面中,水龙头由于没有关紧,水一滴一滴地滴向

2、脸盆,盆的容量是有限的,水会在某一个时刻从水盆中溢出。假设一开始水盆没有水,65536个水滴恰好可以把水盆装满,恰好是计数了65536次。如果我们计数1000次怎么办呢?向水盆中预先装下了64536滴水,然后打开水龙头,开始滴水,等到水盆中的水溢出了,自然是计数了100次。如果水滴的速度是恒定的,1滴/1秒,计数就变成了计时了。实际古人计时装置“刻漏”的原理和水盆滴水的原理相似。 图3.5.1 水盆滴水 51单片机的定时器/计数器的原理与上面讲述的水盆滴水的例子类似,如表3.5.1所示。3.5.1 定时/计数器和水盆滴水的类比类比水盆滴水定时/计数器类比1水滴脉冲类比2水盆两个8位的RAM类比

3、3预先装入水滴设定RAM初值类比4打开水龙头启动定时器类比5水滴向水盆滴水每来一个脉冲,RAM加1类比6水盆的水溢出RAM数值溢出2、定时器的内部结构及工作原理在51单片机内部有2个定时器,分别称为定时/计数器0、定时/计数器1,每个定时/计数器具有计数和定时两大功能,有4种工作方式。定时/计数器0和定时/计数器1配置上完全相同,现用定时/计数器1的工作方式1来说明定时器内部结构与工作原理。图3.5.2为定时/计数器1在工作方式1下的内部结构图。(1)定时/计数器1的脉冲源有两种:当定时/计数器1工作于定时方式时,加1脉冲由振荡器的12分频提供(12M晶振的12分频为1MHz)。当定时/计数器

4、1工作于计数方式时,加1脉冲由外部脉冲源提供,P3.4是定时/计数器0的外部脉冲源输入端,P3.5是定时/计数器1的外接脉冲输入端。定时/计数器工作于定时还是计数方式,取决于选择开关C/,当C/=0时工作于定时方式,C/=1时工作于计数方式。(2)脉冲要经过启动开关才能到达RAM。启动开关=TR1 & ( | ) ,GATE为门控位,为外部中断1。当GATE=0时, | 的结果为1,则启动开关仅有TR1决定。当GATA=1,则启动开关的不仅由TR1决定,还要由来自于外部中断1的信号决定是否开启中断。(3)两个8位的RAM,高八位的RAM称为TH1,低八位的RAM称为TL1,组合在一起共

5、16位。每来一个脉冲,RAM的值加1,当RAM的数值超过65535时,计数器会溢出,溢出标志位TF1会由0变成1,同时TF1的变化会引发中断事件的发生。要设定不同的定时时间,在定时/计时器启动之前,向RAM预先装入初值。图3.5.2 定时/计数器1的内部结构(方式1)3、定时器的方式控制字51单片机的特殊功能寄存器(SFR)中有两个属于定时器的寄存器,分别为TMOD和TCON。(1) TMOD寄存器76543210GATEC/TM1M0GATEC/TM1M0定时/计数器1定时器/计数器0表3.5.1 TMOD寄存器从表3.5.1中我们可以看到,TMOD被分成两份,每份四位,高四位用于定时/计数

6、器1的控制,低四位用于定时/计数器0的控制。结合图3.5.2 定时/计数1的内部结构,GATE参与了启动开关的选择,称为门控位。C/T是用来选择定时还是计数,M1M0是下面要介绍的4种工作方式的选择位。(2)TCON寄存器表3.5.2 TCON寄存器76543210TF1TR1TF0TR0IE1IT1IE0IT0用于定时器用于外部中断 TCON寄存器也被分成了两份,前四位用于定时/计数器,后四位用于外部中断,如表3.5.2所示。前四位中又被分成了两份,分别属于定时/计数器1和定时/计数器0。其中TF是定时器溢出标志,没有溢出时为0,溢出后为1。TR参与了定时器的启动。需要说明的是,TMOD寄存

7、器中的每一个位不可以单独寻址,举例:定时/计数器0,定时模式,门控位为0,方式0(M1M0=01),可以写成TMOD=0x05。TCON寄存器中的每一个位可单独寻址,举例:启动定时器0,TR0=1就可以了。4、定时/计数器的四种工作方式51单片机的定时器有四种工作方式,TMOD寄存器中M1和M0位决定了使用哪种工作方式。M1M0为的配置和定时器的工作方式的对应关系如表3.5.3所示。表3.5.3 定时器工作方式M1M0工作方式描述00工作方式013位定时/计数器01工作方式116位定时/计数器10工作方式28位自动重装模式11工作方式32个独立8位定时/计数器工作方式0和工作方式3很少使用,在

8、这里不做专门的讲解,下面介绍工作在方式1和工作方式2的特点。(1) 工作方式1:当定时/计数器处于工作方式1时,两个8位的RAM都参与计数,即计数的范围是:065535。需要注意,工作于方式1时,定时/计数器溢出后,需要手动装入初值。(2) 工作方式2定时/计数器处于工作方式2时,相比于方式1,其计数范围缩小了,高8位的RAM不参与计数,低8位的RAM参与计数。其计数范围是0255。高8位的RAM闲置不用吗?实际上不是这样的,首先来分析一下定时/计数器在工作方式1下存在的问题。开发板的晶振频率为12MHz,12分频后为1MHz,脉冲周期是1us,选择定时模式时,每隔1us,RAM的值加1,16

9、位的定时/计数模式,最大定时范围为65.536ms。我们要实现数字钟的1秒定时,可以先定时50ms (RAM初值=65536-50000=15536),然后连续定时20次,就可以实现1秒的定时。在介绍工作方式1时,提到溢出后需要手动装入初值(15536),如果不手动装入初值,则溢出后,RAM从0开始计数。RAM的初值重装是在中断服务函数中完成的。定时/计数器溢出后产生中断,到进入中断服务函数后装入初值,是需要耗费时间的。实际是,定时/计数器溢出后,从0开始计数,运行一段时间初值重装了,又从初值运行。尽管这段时间很小(几十个us),但连续定时,日积月累,误差就大了,所以工作方式1下,定时的精度不

10、高。工作方式2下初值的重装不需要手动装入,一旦溢出,硬件自动完成初值的重装,中间没有时间耽搁,方式2比方式1定时要准确。定时/计数器初始化时,高8位RAM也装入初值,当定时/计数器溢出后,硬件自动把高8位RAM存放的初值导入到低8位RAM,完成初值重装。5、 定时器/计数器的初始化和溢出标志位处理定时器/计数器初始化设置如下:(1)TMOD寄存器的配置:定时/计数的选择,GATE门的设置,工作方式的选择。(2)装入初值,根据任务的要求,给THn、TLn(n为0或1)装入初值。(3)开总中断:EA=1,开定时器中断:ETn(n为0或1)=1。(4)如果还有别的中断,根据任务的重要性,需要确定中断

11、优先级,配置IP寄存器。(5)启动定时器/计数器,TRn(n为0或1)=1。定时器/计数器溢出可以采用查询和中断两种方式进行处理。查询方式效率低(主程序中不停的查询溢出标志位TFn(n为0或1)是否置位),本书中采用中断方式。6、定时/计数应用举例例程1:计数的应用自动化生产线上,12瓶易拉罐饮料为一箱,光电传感器检测到一瓶易拉罐就给送出一个脉冲,控制器连续接收到12个脉冲,则作为一个包装。本例用按键来模拟光电传感器发出的脉冲,按键接P3.4(定时/计数器0的外接脉冲输入端),用发光二极管的状态取反来模拟一个包装的动作,发光二极管接单片机的P0.0。连续按下12次按键,发光二极管状态取反一次。

12、根据任务要求,定时/计数器的配置如下:使用定时/计数器0,计数、工作方式1。程序如下:#include<reg51.h>#define uchar unsigned char #define uint unsigned int sbit LED=P00; /LED接口定义/计数器0初始化void Timer0Init()TMOD=0x05; /GATE=0,C/T=1,M1M0=01;TH0=(65536-12)/256; /RAM高8位赋值TL0=(65536-12)%12; /RAM低8位赋值ET0=EA=1; /开定时器中断和总中断TR0=1; /启动定时器/主函数void

13、main(void)Timer0Init(); /定时/计数器初始化while(1) /执行别的任务/计数器0中断服务函数void Timer0Intr(void) interrupt 1TH0=(65536-12)/256; TL0=(65536-12)%12; /溢出后重新赋初值LED=!LED; /中断每产生一次,发光二极管的状态取反一次程序解释:(1) Timer0Init()函数完成计数器的初始化。外部中断不参与计数器的开启,门控位:GATE=1;计数模式:C/T=1;工作方式1,M1M0=01。每12个脉冲到来,计数器溢出一次,初值为(65536-12),取出高8位和低8位,赋给T

14、H0和TL0。最后开中断,启动计数器。(2)计数器溢出后,CPU响应中断服务函数,在中断服务函数中,重新赋予初值,并完成LED的状态取反。例程2:定时的应用用定时的方式实现LED闪烁,LED闪烁的频率为1Hz。LED接单片机P0.0引脚,0.5秒亮,0.5秒灭。根据任务要求,定时/计数器的配置如下:使用定时/计数器1,计时、工作方式2。#include<reg52.h>#define uchar unsigned char#define uint unsigned int sbit LED=P10; /LED接口定义bit Flag500Ms=0; /500ms标志位/定时器1的初

15、始化void Timer1Init()TMOD=0x02; /GATE=0,C/T=0,M1M0=10; TH1=256-200; /RAM高八位赋值 TL1=256-200; /RAM低八位赋值,200us的定时ET1=EA=1; /开定时器中断和总中断TR1=1; /启动定时器/主函数void main(void)Timer1Init(); /定时器的初始化while(1) if(Flag500Ms=1) /500ms标志位置1Flag500Ms=0; /清空500ms标志位LED=!LED; /LED状态取反 /定时器1的中断服务函数void timer0_intr(void) inte

16、rrupt 1 static uint Cnt200us=0; /200us计数变量 if(+Cnt200us>=2500) /200us*2500=500ms Cnt200us=0; /清空计数变量Flag500Ms=1; /500ms标志位置1程序解释:(1) Timer0Init()函数完成定时器1的初始化。门控位不参与定时:GATE=0;定时:C/T=0;工作方式2,自动重装模式,M1M0=10。所以TMOD=0x20。200us定时器溢出一次,8位自动重装模式,所以TH1=TL1=(256-200)=56。(2) 由于采用了自动重装模式,在中断服务函数中,不需要重新赋初值。本任

17、务的定时目标是500ms,程序中定时器的定时长度是200us ,所以需要连续定时。每进入一次中断服务函数,200us计数变量(Cnt200us)加1,Cnt200us计数到2500,整个计时的时间为200us×2500次=500ms。(3) 500ms到来后,程序中并没有像上一个计数例子一样,在中断服务函数中完成LED的闪烁,而是把500ms标志位(Flag500Ms)置1,在主程序中,检测到该标志位置1,则完成LED的闪烁。(4)计数变量Cnt200us在定义的时候,uint前面多了个关键字static,其作用是声明变量Cnt200us为局部静态变量。什么是局部静态变量呢?C语言变

18、量根据定义的位置不同分为全局变量、局部变量,全局变量是在函数外部定义的变量,又称外部变量。全局变量一般定义在程序的开始处,可以为多个函数共同使用,其有效的作用范围是从它定义的位置开始整个程序文件结束为止。局部变量是在一个函数内部内部定义的变量,该变量只能在定义它的那个函数范围内有效,不同的函数可以使用相同的局部变量名。由于它们的作用范围不同,不会互相干扰,函数的形式参数也属于局部变量。局部变量根据存储空间分配的不同又分为自动变量和静态变量。在函数内部定义的变量,如果不做专门说明,则为自动变量。自动变量的特点是只在定义它们的时候才分配存储空间,在定义他们的函数返回时系统回收变量所占用的存储空间,

19、对这些变量存储空间的分配和回收是系统自动完成的,静态变量在定义是前面多了个关键字static,局部静态变量仍然保留局部变量的特性,只能在定义的函数内部使用,但与自动变量不同的是,再次调用定义它的函数时,它又可继续使用,而且保存了前次被调用后留下的值。 因此,当多次调用一个函数且要求在调用之间保留某些变量的值时,可考虑采用静态局部变量。弄明白了什么是局部静态变量,再来看中断函数中计数变量Cnt200us的使用就简单多了。首次调用中断函数时,计数变量Cnt200us定义且赋初值0,紧跟着在函数中Cnt200us的值加1,退出出中断服务函数后,Cnt200us的值不释放,仍然为1。3.5.3任务实施

20、本节的任务程序实现如下:#incldue<reg52.h>#define uchar unsigned char#define uint unsigned int /段码uchar code Seg7Code=0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90; uchar code Seg7Posit=0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f; /位码uchar DispBuffer6; /缓冲区bit SystemFlag1Ms=1; /1ms标志位 /6位数码管显示子函数,在第二位和第四位上

21、显示小数点void Seg7Display()static uchar i=0;P1=0xff; /消隐P0=Seg7Codedisp_buffi; /送段码if(i=1)|(i=3) P0&=0x80; /在第二位和第四位数码管上加小数点P1=Positi; /送位选if(+i>=6) i=0;/把时间送入缓冲区void TimerToBuffer(uchar nhour,nminute,nsecond)DispBuffer0=nhour/10;DispBuffer1=nhour%10; /小时的个位和十位的分解DispBuffer1=nhour%10; /小时的个位和十位的分

22、解DispBuffer2=nsecond/10;DispBuffer3=nsecond%10; /分的个位和十位的分解DispBuffer4=nminute/10;DispBuffer5=nminute%10; /秒的个位和十位的分解/定时器0初始化void Timer0Init() TMOD=0x02; /GATE=0,C/T=0,M1M0=02; TH0=56; /高8位RAM赋值 TL0=56; /低8位RAM赋值,200us定时 ET0=EA=1; /开定时器中断和总中断 TR0=1; /开启定时器/主函数void main(void) uchar Hour=9; /小时 uchar

23、Minute=23; /分uchar Second=37; /秒uint Cnt1Ms=0; /1ms计数器 Timer0Init(); /定时器0初始化while(1) if(FlagSystem1Ms=1) /定时器产生的1ms的时标信号到 SystemFlag1Ms=0; /时标信号清零 TimerToBuffer(); /显示数据送往缓冲区 Seg7Display(); /6位数码管动态显示 if(+Cnt1Ms>=1000) /1秒到,1ms*1000=1000ms Cnt2Ms=0; /2ms计数变量清零 if(+Second>=60) /秒加1,到60秒,则分加1 Second=0; /秒清零if(+Minute>=60) /分家1,到60分,则小时加1 Second=0; /秒清零 Minute=0; /分清零 if(+Hour>=24) /小时加1,到24小时 Hour=0; /小时清零 /定时器0中断服务函数,提供1ms的时标信号void timer0_intr(void) interrupt 1 static uchar Cnt200us=0; /200us计数变量if(+Cnt200us>=5) /0.2ms*5=1ms Cnt200us=0; /清空计数变量SystemFlag1Ms=1;

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论