描述
刚入门做嵌入式开发时,很多人经常纠结:
- 用定时器采集传感器数据,是直接 while 循环里轮询标志位,还是写个中断函数?
- 串口收发数据时,是用 while(!(USART_SR&RXNE)) 这种老老实实轮询,还是开个中断来接收?
- 项目调试时发现,轮询方式代码好像更直观,但 CPU 占用高得吓人;而中断看起来更“智能”,但又怕响应不及时。
这种困惑可以说是嵌入式开发的经典问题。今天,我们就来系统梳理一下 中断 vs 轮询 的区别、优缺点和应用场景,让你写项目时不再纠结。
一、轮询的本质:CPU 一直在问“好了没?”
所谓轮询,就是 CPU 主动不断查询外设状态寄存器。
例子:
如果我们要检测一个按键输入,代码可能是:
- while(1){
- if(GPIOx->IDR & PIN_MASK){
- // 按键按下,执行操作
- }
- }
特点:
- 简单、直观,好写好调试;
- 但 CPU 一直在跑循环,占用率极高;
- 一旦有多个任务,就容易顾此失彼。
二、中断的本质:外设主动“通知 CPU”
中断的思路是,CPU 不再傻傻问“好了没”,而是外设自己准备好数据时,主动打断 CPU 的当前任务,让 CPU 去执行中断服务程序。
例子:
- void EXTI0_IRQHandler(void){
- if(EXTI->PR &(1<<0)){
- EXTI->PR |=(1<<0);// 清中断标志
- // 按键按下,执行操作
- }
- }
特点:
- CPU 不用浪费时间等待;
- 响应更实时;
- 但中断嵌套过多时,容易造成优先级冲突和响应延迟。
三、效率对比:什么时候轮询更好,什么时候中断更好?
1. 轮询的优势场景
- 任务非常简单:比如检测一个 LED 状态,CPU 没有别的事干。
- 高频率、低延迟需求:有些场合下,轮询比中断更快,因为不需要保存/恢复上下文。比如极简 bit-banging 通信。
- 调试阶段:初学时,轮询逻辑更直观,不容易出错。
2. 中断的优势场景
- 多任务并行:比如 ADC 连续采样、UART 通信、外部输入信号,这些外设无法预知何时到来,中断能让 CPU 高效切换。
- 低功耗应用:MCU 可以进入休眠状态,等中断唤醒,而不是一直空跑。
- 实时响应需求:外设状态一旦变化,立刻触发 ISR,避免轮询的延迟。
四、实战案例
案例 1:串口接收
- 轮询方式:CPU 在循环中不断检测 RXNE 标志,CPU 占用率高,接收速率高时容易漏数据。
- 中断方式:每来一个字节触发一次中断,CPU 只在需要时处理,效率更高。
【配图建议:串口数据流对比图,轮询方式 CPU 一直忙,中断方式 CPU 空闲→数据来才处理】
案例 2:按键输入
- 轮询方式:需要在主循环不断检测 GPIO 状态,不适合低功耗。
- 中断方式:用外部中断(EXTI)检测电平变化,CPU 平时休眠,按键按下时自动唤醒,非常适合电池供电设备。
案例 3:高速采样任务
- 有时候轮询反而比中断更稳,比如 1MHz 的采样时钟,如果用中断,每秒中断 100 万次,CPU 可能直接崩溃;
- 此时更合适的方案是 DMA + 定时器触发 ADC,比单纯中断/轮询都高效。
五、开发者常见误区
误区 3:中断一定比轮询好错。中断也有开销,尤其是上下文保存和恢复。低延迟场景下,简单轮询反而更快。
误区 2:轮询就是“落后”的方式错。对于某些短小的逻辑,轮询更容易实现,也不会带来复杂的中断优先级问题。
误区 3:所有任务都用中断处理错。中断太多会导致优先级冲突,难以维护。复杂系统一般会用 中断 + RTOS 任务 配合,而不是全靠 ISR。
六、总结:怎么选?
- 项目小、逻辑简单 → 用轮询就行,别折腾太复杂;
- 多任务并行、功耗敏感 → 中断更合适;
- 高频采样、大数据吞吐 → DMA + 定时器触发,才是终极方案;
- 调试阶段 → 可以先用轮询,逻辑清楚后再改成中断。
一句话总结:中断不是万能的,轮询也不是落后的,两者都有存在价值。关键是根据项目场景来选。
打开APP阅读更多精彩内容