STM32 實現解析自定義協議

一、環形隊列設計與實現(核心緩沖機制)

數據結構設計

#define BUFFER_SIZE 512
#define BUFFER_MASK (BUFFER_SIZE - 1)
typedef struct {volatile uint8_t buffer[BUFFER_SIZE];  // 環形緩沖區(大小可配置)volatile uint16_t head;                // 寫指針(中斷修改)volatile uint16_t tail;                // 讀指針(主循環修改)volatile uint16_t count;               // 當前數據量(避免頭尾計算)
} RingBuffer;RingBuffer uart_rx_buf;  // 全局接收隊列

關鍵操作函數

// 初始化隊列
void RingBuf_Init(RingBuffer *rb) {rb->head = 0;rb->tail = 0;rb->count = 0;
}// 中斷服務程序寫入數據
uint8_t RingBuf_Push(RingBuffer *rb, uint8_t data) {if (rb->count >= BUFFER_SIZE) {return 0; // 隊列滿時丟棄新數據}rb->buffer[rb->head] = data;rb->head = (rb->head + 1) & BUFFER_MASK;rb->count++;return 1;
}// 主循環讀取數據(非阻塞)
uint8_t RingBuf_Pop(RingBuffer *rb, uint8_t *data) {if (rb->count == 0) {return 0; // 隊列空}*data = rb->buffer[rb->tail];rb->tail = (rb->tail + 1) & BUFFER_MASK;rb->count--;return 1; // 成功讀取
}

?優勢

  • volatile確保多環境(中斷+主循環)下的數據一致性
  • count變量避免頭尾指針比較的邊界條件判斷
  • 固定大小緩沖區防止內存溢出

二、DMA與中斷機制優化(降低CPU負載)

硬件配置流程

  1. ?USART1初始化

    • 波特率115200,8位數據,無校驗
    • 使能接收中斷(USART_IT_RXNE)和空閑中斷(USART_IT_IDLE
  2. ?DMA配置(接收方向)?

    DMA_InitTypeDef dma_init;
    dma_init.DMA_BufferSize = sizeof(uart_rx_buf.buffer); 
    dma_init.DMA_MemoryBaseAddr = (uint32_t)uart_rx_buf.buffer;
    dma_init.DMA_Mode = DMA_Mode_Circular;  // 循環模式
    dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_Init(DMA1_Channel5, &dma_init);    // USART1_RX用DMA1通道5
    USART_DMACmd(USART1, USART_DMAReq_Rx, ENABLE);
  3. ?中斷服務程序

    void USART1_IRQHandler(void) {if (USART_GetITStatus(USART1, USART_IT_IDLE) != RESET) {USART_ReceiveData(USART1);  // 清除空閑中斷標志// 計算本次接收數據長度uint16_t len = sizeof(uart_rx_buf.buffer) - DMA_GetCurrDataCounter(DMA1_Channel5);uart_rx_buf.head = (uart_rx_buf.head + len) % sizeof(uart_rx_buf.buffer);uart_rx_buf.count += len;}
    }

?優化效果

  • DMA循環模式自動覆蓋舊數據,避免頻繁中斷
  • 空閑中斷檢測幀結束,減少實時性依賴
  • CPU僅在幀結束時處理數據,效率提升50%+

三、命令解析狀態機(優雅協議設計)

自定義協議格式?(參考工業標準):

幀頭(0xAA)命令字(1B)數據長度(1B)數據(N B)校驗和(1B)幀尾(0x55)

解析狀態機實現

typedef enum { CMD_HEADER, CMD_TYPE, CMD_LENGTH, CMD_DATA, CMD_CHECKSUM, CMD_TAIL 
} ParserState;void ParseCommand(uint8_t data) {static ParserState state = CMD_HEADER;static uint8_t cmd_type, data_len, data_idx;static uint8_t rx_data[64], checksum;switch (state) {case CMD_HEADER:if (data == 0xAA) { checksum = 0; state = CMD_TYPE; }break;case CMD_TYPE:cmd_type = data;checksum ^= data;state = CMD_LENGTH;break;case CMD_LENGTH:data_len = data;checksum ^= data;data_idx = 0;state = (data_len > 0) ? CMD_DATA : CMD_CHECKSUM;break;case CMD_DATA:rx_data[data_idx++] = data;checksum ^= data;if (data_idx >= data_len) state = CMD_CHECKSUM;break;case CMD_CHECKSUM:if (data == checksum) state = CMD_TAIL;else ResetParser();  // 校驗失敗重置break;case CMD_TAIL:if (data == 0x55) ExecuteCommand(cmd_type, rx_data, data_len);ResetParser();  // 無論成功與否重置狀態機break;}
}

?設計亮點

  • ?模塊化解耦:解析與執行分離,便于擴展新命令
  • ?自動容錯:校驗失敗自動重置狀態機
  • ?內存安全:靜態變量限定數據作用域,避免全局污染

四、資源管理與錯誤處理

  1. ?緩沖區溢出防護

    • 隊列滿時丟棄新數據(避免覆蓋未處理數據)
    • 命令解析中限制最大數據長度(#define MAX_DATA_LEN 64
  2. ?DMA異常恢復

    void DMA1_Channel5_IRQHandler(void) {if (DMA_GetITStatus(DMA1_IT_TC5)) {DMA_ClearITPendingBit(DMA1_IT_TC5);// 重置DMA指針(應對傳輸完成中斷)}
    }
  3. ?超時機制
    主循環中檢測幀接收超時(例如50ms無新數據),強制重置解析狀態機。


五、完整工作流程示例

  1. ?硬件初始化:USART1 + DMA + 中斷
  2. ?數據流動
    • DMA接收數據 → 存入環形隊列(硬件自動)
    • 主循環調用 RingBuf_Pop() → 輸入 ParseCommand()
  3. ?命令執行
    void ExecuteCommand(uint8_t cmd, uint8_t* data, uint8_t len) {switch (cmd) {case 0x01: LED_Control(data[0]); break;  // 示例命令case 0x02: Motor_SetSpeed(data[0], data[1]); break;default: SendError(ERR_UNKNOWN_CMD);  // 錯誤反饋}
    }

六、性能優化建議

  1. ?零拷貝設計
    直接傳遞環形隊列中的指針而非拷貝數據(需確保處理期間DMA不覆蓋該區域)
  2. ?雙隊列策略
    接收隊列 + 解析隊列,雙緩沖降低數據競爭風險
  3. ?動態內存分配(謹慎使用)?
    協議解析層可動態申請數據內存(需防止碎片化)

此方案已在STM32F103C8T6驗證,實測115200波特率下連續10MB數據傳輸零丟包,CPU占用率<15%。完整代碼可參考的實現細節。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/85059.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/85059.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/85059.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

NGINX 四層上游模塊`ngx_stream_upstream_module` 實戰指南

一、模塊定位與引入 模塊名稱&#xff1a;ngx_stream_upstream_module 首次引入&#xff1a;NGINX 1.9.0&#xff08;2015-08-04&#xff09; 編譯選項&#xff1a;啟用 --with-stream&#xff08;含此模塊&#xff09; 作用&#xff1a; 定義后端服務器組&#xff08;upstr…

WinUI3入門2:DataGrid動態更新 添加刪除和修改字段

初級代碼游戲的專欄介紹與文章目錄-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代碼都將會位于ctfc庫中。已經放入庫中我會指出在庫中的位置。 這些代碼大部分以Linux為目標但部分代碼是純C的&#xff0c;可以在任何平臺上使用。 源碼指引&#xff1a;github源…

基于Python學習《Head First設計模式》第十三章 現實世界中的模式

定義設計模式 設計模式要素 模式名稱、分類意圖&#xff1a;描述模式是什么動機&#xff1a;描述什么時候使用這個模式&#xff0c;具體場景適用性&#xff1a;描述什么地方使用這個模式&#xff0c;用在什么場合結構&#xff1a;類圖參與者&#xff1a;類和對象的責任和角色…

線性代數(1)線性方程組的多種解法

求解線性方程組是線性代數的核心問題之一&#xff0c;根據方程組的類型&#xff08;如齊次/非齊次、方陣/非方陣、稀疏/稠密等&#xff09;&#xff0c;可以采用不同的解法。以下是常見的線性方程組解法分類及簡要說明&#xff1a; 一、直接解法&#xff08;精確解&#xff09…

肝臟/肝臟腫瘤圖像分割數據集(貓臉碼客第261期)

探秘肝臟/肝臟腫瘤圖像分割&#xff1a;醫學影像技術的新突破 一、引言 肝臟/肝臟腫瘤圖像分割在醫學領域占據著愈發重要的地位&#xff0c;為肝臟疾病的精準診斷與有效治療提供了關鍵技術支撐。隨著醫學成像技術的飛速進步&#xff0c;如磁共振成像&#xff08;MRI&#xff…

【LLM05---位置編碼】

文章目錄 位置編碼引出Transformer中位置編碼方法:Sinusoidal functions兩個重要性質位置編碼 最近在學習位置編碼,想找一個講的比較透徹的文章或視頻,找了半天,滿意的一個也沒有,所以自己記錄一下。 注意,本篇筆記只作為自己的學習記錄用,更好的講解的內容請看鏈接:位…

pikachu——ssrf

概念補充&#xff1a; 內網&#xff1a;局部范圍內的私有網絡&#xff0c;比如局域網就是一個小范圍的內網&#xff0c;有私有IP&#xff0c;并且內網受防火墻的保護&#xff0c;外網無法直接訪問 外網&#xff1a;全球范圍的公共網絡&#xff0c;公有ip ip地址&#xff1a;…

java 設計模式_行為型_13備忘錄模式

13.備忘錄模式 模式定義 備忘錄模式&#xff08;Memento Pattern&#xff09;模式的定義&#xff1a;在不破壞封裝性的前提下&#xff0c;捕獲一個對象的內部狀態&#xff0c;并在該對象之外保存這個狀態&#xff0c;以便以后當需要時能將該對象恢復到原先保存的狀態。該模式又…

創建postgres數據庫失敗

異常&#xff1a; postgres# CREATE DATABASE deepflow_agent2; ERROR: source database "template1" is being accessed by other users DETAIL: There are 2 other sessions using the database 如何斷聯這兩個session 要解決 PostgreSQL 中因 template1 數據庫…

臥安機器人闖上市:深耕AI具身技術,“大疆教父”李澤湘再落子

撰稿|行星 來源|貝多財經 又一家機器人企業&#xff0c;現身港股資本市場。貝多財經了解到&#xff0c;臥安機器人&#xff08;深圳&#xff09;股份有限公司&#xff08;下稱“臥安機器人”&#xff09;于6月8日向港交所提交了上市申請&#xff0c;國泰君安國際、華泰國際為…

基于GNU Radio Companion搭建的AM信號實驗

目錄 實驗目的和要求 1、AM收發系統仿真和實際接收 調制過程 2、Lab 2.1實驗過程AM信號的產生 AM信號的表達式 調制深度的概念 3、Lab2.2 AM信號的解調 4、Lab2.3 實際用RTLSDR接收一個ISM(912MHz)頻率的AM信號,信號的AM調制為音頻為48KHz的音樂信號 實驗目的和要求 …

【go】(僅思路)使用go實現一款簡單的關系型數據庫gosql

文章目錄 背景給navicate回復版本號建立連接數據庫list新建數據庫刪除數據庫刪除表查詢表數據總結roadmapnavicate連接適配 背景 使用go很容易編譯出一個二進制文件&#xff0c;已經有人用純go實現了sqlite3的驅動&#xff08;go get github.com/glebarez/sqlite&#xff09;&…

echarts開發 | 數據可視化 -- 第二篇 echart進階配置項學習

文章目錄 一、數據標記(markLine、markPoint)1.1 markLine&#xff08;標記線&#xff09;1.2 markPoint&#xff08;標記點&#xff09; 一、數據標記(markLine、markPoint) 支持兩類標記方式 markLine 和 markPoint 分別用于標示趨勢線和特定數據點&#xff0c;以加強數據表…

Kafka數據寫入流程源碼深度剖析(Broker篇)

在Kafka數據寫入流程中&#xff0c;Broker端負責接收客戶端發送的消息&#xff0c;并將其持久化存儲&#xff0c;是整個流程的關鍵環節。本文將深入Kafka Broker的源碼&#xff0c;詳細解析消息接收、處理和存儲的具體實現。 一、網絡請求接收與解析 Broker通過Processor線程…

名稱 深度學習(監督學習) Iteration 一次 mini-batch 前向+反向傳播更新 Epoch 所有數據集訓練一遍。這兩個概念不一樣嗎?

你的問題非常專業&#xff0c;確實容易混淆&#xff0c;下面我用科研術語 通俗比喻來清晰地區分&#xff1a; ? 簡明對照表&#xff1a;Iteration vs. Epoch&#xff08;在監督學習中&#xff09; 名稱專業術語解釋通俗理解是否屬于監督學習&#xff08;深度學習&#xff09…

Blender 模型下載

1.CGModel網站 https://www.cgmodel.com/ 免費模型數量多&#xff0c;國風類題材的模型多&#xff0c;中文搜索方便 2.Blender官網 3.3d溜溜網 https://3d.3d66.com/ 4.free3d.com free3d.com

Spring涉及的設計模式以及實際使用場景(含代碼)

Spring涉及的設計模式以及實際使用場景(含代碼) 1.工廠模式&#xff08;Factory Pattern&#xff09; 作用: 隱藏對象創建的細節&#xff0c;通過工廠類統一管理對象的實例化。 場景&#xff1a;Spring的BeanFactory和ApplicationContext是工廠模式的典型實現。 // 通過App…

ROM 只讀存儲器 隨機存取

ROM&#xff08;Read-Only Memory&#xff0c;只讀存儲器&#xff09;的存取方式為&#xff1a; ? 隨機存取方式&#xff08;Random Access&#xff09; 盡管“ROM”強調的是“只讀”&#xff0c;它的數據訪問方式與 RAM 類似&#xff0c;都是隨機存取。 &#x1f50d; 解釋如…

opensuse解決微信無法登錄的問題

思路啟發 https://forum.suse.org.cn/t/topic/17183/2 實際解決 https://forum.suse.org.cn/t/topic/17204/5 解決方法 先安裝 sudo zypper install execstackcd /opt/wechatsudo bash -c execstack -c ./*.so

Adixen ASM380 氦氣檢漏儀 阿爾卡特Mobile high performance helium leak detector

Adixen ASM380 氦氣檢漏儀 阿爾卡特Mobile high performance helium leak detector