367 lines
12 KiB
Markdown
367 lines
12 KiB
Markdown
# 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. 上电初始化流程
|
||
|
||
上电后先将继电器设置为断开,然后按以下状态机执行:
|
||
|
||
```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 通信本身不可用;
|
||
- 初始化失败由 LED3 以亮灭各 300 ms 指示;
|
||
- Mesh 未组网不是初始化故障,不因为 PC3 为低电平而强制断开继电器;
|
||
- PC3 必须连续稳定确认至少 3 秒后,才认为组网状态发生变化。
|
||
|
||
## 5. LED3 指示规则
|
||
|
||
状态优先级:
|
||
|
||
```text
|
||
蓝牙初始化故障 > 未组网 > 已组网
|
||
```
|
||
|
||
| 状态 | LED3 |
|
||
|---|---|
|
||
| 蓝牙初始化故障 | 亮 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 09 00 0A | 源短地址 2B | 业务数据 | 0D 0A
|
||
```
|
||
|
||
- `F1 DD 09 00 0A`:固定接收帧头;
|
||
- 源短地址:2 字节;
|
||
- 业务数据:STM8 自定义业务帧;
|
||
- `0D 0A`:蓝牙帧结束符。
|
||
|
||
广播和单播格式相同,仅目标地址不同。整个 JDY-28M 外层数据包最大 20 字节。
|
||
|
||
## 7. STM8 业务帧
|
||
|
||
```text
|
||
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 外层帧字段。
|
||
|
||
测试向量:
|
||
|
||
```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 上报,只通过 LED3 指示。
|
||
|
||
蓝牙初始化异常使用 LED3 指示,不通过 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` 状态机以及 LED3 状态指示。
|
||
|
||
### 阶段四:继电器业务
|
||
|
||
完成 `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 写入接口的具体芯片库实现。
|
||
|
||
不得把以上未确认内容硬编码成无法修改的业务逻辑。
|