第二章:系统架构设计——整体软件架构分层与模块划分
好,咱们进入第二章。这一章很关键,说白了就是给整个智能电表软件平台搭骨架。骨架搭不好,后面写再多代码也是白搭。我个人习惯是先想清楚分层,再谈模块,最后选通信协议。咱们一步步来。
2.1 整体软件架构分层
智能电表这东西,资源有限——RAM可能就几十KB,Flash也就几百KB。你不能像写服务器程序那样随便堆框架。所以分层要清晰,但层与层之间不能太厚。
我一般分三层:应用层、中间件层、驱动层。你想想看,这其实跟操作系统里的分层思想一脉相承。
| 分层 | 职责 | 典型内容 |
|---|---|---|
| 应用层 | 业务逻辑、用户交互 | 费率管理、数据上报、LCD显示、按键处理 |
| 中间件层 | 协议封装、数据管理、任务调度 | DL/T645协议栈、FreeRTOS、文件系统、加密库 |
| 驱动层 | 硬件抽象、寄存器操作 | GPIO、SPI、UART、ADC、计量芯片驱动 |
嗯,这里要注意:驱动层绝对不能直接暴露给应用层。我在项目中遇到过有人图省事,直接在应用层里写寄存器操作,结果换了个MCU型号,代码几乎重写。这就是分层没做好的代价。
2.2 模块划分——每个模块只干一件事
模块划分的原则很简单:高内聚、低耦合。说白了,每个模块只关心自己的事,别管别人怎么用。
我习惯把智能电表拆成以下几个核心模块:
- 计量模块:负责读取电能脉冲、计算有功/无功功率、累计电量。这块通常依赖专用计量芯片(比如RN8302、ADE7878),驱动层封装好读写接口,中间件层做数据校准和滤波。
- 费率管理模块:处理尖峰平谷时段切换、阶梯电价计算。这个模块纯逻辑,跟硬件无关,放在应用层最合适。
- 存储管理模块:管理EEPROM或Flash中的数据存储,包括参数配置、冻结数据、事件记录。我建议用中间件层封装一个“键值对存储”接口,上层只管读写,不用管具体存哪。
- 通信模块:负责RS485、红外、Wi-Fi或NB-IoT的数据收发。这个模块要同时处理物理层和协议层,所以横跨驱动层和中间件层。
- 显示与按键模块:驱动LCD段码屏或OLED,处理按键轮询。纯驱动层+应用层回调。
- 任务调度模块:基于FreeRTOS或裸机状态机,管理各任务的执行周期。比如计量任务每100ms执行一次,通信任务每500ms轮询一次。
避坑指南:我曾经在一个项目里把计量和通信写在同一个模块里,结果通信阻塞时计量数据丢了,导致电量累计出错。后来我强制要求:计量模块必须独立运行,优先级最高,不能被其他模块阻塞。
2.3 通信协议栈选型
智能电表的通信协议,国内基本绕不开DL/T645。这是国标,强制要求。但光有DL/T645还不够,你还要考虑物理层和上层应用协议。
我列一下常见的选型组合:
| 场景 | 物理层 | 数据链路层 | 应用层 |
|---|---|---|---|
| 本地抄表 | RS485 | DL/T645-2007 | DL/T645命令集 |
| 远程无线 | NB-IoT / 4G | TCP/UDP + CoAP | DL/T645 over CoAP |
| 红外通信 | 红外光电头 | DL/T645(波特率1200) | DL/T645命令集 |
| Wi-Fi(智能家居) | Wi-Fi | MQTT | 自定义JSON + DL/T645映射 |
为什么会这样选?因为DL/T645在RS485上效率很高,但到了TCP/IP网络里,直接裸传DL/T645帧会出问题——没有会话管理、没有重传机制。所以我在NB-IoT方案里,会在DL/T645外面再包一层CoAP,既保留了原有协议语义,又解决了可靠传输问题。
个人经验:如果你做的是出口电表,那DL/T645就不适用了。国外常用IEC 62056(DLMS/COSEM)或Modbus。我建议你在中间件层做一个协议适配器,把计量数据抽象成统一接口,换协议时只改适配器,不动上层业务逻辑。
2.4 架构图(文字描述)
这里我不画图,但你可以想象一个三层结构:
+-------------------------------------------+
| 应用层 |
| 费率管理 数据上报 事件记录 LCD显示 |
+-------------------------------------------+
| 中间件层 |
| DL/T645协议栈 FreeRTOS 文件系统 加密库 |
| 键值对存储 任务调度 协议适配器 |
+-------------------------------------------+
| 驱动层 |
| GPIO SPI UART ADC 计量芯片驱动 LCD驱动|
+-------------------------------------------+
| 硬件层 |
| MCU 计量芯片 EEPROM LCD RS485 NB-IoT |
+-------------------------------------------+
嗯,这个结构我用了好几年,从8位MCU到ARM Cortex-M4都跑过。核心思想就是:驱动层只管硬件,中间件层只管数据,应用层只管业务。谁也别越界。
2.5 本章小结
这一章我们聊了三件事:
- 软件分三层:应用层、中间件层、驱动层,层间接口要稳定
- 模块划分要独立,计量模块优先级最高
- 通信协议选型要因地制宜,DL/T645是主流,但别忘了协议适配
下一章我会带你手写驱动层代码,从GPIO和UART开始。到时候咱们再细聊寄存器操作的那些坑。
警告:不要试图在架构阶段把所有细节都定死。留一些扩展点,比如协议适配器接口、存储模块的抽象层。否则后期需求一变,你会想砸键盘的——我砸过,真的。