成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

STM32串口開發之環形緩沖區

開發 前端
緩沖區看名字就知道,是緩沖數據用的。實現緩沖區最簡單的辦法時,定義多個數組,接收一包數據到數組A,就把接收數據的地址換成數組B,每個數據有個標記字節用于表示這個數組是否收到數據,收到數據是否處理完成。

[[407451]]

01簡介

在之前的文章《stm32 串口詳解》中,我們講解了串口的基本應用,使用串口中斷接收數據,串口中斷發送回包(一般可以使用非中斷形式發送回包,在數據接收不頻繁的應用中。串口接收中斷保證串口數據及時響應,使用非中斷方式發送回包即可)。

后面的文章《STM32使用DMA接收串口數據》和《STM32使用DMA發送串口數據》講解了如何使用DMA輔助串口收發數據,使用DMA的好處在于不用CPU即可完成串口收發數據,減輕CPU負擔,在串口通信頻繁且不想頻繁中斷的應用中非常有用。

除了上述兩種場景,還有一種應用場景:串口接收數據長度位置,頻率未知,不要求實時處理的場景。如果采用上述方案,接收一幀數據立即處理,那么在處理的時候來的數據包就“丟失”了。這個時候就需要緩沖隊列來解決這個問題。

02緩沖區

緩沖區看名字就知道,是緩沖數據用的。實現緩沖區最簡單的辦法時,定義多個數組,接收一包數據到數組A,就把接收數據的地址換成數組B,每個數據有個標記字節用于表示這個數組是否收到數據,收到數據是否處理完成。

上述方案是完全可行的,但有缺點:

①緩沖數據組數一定,且有多變量,代碼結構不太清晰。

②接收數據長度可能大于數組大小,也可能小于數組大小。不靈活,需要接收數據很長時容易出錯,且內存利用率低。

解決這個問題的好辦法是:環形緩沖區。

環形緩沖區就是一個帶“頭指針”和“尾指針”的數組。“頭指針”指向環形緩沖區中可讀的數據,“尾指針”指向環形緩沖區中可寫的緩沖空間。通過移動“頭指針”和“尾指針”就可以實現緩沖區的數據讀取和寫入。在通常情況下,應用程序讀取環形緩沖區的數據僅僅會影響“頭指針”,而串口接收數據僅僅會影響“尾指針”。當串口接收到新的數組,則將數組保存到環形緩沖區中,同時將“尾指針”加1,以保存下一個數據;應用程序在讀取數據時,“頭指針”加1,以讀取下一個數據。當“尾指針”超過數組大小,則“尾指針”重新指向數組的首元素,從而形成“環形緩沖區”!,有效數據區域在“頭指針”和“尾指針”之間。如下圖

如上面說的,環形緩沖區其實就是一個數組,將其“剪開”,然后“拉直”后如下圖

環形緩沖區的特性

1、先進新出。

2、當緩沖區被使用完,且又有新的數據需要存儲時,丟掉歷史最久的數據,保存最新數據。

03代碼實現

環形緩沖區的實現很簡單,只需要簡單的幾個接口即可。

首先需要創建一個環形緩沖區

  1. #define  RINGBUFF_LEN          (500)     //定義最大接收字節數 500 
  2. #define  RINGBUFF_OK           1      
  3. #define  RINGBUFF_ERR          0    
  4. typedef struct 
  5.     uint16_t Head;            
  6.     uint16_t Tail; 
  7.     uint16_t Lenght; 
  8.     uint8_t  Ring_data[RINGBUFF_LEN]; 
  9. }RingBuff_t; 
  10. RingBuff_t ringBuff;//創建一個ringBuff的緩沖區 

當我們發現環形緩沖區被“沖爆”時,也就是緩沖區滿了,但是還有待緩沖的數據時,只需要修改RINGBUFF_LEN的宏定義,增大緩沖區間即可。

環形緩沖區的初始化

  1. /** 
  2. * @brief  RingBuff_Init 
  3. * @param  void 
  4. * @return void 
  5. * @note   初始化環形緩沖區 
  6. */ 
  7. void RingBuff_Init(void) 
  8.   //初始化相關信息 
  9.   ringBuff.Head = 0; 
  10.   ringBuff.Tail = 0; 
  11.   ringBuff.Lenght = 0; 

主要是將環形緩沖區的頭,尾和長度清零,表示沒有任何數據存入。

環形緩沖區的寫入

  1. /** 
  2. * @brief  Write_RingBuff 
  3. * @param  uint8_t data 
  4. * @return FLASE:環形緩沖區已滿,寫入失敗;TRUE:寫入成功 
  5. * @note   往環形緩沖區寫入uint8_t類型的數據 
  6. */ 
  7. uint8_t Write_RingBuff(uint8_t data) 
  8.   if(ringBuff.Lenght >= RINGBUFF_LEN) //判斷緩沖區是否已滿 
  9.   { 
  10.     return RINGBUFF_ERR; 
  11.   } 
  12.   ringBuff.Ring_data[ringBuff.Tail]=data; 
  13.   ringBuff.Tail = (ringBuff.Tail+1)%RINGBUFF_LEN;//防止越界非法訪問 
  14.   ringBuff.Lenght++; 
  15.   return RINGBUFF_OK; 

這個接口是寫入一個字節到環形緩沖區。這里注意:大家可以根據自己的實際應用修改為一次緩沖多個字節。并且這個做了緩沖區滿時報錯且防止非法越界的處理,大家可以自行修改為緩沖區滿時覆蓋最早的數據。

環形緩沖區的讀取

  1. /** 
  2. * @brief  Read_RingBuff 
  3. * @param  uint8_t *rData,用于保存讀取的數據 
  4. * @return FLASE:環形緩沖區沒有數據,讀取失敗;TRUE:讀取成功 
  5. * @note   從環形緩沖區讀取一個u8類型的數據 
  6. */ 
  7. uint8_t Read_RingBuff(uint8_t *rData) 
  8.   if(ringBuff.Lenght == 0)//判斷非空 
  9.   { 
  10.     return RINGBUFF_ERR; 
  11.   } 
  12.   *rData = ringBuff.Ring_data[ringBuff.Head];//先進先出FIFO,從緩沖區頭出 
  13.   ringBuff.Head = (ringBuff.Head+1)%RINGBUFF_LEN;//防止越界非法訪問 
  14.   ringBuff.Lenght--; 
  15.   return RINGBUFF_OK; 

讀取的話也很簡單,同樣是讀取一個字節,大家可以自行修改為讀取多個字節。

04驗證

光說不練假把式,下面我們就來驗證上面的代碼可行性。

串口中斷函數中緩沖數據

  1. void USART1_IRQHandler(void) 
  2.   if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE)) 
  3.   { 
  4.     Write_RingBuff(USART_ReceiveData(USART1)); 
  5.     USART_ClearFlag(USART1, USART_FLAG_RXNE); 
  6.   } 

在主循環中,讀取緩沖區的數據,然后發送出去,因為是簡單的demo,添加了延時模擬CPU處理其他任務。

  1. while (1) 
  2.   { 
  3.     if(Read_RingBuff(&data))            //從環形緩沖區中讀取數據 
  4.     { 
  5.       USART_SendData(USART1, data); 
  6.     } 
  7.     SysCtlDelay(1*(SystemCoreClock/3000)); 
  8.   } 

驗證,間隔100ms發送數據。

結果顯示沒有出現丟包問題。如果你的應用場景串口通信速率快,數據量大或處理速度慢導致丟包,建議增大RINGBUFF_LEN的宏定義,增大緩沖區間即可。

本文轉載自微信公眾號「 知曉編程」,可以通過以下二維碼關注。轉載本文請聯系 知曉編程公眾號。

 

責任編輯:姜華 來源: 知曉編程
相關推薦

2017-07-04 17:09:10

Map環形緩沖區數據

2018-01-26 14:52:43

2021-05-20 07:26:22

DMASTM32數據

2021-05-06 08:54:39

串口DMASTM32

2011-12-14 16:30:42

javanio

2017-01-09 17:03:34

2019-02-27 13:58:29

漏洞緩沖區溢出系統安全

2014-07-30 11:21:46

2009-11-16 17:26:17

Oracle優化緩沖區

2009-11-16 17:08:59

Oracle日志緩沖區

2021-01-20 09:51:25

STM32網絡接口

2009-07-15 15:50:48

Jython線程

2009-11-16 16:59:24

Oracle優化庫高速

2023-10-09 23:01:09

MySQL數據庫

2009-09-24 18:16:40

2011-07-20 10:54:14

C++

2010-12-27 10:21:21

2015-03-06 17:09:10

2022-05-07 08:27:42

緩沖區溢出堆棧

2010-10-09 14:45:48

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 色综合一区| 国产精品a一区二区三区网址 | 亚洲色欧美另类 | 在线亚洲欧美 | 久久成人精品视频 | 国产精品小视频在线观看 | 久久国产一区二区 | 看真人视频一级毛片 | 日韩亚洲一区二区 | 国产精品国产精品国产专区不卡 | 国产成人99| 久草福利 | 美女爽到呻吟久久久久 | 国产精品久久久久久亚洲调教 | 99国产精品久久久 | 国产91在线播放精品91 | 日韩和的一区二区 | 久综合 | 精精国产xxxx视频在线 | 欧美精品久久久久 | 成人免费淫片aa视频免费 | av一区二区三区四区 | 一级片网址 | 亚洲欧美日韩一区二区 | 久久三区| 日韩欧美三级 | 性精品 | 久草视频2| 中文字幕高清 | 亚洲精品一区二区三区蜜桃久 | 久久精品国产一区二区三区不卡 | 少妇久久久 | 欧美韩一区二区三区 | 狠狠操狠狠搞 | 伊人久久成人 | 午夜精品久久久久久久99黑人 | 九色在线视频 | 亚洲成人自拍 | 精品1区2区3区 | 亚洲视频三区 | 亚洲国产偷 |