转载自微信公众号“玩转单片机”,感谢原作者“杰杰”。

队列的概念

在此之前,我们来回顾一下队列的基本概念:队列 (Queue):是一种先进先出(First In First Out ,简称 FIFO)的线性表,只允许在一端插入(入队),在另一端进行删除(出队)。

队列的特点

类似售票排队窗口,先到的人看到能先买到票,然后先走,后来的人只能后买到票

队列的常见两种形式

在计算机中,每个信息都是存储在存储单元中的,比喻一下吧,上图的一些小正方形格子就是一个个存储单元,你可以理解为常见的数组,存放我们一个个的信息。

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

它的队列就是一个环,它避免了普通队列的缺点,就是有点难理解而已,其实它就是一个队列,一样有队列头,队列尾,一样是先进先出(FIFO)。我们采用顺时针的方式来对队列进行排序。

队列头 (Head) :允许进行删除的一端称为队首。

队列尾 (Tail) :允许进行插入的一端称为队尾。

环形队列的实现:在计算机中,也是没有环形的内存的,只不过是我们将顺序的内存处理过,让某一段内存形成环形,使他们首尾相连,简单来说,这其实就是一个数组,只不过有两个指针,一个指向列队头,一个指向列队尾。指向列队头的指针(Head)是缓冲区可读的数据,指向列队尾的指针(Tail)是缓冲区可写的数据,通过移动这两个指针(Head) &(Tail)即可对缓冲区的数据进行读写操作了,直到缓冲区已满(头尾相接),将数据处理完,可以释放掉数据,又可以进行存储新的数据了。

实现的原理:初始化的时候,列队头与列队尾都指向0,当有数据存储的时候,数据存储在‘0’的地址空间,列队尾指向下一个可以存储数据的地方‘1’,再有数据来的时候,存储数据到地址‘1’,然后队列尾指向下一个地址‘2’。当数据要进行处理的时候,肯定是先处理‘0’空间的数据,也就是列队头的数据,处理完了数据,‘0’地址空间的数据进行释放掉,列队头指向下一个可以处理数据的地址‘1’。从而实现整个环形缓冲区的数据读写。

看图,队列头就是指向已经存储的数据,并且这个数据是待处理的。下一个CPU处理的数据就是1;而队列尾则指向可以进行写数据的地址。当1处理了,就会把1释放掉。并且把队列头指向2。当写入了一个数据6,那么队列尾的指针就会指向下一个可以写的地址。

如果你懂了环形队列,那就跟着歌曲来一步步用代码实现吧:

从队列到串口缓冲区的实现

串口环形缓冲区收发:在很多入门级教程中,我们知道的串口收发都是:接收一个数据,触发中断,然后把数据发回来。这种处理方式是没有缓冲的,当数量太大的时候,亦或者当数据接收太快的时候,我们来不及处理已经收到的数据,那么,当再次收到数据的时候,就会将之前还未处理的数据覆盖掉。那么就会出现丢包的现象了,对我们的程序是一个致命的创伤。

那么如何避免这种情况的发生呢,很显然,上面说的一些队列的特性很容易帮我们实现我们需要的情况。将接受的数据缓存一下,让处理的速度有些许缓冲,使得处理的速度赶得上接收的速度,上面又已经分析了普通队列与环形队列的优劣了,那么我们肯定是用环形队列来进行实现了。下面就是代码的实现:

 //①定义一个结构体:

 typedef struct
{
u16 Head;
u16 Tail;
u16 Lenght;
u8 Ring_Buff[RINGBUFF_LEN];
} RingBuff_t; RingBuff_t ringBuff;//创建一个ringBuff的缓冲区 //②初始化结构体相关信息:使得我们的环形缓冲区是头尾相连的,
//并且里面没有数据,也就是空的队列。 /**
* @brief RingBuff_Init
* @param void
* @return void
* @author 杰杰
* @date 2018
* @version v1.0
* @note 初始化环形缓冲区
*/
void RingBuff_Init(void)
{
//初始化相关信息
ringBuff.Head = ;
ringBuff.Tail = ;
ringBuff.Lenght = ;
}
//初始化效果如下: //写入环形缓冲区的代码实现: /**
* @brief Write_RingBuff
* @param u8 data
* @return FLASE:环形缓冲区已满,写入失败; TRUE:写入成功
* @author 杰杰
* @date 2018
* @version v1.0
* @note 往环形缓冲区写入u8类型的数据
*/
u8 Write_RingBuff(u8 data)
{
if(ringBuff.Lenght >= RINGBUFF_LEN) //判断缓冲区是否已满
{
return FLASE;
} ringBuff.Ring_Buff[ringBuff.Tail]=data; // ringBuff.Tail++; ringBuff.Tail = ( ringBuff.Tail + ) % RINGBUFF_LEN;//防止越界非法访问
ringBuff.Lenght++; return TRUE;
} //读取缓冲区的数据的代码实现: /**
* @brief Read_RingBuff
* @param u8 *rData,用于保存读取的数据
* @return FLASE:环形缓冲区没有数据,读取失败;TRUE:读取成功
* @author 杰杰
* @date 2018
* @version v1.0
* @note 从环形缓冲区读取一个u8类型的数据
*/
u8 Read_RingBuff(u8 *rData)
{
if(ringBuff.Lenght == )//判断非空
{
return FLASE;
} *rData = ringBuff.Ring_Buff[ringBuff.Head];//先进先出FIFO,从缓冲区头出 // ringBuff.Head++;
ringBuff.Head = (ringBuff.Head + ) % RINGBUFF_LEN;//防止越界非法访问
ringBuff.Lenght--; return TRUE;
} /* 对于读写操作需要注意的地方有两个:
1:判断队列是否为空或者满,如果空的话,是不允许读取数据的,返回FLASE。如果是满的话,也是不允许写入数据的,避免将已有数据覆盖掉。那么如果处理的速度赶不上接收的速度,可以适当增大缓冲区的大小,用空间换取时间。
2:防止指针越界非法访问,程序有说明,需要使用者对整个缓冲区的大小进行把握。 那么在串口接收函数中: */ void USART1_IRQHandler(void)
{
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中断
{
USART_ClearITPendingBit(USART1,USART_IT_RXNE); //清楚标志位
Write_RingBuff(USART_ReceiveData(USART1)); //读取接收到的数据
}
} /* 测试效果 测试数据没有发生丢包现象 补充
对于现在的阶段,杰杰我本人写代码也慢慢学会规范了。所有的代码片段均使用了可读性很强的,还有可移植性也很强的。我使用了宏定义来决定是否开启环形缓冲区的方式来收发数据,移植到大家的代码并不会有其他副作用,只需要开启宏定义即可使用了。 */ #define USER_RINGBUFF 1 //使用环形缓冲区形式接收数据
#if USER_RINGBUFF
/**如果使用环形缓冲形式接收串口数据***/
#define RINGBUFF_LEN 200 //定义最大接收字节数 200
#define FLASE 1
#define TRUE 0
void RingBuff_Init(void);
u8 Write_RingBuff(u8 data);
u8 Read_RingBuff(u8 *rData);
#endif //当然,我们完全可以用空闲中断与DMA传输,效率更高,但是某些单片机没有空闲中断与DMA,那么这种环形缓冲区的作用就很大了,并且移植简便。

STM32进阶之串口环形缓冲区实现(转载)的更多相关文章

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

    队列的概念 在此之前,我们来回顾一下队列的基本概念: 队列 (Queue):是一种先进先出(First In First Out ,简称 FIFO)的线性表,只允许在一端插入(入队),在另一端进行删除 ...

  2. STM32 串口功能 库函数 详解和DMA 串口高级运用(转载)

    数据传输时要从支持那些相关的标准?传输的速度?什么时候开始?什么时候结束?传输的内容?怎样防止通信出错?数据量大的时候怎么弄?硬件怎么连接出发,当然对于stm32还要熟悉库函数的功能 具起来rs232 ...

  3. RT-Thread下的串口驱动程序分析【转载】

    编写本文稿的目的,在于通过分析stm32平台上的串口中断源码,学习 RTT中如何编写中断处理程序 如何编写RTT设备驱动接口代码 了解串行设备的常见处理机制 先以RTT官方源码中的STM32 BSP包 ...

  4. 嵌入式框架Zorb Framework搭建二:环形缓冲区的实现

    我是卓波,我是一名嵌入式工程师,我万万没想到我会在这里跟大家吹牛皮. 嵌入式框架Zorb Framework搭建过程 嵌入式框架Zorb Framework搭建一:嵌入式环境搭建.调试输出和建立时间系 ...

  5. 环形缓冲区-模仿linux kfifo【转】

    转自:https://blog.csdn.net/vertor11/article/details/53741681 struct kfifo{ uint8_t *buffer; uint32_t i ...

  6. C#环形缓冲区(队列)完全实现

    公司项目中经常设计到串口通信,TCP通信,而且大多都是实时的大数据的传输,然后大家都知道协议通讯肯定涉及到什么,封包.拆包.粘包.校验--什么鬼的概念一大堆,说简单点儿就是要一个高效率可复用的缓存区. ...

  7. 正确理解hadoop 2.x 的环形缓冲区: (一) MR环形缓冲区的结构

    转载:http://blog.csdn.net/HADOOP_83425744/article/details/49560583 http://bigdatadecode.club/MapReduce ...

  8. linux device driver —— 环形缓冲区的实现

    还是没有接触到怎么控制硬件,但是在书里看到了一个挺巧妙的环形缓冲区实现. 此环形缓冲区实际为一个大小为bufsize的一维数组,有一个rp的读指针,一个wp的写指针. 在数据满时写进程会等待读进程读取 ...

  9. STM32 USB虚拟串口(转)

    源:STM32 USB虚拟串口 串口调试在项目中被使用越来越多,串口资源的紧缺也变的尤为突出.很多本本人群,更是深有体会,不准备一个USB转串口工具就没办法进行开发.本章节来简单概述STM32低端芯片 ...

随机推荐

  1. BIEE入门(四)展现层

    BIEE里最终面向最终用户(业务界面使用者的)叫做BIEE的Presentation Layer也即展现层,展现层的定义将是最终用户Web报表开发界面里能够看见的完全一样的样子,所以展现层一般将是以最 ...

  2. SQL转Linq工具的使用——Linqer

    官方下载网站:http://www.sqltolinq.com/ 本文介绍版本为Linqer 4.5.7 第一步:下载下来,解压,双击安装.exe文件,运行界面如下. 第二步:建立与数据库的连接 点击 ...

  3. 记录项目代码迁移后,UI测试框架的搭建(配置文件的修改、测试脚本试运行)

    前文:记录一次项目代码迁移过程 上文代码迁移的目的就是为了新增vue脚手架自带的UI测试框架,工具有了,就需要实践运行在项目中了(修改配置文件.编写测试脚本等). 一.单元测试 测试框架 karma ...

  4. 常用的shell语句 【awk】去重,排列

    目的:从日志access.log中,筛选出IP来,并统计每个IP出现的次数,然后显示出来. 因为:awk = 扒IP  shot = 排序  uniq =  去重 所以:awk '{print $1} ...

  5. strtoul (将字符串转换成无符号长整型数)

    strtoul strtoul (将字符串转换成无符号长整型数) 相关函数 atof,atoi,atol,strtod,strtol 表头文件 #include<stdlib.h> 定义函 ...

  6. UVA - 11488 前缀

    题目链接:https://vjudge.net/contest/166647#problem/A 题意: 从一些字符串集合里面挑一子集,然后公共前缀长度*字符串个数最大: 分析: 将这些字符串放到一个 ...

  7. mybatis学习记录三——SqlMapConfig.xml相关参数详解

      5       SqlMapConfig.xml mybatis的全局配置文件SqlMapConfig.xml,配置内容如下: properties(属性) settings(全局配置参数) ty ...

  8. json sort

    Array.sort()方法是用来对数组项进行排序的 ,默认情况下是进行升序排列.sort() 方法可以接受一个 方法为参数. sort()排序时每次比较两个数组项都回执行这个参数,并把两个比较的数组 ...

  9. 【luogu P1807 最长路_NOI导刊2010提高(07)】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1807 求最大路?就是把权值取相反数跑最短路. #include <cstdio> #includ ...

  10. 【luogu P1821 [USACO07FEB]银牛派对Silver Cow Party】 题解

    题目链接:https://www.luogu.org/problemnew/show/P1821 反向多存一个图,暴力跑两遍 #include <cstdio> #include < ...