「从入门到精通」的目录网上到处都是,但没人告诉你学到哪一步算过关。我按五个阶段排,每段只给一个标准:做不出来,就还没过,别急着往下走。
大部分「学不会 STM32」的人,问题不在 STM32,在 C 语言。指针、数组退化、结构体布局没搞明白,看寄存器手册就是看天书。
必须掌握:指针与指针的指针、数组与指针的区别、结构体与位域、函数指针与回调、const / static / volatile、位运算与宏。
建议练习:不看资料写一个环形缓冲区(ring buffer),再用函数指针表实现一个状态机。
验收:能解释 *(uint32_t *)(0x40020014) 这一行在做什么,以及为什么这里必须加 volatile。
顺序很重要:GPIO → EXTI → TIM → UART → I2C → SPI → ADC → DMA → Flash。每个外设都要做三遍:读时序图、用寄存器写一遍、再看 HAL 怎么封装。
为什么先写寄存器:不是让你以后都手写寄存器,是让你在 HAL 出问题时知道往哪看。只会调库的人,遇到库不工作就只能等别人救。
每个外设的通关三问:它的时钟从哪来?它的中断标志怎么清?它的错误标志分别代表什么?
验收:用寄存器(不用 HAL)写一个 UART 中断收发,能算出波特率寄存器的值并说明误差来源。
这一步是分水岭。绝大多数教程停在 Phase 1,所以你看到的所有代码都是「一个 main.c 里三千行」。
分层:bsp(板级:引脚、外设初始化)/ drv(器件驱动:传感器、屏、Flash)/ app(业务逻辑)。规则只有一条:不允许跨层调用。
非阻塞:业务代码里禁止 HAL_Delay()。用状态机 + 时间戳轮询,或者定时器驱动的 tick。
日志:分级(ERROR / WARN / INFO / DEBUG)+ 环形缓冲 + DMA 空闲中断发送,编译期可整段裁掉。
参数存储:Flash 双备份 + CRC 校验 + 版本号。单备份的产品,掉一次电就有一批板子返修。
验收:加一个新传感器,只新增文件、不改动已有模块的任何一行代码。
不是所有项目都需要 RTOS,但「需要」的时候往往已经晚了。判断标准:有多个「同时」发生的需求,或者有等待时间不确定的操作(通信、存储、人机交互)。
任务划分三原则:按触发源分而不是按功能分;一个任务只阻塞在一个地方;任务间只通过队列 / 信号量 / 任务通知通信,不共享裸变量。
别做的事:给每个函数开一个任务(几十个任务互相等,调度开销吃掉一半 CPU)。
验收:把 Phase 2 的项目改成 4 个左右任务的 RTOS 版本,每个任务的栈都用 HighWaterMark 量过并留 30% 余量。
详细内容见 FreeRTOS 学习攻略。
开发板上跑通,只完成了整个工作量的一小半。剩下的部分没人教,但决定产品能不能出货。
电源与复位:上电时序、复位 RC 参数、欠压检测阈值、复位脚走线远离干扰源。
时钟:外部晶振的负载电容要按晶体规格算,起振时间留余量,HSE 起振失败要能回退到内部 RC 并上报。
看门狗:独立看门狗 + 任务心跳汇总,别在定时器中断里喂。
升级:Bootloader + 双区 OTA + 断电续传 + 版本回滚 + 完整性校验。这四项缺一项,现场升级就会变砖。
低功耗:每个外设在睡眠前要关时钟,唤醒源要清理干净,实测待机电流而不是看手册典型值。
验收:断电拔电 500 次参数不丢;OTA 到 60% 断电,重新上电能接着升或回滚;待机电流达标且重复 20 次一致。
Phase 2 说的分层,落到文件夹就是下面这样。新建项目直接照抄,改改模块名即可。
留言 / 提问
写你卡住的地方:什么芯片、什么现象、已经试过什么。频率高的问题我会写进页面。昵称不填也能发。