中断系统
介绍
中断系统的目的是为了使CPU具有对外界紧急事件的实时处理能力。当外界发出紧急事件的请求,可要求CPU暂停当前的工作,转而去处理这个紧急事件,处理完成后,再回到原来被中断的地方,继续原来的工作。通俗来讲就是,相当于假如你在家写作业,然后呢,要到煮饭的时间了,对人来讲,这时候吃饭是紧急的事件,毕竟人是铁,饭是钢,一顿不吃饿得慌,因此,你就不得不停下手头的作业,去完成煮饭吃饭的工作,等吃完后,你又会回到当时被中断作业上,继续完成作业。
其中,请示CPU中断的请求源称中断源。一般存在多个中断源,每个中断源有优先级别。因此可以实现中断嵌套,而51单片机有8个中断,如下图,Int是外部中断,Timer是定时器中断,UART是串口中断
中断系统的结构图如下
结合上图,定时器0和1的中断请求标志位是TF0和TF1。当定时器寄存器THx/TLx(x=0/1)溢出时,溢出标志位TFx(x=0/1)会被置位,定时器中断发生。当执行定时器中断时,TFx(x=0/1)会被硬件清除。
串行口接收中断请求的标志位RI和串行口1发送中断请求标志位TI中的任何一个被置为1后,串行口中断都会发生。
中断寄存器
这51单片机与中断相关的所有寄存器,其中,定时器需要用到的寄存器有两个,分别是TCON和SCON。
TCON的具体说明
SCON的具体说明
定时器
定时器控制寄存
不可位寻址:即此地址只可用十六进制一次性赋值,不能一个一个的去赋值,如:单独的P2_1是无法赋值的。可位寻址就与之相反。
定时器一般用较多的模式是模式0。
上图,如果会看电路图的话,这张图的原理理解起来应该不是什么问题。
用定时器做流水灯
主函数代码:
#include <REGX52.H>
#include "Timer0.h"
#include "Key.h"
#include "Delay.h"
#include <INTRINS.H>
unsigned char KeyNum,LEDMode;
void main()
{
P2=0xFE;
Timer0Init();//中断函数只有在主函数先初始化才可以启动定时器
while(1)
{
KeyNum=Key();
if(KeyNum)
{
if(KeyNum==1)
{
LEDMode++;
if(LEDMode>=2)LEDMode=0;
}
}
}
}
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count;
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
T0Count++;
if(T0Count>=500)
{
T0Count=0;
if(LEDMode==0)
{
P2=_crol_(P2,1);
}
if(LEDMode==1)
{
P2=_cror_(P2,1);
}
}
}
定时器模块的代码:
#include <REGX52.H>
/**
*@brief 定时器0初始化,1毫秒@12.000MHz
*@param 无
*@retval 无
*/
void Timer0Init(void)
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
ET0=1; //允许中断系统的开启
EA=1; //打开中断系统寄存器
PT0=0; //中断的优先级位低级
}
一般,我们习惯与将中断函数放在主函数的页面中,不会放在定时器模块中。
用定时器做简易时钟
在知道定时器的代码怎么写的基础上,我们可以用定时器去做一个简易的时钟,
主函数的代码如下:
#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#include "Timer0.h"
unsigned char Sec,Min,Hour;
void main()
{
LCD_Init();
Timer0Init();
LCD_ShowString(1,1,"Clock");
LCD_ShowString(2,1," : :");
while(1)
{
LCD_ShowNum(2,1,Hour,2);
LCD_ShowNum(2,4,Min,2);
LCD_ShowNum(2,7,Sec,2);
}
}
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count;
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
T0Count++;
if(T0Count>=1000)
{
T0Count=0;
Sec++;
if(Sec>=60)
{
Sec=0;
Min++;
if(Min>=60)
{
Min=0;
Hour++;
if(Hour>=24)
{
Hour=0;
}
}
}
}
}