Files
STM8_Mesh_Control/CODEX_FIRMWARE_HANDOFF.md
T

12 KiB
Raw Blame History

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. 上电初始化流程

上电后先将继电器设置为断开,然后按以下状态机执行:

初始化 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. 蓝牙状态/故障灯指示规则

状态优先级:

蓝牙初始化故障 > 未组网 > 已组网
状态 PB5蓝牙状态/故障灯
蓝牙初始化故障 亮 300 ms、灭 300 ms
初始化完成但未组网 亮 1 s、灭 1 s
已完成 Mesh 组网 常亮

JDY-28M 的 STAT 依据模块手册第 7 页:MESH 模式下高电平表示入网成功,低电平表示未入网。

6. JDY-28M 外层 Mesh 帧

手册第 29 页给出了外层格式。

6.1 STM8/主机发送给模块

41 54 2B AA A1 | 目标短地址 2B | A0 | 业务数据 | 0D 0A
  • 41 54 2B AA A1:固定 Mesh 指令头;
  • 目标地址:2 字节;
  • FFFF:广播;
  • A0:固定 Mesh 数据通信标志;
  • 0D 0A:蓝牙帧结束符。

6.2 模块转发给 STM8

F1 DD 08/09/0A | 源短地址 2B | 目标短地址 2B | 业务数据 | 0A
  • F1 DD 08/09/0A:根据当前实测,第三字节可能随模块固件或转发路径变化;
  • 源短地址:2 字节;
  • 目标短地址:2 字节;
  • 业务数据:STM8 自定义业务帧;
  • 0A:实测帧尾,部分串口工具可能同时显示前置0D。

广播和单播格式相同,仅目标地址不同。整个 JDY-28M 外层数据包最大 20 字节。

7. STM8 业务帧

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 外层帧字段。

测试向量:

输入: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 广播应答

广播地址查询和广播控制都需要应答:

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 位:

V_ADC = ADC_CODE × 3.3 / 1023
V_ACS = V_ADC × 2

不能直接固定使用 2.5 V 零点,必须使用上电校准得到的 ADC_ZERO:

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)

理论上约为:

I_mA ≈ (ADC_CODE - ADC_ZERO) × 97.7

该比例只能作为初始值,正式程序应通过标准负载校准 current_scale,因为器件存在零点、灵敏度、温度和噪声误差。

9.2 上电零点校准

上电时继电器保持断开并确认负载没有电流,连续采集 200 ms 至 500 ms 的 ADC 样本并求平均:

ADC_ZERO = sum(ADC_SAMPLE[0..N-1]) / N

零点校准期间不能让负载通电,否则后续所有电流值都会产生偏移。

9.3 交流 RMS 计算

交流负载不能通过单次 ADC 值判断,必须先减去零点并计算 RMS:

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。实时采样路径使用整数或定点运算,不使用浮点运算。

初始定点换算可以写成:

/*
 * 根据 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. 推荐代码分层

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 为准。

固件交付前至少需要完成:

make clean
make
生成 .ihx/.hex 文件
使用 ST-LINK V2/SWIM 烧录

15. 当前未授权假设

以下内容必须在实现前明确或以配置宏形式保留:

  • STM8 编译器和工程模板;
  • PC4 对应的具体 ADC 通道编号;
  • JDY-28M UART 的最终波特率;
  • 外层 Mesh 20 字节限制在模块实际固件中的精确统计范围;
  • 控制成功和阈值配置成功应答的具体 Mesh 发送目标地址;
  • ROM 写入接口的具体芯片库实现。

不得把以上未确认内容硬编码成无法修改的业务逻辑。