51单片机有两个16位定时器,今天复习了一下使用方法,发现当初刚开始学习51单片机时并没有记录,特此今天补上这篇博客。
下面是定时器的总览示意图,看到这个图就能想到定时器怎么设置,怎么开始工作。
第一步:设置特殊功能寄存器 TMOD,配置好工作模式;
第二步:设置计数寄存器 TH0 和 TL0 的初值;
先来学会计算如何用定时器定时时间。我们的晶振是 11.0592M,时钟周期就是 1/11059200,机器周期就是12/11059200,我们假如要定时 20ms,就是 0.02秒,要经过 x 个机器周期得到 0.02 秒,我们来算一下:x*12/11059200=0.02,得到 x= 18432。那么我们现在 16 位的定时器溢出值是 65536,我们可以这样,先给 TH0 和 TL0 一个初值,让他们经过18432 个机器周期后刚好溢出,溢出后我们可以通过检测 TF0 位得知,就刚好是 0.02 秒。这个初值 y = 65536 - 18432 = 47104,转成 16 进制就是 0xB800,那么就是 TH0 = 0xB8,TL0 = 0x00。
第三步:设置 TCON,通过打开 TR0 位来让定时器开始计数。
第四步:判断 TCON 寄存器的 TF0 位,监测定时器溢出情况
同时这个TF0位也可以不检测,直接写个中断函数,因为数据溢出后会产生中断,进入中断函数,执行其中的代码,定时器0的中断入口是1,定时器1的中断入口是3.
#include<reg52.h>#define uc unsigned charuc s[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};uc count=0, num=0;void init_time0(); void display();void main() {init_time0();while(1){display();} }void display() {P2=s[num]; }void init_time0() {TMOD=0x01;TH0=(65536-50000)/256;TL0=(65536-50000)%256;TR0=1;ET0=1;EA=1; }void time0_isr()interrupt 1 {TH0=(65536-50000)/256;TL0=(65536-50000)%256;count++;if(count==20){count=0;num++;if(num==10)num=0;} }
此程序可以每隔1秒钟使下方的模拟图中的数码管加1,到9后归0,在下面的程序写如何加入外部中断INT0来控制定时器0的开启, INT1可以开启定时器1。 这个是固定的,我没有找到交叉启动的方法。
程序如下面这样,上图中的按键按下后定时器开始工作,开始计时,每隔1秒钟数码管数字加1.
#include<reg52.h>#define uc unsigned charuc s[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};uc count=0, num=0;void init_time0();
void display();void main()
{P3=0x00; // 主要是为了把外部中断的两个口给拉低了,因为只有高电平可以开启定时器。init_time0();while(1){display();}
}void display()
{P2=s[num];
}void init_time0()
{TMOD=0x09; // 这里改成09是把低4位中的gate位置1了,所以就是0x09(0000 1001)TH0=(65536-50000)/256;TL0=(65536-50000)%256;TR0=1;ET0=1;EA=1;
}void time0_isr()interrupt 1
{TH0=(65536-50000)/256;TL0=(65536-50000)%256;count++;if(count==20){count=0;num++;if(num==10)num=0;}
}