分层架构基础:驱动层、中间件层、业务层
很多刚入行的朋友问我,单片机代码到底该怎么组织?说实话,我早年也吃过不少苦头。一个项目写下来,main函数里上千行,GPIO和定时器配置混在一起,算法逻辑和硬件操作搅成一锅粥。后来改个LED闪烁频率,结果把整个系统的时序都搞崩了。
为什么会这样?说白了就是没有分层。
分层架构不是什么高深理论,它就是一套代码组织的规矩。我做了十几年嵌入式,从8位机到Cortex-M系列,项目越复杂,越觉得分层是救命稻草。今天咱们就聊聊这三层:驱动层、中间件层、业务层。
驱动层:和硬件打交道的那层
驱动层是离硬件最近的一层。它直接操作寄存器、处理中断、配置外设。说白了,它就是硬件和软件之间的翻译官。
驱动层的职责很明确:
- 硬件初始化:配置时钟、GPIO模式、外设参数
- 数据收发:通过SPI、I2C、UART等接口读写数据
- 中断处理:响应硬件事件,比如定时器溢出、外部中断触发
- 状态查询:读取寄存器状态,判断硬件是否就绪
我记得有一次做电机驱动项目,芯片从STM32F1换到GD32。如果驱动层封装得好,只需要改底层寄存器操作,上层代码一行不动。但当时我偷懒,把GPIO操作直接写在业务逻辑里……结果换芯片时,改了整整三天。
spi_send_byte()、gpio_set_level(),绝不掺和业务判断。
中间件层:承上启下的胶水层
中间件层夹在驱动和业务之间。它不直接操作硬件,也不处理具体业务,而是提供一些通用服务。
常见的中间件包括:
- 协议栈:Modbus、CANopen、TCP/IP
- 文件系统:FATFS、LittleFS
- RTOS内核:FreeRTOS、RT-Thread
- 算法库:PID控制、FFT、滤波
- 数据管理:环形缓冲区、链表、内存池
中间件层的核心价值在于复用。你想想看,一个Modbus协议栈,不管底层是用UART还是SPI,协议解析的逻辑是一样的。中间件层把这种通用逻辑抽出来,换个平台照样用。
我曾经在一个项目里自己手写了一个环形缓冲区,后来发现FreeRTOS自带的消息队列完全够用。嗯,这就是中间件层的意义——别重复造轮子,除非你想练手。
业务层:真正干活的层
业务层是产品逻辑的所在地。它决定系统做什么、什么时候做、怎么做。
业务层的典型内容:
- 状态机:系统运行状态切换
- 控制逻辑:根据传感器数据决定执行器动作
- 用户交互:按键响应、界面刷新
- 数据上报:按照业务规则打包数据并发送
业务层应该只关心逻辑,不关心硬件细节。比如“温度超过50度就打开风扇”,业务层只需要调用 fan_on(),至于风扇是GPIO控制还是PWM控制,那是驱动层的事。
三层之间的依赖关系
依赖关系是分层的灵魂。规矩很简单:上层依赖下层,下层不依赖上层。
| 层级 | 依赖谁 | 被谁依赖 | 能否独立测试 |
|---|---|---|---|
| 业务层 | 中间件层、驱动层 | 无 | 需要Mock下层接口 |
| 中间件层 | 驱动层 | 业务层 | 可独立测试 |
| 驱动层 | 无 | 中间件层、业务层 | 需要硬件环境 |
这个依赖方向不是随便定的。你想想看,如果驱动层依赖了业务层,那换个业务场景,驱动层也得跟着改,这还叫什么分层?
我个人的做法是:在代码里用接口指针或者回调函数来解耦。比如驱动层提供一个 uart_rx_callback 注册函数,中间件层注册自己的处理函数。这样驱动层完全不知道上层是谁,只管收数据、调回调。
一个实际的分层案例
拿一个温控系统来说:
- 驱动层:DS18B20温度传感器驱动、继电器驱动、LCD显示驱动
- 中间件层:OneWire协议解析、PID控制算法、环形缓冲区
- 业务层:温度超过阈值开继电器、LCD显示当前温度、按键切换工作模式
如果哪天要把DS18B20换成NTC热敏电阻,只需要改驱动层,中间件层的PID算法和业务层的控制逻辑完全不用动。这就是分层带来的好处。
分层架构的SVG结构图
下面这张图展示了三层架构的依赖关系和典型内容。你可以看到箭头方向是从上层指向下层,下层对上层一无所知。
分层的几个常见误区
我见过不少团队,嘴上说分层,实际写出来的代码还是乱的。这里列几个常见问题:
- 过度分层:一个简单的LED闪烁项目,硬是分了五层。没必要,小项目可以适当简化。
- 层间耦合:驱动层返回一个结构体,业务层直接修改结构体成员。这等于把驱动层的内部暴露给了上层。
- 接口不稳定:今天驱动层接口是
uart_send(),明天改成uart_transmit(),上层代码跟着改。接口一旦确定,尽量保持稳定。 - 忽略错误处理:驱动层返回错误码,业务层直接忽略。时间长了,系统出问题根本查不到原因。
总结一下
驱动层管硬件,中间件层管通用服务,业务层管产品逻辑。三层之间单向依赖,上层调用下层,下层对上层一无所知。
这个架构不是银弹,但它能解决80%的代码混乱问题。你想想看,一个项目动辄几万行代码,没有分层,后期维护就是噩梦。我早期踩过的坑,希望你能绕过去。