# STM8S003F3P6TR 蓝牙 Mesh 继电器固件设计 ## 1. 适用范围 本设计对应当前电路图中的单路交流通断器,功能包括: - 通过 JDY-28M 蓝牙模块接收 Mesh 控制指令; - 控制 PA1 输出,驱动 SS8050 和继电器线圈; - 通过 ACS712ELCTR-30A 连续采集负载电流; - 继电器吸合后在规定时间内无电流,生成“吸合无电流”故障; - 继电器断开后仍有电流,生成“断开有电流”故障; - 通过蓝牙返回状态、实时电流和故障码。 ## 2. 引脚连接确认 根据原理图重新核对后,ACS712 的 VIOUT 经 R3/R4/C2 滤波后连接到 STM8 的 `PC4`,用于电流 ADC 采样;`PC3_JDY-28M-STAT` 是 JDY-28M 的 STAT 状态信号,两者不是同一网络。因此,之前关于“ACS712 模拟输出与 JDY-28M 状态输出共用 PC3”的判断已撤销。 程序中应按以下方式配置: - `PC4`:模拟输入,连接 ACS712 电流检测滤波输出;禁止配置为推挽数字输出; - `PC3`:数字输入,用于读取 JDY-28M 状态;不要把它当作 ACS712 ADC 通道; - PC3 的有效电平已经由 JDY-28M 手册明确:MESH 模式下高电平表示入网成功,低电平表示尚未入网。 ## 3. 推荐软件接口 | 功能 | 原理图网络 | 固件用途 | |---|---|---| | 继电器驱动 | `PA1_relay` | 高电平吸合,低电平断开 | | 电流模拟量 | `PC4` | ADC 输入,连接 ACS712 滤波输出 | | 蓝牙状态 | `PC3_JDY-28M-STAT` | 数字输入,读取 JDY-28M 状态 | | 蓝牙接收 | `PD5_JDY-28M-RXD` | MCU UART TX,发送给 JDY-28M RXD | | 蓝牙发送 | `PD6_JDY-28M-TXD` | MCU UART RX,接收 JDY-28M TXD | | 调试下载 | `SWIM/NRST` | 仅用于 SWIM 调试和下载 | | 本地按键 | `SW1` | 短按切换,长按恢复出厂设置 | STM8S003F3 的 ADC 是 10 位,输入范围为 0 至 VDDA;UART1 可用于蓝牙串口通信。根据 ST 官方 STM8S003F3 数据手册 DS7147 Rev 10 的表 6,TSSOP20/UFQFPN20 封装的 PC4 标注为 `AIN2`,因此程序选择 ADC1 通道 2;PC4 仍必须配置为模拟输入,不能作为数字推挽输出。 ## 4. JDY-28M Mesh 使用方式 根据 JDY-28M V1.4 手册,本项目采用 `AT+ROLE2` 的 MESH 指令通信模式。该模式支持目标地址和 CMD 指令,通信数据带有模块定义的数据头,适合本项目的设备寻址、命令确认和故障上报。 JDY-28M 仍然只负责 Mesh 组网和无线转发,STM8 负责继电器、电流采样、故障判定和最终执行。不能让 JDY-28M 直接通过 OUT 引脚控制继电器,否则会绕过 STM8 的 ACS712 电流确认逻辑。 ### 4.1 上电自动确认 Mesh 指令模式 STM8 上电后必须先保持继电器断开,再初始化 JDY-28M。启动流程如下: ```text 上电 ↓ 继电器强制断开,启动 UART 接收环形缓冲区 ↓ 进入模块串口指令窗口,发送 AT+ROLE ↓ 收到 +ROLE=2? ── 是 ──→ 发送 AT+MADDR 查询短地址 │ 否 ↓ 发送 AT+ROLE2 ↓ 等待 +OK,发送 AT+RESET ↓ 等待模块重新启动,再次发送 AT+ROLE 验证 ↓ 收到 +MADDR=<短地址> ↓ 校验短地址并保存到运行期 RAM ↓ Mesh 初始化完成,允许继电器业务运行 ``` 程序要求: - `AT+ROLE` 返回值必须严格等于 `2`,不能只根据 `+OK` 判断成功; - 发送 `AT+ROLE2` 后应等待模块返回 `+OK`,再发送 `AT+RESET`,不要连续发送多条命令; - 模块复位期间继电器必须保持断开,UART 接收缓存应清空,避免把启动回显当作业务帧; - 复位后要重新查询并验证 `AT+ROLE`,不能假定设置命令已经持久化成功; - 只有成功收到并解析 `AT+MADDR` 返回的有效 2 字节短地址后,才允许把 Mesh 初始化标记为完成;短地址只保存在运行期 RAM 中,每次上电重新查询,不写入 EEPROM; - 如果连续重试仍无法确认模式或短地址,进入 `BT_INIT_FAULT`,继电器保持断开,并通过 LED/故障状态报告蓝牙初始化故障;Mesh 尚未组网本身不属于初始化故障,不强制断开继电器; - 短地址不写入 EEPROM,设备每次上电都从 JDY-28M 重新查询。 JDY-28M 手册说明,MESH 指令模式相关配置需要注意模块的指令/透传状态和 PWRC 管脚条件。实际硬件上应确认 `PC5_JDY-28M-PWRC` 的上电电平;如果模块未进入指令窗口,STM8 应先按手册要求控制 PWRC,再发送 `AT+ROLE`。 建议的初始化状态枚举如下: ```c typedef enum { BT_INIT_START = 0, /* 初始化开始,继电器仍保持断开 */ BT_INIT_QUERY_ROLE, /* 查询 JDY-28M 当前工作模式 */ BT_INIT_SET_ROLE, /* 当前模式不是 ROLE2,发送 AT+ROLE2 */ BT_INIT_RESET_WAIT, /* 等待模块复位并重新启动 */ BT_INIT_QUERY_ADDRESS, /* 发送 AT+MADDR 查询 Mesh 短地址 */ BT_INIT_SAVE_ADDRESS, /* 校验地址并保存到运行期 RAM */ BT_INIT_READY, /* 蓝牙初始化成功,允许进入业务状态 */ BT_INIT_FAULT /* 初始化失败,继电器保持断开 */ } BluetoothInitState; /* * 蓝牙模块初始化任务。 * 该任务必须采用超时和重试机制,不能使用长时间阻塞延时, * 否则会影响 ACS712 采样、看门狗服务和本地按键检测。 */ void Bluetooth_InitTask(void) { /* 只有收到明确的 +ROLE=2 和有效 +MADDR 响应后才进入 READY。 */ } ``` 短地址只保存在运行期 RAM 中。上电时必须重新执行 `AT+MADDR` 查询并校验,查询失败不能使用旧地址替代。 ### 4.2 LED3 蓝牙状态指示 LED3 由 STM8 的 `PD3` 控制,`PC3_JDY-28M-STAT` 用于读取 JDY-28M 的 Mesh 状态。蓝牙初始化完成后,程序需要区分“模块初始化成功”和“已经完成组网”两个状态,不能仅凭 `AT+ROLE2` 成功就认为已经入网。 LED3 显示规则如下: | 条件 | LED3 状态 | 说明 | |---|---|---| | 蓝牙模块初始化故障 | 300 ms 亮、300 ms 灭 | 最高优先级,表示 ROLE/RESET/MADDR 初始化失败 | | 初始化成功但尚未完成 Mesh 组网 | 1 s 亮、1 s 灭 | 表示模块正常,但当前没有完成组网 | | 已完成 Mesh 组网 | 常亮 | 表示 PC3 已确认模块处于组网状态 | 建议使用 1 ms 系统节拍实现 LED 状态机,不在主循环中使用阻塞延时。LED 状态优先级固定为: ```text BT_INIT_FAULT > BT_NOT_JOINED > BT_JOINED ``` JDY-28M 手册第 7 页对 STAT(第 6 脚)给出了明确规定:在 MESH 模式下,入网成功输出高电平,未入网输出低电平。因此原理图中的 `PC3_JDY-28M-STAT` 应按高有效处理: ```c /* JDY-28M 手册明确规定:MESH 入网成功时 STAT 输出高电平。 */ #define JDY_MESH_JOINED_LEVEL 1 /* * 更新 LED3 显示状态。 * - 初始化故障时以 300 ms 周期闪烁; * - 初始化成功但 PC3 未确认组网时以 1 s 周期闪烁; * - PC3 连续稳定确认已组网时保持常亮。 */ void BluetoothLed_Update(uint8_t init_fault, uint8_t init_ready, uint8_t mesh_status_level) { /* 具体 GPIO 翻转由 1 ms 定时任务执行,避免阻塞业务处理。 */ } ``` PC3 状态必须连续稳定确认至少 3 秒:连续 3 秒读取到高电平才切换为常亮;连续 3 秒读取到低电平才切换为 1 秒闪烁。模块的 ALED(第 17 脚)是 JDY-28M 自带的广播 LED 指示脚,不应与本项目由 STM8 PD3 控制的 LED3 混淆。 ### 4.3 量产配置 每个设备在产测或配网阶段配置一次,之后发送 `AT+RESET`: ```text AT+ROLE2 AT+BAUD4 AT+MADDR<设备两字节短地址> AT+NETID<四字节组网ID>,<十六进制参数> AT+MCLSSA0 AT+ZJEN1 AT+RESET ``` - `AT+BAUD4` 为 9600 baud,应与 STM8 UART 保持一致; - `AT+MADDR` 设置 Mesh 短地址,设备之间不能重复; - `AT+NETID` 设置网络 ID,同一网络必须一致,手册说明该参数设置后不能查询,因此必须保存生产记录; - `AT+MCLSSA0` 选择 A0 类型,适合 MESH 透传/指令通信与低功耗 IO 类设备; - `AT+ZJEN1` 开启 Mesh 中继能力,是否关闭应根据现场网络拓扑测试决定。 ### 4.4 MESH 指令与 STM8 应用层 在 `AT+ROLE2` 下,JDY-28M 使用目标短地址和 Mesh CMD 进行通信。手册第 29 页给出了 UART 发送和接收的完整示例。本项目使用其中的 Mesh 数据通信方式,把 STM8 业务帧作为 Mesh 数据区发送;不把业务帧中的 `0x55 0xAA` 误认为 JDY-28M 的无线帧头。 STM8 仍然需要对 UART 业务数据进行二次校验,不能把收到的任何 UART 字节直接当作继电器命令。由于当前使用的是 `AT+ROLE2` MESH 指令通信模式,目标短地址属于 JDY-28M 的发送帧字段,接收帧中还会携带来源短地址,因此不应在 STM8 业务载荷中重复添加。 ### 4.4.1 JDY-28M Mesh 外层帧 手册第 29 页的示例表明,JDY-28M 串口发送给模块的外层帧为: ```text 41 54 2B AA A1 | 目标短地址 2B | A0 | 业务数据 | 0D 0A ``` 其中: - `41 54 2B AA A1`:固定的 JDY-28M MESH 指令前缀,对应 ASCII/十六进制字符串 `41542BAAA1`; - 目标短地址:2 字节,例如 `FFFF` 表示广播,`000C` 表示发送到短地址 `000C`; - `A0`:手册示例中的 MESH 数据通信命令字节; - 业务数据:本项目的 STM8 业务帧,例如 `55 AA CMD LEN DATA CRC16`; - `0D 0A`:JDY-28M 指令结束符。 因此,主机或上位机发送给某个继电器节点的完整数据应类似: ```text 41 54 2B AA A1 00 0C A0 55 AA CMD LEN DATA CRC16 0D 0A ``` 手册给出的设备接收帧格式为: ```text F1 DD 09 00 0A | 源短地址 2B | 业务数据 | 0D 0A ``` 例如源地址为 `000C`、业务数据为 `1122334455` 时,接收格式为: ```text F1 DD 09 00 0A 00 0C 11 22 33 44 55 0D 0A ``` STM8 收到外层帧后,应先识别并剥离 `F1 DD 09 00 0A`、来源短地址和 `0D 0A`,再把中间的业务数据交给 `55 AA | CMD | LEN | DATA | CRC16` 解析器。手册第 29 页说明 MESH 数据长度支持最长 20 字节,因此本项目的业务帧总长度必须控制在该限制内。 因此,STM8 业务数据只保留以下应用层字段: ```text 帧头 0x55 0xAA | CMD | LEN | DATA | CRC16 ``` 字段定义: - `0x55 0xAA`:STM8 业务帧同步头; - `CMD`:需要执行或返回的命令; - `LEN`:DATA 字段的字节数; - `DATA`:命令参数或返回数据; - `CRC16`:从 `CMD` 开始计算到 DATA 结束的 CRC16,不包含帧头。 CRC16 固定采用 CRC-16/MODBUS,参数必须由主机和 STM8 完全一致地实现: - 多项式:标准表示为 `0x8005`,采用右移实现时使用 `0xA001`; - 初始值:`0xFFFF`; - 输入反转:是; - 输出反转:是; - CRC 字节顺序:低字节在前、高字节在后; - 计算范围:从 `CMD` 开始,到 DATA 结束,不包含 `0x55 0xAA` 帧头; - 不计算 JDY-28M 外层帧头、目标地址、`A0` 和 `0D 0A`。 固定测试向量: ```text 输入数据:01 01 01 CRC结果:0x4498 发送顺序:98 44 完整示例:55 AA 01 01 01 98 44 ``` ### 5.5 业务命令定义 | CMD | 名称 | 方向 | DATA 定义 | |---|---|---|---| | `0x01` | 继电器控制 | 主机→设备 | `0x00` 断开;`0x01` 吸合 | | `0x02` | 查询继电器状态 | 主机→设备/设备→主机 | 返回 `0x00` 断开;`0x01` 吸合 | | `0x03` | 读取电流数据 | 主机→设备/设备→主机 | 返回 2 字节实际电流值,单位 mA,低字节在前 | | `0x04` | 故障上报 | 设备→主机 | `0x00` 吸合但无电流;`0x01` 断开但有异常电流;`0x02` 采样异常;`0x04/0x06` 对应恢复 | | `0x05` | 设备短地址上报 | 设备→主机 | 返回 2 字节 Mesh 短地址 | | `0x06` | 配置电流阈值 | 主机→设备 | 2 字节无符号阈值,单位 mA,低字节在前 | ### 5.5.1 应答命令分配建议 采用“请求命令 + `0x80` = 应答命令”的规则: | 请求 CMD | 应答 CMD | 应答含义 | DATA | |---|---|---|---| | `0x01` | `0x81` | 继电器控制成功 | `0x00` 断开,`0x01` 吸合 | | `0x02` | `0x82` | 继电器状态返回 | `0x00` 断开,`0x01` 吸合 | | `0x03` | `0x83` | 电流数据返回 | 2 字节实际电流值,单位 mA,低字节在前 | | `0x04` | - | 故障/恢复主动上报 | 故障码,设备主动发送 | | `0x05` | `0x85` | 设备短地址返回 | 2 字节短地址,低字节在前 | | `0x06` | `0x86` | 电流阈值配置成功 | 2 字节当前阈值,单位 mA,低字节在前 | | `0x04` | `0x84` | 故障/恢复上报确认 | 1 字节,被确认的故障码 | 如果设备不能执行请求,使用统一错误应答 `CMD=0xE0`: ```text DATA[0]:错误码 0x01 = 设备未初始化完成 0x02 = 参数长度错误 0x03 = 参数值非法 0x04 = 当前状态不允许执行 0x05 = ROM 写入失败 0x06 = 业务命令不支持 ``` CRC 错误不发送 `0xE0`,直接丢弃,因为 CRC 错误时不能确认收到的命令内容。 广播请求同样需要应答。特别是广播 `CMD=0x05` 地址查询时,主机通过收集所有设备返回的 `0x85` 应答获得网络内的短地址列表。 为避免所有设备同时回复造成 Mesh 碰撞,广播地址查询应采用错峰应答: ```text response_delay_ms = 20 + (mesh_short_address % 16) * 20 ``` 设备收到广播地址查询后,不立即发送,而是在计算出的时间槽发送 `CMD=0x85`,DATA 为本机 2 字节短地址。主机应在足够的收集窗口内接收多个应答,并按短地址去重。 广播控制指令也返回 `0x81` 控制应答;为避免多个设备同时回复,广播控制应答同样采用基于短地址的错峰发送。单播指令不需要错峰,可以在执行后立即应答。 建议固定返回格式: ```text CMD=0x02, LEN=1, DATA=[RELAY_STATE] CMD=0x03, LEN=2, DATA=[CURRENT_L, CURRENT_H] CMD=0x05, LEN=2, DATA=[ADDR_L, ADDR_H] ``` `0x04` 故障上报建议定义为: ```text DATA[0]:故障码,0x00=继电器已吸合但没有电流输出,0x01=继电器已断开但仍存在异常电流,0x02=ACS712采样异常,0x04=电流故障恢复,0x06=采样异常恢复。蓝牙初始化异常不通过 Mesh 上报,只通过 LED3 指示。 ``` `CMD=0x03` 的电流数据是 STM8 根据 ACS712 采样值、零点偏置和校准系数计算出的实际电流,不是 ADC 原始值。数据类型为 16 位无符号整数,单位为 mA,低字节在前,并采用四舍五入: ```text 实际电流 1250 mA = 0x04E2 DATA = 0xE2 0x04 实际电流 500 mA = 0x01F4 DATA = 0xF4 0x01 ``` 该格式的最大表示值为 65535 mA,即 65.535 A,能够覆盖 ACS712ELCTR-30A 的量程。 例如,继电器吸合后检测不到电流时主动发送: ```text 55 AA 04 01 00 CRC16 ``` 其中 `CMD=0x04`,`LEN=0x01`,故障码为 `0x00`,表示继电器已吸合但没有电流输出。实际发送时应将末尾 `CRC16` 替换为计算结果。 JDY-28M 先按 MESH 外层帧完成目标地址处理和来源地址携带,STM8 再校验业务帧头、命令、长度和 CRC,然后执行命令。当前协议不设置业务层 SEQ;因此主机不应在未确认应答时盲目重发继电器控制帧,后续如需要可靠重发,应另行增加事务机制。 只有在未来存在“模块地址”和“业务逻辑地址”不一致的需求时,才在业务载荷中额外增加逻辑设备号;此时字段名称必须使用 `logical_device_id`,不能再命名为目标短地址或源短地址,以免与 JDY-28M 地址混淆。 ## 5. 设备进入可执行状态后的指令划分 只有完成以下条件后,设备才将 `device_ready` 置为 1,开始处理业务指令: 1. JDY-28M 已确认 `AT+ROLE=2`; 2. 已成功查询并校验 Mesh 短地址; 3. 已读取并保存 Mesh 状态;组网状态由 LED3 单独指示; 4. STM8 已完成 ACS712 零点初始化; 5. 继电器输出已经处于安全的断开状态。 未进入 `device_ready` 前,只允许处理初始化相关命令,不能执行远程继电器控制。初始化完成后,即使 Mesh 尚未组网,也不强制断开继电器;如果收到本地或后续有效业务控制,仍可按正常逻辑执行。 ### 5.1 指令一:询问设备短地址 主机发送“询问地址”业务指令后,STM8 不重新修改地址,只返回启动阶段通过 `AT+MADDR` 查询并保存的当前短地址。 ```text 请求方式:主机发送地址查询请求 应答命令:0x05 ADDRESS_REPORT 应答数据:设备短地址 2 bytes ``` 如果地址没有通过校验或蓝牙初始化尚未完成,应返回地址无效/设备未就绪错误,不能返回未校验的旧地址。 ### 5.1.1 指令六:配置电流阈值 主机发送 `CMD=0x06`、`LEN=2`,DATA 为低字节在前的 16 位无符号阈值,单位为 mA。STM8 校验通过后将阈值写入 ROM;后续上电时读取该值,读取失败或数据无效时使用默认值 100 mA。 ```text CMD=0x06, LEN=2, DATA=[THRESHOLD_L, THRESHOLD_H] ``` 阈值配置成功后,设备重新封装应答帧,使用专用的配置应答 CMD 并重新计算 CRC16,不能直接原样返回主机的 Mesh 外层帧。 ### 5.2 指令二:控制继电器吸合或断开 ```text 请求命令:0x01 RELAY_CONTROL 应答方式:返回当前继电器状态帧(CMD=0x02) ``` 处理流程: 1. 校验 JDY-28M 外层地址、业务命令长度和 CRC; 2. 判断设备是否 `device_ready`; 3. 设置继电器软件目标状态; 4. 立即控制 `PA1_relay` 输出,使继电器吸合或断开; 5. 重新封装一帧应答数据,使用专用的控制应答 CMD,重新计算业务 CRC16,并通过新的 JDY-28M 外层地址和帧头发送; 7. 继续由 ACS712 采样和故障状态机进行后续确认。 控制应答不需要等待电流确认。返回成功表示继电器控制动作已经发出,不表示负载电流已经符合预期。由于目前没有触点反馈,不单独判断继电器机械控制失败;后续异常统一由 ACS712 电流检测故障上报。 收到新的控制指令时,应立即更新目标状态,并重新启动对应的电流确认窗口。 ### 5.3 指令三:故障主动上报 故障不是主机查询后才返回,而是由 STM8 在电流确认窗口结束后主动通过 JDY-28M 上报: ```text 上报命令:0x04 FAULT_REPORT 故障码 DATA[0]=0x00:继电器吸合,但持续无有效电流 故障码 DATA[0]=0x01:继电器断开,但仍持续存在有效电流 故障码 DATA[0]=0x02:ACS712 采样异常 故障码 DATA[0]=0x04:电流故障恢复 故障码 DATA[0]=0x06:采样异常恢复 ``` 故障上报数据建议包含: ```text 设备短地址 | 故障码 | 继电器目标状态 | 当前电流值 ``` 上报规则: - 吸合后持续检测至少 10 s,电流始终低于 `I_ON_THRESHOLD`,主动上报 `0x00`; - 断开后持续检测至少 10 s,电流仍持续高于 `I_OFF_THRESHOLD`,主动上报 `0x01`; - ACS712 采样异常上报 `0x02`;蓝牙初始化异常无法通过 Mesh 上报,只通过 LED3 指示; - 后续连续检测恢复正常至少 10 s 时,清除对应故障并主动上报恢复码 `0x04` 或 `0x06`;蓝牙初始化故障无法通过 Mesh 上报,恢复后仅结束 LED3 故障闪烁; - 故障或恢复上报发送后,等待主机返回 `CMD=0x84` 确认; - 未收到确认时,每隔 10 s 重发一次相同的 `CMD=0x04` 上报帧; - 收到 `CMD=0x84` 且 DATA 与当前待确认故障码一致后,停止该事件的周期重发; - 重复收到的故障上报不得重复改变继电器状态,只需返回 `CMD=0x84`; - 故障上报不能改变当前继电器输出,除非产品需求明确要求保护性断开; - `0x04` 专用于设备主动故障/恢复上报,`0x84` 专用于主机确认。 ### 5.4 指令处理优先级 ```text 初始化故障保护 > 继电器控制指令 > 故障状态机 > 周期状态上报 ``` 如果设备处于蓝牙初始化故障,继电器必须保持断开;如果设备已经进入业务运行状态,继电器控制应答和故障主动上报分别走同步、异步两条路径。 ## 6. 状态模型 继电器控制状态不应直接等同于“负载已经工作”。建议保存以下状态: ```c typedef enum { RELAY_OFF = 0, /* 软件要求继电器断开 */ RELAY_ON = 1 /* 软件要求继电器吸合 */ } RelayCommandState; typedef enum { FAULT_NONE = 0x00, /* 无故障 */ FAULT_ON_NO_CURRENT = 0x01, /* 要求吸合,但确认窗口内无电流 */ FAULT_OFF_HAS_CURRENT = 0x02,/* 要求断开,但确认窗口内仍有电流 */ FAULT_CURRENT_SENSOR = 0x03 /* 采样异常或零点未校准 */ } FaultCode; ``` 建议故障状态采用“锁存 + 明确清除”:故障发生后继续上报,只有收到清除故障指令、重新执行一次有效控制,或设备重启并完成自检后才清除。是否允许自动清除,应由产品需求决定。 ## 7. ACS712 采样算法 ACS712 输出是以约 VCC/2 为零电流中心的模拟电压,30 A 型号的典型灵敏度约为 66 mV/A。不要用单次 ADC 值判断有无电流,应采用连续采样计算 RMS。 推荐参数: - ADC 采样频率:1 kHz 至 2 kHz; - RMS 窗口:至少 20 ms,推荐 100 ms; - 每个窗口先计算平均值作为零点/偏置; - 对每个采样值计算相对零点的平方和; - 使用整数或定点运算,避免 STM8 上使用浮点造成代码过大和执行时间不可控; - 上电后继电器保持断开,采集 200 ms 至 500 ms 的零点偏置; - 零点偏置只能在确认负载无电流时更新,不能在继电器吸合状态下随意跟踪。 计算关系为: ```text I_rms = sqrt(sum((ADC_i - ADC_zero)^2) / N) * Vref / (1023 * 0.066) ``` 实际项目中应使用已知标准电流进行两点或多点校准,得到 `CURRENT_SCALE` 和 `CURRENT_OFFSET`,不要直接把典型灵敏度当成最终精度。 ## 8. 故障判定时序 ### 6.1 吸合无电流 1. 收到 ON 指令; 2. 设置软件目标状态为 ON; 3. PA1 输出吸合电平; 4. 等待继电器机械动作时间,例如 100 ms; 5. 持续检测电流,确认窗口至少 10 s; 6. 若窗口内连续满足 `I_rms >= I_ON_THRESHOLD`,判定吸合成功; 7. 窗口结束仍无有效电流,生成 `FAULT_ON_NO_CURRENT`。 `I_ON_THRESHOLD` 支持动态配置,默认值为 100 mA;实际产品可根据最小负载电流、ACS712 噪声和现场校准结果调整。 ### 6.2 断开仍有电流 1. 收到 OFF 指令; 2. 设置软件目标状态为 OFF; 3. PA1 输出断开电平; 4. 等待触点释放时间,例如 100 ms; 5. 持续检测电流,确认窗口至少 10 s; 6. 若窗口内电流持续低于阈值,判定断开正常; 7. 若连续多个采样窗口仍满足 `I_rms >= I_OFF_THRESHOLD`,生成 `FAULT_OFF_HAS_CURRENT`。 `I_OFF_THRESHOLD` 应高于零点噪声。吸合和断开的电流阈值支持动态配置,默认值均为 100 mA。电流必须持续满足故障条件至少 10 s 才上报,不能根据单次采样或瞬时浪涌报错。 ## 9. 推荐主循环结构 ```c void App_MainLoop(void) { /* 读取 UART 环形缓冲区,将完整帧交给协议解析器。 */ Bluetooth_ProcessRxFrames(); /* 由 1 ms 定时节拍触发电流采样,不在主循环中使用阻塞延时。 */ CurrentSampler_ProcessPendingSamples(); /* 每完成一个 RMS 窗口,就更新当前电流和采样质量。 */ CurrentMonitor_ProcessCompletedWindow(); /* 根据继电器目标状态、延时和电流结果推进故障状态机。 */ RelayFaultMonitor_Run(); /* 周期性发送状态,不应阻塞继电器控制和 ADC 采样。 */ Bluetooth_ReportPeriodicStatusIfDue(); /* 防止程序跑飞;喂狗动作应放在确认主循环各任务正常执行之后。 */ IWDG_ServiceIfSystemHealthy(); } ``` ## 10. 建议蓝牙协议 正式量产使用前文定义的二进制帧: ```text 0x55 0xAA | CMD | LEN | DATA | CRC16 ``` Mesh 目标地址和源地址由 JDY-28M 的 MESH 指令帧承担,不放入 STM8 业务载荷。 ## 11. 关键异常处理 - 蓝牙帧 CRC 错误:丢弃并返回通信错误,不改变继电器状态; - LEN 超出协议允许范围:丢弃整帧,不执行继电器动作; - 上电:继电器默认断开,先完成 ADC 零点采集和自检;初始化完成后,Mesh 未组网不再强制改变继电器状态; - ACS712 输出超出 0 至 VDDA:记录传感器故障,禁止根据异常值自动闭合; - 采样窗口不足:不更新电流值,不进行故障判定; - MCU 看门狗复位:重启后保持继电器断开,并上报复位原因; - 故障状态下:可以继续发送实时电流,但不应静默覆盖原故障码。 ## 12. 推荐实现顺序 1. 复核 PC4 的 ADC 通道编号、PC3 的蓝牙状态有效电平以及 PCB 走线; 2. 单独验证 PA1-继电器吸合/断开极性; 3. 在继电器断开状态下验证 ACS712 零点和噪声; 4. 用已知负载校准电流换算; 5. 验证蓝牙 UART 收发和 Mesh 重发/去重; 6. 最后启用两类故障判定,并分别测试“空载吸合”和“触点粘连/外部旁路带电”场景。 该文档是固件设计和测试基线,不代表已经完成编译、下载、PCB 实测或市电安全认证。