51单片机的定时/计数器是一种可编程部件。它的工作方式、计数初值以及启停操作均应在定时/计数器工作前进行初始化,即向相应的寄存器写入相应的控制字。
标准的51单片机内部有T0和T1两个定时器,与这两个定时器有关的特殊功能寄存器主要由定时值存储寄存器、定时器控制寄存器和定时器模式寄存器。
在使用定时器的时候,需要完成对定时器配置,配置步骤如下:
第一:设置特殊功能寄存器TMOD,配置好工作模式。
第二:设置计数寄存器TH0和TL0的初值。
第三:设置TCON,通过TRX置1来让定时器开始计数。
第四:判断TCON寄存器的TFX位,监测定时器溢出情况
这里TRX和TFX中的X指的是0或者1。
下面程序使用定时器0,工作模式1,实现20ms的定时功能,控制单片机的P1.0输出周期为40ms的方波信号。
1.首先设置特殊功能寄存器TMOD,配置定时器0工作在模式1。TMOD寄存器的各位如下表所示,根据要求,采用定时器0,而高四位是定时器1的控制位,所以TMOD的高四位置0,TMOD的低四位为定时0的控制位。根据要求定时器0工作在定时器模式,所以C/T(T0)位因该是置0,表示工作在定时模式。本定时器启动不受到单片机引脚INT0外部信号的控制,所以GATA(T0)为清零即可。要求定时器0工作在模式1,则M1(T0)位置0,M0(T0)位置1即可。因此通过以上分析,可知TMOD的各位如下TMOD=0B00000001即,TMOD=0X01.
2.设置计数寄存器TH0和TL0的初值,根据定时时间20ms,确定TH0和TL0的初值。单片机的晶振为11.0592M,时钟周期就是1/11059200,机器周期是12/11059200 秒,定时间20ms,就是要经过X个机器周期得到0.02秒,即X* 12/11059200=0.02,得到X=18432.16位定时器的溢出值是65536(因65535加1才是溢出),这样先给TH0和TL0一个初始值,让它们经过18432个机器周期后刚好达到65536溢出,溢出之后TF0置1,通过TF0就可以得知0.02秒时间到。那么初值y=65536-18432=47104,转换为十六进制就是0XB800;即TH0=0XB8;TL0=0X00;
3.设置TCON,通过TR0置1来让定时器开始计数,即通过TR0=1启动定时器。
4.判断TCON寄存器的TF0位,监测定时器溢出情况,TF0为1则定时器溢出,定时时间到,就可以做相应的处理,比如改变P10引脚电平状态实现40ms方波信号。
将上述定时器初始化设置的流程,封装成一个函数如下:
void timer0_init()
{
TMOD=0X01;
TH0=0XB8;
TL0=0X00;
TR0=1;
}
然后在主函数调用timer0_init()函数实现对定时器的初始化。并在主函数中查询定时器是否溢出,溢出说明定时间到,进行响应的处理,main函数如下
void main() //主函数
{
timer0_init();//调用定时器初始化函数
while(1)
{
if(1==TF0)//判断定时器是否溢出
{
TH0=0XB8;//
TL0=0X00;//对于定时器0工作1需要溢出之后,重新装入初始值
P10=~P10;//P10电平状态反转,实现高低电平切换
}
}
}
仿真结果如图所示,一个格子是10ms,一个方波周期是4个格子,正好是40ms。
这是一个定时器最简单的一个例子,通过这个例子掌握定时器的使用方法,稍加修改就可以实现一些功能,比如:赛事活动中使用的秒表、智能定时断电插座、通过对单片机端口引脚上输入的由外部事件产生的“触发脉冲信号”进行计数,从而根据计数结果实现相应的功能控制,比如频率计等。