第二章 系统总体架构设计:硬件架构选型与软件分层

各位同学,咱们直接进入正题。上一章聊了项目背景和需求,这一章要动真格的了——把整个货架系统的骨架搭起来。

我个人习惯,做任何嵌入式项目,第一步不是画原理图,而是先想清楚两件事:用什么芯片软件怎么分层。这两件事定下来,后面就是填坑的体力活了。

2.1 硬件架构选型:MCU、传感器、无线模块

低功耗货架系统,说白了就是一堆传感器定时醒来,把数据发出去,然后继续睡大觉。所以硬件选型的核心就三个字:省、稳、小

2.1.1 MCU选型——心脏要够强,还得会睡觉

MCU是整个系统的大脑。我选MCU有个原则:性能够用就行,功耗越低越好

为什么?你想想看,货架系统大部分时间都在待机。如果MCU的待机电流是10μA,另一颗是1μA,一年下来电池寿命差好几倍。

我推荐几颗常用的低功耗MCU:

型号 内核 待机电流 唤醒时间 适合场景
STM32L0系列 Cortex-M0+ 0.3μA 3.5μs 通用型,生态好
EFM32 Gecko Cortex-M3 0.2μA 2μs 超低功耗场景
nRF52840 Cortex-M4F 1.3μA 1.3μs 自带BLE,省一颗芯片

我个人偏好STM32L0系列。原因很简单:资料多、坑少、便宜。我在项目中遇到过用某款小众MCU,结果低功耗模式唤醒后ADC采样值漂移,查了三天才发现是芯片内部参考电压没稳定。嗯,从那以后我再也不敢用太冷门的片子了。

小技巧:选MCU时,别忘了看它的RTC功耗。很多MCU待机电流很低,但RTC一开就翻倍。我一般要求RTC+RAM保持的总功耗不超过1μA。

2.1.2 传感器选型——够用就好,别堆料

货架系统需要感知什么?无非是:有没有货、温度湿度、门有没有关好

我见过一些方案,一个货架上装了红外、超声波、激光、压力传感器……说实话,没必要。传感器越多,功耗越高,故障点也越多。

我的建议:

  • 重量检测:用HX711+电阻应变片。便宜、成熟、功耗低。我习惯在HX711的电源脚加一个MOS管,不用时彻底断电。
  • 温湿度:SHT30或DHT22。SHT30精度更高,但DHT22便宜。看预算选。
  • 门磁检测:干簧管+磁铁。最简单的方案,零功耗待机。

这里有个坑:传感器不要一直供电。我曾经做过一个项目,传感器上电后需要100ms稳定时间,我直接让MCU一直供电,结果待机电流多了50μA。后来改成采样前100ms才供电,功耗直接降了一个数量级。

注意:传感器选型时,一定要看它的启动时间。有些传感器启动需要几百毫秒,这会严重影响你的采样周期设计。我一般要求启动时间不超过50ms。

2.1.3 无线模块选型——距离、功耗、成本三选二

无线通信是货架系统的命脉。数据传不出去,前面所有工作都白费。

市面上主流的无线方案就几种:

  • BLE(蓝牙低功耗):适合近距离(10-30米)、低数据量。nRF52840或TI CC2540。我推荐nRF52840,自带MCU,一颗芯片搞定所有。
  • LoRa:适合远距离(1-5公里)、超低功耗。SX1278或ASR6501。适合仓库、冷链等大场景。
  • Zigbee:适合组网、多节点。CC2530。但说实话,Zigbee的协议栈有点重,小项目不推荐。
  • Wi-Fi:ESP8266或ESP32。功耗高,但胜在直接连路由器。适合有电源的场景。

我个人习惯:小货架用BLE,大仓库用LoRa。为什么?BLE便宜、简单、手机就能调试。LoRa虽然贵一点,但一个网关能覆盖整个仓库,省了布线成本。

我记得有一次做冷链项目,客户要求货架间距50米,用BLE死活连不上。后来换成LoRa,一发入魂。嗯,选型这事,真不能拍脑袋。

2.2 软件分层架构设计

硬件选好了,接下来是软件。很多新手喜欢把所有代码写在一个main.c里,看着很爽,但后期维护起来……嗯,你懂的。

我建议采用三层架构

┌─────────────────────────────┐
│      应用层 (App Layer)       │
│  数据采集、上报策略、告警逻辑  │
├─────────────────────────────┤
│      中间层 (Middleware)      │
│  协议栈、数据缓存、任务调度    │
├─────────────────────────────┤
│      驱动层 (Driver Layer)    │
│  MCU外设、传感器驱动、无线驱动 │
└─────────────────────────────┘

2.2.1 驱动层——让硬件乖乖听话

驱动层是最底层的代码,直接操作寄存器或HAL库。这一层的原则是:只做一件事,做好一件事

比如一个温度传感器驱动,就只负责:

  • 初始化I2C接口
  • 发送读取命令
  • 解析返回数据
  • 返回温度值(单位:℃)

不要在这里做滤波、不要做阈值判断、不要做日志打印。那些是上层的事。

我写驱动有个习惯:每个驱动都提供一个Init()和一个Deinit()。Init里开时钟、配GPIO;Deinit里关时钟、拉低功耗。这样上层可以灵活控制外设的开关。

核心思想:驱动层只关心「怎么让硬件工作」,不关心「为什么要让它工作」。

2.2.2 中间层——承上启下的粘合剂

中间层是很多人容易忽略的部分。说白了,它负责:

  • 数据缓存:传感器数据采集后,先存到环形缓冲区,等无线模块空闲了再发。
  • 协议封装:把原始数据打包成JSON或自定义二进制协议。
  • 任务调度:什么时候采样、什么时候发送、什么时候休眠。

我建议在中间层实现一个简单的状态机。比如:

typedef enum {
    STATE_INIT,
    STATE_SENSOR_READ,
    STATE_DATA_PROCESS,
    STATE_WIRELESS_SEND,
    STATE_SLEEP
} SystemState_t;

每个状态只做一件事,做完就跳到下一个状态。这样代码逻辑清晰,调试也方便。我在项目中遇到过状态机跳转混乱导致死机的问题,后来加了一个状态超时保护,再也没出过事。

2.2.3 应用层——业务逻辑的舞台

应用层是离用户最近的一层。它决定:

  • 多久采集一次数据(5分钟?10分钟?)
  • 数据怎么上报(实时?定时?阈值触发?)
  • 什么情况下告警(温度超限?电量过低?)

这一层我建议用配置文件来驱动。比如:

// config.h
#define SAMPLE_INTERVAL_MS    60000   // 采样间隔:1分钟
#define SEND_INTERVAL_MS      300000  // 上报间隔:5分钟
#define TEMP_ALARM_HIGH       40.0f   // 高温告警阈值
#define BATTERY_LOW_THRESHOLD 10      // 低电量阈值(%)

为什么要用配置文件?因为客户的需求经常变。今天说5分钟上报一次,明天说改成10分钟。如果这些值硬编码在代码里,每次都要重新编译烧录。用配置文件,直接通过无线模块下发指令修改就行。

经验之谈:应用层的代码,尽量写成事件驱动。不要用while(1)死循环轮询,而是用定时器中断或外部中断触发。这样MCU大部分时间都在睡觉,功耗自然就低了。

2.3 本章小结

好了,这一章的内容就这些。总结一下:

  • 硬件选型:MCU选STM32L0系列,传感器按需选型,无线模块看距离选BLE或LoRa。
  • 软件分层:驱动层管硬件、中间层管调度、应用层管业务。层与层之间通过接口通信,不要跨层调用。

下一章,咱们开始画原理图,把今天选的这些芯片连起来。到时候我会详细讲电源设计——这可是低功耗系统的命门。

各位,先消化一下。有问题随时交流。