12 KiB
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 |
高电平表示已入网,低电平表示未入网 |
| LED3 | 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 通信本身不可用;
- 初始化失败由 LED3 以亮灭各 300 ms 指示;
- Mesh 未组网不是初始化故障,不因为 PC3 为低电平而强制断开继电器;
- PC3 必须连续稳定确认至少 3 秒后,才认为组网状态发生变化。
5. LED3 指示规则
状态优先级:
蓝牙初始化故障 > 未组网 > 已组网
| 状态 | LED3 |
|---|---|
| 蓝牙初始化故障 | 亮 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 09 00 0A | 源短地址 2B | 业务数据 | 0D 0A
F1 DD 09 00 0A:固定接收帧头;- 源短地址:2 字节;
- 业务数据:STM8 自定义业务帧;
0D 0A:蓝牙帧结束符。
广播和单播格式相同,仅目标地址不同。整个 JDY-28M 外层数据包最大 20 字节。
7. STM8 业务帧
0x55 0xAA | CMD | LEN | DATA | CRC16
0x55 0xAA:业务帧头;CMD:命令码;LEN:DATA 长度;DATA:命令数据;CRC16:CRC-16/MODBUS。
CRC-16/MODBUS 固定参数:
- 初始值:
0xFFFF; - 右移实现多项式:
0xA001; - 输入、输出反转;
- CRC 低字节在前;
- 计算范围:从
CMD到 DATA,不包含0x55 0xAA; - 不计算 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 上报,只通过 LED3 指示。
蓝牙初始化异常使用 LED3 指示,不通过 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 状态机以及 LED3 状态指示。
阶段四:继电器业务
完成 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 写入接口的具体芯片库实现。
不得把以上未确认内容硬编码成无法修改的业务逻辑。