很多 MCU 工程表面跑得挺好,一上线就出问题。原因通常不是硬件坏,而是代码里埋了“容易犯错”的地雷。本文整理了单片机开发中最常见的 Bug 类型、典型例子以及规避建议,适合裸机、RTOS 和各种嵌入式场景。 一、中断相关问题(最容易出 BUG) 中断和主程序共享变量未同步
中断优先级错误
中断未清标志
问题:ISR 中未清除中断标志,导致反复触发。 建议:
判断中断源后第一时间清除标志; ISR 尾部不能依赖“自然清除”。
示例: void TIM2_IRQHandler(void)
{
if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM2, TIM_IT_Update); // 一定要先清标志
// 处理中断事件...
}
}
二、内存和指针问题 指针非法访问 / 越界
问题:数组越界、空指针解引用、类型错误。 建议:
所有数组操作都加边界检查; 禁止使用未经初始化的指针; 用调试器查看访问地址是否合法。
栈溢出
问题:局部变量太大、递归、ISR 堆栈深度太大。 后果:程序跑飞或重启。 建议:
减少 ISR 内局部变量; 使用全局缓冲区替代大数组; 注意链接文件栈空间配置。
DMA 与 CPU 访问冲突
三、外设配置问题 四、状态机与逻辑控制 if/else 过多,流程混乱
状态变量未初始化
问题:未初始化的状态进入未知分支。 建议:
进入主循环前初始化所有状态变量; 状态机中加入默认处理。
五、volatile 使用不当 六、时序问题 初始化顺序错误
接口协议时序不满足(如 SPI/I2C)
问题:时钟/片选/延时配合不对,导致通信失败。 建议:
七、看门狗相关 忘记喂狗 / 错误喂狗
问题:系统运行中被错误复位。 建议:
喂狗应在主任务执行成功后再进行; 不能在死循环或异常分支内喂狗。
八、编译优化与链接问题 DEBUG 能跑,RELEASE 崩溃
ISR 名字拼错,启动文件未链接
后果:中断触发直接跑飞。 建议:
检查启动文件中断向量表定义; 建议使用统一 ISR 重定向表。
九、边界条件与偶发异常 缓冲区满、队列溢出、越界访问
问题:数据量超过处理能力未及时判断,导致错乱。 建议:
加入队列满判断、缓冲区环绕判断; 使用 assert 或日志记录关键边界。
高负载时偶发问题
十、RTOS 混用错误(如使用 FreeRTOS) 总结:单片机开发中常见的高风险点汇总如下 【中断同步】 共享变量未保护
【指针内存】 数组越界 / 栈溢出
【外设配置】 GPIO、时钟、USART 时序错误
【状态逻辑】 没有状态机、流程混乱
【volatile】 缺失或误用
【DMA冲突】 DMA 与 CPU 同时操作
【看门狗】 忘记喂狗或错误喂狗
【编译优化】 DEBUG 能跑,RELEASE 崩溃
【RTOS】 中断中误用任务 API、优先级错误 建议: 如有需要,我可以分享一份中断+缓冲+状态控制的高可靠通信模板(裸机/RTOS皆可)。
欢迎补充与交流。希望本文能帮你提前避免那些“我也不知道为啥炸了”的问题。
|