8051定时器的使用
扫描二维码
随时随地手机看文章
8051定时器/计数器介绍:
8051有两个定时器/计数器,而8052则有三个定时器/计数器。定时器、计数器本质都是一样的,定时器通过对内部脉冲进行计数来达到计时的目的,而计数器是对外部输入脉冲进行计数,所以它们的本质都是一样的。
定时器/计数器的工作模式:
定时器/计数器0有四种工作模式,而定时器/计数器1只有三种工作模式,工作模式由TMOD寄存器的M1和M0位控制。
M1M0工作模式00013位定时器/计数器。01116位定时器/计数器。1028位自动重装定时器/计数器。113模式3只能用于定时器/计数器0,T0被分为两个8位定时器/计数器,TL0可以作为定时器/计数器来使用,由T0的控制位来控制,而TH0只能用于计数器,有T1的控制位来控制。GATEGATE为0时,由TRx(软件控制)来控制定时器/计数器的启动和停止,当GATE为1时,定时器/计数器的启动由TRx和引脚INTx共同来控制(硬件来控制,仅当TRx=1并且引脚INTx输入高电平时才工作)。C/T定时器/计数器选择位,0工作在定时器模式,1工作在计数器模式。TCON寄存器:TFx定时器/计数器溢出标志位,当定时器/计数器计数溢出时,由硬件自动置1,在编写程序时可以通过检测该位来判断是否达到定时时间,需要通过软件来清零。工作在中断方式下不需要清零,因为在执行中断服务程序时会自动给我们清零。TRx定时器/计数器运行控制位。IE寄存器:ETx定时器/计数器中断使能位。EA全局中断使能位。
THx、TLx初值计算:
假设8051外接12MHz的晶振,由于8051的机器周期是时钟周期的12分频,所以8051的机器周期为1MHz,那么计数一次的时间刚好为1us,如果定时器工作在模式0下,那么可以最长计时为8192us,工作模式1可以最长计时为65536us。那么假设8051工作在模式1下,定时1ms,那么THx、TLx的初值应该为多少呢?如果定时1ms,也就意味着需要计数1000次,那么初值就应该为65536-1000=64536,也就是THx=0xFC,TLx=0x18。
根据上面可以总结出如下公式:
定时时间=(最大计数值-计数器初值)*机器周期=(最大计数值-计数器初值)*(12000000/晶振频率(Hz))(us);
计数器初值=(最大计数值-定时时间*(晶振频率(Hz)/12000000));
套用这个公式,初值=(65536-1000*(12000000/12000000))=64536=0xFC18,那么TH就应该为0xFC,TL为0x18。
整个程序如下:
/*timer.c*/
#include
#defineOSC_FREQ12000000UL
#defineTIMER_MODE00x00
#defineTIMER_MODE10x01
#defineTIMER_MODE20x02
#defineTIMER_MODE30x03
voidtimer0_init(void)
{
TMOD&=0xF0;
TMOD|=TIMER_MODE1;/*Timer0workon16-bittimermode*/
TH0=(65536-1000*(OSC_FREQ/12000000))>>8;
TL0=(65536-1000*(OSC_FREQ/12000000))&0x00FF;
TR0=1;/*Turnontimer0*/
}
voiddelayms(unsignedintn)
{
while(n--){
while(!TF0);
TF0=0;
TH0=(65536-1000*(OSC_FREQ/12000000))>>8;
TL0=(65536-1000*(OSC_FREQ/12000000))&0x00FF;
}
}
/*timer.h*/
#ifndef__TIMER_H
#define__TIMER_H
externvoidtimer0_init(void);
externvoiddelayms(unsignedintn);
#endif/*__TIMER_H*/
/*main.c*/
#include
#include"timer.h"
#defineled1P2_0
voidmain(void)
{
timer0_init();
while(1){
led1=0;
delayms(1000);
led1=1;
delayms(1000);
}
}