feat(vd960DBN): 实现 DLD960Loop 串口通信协议 (0x7F)
新增: - docs/DLD960Loop_串口通信协议.md — 协议文档 V1.02 - loop_uart_proto.h/c — 协议实现: checksum/组包/解析/帧状态机/命令状态机 修改: - usart_biz.c: 使用 lup_feed_byte() 帧解析器替代 timeout heuristic; 波特率修正为 115200 - tcp_json_srv.c/h: loop_param_set/query 真实实现(0x63/0x64), 0xC0 传感器推流, 延迟响应机制 - peripheral_main.c: 添加 tcp_json_push_sensor() 调用, 帧解析器超时保护 校验验证: 5个协议例程 XOR+SUM 全部通过
This commit is contained in:
@@ -0,0 +1,239 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file loop_uart_proto.h
|
||||
* @author wangfq
|
||||
* @version V1.0
|
||||
* @date 2026-07-02
|
||||
* @brief DLD960Loop 串口通信协议 (7F) — CH32V208 ↔ DLD960Loop MCU
|
||||
*
|
||||
* 帧格式: 7F | Addr | LEN | CMD | Data... | XOR | SUM
|
||||
* UART: USART2, 115200bps, PA2(Tx)/PA3(Rx)
|
||||
*
|
||||
* 该协议是通信MCU(CH32V208)与地感MCU(DLD960Loop/AT32F421)之间的接口。
|
||||
* 网络接口(TCP JSON/5960)通过本模块向地感MCU下发命令并获取数据。
|
||||
******************************************************************************
|
||||
*/
|
||||
#ifndef __LOOP_UART_PROTO_H__
|
||||
#define __LOOP_UART_PROTO_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*===========================================================================
|
||||
* Protocol Constants
|
||||
*===========================================================================*/
|
||||
#define LUP_MAGIC 0x7F // 配置/查询协议
|
||||
#define LUP_MAGIC_OTA 0x9F // OTA
|
||||
|
||||
#define LUP_ADDR_DEFAULT 0x00 // 默认地址
|
||||
|
||||
#define LUP_MAX_VALUE_LEN 64 // Value 字段最大长度
|
||||
#define LUP_MAX_PKG_LEN (1 + 3 + LUP_MAX_VALUE_LEN + 2) // 70 bytes 最大帧
|
||||
|
||||
/*===========================================================================
|
||||
* Command Bytes (CMD)
|
||||
*===========================================================================*/
|
||||
#define LUP_CMD_GET_VERSION 0x4A // 获取设备版本号
|
||||
#define LUP_CMD_RESET 0x6D // 设备复位(无回复)
|
||||
#define LUP_CMD_FACTORY_INIT 0x92 // 出厂初始化
|
||||
#define LUP_CMD_SENSITIVITY 0x8A // 读写线圈灵敏度列表
|
||||
#define LUP_CMD_SET_PARAM 0x63 // 设置多路参数
|
||||
#define LUP_CMD_GET_PARAM 0x64 // 读取多路参数
|
||||
#define LUP_CMD_SENSOR_REPORT 0xC0 // 设备主动上报传感信息
|
||||
|
||||
/*===========================================================================
|
||||
* Sensor Types (0xC0 SensType)
|
||||
*===========================================================================*/
|
||||
#define LUP_SENS_TYPE_MULTI_COIL 0x0C // 多路线圈传感信息(四路)
|
||||
|
||||
/*===========================================================================
|
||||
* R/W byte for sensitivity (0x8A)
|
||||
*===========================================================================*/
|
||||
#define LUP_SENS_RW_READ 0x00
|
||||
#define LUP_SENS_RW_WRITE 0x01
|
||||
|
||||
/*===========================================================================
|
||||
* 线圈数
|
||||
*===========================================================================*/
|
||||
#define LUP_COIL_COUNT 4
|
||||
|
||||
/*===========================================================================
|
||||
* Data Structures
|
||||
*===========================================================================*/
|
||||
|
||||
/* 线圈配置 (0x63 Set / 0x64 Get 中使用) */
|
||||
typedef struct {
|
||||
uint8_t sensitivity; // 低4位灵敏度(0~9), 高4位频率等级[4]=高频,[5]=低频
|
||||
uint8_t loop_delay; // 延时时间 0~200, 0.1s/级
|
||||
uint8_t output_mode; // 低3位: 0=存在,1=进入脉冲,2=离开脉冲,3=方向
|
||||
// 高5位: SafeMode 分钟数(0=关闭)
|
||||
uint8_t exist_mode; // 低4位: 0=永久, 非0=有限分钟
|
||||
uint8_t direction_mode; // 低3位: 0=触发, 1~6=方向模式
|
||||
// 高4位: Function_Mode
|
||||
} LUP_CoilParam;
|
||||
|
||||
/* 多路参数设置 (0x63) */
|
||||
typedef struct {
|
||||
uint8_t auto_mode; // 0=不启用自动调频, 默认0
|
||||
uint8_t amount; // 线圈数量
|
||||
LUP_CoilParam params[LUP_COIL_COUNT];
|
||||
} LUP_ParamSet;
|
||||
|
||||
/* 多路参数读取返回 (0x64 Response) */
|
||||
typedef struct {
|
||||
uint8_t auto_mode;
|
||||
uint8_t amount;
|
||||
LUP_CoilParam params[LUP_COIL_COUNT];
|
||||
uint32_t freq[LUP_COIL_COUNT][3]; // [ch][0]=freq1, [1]=freq2, [2]=freq3
|
||||
} LUP_ParamGet;
|
||||
|
||||
/* 单路线圈传感数据单元 (0xC0/0x0C 中的每一路线圈) */
|
||||
typedef struct {
|
||||
uint8_t freq_level : 2; // 00=高频33nF, 01=中高43nF, 10=中低66nF, 11=低频76nF
|
||||
uint8_t direction : 1; // 0=触发, 1=方向判别
|
||||
uint8_t freq_type : 1; // 0=初始频率, 1=实时频率
|
||||
uint8_t sensitivity : 4; // 灵敏度等级
|
||||
// 线圈评估条件
|
||||
uint8_t condition : 4; // 环境状态评估值(0=正常, 值越大干扰越大)
|
||||
uint8_t loop_state : 1; // 0=正常, 1=断开
|
||||
uint8_t car_state : 1; // 0=无车, 1=有车
|
||||
uint8_t misc_type : 2; // 0=时间量, 1=断开次数, 2=车流量
|
||||
uint32_t freq; // 频率 (3 bytes, little-endian)
|
||||
uint16_t variation; // 变化量 (2 bytes, little-endian)
|
||||
union {
|
||||
uint32_t passtime_ms5; // 通过时间/车间距, 5ms单位 (misc_type=0)
|
||||
uint32_t cut_amount; // 线圈断开次数 (misc_type=1)
|
||||
uint32_t flow_amount; // 车流量数 (misc_type=2)
|
||||
} misc;
|
||||
} LUP_CoilSensor;
|
||||
|
||||
/* 主动上报传感信息 (0xC0/0x0C) */
|
||||
typedef struct {
|
||||
uint8_t sens_type; // 0x0C
|
||||
uint8_t sub_amount; // 分包数量(高4位), 0=无分包
|
||||
uint8_t sub_sequence; // 当前分包序号(低4位), 1-based
|
||||
uint8_t coil_count; // 线圈数 (解析出的)
|
||||
LUP_CoilSensor coils[LUP_COIL_COUNT];
|
||||
} LUP_SensorReport;
|
||||
|
||||
/* 灵敏度读写 (0x8A) */
|
||||
typedef struct {
|
||||
uint8_t rw; // 0=Read, 1=Write
|
||||
uint8_t amount; // 灵敏度值数量
|
||||
uint16_t sens_in[LUP_COIL_COUNT]; // 触发灵敏度
|
||||
uint16_t sens_out[LUP_COIL_COUNT]; // 释放灵敏度
|
||||
} LUP_Sensitivity;
|
||||
|
||||
/* 版本信息 (0x4A Response) */
|
||||
typedef struct {
|
||||
uint8_t status; // Status byte
|
||||
uint8_t hard_main;
|
||||
uint8_t hard_sub;
|
||||
uint8_t hard_ssub;
|
||||
uint8_t soft_main;
|
||||
uint8_t soft_sub;
|
||||
uint8_t soft_ssub;
|
||||
char version_str[32]; // 格式化字符串
|
||||
} LUP_VersionInfo;
|
||||
|
||||
/* 命令状态机 */
|
||||
typedef enum {
|
||||
LUP_STATE_IDLE = 0, // 空闲
|
||||
LUP_STATE_WAIT_RESPONSE, // 等待响应
|
||||
LUP_STATE_RESPONSE_READY, // 响应已就绪
|
||||
LUP_STATE_TIMEOUT // 超时
|
||||
} LUP_CmdState;
|
||||
|
||||
/* 挂起的命令跟踪 */
|
||||
typedef struct {
|
||||
uint8_t pending_cmd; // 当前等待响应的命令字节
|
||||
uint32_t send_tick; // 发送时刻 (ms)
|
||||
uint32_t timeout_ms; // 超时时间
|
||||
LUP_CmdState state;
|
||||
// 响应数据缓冲区
|
||||
uint8_t resp_buf[LUP_MAX_PKG_LEN];
|
||||
uint16_t resp_len;
|
||||
} LUP_CmdTracker;
|
||||
|
||||
/*===========================================================================
|
||||
* Global State
|
||||
*===========================================================================*/
|
||||
extern LUP_CmdTracker g_lup_cmd;
|
||||
|
||||
/*===========================================================================
|
||||
* Public API
|
||||
*===========================================================================*/
|
||||
|
||||
/* --- Checksum --- */
|
||||
uint8_t lup_calc_xor(const uint8_t *data, uint16_t len);
|
||||
uint8_t lup_calc_sum(const uint8_t *data, uint16_t len);
|
||||
int lup_verify_checksum(const uint8_t *pkg, uint16_t len);
|
||||
void lup_append_checksum(uint8_t *pkg);
|
||||
|
||||
/* --- Packet Builders (returns total packet length) --- */
|
||||
uint16_t lup_build_get_version(uint8_t *buf);
|
||||
uint16_t lup_build_reset(uint8_t *buf);
|
||||
uint16_t lup_build_factory_init(uint8_t *buf);
|
||||
uint16_t lup_build_sensitivity_read(uint8_t *buf);
|
||||
uint16_t lup_build_sensitivity_write(uint8_t *buf, const LUP_Sensitivity *sens);
|
||||
uint16_t lup_build_set_param(uint8_t *buf, const LUP_ParamSet *ps);
|
||||
uint16_t lup_build_get_param(uint8_t *buf);
|
||||
|
||||
/* --- Packet Parsers (returns 0=success, <0=error) --- */
|
||||
int lup_parse_version(const uint8_t *pkg, uint16_t len, LUP_VersionInfo *info);
|
||||
int lup_parse_factory_init_resp(const uint8_t *pkg, uint16_t len, uint8_t *success);
|
||||
int lup_parse_sensitivity_resp(const uint8_t *pkg, uint16_t len, LUP_Sensitivity *sens);
|
||||
int lup_parse_param_get(const uint8_t *pkg, uint16_t len, LUP_ParamGet *pg);
|
||||
int lup_parse_sensor_report(const uint8_t *pkg, uint16_t len, LUP_SensorReport *report);
|
||||
int lup_parse_set_param_resp(const uint8_t *pkg, uint16_t len, uint8_t *success);
|
||||
|
||||
/* --- Command State Machine --- */
|
||||
void lup_cmd_begin(uint8_t cmd, uint32_t timeout_ms);
|
||||
void lup_cmd_done(void);
|
||||
int lup_cmd_check_timeout(void);
|
||||
void lup_cmd_on_response(const uint8_t *pkg, uint16_t len);
|
||||
|
||||
/* --- High-level Commands (send + wait handled by state machine) --- */
|
||||
void lup_send_get_version(void);
|
||||
void lup_send_reset(void);
|
||||
void lup_send_factory_init(void);
|
||||
void lup_send_sensitivity_read(void);
|
||||
void lup_send_set_param(const LUP_ParamSet *ps);
|
||||
void lup_send_get_param(void);
|
||||
|
||||
/* --- Mid-packet ACK for 0xC0 multi-packet --- */
|
||||
uint16_t lup_build_sensor_ack(uint8_t *buf, uint8_t sens_type,
|
||||
uint8_t seq, uint8_t sub_amount);
|
||||
|
||||
/* --- UART Frame Parser (called from USART2 ISR context) --- */
|
||||
typedef enum {
|
||||
LUP_FRAME_STATE_IDLE = 0, // 等待 0x7F
|
||||
LUP_FRAME_STATE_HEADER, // 接收 Header (Addr, LEN, CMD)
|
||||
LUP_FRAME_STATE_VALUE, // 接收 Value
|
||||
LUP_FRAME_STATE_CHECK, // 接收 Checksum
|
||||
LUP_FRAME_STATE_COMPLETE // 帧完成
|
||||
} LUP_FrameState;
|
||||
|
||||
typedef struct {
|
||||
LUP_FrameState state;
|
||||
uint8_t buf[LUP_MAX_PKG_LEN];
|
||||
uint16_t idx; // 当前写入位置
|
||||
uint16_t value_len; // 期望的 Value 长度 (从 LEN 字段解析)
|
||||
uint16_t value_idx; // 当前已接收的 Value 字节数
|
||||
} LUP_FrameParser;
|
||||
|
||||
extern LUP_FrameParser g_lup_parser;
|
||||
|
||||
/* 喂一个字节给帧解析器,返回 1 表示帧接收完成 */
|
||||
int lup_feed_byte(uint8_t byte);
|
||||
|
||||
/* 取完整帧的指针和数据长度 */
|
||||
const uint8_t *lup_frame_data(void);
|
||||
uint16_t lup_frame_len(void);
|
||||
|
||||
/* 重置帧解析器 */
|
||||
void lup_frame_reset(void);
|
||||
|
||||
/* --- Process a complete frame (call from main loop context) --- */
|
||||
void lup_process_frame(const uint8_t *pkg, uint16_t len);
|
||||
|
||||
#endif /* __LOOP_UART_PROTO_H__ */
|
||||
@@ -44,6 +44,17 @@ typedef enum {
|
||||
#define JSON_CODE_DATA_TOO_LONG 6
|
||||
#define JSON_CODE_NOT_AUTHED 7
|
||||
|
||||
/*===========================================================================
|
||||
* Pending Loop MCU Command Response (deferred)
|
||||
*===========================================================================*/
|
||||
typedef struct {
|
||||
uint8_t active; // 1 = pending response
|
||||
uint8_t socket; // TCP socket to reply to
|
||||
uint32_t msg_id; // Original msg_id
|
||||
char cmd[32]; // Original command string
|
||||
uint32_t deadline; // ms deadline for timeout
|
||||
} TcpJsonPending;
|
||||
|
||||
/*===========================================================================
|
||||
* Externs
|
||||
*===========================================================================*/
|
||||
@@ -51,6 +62,7 @@ extern uint8_t g_json_socket_listen; // TCP socket ID (listen + data)
|
||||
extern TcpJsonAuthState g_json_auth_state;
|
||||
extern uint32_t g_json_auth_timer; // ms timer for auth timeout
|
||||
extern uint8_t g_json_pwd_retry; // password retry counter
|
||||
extern TcpJsonPending g_json_pending; // Pending Loop MCU command state
|
||||
|
||||
/*===========================================================================
|
||||
* API
|
||||
@@ -58,5 +70,6 @@ extern uint8_t g_json_pwd_retry; // password retry counter
|
||||
void tcp_json_srv_init(void); // Create listen socket on port 5960
|
||||
void tcp_json_handle_sock_int(uint8_t socketid, uint8_t intstat); // Socket interrupt handler
|
||||
void tcp_json_poll(void); // Periodic poll (auth timeout, etc.)
|
||||
void tcp_json_push_sensor(void); // Push sensor data (0xC0) to TCP client
|
||||
|
||||
#endif /* __TCP_JSON_SRV_H__ */
|
||||
|
||||
Reference in New Issue
Block a user