【嵌入式成长3】STC89C51外部中断|中断原理、寄存器、中断服务函数

一、什么是中断

中断是单片机用来实时处理外部/内部随机事件的重要机制。

通俗理解:CPU正在做A任务,突然来了紧急事件B,CPU暂停A,转去处理B,B处理完毕,回到A任务断点继续执行。

生活类比:你正在洗衣服(主程序while循环),水壶烧开(中断事件),停下洗衣服,关火倒水(中断服务函数),处理完继续回去洗衣服。

轮询按键的痛点

如果主循环内部有长时间延时,例如delay_ms(20000);延时20秒。在延时期间按下按键,程序无法捕捉按键动作,按键信号直接丢失

中断可以解决这个痛点:无论CPU正在执行什么代码,只要中断事件触发,立刻跳转到中断服务函数处理。

二、硬件接线说明(P3.2‑INT0按键)

开发板硬件:

  • INT0 → P3.2,外接独立按键KEY1
  • 按键电路:4.7K上拉,松开:高电平;按下:低电平
  • LED指示灯:P2.7,低电平点亮

实验目标:按下P3.2按键触发外部中断0,翻转LED亮灭状态。

三、STC89C52RC中断源

STC89C5X一共有8个中断请求源:

  1. 外部中断0 INT0(P3.2)
  2. 外部中断1 INT1(P3.3)
  3. 外部中断2 INT2(P4.2)
  4. 外部中断3 INT3(P4.3)
  5. 定时器0中断T0
  6. 定时器1中断T1
  7. 定时器2中断T2
  8. 串口UART中断

分类:

  • 外部中断:外部引脚电平变化触发
  • 定时器中断:单片机内部定时器计数溢出触发
  • 串口中断:串口完成接收/发送一帧数据触发

本章重点讲解外部中断0(P3.2/INT0)

四、中断相关寄存器

1.IE 中断允许寄存器(A8H)

符号 功能
IE.7 EA 全局总中断开关,EA=1开启所有中断总开关
IE.0 EX0 外部中断0使能位,EX0=1开启INT0(P3.2)
IE.1 ET0 定时器0中断使能
IE.2 EX1 外部中断1使能
IE.3 ET1 定时器1中断使能
IE.4 ES 串口中断使能

✅开启外部中断0三步:

  1. 设置触发方式 IT0
  2. 打开INT0中断使能 EX0 = 1
  3. 打开全局总中断 EA = 1

2.TCON寄存器(88H)

IT0:外部中断0触发方式

  • IT0=0:低电平触发
  • IT0=1下降沿触发(推荐,按键首选)

下降沿含义:引脚电平 高 → 低 跳变,正好对应按键按下瞬间。

IE0:外部中断0中断请求标志,中断响应后硬件自动清零。

3.XICON辅助中断控制寄存器(C0H)

用于STC扩展的外部中断2、外部中断3(INT2、INT3)。标准reg52.h头文件没有定义该寄存器。

4.IP、IPH中断优先级寄存器

  • IP:中断优先级低位
  • IPH:中断优先级高位

⚠️IPH寄存器不可位寻址!不能写PX0H = 1;只能整体字节赋值 IPH = 0x01;

优先级规则:

  1. 高优先级中断可以打断低优先级中断,实现中断嵌套;
  2. 低优先级不能打断高优先级;
  3. 相同优先级同时触发,按照硬件查询次序响应。

五、中断服务函数语法

Keil C51扩展关键字interrupt,后面跟中断号,代表对应中断源。

c 复制代码
void 函数名(void) interrupt 中断号
{
    //中断处理逻辑
}

STC89C52RC中断号对照表

中断源 中断号 引脚
INT0外部中断0 0 P3.2
T0定时器0 1 ---
INT1外部中断1 2 P3.3
T1定时器1 3 ---
UART串口 4 ---
T2定时器2 5 ---
INT2外部中断2 6 P4.2
INT3外部中断3 7 P4.3

注意:中断服务函数不能有返回值,不能带形参。不要在中断里面写长延时、复杂运算。

六、完整可编译代码

版本1:最简版(基础功能,无消抖)

c 复制代码
#include <reg52.h>

//STC扩展寄存器
sfr XICON = 0xC0;
sfr P4    = 0xE8;
sfr IPH   = 0xB7;

sbit led1 = P2^7;
// KEY 直接硬件绑定 P3.2(INT0引脚),不需要额外sbit定义
// INT0硬件引脚固定 P3.2

//外部中断0初始化
void Int0_Init(void)
{
    IT0 = 1;     //下降沿触发 (高电平变低电平,按键按下)
    EX0 = 1;     //使能外部中断0(P3.2)
    EA  = 1;     //打开全局总中断
}

//外部中断0中断服务函数,中断号0
void Int0_ISR(void) interrupt 0
{
    led1 = ~led1; //翻转LED
}

void main(void)
{
    Int0_Init();
    while(1)
    {
        //主循环可以运行别的任务,不会阻塞按键
    }
}

解释:INT0是硬件功能,P3.2引脚硬件默认绑定外部中断0 ,不需要sbit key = P3^2读取电平;只要引脚检测到下降沿,自动触发中断。

缺点:机械按键抖动,可能一次按下触发多次中断

版本2:工程可用版(中断内部软件消抖)

c 复制代码
#include <reg52.h>

sfr XICON = 0xC0;
sfr P4    = 0xE8;
sfr IPH   = 0xB7;

sbit led1 = P2^7;
sbit key_int0 = P3^2;  //显式定义INT0按键引脚,代码可读性更好

//12M晶振毫秒延时
void delay_ms(unsigned int xms)
{
    unsigned int i,j;
    for(i = xms; i > 0; i--)
        for(j = 124; j > 0; j--);
}

//外部中断0初始化
void Int0_Init(void)
{
    IT0 = 1;
    EX0 = 1;
    EA  = 1;
}

//中断服务函数
void Int0_ISR(void) interrupt 0
{
    delay_ms(10);          //延时消抖
    if(key_int0 == 0)      //再次确认引脚确实是低电平,按键按下
    {
        led1 = ~led1;
        while(key_int0 == 0); //等待松开按键,避免长按反复触发
    }
}

void main(void)
{
    Int0_Init();
    while(1)
    {

    }
}

✅这份代码完整体现P3.2按键:

  1. sbit key_int0 = P3^2显式定义按键引脚
  2. IT0=1配置下降沿触发(P3.2由高变低,按键按下)
  3. 中断进来之后再次读取P3.2引脚电平做消抖校验

七、开发注意事项

  1. INT0硬件固定引脚为P3.2,INT1固定P3.3;不需要IO口手动轮询,硬件自动检测电平跳变。
  2. 机械按键抖动会导致单次按键多次进中断,实际项目必须增加软件消抖。
  3. 中断里面延时函数不宜过长,复杂业务逻辑尽量放主循环,中断内只做标志位。
  4. IPH寄存器不能位操作,只能直接字节赋值。
  5. 下降沿触发适合机械按键;电平触发容易重复触发。

八、本章小结

  1. INT0硬件引脚固定映射P3.2,配置好寄存器之后引脚电平跳变自动触发中断。
  2. 使用外部中断0:开启全局中断EA,开启EX0,配置IT0触发方式。
  3. 中断函数interrupt 0对应P3.2外部中断0。
  4. 机械按键必须消抖,否则会出现按一次LED翻转多次。
相关推荐
优化Henry2 小时前
学习笔记之爱立信站点指向证书执行
运维·服务器·网络·笔记·学习·信息与通信
科芯创展2 小时前
1A,5.5VIN,同步升降压恒流芯片,XZ3442
单片机
恒锐丰-罗生3 小时前
率能半导体 SS6840 单通道 H 桥电机驱动芯片深度解析
驱动开发·嵌入式硬件·硬件工程
IT古董3 小时前
【WMS学习笔记系列】03-功能模块设计
笔记·学习·系统架构
zyf1044164 小时前
暑期实践日志 Day31:推进修改任务,完成第五章字幕添加
学习·计算机网络·剪辑·暑期实践·课题任务·课程视频
拾知_H4 小时前
STM32+FreeRTOS基础配置
stm32·嵌入式硬件·freertos
智购科技自动贩卖机4 小时前
自动售货机硬件主控方案选型实战:单片机、树莓派、ESP32怎么选?
人工智能·单片机·嵌入式硬件·物联网·网络协议·yolo·架构
Canmag 兴隆磁性5 小时前
充磁的时候,磁铁里面到底发生了什么
学习·永磁材料·充磁·退磁
海兰6 小时前
【Kafka学习4】六大核心 API
学习·kafka·linq