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 char uc 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 char
uc 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;
}
}