# 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 写入接口的具体芯片库实现。 不得把以上未确认内容硬编码成无法修改的业务逻辑。