環形緩沖區簡介
在單片機中串口通信是我們使用最頻繁的,使用串口通信就會用到串口的數據接收與發送,環形緩沖區方式接收數據可以更好的保證數據丟幀率第。
在通信程序中,經常使用環形緩沖器作為數據結構來存放通信中發送和接收的數據。環形緩沖區是一個先進先出的循環緩沖區,可以向通信程序提供對緩沖區的互斥訪問。
環形緩沖區的一個有用特性是:當一個數據元素被用掉后,其余數據元素不需要移動其存儲位置。相反,一個非圓形緩沖區(例如一個普通的隊列)在用掉一個數據元素后,其余數據元素需要向前搬移。換句話說,環形緩沖區適合實現先進先出緩沖區,而非環形緩沖區適合后進先出緩沖區。
STM32環形緩沖區示例
串口配置示例
#include "usart.h"
/********************串口初始化函數封裝*********************
****硬件接口:USART1_TX -- PA9(發送)
** USART1-RX --PA10(接收)
** USART2_TX -- PA2(發送)
** USART2-RX --PA3(接收)
** USART3_TX -- PB10(發送)
** USART3_RX -- PB11(接收)
形參:USART_TypeDef *USARTx -- 要配置的哪個串口
** u32 baud --波特率
** u32 sysclk --時鐘頻率(USART1 --72MHZ ,USAT2\USART3 --36MHZ)
**
***********************************************************/
void Usartx_Init(USART_TypeDef *USARTx,u32 baud,u32 sysclk)
{
if(USART1 == USARTx)
{
/*1.開時鐘*/
RCC->APB2ENR|=1<<2;//PA時鐘
RCC->APB2ENR|=1<<14;//串口時鐘
RCC->APB2RSTR|=1<<14;//串口復位
RCC->APB2RSTR&=~(1<<14);//取消復位
/*2.配置GPIO口*/
GPIOA->CRH&=0xFFFFF00F;
GPIOA->CRH|=0x000008B0;//上下拉輸入,復用推挽輸出
#ifdef USART1_IQR
USART1->CR1|=1<<5;//開啟串口接收中斷
STM32_NVIC_SetPriority(USART1_IRQn,0,1);//設置優先級
#endif
}
else if(USART2 == USARTx)
{
/*1.開時鐘*/
RCC->APB2ENR|=1<<2;//PA時鐘
RCC->APB1ENR|=1<<17;//USART2時鐘
RCC->APB1RSTR|=1<<17;//開復位時鐘
RCC->APB1RSTR&=~(1<<17);//取消復位
/*2.配置GPIO口*/
GPIOA->CRL&=0xFFFF00FF;//清除原來寄存器中的值
GPIOA->CRL|=0x00008B00;
#ifdef USART2_IRQ
USART2->CR1|=1<<5;//串口2接收中斷
STM32_NVIC_SetPriority(USART2_IRQn,1,2);//設置優先級
#endif
}
else if(USART3 == USARTx)
{
/*1.開時鐘*/
RCC->APB2ENR|=1<<3;//PB時鐘
RCC->APB1ENR|=1<<18;//USART3時鐘
RCC->APB1RSTR|=1<<18;//開復位時鐘
RCC->APB1RSTR&=~(1<<18);//取消復位
/*2.配置GPIO口*/
GPIOB->CRH&=0xFFFF00FF;
GPIOB->CRH|=0x00008B00;
#ifdef USART3_IRQ
USART3->CR1|=1<<5;//開啟接收中斷
STM32_NVIC_SetPriority(USART3_IRQn,0,0);//設置優先級
#endif
}
else return;
/*3.配置串口核心寄存器*/
USARTx->BRR=sysclk*1000000/baud;//設置波特率
USARTx->CR1|=1<<2;//接收使能
USARTx->CR1|=1<<3;//發送使能
USARTx->CR1|=1<<13;//使能串口3
}
/************************串口發送字符************************/
void Usartx_SendString(USART_TypeDef *USARTx,u8 *str,u8 len)
{
while(len--)
{
USARTx->DR=*str;
while((USARTx->SR&1<<7)==0){}//等待數據發送完成
str++;
}
}
/***************printf重定向**************/
int fputc(int c,FILE *stream)
{
USART1->DR=c;
while(!(USART1->SR&1<<7)){}
return c;
}
中斷接收數據 - - 環形緩沖區接收
/********************串口接收數據結構體********************/
#define USART1_LEN 200 //緩沖區大小
typedef struct
{
char buff[USART1_LEN];//緩沖區
u8 usart1_rx_len;//保存的數據長度
u8 usart1_flag;//數據接收完成標志
u8 w;//寫
u8 r;//讀
}USART1_RX;
USART1_RX USART1_rx={{0},0,0,0,0};//串口接收數據緩沖區初始化
void USART1_IRQHandler(void)
{
u8 c;
if(USART1->SR&1<<5)
{
c=USART1->DR;
//當寫入的數據長度==緩沖區長度,表示緩沖區滿
if(USART1_rx.usart1_rx_lenCNT=0;//清空計數器值
TIM2->CR1|=1<<0;
}
else USART1_rx.usart1_flag=1;//緩沖區滿
}
USART1->SR=0;//清除標志位
}
)>
讀取緩沖區數據
/**********************從緩沖區讀取數據******************
**
**形參:u8 *tx_data -- 讀取數據保存地址
**
*********************************************************/
u8 Usart1_Annular_txdata(u8 *tx_data)
{
u8 len=0;
//緩沖區為空 或者 USART1_rx.usart1_flag 數據接收完成標志(為了兼容字符串接收處理)
if(USART1_rx.usart1_rx_len==0 || USART1_rx.usart1_flag==0)return 0;
while(USART1_rx.usart1_rx_len)
{
*tx_data=USART1_rx.buff[USART1_rx.r];//讀取緩沖區數據
USART1_rx.r= (USART1_rx.r+1)%USART1_LEN;
USART1_rx.usart1_rx_len--;//緩沖區長度-1
tx_data++;
len++;
}
USART1_rx.usart1_flag=0;//清除標志位
*tx_data='\0';//接收到的字符保存為字符串
return len;//返回讀取到的字符個數
}
主函數
#include "stm32f10x.h"
#include "usart.h"
#include "led.h"
#include "timer.h"
u8 buff[200];
int main()
{
u8 stat=0;
Led_Init();//LED初始化
Usartx_Init(USART1,115200,72);
TIMx_Init(TIM2,72,20000);//通過定時器2輔助串口接收數據,20ms
printf("串口初始化完成\r\n");
/*輪詢*/
while(1)
{
stat=Usart1_Annular_txdata(buff);
if(stat)
{
Usartx_SendString(USART1,buff,stat);
}
}
}
審核編輯:湯梓紅
聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。
舉報投訴
-
單片機
+關注
關注
6035文章
44554瀏覽量
634631 -
緩沖區
+關注
關注
0文章
33瀏覽量
9107 -
STM32
+關注
關注
2270文章
10895瀏覽量
355729
發布評論請先 登錄
相關推薦
環形緩沖區的設計分享!
去訪問該緩沖區的最后一個內存位置的的后一位置時回到環形緩沖區的起點。類似一個環一樣。這樣形容就很好理解了,當然有辦法實現了。我在這里采用了2種方式實現了
發表于 10-28 23:29
請問串口的DMA接收緩沖區是不是環形緩沖區
大家好!請問串口的DMA接收緩沖區是不是環形緩沖區?通過閱讀串口部分的代碼,我了解到這樣幾點:1、串口的DMA接收時循環接收,當緩沖區滿了會重新從頭開始覆蓋掉之前的數據,和
發表于 08-30 14:27
環形緩沖區讀寫操作的分析與實現
環形緩沖區是嵌入式系統中一種重要的常用數據結構。在多任務環境下實現時,如果有多個讀寫任務,一般需要用信號量來保護多個任務共享的環形緩沖區。但是如果只存在1 個讀
發表于 04-15 11:35
?40次下載
緩沖區是啥意思 STM32串口數據接收之環形緩沖區
完成。 缺點: ①緩沖數據組數一定,且有多變量,代碼結構不太清晰。 ②接收數據長度可能大于數組大小,也可能小于數組大小。不靈活,需要接收數據很長時容易出錯,且內存利用率低。 解決這個問題的好辦法是:環形緩沖區。
環形緩沖區的實現思路
單片機程序開發一般都會用到UART串口通信,通過通信來實現上位機和單片機程序的數據交互。通信中為了實現正常的收發,一般都會有對應的發送和接收緩存來暫存通信數據。這里使用環形緩沖區的方式來設計數據收發的緩存,即緩沖區溢出后,從
C++環形緩沖區設計與實現
一、環形緩沖區基礎理論解析(Basic Theory of Circular Buffer) 1.1 環形緩沖區的定義與作用(Definition and Function of Ci
評論