0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

环形缓冲区简介 STM32环形缓冲区示例

嵌入式技术 来源:嵌入式技术 作者:嵌入式技术 2022-05-31 11:27 次阅读

环形缓冲区简介
单片机中串口通信是我们使用最频繁的,使用串口通信就会用到串口的数据接收与发送,环形缓冲区方式接收数据可以更好的保证数据丢帧率第。
在通信程序中,经常使用环形缓冲器作为数据结构来存放通信中发送和接收的数据。环形缓冲区是一个先进先出的循环缓冲区,可以向通信程序提供对缓冲区的互斥访问。
环形缓冲区的一个有用特性是:当一个数据元素被用掉后,其余数据元素不需要移动其存储位置。相反,一个非圆形缓冲区(例如一个普通的队列)在用掉一个数据元素后,其余数据元素需要向前搬移。换句话说,环形缓冲区适合实现先进先出缓冲区,而非环形缓冲区适合后进先出缓冲区。

watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDQ1MzY5NA==,size_16,color_FFFFFF,t_70#pic_center

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);
        }
	}
}
watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80NDQ1MzY5NA==,size_16,color_FFFFFF,t_70#pic_center

审核编辑:汤梓红
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 单片机
    +关注

    关注

    6001

    文章

    43973

    浏览量

    620821
  • 缓冲区
    +关注

    关注

    0

    文章

    31

    浏览量

    9031
  • STM32
    +关注

    关注

    2239

    文章

    10671

    浏览量

    348735
收藏 人收藏

    评论

    相关推荐

    STM32进阶之串口环形缓冲区实现

    完了数据,‘0’地址空间的数据进行释放掉,列队头指向下一个可以处理数据的地址‘1’。从而实现整个环形缓冲区的数据读写。看图,队列头就是指向已经存储的数据,并且这个数据是待处理的。下一个CPU处理的数据
    发表于 06-08 14:03

    杰杰带你解读【机智云】环形缓冲区源码

    ,人家既然能拿来做商业用,还是有很厉害的地方的,如果还不知道什么叫环形缓冲区环形队列)的同学,请看——STM32进阶之串口环形
    发表于 07-17 14:58

    STM32串口环形缓冲区的实现

    是列队头的数据,处理完了数据,‘0’地址空间的数据进行释放掉,列队头指向下一个可以处理数据的地址‘1’。从而实现整个环形缓冲区的数据读写。看图,队列头就是指向已经存储的数据,并且这个数据是待处理
    发表于 10-16 11:40

    环形缓冲区的设计分享!

    去访问该缓冲区的最后一个内存位置的的后一位置时回到环形缓冲区的起点。类似一个一样。这样形容就很好理解了,当然有办法实现了。我在这里采用了2种方式实现了
    发表于 10-28 23:29

    STM32串口环形缓冲区的实现方法

    STM32串口环形缓冲区的实现
    发表于 12-24 07:30

    环形缓冲区简介

    STM32串口数据接收 --环形缓冲区环形缓冲区简介  在单片机中串口通信是我们使用最频繁的,使
    发表于 08-17 06:56

    什么是STM32环形缓冲区

    什么是STM32环形缓冲区
    发表于 11-18 07:52

    怎么实现串口环形缓冲区

    怎么实现串口环形缓冲区
    发表于 12-06 06:01

    STM32环形缓冲区怎么实现?

    STM32环形缓冲区怎么实现?
    发表于 12-07 07:25

    stm32是怎样使用环形缓冲区形式去接收数据的

    stm32是怎样使用环形缓冲区形式去接收数据的?如何去实现其代码呢?
    发表于 12-07 06:24

    如何实现STM32串口环形缓冲区

    如何实现STM32串口环形缓冲区
    发表于 12-08 06:13

    请问串口的DMA接收缓冲区是不是环形缓冲区

    大家好!请问串口的DMA接收缓冲区是不是环形缓冲区?通过阅读串口部分的代码,我了解到这样几点:1、串口的DMA接收时循环接收,当缓冲区满了会重新从头开始覆盖掉之前的数据,和
    发表于 08-30 14:27

    环形缓冲区的实现原理

    在通信程序中,经常使用环形缓冲区作为数据结构来存放通信中发送和接收的数据。环形缓冲区是一个先进先出的循环缓冲区,可以向通信程序提供对
    的头像 发表于 03-22 10:03 7173次阅读
    <b class='flag-5'>环形</b><b class='flag-5'>缓冲区</b>的实现原理

    STM32串口数据接收 --环形缓冲区

    STM32串口数据接收 --环形缓冲区环形缓冲区简介  在单片机中串口通信是我们使用最频繁的,使
    发表于 12-28 19:24 30次下载
    <b class='flag-5'>STM32</b>串口数据接收 --<b class='flag-5'>环形</b><b class='flag-5'>缓冲区</b>

    STM32进阶之串口环形缓冲区实现

    STM32进阶之串口环形缓冲区实现
    的头像 发表于 09-19 09:20 1637次阅读
    <b class='flag-5'>STM32</b>进阶之串口<b class='flag-5'>环形</b><b class='flag-5'>缓冲区</b>实现