Files
STM8_Mesh_Control/CODEX_FIRMWARE_HANDOFF.md
T

368 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# STM8S003F3P6TR 蓝牙 Mesh 继电器固件开发交接文档
## 1. 文档目的
本文件供后续 Codex 固件开发任务使用。开发人员必须以本文件和 `PROGRAM_DESIGN.md` 为当前设计基线,不得擅自修改已经确认的通信协议、故障码和安全策略。
当前阶段只完成了固件设计,尚未创建 STM8 工程、尚未编译、尚未烧录,也尚未进行实物或市电测试。
## 2. 目标功能
固件运行于 `STM8S003F3P6TR`,通过 `JDY-28M` 的 Mesh 指令模式实现:
- 单路继电器吸合/断开控制;
- Mesh 短地址查询和广播发现;
- ACS712ELCTR-30A 实际电流计算;
- 吸合无电流、断开有电流故障检测;
- 故障恢复主动上报;
- 蓝牙初始化和 Mesh 组网 LED 指示;
- 电流阈值运行期配置并保存到 ROM。
## 3. 已确认硬件连接
| 功能 | MCU/网络 | 固定要求 |
|---|---|---|
| 继电器控制 | `PA1_relay` | `PA1=1` 吸合,`PA1=0` 断开 |
| ACS712 电流 ADC | `PC4` | 模拟输入,计算实际电流,不使用 ADC 原始值直接上报 |
| JDY-28M Mesh 状态 | `PC3_JDY-28M-STAT` | 高电平表示已入网,低电平表示未入网 |
| 蓝牙状态/故障灯 | `PB5` | 低电平点亮 |
| 继电器状态灯 | `PD3` | 高电平点亮,吸合常亮、断开熄灭 |
| JDY-28M UART TX | `PD5_JDY-28M-RXD` | MCU TX 连接模块 RXD |
| JDY-28M UART RX | `PD6_JDY-28M-TXD` | MCU RX 连接模块 TXD |
| 下载调试 | `SWIM/NRST` | 用于 SWIM 下载和调试 |
JDY-28M 运行模式必须是 `AT+ROLE2`,即 MESH 指令通信模式。
## 4. 上电初始化流程
上电后先将继电器设置为断开,然后按以下状态机执行:
```text
初始化 GPIO、UART、定时器、ADC、看门狗
→ PA1_relay=0
→ 查询 AT+ROLE
→ 如果不是 ROLE2,发送 AT+ROLE2
→ 等待 +OK
→ 发送 AT+RESET
→ 等待模块重启
→ 再次查询 AT+ROLE
→ 发送 AT+MADDR
→ 解析 2 字节短地址并保存到运行期 RAM
→ 初始化 ACS712 零点
→ 进入业务运行态
```
要求:
- 短地址不写 EEPROM/ROM,每次上电都从 JDY-28M 重新查询;
- `AT+ROLE2`、`AT+MADDR` 必须有超时和有限次数重试;
- 初始化失败时继电器保持断开;
- 初始化失败不能通过 Mesh 上报,因为 Mesh 通信本身不可用;
- 初始化失败由 PB5 蓝牙状态/故障灯以亮灭各 300 ms 指示;
- Mesh 未组网不是初始化故障,不因为 PC3 为低电平而强制断开继电器;
- PC3 必须连续稳定确认至少 3 秒后,才认为组网状态发生变化。
## 5. 蓝牙状态/故障灯指示规则
状态优先级:
```text
蓝牙初始化故障 > 未组网 > 已组网
```
| 状态 | PB5蓝牙状态/故障灯 |
|---|---|
| 蓝牙初始化故障 | 亮 300 ms、灭 300 ms |
| 初始化完成但未组网 | 亮 1 s、灭 1 s |
| 已完成 Mesh 组网 | 常亮 |
JDY-28M 的 STAT 依据模块手册第 7 页:MESH 模式下高电平表示入网成功,低电平表示未入网。
## 6. JDY-28M 外层 Mesh 帧
手册第 29 页给出了外层格式。
### 6.1 STM8/主机发送给模块
```text
41 54 2B AA A1 | 目标短地址 2B | A0 | 业务数据 | 0D 0A
```
- `41 54 2B AA A1`:固定 Mesh 指令头;
- 目标地址:2 字节;
- `FFFF`:广播;
- `A0`:固定 Mesh 数据通信标志;
- `0D 0A`:蓝牙帧结束符。
### 6.2 模块转发给 STM8
```text
F1 DD 08/09/0A | 源短地址 2B | 目标短地址 2B | 业务数据 | 0A
```
- `F1 DD 08/09/0A`:根据当前实测,第三字节可能随模块固件或转发路径变化;
- 源短地址:2 字节;
- 目标短地址:2 字节;
- 业务数据:STM8 自定义业务帧;
- `0A`:实测帧尾,部分串口工具可能同时显示前置`0D`。
广播和单播格式相同,仅目标地址不同。整个 JDY-28M 外层数据包最大 20 字节。
## 7. STM8 业务帧
```text
CMD | LEN | DATA | CRC16_H | CRC16_L
```
- `CMD`:命令码;
- `LEN`:DATA 长度;
- `DATA`:命令数据;
- `CRC16`:CRC-16/MODBUS。
CRC-16/MODBUS 固定参数:
- 初始值:`0xFFFF`;
- 右移实现多项式:`0xA001`;
- 输入、输出反转;
- CRC 高字节在前,低字节在后;
- 计算范围:从 `CMD` 到 DATA;
- 不计算 JDY-28M 外层帧字段。
测试向量:
```text
输入:01 01 01
CRC:0x4498
发送:98 44
完整业务帧:55 AA 01 01 01 98 44
```
## 8. 业务命令和应答
采用“请求 CMD + `0x80` = 应答 CMD”:
| CMD | 含义 | DATA |
|---|---|---|
| `0x01` | 控制继电器 | `0x00` 断开,`0x01` 吸合 |
| `0x02` | 查询继电器状态 | 请求 DATA 为空,返回状态 |
| `0x03` | 读取电流 | 请求 DATA 为空,返回 2 字节电流 |
| `0x04` | 故障/恢复主动上报 | 1 字节故障码 |
| `0x05` | 查询/上报短地址 | 返回 2 字节短地址 |
| `0x06` | 配置电流阈值 | 2 字节阈值,低字节在前,单位 mA |
| `0x81` | 继电器控制成功应答 | 当前继电器状态 |
| `0x82` | 继电器状态应答 | `0x00/0x01` |
| `0x83` | 电流数据应答 | 2 字节实际电流 |
| `0x85` | 短地址应答 | 2 字节短地址 |
| `0x86` | 阈值配置成功应答 | 2 字节当前阈值 |
| `0x84` | 故障/恢复上报确认 | 1 字节,被确认的故障码 |
| `0xE0` | 通用错误应答 | 1 字节错误码 |
### 8.1 控制应答
`CMD=0x01` 收到后,STM8 控制 PA1,并重新封装应答帧,使用 `CMD=0x81`,重新计算 CRC16,通过新的 JDY-28M 外层帧发送。不能直接原样返回主机原始 Mesh 帧。
控制应答只表示 STM8 已接受并发出了继电器控制动作,不表示负载电流已经正常。当前没有触点反馈,不单独实现继电器机械动作失败检测。
### 8.2 广播应答
广播地址查询和广播控制都需要应答:
```text
delay_ms = 20 + (mesh_short_address % 16) * 20
```
单播应答可以立即发送;广播应答使用短地址计算错峰时间,避免多个设备同时发送。
## 9. 电流采样和阈值
ACS712ELCTR-30A 由 5 V 供电,典型灵敏度约为 66 mV/A,零电流输出约为 VCC/2。原理图中 ACS712 的 VIOUT 经过 R3=10K、R4=10K 分压后接入 STM8 `PC4`,因此 ADC 输入电压约为 ACS712 VIOUT 的一半。
### 9.1 ADC 到电流的计算
假定 STM8 ADC 参考电压为 3.3 V、ADC 为 10 位:
```text
V_ADC = ADC_CODE × 3.3 / 1023
V_ACS = V_ADC × 2
```
不能直接固定使用 2.5 V 零点,必须使用上电校准得到的 `ADC_ZERO`:
```text
I_A = (ADC_CODE - ADC_ZERO) × 3.3 × 2 / (1023 × 0.066)
I_mA = (ADC_CODE - ADC_ZERO) × 3.3 × 2 × 1000 / (1023 × 0.066)
```
理论上约为:
```text
I_mA ≈ (ADC_CODE - ADC_ZERO) × 97.7
```
该比例只能作为初始值,正式程序应通过标准负载校准 `current_scale`,因为器件存在零点、灵敏度、温度和噪声误差。
### 9.2 上电零点校准
上电时继电器保持断开并确认负载没有电流,连续采集 200 ms 至 500 ms 的 ADC 样本并求平均:
```text
ADC_ZERO = sum(ADC_SAMPLE[0..N-1]) / N
```
零点校准期间不能让负载通电,否则后续所有电流值都会产生偏移。
### 9.3 交流 RMS 计算
交流负载不能通过单次 ADC 值判断,必须先减去零点并计算 RMS:
```text
adc_delta = ADC_CODE - ADC_ZERO
ADC_RMS = sqrt(sum(adc_delta × adc_delta) / SAMPLE_COUNT)
I_RMS_mA = ADC_RMS × current_scale
```
建议 ADC 采样频率为 1 kHz 至 2 kHz,RMS 窗口使用 100 ms。实时采样路径使用整数或定点运算,不使用浮点运算。
初始定点换算可以写成:
```c
/*
* 根据 ADC RMS 值计算实际电流,返回单位为 mA。
* 6600 表示 3.3 V × 1000,2 表示 ACS712 输出经过 1:1 分压,
* 1023 是 10 位 ADC 满量程,66 表示 66 mV/A 的典型灵敏度。
*/
current_mA = adc_rms * 6600UL * 2UL / (1023UL * 66UL);
```
### 9.4 电流输出和阈值
- 上报的是计算后的实际电流,不是 ADC 原始值;
- 电流类型为 16 位无符号整数;
- 单位为 mA;
- 低字节在前;
- 采用四舍五入;
- 超过 65535 mA 视为超出 ACS712ELCTR-30A 设计范围;
- 默认电流阈值为 100 mA;
- `CMD=0x06` 可动态修改阈值;
- 阈值写入 ROM;
- 上电读取阈值失败或值无效时使用默认值 100 mA;
- 吸合无电流、断开有电流以及对应恢复都必须连续确认至少 10 秒。
## 10. 故障和恢复
| 故障码 | 含义 |
|---|---|
| `0x00` | 继电器吸合后持续无有效电流 |
| `0x01` | 继电器断开后仍持续存在电流 |
| `0x02` | ACS712 采样异常 |
| `0x04` | 电流故障恢复 |
| `0x06` | 采样异常恢复 |
故障产生和恢复均需连续确认至少 10 秒:
- 吸合后持续无有效电流 10 秒,上报 `0x00`;
- 断开后持续有电流 10 秒,上报 `0x01`;
- 电流故障恢复正常 10 秒,上报 `0x04`;
- 采样异常恢复正常 10 秒,上报 `0x06`。
故障或恢复事件需要主机确认:
- 设备发送 `CMD=0x04` 后等待主机返回 `CMD=0x84`;
- `CMD=0x84` 的 DATA 为被确认的故障码;
- 未收到确认时,每隔 10 秒重发相同的故障或恢复上报帧;
- 收到匹配的 `0x84` 确认后,停止该事件的周期重发;
- 重复收到同一故障上报时,不重复改变继电器状态,只返回 `0x84`;
- 蓝牙初始化故障不能通过 Mesh 上报,只通过 PB5 指示。
蓝牙初始化异常使用 PB5 指示,不通过 Mesh 上报。
## 11. 错误处理
- CRC 错误:直接丢弃,不执行命令,不返回错误帧;
- 长度错误:返回 `CMD=0xE0`,错误码 `0x02`;
- 参数非法:返回 `CMD=0xE0`,错误码 `0x03`;
- ROM 写入失败:返回 `CMD=0xE0`,错误码 `0x05`;
- 未完成初始化:返回 `CMD=0xE0`,错误码 `0x01`;
- 看门狗复位后继电器默认断开。
## 12. 推荐代码分层
```text
drivers/
gpio.c GPIO 配置和读写
timer.c 1 ms 系统节拍
uart1.c UART 中断和环形缓冲区
adc.c PC4 ADC 采样
eeprom.c 阈值 ROM 读写
watchdog.c 独立看门狗
protocol/
crc16_modbus.c
mesh_frame.c
business_frame.c
services/
bluetooth_init.c
relay_service.c
current_service.c
fault_service.c
led_service.c
```
所有新增函数、结构体、枚举、字段和复杂逻辑必须使用详细中文注释。主循环不得使用长时间阻塞延时,蓝牙初始化、LED 闪烁、电流确认和故障恢复都应使用状态机和 1 ms 系统节拍。
## 13. 分阶段实施要求
### 阶段一:工程和底层
完成 STM8 工程、GPIO、定时器、UART 环形缓冲区、ADC、ROM 和看门狗。要求能够编译通过。
### 阶段二:协议
完成 CRC-16/MODBUS、JDY-28M 外层帧解析、业务帧解析和错误处理。使用串口数据模拟测试,不接市电。
### 阶段三:蓝牙初始化
完成 `AT+ROLE`、`AT+ROLE2`、`AT+RESET`、`AT+MADDR` 状态机以及 PB5 状态指示。
### 阶段四:继电器业务
完成 `0x01` 至 `0x06` 命令、单播/广播应答和阈值 ROM 保存。
### 阶段五:ACS712 和故障
完成零点校准、RMS、电流换算、10 秒故障确认和 10 秒恢复确认。
未得到用户确认前,不自动跨阶段继续实现下一阶段。
## 14. 固定开发和烧录工具
- 编辑器:VS Code;
- 编译器:SDCC;
- 构建工具:Make;
- 烧录/在线调试工具:ST-LINK V2;
- 调试接口:SWIM,连接 STM8 的 SWIM/NRST/VCC/GND;
- 不以 STVD 工程作为主工程格式,主工程以可命令行执行的 Makefile 为准。
固件交付前至少需要完成:
```text
make clean
make
生成 .ihx/.hex 文件
使用 ST-LINK V2/SWIM 烧录
```
## 15. 当前未授权假设
以下内容必须在实现前明确或以配置宏形式保留:
- STM8 编译器和工程模板;
- PC4 对应的具体 ADC 通道编号;
- JDY-28M UART 的最终波特率;
- 外层 Mesh 20 字节限制在模块实际固件中的精确统计范围;
- 控制成功和阈值配置成功应答的具体 Mesh 发送目标地址;
- ROM 写入接口的具体芯片库实现。
不得把以上未确认内容硬编码成无法修改的业务逻辑。