重点--环形缓冲区-----适合在通信中接收数据

news2024/10/5 19:19:02

为什么要用环形缓冲区
当有大量数据的时候,我们不能存储所有的数据,那么计算机处理数据的时候,只能先处理先来的,处理之后就会把数据释放掉,再处理下一个。那么已经处理的数据的内存就会被浪费掉。因为后来的数据只能往后排队,如果要将剩余的数据都往前移动一次,那么效率就会低下了,肯定不现实,所以,环形队列就出现了。

环形缓冲区是一项很好的技术,不用频繁的分配内存,而且在大多数情况下,内存的反复使用也使得我们能用更少的内存块做更多的事。

例如在串口数据接受中,外设某次发送的报文最大是100个字节,如果使用普通接收方式则需要申请一个100字节的数组。而外设并不是每次都是发送100个字节,当发送50个字节的时候,剩余的50个字节就会被浪费掉。因此引入环形缓冲区,mcu接收到一个数据在串口中断往环形缓冲区里面写一个数据,另一个线程就读一个数据,互相追逐,使用这种方式接收100字节的报文或许只需要20个字节的环形缓冲区,大大节省了内存。

typedef struct {
volatile unsigned int pW; //写位置
volatile unsigned int pR; //读位置
volatile unsigned char buff[RING_BUFF_SIZE];//缓冲区
}RingBuff;
环形缓冲区实现原理

环形缓冲区通常有一个表示读位置的变量和写位置的变量。读位置指向环形缓冲区可读的数据,写位置只想环形缓冲区可写的数据。我们只需要移动读写位置就可以获实现缓冲区的读写。初始化时读写位置都为0。

void RingBuffInitial(RingBuff *dst_buff)
{
dst_buff->pW = 0;
dst_buff->pR = 0;
}
在这里插入图片描述
写数据
往环形缓冲区里面写数据数据时要考虑缓冲区是否已经满了,如果满了就放弃这次的数据。每写入成功一个数据pW位置都要更新W

判断环形缓冲区满的条件是pR ==(pW +1)%RING_BUFF_SIZE则为满

void RingBuffWrite(RingBuff *dst_buff, unsigned char dat)
{

int i;
i = (dst_buff->pW + 1)%RING_BUFF_SIZE;
if(i != dst_buff->pR)
{
    dst_buff->buff[dst_buff->pW] = dat;
    dst_buff->pW = i; //更新pW位置
}

}
在这里插入图片描述
读数据
读取数据要考虑环形缓冲区是否为空。判断条件是pW == pR则为空,读取成功返回0 失败返回-1

每读取成功一个数据pR位置都要更新

int RingBuffRead(RingBuff *dst_buff, unsigned char *dat)
{

if(dst_buff->pW == dst_buff->pR)
{
    return -1;
}
else
{
    *dat = dst_buff->buff[dst_buff->pR];
    dst_buff->pR = (dst_buff->pR+1)%RING_BUFF_SIZE; 更新pW位置
    return 0;
}

}
在这里插入图片描述
可以看出来,读取位置和写位置一直在互相追逐,当读位置追上写位置的时候,表示环形缓冲区数据为空。反过来则表示为满。

完整代码如下
#include <stdio.h>

#define RING_BUFF_SIZE 10

typedef struct {
volatile unsigned int pW;
volatile unsigned int pR;
volatile unsigned char buff[RING_BUFF_SIZE];
}RingBuff;

void RingBuffInitial(RingBuff *dst_buff)
{
dst_buff->pW = 0;
dst_buff->pR = 0;
}

void RingBuffWrite(RingBuff *dst_buff, unsigned char dat)
{

int i;
i = (dst_buff->pW + 1)%RING_BUFF_SIZE;
if(i != dst_buff->pR)
{
    dst_buff->buff[dst_buff->pW] = dat;
    dst_buff->pW = i;
}

}

int RingBuffRead(RingBuff *dst_buff, unsigned char *dat)
{

if(dst_buff->pW == dst_buff->pR)
{
    return -1;
}
else
{
    *dat = dst_buff->buff[dst_buff->pR];
    dst_buff->pR = (dst_buff->pR+1)%RING_BUFF_SIZE; 更新pW位置
    return 0;
}

}

int main()
{
int i=0;
int ret;
unsigned char read_dat;
RingBuff RecvBuff;
RingBuffInitial(&RecvBuff);

 printf("当前位置RecvBuff.pW = %d, RecvBuff.pR = %d\n",RecvBuff.pW,RecvBuff.pR);
for(i = 0; i < 5; i++)
{
    RingBuffWrite(&RecvBuff,'A'+i);
    printf("RecvBuff.pW = %d ,RecvBuff.pR = %d ,RecvBuff.buff[%d] = %c\n",\
           RecvBuff.pW,RecvBuff.pR,i,RecvBuff.buff[i]);
}
printf("当前位置RecvBuff.pW = %d, RecvBuff.pR = %d\n",RecvBuff.pW,RecvBuff.pR);
for(i = 0; i < 5; i++)
{
    ret = RingBuffRead(&RecvBuff,&read_dat);
    if(!ret)
        printf("read_dat = %c\n",read_dat);
    else
        printf("read err\n");
}
printf("当前位置RecvBuff.pW = %d, RecvBuff.pR = %d\n",RecvBuff.pW,RecvBuff.pR);
for(i = 0; i < 5; i++)
{
    ret = RingBuffRead(&RecvBuff,&read_dat);
    if(!ret)
        printf("read_dat = %c\n",read_dat);
    else
        printf("read err\n");
}
printf("当前位置RecvBuff.pW = %d, RecvBuff.pR = %d\n",RecvBuff.pW,RecvBuff.pR);
for(i = 5; i < 10; i++)
{
    RingBuffWrite(&RecvBuff,'A'+i);
    printf("RecvBuff.pW = %d ,RecvBuff.pR = %d ,RecvBuff.buff[%d] = %c\n",\
           RecvBuff.pW,RecvBuff.pR,i,RecvBuff.buff[i]);
}
printf("当前位置RecvBuff.pW = %d, RecvBuff.pR = %d\n",RecvBuff.pW,RecvBuff.pR);
    for(i = 0; i < 5; i++)
{
    ret = RingBuffRead(&RecvBuff,&read_dat);
    if(!ret)
        printf("read_dat = %c\n",read_dat);
    else
        printf("read err\n");
}
printf("当前位置RecvBuff.pW = %d, RecvBuff.pR = %d\n",RecvBuff.pW,RecvBuff.pR);
return 0;

}
在这里插入图片描述
原文连接

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1012021.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

冠达管理:央行降准0.25个百分点 释放流动性超5000亿

人民银行昨日发布消息称&#xff0c;为巩固经济上升向好根底&#xff0c;坚持活动性合理富余&#xff0c;决定于9月15日下调金融组织存款准备金率0.25个百分点&#xff08;不含已执行5%存款准备金率的金融组织&#xff09;。本次下调后&#xff0c;金融组织加权平均存款准备金率…

SwiftUI Swift iOS iPadOS 实现更改 App 图标

Xcode: 14.3.1 更改 App 图标 淘宝&#xff0c;支付宝&#xff0c;有道翻译有时候会随着运营活动去调整图标&#xff0c;比如 双 11。&#xff08;这个很简单&#xff0c;替换一下 AppIcon 就可以了&#xff09;Github App 提供了多套图标可以修改。&#xff08;需要配置 &…

誉天在线项目-UML状态图+泳道图

什么是UML UML&#xff08;Unified Modeling Language&#xff09;是一种用于软件系统建模的标准化语言。它提供了一组图形符号和规范&#xff0c;用于描述和设计软件系统的结构、行为和交互。 UML图形符号包括类图、用例图、时序图、活动图、组件图、部署图等&#xff0c;每…

原生微信小程序中进行 API 请求

原生微信小程序中进行 API 请求 当在原生微信小程序中进行 API 请求时&#xff0c;封装请求可以提高代码的可维护性和可扩展性。在本篇博客中&#xff0c;我们将一步步介绍如何进一步封装请求&#xff0c;并添加请求超时、拦截器和请求取消功能。 第一步&#xff1a;基本请求封…

生产设备上的静电该如何处理?

在工厂生产车间里有很多机械设备&#xff0c;在生产运作过程中&#xff0c;难免会产生大量静电&#xff0c;静电会产生许多危害。 例如&#xff0c;1、会使电子设备故障、误操作而引起的电磁干扰。 2、电子元件或集成电路的静电击穿; 3、高压静电放电引起触电; 4、静电放电引起…

一种新的图像去噪方式:图像修补+斑点检测的预处理

灵感来源于我之前写的一篇博客&#xff1a;图像处理&#xff1a;基于cv2.inpaint()图像修补。 这种方式可以有效的去除白色的噪点&#xff0c;这里我们需要一张噪点的图像&#xff0c;你可以用下面的代码随机生成一张噪点图片&#xff1a; import cv2 import numpy as np # i…

EDI经营许可证办理要求及流程全解!

我们正处在互联网的大时代&#xff0c;从事互联网行业又会想到电商&#xff0c;提到电商企业&#xff0c;大家会关注这个平台是否合法或是否靠谱&#xff0c;那除了对这个电商品牌的认知以外&#xff0c;还会关注其是否合法合规为用户提供货物购买交易服务&#xff0c;是否具备…

评价模型:层次分析法

1. 模型建立 1.1 建立层次结构模型 在深入分析实际问题的基础上&#xff0c;将有关的各个因素按照不同属性自上而下地分解成若干层次&#xff0c;同一层的诸因素从属于上一层的因素或对上层因素有影响&#xff0c;同时又支配下一层的因素或受到下层因素的作用。最上层为目标层…

day10常用API

1.API 1.1API概述 什么是API ​ API (Application Programming Interface) &#xff1a;应用程序编程接口 java中的API ​ 指的就是 JDK 中提供的各种功能的 Java类&#xff0c;这些类将底层的实现封装了起来&#xff0c;我们不需要关心这些类是如何实现的&#xff0c;只需要…

奶牛个体识别 奶牛身份识别

融合YOLOv5s与通道剪枝算法的奶牛轻量化个体识别方法 Light-weight recognition network for dairy cows based on the fusion of YOLOv5s and channel pruning algorithm 论文链接 知网链接 DOI链接 该文章讨论了奶牛花斑、光照条件、不同剪枝方法、不同剪枝率对准确率的影响…

【C语言】指针查漏补缺

【C语言】指针查漏补缺 预备知识一维整数数组字符数组字符常量数组字符串常量二维数组 预备知识 sizeof 是计算对象或者类型创建的对象所占内存空间的大小&#xff0c;单位是字节 sizeof 是操作符&#xff0c;不是函数 strlen 求字符串长度的&#xff0c;计算的是字符串中\0之…

向量的概念、向量组的概念

目录 向量的概念、向量组的概念 向量的基本运算 线性表出、线性相关、线性无关 向量的概念、向量组的概念 向量&#xff08;Vector&#xff09;是一个有次序的数所组成的数组&#xff0c;通常用来表示一个物理量或者一个对象在空间中的移动。向量可以表示位置、速度、力等物…

竞赛 基于机器视觉的手势检测和识别算法

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 基于深度学习的手势检测与识别算法 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f9ff; 更多资料, 项目分享&#xff1a; https://gitee.com/dancheng…

蓝牙核心规范(V5.4)12.2-深入详解之加密广播数据(Encrypted Advertising Data)

蓝牙篇之蓝牙核心规范(V5.4)深入详解汇总 1.知识回顾 1.1 带响应的周期广播 在上一节已经讲了。 1.2 广播结构体 蓝牙核心规范定义了广播数据(AD)结构。它是一个用于包含在蓝牙LE广告和扫描响应数据包中以及在蓝牙BR/EDR扩展查询响应(EIR)数据包中的一般容器。包含在A…

nvm 一个nodejs版本管理工具

nvm 一个nodejs版本管理工具 NVM是什么 nvm全英文也叫node.js version management&#xff0c;是一个nodejs的版本管理工具。nvm和n都是node.js版本管理工具&#xff0c;为了解决node.js各种版本存在不兼容现象可以通过它可以安装和切换不同版本的node.js NVM下载 可在点此在…

长城靶场溯源第四题

先统计访问的ip 直到第一个包过滤到202.1.1.2 很明显的一句话木马&#xff0c;就是他了&#xff0c;202.1.1.2 卡描述&#xff1a;2.服务器1.99的web服务器使用的CMS及其版本号&#xff08;请直接复制&#xff09; 继续查看同一个数据包&#xff0c;发现个奇奇怪怪的phpinf…

python flask框架接受axios发送的图片文件

文章目录 前端部分axios配置请求部分代码页面代码 后端代码结果 前端部分 axios配置 主要是一些基础的配置&#xff0c;这里可看可不看&#xff0c;主要的不是这里 import axios from axios; let baseURL /demo// 创建axios实例 const service axios.create({// axios中请…

山洪灾害预警方案(山洪预警解决方案的组成)

​ 随着气候变化的不断加剧&#xff0c;山洪灾害在许多地区成为了极具威胁性的自然灾害之一。为了帮助地方政府和居民更好地预防和应对山洪灾害&#xff0c;我们设计了一套基于星创易联的SR600工业路由器和DTU200的山洪灾害预警方案&#xff0c;并成功在某地区进行了部署。 案…

【Linux从入门到精通】线程 | 线程介绍线程控制

本篇文章主要对线程的概念和线程的控制进行了讲解。其中我们再次对进程概念理解。同时对比了进程和线程的区别。希望本篇文章会对你有所帮助。 文章目录 一、线程概念 1、1 什么是线程 1、2 再次理解进程概念 1、3 轻量级进程 二、进程控制 2、1 创建线程 pthread_create 2、2…

代码随想录算法训练营第49天|121. 买卖股票的最佳时机,买卖股票的最佳时机II

链接: 121. 买卖股票的最佳时机 链接: 122.买卖股票的最佳时机II 121. 买卖股票的最佳时机 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出…