当前位置: 首页 > news >正文

嵌入式通用通信帧协议设计

嵌入式通用通信帧协议设计

嵌入式系统开发中,如串口UART、蓝牙、轻量级网络等通信链路往往需要自定义封包协议来保证数据传输的准确性。本文分享一套简洁、通用、易实现的帧协议设计方案,适配多类嵌入式通信场景。

一、帧协议结构(小端序)

协议采用 “帧头 + 标识 + 数据 + 校验 + 帧尾” 的经典结构,总长度灵活且解析逻辑简单,各字段定义如下:

字段 字节数 定义 / 取值 核心作用
帧头 2 0xAA55(小端存储) 帧同步标识,快速定位帧起始位置
帧计数 1 0~255(溢出归零) 区分帧的新旧顺序,辅助检测丢包、重传
帧 ID 2 自定义(如指令码 / 设备 ID) 标识帧的功能类型(如读指令 / 写指令 / 响应包),适配多指令 / 多设备通信
数据长度 2 0~65535 标识 “数据位” 的字节数,避免解析时内存溢出,限定数据区范围
数据位 不定 业务自定义数据 承载实际业务数据(如传感器值、控制指令参数)
CRC16 校验 2 小端存储 校验范围:帧计数~数据位,采用 CRC16-CCITT 多项式,检测传输过程中的字节错误
帧尾 2 0x55AA(小端存储) 帧结束标识,辅助确认帧边界,降低字节流通信的帧解析错误率

二、CRC16-CCITT的C代码

/*** @brief       CCITT CRC16算法* @param       data :传入的数据指针* @param       length  : 数据长度* @retval      crc计算结果*/
uint16_t crc16_CCITT(const uint8_t *data, uint32_t length) 
{uint16_t crc16_polynomial = 0x1021;uint16_t crc16_start_value = 0xFFFF;uint16_t crc = crc16_start_value;for (uint32_t i = 0; i < length; i++) {crc ^= (uint16_t)data[i] << 8;for (uint8_t bit = 0; bit < 8; bit++) {if (crc & 0x8000) crc = (crc << 1) ^ crc16_polynomial;else crc = crc << 1;}}return crc;
}

三、帧解析的C代码

/* 帧格式定义 */
#define FRAME_HEADER      0xAA55
#define FRAME_TAIL        0x55AA
#define MIN_FRAME_LEN     9  /* 最小帧长度 *//*** @brief       用户命令帧结构体(适配自定义通用协议)*/
typedef struct {uint8_t  seq_num;       /* 帧计数(1字节) */uint16_t frame_id;      /* 帧ID(2字节,小端) */uint16_t data_len;      /* 数据段长度(2字节,小端) */uint8_t* data;          /* 数据段指针 */uint16_t crc16;         /* CRC16校验值(2字节,小端) */
} UserCommandFrame;/*** @brief       解析命令帧* @param       rx_buffer   : 接收缓冲区指针* @param       size        : 数据长度* @param       cmd         : 解析后的命令结构体指针* @retval      true:解析成功, false:解析失败*/
bool parse_command_frame(uint8_t *rx_buffer, uint16_t size, \UserCommandFrame *cmd)
{/* 1. 基本长度检查 */if (size < MIN_FRAME_LEN || rx_buffer == NULL || cmd == NULL) {return false;}/* 2. 帧头检查 (0xAA55, 小端存储: 0x55 0xAA) */if (rx_buffer[0] != 0x55 || rx_buffer[1] != 0xAA) {return false;}/* 3. 解析固定字段 */cmd->seq_num  = rx_buffer[2];                          /* 帧计数 */cmd->frame_id = rx_buffer[3] | (rx_buffer[4] << 8);    /* 帧ID(小端) */cmd->data_len = rx_buffer[5] | (rx_buffer[6] << 8);    /* 数据长度(小端) *//* 4. 总长度验证: 帧头2 + 帧计数1 + 帧ID2 + 数据长度2 + 数据 + CRC2 + 帧尾2 */if (size != 11 + cmd->data_len) {return false;}/* 5. 帧尾检查 (0x55AA, 小端存储: 0xAA 0x55) */if (rx_buffer[size-2] != 0xAA || rx_buffer[size-1] != 0x55) {return false;}/* 6. 数据段指针赋值 */cmd->data = &rx_buffer[7];/* 7. 解析CRC16 */uint16_t data_end = 7 + cmd->data_len;cmd->crc16 = rx_buffer[data_end] | (rx_buffer[data_end + 1] << 8);/* 8. CRC校验 (计算从帧计数到数据结束的数据) */uint16_t cal_crc = crc16_CCITT(&rx_buffer[2], 5 + cmd->data_len);if (cal_crc != cmd->crc16) {return false;}return true;  /* 解析成功 */
}
http://www.jsqmd.com/news/429474/

相关文章:

  • RAG 检索增强生成
  • 一篇配有AI漫画的文章告诉大家从小抓好体能素质的意义,比考试成绩重要得多,关键时刻能保命(公益文章,希望增大展现量,漫画由智谱清言AI生成)
  • 豆包广告怎么投?2026年企业获客的2个方案 - 品牌2026
  • 嵌入式软件分层架构
  • Git:临时切换分支保存当前工作
  • [AI智能体与提效-121] - LangChain 核心专业术语与阐述
  • 读懂用户心理,才是好 UI 设计的开始 - ui设计公司兰亭妙微
  • Git分支命名规范示例
  • why visual letters are good
  • DeepSeek能植入广告吗?2026年企业获客新解法 - 品牌2026
  • 一文读懂大数据领域的数据血缘
  • 一.系统烧写
  • 前端工程化过程 - 何苦
  • the similarity between Japan and Russian
  • RDD编程初级实践
  • 2025年六大热门数据库管理工具!哪款工具功能最强大?
  • DeepSeek能植入广告推广吗?联系哪家公司? - 品牌2026
  • Doris查询缓存机制:提升大数据重复查询性能
  • 荷马史诗-huffman树
  • 黑匣子-对顶堆
  • DeepSeek能做广告推广吗?联系哪家公司? - 品牌2026
  • 40.kubernetes面试
  • [Arduino UNO]使用simavr和gdb-avr 调试arduino IDEblink参考代码
  • SAP HCM中动态选择的实现与应用方法
  • ▲DQPSK调制解调+扩频解扩通信链路matlab误码率仿真
  • 个性化U盘图标设置的详细步骤与技巧
  • 多模型编排爆火:Perplexity 最新架构解析与私有化部署
  • 2026.3.2
  • PowerShell 新建 Address Book Policy
  • P2922 [USACO08DEC] Secret Message G