Initial commit: CCU621_M firmware project with BLE debug link support.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-08 17:28:36 +08:00
commit 9ceb218f80
1597 changed files with 724159 additions and 0 deletions
+134
View File
@@ -0,0 +1,134 @@
#ifndef VTK_FRAME_H
#define VTK_FRAME_H
#include "publicdata/public_define.h"
#if (POS_VTK_EN)
#ifdef __cplusplus
extern "C" {
#endif
#include "main.h"
/* VTK 基础协议号(串口模式) */
#define VTK_PD_VMC_TO_POS ((U16_T)0x96FB) /* CCU(VMC) → POS */
#define VTK_PD_POS_TO_VMC ((U16_T)0x97FB) /* POS → CCU(VMC) */
/* 串口帧相关常量 */
#define VTK_FRAME_START_BYTE ((U8_T)0x1F)
#define VTK_MAX_APP_LEN ((U16_T)512)
#define VTK_MAX_FRAME_LEN ((U16_T)(1 + 2 + 2 + VTK_MAX_APP_LEN + 2)) /* Start + Len + PD + App + CRC */
typedef struct
{
U16_T protoDisc; /* 协议号:VTK_PD_VMC_TO_POS / VTK_PD_POS_TO_VMC */
const U8_T *pApp; /* 指向应用层 TLV 数据起始地址 */
U16_T appLen; /* 应用层 TLV 数据长度 */
} VTK_FRAME_INFO_T;
/* 串口帧打包:把 TLV 应用数据封装为完整 VTK 串口帧
* @param[in] pApp 应用层 TLV 数据指针
* @param[in] appLen 应用层 TLV 数据长度
* @param[in] protoDisc 协议号(通常为 VTK_PD_VMC_TO_POS
* @param[out] pOut 输出缓冲区
* @param[in] outMax 输出缓冲区大小
* @return U16_T 串口帧总长度;0 表示失败(缓冲区不足等)
*/
U16_T vtk_build_frame(const U8_T *pApp, U16_T appLen, U16_T protoDisc,
U8_T *pOut, U16_T outMax);
/* 串口帧解析:对一整帧(含 0x1F 起始和 CRC)做合法性校验,并给出应用层 TLV 区段
* @param[in] pFrame 输入帧缓冲区
* @param[in] frameLen 输入帧长度
* @param[out] pInfo 输出解析结果(协议号、应用层指针与长度)
* @return U8_T 1=解析成功且 CRC 正确,0=失败
*/
U8_T vtk_parse_frame(const U8_T *pFrame, U16_T frameLen, VTK_FRAME_INFO_T *pInfo);
/* 流式解析器:用于从串口逐字节接收数据并拼出完整 VTK 帧 */
typedef enum
{
VTK_PARSE_WAIT_START = 0,
VTK_PARSE_LEN_H,
VTK_PARSE_LEN_L,
VTK_PARSE_BODY,
VTK_PARSE_CRC_H,
VTK_PARSE_CRC_L
} VTK_PARSE_STATE_E;
typedef struct
{
VTK_PARSE_STATE_E state;
U16_T lengthField; /* Length 字段值(Protocol Disc + App 长度) */
U16_T index; /* 当前已接收字节数 */
U16_T totalLen; /* 预期整帧长度(含起始和 CRC) */
U8_T buf[VTK_MAX_FRAME_LEN]; /* 内部缓冲区 */
} VTK_FRAME_PARSER_T;
/* 初始化帧解析器 */
void vtk_frame_parser_init(VTK_FRAME_PARSER_T *parser);
/* 向帧解析器输入 1 字节
* @param[in,out] parser 解析器状态
* @param[in] byte 串口接收到的 1 字节
* @param[out] ppFrame 当返回 1 时,指向完整帧起始地址(内部缓冲区)
* @param[out] pLen 当返回 1 时,给出完整帧长度
* @return U8_T 1=拼出完整合法帧;0=尚未完成或校验失败
*/
U8_T vtk_frame_parser_input(VTK_FRAME_PARSER_T *parser, U8_T byte,
const U8_T **ppFrame, U16_T *pLen);
/* 使用示例(发送 + 接收):
*
* // 发送侧:构造一帧带 TLV 的 VTK 串口报文并通过 UART 发送
* U8_T tlvBuf[VTK_MAX_APP_LEN];
* U16_T tlvLen = 0;
* U8_T frameBuf[VTK_MAX_FRAME_LEN];
* U16_T frameLen;
*
* // 追加 TLV 参数,例如 MessageName(Tag=0x01)="CDP"
* vtk_tlv_append_ascii(0x01, "CDP", tlvBuf, sizeof(tlvBuf), &tlvLen);
* // 追加 OperationNo(Tag=0x03)="12345"
* vtk_tlv_append_ascii_uint(0x03, 12345, 1, tlvBuf, sizeof(tlvBuf), &tlvLen);
* // 追加 Amount(Tag=0x04)="5000"
* vtk_tlv_append_ascii_uint(0x04, 5000, 1, tlvBuf, sizeof(tlvBuf), &tlvLen);
*
* // 封装为串口帧并发送
* frameLen = vtk_build_frame(tlvBuf, tlvLen, VTK_PD_VMC_TO_POS,
* frameBuf, sizeof(frameBuf));
* if (frameLen > 0U)
* {
* POS_VTK_UART_SEND(frameBuf, frameLen); // 由上层实现的串口发送函数
* }
*
* // 接收侧:在 UART 接收中断/任务中逐字节喂入解析器
* static VTK_FRAME_PARSER_T s_parser;
* static U8_T parserInited = 0;
*
* if (!parserInited)
* {
* vtk_frame_parser_init(&s_parser);
* parserInited = 1;
* }
*
* void UART_Rx_Handler_Byte(U8_T rxByte)
* {
* const U8_T *pFrame;
* U16_T frameLen;
*
* if (vtk_frame_parser_input(&s_parser, rxByte, &pFrame, &frameLen))
* {
* // 这里获得了一整帧 VTK 报文,可继续调用 vtk_parse_frame / vtk_parse_payment_response 解析
* }
* }
*/
#ifdef __cplusplus
}
#endif
#endif /* POS_VTK_EN */
#endif /* VTK_FRAME_H */