引言
在嵌入式開發中,數據包封裝是不可或缺的一環。手動編寫協議不僅耗時,還容易出錯。ProtoFlow 的出現,就是為了讓數據包封裝變得簡單、高效、可靠。它不僅占用資源少,還能適配多種場景,是你項目的理想助手。
項目地址:Github倉庫:https://github.com/nanwanuser/ProtoFlow
項目簡介
ProtoFlow 是一個專為數據包封裝和解析設計的輕量級協議棧,旨在幫助嵌入式開發者快速、高效地處理數據打包需求。無論你的項目使用串口、SPI、I2C,還是 CAN 等通信方式,ProtoFlow 都能提供靈活、可配置的數據包封裝功能,讓你專注于核心開發,而無需為通信細節操心。
為什么選擇 ProtoFlow?
在嵌入式開發中,數據包封裝是不可或缺的一環。手動編寫協議不僅耗時,還容易出錯。ProtoFlow 的出現,就是為了讓數據包封裝變得簡單、高效、可靠。它不僅占用資源少,還能適配多種場景,是你項目的理想助手。
ProtoFlow 的核心亮點
- 專注于數據包封裝:提供靈活的幀結構,支持動態長度數據包(最大 256 字節)。
- 輕量高效:協議棧占用不到 2KB Flash,適合資源有限的 MCU。
- 多場景適用:支持串口、SPI、I2C、CAN 等多種通信方式的數據包封裝。
- 可靠傳輸:可選 CRC16 校驗,確保數據完整性。
- 簡單易用:直觀的 API 和示例代碼,快速集成到 STM32 項目中。
ProtoFlow 項目
特性
- 輕量級協議棧(<2KB Flash)
- 支持動態長度數據包(最大 256 字節)
- 可配置幀頭幀尾(默認 0xAA55/0x55AA)
- 支持 CRC16 校驗(可選啟用)
- 狀態機驅動解析(9 種解析狀態)
- 全中斷驅動設計(零阻塞)
- 自動重同步機制
- 多通信方式支持:不僅限于串口,可擴展到 SPI、I2C、CAN 等
- 適用于多種數據通信場景
快速開始
1. 添加文件到工程
# 復制以下文件到 STM32 工程目錄
protoflow.h protoflow.c
2. 協議配置(protoflow.h)
// 幀結構配置
#define FRAME_HEADER 0xAA55 // 2 字節幀頭
#define FRAME_END 0x55AA // 2 字節幀尾
#define MAX_DATA_LENGTH 256 // 最大數據長度
#define USE_CRC16 1 // 啟用 CRC16 校驗(0-禁用 1-啟用)// 硬件抽象聲明(用戶必須實現)
void user_transmit(uint8_t *data, uint16_t len); // 通信發送函數(支持多種通信方式)
3. 示例代碼集成(以串口為例)
// main.c
#include "protoflow.h"int main(void) {// HAL 初始化MX_USART1_UART_Init();protoflow_init(); // 協議棧初始化while(1) {// 主循環處理}
}// 串口接收中斷回調
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {if(huart->Instance == USART1) {uint8_t data = huart->Instance->DR;parse_byte(data); // 字節解析}
}
API 說明
數據打包發送
/*** @brief 打包并發送數據* @param cmd : 命令字(1 字節)* @param data : 有效載荷數據指針* @param len : 數據長度(0~MAX_DATA_LENGTH)* @retval 實際發送的數據包長度*/
uint16_t pack_data_transmit(uint8_t cmd, uint8_t *data, uint16_t len);
數據解析
/*** @brief 解析接收字節(將接收到的字節傳入,解析后在 user_package_handler 中使用數據包)* @param byte : 接收到的字節*/
void parse_byte(uint8_t byte);
回調函數(用戶實現)
/*** @brief 完整數據包回調* @param cmd : 接收到的命令字* @param data : 數據緩沖區指針* @param len : 有效數據長度*/
void user_package_handler(uint8_t cmd, uint8_t *data, uint16_t len);
典型應用場景
數據發送(以串口為例)
// 發送溫濕度傳感器數據
void send_sensor_data(float temp, float humidity) {uint8_t payload[4];// 轉換為 16 位整型(0.1℃ 精度)uint16_t temp_raw = (uint16_t)(temp * 10);uint16_t humi_raw = (uint16_t)(humidity * 10);payload[0] = temp_raw >> 8;payload[1] = temp_raw & 0xFF;payload[2] = humi_raw >> 8;payload[3] = humi_raw & 0xFF;pack_data_transmit(0x01, payload, sizeof(payload)); // 自動發送
}
數據接收處理
// 接收控制指令(示例:PWM 控制)
void user_package_handler(uint8_t cmd, uint8_t *data, uint16_t len) {switch(cmd) {case 0xA1: // 電機控制if(len == 4) {uint16_t speed = (data[0] << 8) | data[1];uint16_t duration = (data[2] << 8) | data[3];set_motor(speed, duration);}break;case 0xA2: // LED 亮度調節if(len == 2) {uint16_t brightness = (data[0] << 8) | data[1];set_led_brightness(brightness);}break;}
}
移植指南
必須實現的硬件接口
ProtoFlow 支持多種通信方式,用戶需根據具體硬件實現發送函數。例如:
串口:
void user_transmit(uint8_t *data, uint16_t len) {HAL_UART_Transmit(&huart1, data, len, 100);
}
SPI:
void user_transmit(uint8_t *data, uint16_t len) {HAL_SPI_Transmit(&hspi1, data, len, 100);
}
I2C:
void user_transmit(uint8_t *data, uint16_t len) {HAL_I2C_Master_Transmit(&hi2c1, DEVICE_ADDR, data, len, 100);
}
配置步驟
- 在 protoflow.h 中配置協議參數(幀頭、幀尾、最大數據長度、CRC16 等)
- 根據通信方式實現 user_transmit 發送函數
- 實現 user_package_handler 數據回調函數
- 在通信接收中斷中調用 parse_byte()(如串口接收中斷)
- 調用 protoflow_init() 初始化協議棧
注意事項
- 幀結構:Header(2) + Length(2) + Cmd(1) + Data(n) + CRC16(2) + End(2)
- 數據長度字段:包含命令字(1 字節)+ 數據長度
- CRC16:啟用時數據包增加 2 字節校驗碼
- DMA 建議:使用 DMA 傳輸時,保持緩沖區有效直到發送完成