找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

帖子
查看: 6824|回復(fù): 3
收起左側(cè)

[開(kāi)源]輕量級(jí)環(huán)形緩沖區(qū)Ring Buffer,非常適合用于MCU嵌入式平臺(tái)的串口收發(fā)

  [復(fù)制鏈接]
ID:826745 發(fā)表于 2021-1-30 11:53 | 顯示全部樓層 |閱讀模式
Ring Buffer是一個(gè)基于C語(yǔ)言開(kāi)發(fā)的輕量級(jí)環(huán)形緩沖區(qū),適用于各嵌入式平臺(tái)的串口收發(fā)等應(yīng)用場(chǎng)景;

相較于普通的收發(fā)緩沖數(shù)組,環(huán)形緩沖區(qū)的操作更加簡(jiǎn)單,性能更加強(qiáng)大;
使用Ring Buffer提供的函數(shù),可以輕松實(shí)現(xiàn)數(shù)據(jù)的讀寫、查詢、刪除等操作,不需要編寫復(fù)雜的地址記錄、讀寫計(jì)數(shù)等代碼,減少了數(shù)據(jù)指針溢出、數(shù)據(jù)被覆蓋的風(fēng)險(xiǎn);
同時(shí)Ring Buffer還提供了可自定義分隔關(guān)鍵字的插入、查找等功能,運(yùn)用在嵌入式的串口收發(fā)中可以實(shí)現(xiàn)多段數(shù)據(jù)的儲(chǔ)存,段落之間分隔獨(dú)立,讀寫緩沖區(qū)不再受到硬件時(shí)序的阻塞,降低串口對(duì)芯片實(shí)時(shí)響應(yīng)的要求并提升了數(shù)據(jù)傳輸?shù)目煽啃裕?br />
代碼已在GD32F130C8T6 MCU平臺(tái)上通過(guò)編譯,已進(jìn)行過(guò)大量數(shù)據(jù)的串口收發(fā)壓力測(cè)試,暫未發(fā)現(xiàn)顯性BUG;
項(xiàng)目開(kāi)源地址:Github

XCOM_V2.2_VokMjsmVNN.png

2021.01.19 v1.0.0 發(fā)布第一版本
2021.01.24 v1.1.0 增加匹配字符查找函數(shù)
2021.01.27 v1.2.0 重制匹配字符查找函數(shù),現(xiàn)已支持8位到32位關(guān)鍵詞查詢
2021.01.28 v1.3.0 復(fù)位函數(shù)修改為刪除函數(shù)、增加關(guān)鍵詞插入函數(shù)(自適應(yīng)大小端)
2021.01.30 v1.3.1 修復(fù)String讀寫函數(shù)的小概率指針溢出錯(cuò)誤
持續(xù)更新中,歡迎大家使用,如果有BUG請(qǐng)到Github上及時(shí)向我反饋,謝謝

同時(shí)我在GD32F130平臺(tái)上基于Ring Buffer庫(kù)開(kāi)發(fā)了一款單片機(jī)串口收發(fā)框架UIO,開(kāi)發(fā)UIO的目的也是為了更好的利用Ring Buffer的特點(diǎn),在實(shí)際使用環(huán)形緩沖的過(guò)程中不斷的優(yōu)化與改進(jìn);
使用UIO后,你可以在單片機(jī)中同時(shí)緩存好幾條串口指令卻不需要實(shí)時(shí)處理,等到單片機(jī)忙完其他阻塞任務(wù)后再將接收緩存的串口數(shù)據(jù)逐條讀出并逐條處理,從容不迫;
UIO的大部分代碼與平臺(tái)分離,移植簡(jiǎn)單,同時(shí)對(duì)硬件串口外設(shè)進(jìn)行封裝,在應(yīng)用層開(kāi)發(fā)的時(shí)候非常方便,UIO仍在加緊時(shí)間開(kāi)發(fā)并測(cè)試,屆時(shí)將會(huì)第一時(shí)間開(kāi)源分享給大家吐槽,敬請(qǐng)期待吧!

歡迎關(guān)注我的b站視頻賬號(hào):bilibili

評(píng)分

參與人數(shù) 1黑幣 +100 收起 理由
admin + 100 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

回復(fù)

使用道具 舉報(bào)

ID:826745 發(fā)表于 2021-1-30 12:12 | 顯示全部樓層
復(fù)制庫(kù)文件至工程中,在源代碼中引用 Ring Buffer 頭文件;
新建一個(gè) uint8_t 數(shù)組,數(shù)組的大小即是環(huán)形緩沖區(qū)的大��;
新建 Ring Buffer 操作句柄;
初始化 Ring Buffer 操作句柄,將其與剛才新建的數(shù)組綁定,轉(zhuǎn)換成環(huán)形緩沖區(qū);
這時(shí)候我們就可以使用庫(kù)提供的各種函數(shù)對(duì)新建的緩沖區(qū)進(jìn)行讀寫等操作;
函數(shù)詳細(xì)內(nèi)容請(qǐng)?jiān)诰幊痰倪^(guò)程中參考ring_buffer.c內(nèi)的注釋;
回復(fù)

使用道具 舉報(bào)

ID:826745 發(fā)表于 2021-1-30 12:13 | 顯示全部樓層
在這里我展示了如何新建并初始化Ring Buffer、讀寫環(huán)形緩沖、查詢數(shù)據(jù)長(zhǎng)度等基礎(chǔ)操作
您可以了解到Ring Buffer的函數(shù)命名與參數(shù)的風(fēng)格和基本的使用方法
  1. #include <stdio.h>
  2. #include <ring_buffer.h>

  3. #define Read_BUFFER_SIZE        256

  4. int main()
  5. {
  6.     //新建緩沖區(qū)數(shù)組與Ring Buff操作句柄
  7.     uint8_t buffer[Read_BUFFER_SIZE] ;
  8.     ring_buffer RB ;

  9.     //初始化Ring Buff操作句柄,綁定緩沖區(qū)數(shù)組;
  10.     Ring_Buffer_Init(&RB, buffer, Read_BUFFER_SIZE);

  11.     //向環(huán)形緩沖區(qū)寫入一段字節(jié)和一個(gè)字節(jié)
  12.     Ring_Buffer_Write_String(&RB, "hello world", 11);
  13.     Ring_Buffer_Write_Byte(&RB, '!');

  14.     //獲取已儲(chǔ)存的數(shù)據(jù)長(zhǎng)度,讀出環(huán)形緩沖區(qū)中的數(shù)據(jù)并打印
  15.     uint32_t num = Ring_Buffer_Get_Lenght(&RB);
  16.     uint8_t get[16] ;
  17.     Ring_Buffer_Read_String(&RB, get, num);
  18.     printf("%s", get);
  19.    
  20.     return 0 ;
  21. }
復(fù)制代碼
回復(fù)

使用道具 舉報(bào)

ID:826745 發(fā)表于 2021-1-30 12:13 | 顯示全部樓層
除了基本的讀寫操作之外,為了更好的利用環(huán)形這一特點(diǎn),我加入了分隔關(guān)鍵詞、查詢關(guān)鍵詞、刪除數(shù)據(jù)等功能
基于這些功能您可以在串口收發(fā)中實(shí)現(xiàn)多段數(shù)據(jù)的緩存與準(zhǔn)確讀取;降低了實(shí)時(shí)性響應(yīng)的要求、提升了串口收發(fā)的性能
  1. #include <stdio.h>
  2. #include <ring_buffer.h>

  3. #define Read_BUFFER_SIZE        256

  4. //設(shè)定一個(gè)分隔關(guān)鍵詞和關(guān)鍵詞的長(zhǎng)度(字節(jié))
  5. #define SEPARATE_SIGN       0xCCFB22AA
  6. #define SEPARATE_SIGN_SIZE  4

  7. int main()
  8. {
  9.     //新建緩沖區(qū)數(shù)組與Ring Buff操作句柄
  10.     uint8_t buffer[Read_BUFFER_SIZE] ;
  11.     ring_buffer RB ;

  12.     //初始化Ring Buff操作句柄,綁定緩沖區(qū)數(shù)組;
  13.     Ring_Buffer_Init(&RB, buffer, Read_BUFFER_SIZE);

  14.     //記錄段落數(shù)量
  15.     uint8_t String_Count = 0 ;

  16.     //向環(huán)形緩沖區(qū)寫入三段數(shù)據(jù),每段之間插入一個(gè)分隔關(guān)鍵詞
  17.     Ring_Buffer_Write_String(&RB, "ABCDEFGHIJK\r\n", 13);//寫入一段數(shù)據(jù)
  18.     Ring_Buffer_Insert_Keyword(&RB, SEPARATE_SIGN, SEPARATE_SIGN_SIZE);//插入一個(gè)分隔關(guān)鍵詞
  19.     String_Count ++ ;//記錄段落數(shù)量 +1

  20.     Ring_Buffer_Write_String(&RB, "abcdefg\r\n", 9);
  21.     Ring_Buffer_Insert_Keyword(&RB, SEPARATE_SIGN, SEPARATE_SIGN_SIZE);
  22.     String_Count ++ ;

  23.     Ring_Buffer_Write_String(&RB, "1234\r\n", 6);
  24.     Ring_Buffer_Insert_Keyword(&RB, SEPARATE_SIGN, SEPARATE_SIGN_SIZE);
  25.     String_Count ++ ;

  26.     while(String_Count != 0)
  27.     {
  28.         uint8_t get[16] ;
  29.         //獲得頭指針到關(guān)鍵詞高位的距離,距離-1得到第一段數(shù)據(jù)的長(zhǎng)度
  30.         uint8_t lenght = Ring_Buffer_Find_Keyword(&RB, SEPARATE_SIGN, SEPARATE_SIGN_SIZE) - 1 ;
  31.         Ring_Buffer_Read_String(&RB, get, lenght);//讀取一段數(shù)據(jù),保存到get數(shù)組
  32.         printf("%s", get);//打印數(shù)據(jù)
  33.         Ring_Buffer_Delete(&RB, SEPARATE_SIGN_SIZE);//刪除分隔關(guān)鍵詞的長(zhǎng)度的數(shù)據(jù),即刪除關(guān)鍵詞
  34.         String_Count -- ;//記錄段落數(shù)量 -1
  35.     }

  36.     return 0 ;
  37. }
復(fù)制代碼
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表