【STM32 CubeMX】学STM必会的数据结构——环形缓冲区


前言

在嵌入式系统开发中,经常需要处理数据的缓存和传输,而环形缓冲区是一种常见且有效的数据结构,特别适用于处理实时数据流或者在有限的内存资源下高效地管理数据。在STM32微控制器的开发中,使用CubeMX工具可以方便地配置和生成环形缓冲区的代码,从而加速开发过程并提高代码的可维护性。本文将介绍STM32 CubeMX中环形缓冲区的使用方法以及其在嵌入式系统开发中的重要性。


一、环形缓冲区是什么

当我们处理数据时,有时候需要一个地方来临时存储它们,就好像我们用盘子装菜一样。但是,内存有限,如果盘子装满了就得从头开始放菜,这样效率不高。环形缓冲区就像是一个环形的菜盘,当盘子满了,就会从一端开始取走菜,同时从另一端继续放新的菜,这样就能不停地装菜,而且效率很高。

现在,让我们画一个简单的图来演示一下:

[ 1 ] [ 2 ] [ 3 ] [ 4 ] [ 5 ] [ 6 ] [ 7 ] [ 8 ]
 ^                           ^
 |                           |
取走                        放入

在这里插入图片描述

这里,我们有一个有8个位置的环形缓冲区,用方括号表示每个位置。现在,我们从左边取走了一个数据,然后从右边放入了一个新的数据。这样,缓冲区就像一个环,数据可以不停地在其中循环。

这种数据结构适合一方读buf,一方写buf的情节

二、实现环形缓冲区

实现分析

我们需要定义存储区buf

char buf[100];

我们还需要定义读位置为0,写位置为0
后面我们通过这两个变量来操作读和写

int r,w = 0;

那么怎么写入数据和读数据呢?
读:
首先肯定要有数据我们才能读吧,那么怎么判断有没有数据呢?
当我们的r = w时,他是空的,如果是空,我们肯定不能读,如果是有数据,直接返回对应下标即可

写:
首先我们要知道,如果buf满了,肯定是不能把原来的数据给干掉的,那么我们怎么判断他有没有满呢,如果直接使用r = w来判断,那就和判断空是一样的了,我们可以使用w+1 = r来判断,因为如果没满,我写一个进去,他肯定不等于r,如果满了我写一个进去他等于r就是满了,我们使用w+1来模拟写入后的w状态即可

如果读和写超过了这个buf的原始大小,因为他是环形缓冲区,所以需要把下标取余个buf的size

2.1 环形缓冲区初始化

首先声明一个结构体,这个结构体存储着缓冲区buf,读r和写w

typedef struct
{
	int *buf;
	int len;
	int r;
	int w;
}CircleBuf,*p_CircleBuf;

接下来声明一个函数进行init操作

void CircleBufInit(p_CircleBuf pbuf,int* buf ,int len)
{
	pbuf->r = pbuf->w = 0;
	pbuf->buf = buf;
	pbuf->len = len;
}

对于这个函数,你可以从外部传入buf进行缓冲区的初始化,也可以使用malloc进行内存的分配初始化

2.2 写buf

我们需要实现下面这个函数来进行写buf

void CircleBufWrite(p_CircleBuf pCircleBuf, int val);

首先我们需要先定义一个变量存储w的下一个下标,并且如果下一个下标超出len,需要变成0,实现环形

int nextW = pCircleBuf->w + 1;
nextW %= pCircleBuf->len;

接下来,我们需要去判断nextW是否等于r,如果不等于,代码没有满

if (pCircleBuf->r != nextW)

如果没有满,我们需要把对应的w下标赋值成val
然后w下标++,再对w进行取余len,如果下标超出len,需要变成0,实现环形

pCircleBuf->buf[pCircleBuf->w] = val;
pCircleBuf->w++;
pCircleBuf->w %= pCircleBuf->len;

2.3 读buf

我们需要实现下面这个函数来进行读buf

void CircleBufRead(p_CircleBuf pCircleBuf, int* val);

首先我们先要判断r !=w才能进行读操作

if (pCircleBuf->r != pCircleBuf->w)

如果不等于
我们可以把r对应的下标给val
然后r读下标++
因为可能存在读完的情况所以我们需要进行取余操作

*val = pCircleBuf->buf[pCircleBuf->r];
pCircleBuf->r++;
pCircleBuf->r %= pCircleBuf->len;

如果等于,我们可以把val的值变成NULL

else
{
	val = NULL;
}

2.4 测试

我们可以先写入一部分数据,然后,我们可以使用CircleBufRead读出来,读出来之后立马进行写,我们可以通过下面这种方法进行缓冲区的测试:

CircleBuf cBuf;
int buf[100] = { 0 };
CircleBufInit(&cBuf,&buf,100);

for (int i = 0; i < 100; i++)
{
	CircleBufWrite(&cBuf, i);
}

int i = 100;
while (1)
{
	int temp = -1;
	CircleBufRead(&cBuf, &temp);
	printf("%d ", temp);

	CircleBufWrite(&cBuf, i);
	i++;

	Sleep(10);
}

三、代码总况

//Circle.c
#include "circleBuf.h"
#include <memory.h>

void CircleBufInit(p_CircleBuf pbuf,int* buf ,int len)
{
	pbuf->r = pbuf->w = 0;
	pbuf->buf = buf;
	pbuf->len = len;
}

void CircleBufRead(p_CircleBuf pCircleBuf, int* val)
{
	if (pCircleBuf->r != pCircleBuf->w)
	{
		*val = pCircleBuf->buf[pCircleBuf->r];
		pCircleBuf->r++;
		pCircleBuf->r %= pCircleBuf->len;
	}
	else
	{
		val = NULL;
	}
}

void CircleBufWrite(p_CircleBuf pCircleBuf, int val)
{
	int nextW = pCircleBuf->w + 1;
	nextW %= pCircleBuf->len;
	if (pCircleBuf->r != nextW)
	{
		pCircleBuf->buf[pCircleBuf->w] = val;
		pCircleBuf->w++;
		pCircleBuf->w %= pCircleBuf->len;
	}
}
//Circle.h
#pragma once

typedef struct
{
	int *buf;
	int len;
	int r;
	int w;
}CircleBuf,*p_CircleBuf;

void CircleBufInit(p_CircleBuf pbuf, int*buf ,int len);

void CircleBufRead(p_CircleBuf pCircleBuf, int* val);

void CircleBufWrite(p_CircleBuf pCircleBuf, int val);
//main.c
#include <stdio.h>
#include <stdlib.h>
#include "circleBuf.h"
#include <Windows.h>

int main()
{
	CircleBuf cBuf;
	int buf[100] = { 0 };
	CircleBufInit(&cBuf,&buf,100);

	for (int i = 0; i < 100; i++)
	{
		CircleBufWrite(&cBuf, i);
	}

	int i = 100;
	while (1)
	{
		int temp = -1;
		CircleBufRead(&cBuf, &temp);
		printf("%d ", temp);

		CircleBufWrite(&cBuf, i);
		i++;

		Sleep(10);
	}

	system("pause>0");
	return 0;
}

总结

环形缓冲区是嵌入式系统开发中常用的数据结构之一,具有高效、可靠的特性。通过STM32 CubeMX工具,我们可以轻松地配置和生成环形缓冲区的代码,从而简化开发流程并提高代码的可维护性。掌握环形缓冲区的原理和使用方法,对于STM32微控制器的开发者来说是必不可少的技能。希望本文能够帮助读者更好地理解和应用环形缓冲区,从而更加高效地开发嵌入式系统。

  • 35
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
STM32CubeMX可以帮助你更方便地进行STM32芯片的图形化配置和代码生成。STM32CubeMX是ST意法半导体推荐的配置工具,可以通过图形化界面来进行基础设置配置以及生成C语言的初始化代码,从而减轻开发工作的负担,节省时间和费用,并提高开发效率。它几乎覆盖了STM32全系列芯片。 在STM32CubeMX之前,首先需要了解其界面介绍。界面介绍包括了STM32CubeMX的各个部分以及它们的功能和作用。这些信息可以在文献中找到。 此外,了解代码编写的规范也是很重要的。在使用STM32CubeMX时,要将自己的代码写在 /* XX CODE BEGIN*/ 和 /* XX CODE END*/ 之间,这样在下次再生成工程时,不在这个区域内的代码不会被删除。更多关于代码编写规范的详细信息可以在文献中找到。 另外,补充一下STM32的三种开发模式,它们是:标准外设库模式、HAL库模式和LL库模式。每种模式都有自己的特点和适用场景,具体的内容可以在之后的博客中详细介绍。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [STM32 CubeMx教程 -- 基础知识及配置使用教程](https://blog.csdn.net/Dir_x/article/details/128846252)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

人才程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值