1. 分层设计思想入门:什么是分层架构?为什么单片机软件需要分层?

大家好,我是你们的老朋友。今天咱们聊聊单片机软件分层这件事。

说实话,我刚开始做单片机开发那会儿,哪懂什么分层不分层。一个main函数从头写到尾,全局变量满天飞,中断服务函数里塞满业务逻辑。那时候觉得,能跑起来就是胜利。直到有一次,一个智能家居项目让我彻底栽了跟头——客户要改一个传感器读取方式,我改了三天,结果把三个不相关的功能模块全搞崩了。嗯,从那以后,我开始认真思考:代码到底该怎么组织?

什么是分层架构?

分层架构,说白了就是把软件按照职责切分成几个「层」。每一层只关心自己的事,层与层之间通过约定的接口通信。

你想想看,我们盖房子不会把地基、墙壁、屋顶混在一起浇筑吧?软件也一样。典型的单片机分层架构长这样:

+----------------------------+
|       应用层 (App)          |  ← 业务逻辑、状态机
+----------------------------+
|       服务层 (Service)      |  ← 协议解析、数据管理
+----------------------------+
|       驱动层 (Driver)       |  ← GPIO、UART、SPI操作
+----------------------------+
|       硬件抽象层 (HAL)      |  ← 寄存器映射、外设封装
+----------------------------+
|       硬件 (Hardware)       |  ← 芯片、外设芯片
+----------------------------+

每一层都像是一个「黑盒子」。上层只管调用下层提供的接口,不用关心下层怎么实现的。下层只管做好自己的事,不用管上层拿数据去干嘛。

为什么单片机软件需要分层?

很多刚入行的朋友会问:单片机资源这么紧张,搞分层不是浪费吗?

我的回答是:恰恰相反。分层不是浪费,而是投资。我经历过一个血泪教训——

我曾经接手过一个项目,前任工程师把所有代码写在一个文件里,足足3000多行。我要把STM32F103换成GD32F103,结果发现GPIO操作、定时器配置、中断处理全部混在一起。改一个引脚定义,要翻遍整个文件。最后花了整整两周才完成移植,还引入了三个新bug。

分层的好处,我总结了几点:

  • 可移植性:换芯片?只需要改最底层的HAL层,上层代码纹丝不动
  • 可维护性:出bug了,定位到具体层,不用从头翻到尾
  • 可测试性:每一层可以单独测试,不用等硬件就绪
  • 团队协作:A写驱动,B写应用,接口定好就能并行开发

你想想看,一个产品从原型到量产,芯片型号可能换好几次。没有分层,每次换芯片都是噩梦。

分层设计的核心原则:高内聚、低耦合

这两个词,我估计你听得耳朵都起茧了。但真正理解的人不多。

高内聚:一个模块内部的元素,应该紧密相关。比如,UART驱动里只放UART相关的东西,别把LED控制代码塞进去。

低耦合:模块之间的依赖关系要尽量少。A模块改了,B模块不应该受影响。

我举个例子你就明白了:

反面教材(耦合严重)

// 驱动层直接调用应用层的LED闪烁函数
void uart_send_byte(uint8_t data) {
    // 发送数据...
    led_blink(3);  // 这行代码不该出现在这里!
}

正确做法(低耦合)

// 驱动层只做驱动的事
void uart_send_byte(uint8_t data) {
    // 发送数据...
    // 不关心上层怎么处理
}

// 应用层通过回调或事件通知来响应
void uart_rx_callback(uint8_t data) {
    led_blink(3);  // 这里才是正确的位置
}

我个人习惯用「接口隔离」来保证低耦合。每个模块只暴露必要的函数,内部实现全部隐藏。这样别人想乱用都没机会。

分层设计中的常见误区

这里我列几个我踩过的坑:

误区 表现 后果
过度分层 明明只有两个功能,硬要分五层 代码膨胀,性能下降
层间泄漏 应用层直接操作寄存器 移植困难,耦合严重
接口臃肿 一个函数传七八个参数 调用复杂,容易出错
忽视性能 每层都加抽象,中断响应变慢 实时性不达标

避坑指南:我曾经在一个项目中,为了追求「完美分层」,在中断服务函数里加了三级函数调用。结果中断响应时间从2微秒变成了15微秒。后来我学乖了——中断里尽量直通硬件,分层留给主循环。

什么时候该分层?什么时候不该?

这不是一个非黑即白的问题。我的经验是:

  • 产品级代码:必须分层。哪怕是个简单的温控器,也要考虑后续维护
  • 原型验证:可以不分层。快速出活最重要,后面再重构
  • 资源极度受限:比如1KB RAM的芯片,分层要适度,但核心思想不能丢

说白了,分层是一种「思维习惯」。即使你写一个100行的程序,也可以在心里把功能划分清楚。等代码膨胀到1000行时,你自然知道该往哪里放新功能。

小结

这一章我们聊了分层架构的基本概念、为什么需要分层、以及高内聚低耦合的核心原则。记住一句话:分层不是目的,而是手段。它的终极目标是让代码好改、好测、好移植。

下一章,我会带你手把手搭建一个实际的分层架构,从硬件抽象层开始。到时候你会看到,分层到底是怎么落地的。

公众号:蓝海资料掘金营,微信deep3321