欢迎光临
我们一直在努力

中断与定时器中断

前言

上一篇的轮询模式,CPU 被绑在 while(1) 里不停查询。本篇引入中断,让硬件主动通知 CPU;再重点讲最常用的内部中断——定时器中断,实现非阻塞的精准定时。

一、什么是中断?一句话理解

CPU 正在执行主程序,某个紧急事件向 CPU 发来请求信号。CPU 立刻暂停当前代码、保存现场,跳转到专门写好的中断服务函数处理;处理完恢复现场,回到刚才的位置继续执行。

类比:你在看书(while(1)),手机响了(中断)。

  • 放下书,标记读到第几页(保护现场)
  • 接电话处理(中断服务函数)
  • 挂断,翻回标记继续看(恢复现场)

核心优势:不是 CPU 主动轮询查事件,而是事件主动通知 CPU,实时响应。

基础名词

  • 中断源:触发中断的来源。外部中断(按键、外部电平变化);内部中断(定时器、串口、ADC)
  • 中断标志位:硬件自动置 1,代表 “中断来了”;进入中断函数后必须清零,否则重复触发
  • 中断优先级:多个中断同时到,优先级高的先执行;高优先级可抢占低优先级(中断嵌套)
  • 中断服务函数 ISR:不能传参、不能返回值,尽量简短
  • 中断向量表:内存地址表,存各中断源的 ISR 入口地址,硬件自动查表跳转

二、外部中断(按键中断举例)

外部中断靠引脚电平变化触发:

  • 下降沿触发:高→低瞬间(按键按下最常用)
  • 上升沿触发:低→高瞬间
  • 电平触发:持续低 / 高就持续触发(易重复进中断,少用)

机械按键有抖动,硬件加电容消抖,或软件在中断里延时消抖。但中断里不推荐延时,项目一般用标志位,把业务逻辑放回 while(1)。

sbit LED = P1^0;
bit key_flag = 0; // 按键标志位

void Int0_ISR() interrupt 0 // 外部中断0
{
key_flag = 1; // 只打标记,不做复杂操作
}

void main(void)
{
IT0 = 1; // 下降沿触发
EX0 = 1; // 开外部中断0
EA = 1; // 开总中断

while(1)
{
if(key_flag) // 主循环处理业务
{
LED = ~LED;
key_flag = 0;
}
}
}

好习惯:中断只做标记,业务逻辑交给主循环。ISR 一定要短!

三、定时器中断:最常用的内部中断

定时器本质是一个不断自增的计数器,由系统时钟驱动。计数到预设值溢出,硬件自动触发中断。

对比阻塞延时:

  • delay_ms():CPU 原地空转,啥也干不了(阻塞)
  • 定时器中断:计数器硬件自动计数,CPU 正常跑主程序;到点触发中断(非阻塞)

配置要点

  • 预分频:把系统时钟分频,得到计数脉冲
  • 自动重装载值:计数器 0 加到设定值 → 溢出 → 置标志位
  • 开启定时器:中断使能 + 总中断

代码示例(51 单片机,定时器 0,50ms 定时,20 次 = 1s,LED 每秒翻转):

#include <reg52.h>

sbit LED = P1^0;
bit timer_flag = 0;
unsigned char cnt = 0;

void Timer0_ISR() interrupt 1 // 定时器0中断
{
TH0 = 0x4C; // 重装初值,50ms
TL0 = 0x00;
cnt++;
if(cnt >= 20) // 20*50ms = 1s
{
cnt = 0;
timer_flag = 1;
}
}

void Timer0_Init(void)
{
TMOD |= 0x01; // 模式1
TH0 = 0x4C;
TL0 = 0x00;
ET0 = 1; // 开定时器0中断
TR0 = 1; // 启动定时器
EA = 1; // 开总中断
}

void main(void)
{
Timer0_Init();
while(1)
{
if(timer_flag) // 每秒执行一次任务
{
LED = ~LED;
timer_flag = 0;
}
}
}

四、中断执行完整流程(重点)

  • 主程序正常运行 while(1)
  • 中断源产生事件,硬件置中断标志位
  • 中断使能打开且条件满足 → 触发中断
  • CPU 暂停当前代码,保护现场(寄存器压栈)
  • 查中断向量表,跳转对应 ISR
  • 执行 ISR:处理事件,必须清中断标志位
  • ISR 结束,恢复现场(寄存器出栈)
  • CPU 回到暂停处继续执行
  • 五、写中断代码的避坑要点

    • ✅ ISR 尽量短小,禁止长延时、复杂循环、printf(耗时)
    • ✅ 中断和主循环共用的变量加 volatile,防编译器优化
    • ✅ 中断标志位一定清除,不清零会反复进入中断
    • ✅ 不要在中断里调用耗时函数,中断只负责打标记
    • ✅ 注意中断优先级,避免低优先级任务被一直抢占丢事件
    • ❌ 别在中断里做大量业务逻辑,只做标记!

    六、小结

    • 中断本质:硬件主动通知 CPU,实现异步事件响应。
    • 外部中断:响应突发外部信号(按键、传感器)
    • 定时器中断:周期性定时任务,替代阻塞延时,项目里最常用
    赞(0)
    未经允许不得转载:171主机测评 » 中断与定时器中断
    分享到: 更多 (0)

    评论 抢沙发

    • 昵称 (必填)
    • 邮箱 (必填)
    • 网址