1. 课程导论与分层架构全景:为什么需要分层?
大家好,我是你们这趟旅程的向导。先聊聊我自己的经历吧。十年前我刚入行时,写STM32程序就是典型的“裸奔”——一个main.c里塞满所有外设初始化、中断处理和业务逻辑。那时候项目小,感觉还挺爽。直到有一次接手一个带Wi-Fi、蓝牙、LCD显示和多个传感器的项目……嗯,那代码简直成了意大利面条,改一个定时器参数,莫名其妙把LCD刷新搞崩了。
从那天起,我开始认真思考一个问题:为什么我们的代码不能像搭积木一样,各玩各的,互不干扰?
1.1 从裸机开发到分层架构的演进
先看一张图,直观感受一下这种演进过程。
说白了,分层架构就是给代码划地盘。每一层只关心自己的事,通过固定的接口跟上下层打交道。我见过太多新手一上来就怼RTOS,结果任务之间互相抢资源,死锁频繁——其实根源不是RTOS不好,而是底层没有做好隔离。
1.2 为什么需要分层?三个核心理由
| 维度 | 裸机/平铺式 | 分层架构 |
|---|---|---|
| 可维护性 | 改一个外设驱动,可能影响三个业务模块 | 驱动层修改,上层接口不变,业务层无感知 |
| 可移植性 | 换MCU型号,几乎重写全部代码 | 只换最底层HAL驱动,应用层代码几乎不动 |
| 团队协作 | 两个人同时改同一个文件,合并时想哭 | A写驱动层,B写应用层,接口约定好就行 |
我个人习惯:在项目启动前,先用白板画出三层结构——硬件抽象层、服务层、应用层。哪怕后面要调整,也比直接写代码强十倍。
1.3 分层架构在STM32 HAL库中的落地
你可能会问:HAL库本身不就是一层封装吗?没错,但HAL库只做到了硬件抽象,它没有帮你解决任务调度和模块间通信的问题。
举个例子:你用HAL_UART_Receive_IT接收数据,中断来了,数据存到哪儿?谁来处理?如果此时LCD正在刷新,会不会冲突?
这就是我们这门课要解决的核心问题——在HAL库之上,构建一套清晰的分层任务调度框架。
一个小技巧:把HAL库当作“硬件驱动层”,不要在里面写任何业务逻辑。我在项目中见过有人直接在UART中断回调里做JSON解析……那场面,简直灾难。
1.4 课程目标与学习路径
这门课不是教你怎么点灯,也不是教你怎么用RTOS。我们的目标是:
- 掌握分层架构的设计思想——知道什么时候该拆,什么时候该合
- 学会在HAL库基础上搭建任务调度框架——不用RTOS也能实现多任务协同
- 写出可移植、可维护的驱动代码——换芯片不换逻辑
整个课程分四个阶段:
- 基础篇(第1-8章):分层架构理论 + HAL库底层机制剖析
- 框架篇(第9-16章):搭建任务调度核心,实现队列、信号量、事件标志组
- 驱动篇(第17-24章):用分层思想重写UART、SPI、I2C、定时器等外设驱动
- 实战篇(第25-30章):综合项目——多传感器数据采集与远程上报系统
注意:如果你对HAL库的基本用法还不熟(比如不知道HAL_UART_Transmit怎么用),建议先补一下基础。这门课默认你已经能独立使用HAL库操作常用外设。
1.5 本章小结
一句话总结:分层不是炫技,是让你少加班。我当年要是早点明白这个道理,至少能少熬几十个通宵。