Files
DLD154Pro/docs/devlog.md
T

598 lines
24 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# DLD154Pro 开发日志
> MCU: CH591R (RISC-V, BLE) @60MHz | 线圈通道: 1路 | 调试口: RS485 / BLE
---
## 2026-07-30 — Modbus RTU V1.6 私有协议编码实现
### 背景
根据 `docs/rs485-modbus-protocol.md` V1.6 规范,实现完整 Modbus RTU 从机协议(含主动上报私有扩展)。
与 700BS 协议共享 UART0 物理层,通过 `g_fm_700bs_disable` 互斥切换。
### 新增文件
| 文件 | 行数 | 说明 |
|------|------|------|
| `APP/include/rs485_modbus.h` | 52 | API + 协议常量宏 (MB_IR_FULL_BLOCK_START/COUNT, MB_HR_AUTO_RPT_ENABLE/ACTIVE_THRESHOLD, 上报间隔) |
| `APP/rs485_modbus.c` | 815 | 完整 Modbus 实现: CRC16 查表 + 6 个 FC 处理函数 + 全数据块组装 + 主动上报调度 + 车间距/通过时间测量 |
### 实现的功能码
| FC | 功能 | 关键细节 |
|----|------|---------|
| 0x02 | 读离散输入 | 9-bit 位图, GPIOB_ReadPortPin 直读光耦 |
| 0x03 | 读保持寄存器 | 含 HR 0x0010(主动上报使能) 和 0x0011(活动阈值) |
| 0x04 | 读输入寄存器 | 基础 IR 0x00000x000C + 全数据块 0x01000x0112 (19 reg = 38B) |
| 0x06 | 写单寄存器 | 值域校验 + 只读拦截 + 连锁写入: Fusion Mode→direction_mode, Hold Time→g_hold_time, Freq Level→loopFreq_Level |
| 0x10 | 批量写寄存器 | 逐寄存器同 FC 0x06 逻辑 |
| 0x11 | Report Slave ID | "DLD154Pro\0" + loop1_LOOP_OK 状态 |
### 全数据块 (0x01000x0112)
```
灵敏度 | 频率档 | 融合模式 | car_state | 线圈状态(bit0=断开/bit1=稳定) | 光耦状态
频率Hz(32b) | CAPVD(32b) | Variation(32b signed)
断开累计(32b) | 继电器吸合累计(32b)
Time Type(0=间隙/1=通过/0xFFFF=无效) | 时间值10ms(32b)
```
- Variation = `loop1_CAPVD loop1_Origin`,实时计算
- 频率 = `FREQ_SYS * LPCNT / CAPVD + 360`,与 700BS 一致
- 光耦 = `GPIOB_ReadPortPin(Pin_10) == 0`,直读硬件
### 主动上报 3 级速率调度
| 状态 | 条件 | 间隔 | 迟滞 |
|------|------|------|------|
| 事件 | 继电器翻转 (relay1_state 边沿) | 立即 | — |
| 活动 | \|Variation\| ≥ 阈值 (HR 0x0011, 默认 10) | 150ms (30 tick) | — |
| 空闲 | \|Variation\| < 阈值 | 800ms (160 tick) | 连续 2 次低于阈值才降速 |
- 帧格式复用 FC 0x04 响应,与轮询完全一致
- 上报前先调 `update_misc_time()` 更新 gap/pass time
### 车间距 / 通过时间
- 单位: 10ms (`mstick()/2`)
- 继电器 0→1 吸合沿 → `_misc_time_value = now _last_relay_off_10ms`, `_misc_time_type = 0`
- 继电器 1→0 释放沿 → `_misc_time_value = now _last_relay_on_10ms`, `_misc_time_type = 1`
- `_relay_engage_cnt` 在每次吸合沿递增 (全数据块 0x010E0x010F)
### 改造现有文件
| 文件 | 变更 |
|------|------|
| `rs485_700bs.h` | +`rs485_send()` 声明; +`extern _rx_buf/_rx_len/_rx_last_tick` |
| `rs485_700bs.c` | `_rx_buf`/`_rx_len`/`_rx_last_tick``static`; `rs485_send``static` |
| `peripheral_main.c` | +`#include "rs485_modbus.h"`; `gpio_uart_init``modbus_init()`; `Main_Circulation``g_fm_700bs_disable` 分派 700BS/Modbus |
### 关键设计决策
- **与 700BS 共享 ISR**: 不创建第二个 UART0_IRQHandlerModbus 从共享 `_rx_buf` 读取
- **帧超时判定**: `mstick() _rx_last_tick ≥ 2` (10ms), 对齐 9600 的 t3.5≈4ms
- **写穿透**: Holding Register 写入后立即同步到 RAM 全局变量,不等待 flash 持久化 (flash 写入由调用方处理)
- **CRC 错误静默**: 符合 Modbus 标准——CRC 不匹配时不回应
### 影响
- RS485 物理层零改动,Modbus/700BS 通过 BLE 小程序切换
- 主动上报默认关闭 (`_auto_rpt_enable = 0`),需通过 HR 0x0010 使能
- Holding Register 写操作不写 flash,若需持久化需额外调用 `write_cfg_to_store`
---
## 2026-07-30 — 输出融合模式枚举再次重排:地感且光耦后移
### 变更
将「地感且光耦」从值 1 移到值 3(排到后面),混行/ETC 前移:
```
旧 (V1.4): 0=或 1=且 2=混行 3=ETC 4=仅地感 5=仅光耦 6=复位
新 (V1.5): 0=或 1=混行 2=ETC 3=且 4=仅地感 5=仅光耦 6=复位
```
### 涉及文件
| 文件 | 变更 |
|------|------|
| `storage.h` | `DLD_OUTPUT_MODE` 枚举顺序:AND_RADAR 从 line 2 移至 line 4 |
| `peripheral_main.c` | 注释块 MODE N 标签 + 内联模式号 (0/1/5→0/3/5, 2/3→1/2) |
| `docs/technical-spec.md` | §6.1 融合模式表重排; §6.2/6.3 标题模式号更新; §7.2 LED 行改写为非数字区间 |
| `docs/product-manual.md` | §4.6 融合模式表重排 + 默认值 1→4 (仅地感); 模式号引用更新 |
| `docs/rs485-modbus-protocol.md` | §6.5 融合模式表重排 + 状态机标题模式号更新; V1.4→V1.5 |
| `docs/devlog.md` | 本条目 |
### 影响
- 代码全用符号名,无行为影响
- 已有 flash 配置的 `fusion_mode` 旧值语义与新模式不兼容,需重新设置
---
## 2026-07-29 — 输出融合模式枚举重排
### 变更
枚举值重新分配,将高频使用的融合模式前置:
```
旧: 0=复位 1=仅地感 2=仅光耦 3=或 4=且 5=混行 6=ETC
新: 0=或 1=且 2=混行 3=ETC 4=仅地感 5=仅光耦 6=复位
```
### 涉及文件
| 文件 | 变更 |
|------|------|
| `storage.h` | `DLD_OUTPUT_MODE` 枚举顺序重排 |
| `peripheral_main.c` | 注释号同步更新 (0→6, 1→4, 2/3/4→0/1/5, 5/6→2/3); L1279 `>= RADAR_ONLY` 区间判断→精确 `!=LOOP_ONLY && !=LOOP_X_RESET` 比较; 工厂默认 `direction_mode=0x04` (仅地感) |
| `docs/technical-spec.md` | §6 融合模式表 + 状态机标题 |
| `docs/product-manual.md` | §4.6 融合模式表 |
| `docs/rs485-modbus-protocol.md` | V1.3→V1.4: §3.3 默认值、§4.3/4.4 示例、§6.5 表格、复位注释 |
| `docs/devlog.md` | 本条目 |
### 影响
- 已有测试设备的 flash 配置 (`direction_mode` 低 4 位) 需要重新设置,旧值与新模式语义不兼容
- 代码逻辑(命名常量比较)不受影响,仅枚举值和注释变更
---
## 2026-07-29 — 发布 V3.01 版本文档:技术规格书 + 产品说明书
### 文档产出
| 文档 | 路径 | 内容 |
|------|------|------|
| 技术规格书 | `docs/technical-spec.md` | 系统架构、电气参数、IO 引脚分配、检测算法全链路(频率测量/IIR/斜率限幅/灵敏度表/进入确认/平坦性离开/基线跟踪/冻结超时)、时序状态机、7 种输出融合模式状态机、指示灯、上电稳定期、线圈故障处理、通信协议(BLE/700BS/Modbus)、Flash 存储布局 |
| 产品说明书 | `docs/product-manual.md` | 面向终端用户:产品概述、技术参数、硬件接口(端子定义/指示灯)、BLE 配置项、灵敏度档位、输出模式、输出融合模式(含人车混行防砸和ETC工作原理)、安装指南、故障排查、RS485总线集成速查、订购信息 |
### 源数据来源
- `peripheral_main.c`: 算法参数 (MEASUREMENT_BASE=524288, ALFA_CAP1=79, MAX_SLOPE_RATE=5%, ENTRY_CONFIRM=3, FREEZE_TIMEOUT=1000, WINDOW_ORIGIN=500, STABLE_SAMPLES=128)
- `cmcng.h`: 版本号 (FW 3.01 / HW 3.01), 全局变量声明
- `storage.h`: Flash 布局, 配置结构体, `DLD_OUTPUT_MODE` 枚举
- `dbn_ble_srv.h`: BLE 命令码
- `docs/DLD154Pro硬件资源.md`: IO 分配
- `docs/rs485-modbus-protocol.md` / `docs/rs485-700bs-protocol.md`: 通信协议
### 与 DLD154V4B 的关键差异
| 项目 | DLD154V4B | DLD154Pro |
|------|-----------|-----------|
| MCU | AT32F421 (ARM M4) | CH591R (RISC-V) |
| 配置方式 | 物理 DIP 开关 | BLE 小程序 |
| 通信接口 | TTL Tx 调试口 | RS485 (双协议) + BLE |
| 继电器 | 2 路 | 1 路 |
| 指示灯 | 红+绿+黄 (3 LED) | 红呼吸+绿 (2 LED) |
| 光耦 | 无 | 有 (7 种融合模式) |
---
## 2026-07-28 (傍晚) — 光耦参与模式下 LEDA 同步继电器状态
光耦参与模式 (MODE 2-6) 下,绿色 LED 原先跟随线圈 `FLAG_IN`/`FLAG_OUT` 变化,
在雷达单独触发(如人车混行防砸窗口)时 LED 不亮。修正为:
- TMR1 ISR 50ms 块末尾,`g_output_radar_mode >= 2` 且正常运行(非断开/非稳定期)时,
LEDA 直接跟随 `g_loop_acs_info.relay1_state`
- 断开/稳定期 200ms 闪烁优先级不变(5ms 段优先处理)
> 效果:继电器吸合→绿灯亮,继电器释放→绿灯灭,与线圈或雷达触发源无关。
---
## 2026-07-28 (午后) — 光耦输出模式完整实现:6 种融合逻辑 + 状态机
### 架构
`opt_input_poll()` 处理光耦输入 → 产出 `g_opt_trigger` (1=有效) → TMR1 ISR 继电器输出段 `case 0` 根据 `g_output_radar_mode` 做融合判决。
```
光耦 PB10 → 3样本多数表决防抖 → opt_input_poll() → g_opt_trigger
线圈 VD_FLAG/FLAG_OUT → coil_sig ──────────→ 融合判决 → RLY1
g_output_radar_mode
```
### 各模式实现
| 模式 | 值 | `opt_input_poll()` | 继电器 `case 0` 融合公式 |
|------|-----|-------------------|--------------------------|
| LOOP_X_RESET | 0 | 光耦复位 (400ms低→上升沿→SYS_ResetExecute) | `coil_sig` |
| LOOP_ONLY | 1 | return, g_opt_trigger=0 | `coil_sig` |
| RADAR_ONLY | 2 | g_opt_trigger = 光耦信号 | `g_opt_trigger` |
| LOOP_OR_RADAR | 3 | g_opt_trigger = 光耦信号 | `coil_sig \|\| g_opt_trigger` |
| LOOP_AND_RADAR | 4 | g_opt_trigger = 光耦信号 | `coil_sig && g_opt_trigger` |
| HUMAN_VD_MIX | 5 | 状态机 (见下) | `coil_sig \|\| g_opt_trigger` |
| ETC | 6 | 状态机 (见下) | `coil_sig \|\| g_opt_trigger` |
> 注: `coil_sig = (loop1_VD_FLAG | loop1_FLAG_OUT)` — 含离开脉冲保持
### HUMAN_VD_MIX 状态机 (人车混行防砸)
```
IDLE (雷达屏蔽, 仅线圈)
│ 线圈检测到车
ARMED (雷达解禁, 线圈||雷达)
│ 两者均释放
WINDOW (3s 防砸窗口)
│ 雷达触发 → g_opt_trigger=1 → 继电器吸合, 窗口复位
│ 线圈上线 → 回到 ARMED
│ 3s 超时无触发 → 回到 IDLE, 落杆
```
定时参数: `OPT_VM_WINDOW_TICK = 600` (600×5ms = 3s)
### ETC 状态机
```
IDLE (雷达屏蔽, 仅线圈)
│ 线圈检测到车
ARMED (雷达解禁, 线圈||雷达)
│ 两者均释放
DEBOUNCE (500ms 防抖)
│ 线圈/雷达重新触发 → 回到 ARMED
│ 500ms 超时 → 回到 IDLE, 落杆
```
定时参数: `OPT_ETC_DEBOUNCE_TICK = 100` (100×5ms = 500ms)
### 光耦防抖
所有非复位模式共用 3 样本多数表决 (`OPT_DEBOUNCE_CNT=6`): 最近 3 次采样中 ≥2 票即判定有效,等效 ~30ms 消抖。
### 文件变更
| 文件 | 变更 |
|------|------|
| `peripheral_main.c` | +`g_opt_trigger` 全局变量, `opt_input_poll()` 重写 (120→180行), TMR1 ISR `case 0` 融合判决 |
| `cmcng.h` | +`extern uint8_t g_opt_trigger` |
---
## 2026-07-28 — 光耦输出模式升级:`DLD_OUTPUT_MODE` 枚举 + `direction_mode` 低四位取值
### 背景
光耦输入功能从原来的「二值化开关」(使能/复位)升级为 **7 种输出模式**
`direction_mode` 字节的低四位选择。`g_fm_radar_input_disable`(来自 `function_mode` bit1
更名为 `g_output_radar_mode`,语义从布尔值变为枚举值。
### `DLD_OUTPUT_MODE` 枚举
```c
typedef enum _DLD_OUTPUT_MODE
{
OUTPUT_MODE_LOOP_X_RESET = 0, // 光耦输入为复位信号,仅地感检测输出
OUTPUT_MODE_LOOP_ONLY, // 仅地感,光耦输入无效
OUTPUT_MODE_RADAR_ONLY, // 仅光耦(雷达输出接光耦输入),地感无效
OUTPUT_MODE_LOOP_OR_RADAR, // 地感或雷达
OUTPUT_MODE_LOOP_AND_RADAR, // 地感和雷达
OUTPUT_MODE_HUMAN_VD_MIX, // 人车混行防砸:有车后光耦/地感"或",离场 3s 内光耦有效持续防砸
OUTPUT_MODE_ETC, // ETC:有车后光耦/地感"或",光耦断开需 500ms 防抖才释放继电器
}DLD_OUTPUT_MODE;
```
### 变量与取值变更
| 项目 | 旧 | 新 |
|------|-----|-----|
| 全局变量名 | `g_fm_radar_input_disable` | `g_output_radar_mode` |
| 符号类型 | bit (0/1) | `uint8_t` (0~6) |
| 取值来源 | `(function_mode >> 1) & 0x01` | `direction_mode & 0x0F` |
| 解析位置 | `peripheral_main.c:para_store_init()` + `dbn_ble_srv.c:unpack_pkg_set_cjq_param()` | 同上 |
| BLE 回读字段 | `g_function_mode` | `g_loop_cng_unit.direction_mode` (完整 8 位) |
| `opt_input_poll` 门控 | `if (g_fm_radar_input_disable == 0)` → 雷达模式 return | `if (g_output_radar_mode)` → 非 0 模式 return |
### 实现状态
| 模式 | 状态 | 说明 |
|------|------|------|
| 0 — LOOP_X_RESET | ✅ 已实现 | PB10 低电平 ≥400ms80 tick×5ms)后上升沿 `SYS_ResetExecute()` 芯片复位 |
| 1~6 | ❌ 未实现 | `opt_input_poll()` 中直接 return |
### 文件变更
| 文件 | 变更 |
|------|------|
| `storage.h` | +`DLD_OUTPUT_MODE` 枚举 (7 种模式) |
| `cmcng.h` | `g_fm_radar_input_disable``g_output_radar_mode` |
| `peripheral_main.c` | 变量更名 + 解析路径改 `direction_mode & 0x0F` |
| `dbn_ble_srv.c` | 同上 + BLE 回读改用 `direction_mode` 完整字段 |
---
## 2026-07-22 — BLE 新增 RS485 地址/波特率读写 + 空闲关蓝牙超时 + 功能码细分
### 新增 BLE 命令
**`CMD_DBN_RW_UART_BAUD (0x31)`** — 读写 RS485 通信参数:
| 字节偏移 | 字段 | 说明 |
|---------|------|------|
| [4] | RW | 0=读, 1=写 |
| [5] | BT_close_min | 蓝牙空闲超时关闭时间 (分钟), 0=不关闭 |
| [6:8] | baud_rate | RS485 波特率 (3 字节, little-endian) |
| [9] | rs485_id | RS485 从机地址 (1-247) |
| [10:12] | reserved | 预留 |
- 读:返回当前存储值 + status=0
- 写:写入 RAM 并持久化到 DataFlash (`ADDR_BT_Close_TIMEOUT_Offset` 起 5 字节)
### Flash 存储布局
```
0x10 ADDR_BT_Close_TIMEOUT_Offset 1B 蓝牙空闲超时 (分钟)
0x11 Addr_RS485_Baud_Offset 3B RS485 波特率 (LE32)
0x14 Addr_RS485_ID_Offset 1B RS485 从机地址
```
出厂默认:RS485 ID=1, 波特率=9600, 蓝牙超时=0(不关闭)
### 功能码细分 (g_function_mode)
`g_function_mode` 取自 `direction_mode` 高 4 位,低 2 位细分:
| bit | 字段 | 0 | 1 |
|-----|------|---|---|
| bit0 | `g_fm_700bs_disable` | **700BS 协议** | Modbus 协议 |
| bit1 | `g_fm_radar_input_disable` | **光耦输入使能** | 光耦输入复位 |
> RS485 将支持两种协议:700BS(后续上传)和 Modbus。通过小程序设置 `direction_mode` 高 4 位的 bit0 切换。
### 文件变更
| 文件 | 变更 |
|------|------|
| `dbn_ble_srv.h` | +`CMD_DBN_RW_UART_BAUD 0x31` |
| `cmcng.h` | +extern 声明: `fm_700bs_disable`, `fm_radar_input_disable`, uart/bt 配置 |
| `storage.h` | +Flash 地址宏: BT_timeout, RS485_baud, RS485_ID |
| `peripheral_main.c` | +全局变量定义, factory_dev 默认值, para_store_init 恢复 |
| `dbn_ble_srv.c` | +`CMD_DBN_RW_UART_BAUD` handler, unpack 中解析 function_mode bits |
### 待办
- [ ] RS485 700BS 协议定义
- [ ] RS485 Modbus 协议定义
- [ ] RS485 串口中断收发实现 (UART0)
- [ ] 蓝牙空闲超时自动关闭逻辑
---
## 2026-07-21 — 灵敏度等级与 ΔL/L 的物理关系分析
### 参数表
```c
// sens_in: 进入阈值, sens_out: 离开阈值 (0=最低, 3=最高)
SensTable = { 108, 54, 28, 14 }; // 进入
SensTable1 = { 81, 32, 16, 12 }; // 离开
```
### 计算链路
**Step 1:阈值差值**
```c
loop1_dlt_ORG = (Origin * sens) >> 16; // = Origin × sens / 65536
```
**Step 2:进入判定**
```c
if (CAPVD < Origin - dlt_ORG) // ← ΔCAPVD / Origin > sens / 65536
```
**Step 3CAPVD → 电感**
线圈振荡频率 `f ∝ 1/√L`,周期 `T ∝ √L`。测量窗 CAPVD 正比于平均周期:
```
ΔCAPVD / Origin = ΔT / T₀ = (√L - √L₀) / √L₀
```
对微小变化泰勒展开:`dT/T ≈ dL/(2L)`,即:
```
ΔL / L ≈ 2 × ΔCAPVD / Origin
```
**Step 4:最终 ΔL/L 公式**
```
ΔL/L_entry = 2 × sens_in / 65536
ΔL/L_exit = 2 × sens_out / 65536
```
### 灵敏度等级对应 ΔL/L
| 等级 | sens_in | ΔL/L 进入 | sens_out | ΔL/L 离开 | 迟滞比 |
|------|---------|----------|----------|----------|--------|
| 低 (0) | 108 | **0.330%** | 81 | **0.247%** | 1.33 |
| 中 (1) | 54 | **0.165%** | 32 | **0.098%** | 1.69 |
| 高 (2) | 28 | **0.085%** | 16 | **0.049%** | 1.75 |
| 最高(3) | 14 | **0.043%** | 12 | **0.037%** | 1.17 |
### 物理验证
典型 100μH 线圈:
- 现代轿车经过:ΔL/L ≈ 5%–15%,任一灵敏度均能可靠触发
- 高灵敏度 0.085%:足够敏感,需注意温漂(~20°C 引起约 0.1% 的感量偏移)和邻道串扰
- 迟滞比 1.33–1.75:防止车辆边界状态反复跳变,低灵敏度迟滞最小
### 快速换算
`sens` 值直接对应 **千分之 2×sens 的感量变化百分比**——除以 1000 就是 ΔL/L(%)。
---
## 2026-07-21 (午后) — 修复灵敏度 bug + 有限存在时间 + 版本号
### BLE 灵敏度无法修改
**根因:** 硬件适配时删了 `poll_sens_key()`,在 `INIT_VD()` 中硬编码了 `g_freq_sens = 2`
但未在 BLE 参数解包 `unpack_pkg_set_cjq_param()` 中同步更新,导致小程序修改灵敏度无效。
**修复:**
- `peripheral_main.c`: `g_freq_sens``INIT_VD()` 移到 `para_store_init()`
从存储的 `g_loop_cng_unit.sensitvity` 读取:`(sensitvity > 0) ? (sensitvity - 1) : 0`
- `dbn_ble_srv.c`: `unpack_pkg_set_cjq_param()` 中同样增加 `g_freq_sens` 同步更新,
确保 BLE 小程序实时修改后立即生效
### 有限存在时间公式对齐
`dbn_ble_srv.c``g_hold_time` 计算写的是 `exist_mode * 30 * 20`
`para_store_init()` 中用的是 `exist_mode * 20 * 5`50ms tick)。
统一为 `20 * 5`(对应参数值 × 100ms × 5s 基础周期)。
### 版本号
- 固件: `4.01``3.00`
- 硬件: `1.00``3.01`
---
## 2026-07-21 — 项目初始化:从 DLD110SV4 复制基线 + 按硬件资源文档调整 IO
### 背景
DLD154Pro 是 DLD110SV4 的硬件升级版(同 MCU CH591R),核心变更:
- 继电器 双路→单路(删 RLY2
- 删除拨码开关(灵敏度改由小程序设置)
- 线圈调频 两级→一级(删 PA13 FLEVEL_L
- 新增 RS485 接口(PA14/PA15/PA13,协议待定)
- 新增光耦输入(PB10,逻辑待定)
- 指示灯从单色→双色(LEDA 绿 + LEDB 红呼吸灯)
- DEBUG UART0 被 RS485 占用,删除全部
### 仓库
- 远程: http://118.178.252.17:3000/wangfq/DLD154Pro
- 本地: `/home/wfq/projects/vd_detector/DLD154Pro`
- commit `5f5f697`: init 基线
- commit `91ba844`: feat 硬件适配
### IO 宏重定义
| 引脚 | 旧(DLD110SV4) | 新(DLD154Pro) |
|------|--------------|---------------|
| PA8 | RLY1 (存在) | RLY1 (存在,不变) |
| PB23 | RLY2 (功能/脉冲) | **LEDB (红色呼吸灯)** |
| PA12 | FLEVEL_H (33nF) | FLEVEL (33nF,一级) |
| PA13 | FLEVEL_L (10nF) | **UART0_RE (RS485 方向)** |
| PA14 | KEY_SA1 / DEBUG_TX | **UART0_TX (RS485)** |
| PA15 | KEY_SA2 / DEBUG_RX | **UART0_RX (RS485)** |
| PB10 | - | **IN_1 (光耦输入)** |
| PB22 | LEDA (绿色) | LEDA (绿色,不变) |
### 删除项
- `RLY2_ON/OFF` 宏及全部 RLY2 输出逻辑
- `KEY_SA1/KEY_SA2` 宏及 `poll_sens_key()` 函数
- `FLEVEL_L_LOW/HIGH`, `FLEVEL_H_LOW/HIGH` → 改为 `FLEVEL_LOW/HIGH`
- `g_flag_output`, `g_xn_counter` 全局变量
- DEBUG UART0 初始化 (`gpio_uart_init``#ifdef DEBUG` 块)
- `Main_Circulation``#ifdef DEBUG` PRINT 块
- TMR1_ISR 中 `_cnt` / `g_flag_output` DEBUG 定时器
- TMR0_ISR 中 `g_xn_counter` DEBUG 计数器
- `para_store_init()` 中频率四档 switch → 双档 if/else
### 新增/预留
- RS485 引脚宏: `RS485_TX_PIN`, `RS485_RX_PIN`, `RS485_RE_PIN`, `RS485_RE_TX()`, `RS485_RE_RX()`(仅初始化引脚,协议待定)
- 光耦输入宏: `OPT_IN1`(仅初始化 PB10 输入上拉,逻辑待定)
- LEDB 宏: `LEDB_ON/OFF`PB23,低电平有效)
- `g_freq_sens = 2` 默认最高灵敏度(取代 poll_sens_key 拨码逻辑)
### 继电器输出简化
| 模式 | 旧 (双继电器) | 新 (单继电器) |
|------|-------------|---------------|
| case 0: 存在输出 | RLY1 跟随 VD, RLY2 跟随 VD | RLY1 跟随 VD |
| case 1: 进入脉冲 | RLY2=存在, RLY1=进入脉冲 | RLY1=进入脉冲 |
| case 2: 离开脉冲 | RLY2=存在, RLY1=离开脉冲 | RLY1=离开脉冲 |
| default | RLY2=存在 | RLY1=存在 |
### 保留(协议兼容)
- `storage.h``Loop_ACS_Info.relay2_cng/relay2_state` 字段保留,默认值=0
- `dbn_ble_srv.c:468` 上报字节 relay2 位自动为 0(字段初始化为 0 后无写入)
### 待办
- [x] RS485 通信协议定义 + UART0 中断/收发实现 ~~(2026-07-24 完成)~~
- [ ] 光耦输入逻辑(与其他检测器联动 / 综合判断)
- [ ] IAP/OTA 项目文件中的 DLD110S 引用更新(`592OnlyUpdateApp_*`
- [ ] `.mrs/` 工作区文件清理(大量 DLD110S 历史快照)
---
## 2026-07-2324 — RS485 700BS 协议实现 & 四级灵敏度
### RS485 700BS 从机协议
| 项目 | 说明 |
|------|------|
| 物理层 | RS485 半双工, 9600 8N1, PA14=TX PA15=RX PA13=RE |
| 帧格式 | 主机 3 字节 (STX ADDR XOR), 从机 3~9 字节变长 |
| 心跳 | 空闲 5s / 故障(线圈断开) 1s / 事件(car_state翻转)立即 |
| 命令 | 0xFA 查询状态, 0x1B 查询频率, 0x2C 复位线圈, 0x3D 查询DIP |
**文件:** `APP/rs485_700bs.c` (新增), `APP/include/rs485_700bs.h` (新增)
### 踩坑记录
1. **UART0 API 不兼容** — CH592 SDK 中 `UART0_GetITFlag()` 是无参宏(非函数),`UART0_ClearITFlag()` 不存在。改用 `switch(UART0_GetITFlag())` 标准模式,参考 UART1 例程。
2. **`while(R8_UART0_TFC == 0)` 死循环** — TX FIFO 空时条件永真,主循环卡死导致地感不工作。修正为 `!= 0`(等 FIFO 空再写下一字节)。
3. **`rs485_init()` 从未被调用** — `gpio_uart_init()` 只写了注释 `/* 由 rs485_init() 统一初始化 */` 但未实际调用,UART0/GPIO 未配置。修复:替换注释为函数调用。
4. **频率始终为 0**`g_loop_acs_info.frequent` 只在 BLE 报告路径 `usart_packet_processing_acs_loop` 中更新,BLE 断开时永不执行 → freq=0。
5. **频率非实时** — 改用 `g_loop_acs_info.loop_capvd` 仍有问题:该值被 `flag_change` 门控冻结(上电/车辆进出时 `flag_change=1`→capvd 不更新,清零只在 BLE 报告路径)。最终方案:直接使用 `loop1_CAPVD``vd1_task()` 每次实时 IIR 滤波值),不经过 BLE 通道。
**最终频率计算:**
```c
freq = (uint64_t)FREQ_SYS * loop1_LPCNT / loop1_CAPVD + 360
```
### 四级灵敏度
`MAX_LOOP_SENS_AMOUNT`: 3 → 4
新增第四档:进入阈值 14, 离开阈值 12 (ΔL/L≈0.04%),适用于极高灵敏度场景(如摩托车/小型车辆检测)。需注意温漂影响——20°C 温度变化可引起约 0.1% 感量偏移,第四档信噪比余量仅约 2:1。
---
## 2026-07-24 (傍晚) — 光耦输入复位功能 & mstick() 时间单位修正
### 光耦输入复位 (`opt_input_poll`)
| 项目 | 说明 |
|------|------|
| 引脚 | PB10 (IN_1), 内部上拉, 光耦干接点输入 |
| 使能条件 | `g_fm_radar_input_disable == 1` |
| 触发逻辑 | 干接点接通(PB10=0) ≥500ms → 断开(上升沿) → `SYS_ResetExecute()` |
| 消抖 | <500ms 短脉冲上升沿清零计时, 不触发 |
**关键修复:PB10 数字输入使能**
`R32_PIN_CONFIG2` 寄存器中 `RB_PIN_PB10_15_DIS` 默认置位(关闭数字输入省电)。`GPIOB_ModeCfg(..., GPIO_ModeIN_PU)` 只配置了上下拉和方向,数字输入通路在更底层被掐断。修复:`R32_PIN_CONFIG2 &= ~(1UL << 26)`
### mstick() 时间单位修正
`mstick()` = `TimingDelayInc`,在 TMR1 ISR (5ms 间隔) 中递增。**单位是 5ms/tick,不是毫秒。**
| 位置 | 原来 | 修正后 | 实际时间 |
|------|------|--------|---------|
| `opt_input_poll` 阈值 | `>= 500` | `>= 100` | 500ms |
| `RS485_HEARTBEAT_MS` | 5000 | 1000 | 5s |
| `RS485_FAULT_MS` | 1000 | 200 | 1s |
> 帧超时 `mstick() - _rx_last_tick > 10`=50ms)保留未改,对 9600 波特率够用。