8051单片机内部有两个定时/计数器T0及T1,具有定时和计数两种功能。T0及T1在计数过程中不需要CPU参与,也不影响CPU的其他工作。当计数溢出后,定时/计数器给出中断信号,申请CPU停止当前的工作,去处理预先设定的中断事件。
定时器工作模式:对内部时钟信号计数。由于时钟频率是定值,所以可根据计数值计算出定时时间。
计数器工作模式:是对加在T1(P3.5)引脚上的外部脉冲进行计数。
计数器用于统计从TO(P3.4)和Tl(P3.5)两个引脚输入脉冲的负跳变数量。负跳变是指前一个机器周期采样为高电平,后一个机器周期为低电平。每输入一个脉冲负跳变,计数器加1。
输入脉冲的高电平与低电平至少应保持一个机器周期时间,以确保正确采样,因此输入脉冲的频率最高为单片机内部脉冲频率的一半。如果内部脉冲频率为1 MHZ,则最高计数频率为0.5 MHz。
定时功能是单片机通过对内部机器脉冲信号计数实现的,计数值乘以机器周期就是相应的时间。例如,如果单片机采用12 MHz的晶振,则机器内部脉冲频率为1 MHz,则机器周期为1us,若共计数1000,则用时为1ms时间。
工作方式寄存器TMOD
工作方式寄存器TMOD用于控制定时/计数器的工作方式和工作模式,长度为一个字节,只能按字节整体赋值。
(1)Ml和M0用于设置TO(T1)的工作方式。
(2)C/T用于设置TRO(TR1)是工作于计数器或定时器模式。
C/T—计数器模式和定时器模式选择位
0:定时器工作模式,对单片机的晶体振荡器12分频后的脉冲进行计数。
1:计数器工作模式,计数器对外部输入引脚T0(P3.4)或T1(P3.5)的外部脉冲(负跳变)计数。
(3)GATE(门控制位)用于设置TO(T1)的启动方式。
GATE—门控位。
0:仅由运行控制位TRx(x =0,1)来控制定时器/计数器运行。
1:用外中断引脚INT0(或INT1 )上的电平与运行控制位TRx共同来控制定时器/计数器运行。
例:设定时器1为定时工作方式,按方式2工作,定时器0为计数方式,按方式1工作,均由程序单独控制启动和停止,请给出TMOD控制字。
解:
定时器1做定时器使用则D6=0;按方式2工作则D5=1,D4=0; 由程序单独控制启停则D7=0。 定时器0做计数器使用则D2=1;按方式1工作则D0=0,D1=1; 由程序单独控制启停则D3=0。 因此命令字TMOD的值应为00100101B,即25H。
定时器控制寄存器TCON (Timer controller)
TCON也是8位寄存器,与TMOD不同的是它可按位单独赋值,其各位的意义见下表。
1、TF1、TF0—计数溢出标志位。
当计数器计数溢出时,该位置“1”。
使用中断方式时,此位作为中断请求标志位,标志位由硬件自动清“0”。使用查询方式时,应注意查询有效后使用软件及时将该位清“0”。
2、TR1、TR0—计数运行控制位。
TR1位(或TR0位)=1,启动定时器/计数器工作的必要条件。
TR1位(或TR0位)=0,停止定时器/计数器工作。
方式0是13位的定时/计数器,它由TL的低5位和TH的8位构成。
方式1是16位的定时/计数器,由TH的8位和TL的8位构成。方式0和方式1的工作原理基本相同。
方式0和方式1的特点:
T1启动后,在TL1和TH1中存储的计数初值基础上进行加“1”计数,直至溢出。溢出时T1寄存器被清零,TF1被置位,并申请中断。此后,若T1重新启动,则从零重新开始计数。若希望T1从某一数值开始计数,则应给计数器赋初值。
若所需计数长度为N,则计数初值X=2M-N(1≤N≤2M),其中当工作于方式0时,M=13,当工作于方式1时,M=16。在为计数器赋初值时,应将初值拆成高低两部分字节,分别送入TL1和TH1。
实例:欲采用8051单片机控制8个LED同时以1s为周期闪烁,设计电路原理图并编写程序。
设置定时/计数器的过程:
1)先初始化工作方式寄存器TMOD
2)为定时/计数器赋初值
3)通过控制寄存器TCON中的TRO或TRl实现启动或停止。
#include
// 将8051单片机头文件包含到文件中main(void) {unsignedcharcounter;//设置无符号字符型变量,存储定时器中断次数。TMOD=0x01;//设T0为定时模式,由TR0控制启动和停止,且工作于方式1TH0=(65536-46083)/256;//初始化T0的高8位TL0=(65536-46083)%256;//初始化T0的低8位TF0=0;//初始化定时器溢出标志P0=0xff;//关闭LEDcounter=0;//从0开始计数TR0=1;//启动定时器0while(1) {while(TF0==1)//如果定时器溢出{ counter++;//计时次数加1if(counter==20)//计时时间达到1s{ P0=~P0;// P0所有位取反,使LED闪烁counter=0;//重新从0开始计数} TH0=(65536-46083)/256;//重新初始化T0的高8位TL0=(65536-46083)%256;//重新初始化T0的低8位TF0=0;//重新初始化定时器溢出标志} } }
方式0和方式1的特点:
T1启动后,在TL1和TH1中存储的计数初值基础上进行加“1”计数,直至溢出。溢出时T1寄存器被清零,TF1被置位,并申请中断。此后,若T1重新启动,则从零重新开始计数。若希望T1从某一数值开始计数,则应给计数器赋初值。
若所需计数长度为N,则计数初值X=2M-N(1≤N≤2M),其中当工作于方式0时,M=13,当工作于方式1时,M=16。在为计数器赋初值时,应将初值拆成高低两部分字节,分别送入TL1和TH1。
实例:欲采用8051单片机控制8个LED同时以1s为周期闪烁,设计电路原理图并编写程序。
设置定时/计数器的过程:
1)先初始化工作方式寄存器TMOD
2)为定时/计数器赋初值
3)通过控制寄存器TCON中的TRO或TRl实现启动或停止。
#include
// 将8051单片机头文件包含到文件中main(void) {unsignedcharcounter;//设置无符号字符型变量,存储定时器中断次数。TMOD=0x01;//设T0为定时模式,由TR0控制启动和停止,且工作于方式1TH0=(65536-46083)/256;//初始化T0的高8位TL0=(65536-46083)%256;//初始化T0的低8位TF0=0;//初始化定时器溢出标志P0=0xff;//关闭LEDcounter=0;//从0开始计数TR0=1;//启动定时器0while(1) {while(TF0==1)//如果定时器溢出{ counter++;//计时次数加1if(counter==20)//计时时间达到1s{ P0=~P0;// P0所有位取反,使LED闪烁counter=0;//重新从0开始计数} TH0=(65536-46083)/256;//重新初始化T0的高8位TL0=(65536-46083)%256;//重新初始化T0的低8位TF0=0;//重新初始化定时器溢出标志} }
方式2的特点是能自动加载计数初值。16位计数器被分为两部分,以TL0作为计数器,以TH0作为存储器。初始化时把计数初值分别加载至TL0和TH0中,当计数溢出时,由存储器TH0自动给计数器TL0加载计数初值。若所需计数长度为N,则计数初值X=28-N(1≤N≤256)。
实例:下图是产品包装生产线的计数系统,每个产品经过计数装置时由机械杆碰合按键S1一次。当第一次计满一包(5个)则D1亮,计满第二包则D2亮…,计满第八包则D1~D8全亮,八包包装成一箱,此后重复以上过程。编写程序实现此功能。
#include
// 包含51单片机寄存器定义的头文件unsignedcharcounter;//计数初值main(void) { TMOD=0x60;//使用T1的工作方式2TH1=256-5;// T1的高8位赋初值TL1=256-5;// T1的低8位赋初值counter=0; TR1=1;//启动T1while(1) {while(TF1==1)//如果计满{ TF1=0;//计数器溢出后,将TF1清0counter++;//计数加1switch(counter)//检查中断计数值{case1: P0=0xfe;break;//则第1个灯亮case2: P0=0xfd;break;//第2个灯亮case3: P0=0xfb;break;//第3个灯亮case4: P0=0xf7;break;//第4个灯亮case5: P0=0xef;break;//第5个灯亮case6: P0=0xdf;break;//第6个灯亮case7: P0=0xbf;break;//第7个灯亮case8: P0=0x00; counter=0;break;//8个灯全亮} } } }
TO被拆成两个独立的8位计数器TLO和THO,TL0独占T0的各控制位、引脚和中断源,既可以用作定时器也可作计数器。TH0只能作为定时器使用,且需要占用T1的控制位TR1和TF1实现启停和中断。
两个定时/计数器的使用方法与方式0或1相似。工作方式3只适用于T0,不适用于T1。若将T1强行设置为模式3,将使T1立即停止计时或计数,相当于使TR1=0。
当T0作方式3时,T1仍可以设置为除工作方式3外的其它工作方式,但由于它的TR1和TF1已被T0占用,因此无法按正常计时/计数器工作,常用于串行通信时的波特率发生器,以控制传输数据的速度。
单片机的P0口接了8个发光二极管,要求使用定时器T0中断实现流水灯操作,流水频率为每0.5秒钟更替一次(假设单片机外接11.0592MHz的晶振)。
#include
unsignedcharcnt=0;//用于中断次数计数unsignedcharled =0xfe;//初始化流水灯intmain(void){ TMOD=0x01;//16位定时方式TH0=(65536-46083)/256;//初始化T0的高8位TL0=(65536-46083)%256;//初始化T0的低8位EA=1; ET0=1;//开中断TR0=1;//启动T0工作while(1); }voidT0_int(void)interrupt 1{ cnt++;if( cnt==10)//0.5秒钟的时间到了{ cnt=0;//清除次数统计led =(led <<1)|1;//更新流水灯数据if(led ==0xff) { led =0xfe; } P0=led;//显示流水灯} TH0=(65536-46083)/256;//初始化T0的高8位TL0=(65536-46083)%256;//初始化T0的低8位}
全部0条评论
快来发表一下你的评论吧 !