一、外部中断
1.中断是为使单片机具有对外部或内部随机发生的事件实时处理而设置的。
2.中断结构(从左到右 :中断请求方式-中断打开-查看中断优先级(默认即可,单个中断无需设置))
3.中断寄存器
4.中断优先寄存器
5.中断号
51单片机具有外部中断INT0,INT0两个外部中断源,T0,T1两个定时/计数中断源,还有一个串口中断源,
当需要使用INT0中断时,要满足①有中断请求②中断允许打开③配置相关寄存器位
当要使用INT0中断时,首先设置中断请求触发方式,即设置TCON寄存器中IT0位值。当IT0位0时,为低电平触发,即相应引脚设置为低电平时发出中断请求,当IT0为1时,设置下降沿触发,即高电平变成低电平的时候触发中断,此时中断源发出中断请求。TCON寄存器的IE0位是中断状态标志位,当IT0设置触发方式后,IE0被自动设置为1。到此中断请求设置完成,此时去设置中断允许控制寄存器,IE寄存器的EX0为中断INT0的中断允许位,EA是所有中断的总允许为位,当EX0和EA设置为1时,中断(功能)打开,中断配置完毕。
中断结构图中的IP列为中断优先序列,当同时多个中断触发时,会按照默认优先级进行中断请求处理,默认优先级依次为INT0->T0->INT1->T1->TI/RI(串口中断),中断优先级可更改。
示例代码:
以STC89C52开发板为例,实现按键按下进入中断程序,在中断程序中设置LED1状态翻转。
实验名称:外部中断0实验
实验现象:下载程序后,当按下K3键可控制D1指示灯亮灭
#include "reg52.h"
typedef unsigned int u16; //对系统默认数据类型进行重定义
typedef unsigned char u8;
//定义LED1管脚
sbit LED1=P2^0;
//定义独立按键K3控制脚
sbit KEY3=P3^2;
void delay_10us(u16 ten_us)
{
while(ten_us--);
}
void exti0_init(void)
{
IT0=1;//跳变沿触发方式(下降沿)
EX0=1;//打开INT0的中断允许
EA=1;//打开总中断
}
void main()
{
exti0_init();//外部中断0配置
while(1)
{
}
}
void exti0() interrupt 0 //外部中断0中断函数
{
delay_10us(1000);//消抖 防止外界物理干扰
if(KEY3==0)//再次判断K3键是否按下
LED1=!LED1;//LED1状态翻转
}
中断号依中断源优先级从0开始,中断程序必须设置对应中断号,此时INT0中断源优先级最高,故中断号为0。若使用INT1中断,只需将IT0 EX0 改成IT1 EX1即可,中断号为2
二、定时/计数中断
上面讲过,51有T0、T1两个中断源,该中断源可实现定时或者计数中断功能(比如可以用定时模式设置led每1秒闪烁1次)。
该中断有两种模式:定时和计数。定时模式由硬件内部的脉冲进行定时,计数模式由外部电平进行计数,以stc89c52为例,内置12MHZ晶振,一个震荡周期为1/12(周期与频率成反比),一个机器周期为1微秒(一个机器周期=12个震荡周期),内部每过一个机器周期,都会有一个脉冲信号发送给定时器0(此时假设使用T0中断源),此时T0加1,
TH0为T0高8位,TL0为T0低八位,也就是说,最大可以定时或者计数到2的八次方65536,此时TCON寄存器的中断状态位TF0置1表示计数溢出。
1.定时/计数内部结构图
2.中断结构
3.工作方式寄存器TMOD
4.方式1结构
以使用T0中断为例,使用步骤①对TMOD赋值,确定T0工作方式(定时还是计数)②根据需要将初值写入TH0,TL0
③使用中断 打开中断④启动定时/计数器
以T0中断源举例,设置模式为定时,实现每1sled灯闪烁一次
#include "reg52.h"
typedef unsigned int u16;
typedef unsigned char u8;
sbit LED1=P2^0;
void time0_init(void)
{
TMOD|=0X01;// 此时TOMD为0000 0001 低四位为T0 高四位为T1,M1M0=01 选用方式1,C/~T(非T不会打),置1为计数,0为定时,GATE置0表明定时中断不受INT0 INT1等外部中断影响
TH0=0XFC; // 定时器高八位
TL0=0X18; // 低四位 此时初值为64536
ET0=1;// IE中断允许寄存器打开
EA=1;// 总中断打开
TR0=1;//开启定时0中断
}
void main()
{
time0_init();
while(1)
{
}
}
void time0() interrupt 1
{
static u16 i=0;设置静态变量
TH0=0XFC; // 每次进入中断内部,将初值设为64536
TL0=0X18;
i++; //每次进入中断 i++,i记录进入次数
if(i==1000) //每当进入1000次中断,一次是1毫秒 1000次正好1秒
{
i=0; //之后i重新从0次开始计
LED1=!LED1; // led翻转
}
}
因为一次机器周期是1微秒,从64536到65536正好1000微秒也就是1毫秒,数到65536计数溢出进入一次中断,也就是每次中断为1毫秒。i记录中断次数,1000次中断又正好是1000毫秒,也就是1秒。