From eaec1bd1bde095abc27c5956a99f3ed3568a414a Mon Sep 17 00:00:00 2001 From: wangfq Date: Tue, 25 Aug 2026 17:05:36 +0800 Subject: [PATCH] =?UTF-8?q?docs(DLD110SV4):=20=E6=96=B0=E5=A2=9E=E8=93=9D?= =?UTF-8?q?=E7=89=99=E5=B0=8F=E7=A8=8B=E5=BA=8F=E6=8E=A5=E5=8F=A3=E5=8D=8F?= =?UTF-8?q?=E8=AE=AE=E6=96=87=E6=A1=A3=20(=E4=BE=9D=E6=8D=AE=20dbn=5Fble?= =?UTF-8?q?=5Fsrv.c)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 与 DLD154Pro 三处关键差异: 拨码灵敏度/3档表/无0x31 - §1 BLE 服务: 0xFFE0, Char1(0xFFE1 RW)/Char4(0xFFE4 Notify), 设备名 DLD110S - §2-3 帧格式/分包: Magic(8F/7F)+Header+Len+CMD+Data+XOR+SUM; 14B 写死分包 - §4-5 命令: 0x10/0x1F/0x23/0x24/0x8A/0x92/0xC5 逐字段 - §6 主动上报 0xC0: type=5 线圈动态 - §7 坑清单: 拨码灵敏度不生效/3档/0x24偏移7=g_function_mode/0xC5超时疑bug - devlog 置顶 2026-08-25 条目 --- docs/ble-protocol.md | 227 +++++++++++++++++++++++++++++++++++++++++++ docs/devlog.md | 34 +++++++ 2 files changed, 261 insertions(+) create mode 100644 docs/ble-protocol.md diff --git a/docs/ble-protocol.md b/docs/ble-protocol.md new file mode 100644 index 0000000..d3a2cca --- /dev/null +++ b/docs/ble-protocol.md @@ -0,0 +1,227 @@ +# DLD110SV4 蓝牙小程序接口协议 + +> 依据源码整理:`BLE/DLD110S_Peripheral_28K/APP/dbn_ble_srv.c`(主逻辑)、`peripheral.c`/`Profile/gattprofile.c`(BLE 服务)、`peripheral_main.c`(灵敏度/检测)、`include/storage.h`(配置结构)、`include/cmcng.h`(常量) +> 固件版本:V4.20(cmcng.h `FIRMWARE_VER`)| 硬件版本:V4.01 | 产品型号:DLD110S(BLE 单线圈) + +--- + +## ⚠ 与 DLD154Pro 协议的三处关键差异(先读这节) + +| # | 差异 | DLD110SV4 | DLD154Pro | +|---|------|-----------|-----------| +| 1 | **灵敏度来源** | **硬件拨码 KEY_SA1/SA2 决定**(`poll_sens_key`,peripheral_main.c:263),协议 0x23 设置的 `sensitvity` **不参与检测** | BLE 配置(无拨码),sensitvity 1~4 直接生效 | +| 2 | 灵敏度档数 | **3 档** `{108,54,28}` / `{81,32,16}`(sens_in/sens_out) | 4 档 `{108,54,28,14}` / `{81,32,16,12}` | +| 3 | 命令 0x31 | **无**(无 RS485) | 有(读写波特率/地址) | + +> **灵敏度拨码映射**(`poll_sens_key`,每周期刷新 `g_freq_sens`,检测阈值 = `g_loop_sens_list.sens[g_freq_sens]`): +> +> | KEY_SA1 | KEY_SA2 | g_freq_sens | 档位 | 检测阈值 sens_in | +> |---------|---------|-------------|------|-----------------| +> | 1 | 1 | 0 | 最低 | 108(0.165% Δf/f) | +> | 0 | 1 | 1 | 中 | 54(0.082%) | +> | 1 | 0 | 2 | 最高 | 28(0.043%) | +> | 0 | 0 | — | 保持上次 | — | +> +> DEBUG 编译时固定 `g_freq_sens = 2`。 + +--- + +## 1. BLE 服务与特征 + +| 服务/特征 | UUID | 属性 | 长度 | 用途 | +|-----------|------|------|------|------| +| 服务 SIMPLEPROFILE | 0xFFE0 | — | — | 广播服务 UUID | +| Char1 | 0xFFE1 | 读写 (RW) | 64B | **小程序 → 芯片:命令下发** | +| Char2 | 0xFFE2 | 读 | 1B | 预留 | +| Char3 | 0xFFE3 | 写 | 8B | 预留 | +| Char4 | 0xFFE4 | **通知 (Notify)** | 32B | **芯片 → 小程序:命令响应 + 主动上报** | +| Char5 | 0xFFE5 | 读 | 5B | 预留 | + +- 设备名:`DLD110S`(广播 + GATT Device Name) +- **MTU**:默认 23,连接后协商(`ATT_MTU_UPDATED_EVENT`)。notify 单包 payload ≤ `peripheralMTU − 3` +- **交互模型**:写 Char1 下发命令帧 → 芯片处理 → Char4 notify 返回响应帧;主动上报也走 Char4 + +--- + +## 2. 帧格式与校验 + +``` +| Magic 1B | Header 1B | Len 1B | CMD 1B | Data N B | XOR 1B | SUM 1B | +``` + +| 字段 | 说明 | +|------|------| +| Magic | `0x8F` = 车检器默认协议;`0x7F` = 透传 | +| Header | 单包 = `0x00`;分包 = `(pkg_amount << 4) \| pkg_seq`(seq 从 1) | +| Len | `1(CMD)+ N(Data 字节数)` | +| XOR | 从 Header 到 Data 末尾逐字节异或 | +| SUM | 从 Header 到 Data 末尾逐字节求和(低 8 位) | + +校验算法(dbn_ble_srv.c `compute_ckb`/`check_pkg`)与 DLD154Pro 完全一致:最小帧长 6,XOR/SUM 任一不符丢弃。 + +--- + +## 3. 分包机制 + +与 DLD154Pro 相同(同一模板): +- **发送**:`MAX_BLE_DAT_RESPONSE_LEN = 14`(= BLE_BUFF_MAX_LEN−4,MTU=23 旧假设),多包 Header = `(amount<<4)|seq` +- **接收**:`unpack_packs()` 支持重组(当前仅 0x1C/0x1D 使用,已注释) +- ⚠ 分包粒度写死 14B,MTU 协商更大后不重新分包 + +--- + +## 4. 命令总览 + +| CMD | 名称 | 方向 | 说明 | +|-----|------|------|------| +| 0x10 | GET_DEV_INFO | 小程序→芯片 | 读设备信息(MAC/版本/型号) | +| 0x1F | RESET_DEV | 小程序→芯片 | 复位设备(SYS_ResetExecute) | +| 0x23 | SET_CJQ_PARAM | 小程序→芯片 | 设置车检器参数(**灵敏度不生效,见 §5.3**) | +| 0x24 | GET_CJQ_PARAM | 小程序→芯片 | 读车检器参数 | +| 0x8A | LOOP_SENS_LIST | 小程序→芯片 | 读写灵敏度表(sens_in/sens_out) | +| 0x92 | SET_CJQ_FACTORY | 小程序→芯片 | 恢复出厂 | +| 0xC5 | SENS_ACS_ENABLE | 小程序→芯片 | 主动上报使能 | +| 0xC0 | SUB_SENS_REPORT | 芯片→小程序 | 主动上报线圈动态(不可下发) | + +**不存在**:0x31(DLD154Pro 有,本产品无 RS485)。 +**未实现(注释)**:0x1C/0x1D/0x1E/0x20-0x22/0x6D/0x87/0x88/0x89。 + +--- + +## 5. 命令详述 + +### 5.1 0x10 读设备信息 + +无 Data。响应 Data: + +| 偏移 | 字节 | 内容 | +|------|------|------| +| 0-5 | 6 | MAC 地址 | +| 6-7 | 2 | 硬件版本 MAIN/SUB(V4.01 → 04 01) | +| 8-9 | 2 | 固件版本 MAIN/SUB(V4.20 → 04 14) | +| 10 | 1 | 产品型号长度 | +| 11.. | N | 产品型号 ASCII("DLD110S") | +| .. | 6 | 设备编号 | +| .. | 2 | sub_code(固定 0) | +| .. | 2 | 总线设备数(固定 0) | + +### 5.2 0x1F 复位设备 + +无 Data。`SYS_ResetExecute()` 整机冷复位,**无响应帧**。 + +### 5.3 0x23 设置车检器参数 + +Data(5B): + +| 偏移 | 内容 | +|------|------| +| 0 | `sensitvity(低4位) \| loopFreq_Level(高4位)` | +| 1 | delay_time(离开延时) | +| 2 | `output_mode(低2位) \| loopSafe_Timeout(高5位)` | +| 3 | exist_mode(有限存在时长) | +| 4 | direction_mode(高 4 位 = g_function_mode) | + +**⚠ 灵敏度字段不生效**:`g_loop_cng_unit.sensitvity` 仅写入 flash 存档,**检测阈值由拨码 `g_freq_sens` 决定**(见开头差异表)。小程序设置灵敏度无效,现场改灵敏度必须拨码。 + +内部换算(unpack_pkg_set_cjq_param): +``` +g_function_mode = direction_mode >> 4 +g_hold_time = exist_mode * 30 * 20 (600 tick ≈ 30s × exist_mode, @50ms tick) +``` +处理:更新全局 → `write_cfg_to_store(4, tmp, 7)` → `para_store_init()`。响应:1B status=0。 + +### 5.4 0x24 读车检器参数 + +无 Data。响应 Data(8B): + +| 偏移 | 内容 | +|------|------| +| 0 | `(g_freq_sens + 1) \| (loopFreq_Level << 4)`(灵敏度回读 = **拨码档位 + 1**,值域 1~3) | +| 1 | delay_time | +| 2 | `output_mode \| (loopSafe_Timeout << 3)` | +| 3 | exist_mode | +| 4 | `sens_list.total << 4`(= 3,高 4 位) | +| 5 | 线圈断开次数低字节 | +| 6 | 线圈断开次数高字节 | +| 7 | **g_function_mode**(注意:DLD154Pro 此处是 direction_mode) | + +### 5.5 0x8A 读写灵敏度表 + +**读(pkg[4]=0)**:响应 Data:`[0x10] [total=3] [sens0_in LE2 | sens0_out LE2] [sens1...]` + +**写(pkg[4]≠0)**:Data 从 pkg[5] 起:`[total] [表...]`。写 flash `Addr_Loop_Sens_List_Offset(0x20)` + `para_store_init()`。不直接更新 RAM,依赖重读生效。 + +出厂默认 3 档:`sens_in {108, 54, 28}` / `sens_out {81, 32, 16}`(peripheral_main.c:187,滞回 ~75/59/57%)。 + +### 5.6 0x92 恢复出厂 + +`set_factory_param() + factory_dev()` → `para_store_init()`。响应:1B status=0。 + +### 5.7 0xC5 主动上报使能 + +Data:`[enable] [interval] [timeout_min]` +- enable:1=开启,0=关闭 +- interval:间隔系数,实际 `interval × 0x7F`(127) +- timeout_min:超时分钟数(0=不限时) + +处理:开启时 `timeout_counter = timeout_min × 60 × 100`(**源码 TODO 标注 min→ms,60×100=6000 疑应为 60000,待现场验证**)。关闭时 flag=0。 + +--- + +## 6. 主动上报 0xC0(芯片 → 小程序) + +与 DLD154Pro 相同模板(type = 5 SENS_LOOP_DYNAMIC): + +| 偏移 | 字节 | 内容 | +|------|------|------| +| 0 | 1 | `0x05`(SENS_LOOP_DYNAMIC) | +| 1 | 1 | `loop_num<<6 \| freq_level<<4 \| condition&0x0F` | +| 2 | 1 | `relay2_state<<6 \| relay2_cng<<4 \| relay1_state<<2 \| relay1_cng&0x3` | +| 3 | 1 | `loop1_FLAG_CUT<<7 \| car_state<<4 \| direction&0x0F` | +| 4-6 | 3 | 线圈断开次数(LE,上电未连时为 1) | +| 7-9 | 3 | 实际频率(LE,`freq = sclk_freq/CAPVD×LPCNT + 360` 补偿) | +| 10-12 | 3 | variation(**3B 有符号补码 LE**,正=车/金属进入方向) | + +触发:事件(flag_event)立即上报;周期 `report_counter >= 120`(120 × 50ms ≈ 6s);前提 0xC5 开启。 +**variation 接收端注意**:3B 有符号,负值需符号扩展(`if (v & 0x800000) v |= 0xFF000000`)。 +**condition**:环境评估 0~15(`g_env_activity/10`,>150 取 15;线圈断开强制 15)。 + +--- + +## 7. 实现细节与坑(对照源码) + +1. **⚠ 灵敏度是拨码的不是协议的**:检测阈值 = `g_loop_sens_list.sens[g_freq_sens]`(peripheral_main.c:609),g_freq_sens 由 `poll_sens_key()` 读 KEY_SA1/SA2 每周期刷新。0x23 的 sensitvity 只存档不生效,0x24 回读的是拨码档位+1 +2. **3 档灵敏度**(MAX_LOOP_SENS_AMOUNT=3),0x8A 写表 total 上限 3 +3. **无 0x31**:DLD110SV4 无 RS485,小程序不应下发 0x31 +4. **0xC5 超时疑似 bug**:`timeout_min × 60 × 100`(若意图 ms 应为 ×1000,待现场验证) +5. **0x8A 写表不直接更新 RAM**:依赖 `para_store_init()` 重读 +6. **0xC0 frequent +360 补偿**:经验值,示波器标定用 +7. **0x1F/0x92 无响应帧**:复位/出厂类命令执行后设备重启 +8. **notify 超限静默丢弃**:`len > (peripheralMTU-3)` 返回 FAIL 不重发,长响应必须分包 +9. **0x24 偏移 7 是 g_function_mode**(非 direction_mode)——与 DLD154Pro 不同,解析别混 +10. **g_hold_time 换算差异**:`exist_mode × 600 tick`(≈30s/单位,DLD154Pro 为 ×100 tick ≈5s/单位)——产品差异,协议层语义一致 + +--- + +## 8. 交互示例 + +**读取设备信息**(无 Data,Len=1): +``` +下发: 8F 00 01 10 11 11 + │ │ │ │ │ └ SUM = 0x00+0x01+0x10 = 0x11 + │ │ │ │ └─ XOR = 0x00^0x01^0x10 = 0x11 + │ │ │ └─ CMD = 0x10 + │ │ └─ Len = 1 (CMD only) + │ └─ Header = 0 (单包) + └─ Magic = 0x8F + +芯片 → Char4 notify: 8F 00 10 XX [MAC6][04 01][04 14][07 "DLD110S"][dev_no6][00 00][00 00] [XOR] [SUM] +``` + +**设置参数(如延时/输出,灵敏度不生效)**: +``` +下发: 8F 00 06 23 20 00 00 00 00 [XOR] [SUM] + Len=6: CMD(0x23)+Data5 + Data[0]=0x20: sensitvity=2(仅存档) | freq_level=0 + Data[1..4]=延时/输出/存在/方向模式 +``` diff --git a/docs/devlog.md b/docs/devlog.md index 28fcee1..ec0d6b1 100644 --- a/docs/devlog.md +++ b/docs/devlog.md @@ -2,6 +2,40 @@ > MCU: CH591R (RISC-V, BLE) @60MHz | 通道: 1 路线圈 | 调试口: UART0 (DEBUG 编译, 230400) +## 2026-08-25 — 蓝牙小程序接口协议文档 + +### 背景 + +根据 `dbn_ble_srv.c`(+ peripheral.c/gattprofile.c/peripheral_main.c/storage.h/cmcng.h)整理蓝牙小程序与芯片交互的完整接口协议。 + +### 文档要点 + +| 章节 | 内容 | +|------|------| +| 开头差异表 | **与 DLD154Pro 的三处关键差异** | +| §1 BLE 服务 | 0xFFE0 服务;Char1(0xFFE1 RW 命令下发)、Char4(0xFFE4 Notify);设备名 DLD110S | +| §2-3 帧格式/分包 | Magic(8F/7F)+Header+Len+CMD+Data+XOR+SUM;14B 写死分包 | +| §4-5 命令 | 0x10/0x1F/0x23/0x24/0x8A/0x92/0xC5 逐字段(**无 0x31**) | +| §6 主动上报 | 0xC0 线圈动态(type=5) | +| §7 坑清单 | 10 条源码事实 | + +### 关键发现(源码事实) + +1. **⚠ 灵敏度由硬件拨码 KEY_SA1/SA2 决定**(`poll_sens_key` peripheral_main.c:263):检测阈值 = `g_loop_sens_list.sens[g_freq_sens]`,**0x23 设置的 sensitvity 仅存档不生效**,0x24 回读 = 拨码档位+1(1~3) +2. **3 档灵敏度**(MAX_LOOP_SENS_AMOUNT=3):默认 `{108,54,28}` / `{81,32,16}`(DLD154Pro 为 4 档) +3. **无 0x31**(DLD110SV4 无 RS485) +4. 0x24 偏移 7 是 `g_function_mode`(DLD154Pro 为 direction_mode) +5. g_hold_time = exist_mode × 600 tick(DLD154Pro ×100)——产品差异 +6. 0xC5 超时疑似 bug:`timeout_min × 60 × 100`(应 ×1000?待现场验证) + +### 涉及文件 + +| 文件 | 内容 | +|------|------| +| `docs/ble-protocol.md` | 新增(固件 V4.20 / 硬件 V4.01 / 型号 DLD110S) | + +--- + ## 2026-07-20 — variation 3 字节上报 + 编码 GBK→UTF-8 + 线圈重连对齐 DLD154V4B spec ### variation 上报升级