定时器中断
定时器中断我们使用定时器0来做,定时器0中断用到的寄存器为TF0和TR0 。TF0是溢出中断标志,我们默认给0就好了,TR0是定时器运行位,置1时启动计时。
TR0 = 1;
TF0 = 0;
除此之外,我们还要配置TMOD寄存器。
因为我们采用的是定时器0,然后要配成16位TL0、TH0全用的模式,直接给0x01就好了。
TMOD = 0x01;
定时10ms
定时器0用时间定时的话,我们需要使用到TL0和TH0这两个寄存器。因为,我们TMOD配置的是16位全用的模式。所以,定时器0可以计数2^16次,也就是65536次。根据我这块51单片机的晶振来计算,定时器计数1次所要花费的时间为1.085us。溢出一次花的时间为65536 * 1.085,大约是71ms。
TL0和TH0这两个寄存器默认是从0开始计数的,我们可以配置他从61ms开始计数,这样我们就能够定义出10ms了。
TH0 = 0xDC;
TL0 = 0x00;
0xDC00转换为10进制是56320,65536 - 56320 = 9216,9216 * 1.085大约为10ms。
开启中断寄存器
我们使用的是定时器0,需要用到的中断寄存器为ET0和EA。由图可知,ET0是定时器0的中断寄存器,EA是总的中断寄存器。我们全部置1即可。
ET0 = 1;
EA = 1;
中断处理函数
这里一共有8个中断函数,函数名其实都无所谓,主要还是需要主要函数名后面的interrupt 这个关键字。我们使用的是定时器0,所以用的是interrupt 1。
int cnt = 0; //定义一个变量来计数
void Time0Handler() interrupt 1
{
cnt++;
TL0 = 0x00; //每次爆表都初始化为10ms
TH0 = 0xDC;
if(cnt == 100) //当爆表100次时,为1秒
{
cnt = 0; //清空计数
led2 = !led2; //led2状态自动变化
}
}
中断函数我们不需要在main函数内进行调用,硬件会自动调用。这里的逻辑是,led2每一秒翻转一次状态,由亮到灭,或者由灭到亮。
总的函数实现
#include "reg52.h"
sbit led1 = P3^7;
sbit led2 = P3^6;
int cnt = 0;
void Delay300ms() //@11.0592MHz
{
unsigned char i, j, k;
//_nop_();
//_nop_();
i = 13;
j = 156;
k = 83;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void Time0Init()
{
TMOD = 0x01;
TL0 = 0x00;
TH0 = 0xDC;
TR0 = 1;
TF0 = 0;
ET0 = 1;
EA = 1;
}
void main()
{
led2 = 1;
led1 = 1;
Time0Init();
while(1)
{
led1 = !led1;
Delay300ms();
}
}
void Time0Handler() interrupt 1
{
cnt++;
TL0 = 0x00;
TH0 = 0xDC;
if(cnt == 100)
{
cnt = 0;
led2 = !led2;
}
}
在mian函数内,我又设计了一个led1,把它放在while里每个300ms翻转一次状态。通常来说,当主函数执行while里面的代码时,他不会进行其他操作,然而中断的作用就是能够去打断你while的代码,先去执行中断函数的代码,执行以后再来执行while里面的代码。