commit ef806b60134a814375d274bbce46d8e8e26e2d67 Author: wangfq Date: Mon Jun 22 17:02:23 2026 +0800 init: vd_960 项目初始化 - 双 MCU 架构:AT32F421(线圈) + CH32V208(通信) - DLD960 串口通信协议 V1.01 - IoT MQTT 接口协议 V1.00 (JSON) - TCP 接口协议 V1.00 (JSON) diff --git a/README.md b/README.md new file mode 100644 index 0000000..578203a --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# vd_960 — 车检器 DLD960 嵌入式软件 + +## 产品概述 + +DLD960 是一款双 MCU 架构的车检器(车辆检测器),采用线圈检测原理。 + +## 硬件架构 + +| 芯片 | 型号 | 主频 | Flash | SRAM | 职责 | +|------|------|------|-------|------|------| +| 线圈 MCU | AT32F421 | 120MHz | 64KB | 16KB | 四路线圈信号采集与处理 | +| 通信 MCU | CH32V208 | 144MHz | 128KB | 64KB | 蓝牙、网口、1路 RS485 | + +两个 MCU 之间通过内部总线(UART/SPI)通信。 + +## 子项目 + +| 子项目 | 目录 | MCU | 功能 | +|--------|------|-----|------| +| vd960Loop | `vd960Loop/` | AT32F421 | 线圈驱动、频率采样、车辆检测算法 | +| vd960DBN | `vd960DBN/` | CH32V208 | 蓝牙管理、TCP/IP 协议栈、RS485 通信 | + +## 开发环境 + +- vd960Loop: Keil MDK / AT32 IDE(ARM Cortex-M4) +- vd960DBN: MounRiver Studio(RISC-V) diff --git a/docs/DLD960_IoT_MQTT协议.md b/docs/DLD960_IoT_MQTT协议.md new file mode 100644 index 0000000..dae46bf --- /dev/null +++ b/docs/DLD960_IoT_MQTT协议.md @@ -0,0 +1,789 @@ +# DLD960 IoT 接口协议(MQTT + JSON) + +> 基于《DLD960 串口通信协议》V1.01,将设备管理、参数配置、数据上报映射到 MQTT 协议。 +> 交互格式:JSON。 + +--- + +# 1 通信说明 + +## 1.1 连接参数 + +| 项目 | 说明 | +|------|------| +| 协议 | MQTT 3.1.1 / 5.0 | +| 传输层 | TCP (TLS 可选) | +| QoS | 配置类 QoS 1,数据上报类 QoS 0/1 | +| 编码 | UTF-8 | +| 序列化 | JSON | + +## 1.2 Topic 结构 + +``` +dld960/{dev_serial}/{direction}/{category}[/{sub}] +``` + +| 字段 | 说明 | +|------|------| +| `dev_serial` | 设备序列码(6字节十六进制字符串,如 `A1B2C3D4E5F6`) | +| `direction` | `srv` = 服务器下发,`dev` = 设备上报 | +| `category` | 消息类别 | +| `sub` | 子类别(可选) | + +### 1.2.1 服务器下发 Topic(设备订阅) + +| Topic | 说明 | 对应串口 CMD | +|-------|------|-------------| +| `dld960/{sn}/srv/config/set` | 设置配置参数 | 0x11, 0x13, 0x15, 0x63 | +| `dld960/{sn}/srv/config/query` | 查询配置参数 | 0x10, 0x12, 0x14, 0x16, 0x64 | +| `dld960/{sn}/srv/ctrl` | 控制命令 | 0x09, 0x1C, 0x1D, 0x1E, 0x1F, 0xC5 | + +### 1.2.2 设备上报 Topic(服务器订阅) + +| Topic | 说明 | 对应串口 CMD | +|-------|------|-------------| +| `dld960/{sn}/dev/config/resp` | 配置查询/设置响应 | 各命令返回 | +| `dld960/{sn}/dev/data/loop` | 线圈传感数据上报 | 0xC0 (SensType=0x0C) | +| `dld960/{sn}/dev/data/event` | 事件上报(有车/无车、故障等) | — | +| `dld960/{sn}/dev/status` | 设备状态(在线心跳、自检) | — | + +--- + +# 2 JSON 消息格式 + +## 2.1 通用结构 + +```json +{ + "msg_id": 12345, + "cmd": "dev_info_query", + "ts": 1719000000, + "data": { ... } +} +``` + +| 字段 | 类型 | 说明 | +|------|------|------| +| `msg_id` | uint32 | 消息序列号,递增,用于请求-响应匹配(由发起方生成) | +| `cmd` | string | 命令标识符 | +| `ts` | uint32 | Unix 时间戳(秒),发起方填充 | +| `data` | object | 命令参数,结构依 cmd 而定 | + +## 2.2 响应通用结构 + +```json +{ + "msg_id": 12345, + "cmd": "dev_info_query", + "ts": 1719000001, + "code": 0, + "msg": "success", + "data": { ... } +} +``` + +| 字段 | 类型 | 说明 | +|------|------|------| +| `code` | int | 0 = 成功,非 0 = 失败码 | +| `msg` | string | 错误描述(成功时为 `"success"`) | + +### 错误码定义 + +| code | 说明 | +|------|------| +| 0 | 成功 | +| 1 | 参数错误(格式/范围不正确) | +| 2 | 密码验证失败 | +| 3 | 设备忙(操作执行中) | +| 4 | 不支持的命令 | +| 5 | 内部错误 | +| 6 | 数据超长 | + +--- + +# 3 命令详表 + +| cmd | 说明 | 方向 | 对应串口 | +|-----|------|------|----------| +| `dev_serial_set` | 更改设备序列码 | srv→dev | 0x09 | +| `dev_info_query` | 查询设备信息 | srv→dev | 0x10 | +| `ssc_net_set` | 设置 SSC 网络配置 | srv→dev | 0x11 | +| `ssc_net_query` | 查询 SSC 网络配置 | srv→dev | 0x12 | +| `iot_net_set` | 设置 IoT 网络配置 | srv→dev | 0x13 | +| `iot_net_query` | 查询 IoT 网络配置 | srv→dev | 0x14 | +| `iot_topic_set` | 设置设备 Topic | srv→dev | 0x15 | +| `iot_topic_query` | 查询设备 Topic | srv→dev | 0x16 | +| `pwd_verify` | 验证设备密码 | srv→dev | 0x1C | +| `pwd_set` | 设置设备密码 | srv→dev | 0x1D | +| `factory_reset` | 设备出厂初始化 | srv→dev | 0x1E | +| `device_reset` | 设备复位 | srv→dev | 0x1F | +| `loop_param_set` | 设置车检器多路参数 | srv→dev | 0x63 | +| `loop_param_query` | 读取车检器多路参数 | srv→dev | 0x64 | +| `report_config` | 设置主动上报 | srv→dev | 0xC5 | +| `loop_data` | 线圈传感数据上报 | dev→srv | 0xC0 | +| `event_report` | 事件上报 | dev→srv | — | +| `heartbeat` | 设备心跳 | dev→srv | — | + +--- + +# 4 命令详情 + +## 4.1 更改设备序列码 `dev_serial_set` + +> Topic: `dld960/{sn}/srv/config/set` + +**请求:** + +```json +{ + "msg_id": 1, + "cmd": "dev_serial_set", + "ts": 1719000000, + "data": { + "dev_serial": "A1B2C3D4E5F6" + } +} +``` + +**响应:** Topic: `dld960/{sn}/dev/config/resp` + +```json +{ + "msg_id": 1, + "cmd": "dev_serial_set", + "ts": 1719000001, + "code": 0, + "msg": "success" +} +``` + +## 4.2 查询设备信息 `dev_info_query` + +> Topic: `dld960/{sn}/srv/config/query` + +**请求:** + +```json +{ + "msg_id": 2, + "cmd": "dev_info_query", + "ts": 1719000000 +} +``` + +**响应:** + +```json +{ + "msg_id": 2, + "cmd": "dev_info_query", + "ts": 1719000001, + "code": 0, + "msg": "success", + "data": { + "dev_serial": "A1B2C3D4E5F6", + "hard_ver": "1.1", + "soft_ver": "1.1", + "model": "DLD960", + "product_code": "960001", + "sub_code": { + "net": true, + "iot": true + }, + "bus": { + "bus1": 0, + "bus2": 0, + "bus3": 0, + "bus4": 0 + } + } +} +``` + +| data 字段 | 类型 | 说明 | +|-----------|------|------| +| `dev_serial` | string | 12 位十六进制序列码 | +| `hard_ver` | string | 硬件版本,格式 `"主.次"` | +| `soft_ver` | string | 软件版本,格式 `"主.次"` | +| `model` | string | 产品型号,1~10 字符 | +| `product_code` | string | 产品编码,6 位数字字符串 | +| `sub_code.net` | bool | 网络功能是否启用 | +| `sub_code.iot` | bool | IoT/MQTT 功能是否启用 | +| `bus.bus1~4` | uint8 | 各总线探头数 | + +## 4.3 设置 SSC 网络配置 `ssc_net_set` + +> Topic: `dld960/{sn}/srv/config/set` + +**请求:** + +```json +{ + "msg_id": 3, + "cmd": "ssc_net_set", + "ts": 1719000000, + "data": { + "dev_ip": "192.168.1.100", + "subnet_mask": "255.255.255.0", + "route_ip": "192.168.1.1", + "lssc_ip": "192.168.1.200", + "dns": "8.8.8.8", + "port": 502 + } +} +``` + +| data 字段 | 类型 | 说明 | +|-----------|------|------| +| `dev_ip` | string | 设备 IP 地址 | +| `subnet_mask` | string | 子网掩码 | +| `route_ip` | string | 网关地址 | +| `lssc_ip` | string | LSSC 服务器 IP | +| `dns` | string | DNS 服务器 IP | +| `port` | uint16 | 端口号 | + +**响应:** + +```json +{ + "msg_id": 3, + "cmd": "ssc_net_set", + "ts": 1719000001, + "code": 0, + "msg": "success" +} +``` + +## 4.4 查询 SSC 网络配置 `ssc_net_query` + +> Topic: `dld960/{sn}/srv/config/query` + +**请求:** + +```json +{ + "msg_id": 4, + "cmd": "ssc_net_query", + "ts": 1719000000 +} +``` + +**响应:** 返回字段同 4.3 的 `data`。 + +## 4.5 设置 IoT 网络配置 `iot_net_set` + +> Topic: `dld960/{sn}/srv/config/set` + +**请求:** + +```json +{ + "msg_id": 5, + "cmd": "iot_net_set", + "ts": 1719000000, + "data": { + "host": "mqtt.example.com", + "port": 1883, + "client_id": "dld960_A1B2C3D4E5F6", + "username": "admin", + "password": "secret" + } +} +``` + +| data 字段 | 类型 | 说明 | +|-----------|------|------| +| `host` | string | MQTT Broker 域名或 IP | +| `port` | uint16 | MQTT 端口,默认 1883 | +| `client_id` | string | MQTT Client ID,空时用空格 | +| `username` | string | MQTT 用户名 | +| `password` | string | MQTT 密码 | + +**响应:** 标准成功/失败。 + +## 4.6 查询 IoT 网络配置 `iot_net_query` + +> Topic: `dld960/{sn}/srv/config/query` + +**请求:** + +```json +{ + "msg_id": 6, + "cmd": "iot_net_query", + "ts": 1719000000 +} +``` + +**响应:** 返回字段同 4.5 的 `data`。 + +## 4.7 设置设备 Topic `iot_topic_set` + +> Topic: `dld960/{sn}/srv/config/set` + +**请求:** + +```json +{ + "msg_id": 7, + "cmd": "iot_topic_set", + "ts": 1719000000, + "data": { + "client_id_enable": true, + "topic_pub": "dld960/data/A1B2C3D4E5F6", + "topic_sub": "dld960/cmd/A1B2C3D4E5F6" + } +} +``` + +**响应:** 标准成功/失败。 + +## 4.8 查询设备 Topic `iot_topic_query` + +> Topic: `dld960/{sn}/srv/config/query` + +**请求:** + +```json +{ + "msg_id": 8, + "cmd": "iot_topic_query", + "ts": 1719000000 +} +``` + +**响应:** 返回字段同 4.7 的 `data`。 + +## 4.9 验证设备密码 `pwd_verify` + +> Topic: `dld960/{sn}/srv/ctrl` + +**请求:** + +```json +{ + "msg_id": 9, + "cmd": "pwd_verify", + "ts": 1719000000, + "data": { + "password": "123456" + } +} +``` + +| data 字段 | 类型 | 说明 | +|-----------|------|------| +| `password` | string | 6 位数字密码 | + +**响应:** + +```json +{ + "msg_id": 9, + "cmd": "pwd_verify", + "ts": 1719000001, + "code": 0, + "msg": "success" +} +``` + +## 4.10 设置设备密码 `pwd_set` + +> Topic: `dld960/{sn}/srv/ctrl` + +**请求:** + +```json +{ + "msg_id": 10, + "cmd": "pwd_set", + "ts": 1719000000, + "data": { + "old_password": "123456", + "new_password": "654321" + } +} +``` + +**响应:** 标准成功/失败。旧密码错误时 `code=2`。 + +## 4.11 设备出厂初始化 `factory_reset` + +> Topic: `dld960/{sn}/srv/ctrl` + +**请求:** + +```json +{ + "msg_id": 11, + "cmd": "factory_reset", + "ts": 1719000000 +} +``` + +**响应:** + +```json +{ + "msg_id": 11, + "cmd": "factory_reset", + "ts": 1719000001, + "code": 0, + "msg": "success" +} +``` + +## 4.12 设备复位 `device_reset` + +> Topic: `dld960/{sn}/srv/ctrl` + +**请求:** + +```json +{ + "msg_id": 12, + "cmd": "device_reset", + "ts": 1719000000 +} +``` + +无响应(设备复位后断开连接)。 + +## 4.13 设置车检器多路参数 `loop_param_set` + +> Topic: `dld960/{sn}/srv/config/set` + +**请求:** + +```json +{ + "msg_id": 13, + "cmd": "loop_param_set", + "ts": 1719000000, + "data": { + "auto_mode": false, + "channels": [ + { + "ch": 1, + "sensitivity": 7, + "freq_level": "high", + "loop_delay": 0, + "output_mode": "exist", + "exist_mode": 0, + "direction_mode": 0, + "safe_mode": 0, + "function_mode": 0 + }, + { + "ch": 2, + "sensitivity": 7, + "freq_level": "mid_high", + "loop_delay": 5, + "output_mode": "enter_pulse", + "exist_mode": 10, + "direction_mode": 0, + "safe_mode": 0, + "function_mode": 0 + }, + { + "ch": 3, + "sensitivity": 5, + "freq_level": "mid_low", + "loop_delay": 0, + "output_mode": "exist", + "exist_mode": 0, + "direction_mode": 1, + "safe_mode": 5, + "function_mode": 0 + }, + { + "ch": 4, + "sensitivity": 8, + "freq_level": "low", + "loop_delay": 10, + "output_mode": "leave_pulse", + "exist_mode": 15, + "direction_mode": 0, + "safe_mode": 0, + "function_mode": 0 + } + ] + } +} +``` + +| data 字段 | 类型 | 说明 | +|-----------|------|------| +| `auto_mode` | bool | 自动调频模式,默认 false | +| `channels` | array | 各路通道参数,1~4 路 | +| `channels[].ch` | uint8 | 通道号 1~4 | +| `channels[].sensitivity` | uint8 | 灵敏度 0~9,默认 7 | +| `channels[].freq_level` | string | `"high"`(33nF) / `"mid_high"`(43nF) / `"mid_low"`(66nF) / `"low"`(76nF) | +| `channels[].loop_delay` | uint8 | 延时时间,0~200(×0.1s),最大 20s | +| `channels[].output_mode` | string | `"exist"` / `"enter_pulse"` / `"leave_pulse"` / `"direction"` | +| `channels[].exist_mode` | uint8 | 存在方式,0=永久,非0=分钟数 | +| `channels[].direction_mode` | uint8 | 方向判别模式,0=触发,1~6=方向输出 | +| `channels[].safe_mode` | uint8 | 安全模式,0=关闭,非0=分钟数 | +| `channels[].function_mode` | uint8 | 功能模式 | + +**响应:** + +```json +{ + "msg_id": 13, + "cmd": "loop_param_set", + "ts": 1719000001, + "code": 0, + "msg": "success" +} +``` + +## 4.14 读取车检器多路参数 `loop_param_query` + +> Topic: `dld960/{sn}/srv/config/query` + +**请求:** + +```json +{ + "msg_id": 14, + "cmd": "loop_param_query", + "ts": 1719000000 +} +``` + +**响应:** + +```json +{ + "msg_id": 14, + "cmd": "loop_param_query", + "ts": 1719000001, + "code": 0, + "msg": "success", + "data": { + "auto_mode": false, + "channels": [ + { + "ch": 1, + "sensitivity": 7, + "freq_level": "high", + "loop_delay": 0, + "output_mode": "exist", + "exist_mode": 0, + "direction_mode": 0, + "safe_mode": 0, + "function_mode": 0, + "freq_initial": 105300, + "freq_current": 105280, + "freq_diff": 20 + } + ] + } +} +``` + +| 额外字段 | 类型 | 单位 | 说明 | +|----------|------|------|------| +| `freq_initial` | uint32 | Hz | 初始频率 | +| `freq_current` | uint32 | Hz | 当前实时频率 | +| `freq_diff` | uint32 | Hz | 频率变化量(绝对值) | + +## 4.15 设置主动上报 `report_config` + +> Topic: `dld960/{sn}/srv/ctrl` + +**请求:** + +```json +{ + "msg_id": 15, + "cmd": "report_config", + "ts": 1719000000, + "data": { + "sensor_type": 12, + "enable": true, + "once": false, + "env_eval": false, + "interval": 5, + "ack_required": false, + "timeout": 0 + } +} +``` + +| data 字段 | 类型 | 说明 | +|-----------|------|------| +| `sensor_type` | uint8 | 传感器类型,线圈=0x0C(12) | +| `enable` | bool | 是否使能主动上报 | +| `once` | bool | 仅上报一次(查询模式) | +| `env_eval` | bool | 环境评估使能 | +| `interval` | uint8 | 上报间隔(秒),0=实时 | +| `ack_required` | bool | 上报是否需要确认 | +| `timeout` | uint8 | 超时时间(分钟),0=无限制 | + +**响应:** 标准成功/失败。 + +--- + +# 5 设备主动上报 + +## 5.1 线圈传感数据 `loop_data` + +> Topic: `dld960/{sn}/dev/data/loop` +> QoS: 0/1 + +```json +{ + "msg_id": 100, + "cmd": "loop_data", + "ts": 1719000100, + "data": { + "channels": [ + { + "ch": 1, + "freq_level": "high", + "has_car": false, + "loop_ok": true, + "freq_current": 105280, + "freq_diff": 20, + "sensitivity": 7, + "condition": 0, + "misc": { + "type": "time", + "value": 0 + } + }, + { + "ch": 2, + "freq_level": "mid_high", + "has_car": true, + "loop_ok": true, + "freq_current": 98700, + "freq_diff": 1500, + "sensitivity": 7, + "condition": 2, + "misc": { + "type": "time", + "value": 350 + } + }, + { + "ch": 3, + "freq_level": "mid_low", + "has_car": false, + "loop_ok": false, + "freq_current": 0, + "freq_diff": 0, + "sensitivity": 5, + "condition": 0, + "misc": { + "type": "cut_count", + "value": 3 + } + }, + { + "ch": 4, + "freq_level": "low", + "has_car": false, + "loop_ok": true, + "freq_current": 62100, + "freq_diff": 5, + "sensitivity": 8, + "condition": 0, + "misc": { + "type": "flow_count", + "value": 128 + } + } + ] + } +} +``` + +| 通道字段 | 类型 | 说明 | +|----------|------|------| +| `ch` | uint8 | 通道号 1~4 | +| `freq_level` | string | 线圈高低频档位 | +| `has_car` | bool | 是否有车 | +| `loop_ok` | bool | 线圈是否正常(false=断开) | +| `freq_current` | uint32 | 当前频率 (Hz) | +| `freq_diff` | uint32 | 频率变化量 (Hz) | +| `sensitivity` | uint8 | 当前灵敏度等级 | +| `condition` | uint8 | 环境状态评估值(越大干扰越大) | +| `misc.type` | string | `"time"`(时间量) / `"cut_count"`(断开次数) / `"flow_count"`(车流量) | +| `misc.value` | uint32 | 杂项数值(时间量单位 5ms) | + +## 5.2 事件上报 `event_report` + +> Topic: `dld960/{sn}/dev/data/event` + +设备检测到事件时主动上报,非周期性。 + +```json +{ + "msg_id": 101, + "cmd": "event_report", + "ts": 1719000200, + "data": { + "events": [ + { + "type": "car_enter", + "ch": 2, + "value": 0 + }, + { + "type": "car_leave", + "ch": 2, + "value": 350 + }, + { + "type": "loop_cut", + "ch": 3, + "value": 0 + } + ] + } +} +``` + +| 事件类型 `type` | 说明 | `value` 含义 | +|----------------|------|-------------| +| `car_enter` | 车辆进入 | 0 | +| `car_leave` | 车辆离开 | 通过时间 (×5ms) | +| `loop_cut` | 线圈断开 | 0 | +| `loop_restore` | 线圈恢复 | 断开持续时长 (×5ms) | + +## 5.3 设备心跳 `heartbeat` + +> Topic: `dld960/{sn}/dev/status` +> 周期:默认 60 秒 + +```json +{ + "msg_id": 200, + "cmd": "heartbeat", + "ts": 1719000060, + "data": { + "uptime": 3600, + "loop_status": [true, true, false, true], + "net_status": true, + "iot_status": true + } +} +``` + +| data 字段 | 类型 | 说明 | +|-----------|------|------| +| `uptime` | uint32 | 设备运行时长(秒) | +| `loop_status` | bool[4] | 各路线圈是否正常 | +| `net_status` | bool | 以太网连接状态 | +| `iot_status` | bool | MQTT 连接状态 | + +--- + +# 修订记录 + +| 版本 | 修订时间 | 修订说明 | 修订人 | +|------|----------|----------|--------| +| V1.00 | 2026-06-22 | 初始版本,基于串口协议 V1.01 | wangfq | diff --git a/docs/DLD960_TCP_JSON协议.md b/docs/DLD960_TCP_JSON协议.md new file mode 100644 index 0000000..69a0f43 --- /dev/null +++ b/docs/DLD960_TCP_JSON协议.md @@ -0,0 +1,423 @@ +# DLD960 TCP 接口协议(JSON) + +> 基于《DLD960 串口通信协议》V1.01,提供以太网 TCP 通道的 JSON 交互协议。 +> 适用于上位机、调试工具等直接 TCP 连接场景。 + +--- + +# 1 通信说明 + +## 1.1 连接参数 + +| 项目 | 说明 | +|------|------| +| 传输层 | TCP | +| 默认端口 | 502 | +| 编码 | UTF-8 | +| 序列化 | JSON | +| 帧分隔 | 换行符 `\n`(每个 JSON 对象占一行) | +| 最大帧长 | 4096 字节 | + +## 1.2 通信模式 + +- **请求-响应**:客户端发送命令,设备返回响应(同步或异步) +- **主动推送**:设备可主动推送数据(线圈数据、事件) +- **连接保持**:支持长连接,60 秒无数据心跳超时断开 + +## 1.3 连接流程 + +``` +Client Device (DLD960) + | | + |--- TCP Connect ------------------>| + | | + |--- pwd_verify (鉴权) ------------>| + |<-- 鉴权成功 / 失败 ---------------| + | | + |--- 命令 1 ----------------------->| + |<-- 响应 1 ------------------------| + | | + |--- 命令 2 ----------------------->| + |<-- 响应 2 ------------------------| + | | + |<-- 主动推送 (loop_data/event) ----| + | | + |--- TCP Close / 超时 ------------->| +``` + +--- + +# 2 JSON 消息格式 + +## 2.1 请求帧 + +```json +{"msg_id":1,"cmd":"dev_info_query","ts":1719000000,"data":{...}} +``` + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `msg_id` | uint32 | 是 | 消息序列号,递增,用于请求-响应匹配 | +| `cmd` | string | 是 | 命令标识符 | +| `ts` | uint32 | 否 | Unix 时间戳(秒) | +| `data` | object | 否 | 命令参数 | + +## 2.2 响应帧 + +```json +{"msg_id":1,"cmd":"dev_info_query","ts":1719000001,"code":0,"msg":"success","data":{...}} +``` + +| 字段 | 类型 | 必填 | 说明 | +|------|------|------|------| +| `msg_id` | uint32 | 是 | 对应请求的 msg_id | +| `cmd` | string | 是 | 命令标识符(与请求一致) | +| `ts` | uint32 | 否 | 响应时间戳 | +| `code` | int | 是 | 0=成功,非0=错误码 | +| `msg` | string | 是 | 结果描述 | +| `data` | object | 否 | 响应数据 | + +## 2.3 主动推送帧 + +```json +{"msg_id":100,"cmd":"loop_data","ts":1719000100,"data":{...}} +``` + +> 设备主动推送无 `code`/`msg` 字段,由 `cmd` 区分类型。 + +## 2.4 错误码 + +| code | 说明 | +|------|------| +| 0 | 成功 | +| 1 | 参数错误(格式/范围不正确) | +| 2 | 密码验证失败 / 未鉴权 | +| 3 | 设备忙 | +| 4 | 不支持的命令 | +| 5 | 内部错误 | +| 6 | 数据超长 | +| 7 | 连接未鉴权(需先执行 pwd_verify) | + +--- + +# 3 命令详表 + +| cmd | 说明 | 需鉴权 | 对应串口 | +|-----|------|--------|----------| +| `pwd_verify` | 验证设备密码(连接鉴权) | 否 | 0x1C | +| `dev_serial_set` | 更改设备序列码 | 是 | 0x09 | +| `dev_info_query` | 查询设备信息 | 是 | 0x10 | +| `ssc_net_set` | 设置 SSC 网络配置 | 是 | 0x11 | +| `ssc_net_query` | 查询 SSC 网络配置 | 是 | 0x12 | +| `iot_net_set` | 设置 IoT 网络配置 | 是 | 0x13 | +| `iot_net_query` | 查询 IoT 网络配置 | 是 | 0x14 | +| `iot_topic_set` | 设置设备 Topic | 是 | 0x15 | +| `iot_topic_query` | 查询设备 Topic | 是 | 0x16 | +| `pwd_set` | 设置设备密码 | 是 | 0x1D | +| `factory_reset` | 设备出厂初始化 | 是 | 0x1E | +| `device_reset` | 设备复位 | 是 | 0x1F | +| `loop_param_set` | 设置车检器多路参数 | 是 | 0x63 | +| `loop_param_query` | 读取车检器多路参数 | 是 | 0x64 | +| `report_config` | 设置主动上报 | 是 | 0xC5 | +| 主动推送 | | | | +| `loop_data` | 线圈传感数据(设备→客户端) | — | 0xC0 | +| `event_report` | 事件上报(设备→客户端) | — | — | + +--- + +# 4 命令详情 + +## 4.1 验证设备密码 `pwd_verify` + +> 连接后首个命令,鉴权通过后才能执行其他命令。 +> 60 秒内未鉴权则断开连接。 + +**请求:** + +```json +{"msg_id":1,"cmd":"pwd_verify","ts":1719000000,"data":{"password":"123456"}} +``` + +| data 字段 | 类型 | 说明 | +|-----------|------|------| +| `password` | string | 6 位数字密码 | + +**响应(成功):** + +```json +{"msg_id":1,"cmd":"pwd_verify","ts":1719000001,"code":0,"msg":"success"} +``` + +**响应(失败):** + +```json +{"msg_id":1,"cmd":"pwd_verify","ts":1719000001,"code":2,"msg":"password incorrect"} +``` + +连续 3 次密码错误,设备断开连接并锁定 60 秒。 + +## 4.2 更改设备序列码 `dev_serial_set` + +**请求:** + +```json +{"msg_id":2,"cmd":"dev_serial_set","ts":1719000002,"data":{"dev_serial":"A1B2C3D4E5F6"}} +``` + +**响应:** + +```json +{"msg_id":2,"cmd":"dev_serial_set","ts":1719000003,"code":0,"msg":"success"} +``` + +## 4.3 查询设备信息 `dev_info_query` + +**请求:** + +```json +{"msg_id":3,"cmd":"dev_info_query","ts":1719000004} +``` + +**响应:** + +```json +{"msg_id":3,"cmd":"dev_info_query","ts":1719000005,"code":0,"msg":"success","data":{"dev_serial":"A1B2C3D4E5F6","hard_ver":"1.1","soft_ver":"1.1","model":"DLD960","product_code":"960001","sub_code":{"net":true,"iot":true},"bus":{"bus1":0,"bus2":0,"bus3":0,"bus4":0}}} +``` + +## 4.4 设置 SSC 网络配置 `ssc_net_set` + +**请求:** + +```json +{"msg_id":4,"cmd":"ssc_net_set","ts":1719000006,"data":{"dev_ip":"192.168.1.100","subnet_mask":"255.255.255.0","route_ip":"192.168.1.1","lssc_ip":"192.168.1.200","dns":"8.8.8.8","port":502}} +``` + +**响应:** 标准成功/失败。 + +## 4.5 查询 SSC 网络配置 `ssc_net_query` + +**请求:** + +```json +{"msg_id":5,"cmd":"ssc_net_query","ts":1719000008} +``` + +**响应:** `data` 字段同 4.4。 + +## 4.6 设置 IoT 网络配置 `iot_net_set` + +**请求:** + +```json +{"msg_id":6,"cmd":"iot_net_set","ts":1719000010,"data":{"host":"mqtt.example.com","port":1883,"client_id":"dld960_A1B2C3D4E5F6","username":"admin","password":"secret"}} +``` + +## 4.7 查询 IoT 网络配置 `iot_net_query` + +**请求:** + +```json +{"msg_id":7,"cmd":"iot_net_query","ts":1719000012} +``` + +## 4.8 设置设备 Topic `iot_topic_set` + +**请求:** + +```json +{"msg_id":8,"cmd":"iot_topic_set","ts":1719000014,"data":{"client_id_enable":true,"topic_pub":"dld960/data/A1B2C3D4E5F6","topic_sub":"dld960/cmd/A1B2C3D4E5F6"}} +``` + +## 4.9 查询设备 Topic `iot_topic_query` + +**请求:** + +```json +{"msg_id":9,"cmd":"iot_topic_query","ts":1719000016} +``` + +## 4.10 设置设备密码 `pwd_set` + +**请求:** + +```json +{"msg_id":10,"cmd":"pwd_set","ts":1719000018,"data":{"old_password":"123456","new_password":"654321"}} +``` + +## 4.11 设备出厂初始化 `factory_reset` + +**请求:** + +```json +{"msg_id":11,"cmd":"factory_reset","ts":1719000020} +``` + +> 执行后所有配置恢复出厂值,连接可能断开。 + +## 4.12 设备复位 `device_reset` + +**请求:** + +```json +{"msg_id":12,"cmd":"device_reset","ts":1719000022} +``` + +> 无响应,设备立即复位。 + +## 4.13 设置车检器多路参数 `loop_param_set` + +**请求:** + +```json +{"msg_id":13,"cmd":"loop_param_set","ts":1719000024,"data":{"auto_mode":false,"channels":[{"ch":1,"sensitivity":7,"freq_level":"high","loop_delay":0,"output_mode":"exist","exist_mode":0,"direction_mode":0,"safe_mode":0,"function_mode":0},{"ch":2,"sensitivity":7,"freq_level":"mid_high","loop_delay":5,"output_mode":"enter_pulse","exist_mode":10,"direction_mode":0,"safe_mode":0,"function_mode":0},{"ch":3,"sensitivity":5,"freq_level":"mid_low","loop_delay":0,"output_mode":"exist","exist_mode":0,"direction_mode":1,"safe_mode":5,"function_mode":0},{"ch":4,"sensitivity":8,"freq_level":"low","loop_delay":10,"output_mode":"leave_pulse","exist_mode":15,"direction_mode":0,"safe_mode":0,"function_mode":0}]}} +``` + +| `channels[]` 字段 | 类型 | 范围 | 说明 | +|-------------------|------|------|------| +| `ch` | uint8 | 1~4 | 通道号 | +| `sensitivity` | uint8 | 0~9 | 灵敏度,默认 7 | +| `freq_level` | string | 见下 | 线圈高低频档位 | +| `loop_delay` | uint8 | 0~200 | 延时 ×0.1s,最大 20s | +| `output_mode` | string | 见下 | 输出方式 | +| `exist_mode` | uint8 | 0~255 | 0=永久,非0=分钟 | +| `direction_mode` | uint8 | 0~6 | 0=触发,1~6=方向输出 | +| `safe_mode` | uint8 | 0~255 | 0=关闭,非0=分钟 | +| `function_mode` | uint8 | 0~15 | 功能模式 | + +**freq_level 枚举:** + +| 值 | 说明 | +|----|------| +| `"high"` | 高频 (33nF) | +| `"mid_high"` | 中高频 (43nF) | +| `"mid_low"` | 中低频 (66nF) | +| `"low"` | 低频 (76nF) | + +**output_mode 枚举:** + +| 值 | 说明 | +|----|------| +| `"exist"` | 存在输出 | +| `"enter_pulse"` | 进入脉冲 | +| `"leave_pulse"` | 离开脉冲 | +| `"direction"` | 方向判别 | + +## 4.14 读取车检器多路参数 `loop_param_query` + +**请求:** + +```json +{"msg_id":14,"cmd":"loop_param_query","ts":1719000026} +``` + +**响应:** + +```json +{"msg_id":14,"cmd":"loop_param_query","ts":1719000027,"code":0,"msg":"success","data":{"auto_mode":false,"channels":[{"ch":1,"sensitivity":7,"freq_level":"high","loop_delay":0,"output_mode":"exist","exist_mode":0,"direction_mode":0,"safe_mode":0,"function_mode":0,"freq_initial":105300,"freq_current":105280,"freq_diff":20},{"ch":2,"sensitivity":7,"freq_level":"mid_high","loop_delay":5,"output_mode":"enter_pulse","exist_mode":10,"direction_mode":0,"safe_mode":0,"function_mode":0,"freq_initial":100200,"freq_current":98700,"freq_diff":1500},{"ch":3,"sensitivity":5,"freq_level":"mid_low","loop_delay":0,"output_mode":"exist","exist_mode":0,"direction_mode":1,"safe_mode":5,"function_mode":0,"freq_initial":78100,"freq_current":0,"freq_diff":0},{"ch":4,"sensitivity":8,"freq_level":"low","loop_delay":10,"output_mode":"leave_pulse","exist_mode":15,"direction_mode":0,"safe_mode":0,"function_mode":0,"freq_initial":62100,"freq_current":62095,"freq_diff":5}]}} +``` + +| 额外字段 | 类型 | 单位 | 说明 | +|----------|------|------|------| +| `freq_initial` | uint32 | Hz | 初始频率 | +| `freq_current` | uint32 | Hz | 当前实时频率(线圈断开时为 0) | +| `freq_diff` | uint32 | Hz | 频率变化量 | + +## 4.15 设置主动上报 `report_config` + +**请求:** + +```json +{"msg_id":15,"cmd":"report_config","ts":1719000028,"data":{"sensor_type":12,"enable":true,"once":false,"env_eval":false,"interval":5,"ack_required":false,"timeout":0}} +``` + +| data 字段 | 类型 | 说明 | +|-----------|------|------| +| `sensor_type` | uint8 | 传感器类型,12=多路线圈(0x0C) | +| `enable` | bool | 使能主动上报 | +| `once` | bool | 仅上报一次 | +| `env_eval` | bool | 环境评估模式 | +| `interval` | uint8 | 上报间隔(秒),0=实时 | +| `ack_required` | bool | 上报是否需要客户端确认 | +| `timeout` | uint8 | 超时(分钟),0=无限制 | + +--- + +# 5 设备主动推送 + +主动推送帧与请求-响应共用同一条 TCP 连接,由设备在任意时刻发出。 + +## 5.1 线圈传感数据 `loop_data` + +```json +{"msg_id":100,"cmd":"loop_data","ts":1719000100,"data":{"channels":[{"ch":1,"freq_level":"high","has_car":false,"loop_ok":true,"freq_current":105280,"freq_diff":20,"sensitivity":7,"condition":0,"misc":{"type":"time","value":0}},{"ch":2,"freq_level":"mid_high","has_car":true,"loop_ok":true,"freq_current":98700,"freq_diff":1500,"sensitivity":7,"condition":2,"misc":{"type":"time","value":350}},{"ch":3,"freq_level":"mid_low","has_car":false,"loop_ok":false,"freq_current":0,"freq_diff":0,"sensitivity":5,"condition":0,"misc":{"type":"cut_count","value":3}},{"ch":4,"freq_level":"low","has_car":false,"loop_ok":true,"freq_current":62095,"freq_diff":5,"sensitivity":8,"condition":0,"misc":{"type":"flow_count","value":128}}]}} +``` + +| 通道字段 | 类型 | 说明 | +|----------|------|------| +| `ch` | uint8 | 通道号 1~4 | +| `freq_level` | string | 高低频档位 | +| `has_car` | bool | 有车/无车 | +| `loop_ok` | bool | 线圈正常/断开 | +| `freq_current` | uint32 | 当前频率 (Hz) | +| `freq_diff` | uint32 | 频率变化量 (Hz) | +| `sensitivity` | uint8 | 灵敏度等级 | +| `condition` | uint8 | 环境评估值 | +| `misc.type` | string | `"time"` / `"cut_count"` / `"flow_count"` | +| `misc.value` | uint32 | 对应数值 | + +## 5.2 事件上报 `event_report` + +```json +{"msg_id":101,"cmd":"event_report","ts":1719000200,"data":{"events":[{"type":"car_enter","ch":2,"value":0},{"type":"car_leave","ch":2,"value":350}]}} +``` + +| 事件类型 `type` | 说明 | `value` | +|----------------|------|---------| +| `car_enter` | 车辆进入 | 0 | +| `car_leave` | 车辆离开 | 通过时间 (×5ms) | +| `loop_cut` | 线圈断开 | 0 | +| `loop_restore` | 线圈恢复 | 断开持续时长 (×5ms) | + +--- + +# 6 交互示例 + +## 6.1 完整会话 + +``` +>>> {"msg_id":1,"cmd":"pwd_verify","ts":1719000000,"data":{"password":"123456"}} +<<< {"msg_id":1,"cmd":"pwd_verify","ts":1719000001,"code":0,"msg":"success"} + +>>> {"msg_id":2,"cmd":"dev_info_query","ts":1719000002} +<<< {"msg_id":2,"cmd":"dev_info_query","ts":1719000003,"code":0,"msg":"success","data":{...}} + +>>> {"msg_id":3,"cmd":"loop_param_query","ts":1719000004} +<<< {"msg_id":3,"cmd":"loop_param_query","ts":1719000005,"code":0,"msg":"success","data":{...}} + +>>> {"msg_id":4,"cmd":"report_config","ts":1719000006,"data":{"sensor_type":12,"enable":true,"interval":5}} +<<< {"msg_id":4,"cmd":"report_config","ts":1719000007,"code":0,"msg":"success"} + +... (5 秒后设备主动推送) ... + +<<< {"msg_id":100,"cmd":"loop_data","ts":1719000012,"data":{...}} +<<< {"msg_id":101,"cmd":"loop_data","ts":1719000017,"data":{...}} +<<< {"msg_id":102,"cmd":"event_report","ts":1719000020,"data":{"events":[{"type":"car_enter","ch":1,"value":0}]}} +``` + +--- + +# 7 帧解析说明 + +- 每个 JSON 对象为一行,以 `\n` (0x0A) 结尾 +- 解析时按行读取,提取完整 JSON 后解析 +- JSON 内部不含换行符(紧凑格式) +- 收到非 JSON 行则丢弃并返回错误 +- 帧长超过 4096 字节则断开连接 + +--- + +# 修订记录 + +| 版本 | 修订时间 | 修订说明 | 修订人 | +|------|----------|----------|--------| +| V1.00 | 2026-06-22 | 初始版本,基于串口协议 V1.01 | wangfq | diff --git a/docs/DLD960_串口通信协议.md b/docs/DLD960_串口通信协议.md new file mode 100644 index 0000000..dd7af36 --- /dev/null +++ b/docs/DLD960_串口通信协议.md @@ -0,0 +1,353 @@ +# DLD960 串口通信协议 + +# 1 通信说明 + +## 1.1 通信方式 + +串口通信,波特率:115200 + +# 2 协议格式 + +Package + +| 1Byte | 3Bytes | 0~64Bytes | 2Bytes | +| --- | --- | --- | --- | +| Magic byte | Header | Value | Check Bytes | + +## 2.1 Magic Byte(1Byte) + +标识协议类型,也表示数据包开始信息。 + +| Magic Byte | 说明 | +| --- | --- | +| 0x7F | 屏、地感检测、探头的配置和查询协议,或者部分雷达的协议 | +| 0x8F | 支持DBN查询和配置的专有协议 | + +## 2.2 Header(3Bytes) + +当Magic Byte为 0x7F时,Header字节定义如下: + +| 1Byte | 1Byte | 1Byte | +| --- | --- | --- | +| Addr 地址 | LEN 数据长度 | CMD 命令字节 | + +* LEN数据长度,表示数据包的有效数据(Value)长度,包括命令(CMD Byte)和数据(Data Bytes); +* CMD 命令字节; +* 该协议的详细说明参考《DCP101点阵驱动说明》以及相关的地感检测485协议 + +当Magic Byte为0x8F时,Header字节定义如下: + +| 1Byte | 1Byte | 1Byte | +| --- | --- | --- | +| SubPkgFlag 分包标记 | LEN 数据长度 | CMD 命令字节 | + +> 分包标记 SubPkgFlag,高四位表示分包数量SubAmount,低四位表示为当前分包中第几个分包SubSequence,其中SubSequence = [1,SubAmount]: +* 00表示无分包,是一条数据完整的记录; +* 当SubAmount不为0时,SubSequence从1开始到SubAmount结束,整合为一条完整的数据包。 + +## 2.3 校验字节(Check Bytes:2Bytes) + +当Magic Byte为0x7F时,校验字节实现参考《DCP101点阵驱动说明》《DPG100 485通信协议》 和相关的地感检测485协议说明,部分雷探头的协议也需要支持0x7F。 +当Magic Byte为0x8F时,校验字节实现如下: + +| 1Byte | 1Byte | +| --- | --- | +| XOR 异或校验 | SUM 和校验 | + +> XOR 异或校验,校验从分包标记字节开始,到命令数据的最后一个字节结束; +> SUM 和校验,校验从分包标记字节开始,到命令数据的最后一个字节结束。 + +# 3 Cmd详解 + +## 3.1 更改设备序列码(0x09) + +| | Header | Dev_Serial | +| --- | --- | --- | +| **Value(Hex)** | 00 08 09 | xx | +| **Length** | 3 Byte | 6 Byte | + +返回: + +| | Header | status | +| --- | --- | --- | +| **Value(Hex)** | 00 01 11 | 00/01 | +| **Length** | 3 Byte | 1 Byte | + +> **status**: 00 success, 01 fail + +## 3.2 查询设备信息命令(0x10) + +| | Header | Data Value | +| --- | --- | --- | +| **Value(Hex)** | 00 01 10 | | +| **Length** | 3 Byte | 0 Byte | + +返回: + +| | Header | Dev_Serial | Hard Ver | Soft Ver | Model | Num | Sub_Code | Bus1 | Bus2 | Bus3 | Bus4 | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | +| **Value(Hex)** | 00 1C 10 | xx | 01 01 | 01 01 | xx | xx | xx | xx | xx | xx | xx | +| **Length** | 3 Byte | 6 Byte | 2 Byte | 2 Byte | 7~10 Byte | 6 Byte | 2 Byte | 1 Byte | 1 Byte | 1 Byte | 1 Byte | +| **Describe** | | 序列码 | 硬件版本号 | 软件版本号 | 产品型号 | 产品编码 | 子功能代码 | 总线1探头数 | 总线2 | 总线3 | 总线4 | + +> Model: 当首字节的值在[1,12]内时表示Mode的有效字节长度。 +> Sub_Code: 表示子功能代码 `SUB_CODE`,各个比特位对应不同的子功能,0表示禁用,1表示启用 + +| [0] | [1] | [2] | [3] | [4] | [5] | [6] | [7] | +| --- | --- | --- | --- | --- | --- | --- | --- | +| net | iot | RFU | RFU | RFU | RFU | RFU | RFU | +| 网络 | MQTT | | | | | | | + +| [8] | [9] | [10] | [11] | [12] | [13] | [14] | [15] | +| --- | --- | --- | --- | --- | --- | --- | --- | +| RFU | RFU | RFU | RFU | RFU | RFU | RFU | RFU | +| | | | | | | | | + +## 3.3 设置SSC网络配置(0x11) + +| | Header | Dev IP | Subnet Mask | Route IP | LSSC IP | DNS | Port | +| --- | --- | --- | --- | --- | --- | --- | --- | +| **Value(Hex)** | 00 19 11 | xx | xx | xx | xx | xx | xx | +| **Length** | 3 Byte | 4 Byte | 4 Byte | 4 Byte | 4 Byte | 4 Byte | 10 Byte | + +返回: + +| | Header | status | +| --- | --- | --- | +| **Value(Hex)** | 00 01 11 | 00/01 | +| **Length** | 3 Byte | 1 Byte | + +> **status**: 00 success, 01 fail + +## 3.4 查询SSC网络配置(0x12) + +| | Header | Data | +| --- | --- | --- | +| **Value(Hex)** | 00 01 12 | | +| **Length** | 3 Byte | 0 Byte | + +返回: + +| | Header | Dev IP | Subnet Mask | Route IP | LSSC IP | DNS | Port | +| --- | --- | --- | --- | --- | --- | --- | --- | +| **Value(Hex)** | 00 19 12 | xx | xx | xx | xx | xx | 00 | +| **Length** | 3 Byte | 4 Byte | 4 Byte | 4 Byte | 4 Byte | 4 Byte | 10 Byte | + +## 3.5 设置IoT网络配置(0x13) + +| | Header | IoT Host(Domain name/IP) + Port + ClientID + Username + Password | +| --- | --- | --- | +| **Value(Hex)** | xx xx 13 | xx 00 xx 00 xx 00 xx 00 xx | +| **Length** | 3 Byte | xx Byte | + +> 注: +* 数据部分的不同字段通过 0x00 分隔 +* ClientID 为空时用一个空格符替代 + +返回: + +| | Header | Status | +| --- | --- | --- | +| **Value(Hex)** | 00 01 13 | 00/01 | +| **Length** | 3 Byte | 1 Byte | + +> **Status**: 00 success, 01 failed + +## 3.6 查询IoT网络配置(0x14) + +| | Header | Data | +| --- | --- | --- | +| **Value(Hex)** | 00 01 14 | | +| **Length** | 3 Byte | 0 Byte | + +返回: + +| | Header | IoT Host(Domain name/IP) | +| --- | --- | --- | +| **Value(Hex)** | 00 xx 14 | xx | +| **Length** | 3 Byte | xx Byte | + +## 3.7 设置设备Topic(0x15) + +| | Header | ClientID_Enable + Topic_Pub + Topic_Sub | +| --- | --- | --- | +| **Value(Hex)** | xx xx 15 | xx 00 xx 00 | +| **Length** | 3 Byte | xx Byte | + +* 数据部分不同字段通过0x00 来分隔 +* Client_Enable: 0x00 disable, 0x01 enable + +返回: + +| | Header | Status | +| --- | --- | --- | +| **Value(Hex)** | 00 01 15 | 00/01 | +| **Length** | 3 Byte | 1 Byte | + +> **Status**: 00 success, 01 failed + +## 3.8 查询设备Topic(0x16) + +发送: + +| | Header | | +| --- | --- | --- | +| **Value(Hex)** | 00 01 16 | | +| **Length** | 3 Byte | | + +> **Status**: 00 success, 01 failed + +返回: + +| | Header | ClientID_Enable + Topic_Pub + Topic_Sub | +| --- | --- | --- | +| **Value(Hex)** | xx xx 16 | xx 00 xx 00 | +| **Length** | 3 Byte | xx Byte | + +## 3.9 验证设备密码(0x1C) + +| | Header | Password | +| --- | --- | --- | +| **Value(Hex)** | 00 07 1C | 31 32 33 34 35 36 | +| **Length** | 3 Byte | 6 Byte | + +返回: + +| | Header | Status | +| --- | --- | --- | +| **Value(Hex)** | 00 01 1C | 00/01 | +| **Length** | 3 Byte | 1 Byte | + +> Status: 00 Success, 01 Failed + +## 3.10 设置设备密码(0x1D) + +| | Header | Old Password | New Password | +| --- | --- | --- | --- | +| **Value(Hex)** | 00 0D 1D | | | +| **Length** | 3 Byte | 6 Byte | 6 Byte | + +返回: + +| | Header | Status | +| --- | --- | --- | +| **Value(Hex)** | 00 02 1D | 00/01 | +| **Length** | 3 Byte | 1 Byte | + +## 3.11 设备出厂初始化(0x1E) + +| | Header | Data | +| --- | --- | --- | +| **Value(Hex)** | 00 01 1E | | +| **Length** | 3 Byte | 0Byte | + +返回: + +| | Header | Status | +| --- | --- | --- | +| **Value(Hex)** | 00 02 1E | 00/01 | +| **Length** | 3 Byte | 1 Byte | + +## 3.12 设备复位(0x1F) + +| | Header | Data | +| --- | --- | --- | +| **Value(Hex)** | 00 01 1F | | +| **Length** | 3 Byte | 0 Byte | + +设备无回复。 + +## 3.13 设置车检器多路参数(0x63) + +| | Header | AutoMode + Amount + Param[Sensitivity, Loop_Delay, Output_Mode, Exist_Mode, Direction_Mode] | +| --- | --- | --- | +| **Value(Hex)** | 00 xx 63 | xx | +| **Length** | 3 Byte | (2 + 5 * Amount) Byte | + +* AutoMode: 是否处于自动模式(自动调频),0表示不启用,默认0。 +* Sensitivity: 低四位表示灵敏度,0~9级,值越大,灵敏度越高,默认7;高四位表示高低频,其中,[4,5]表示线圈的高低频。 +* Loop_Delay: 地感延时时间,0~200, 0.1s为一级,延时时间范围:[0, 20秒]; +* Output_Mode: 低三位有效,地感输出方式,0 - 存在输出,1-进入脉冲,2-离开脉冲,3-方向判别;高5位表示SafeMode:是否开启安全模式, 0 关闭,非 0 开启安全模式,分钟为单位。 +* Exist_Mode:低四位表示地感存在方式,0-永久存在,非0-有限存在的分钟数; +* Direction_Mode: + * 低三位表示方向判别模式,0 表示触发模式, 1-6 表示方向判别的输出模式,对应以前的 0-5, update 2023-02-24; + * 高四位表示Function_Mode,功能模式,是否启用特殊的模式 + +| | Header | Status | +| --- | --- | --- | +| **Value(Hex)** | 00 02 63 | 00/01 | +| **Length** | 3 Byte | 1 Byte | + +## 3.14 读取车检器多路参数(0x64) + +| | Header | Param | +| --- | --- | --- | +| **Value(Hex)** | 00 01 64 | | +| **Length** | 3 Byte | | + +返回: + +| | Header | AutoMode+Amount + Data[Sensitivity, Loop_Delay, Output_Mode, Exist_Mode, Direction_Mode, freq1, freq2, freq3] | +| --- | --- | --- | +| **Value(Hex)** | 00 xx 64 | XX | +| **Length** | 3 Byte | (2 + 8 * Amount) Byte | + +## 3.15 设置主动上报(0xC5) + +设置主动上报是否使能、类型、时长等。 + +| 7Fh | ADDR | Len | C5 | SensType(1Byte) | Enable(1Byte) | Interval(1Byte) | Timeout(1Byte) | XOR | SUM | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | + +> Enable: 是否使能,第0位 0 禁用, 1 使能; 0x10表示只上报一次,此时相当于查询功能;第5位表示是否环境评估,如0x21,表示环境评估类型 +> Interval: 当最高位为0时,上报不需要确认,低七位表示上报间隔,0表示实时,低七位非0表示以秒为单位的上报的间隔;最高位为1时,表示上报需要回复确认。 +> Timeout: 单位:分钟;0表示没有时间限制。 + +## 3.16 设备主动上报传感信息(0xC0) + +设备主动上报传感信息指令,具体传感数据需要根据不同的类型进行解析。 + +| 7Fh | ADDR | Len | C0 | SensType(1Byte) | SubPkgFlag(1Byte) | SensData | XOR | SUM | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | + +SensType: 传感数据类型 +SubPkgFlag: 分包标记,高四位表示分包数量 SubAmount,低四位表示为当前分包中第几个分包 SubSequence,其中 SubSequence = [1,SubAmount]: +* 00 表示无分包,是一条数据完整的记录; +* 当SubAmount不为0时,SubSequence从1开始到SubAmount结束,整合为一条完整的数据包。 +* 当SensType为0x05时,SubPkgFlag作为传感数据使用。 +* 当SensType为0x06、0x07、0x09时,SubPkgFlag的Seq和SubAmount分开各用一个字节表示。 + +SensData:传感数据 + +| SensType | 类型说明 | SensData | 传感数据说明 | +| --- | --- | --- | --- | +| 0x0C | 多线圈传感信息 | | 四路线圈 | + +上报线圈传感数据单元(多路线圈,每一路线圈单元的配置) + +| 字段 | 字节数 | 内容 | 详情 | +| --- | --- | --- | --- | +| 配置 1 | 1 | freq_level, Direction,freq_type, sens | 线圈 1 配置
freq_level:高低频,两个比特位,00 表示高频(33nF),01表示中高(43nF), 10表示中低(66nF), 11表示低频(76nF)。
Direction: 0 表示触发,1 表示方向判别
freq_type: 0 表示初始频率,1 表示当前实时频率。
sens:低四位表示当前的灵敏度等级 | +| 线圈评估条件 | 1 | condition, loop_state | loop_condition 正常(0)有效,环境状态条件(环境状态评估值,值越大,干扰越大),高四位有效。低四位中,其中第3位表示线圈状态,0 表示正常,1 表示线圈断开;第 2 位表示有无车,0 表示无车,1 表示有车;低两位表示**杂项类型**,0b00表示时间量,0b01表示线圈断开次数;0b10表示车流量数 | +| 频率 1 | 3 | frequent | 低字节在前 | +| 变化量 1 | 2 | variation | 低字节在前 | +| 杂项 | 4 | in_out_passtime/cut_amount/flow_amount | **杂项类型**,可能是时间量,也可能是线圈断开次数、车流量数,说明:
1、通过时间或车间距,5ms为单位,最大计时()
2、线圈断开次数
3、车流量数 | + +eg: + +`7F 00 2F C0 0C 00 D2 00 00 00 00 00 00 00 00 00 00 52 00 00 00 00 00 00 00 00 00 00 92 00 00 00 00 00 00 00 00 00 00 D2 00 00 00 00 00 00 00 00 00 00 23 83` + +**注意,如果有续包,最后一包上位机无返回**。中间续包上位机返回传感类型,当前收到包的序列和子包的数量: + +| 7Fh | ADDR | 07 | C0 | SensType | Seq(1Byte) | SubAmount(1Byte) | XOR | SUM | +| --- | --- | --- | --- | --- | --- | --- | --- | --- | + +--- + +# 修订记录 + +| 版本 | 修订时间 | 修订说明 | 修订人 | +| --- | --- | --- | --- | +| | | | | +| V1.00 | 2026-03-11 | 创建协议初始版本 | wangfq | +| V1.01 | 2026-06-22 | 补充遗漏的接口说明 | wangfq | diff --git a/vd960DBN/README.md b/vd960DBN/README.md new file mode 100644 index 0000000..8858404 --- /dev/null +++ b/vd960DBN/README.md @@ -0,0 +1,47 @@ +# vd960DBN — 通信子项目 + +## MCU + +沁恒 CH32V208(RISC-V RV32IMAC) + +| 参数 | 数值 | +|------|------| +| 主频 | 144 MHz | +| Flash | 128 KB | +| SRAM | 64 KB | + +## 功能 + +- **蓝牙(BLE)**:无线配置、状态查询、固件升级 +- **以太网**:TCP/IP 协议栈,上位机通信(Modbus TCP / 私有协议) +- **RS485(1路)**:与外部设备/系统集成(Modbus RTU) +- **与 Loop 通信**:接收线圈检测结果,协议转发 + +## 目录结构 + +``` +vd960DBN/ +├── src/ # 源代码 +├── inc/ # 头文件 +├── lib/ # 库文件(HAL、CMSIS、协议栈) +│ ├── HAL/ # CH32V208 标准外设库 +│ └── CMSIS/ # RISC-V CMSIS 适配 +├── docs/ # 文档 +└── tools/ # 辅助工具/脚本 +``` + +## 通信接口 + +| 接口 | 用途 | 备注 | +|------|------|------| +| BLE (2.4GHz) | 现场调试 / 配置 | 手机 APP 连接 | +| Ethernet (10/100M) | 上位机实时数据 | Modbus TCP / HTTP | +| RS485 | 系统集成 | Modbus RTU | +| UART/SPI | 与 Loop MCU 通信 | 内部互联 | + +## 关键技术点 + +- 协议栈:lwIP(轻量级 TCP/IP) +- BLE Stack:CH32V208 内置 BLE 协议栈 +- 双协议支持:同时处理以太网和 485,消息路由与优先级管理 +- OTA 升级:BLE 通道支持 Loop MCU 固件升级 diff --git a/vd960Loop/README.md b/vd960Loop/README.md new file mode 100644 index 0000000..a4ee03f --- /dev/null +++ b/vd960Loop/README.md @@ -0,0 +1,37 @@ +# vd960Loop — 地感子项目 + +## MCU + +雅特力 AT32F421(ARM Cortex-M4) + +| 参数 | 数值 | +|------|------| +| 主频 | 120 MHz | +| Flash | 64 KB | +| SRAM | 16 KB | + +## 功能 + +- **四路线圈驱动**:正弦波激励,独立通道 +- **频率采样**:ADC / 比较器方式测量线圈谐振频率 +- **车辆检测算法**:实时频率偏移监测,灵敏度可配置 +- **与 DBN 通信**:通过 UART/SPI 上报检测结果和状态 + +## 目录结构 + +``` +vd960Loop/ +├── src/ # 源代码 +├── inc/ # 头文件 +├── lib/ # 库文件(HAL、CMSIS 等) +│ ├── HAL/ # AT32F421 标准外设库 +│ └── CMSIS/ # ARM CMSIS-Core +├── docs/ # 文档 +└── tools/ # 辅助工具/脚本 +``` + +## 关键技术点 + +- 线圈振荡电路:LC 并联谐振,频率范围 50–150 kHz +- 采样精度:目标 0.01% 频率分辨率 +- 通道隔离:四路分时采样,避免串扰