9ceb218f80
Co-authored-by: Cursor <cursoragent@cursor.com>
135 lines
4.5 KiB
C
135 lines
4.5 KiB
C
#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 */
|
||
|