串口开发之环形缓冲区

2023-05-16

01、简介

串口的基本应用,使用串口中断接收数据,串口中断发送回包(一般可以使用非中断形式发送回包,在数据接收不频繁的应用中。串口接收中断保证串口数据及时响应,使用非中断方式发送回包即可)。

串口接收数据长度位置,频率未知,不要求实时处理的场景。如果采用上述方案,接收一帧数据立即处理,那么在处理的时候来的数据包就“丢失”了。这个时候就需要缓冲队列来解决这个问题。

02、缓冲区

缓冲区看名字就知道,是缓冲数据用的。实现缓冲区最简单的办法时,定义多个数组,接收一包数据到数组A,就把接收数据的地址换成数组B,每个数据有个标记字节用于表示这个数组是否收到数据,收到数据是否处理完成。

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

①缓冲数据组数一定,且有多变量,代码结构不太清晰。

②接收数据长度可能大于数组大小,也可能小于数组大小。不灵活,需要接收数据很长时容易出错,且内存利用率低。

解决这个问题的好办法是:环形缓冲区。

环形缓冲区就是一个带“头指针”和“尾指针”的数组。“头指针”指向环形缓冲区中可读的数据,“尾指针”指向环形缓冲区中可写的缓冲空间。通过移动“头指针”和“尾指针”就可以实现缓冲区的数据读取和写入。在通常情况下,应用程序读取环形缓冲区的数据仅仅会影响“头指针”,而串口接收数据仅仅会影响“尾指针”。当串口接收到新的数组,则将数组保存到环形缓冲区中,同时将“尾指针”加1,以保存下一个数据;应用程序在读取数据时,“头指针”加1,以读取下一个数据。当“尾指针”超过数组大小,则“尾指针”重新指向数组的首元素,从而形成“环形缓冲区”!,有效数据区域在“头指针”和“尾指针”之间。如下图

如上面说的,环形缓冲区其实就是一个数组,将其“剪开”,然后“拉直”后如下图

环形缓冲区的特性

1、先进新出。

2、当缓冲区被使用完,且又有新的数据需要存储时,丢掉历史最久的数据,保存最新数据。

03、代码实现

环形缓冲区的实现很简单,只需要简单的几个接口即可。

首先需要创建一个环形缓冲区

#define RINGBUFF_LEN (500) //定义最大接收字节数 500

#define RINGBUFF_OK 1

#define RINGBUFF_ERR 0

typedef struct

{

uint16_t Head;

uint16_t Tail;

uint16_t Lenght;

uint8_t Ring_data[RINGBUFF_LEN];

}RingBuff_t;

RingBuff_t ringBuff;//创建一个ringBuff的缓冲区

当我们发现环形缓冲区被“冲爆”时,也就是缓冲区满了,但是还有待缓冲的数据时,只需要修改RINGBUFF_LEN的宏定义,增大缓冲区间即可。

环形缓冲区的初始化

/**

* @brief RingBuff_Init

* @param void

* @return void

* @note 初始化环形缓冲区

*/

void RingBuff_Init(void)

{

//初始化相关信息

ringBuff.Head = 0;

ringBuff.Tail = 0;

ringBuff.Lenght = 0;

}

主要是将环形缓冲区的头,尾和长度清零,表示没有任何数据存入。

环形缓冲区的写入

/**

* @brief Write_RingBuff

* @param uint8_t data

* @return FLASE:环形缓冲区已满,写入失败;TRUE:写入成功

* @note 往环形缓冲区写入uint8_t类型的数据

*/

uint8_t Write_RingBuff(uint8_t data)

{

if(ringBuff.Lenght >= RINGBUFF_LEN) //判断缓冲区是否已满

{

return RINGBUFF_ERR;

}

ringBuff.Ring_data[ringBuff.Tail]=data;

ringBuff.Tail = (ringBuff.Tail+1)%RINGBUFF_LEN;//防止越界非法访问

ringBuff.Lenght++;

return RINGBUFF_OK;

}

这个接口是写入一个字节到环形缓冲区。这里注意:大家可以根据自己的实际应用修改为一次缓冲多个字节。并且这个做了缓冲区满时报错且防止非法越界的处理,大家可以自行修改为缓冲区满时覆盖最早的数据。

环形缓冲区的读取

/**

* @brief Read_RingBuff

* @param uint8_t *rData,用于保存读取的数据

* @return FLASE:环形缓冲区没有数据,读取失败;TRUE:读取成功

* @note 从环形缓冲区读取一个u8类型的数据

*/

uint8_t Read_RingBuff(uint8_t *rData)

{

if(ringBuff.Lenght == 0)//判断非空

{

return RINGBUFF_ERR;

}

*rData = ringBuff.Ring_data[ringBuff.Head];//先进先出FIFO,从缓冲区头出

ringBuff.Head = (ringBuff.Head+1)%RINGBUFF_LEN;//防止越界非法访问

ringBuff.Lenght--;

return RINGBUFF_OK;

}

读取的话也很简单,同样是读取一个字节,大家可以自行修改为读取多个字节。

04、验证

光说不练假把式,下面我们就来验证上面的代码可行性。

串口中断函数中缓冲数据

void USART1_IRQHandler(void)

{

if(USART_GetFlagStatus(USART1, USART_FLAG_RXNE))

{

Write_RingBuff(USART_ReceiveData(USART1));

USART_ClearFlag(USART1, USART_FLAG_RXNE);

}

}

在主循环中,读取缓冲区的数据,然后发送出去,因为是简单的demo,添加了延时模拟CPU处理其他任务。

while (1)

{

if(Read_RingBuff(&data)) //从环形缓冲区中读取数据

{

USART_SendData(USART1, data);

}

SysCtlDelay(1*(SystemCoreClock/3000));

}

验证,间隔100ms发送数据。

结果显示没有出现丢包问题。如果你的应用场景串口通信速率快,数据量大或处理速度慢导致丢包,建议增大RINGBUFF_LEN的宏定义,增大缓冲区间即可。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

串口开发之环形缓冲区 的相关文章

  • 使用Python+Scrapy爬取并保存QQ群空间帖子

    首先声明 xff0c 在Python和爬虫这方面 xff0c 我是业余的那一卦 xff0c 只是平时玩一玩 xff0c 不能当真的 xff0c 请各位大佬轻拍 虽然爬虫与传统意义上的大数据技术不属于同一类 xff0c 但大概也只能放在大数据
  • SLAM 多点导航功能包发布

    SLAM 多点导航功能包 navi multi goals pub rviz plugin 描述 xff1a 该功能包为SLAM 建图导航提供可发布多个目标点任务的导航方式 要求 必须基于 Autolabor SLAM导航使用 一 安装与配
  • 步进电机学习笔记

    扩充的理论知识 xff1a 步进电机的细分技术实质上一种电子阻尼技术 xff0c 其主要目的是减弱或消除低频振动 不同厂家的细分驱动器精度可能差别很大 xff0c 还取决于细分电流控制精度等因素 细分数越大 xff0c 精度越难控制 xff
  • 错误:AttributeError: module ‘cv2.cv2‘ has no attribute ‘TrackerCSRT_create‘ 解决

    OpenCV目标跟踪运行出错 xff1a AttributeError module cv2 cv2 has no attribute 39 TrackerCSRT create C 问题 xff1a 直接上错误代码 xff1a 上我的代码
  • STM32系列(HAL库) ——使用串口打印的3种方式

    一 前期准备 1 硬件 xff1a STM32C8T6最小系统板USB TTL串口模块ST Link下载器 2 软件 xff1a keil5 IDEcubeMX 二 cubeMX配置 1 配置RCC 选择外部时钟源 2 配置SYS Seri
  • C#多线程编程:线程基础

    原文链接 xff1a https www cnblogs com wyt007 p 9486752 html 创建线程 static void Main string args Thread t 61 new Thread PrintNum
  • ROS 控制Innfos机械臂简单例子

    include lt ros ros h gt include lt image transport image transport h gt include lt sensor msgs image encodings h gt incl
  • 使用CMake和Visual Studio搭建工程并引入OpenCV库

    前言 nbsp nbsp nbsp nbsp nbsp nbsp nbsp nbsp 在之前的Windows平台下OpenCV的编译与安装 Mega Li的博客 CSDN博客 nbsp 中介绍了Windows平台中使用CMake编译Open
  • UART通信中流控RTS和CTS的理解

    一 流控 xff0c 顾名思义就是流量控制的意思 目的是协调收发双方 xff0c 使数据不会丢失 如果UART只有RX TX两个信号 xff0c 要流控的话只能是软流控 xff1b 如果有RX xff0c TX xff0c CTS xff0
  • JVM虚拟机栈

    虚拟机栈 每个线程在创建时都会创建一个虚拟机栈 xff0c 其内部保存一个个栈帧 xff0c 对应一次次java方法的调用 xff08 线程私有 xff09 生命周期与线程一致 作用 xff1a 主管java线程的运行 xff0c 保存局部
  • C++之串口通讯

    C 43 43 串口操作 简介代码头文件源码文件 示例创建两个虚拟串口用串口调试助手连接COM2来接数据编写测试代码发送数据结果 总结 简介 串行接口简称串口 xff0c 也称串行通信接口或串行通讯接口 xff08 通常指COM接口 xff
  • 用keil写程序时出现“C(162): error C249: 'DATA': SEGMENT TOO LARGE“的错误

    如果定义的数组不用更改就用 uchar code XX 10 61 根据数据的用处 xff0c 可以有以下几种选择 xff1a data xff1a 直接寻址 的片内RAM区低128B xff08 00H 7FH xff09 bdata x
  • ROS 与 Box Turtle、C Turtle、Indigo Igloo 、Jade Turtle 、Kinetic Kame 、Melodic Morenia、Noetic Ninjemys关系

    如果没有错的话相当于这个些都是ros的版本 xff0c 就是不同时期叫的名字不一样 xff0c 用于区别不同的版本 因为也是初学者 xff0c 都还没入门 xff0c 也是网上找的资料 xff0c 并根据自己的理解写的 xff0c 如果有错
  • C语言——VS编译器下程序运行结果闪退解决方法

    C语言 VS编译器下程序运行结果闪退解决方法 学习C语言的过程中可能会遇到这样的问题 xff0c 程序调试的时候没有错误 xff0c 可是在运行结果的时候会发现程序结果闪退 xff0c 导致看不到结果 在此 xff0c 本文总结对比了几种有
  • Gazebo 加载xacro文件和URDF文件的方式

    版权声明 xff1a lt 本博客所有内容均为自己在学习工作中的总结 摘录等 转载请注明出处 如有侵权请联系删除 gt https blog csdn net xuehuafeiwu123 article details 71108959
  • Gazebo显示加载xacro模型文件---改变模型的颜色注意事项

    在xacro文件中 xff0c 有下列语句是修改模型颜色的 xff1a 例 xff1a lt link name 61 34 base link 34 gt lt visual gt lt geometry gt lt box size 6
  • Gazebo中sdf文件和urdf和xacro文件的区别

    sdf文件 urdf文件和xacro文件都是模型文件 xacro文件是urdf文件的改进版 xff0c urdf文件只能在rviz等中显示 xff0c 不能在仿真器中显示出来 xacro文件可以在gazebo仿真器中显示出来 xff0c 相

随机推荐

  • Gazebo的xacro文件添加各种plugins

    官网地址 xff1a http gazebosim org tutorials tut 61 ros gzplugins Tutorial Using Gazebo plugins with ROS Gazebo plugins give
  • ROS中spawn_model方式加载xacro文件,设置模型的位置(xyz,rpy)

    例如加载turtlebot机器人launch文件如下 xff1a 在gazebo仿真中最后都是通过这种方式加载xacro文件的 lt launch gt lt arg name 61 34 base 34 gt lt arg name 61
  • BT1120

    BT1120是高清晰度电视 HDTV 演播室信号数字接口 图像数据是怎么用二进制数据组织在一起的呢 xff1f 个人理解 xff1a 在BT1120标准中说明的图像数据指的是图像的有效尺寸的数据 因为我们看到编码信号包括图像数据和图像基准码
  • 2021-10-22 常用的串口通讯协议

    串口通讯是什么 学术解释是 xff0c 通过总线在一个时间点连续发送一位数据的方法 如同弓箭手频繁射出弓箭一般 xff0c 嗖 嗖 嗖 串口通讯协议是什么 说的大白话一点 xff0c 就是串口通信时所使用的协议传输方式 串口通讯协议有几种呢
  • curl 命令详解

    curl 是一种命令行工具 xff0c 作用是发出网络请求 xff0c 然后获取数据 xff0c 显示在 34 标准输出 34 xff08 stdout xff09 上面 它支持多种协议 xff0c 下面列举其常用功能 一 查看网页源码 直
  • RS485/云台控制(PTZ)学习文档

    RS485 云台控制 xff08 PTZ xff09 学习文档 zxf 一 项目任务 xff1a 在linux环境下通过RS485串口实现对云台镜头的各种控制 xff08 包括摄像头的打开 xff0c 关闭 xff0c 各个方向的运动及运动
  • 为何某些公司不允许使用C++STL

    点击蓝字 关注我们 最初开始禁用 C 43 43 STL xff0c 是因为早期项目编码实践中留下的惯例 xff0c 被后来的程序员继承下来 老项目中这种选择尤其地多 不过如果有人将其上升到公司行为在不同项目中全面禁用 STL xff0c
  • C++vector用法总结

    点击蓝字 关注我们 来源自网络 xff0c 侵删 一 vector 1 vector 说明 1 xff09 vector是C 43 43 标准模板库中的部分内容 xff0c 它是一个多功能的 xff0c 能够操作多种数据结构和算法的模板类和
  • halcon中的Pose

    Pose 姿态描述的是一个刚性的3D转换 xff0c 即 xff0c 一种由任意平移和旋转组成的变换 在Halcon中 xff0c 一个pose是具有7个参数的元组 xff1a 3个参数描述平移 xff08 TransX TransY Tr
  • halcon中阈值分割算子用法

    1 threshold Image Region MinGray MaxGray xff1a 通过给定的阈值区间对图像进行分割 效果图 xff1a read image Audi2 39 audi2 39 fill interlace Au
  • HALCON guided_filter导向滤波算子分析

    1 guided filter Image ImageGuide ImageGuided Radius Amplitude 可应用在图像增强 xff0c HDR压缩 图像抠图及图像去雾等场景 参数 xff1a Radius xff1a 滤光
  • halcon edges_image算子分析

    edges image Image ImaAmp ImaDir Filter Alpha NMS Low High xff1a 使用Deriche Lanser Shen或者Canny 滤波器进行边缘提取 参数 xff1a Image xf
  • C# NModbus的主从站开发以及Modbus Slave、Modbus Poll工具的使用

    NModbus的主站开发 1 开发环境要求 xff1a PC端作为主站 xff0c 控制器作为从站 2 PC端初始化代码 xff1a serialPort 61 new SerialPort serialPort PortName 61 3
  • OpenCVSharp Mat.Set<T>修改像素颜色

    笔记 xff1a Mat Set lt T gt 方法修改图像中的颜色 xff0c T的类型不能是Scalar 应为Vec3b xff0c 否则颜色修改失败 C 代码 xff1a Mat labs 61 new Mat int counts
  • VSCode idea 配置xml文件的dtd约束文件

    如上图配置XML文件的智能提示功能通过dtd文件 xff1a 1 通过VSCode 的扩展功能下载XML插件 xff08 注意 xff1a 插件内是包含dtd文件配置功能 xff09 配置方式 xff1a 1 DOCTYPE xff1a l
  • 关于0xAA和0x55

    许多串口通讯中测试或握手信号使用AA或55这两个特殊的十六进制数 xff0c 在许多PIC内部的 EEPROM 改写也使用这两个数作为敲门砖 xff0c 初学者可能不解何为 xff0c 其实如果将这两个数展开成二进制就可明白为什么 xff1
  • APS .Net MVC 之APIController与Controller的区别

    APIControllerController开发模式WebAPIMVC命名空间System Web HttpSystem Web Mvc返回方式json text或者xml texthtml textaction的默认请求方式postpo
  • DBeaver连接informix数据库乱码

    在工具栏选择数据库 驱动管理 informix编辑 xff0c 示例URL中添加NEWCODESET 61 utf8 8859 1 819 CLIENT LOCALE 61 en US utf8 DB LOCALE 61 en US 885
  • c语言——http编程

    HTTP协议简介 超文本传输协议是一种用于分布式 协作式和超媒体信息系统的应用层协议 HTTP是一个客户端终端 xff08 用户 xff09 和服务器端 xff08 网站 xff09 请求和应答的标准 xff08 一般基于TCP xff09
  • 串口开发之环形缓冲区

    01 简介 串口的基本应用 xff0c 使用串口中断接收数据 xff0c 串口中断发送回包 xff08 一般可以使用非中断形式发送回包 xff0c 在数据接收不频繁的应用中 串口接收中断保证串口数据及时响应 xff0c 使用非中断方式发送回