51单片机定时器的使用和详细讲解 特别是定时器2
- 格式:ppt
- 大小:629.00 KB
- 文档页数:50
STC89C52单片机定时器2详细整理51单片机是我自学的第一款单片机,那时正好是过春节,想起那个寒假,外面下着大雪,有时还会传来一两声爆竹的炸响,而我一个人在房间里摆弄单片机开发板,反复调试程序的时光,真是难忘!我自认为这款单片机所有的资源中最不好搞清楚的就是定时器2,尤其是对于那些以前从来没有玩过单片机的新手。
定时器2是新增资源,也是51单片机定时器里面功能最强大的一个定时器。
所以掌握好定时器2还是非常有必要的。
以下是在我完全搞明白它的原理和用法的基础上整理的一篇小文章。
读起来,好像Datasheet一样!请原谅,希望没有辜负你的点击!定时器2是一个16位定时器/计数器,通过设置特殊功能寄存器T2CON中的C/T2位可将其设置为定时器或是计数器;通过设置T2CON中的工作模式选择位可将定时器2设置为三种工作模式,分别为捕获、自动重新装载(递增或是递减计数)和波特率发生器。
知识点一、定时器2的控制寄存器T2CON(可按位寻址)*D7位--TF2:定时器2溢出标志位。
用于请求中断(必须由软件清0)D6位--EXF2:定时器外部标志位。
当外部信号使能时,发生外部负跳变时置位请求中断(必须由软件清0)D5位--RCLK:接受时钟标志位。
默认情况下串行口中模式1和模式3的时钟是由定时器1的溢出率提供,若该位置位,则由定时器2提供。
D4位--TCLK:发送时钟标志位。
原理同上D3位--EXEN2:定时器2的外部使能标志位。
定时器2没有作为串行口时钟时,若将该位置位时,将允许T2EX的负跳变产生捕获或重装D2位--TR2:定时器2启动/停止控制位。
D1位--C/T2:定时器2的定时器/计数器选择位(在reg52头文件中定义为了C_T2,请注意,下面相同)D0位--CP/RL2:捕获/重装标志位。
知识点二定时器2的模式控制寄存器T2MOD(不可按位寻址)该寄存器在单片机的头文件reg2.h中可能没有被定义,自己定义吧!D1位—T2OE:定时器2输出使能位D0位—DCEN:向下计数使能位知识点三:定时器2的三种模式**1、捕获模式*在'CP/RL2=1'&&'TR2=1'时进入捕获模式。
151单片机定时器/计时器的使用步骤:1、 打开中断允许位:对IE 寄存器进行控制,IE 寄存器各位的信息如下图所示:EA : 为0时关所有中断;为1时开所有中断ET2:为0时关T2中断;为1时开T2中断,只有8032、8052、8752才有此中断 ES : 为0时关串口中断;为1时开串口中断 ET1:为0时关T1中断;为1时开T1中断 EX1:为0时关1时开 ET0:为0时关T0中断;为1时开T0中断 EX0:为0时关1时开2、 选择定时器/计时器的工作方式:定时器TMOD 格式CPU 在每个机器周期内对T0/T1检测一次,但只有在前一次检测为1和后一次检测为0时才会使计数器加1。
因此,计数器不是由外部时钟负边沿触发,而是在两次检测到负跳变存在时才进行计数的。
由于两次检测需要24个时钟脉冲,故T0/T1线上输入的0或1的持续时间不能少于一个机器周期。
通常,T0或T1输入线上的计数脉冲频率总小于100kHz 。
方式0:定时器/计时器按13位加1计数,这13位由TH 中的高8位和TL 中的低5位组成,其中TL 中的高3位弃之不用(与MCS-48兼容)。
13位计数器按加1计数器计数,计满为0时能自动向CPU 发出溢出中断请求,但要它再次计数,CPU 必须在其中断服务程序中为它重装初值。
方式1:16位加1计数器,由TH 和TL 组成,在方式1的工作情况和方式0的相同,只是计数器值是方式0的8倍。
2方式2:计数器被拆成一个8位寄存器TH 和一个8位计数器TL ,CPU 对它们初始化时必须送相同的定时初值。
当计数器启动后,TL 按8位加1计数,当它计满回零时,一方面向CPU 发送溢出中断请求,另一方面从TH 中重新获得初值并启动计数。
方式3:T0和T1工作方式不同,TH0和TL0按两个独立的8位计数器工作,T1只能按不需要中断的方式2工作。
在方式3下的TH0和TL0是有区别的:TL0可以设定为定时器/计时器或计数器模式工作,仍由TR0控制,并采用TF0作为溢出中断标志;TH0只能按定时器/计时器模式工作,它借用TR1和TF1来控制并存放溢出中断标志。
51单片机的定时器_计数器的C51编程相关知识点:1、单片机的定时器/计数器,实质是按一定时间间隔、自动在系统后台进行计数的。
2、当被设定工作在定时器方式时,自动计数的间隔是机器周期(12个晶振振荡周期),即计数频率是晶振振荡频率的1/12;3、当定时器被启动时,系统自动在后台,从初始值开始进行计数,计数到某个终点值时(方式1时是65535),产生溢出中断,自动去运行定时中断服务程序;注意,整个计数、溢出后去执行中断服务程序,都是单片机系统在后台自动完成的,不需要人工干预!4、定时器的定时时间,应该是(终点值-初始值)x机器周期。
对于工作在方式1和12MHz时钟的单片机,最大的计时时间是(65535-0)x1uS=65.535ms。
这个时间也是一般的51单片机定时器能够定时的最大定时时间,如果需要更长的定时时间,则一般可累加多定时几次得到,比如需要1秒的定时时间,则可让系统定时50ms,循环20次定时就可以得到1s的定时时间。
5、定时器定时得到的时间,由于是系统后台自动进行计数得到的,不受主程序中运行其他程序的影响,所以相当精确;6、使用定时器,必须先用TMOD寄存器设定T0/T1的工作方式,一般设定在方式1的情况比较多,所以可以这样设定:TMOD=0x01(仅设T0为方式1,即16位)、TMOD=0x10(仅设T1为方式1,即16位)、TMOD=0x11(设T0和T1为方式1,即都为16位)。
7、使用定时器,必须根据需要的定时时间,装载相应的初始值,而且在中断服务程序中,很多情况下得重新装载初始值,否则系统会从零开始计数而引起定时失败;8、要使用定时器前,还必须打开总中断和相应的定时中断,并启动之:EA=1(开总中断)、ET0=1(开定时器0中断)、TR0=1(启动定时器0)、ET1=1(开定时器1中断)、TR1=1(启动定时器1);9、注意中断服务程序尽可能短小精干,不要让它完成太多任务,尤其尽量避免出现长延时,以提高系统对其他事件的响应灵敏度.//定时器基本例程-1(未使用定时器,一个灯每隔500ms亮灭一次)//这是个特意安排的例程,以便与下面的例程2进行对比#include <reg52.h>sbit led=P2^7;void delay_ms(unsigned int xms); //ms级延时子程序//=================================================void main(){led=1; //上电初始化,led灯不亮while(1){led=!led;delay_ms(500);}}//=================================================void delay_ms(unsigned int xms) //ms级延时子程序{ unsigned int x,y;for(x=xms;x>0;x--)for(y=130;y>0;y--);}//-------------------------------------------------//定时器基本例程-2(使用定时器,一个灯每隔500ms亮灭一次)#include <reg52.h>sbit led=P2^7;unsigned char num;void delay_ms(unsigned int xms); //ms级延时子程序//=================================================void main(){led=1; //上电初始化,led灯不亮TMOD=0x01; //设定定时器0为工作方式1TH0=(65536-50000)/256; //装载初始值,12MHZ晶振50ms数为50000TL0=(65536-50000)%256; //EA=1; //开总中断ET0=1; //开定时器0中断TR0=1; //启动定时器0while(1){delay_ms(8000);}}//=================================================void delay_ms(unsigned int xms) //ms级延时子程序{ unsigned int x,y;for(x=xms;x>0;x--)for(y=130;y>0;y--);}//-------------------------------------------------void led_flash() interrupt 1 //使用了定时中断0的led闪烁子函数{ TH0=(65536-50000)/256; //装载初始值,12MHZ晶振50ms数为50000 TL0=(65536-50000)%256; //num++;if(num==10){num=0;led=!led;}}////定时器基本例程-3//(使用定时器T1,单片机整个口接的8个灯每隔500ms亮灭一次)#include <reg52.h>#define led_port P0 //宏定义,具体的端口尽量不要出现在主函数和主函数中unsigned char num;void delay_ms(unsigned int xms); //ms级延时子程序//=================================================void main(){led_port=0xff; //上电初始化,所有led灯不亮TMOD=0x10; //设定定时器1为工作方式1(16位方式)TH1=(65536-50000)/256; //装载初始值,12MHZ晶振50ms数为50000TL1=(65536-50000)%256; //EA=1; //开总中断ET1=1; //开定时器1中断TR1=1; //启动定时器1while(1){delay_ms(8000); //这句表明定时中断的运行是在系统后台自动运行的,不需要主函数“操心”}}//=================================================void delay_ms(unsigned int xms) //ms级延时子程序{ unsigned int x,y;for(x=xms;x>0;x--)for(y=130;y>0;y--);}//-------------------------------------------------void led_flash() interrupt 3 //使用了定时中断1的8灯闪烁子函数{ TH1=(65536-50000)/256; //装载初始值,12MHZ晶振50ms数为50000TL1=(65536-50000)%256; //num++; //计数if(num==10) //计够10次,时间就是10x50ms=500ms{num=0; //清零,以便进行下一次500ms的10次计数led_port=~led_port; //整个口接的led灯亮灭状态翻转}}//-------------------------------------------------//定时器基本例程-4//(同时使用定时器T0和定时器T1,单片机某个口的灯和某个口接的8个灯每隔500ms亮灭一次)#include <reg52.h>sbit led=P2^7;#define led_port P0 //宏定义,具体的端口尽量不要出现在主函数和主函数中unsigned char num_0,num_1;void delay_ms(unsigned int xms); //ms级延时子程序//=================================================void main(){led=1; //上电初始化,led灯不亮led_port=0xff; //上电初始化,该口所有led灯不亮TMOD=0x11; //设定定时器0和定时器1都为工作方式1(16位方式)TH0=(65536-50000)/256; //装载初始值,12MHZ晶振50ms数为50000TL0=(65536-50000)%256; //TH1=(65536-50000)/256; //装载初始值,12MHZ晶振50ms数为50000TL1=(65536-50000)%256; //EA=1; //开总中断ET0=1; //开定时器0中断TR0=1; //启动定时器0ET1=1; //开定时器1中断TR1=1; //启动定时器1while(1){delay_ms(8000); //这句表明定时中断的运行是在系统后台自动运行的,不需要主函数“操心”}}//=================================================void delay_ms(unsigned int xms) //ms级延时子程序{ unsigned int x,y;for(x=xms;x>0;x--)for(y=130;y>0;y--);}//-------------------------------------------------void led_flash() interrupt 1 //使用了定时中断0的led闪烁子函数{ TH0=(65536-50000)/256; //装载初始值,12MHZ晶振50ms数为50000TL0=(65536-50000)%256; //num_0++; //计数if(num_0==10) //计够10次,时间就是10x50ms=500ms{num_0=0; //清零,以便进行下一次500ms的10次计数led=!led; //led灯亮灭状态翻转}}//-------------------------------------------------void led_all_flash() interrupt 3 //使用了定时中断1的8灯闪烁子函数{ TH1=(65536-50000)/256; //装载初始值,12MHZ晶振50ms数为50000TL1=(65536-50000)%256; //num_1++; //计数if(num_1==10) //计够10次,时间就是10x50ms=500ms{num_1=0; //清零,以便进行下一次500ms的10次计数led_port=~led_port; //整个口接的led灯亮灭状态翻转}}//-------------------------------------------------//定时器基本例程-5//设定定时器T0工作在方式1的计数应用状态,//单片机T0口(P3.4)接一个按键充当外部脉冲源,//系统对进来的脉冲(每按一次键得一脉冲)进行计数,//计数的结果用接在单片机P0口的8个LED灯表示出来//(大家也可以改成用1602LCD来显示,这样更直观)//广西民大物电学院李映超2010年4月14日#include <reg52.h>#define led_port P0 //宏定义,具体的端口尽量不要出现在主函数和主函数中//=================================================void main(){TMOD=0x05; //设定定时器0为工作方式1、计数器TH0=0; //清零TL0=250; //TR0=1; //启动定时器0进行计数while(1){led_port=TL0; //将计数结果送去显示(用8个LED灯显示),//这里仅显示16位计数器的低8位}}定时器0仍旧工作在计数器状态,增加定时器1工作在定时状态,得到1s的定时时间,定时时间到后,将定时器0计数得到的脉冲数去显示,则这个脉冲数就是所输入的外部信号的频率,从而构成一个简单而准确的频率计!!不过,这个简单的“频率计”能够计量的信号频率(脉冲数),受单片机中断响应速度的影响,一般只能达到单片机系统时钟晶振的1/24,所以要能够测量更高的频率,必须使用前置分频器,对更高频率的待测输入信号进行预分频!。
51单片机定时、计数器介绍一采用11.0592M 的晶振,每接收一个输入脉冲的时间约为1.085μs。
采用12M 的晶振,每接收一个输入脉冲的时间为1μs。
STC89C52 内有三个定时/ 计数器, 分别为T0、T1 和T2。
其中T0、T1 工作方式一样,T2 的工作方式稍有区别。
TMOD(见表1)、TCON(见表3)与定时器T0、定时器T1 间通过内部总线及逻辑电路连接,TMOD 用于设置定时器的工作方式,TCON 用于控制定时器的启动、停止,标志定时器的溢出和中断情况。
当设置了定时器的工作方式并启动定时器工作后,定时器就按被设定的工作方式独立工作,不再占用CPU 的操作时间,只有在计数器计满溢出时才可能中断CPU 当前的操作。
表1 TMOD寄存器表中各位(从左至右为从高位到低位)含义如下。
TMOD 的低4 位为定时器0 的方式字段,高4位为定时器1 的方式字段,它们的含义完全相同。
M1 和M0 :工作方式控制位,其定义如表2 所示( 其中i=0,1)。
表2 定时器工作方式控制位:功能选择位。
=0 时,设置为定时器工作方式;=1 时,设置为计数器工作方式。
GAte :门控位。
当GATE=0 时,软件控制位TR0 或TR1 置1 即可启动定时器。
TR0 或TR1 置0 即可停止定时器工作;当GATE=1 时,软件控制位TR0 或TR1 需置1,同时还需(P3.2) 或(P3.3) 为高电平方可启动定时器,即允许外部中断启动、定时器。
值得注意的是TMOD 寄存器不能位寻址,只能用字节指令设置高4 位定义定时器1 上的工作方式或低4 位定义定时器0 的工作方式。
而且在复位时,TMOD 所有位均置0。
表3 TCON寄存器表中各位(从左至右为从高位到低位)含义如下。
(1)TFl :定时器1 溢出标志位。
当定时器1 计满数产生溢出时,由硬件自动置TF1=1,向CPU发出定时器1 的中断请求,在中断允许时响应。