一、中断概念
中断是为使单片机具有对外部或者内部随机发生的事件实时处理而设置的。
把自己想象成单片机的CPU,你正在洗衣服,但是突然快递小哥给你打电话让你去拿快递,于是你停下洗衣服去拿快递了。快递小哥的电话就是中断信号,告诉你有其他的事情需要先去做,然后你去拿快递就相当于中断之后要去处理的事情。
51单片机有五个中断源
INT0——外部中断0
INT1——外部中断1
T0——定时器/计数器0中断
T1——定时器/计数器1中断
TI/RI——串行口中断
二、使用中断的过程(下面以定时器0、工作方式1为例)
定时器0选择工作方式1
D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
---|---|---|---|---|---|---|---|
GATE | C/T | M1 | M0 | GATE | C/T | M1 | M0 |
这是定时器/计数器工作方式寄存器TMOD,不能位寻址(只能一次操作一个字节,八位,不能单独操控某一位)。
TMOD高四位用于设置定时器/计数器1,低四位用于设置定时器/计数器0;
GATE是们控制位,当GATE=0,定时器/计数器启动与停止仅收TCON寄存器中的TRX(X=0,1)控制;我们对TMOD操作时,直接让GATE这一位为0。
CT位为1时选择计数器模式,为0时选择定时器模式。
M1,M0用于选择工作方式,M0=1,M1=0时,选择的是方式一。
综上,在编程的时候这样写(八位数的二进制换成两位数的16进制,0000 0001 ——0x01)
TMOD=0x10;
2. 给定时器0装初值
上面选择的工作方式1是16位定时器。对于T0来说,TL0寄存器作为低八位,TH0作为高八位,组成16位加一计数器。
当开始计数的时候,低八位计数计满,低八位全部归零,向高八位进一位。当高八位计数计满时,全16位归零,进入中断函数,执行相关操作。
之所以要给定时器装初值,是为了计整数,方便计算使用。
每50ms进入一次中断函数的初值为:
TH0=(65536-45872)/256; TL0=(65536-45872)%256;
3.打开总中断,开启定时器0中断,启动定时器0
首先涉及到中断允许寄存器IE(可以进行位寻址,对某一位操作),全局中断允许位EA,定时器T0中断允许位ET0便在其中。
打开总中断,即EA=1;
开起定时器0中断,即ET0=1;
启动定时器涉及到定时器/计数器控制寄存器TCON(可进行位寻址),定时器0运行控制位TR0便在其中。
启动定时器0,即TR0=1;(在上述GATE=0的前提下)
4.中断服务程序写法
void 函数名() interrupt 中断号
{
中断服务程序内容,中断号百度可查
}
函数名不能与关键字重复,
定时器0,工作方式1为例
void T0_time() interrupt 1
{
TH0=(65536-45872)/256;
TL0=(65536-45872)%256; //重装初值,保证每次进入中断函数都是50ms
//此处可添加需要的程序
}
#include sbit led=P1^0; unsigned char num; void main() { TMOD=0x01; //设置定时器0为工作方式1 TH0=(65536-45872)/256; TL0=(65536-45872)%256; //装初值 EA=1;//开总中断 ET0=1;//开启定时器0中断 TR0=1;//启动定时器0 while(1);//程序在这里等待中断发生 } void T0_time() interrupt 1 { TH0=(65536-45872)/256; TL0=(65536-45872)%256; //进入中断程序说明计数计满,TL0,TH0归零,需要装初值 num++; if(num==20) //每计够20次可以进入一次if语句,改变一次LED灯的状态 { //进入一次需要50ms,进入20次就经历了1s num=0; led=~led; } }