熟女俱乐部五十路二区av,又爽又黄禁片视频1000免费,国产卡一卡二卡三无线乱码新区,中文无码一区二区不卡αv,中文在线中文a

新聞中心

EEPW首頁 > 嵌入式系統(tǒng) > 設計應用 > 高效的串口通信設計:基于 STM32 的環(huán)形緩沖區(qū)收發(fā)機制

高效的串口通信設計:基于 STM32 的環(huán)形緩沖區(qū)收發(fā)機制

作者:嵌入式芯視野 時間:2025-07-09 來源:今日頭條 收藏

在嵌入式系統(tǒng)開發(fā)中,串口(UART)是最基礎也是最常用的通信方式之一。無論是用于調試信息的打印、與外設通信,還是與主控模塊的數(shù)據(jù)交互,一個穩(wěn)定可靠、結構清晰的模塊都是不可或缺的。

介紹一個基于 STM32F4 系列微控制器實現(xiàn)的模塊,該模塊采用環(huán)形緩沖區(qū)結構,并結合中斷機制,實現(xiàn)了非阻塞、緩存式的數(shù)據(jù)收發(fā)。整體設計思路清晰、邏輯模塊化,適合在嵌入式項目中直接復用。

模塊結構概覽

本模塊主要由兩個部分組成:

  1. 串口驅動模塊(tty.c)
    負責 UART 的初始化、收發(fā)控制與中斷服務處理。

  2. 環(huán)形緩沖區(qū)模塊(ringbuffer.c)
    提供通用的循環(huán)數(shù)據(jù)緩存接口,實現(xiàn)數(shù)據(jù)的無損、非阻塞讀寫。

這種設計將通信協(xié)議與緩存機制分離,提升了系統(tǒng)的可維護性與移植性。

基本數(shù)據(jù)結構設計

本模塊的核心是一個 ring_buf_t 類型,其內部應定義如下字段(見 ringbuffer.h):

typedef struct {
    unsigned char *buf;   // 實際數(shù)據(jù)緩沖區(qū)
    unsigned int size;    // 緩沖區(qū)總大?。ū仨殲?的冪)
    unsigned int front;   // 數(shù)據(jù)讀取指針
    unsigned int rear;    // 數(shù)據(jù)寫入指針} ring_buf_t;

設計約束:緩沖區(qū)大小必須為 2 的整數(shù)次冪。
這是為了優(yōu)化環(huán)形地址 wrap-around 操作,使用按位與(&)替代取模運算。


函數(shù)接口說明 初始化與清空

bool ring_buf_init(ring_buf_t *r, unsigned char *buf, unsigned int len);

初始化一個空的環(huán)形緩沖區(qū),要求 len 是 2 的冪,返回值表示初始化成功與否。

void ring_buf_clr(ring_buf_t *r);

將讀寫指針歸零,清空所有數(shù)據(jù)。


數(shù)據(jù)寫入

unsigned int ring_buf_put(ring_buf_t *r, unsigned char *buf, unsigned int len);

將外部數(shù)據(jù) buf 寫入到環(huán)形緩沖區(qū)中。若緩沖區(qū)剩余空間不足,則只寫入能容納的部分。返回實際寫入長度。

關鍵點:

  • 支持跨緩沖區(qū)尾部寫入(wrap-around);

  • 寫入操作不會覆蓋未讀數(shù)據(jù);

  • 使用 rear 指針更新寫入位置。


數(shù)據(jù)讀取

unsigned int ring_buf_get(ring_buf_t *r, unsigned char *buf, unsigned int len);

從環(huán)形緩沖區(qū)讀取數(shù)據(jù)至 buf,若請求數(shù)據(jù)超出已有長度,僅讀取實際可用部分。返回值為實際讀取字節(jié)數(shù)。

關鍵點:

  • 支持跨緩沖區(qū)尾部讀?。?/span>

  • 讀取數(shù)據(jù)后 front 指針更新;

  • 數(shù)據(jù)一旦讀取即“消費”,不可重復讀取。


 獲取當前數(shù)據(jù)長度

unsigned int ring_buf_len(ring_buf_t *r);

返回當前緩沖區(qū)中已存數(shù)據(jù)長度(rear - front)。注意該實現(xiàn)默認讀寫指針不斷增加,不會回繞,即 unsigned int 類型下支持最大 4G 字節(jié)空間。


性能優(yōu)化點

  1. 位操作替代模運算:
    緩沖區(qū)大小為 2 的冪時,可用 & (size - 1) 快速計算 wrap-around 的實際索引位置,減少 CPU 開銷。

r->rear & (r->size - 1)  // 相當于 r->rear % r->size
  1. 雙段 memcpy 提高吞吐:
    為處理尾部 wrap 情況,寫入和讀取都拆分成兩個 memcpy(),分別處理尾部和頭部兩段。


一、串口收發(fā)的關鍵設計思想1. 接收與發(fā)送分離

通過 USART1_IRQHandler 中斷服務函數(shù)分別處理 接收中斷 和 發(fā)送中斷,每次接收到數(shù)據(jù)就放入接收緩沖區(qū)(rxbuf),每次發(fā)送緩沖區(qū)中有數(shù)據(jù)就啟動發(fā)送中斷。這樣設計的優(yōu)點是:

  • 接收及時不中斷,防止數(shù)據(jù)丟失;

  • 發(fā)送自動控制,避免頻繁輪詢;

  • 系統(tǒng)主循環(huán)更加干凈清晰。

2. 非阻塞緩沖機制

通過自定義結構 ring_buf_t,配合 ring_buf_put 與 ring_buf_get,實現(xiàn)了一個靈活的環(huán)形數(shù)據(jù)緩沖區(qū)。相比一次性收發(fā)固定數(shù)據(jù),這種緩存機制更具魯棒性,適合串口波動大、數(shù)據(jù)密集或通信速率不一致的場合。


二、環(huán)形緩沖區(qū)的應用價值

環(huán)形緩沖區(qū)(Ring Buffer)是一種“循環(huán)”的數(shù)據(jù)結構,空間開銷小、速度快,非常適合嵌入式實時系統(tǒng)中對性能要求高的通信模塊。

在串口收發(fā)中,它的典型作用包括:

  • 解決串口收發(fā)異步性問題,接收與處理分離;

  • 支持可變長度數(shù)據(jù)幀的緩沖處理;

  • 與中斷或DMA天然契合,避免主線程阻塞;

  • 數(shù)據(jù)臨時緩存,保障高并發(fā)場景的數(shù)據(jù)完整性。


三、統(tǒng)一串口接口設計

為了提高代碼復用性,模塊中使用了一個結構體 tty_t 對串口操作進行統(tǒng)一抽象,包括:

  • 串口初始化函數(shù);

  • 發(fā)送數(shù)據(jù)接口;

  • 接收數(shù)據(jù)接口;

  • 緩沖狀態(tài)判斷函數(shù)(是否滿、是否空);

通過將這些函數(shù)指針封裝在結構體中,可以非常方便地實現(xiàn)“控制臺接口”或多串口同時支持,只需更換硬件配置部分即可。

const tty_t tty = {
    uart_init,
    uart_write,
    uart_read,
    tx_isfull,
    tx_isempty,
    rx_isempty
};

這種設計方式值得推廣到其他如 SPI、CAN、I2C 等通信模塊上,實現(xiàn)統(tǒng)一接口調用,提升代碼一致性。


四、典型應用場景

這個串口收發(fā)模塊適合嵌入式項目中的以下典型場景:

  • 設備調試打?。捍谧鳛?printf 的輸出設備,緩存打印內容,防止打印阻塞主循環(huán)。

  • 與上位機通訊:通過串口接收指令、發(fā)送響應數(shù)據(jù),配合協(xié)議幀解析模塊構成完整通訊鏈路。

  • 傳感器數(shù)據(jù)采集:將高頻率傳感器的串口數(shù)據(jù)接收后緩存,主線程按需讀取處理。

  • 工業(yè)控制通信:對實時性要求高,使用環(huán)形緩沖區(qū)和中斷機制可避免數(shù)據(jù)積壓。


五、設計優(yōu)點總結

  • 模塊化清晰:緩存模塊與串口驅動分離,便于獨立調試、復用。

  • 性能穩(wěn)定:中斷驅動 + 緩沖機制,避免數(shù)據(jù)丟失。

  • 擴展靈活:支持任意大小的緩存、多個串口實例。

  • 移植方便:與具體芯片無強耦合,適合在不同 STM32 系列中復用。


六、推薦使用方式

建議將此模塊封裝為標準組件,并在上層封裝為串口服務層,例如:

tty.uart_init(115200);tty.uart_write("Hello World", 11);

上層應用只需調用接口函數(shù),無需關注底層緩沖邏輯與中斷機制,提高應用開發(fā)效率。


七、后續(xù)可拓展方向

  • 支持 DMA 模式收發(fā),進一步提升數(shù)據(jù)吞吐;

  • 加入幀協(xié)議解析支持(如 Modbus、自定義幀);

  • 增加線程/RTOS安全訪問控制;

  • 緩沖區(qū)動態(tài)分配與多通道管理。


結語

一個好的串口模塊設計,往往是嵌入式系統(tǒng)穩(wěn)定運行的基礎。本文介紹的環(huán)形緩沖機制與中斷控制結合的串口收發(fā)架構,具有良好的通用性、擴展性與實際工程適用性,值得在項目中加以實踐與改進。

如你也在做基于 STM32 的嵌入式項目,這套結構可以幫助你快速搭建一個健壯、可擴展的模塊。

開源代碼:

#include "ringbuffer.h"#include <string.h>#include <stddef.h>#define min(a,b) ( (a) < (b) )? (a):(b)     
     /*
 *@brief      構造一個空環(huán)形緩沖區(qū)
 *@param[in]  r    - 環(huán)形緩沖區(qū)管理器
 *@param[in]  buf  - 數(shù)據(jù)緩沖區(qū)
 *@param[in]  len  - buf長度(必須是2的N次冪)
 *@retval     bool
 */bool ring_buf_init(ring_buf_t *r,unsigned char *buf, unsigned int len){
    r->buf    = buf;
    r->size   = len;
    r->front  = r->rear = 0;    return buf != NULL && (len & len -1) == 0;
}/*
 *@brief      清空環(huán)形緩沖區(qū) 
 *@param[in]  r - 待清空的環(huán)形緩沖區(qū)
 *@retval     none
 */void ring_buf_clr(ring_buf_t *r){
    r->front = r->rear = 0;
}/*
 *@brief      獲取環(huán)形緩沖區(qū)數(shù)據(jù)長度
 *@retval     環(huán)形緩沖區(qū)中有效字節(jié)數(shù) 
 */unsigned int ring_buf_len(ring_buf_t *r){    return r->rear - r->front;
}/*
 *@brief       將指定長度的數(shù)據(jù)放到環(huán)形緩沖區(qū)中 
 *@param[in]   buf - 數(shù)據(jù)緩沖區(qū)
 *             len - 緩沖區(qū)長度 
 *@retval      實際放到中的數(shù)據(jù) 
 */unsigned int ring_buf_put(ring_buf_t *r,unsigned char *buf,unsigned int len){    unsigned int i;    unsigned int left;
    left = r->size + r->front - r->rear;
    len  = min(len , left);
    i    = min(len, r->size - (r->rear & r->size - 1));   
    memcpy(r->buf + (r->rear & r->size - 1), buf, i); 
    memcpy(r->buf, buf + i, len - i);
    r->rear += len;     
    return len;
    
}/*
 *@brief       從環(huán)形緩沖區(qū)中讀取指定長度的數(shù)據(jù) 
 *@param[in]   len - 讀取長度 
 *@param[out]  buf - 輸出數(shù)據(jù)緩沖區(qū)
 *@retval      實際讀取長度 
 */unsigned int ring_buf_get(ring_buf_t *r,unsigned char *buf,unsigned int len){    unsigned int i;    unsigned int left;    
    left = r->rear - r->front;
    len  = min(len , left);                                
    i    = min(len, r->size - (r->front & r->size - 1));    memcpy(buf, r->buf + (r->front & r->size - 1), i);    
    memcpy(buf + i, r->buf, len - i);   
    r->front += len;    return len;
}



關鍵詞: 串口通信

評論


相關推薦

技術專區(qū)

關閉