51单片机基础-外部中断INT

第十三章 外部中断

1. 导入

在前几章中,我们通过轮询方式检测按键、控制电机等,但这种方式占用CPU资源,且响应不及时。为实现快速响应外部事件 (如紧急停止、按键触发),本章引入外部中断功能。

51单片机提供两个外部中断源:INT0 (P3.2)和 INT1(P3.3),当引脚电平发生变化时,可立即暂停当前程序,执行中断服务程序,处理完后再返回原任务。

本章目标:

  • 理解中断的基本概念与工作流程;
  • 掌握51单片机外部中断的触发方式;
  • 配置INT0和INT1为下降沿或低电平触发;
  • 实现按键通过中断控制LED或电机;
  • 为后续学习实时系统、事件驱动编程打下基础。

2. 硬件设计

2.1 中断引脚

中断源 对应引脚 特殊功能
INT0 P3.2 外部中断0
INT1 P3.3 外部中断1

2.2 典型电路(以INT0为例)

  • 按键K1一端接地;
  • 另一端接P3.2(INT0);
  • P3.2内部有上拉电阻,可省略外部上拉;
  • 按下按键时,P3.2变为低电平,触发中断。

建议添加100nF电容接地,进行硬件消抖(虽软件仍需处理)。


3. 软件设计

3.1 中断相关寄存器

51单片机通过以下寄存器控制中断:

寄存器 说明
TCON IT0(TCON.0) INT0触发方式:0=低电平触发,1=下降沿触发
IE0(TCON.1) INT0中断标志,自动置1,中断响应后自动清零
IT1(TCON.2) INT1触发方式
IE1(TCON.3) INT1中断标志
IE EX0(IE.0) 允许INT0中断
EX1(IE.1) 允许INT1中断
EA(IE.7) 总中断使能

3.2 中断初始化函数

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

sbit LED = P1^0;

void exti0_init() {
    IT0 = 1;    // 下降沿触发(推荐,避免重复触发)
    EX0 = 1;    // 使能INT0中断
    EA  = 1;    // 开启总中断
}

// 外部中断0服务程序
void int0_isr() interrupt 0 {
    LED = ~LED;  // 每次中断翻转LED
}

interrupt 0 表示这是外部中断0的中断服务函数(INT0的中断号为0)。


3.3 完整示例:按键中断控制LED

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

sbit LED = P1^0;

void delay_ms(unsigned int ms) {
    unsigned int i, j;
    for (i = 0; i < ms; i++)
        for (j = 0; j < 125; j++);
}

void exti0_init() {
    IT0 = 1;  // 下降沿触发
    EX0 = 1;  // 使能INT0
    EA  = 1;  // 全局中断开启
}

void main() {
    LED = 0;  // 初始LED亮
    exti0_init();
    while(1) {
        // 主程序可执行其他任务
        // 如:电机控制、显示刷新等
    }
}

// 外部中断0服务函数
void int0_isr() interrupt 0 {
    delay_ms(10);           // 软件消抖
    if (P3 & 0x04) == 0) {  // 再次确认P3.2为低(按键按下)
        LED = ~LED;
    }
    // IE0由硬件自动清零
}

3.4 外部中断1(INT1)示例

c 复制代码
void exti1_init() {
    IT1 = 1;  // 下降沿触发
    EX1 = 1;  // 使能INT1
    EA  = 1;
}

void main() {
    exti1_init();
    while(1);
}

// 外部中断1服务函数
void int1_isr() interrupt 2 {
    // INT1的中断号为2
    P1 = 0x00;  // 触发后关闭所有输出(如紧急停止)
}

3.5 中断触发方式对比

触发方式 配置 特点
低电平触发 IT0=0 只要为低就触发,可能重复触发
下降沿触发 IT0=1 仅在高→低跳变时触发一次,推荐使用

推荐使用下降沿触发,配合软件消抖,避免误触发。


3.6 应用:紧急停止电机

假设电机正在运行,通过INT1实现紧急停止:

c 复制代码
sbit IN1 = P2^0;
sbit IN2 = P2^1;
sbit ENA = P2^2;

void motor_stop() {
    IN1 = 0; IN2 = 0; ENA = 1;
}

void exti1_init() {
    IT1 = 1;
    EX1 = 1;
    EA  = 1;
}

void main() {
    // 启动电机正转
    IN1 = 1; IN2 = 0; ENA = 1;
    exti1_init();
    while(1);
}

void int1_isr() interrupt 2 {
    motor_stop();  // 紧急停止
}

按键接P3.3,按下后立即停止电机,响应速度快。


3.7 编译与下载

  • Keil中创建工程;
  • 确保按键接P3.2或P3.3;
  • 编译生成HEX;
  • 下载至单片机;
  • 按下按键,观察是否立即响应。

若中断不触发:

  • 检查EAEX0/EX1是否开启;
  • 确认IT0/IT1设置正确;
  • 检查按键是否接地,引脚是否为低电平。

4. 小结

本章通过引入外部中断,掌握了事件驱动编程的核心技术,主要内容包括:

  • 中断机制:理解中断的触发、响应与返回过程;
  • 寄存器配置:掌握TCON、IE等关键寄存器的设置;
  • 软件实现:编写中断服务程序,实现快速响应;
  • 应用场景:用于按键检测、紧急停止、实时控制;
  • 系统优化:解放主程序,提高响应速度与系统稳定性。

4.1 常见问题与解决

问题 原因 解决方法
中断不响应 EA未开启或EX0=0 检查中断使能设置
多次触发 未消抖或使用低电平触发 改为下降沿触发 + 软件消抖
程序跑飞 中断函数中使用长延时或递归 中断函数应短小精悍
标志未清 一般由硬件自动清零 不建议手动清除IE0/IE1

4.2 下一步学习建议

  • 结合定时器中断实现多任务系统;
  • 使用外部中断实现计数功能(如转速测量);
  • 引入中断优先级(IP寄存器)管理多个中断;
  • 应用于工业控制智能报警等实时系统。

本章标志着你已掌握实时响应能力,下一章将进入定时器/计数器的深入学习,实现精准延时与周期性任务调度。


相关推荐
Blossom.1186 小时前
把 AI“缝”进布里:生成式编织神经网络让布料自带摄像头
人工智能·python·单片机·深度学习·神经网络·目标检测·机器学习
lzj_pxxw7 小时前
嵌入式开发技巧:舍弃标志位,用宏定义函数实现程序单次运行
笔记·stm32·单片机·嵌入式硬件·学习
XINVRY-FPGA8 小时前
XCAU10P-2SBVB484I Xilinx Artix UltraScale+ FPGA
嵌入式硬件·fpga开发·云计算·硬件工程·dsp开发·射频工程·fpga
木子单片机8 小时前
基于51单片机温度检测报警
stm32·单片机·嵌入式硬件·51单片机·keil
hazy1k17 小时前
51单片机基础-步进电机控制
stm32·单片机·嵌入式硬件·51单片机
清风66666617 小时前
基于单片机的智能收银机模拟系统设计
数据库·单片机·毕业设计·nosql·课程设计
第二层皮-合肥18 小时前
RTC时钟原理
单片机·嵌入式硬件
小莞尔21 小时前
【51单片机】【protues仿真】基于51单片机送带计数器系统
c语言·单片机·嵌入式硬件·物联网·51单片机
云知谷1 天前
【嵌入式基本功】单片机嵌入式学习路线
linux·c语言·c++·单片机·嵌入式硬件