1. 课程导论与分层架构全景

1.1 为什么需要分层架构?

先说说我自己的经历。十年前我刚入行时,接手过一个智能灯控项目。代码全写在一个 main.c 里,全局变量满天飞,中断服务函数里还塞着延时。功能倒是能跑,但每次加需求我都得熬夜改代码。有一次客户要换个 WiFi 模块,我整整重构了两周——因为驱动和业务逻辑全搅在一起了。

你想想看,MCU 开发其实有个很尴尬的现实:硬件迭代快,但软件复用率极低。换个芯片、换个外设,代码就得重写大半。为什么会这样?说白了,就是缺少分层意识。

分层架构的核心价值:

  • 隔离变化——硬件换了,只改底层;需求变了,只改上层
  • 提升复用——写一次驱动,多个项目通用
  • 便于测试——每层可以单独验证,不用等硬件就绪
  • 团队协作——有人写驱动,有人写业务,互不干扰

1.2 MCU 软件开发的痛点与挑战

这些年我带过不少项目,也踩过很多坑。总结下来,MCU 开发有三大顽疾:

痛点 表现 后果
耦合过紧 驱动代码和业务逻辑混在一起 换芯片等于重写整个项目
可移植性差 代码依赖特定 MCU 寄存器操作 换个平台,移植成本比新写还高
调试困难 问题定位需要全盘排查 一个 bug 查三天,最后发现是时序问题

我曾经踩过的坑:有个温控项目,我把 DS18B20 的时序操作直接写在温度采集函数里。后来要换成 NTC 热敏电阻,结果发现温度采集、滤波、阈值判断全耦合在一起。改了一个星期,还引入了新 bug。从那以后,我坚持驱动层必须独立封装。

1.3 经典三层架构详解

我习惯把 MCU 软件分成三层。这个结构不是拍脑袋想的,是经过多个项目验证的。你记住这个图,后面所有章节都围绕它展开。

MCU 嵌入式软件三层架构 APP 应用层 业务逻辑 · 状态机 · 用户交互 温控策略 · 报警处理 · 数据显示 OSAL 操作系统抽象层 任务调度 · 时间管理 · 同步互斥 消息队列 · 软件定时器 · 内存管理 HAL 硬件抽象层 GPIO · UART · I²C · SPI · ADC · PWM 寄存器封装 · 外设驱动 · 板级支持包 依赖方向:上层依赖下层,下层不依赖上层

HAL 层:硬件抽象层

这一层直接跟寄存器打交道。我习惯把每个外设封装成一个独立的模块。比如 UART,就提供 uart_init()、uart_send()、uart_recv() 三个接口。上层调用时,根本不用关心底层是 STM32 还是 GD32。

我的经验:HAL 层接口要尽量简洁。别想着把所有功能都暴露出来。接口越少,上层越稳定。我一般每个外设只暴露 3-5 个核心函数。

OSAL 层:操作系统抽象层

这一层是很多初学者容易忽略的。你想想看,如果你的项目从裸机切换到 FreeRTOS,任务创建、延时、信号量的 API 全都不一样。OSAL 就是给这些系统服务包一层统一的接口。

举个例子:

// OSAL 统一接口
void osal_task_create(void (*task)(void*), void *param);
void osal_delay_ms(uint32_t ms);
int  osal_sem_take(osal_sem_t *sem, uint32_t timeout);

// 底层可以是 FreeRTOS
// #define osal_task_create(task, param) xTaskCreate(task, ...)
// 也可以是 RT-Thread
// #define osal_task_create(task, param) rt_thread_create(...)

APP 层:应用层

这一层只关心业务逻辑。比如温控系统,APP 层只处理:温度到了多少该开加热?温差多大该报警?至于温度怎么读、继电器怎么控制,APP 层一概不管。

1.4 模块化设计原则

分层是纵向切分,模块化是横向切分。我总结了两条铁律:

  • 高内聚:一个模块只做一件事,并且把它做好。比如温度采集模块,就只负责采集和滤波,别掺和报警逻辑。
  • 低耦合:模块之间通过接口通信,别直接访问对方的全局变量。我见过最离谱的代码,一个模块直接修改另一个模块的内部数组——这种代码根本没法维护。

模块化设计的检查清单:

  1. 每个模块是否有独立的 .h 和 .c 文件?
  2. 模块对外暴露的接口是否少于 5 个?
  3. 模块内部是否有 static 关键字保护私有数据?
  4. 模块之间是否只通过函数调用通信?
  5. 删除一个模块,其他模块是否不受影响?

1.5 课程项目概览:智能家居温控系统

光讲理论没意思。这门课会带着你从零搭建一个完整的智能温控系统。项目包含:

模块 功能 涉及知识点
温度采集 读取 DS18B20 / NTC 温度 HAL 层驱动封装、滤波算法
温控策略 PID 控制 / 开关控制 APP 层业务逻辑、状态机
显示模块 OLED 显示当前温度 HAL 层 I²C 驱动、OSAL 任务管理
按键交互 设置目标温度、模式切换 中断处理、去抖算法
通信模块 UART 上报数据 OSAL 消息队列、数据协议

我建议你这样做:每学完一章,就把对应的代码写到你的开发板上。别光看。我当年学 RTOS 时,把书上的例程一个个敲了一遍,虽然慢,但理解得特别深。

这个项目虽然看起来简单,但它覆盖了 MCU 开发中 90% 的常见场景。学完之后,你完全可以把这个架构套用到其他项目上——不管是智能家居、工业控制还是物联网终端。