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

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

3天内不再提示

串口的循环队列是什么?

Q4MP_gh_c472c21 来源:单片机爱好者 作者:单片机爱好者 2022-05-12 14:57 次阅读

先说串口,这个应该都知道吧(不知道的童鞋,先把基本功学好),大部分单片机或者处理器都会带一个或者多个串口,方便进行数据的通信

那么,串口的循环队列是什么?这里以STM32的串口为例,进行解释说明。

假设串口一次只发一个数据,这倒是简单了,每次只对这一个数据进行判断,然后处理相关指令。但现实不会一直都这么美好,很多时候你收到的可能是一大串数据,你要先小心翼翼的把它们存好,然后再依次判断这里面有哪些指令要处理。

假设你定义了一个30个元素的数组a[30],每次串口收到数据都往里面存,存的时候地址加一。这个操作很简单吧,应该是都会的。

但是取的时候怎么取?你收到的指令可能是2个数据,也可能是3个数据,几种长度不一样的指令混在一起。

一次从数组里读出几个数据?怎么快速腾出已读数据的位置?还是一次都读完,然后整个数组清零?

先说一次读完,然后清零的这个方法为什么不行。

1、读的时候,里面的数据不一定是完整的。有可能某组数据刚接收到一半儿。

2、读完以后,清零之前,如果进来新的数据怎么办?

所以,比较稳妥的方法是,一次只读一个数据,读一次,清除该数据所占的位置。所以这需要一个变量,来记录数据头在这个数组中的位置。

第二,当有新数据来的时候,要知道它能放在哪,所以要有一个变量,来记录数据尾在哪。

第三,如果有必要,你可以定义一个变量来记录数据长度,存入的时候加一,取出的时候减一。

第四,也是比较重要的,如果数据尾已经是a[29]了,下一个数据放哪?整个数组都清掉?NO,假设此时a[0]~a[10]已经被取出了,数据头变成了a[11]。那么新的数据尾变成a[0],即当数据尾大于等于30的时候,变成0.

如此一来,相当于把这个数组的头和尾连了起来,成了一个封闭的环,这种处理方式,就叫做串口的循环队列。只要确保数组够大,处理速度够快,那么头和尾就不会撞上。当然,程序上也要对这种意外情况做一个处理。以下图片来自网络

2f4b19b4-d1b6-11ec-bce3-dac502259ad0.png

下面是代码,核心的部分都在这,复制粘贴一下,基本就可以了。

首先是定义一个结构体,关于数据头、数据尾、数组的:

typedef struct

{

u16 Head;

u16 Tail;

u16 Length;

u8 Rsv_DAT[50];

}ringbuff_t;

ringbuff_t Ringbuff;

然后是结构体初始化:

void ringbuff_init(void)

{

Ringbuff.Head = 0;

Ringbuff.Tail = 0;

Ringbuff.Length = 0;

}

然后是存入数据的操作,把这个函数放进串口接收中断就行:

u8 write_ringbuff(u8 data)

{

if(Ringbuff.Length >= 50)

{

return FALSE;

}

else

{

Ringbuff.Rsv_DAT[Ringbuff.Tail] = data;

Ringbuff.Tail = (Ringbuff.Tail + 1)% 50;//防止越界

Ringbuff.Length++;

return TRUE;

}

}

然后是取出数据的操作:

u8 read_ringbuff(u8 *rdata)

{

if(Ringbuff.Length == 0)

{

return FALSE;

}

else

{

*rdata = Ringbuff.Rsv_DAT[Ringbuff.Head];

Ringbuff.Rsv_DAT[Ringbuff.Head] = 0;

Ringbuff.Head = (Ringbuff.Head + 1)%50;

Ringbuff.Length--;

return TRUE;

}

}

然后就能用了,这是写操作:

write_ringbuff(USART_ReceiveData(USART1));

这是读操作:

read_ringbuff(&uart_buf[0]);

读操作的函数里,还可以增加一个操作,就是读出以后,把该位置数据清零,这个看个人需要。

以上,就是串口循环队列的一个简介,如果有写的不好的,欢迎留言指正。当然,方法千千万,不一定只能用这种。最后,借用流浪地球的一句经典台词作为结尾:

方法千万条,稳定第一条。

代码不规范,码农两行泪。

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

    关注

    2239

    文章

    10671

    浏览量

    348732
  • 串口
    +关注

    关注

    14

    文章

    1483

    浏览量

    74506
  • 代码
    +关注

    关注

    30

    文章

    4555

    浏览量

    66750

原文标题:基于STM32的串口循环队列

文章出处:【微信号:gh_c472c2199c88,微信公众号:嵌入式微处理器】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    裸机中环形队列与RTOS中消息队列有何区别呢?

    “环形队列”和“消息队列”在嵌入式领域有应用非常广泛,相信有经验的嵌入式软件工程师对它们都不陌生。
    的头像 发表于 01-26 09:38 245次阅读
    裸机中环形<b class='flag-5'>队列</b>与RTOS中消息<b class='flag-5'>队列</b>有何区别呢?

    嵌入式开发C语言工具代码示例讲解

    循环队列是一种高效的数据结构,适用于缓冲区和数据流应用,例如串口通信接收缓冲。
    发表于 01-21 10:05 278次阅读

    聊一聊消息队列技术选型的7种消息场景

    我们在做消息队列的技术选型时,往往会结合业务场景进行考虑。今天来聊一聊消息队列可能会用到的 7 种消息场景。
    的头像 发表于 12-09 17:50 920次阅读
    聊一聊消息<b class='flag-5'>队列</b>技术选型的7种消息场景

    RT-Thread Nano入门:串口接收与消息队列

    本文主要介绍怎么用RT-Thread Nano的消息队列方式实现串口数据接收,结合串口接收中断和空闲中断,接收上位机发来的一帧数据。
    的头像 发表于 11-22 11:07 1010次阅读
    RT-Thread Nano入门:<b class='flag-5'>串口</b>接收与消息<b class='flag-5'>队列</b>

    无锁队列解决的问题

    为什么需要无锁队列 无锁队列解决了什么问题?无锁队列解决了锁引起的问题。 cache失效 当CPU要访问主存的时候,这些数据首先要被copy到cache中,因为这些数据在不久的将来可能又会被处理器
    的头像 发表于 11-10 15:33 264次阅读
    无锁<b class='flag-5'>队列</b>解决的问题

    消息队列的发展历史

    上一篇我们用一个秒杀案例探讨了我们为什么需要消息队列。今天我们来回顾一下消息队列的发展历史。
    的头像 发表于 10-30 10:49 399次阅读
    消息<b class='flag-5'>队列</b>的发展历史

    两个栈实现一个队列方法

    栈和队列是比较基础的数据结构。无论在工作中,还是在面试中,栈和队列都用的比较多。在计算机的世界,你会看到队列和栈,无处不在。 栈:一个先进后出的数据结构 队列:一个先进先出的数据结构
    的头像 发表于 10-08 15:54 579次阅读

    基于STM32的串口环形队列IAP调试

    基于STM32的串口环形队列IAP调试心得
    的头像 发表于 09-18 15:33 847次阅读
    基于STM32的<b class='flag-5'>串口</b>环形<b class='flag-5'>队列</b>IAP调试

    双端队列和C++ std::deque的用法说明

    双端队列实际上是队列的一种变形,队列要求只能在队尾添加元素,在队头删除元素,而双端队列在队头和队尾都可以进行添加和删除元素的操作。
    的头像 发表于 07-18 17:43 400次阅读
    双端<b class='flag-5'>队列</b>和C++ std::deque的用法说明

    FreeRTOS消息队列结构体

    有一个结构体用于描述队列,叫做 Queue_t,这个结构体在文件 queue.c 中定义。 3、队列创建 在使用队列之前必须先创建队列,有两种创建
    的头像 发表于 07-06 17:03 677次阅读
    FreeRTOS消息<b class='flag-5'>队列</b>结构体

    FreeRTOS消息队列介绍

    队列是为了任务与任务、任务与中断之间的通信而准备的,可以在任务与任务、任务与中断之间传递消息,队列中可以存储有限的、大小固定的数据项目。任务与任务、任务与中断之间要交流的数据保存在队列中,叫做
    的头像 发表于 07-06 16:58 484次阅读
    FreeRTOS消息<b class='flag-5'>队列</b>介绍

    循环队列在网络摄像头项目中处理多则消息的运用

    此文主要记录IPC项目中如何运用循环队列来处理多则消息的,网络摄像头下文简称IPC。
    的头像 发表于 06-25 14:41 284次阅读
    <b class='flag-5'>循环</b><b class='flag-5'>队列</b>在网络摄像头项目中处理多则消息的运用

    RTOS消息队列的应用

    基于RTOS的应用中,通常使用队列机制实现任务间的数据交互,一个应用程序可以有任意数量的消息队列,每个消息队列都有自己的用途。
    发表于 05-29 10:49 420次阅读
    RTOS消息<b class='flag-5'>队列</b>的应用

    利用C++提供的队列封装一个消息队列

    最近的C++项目中,需要用到消息队列,但是C++中又没有原生的消息队列,就在网上找了一下相关资料,利用C++提供的队列,自己封装一个消息队列,以后的项目也可以复用。
    的头像 发表于 05-20 15:16 1099次阅读
    利用C++提供的<b class='flag-5'>队列</b>封装一个消息<b class='flag-5'>队列</b>

    嵌入式环形队列和消息队列是如何去实现的?

    嵌入式环形队列和消息队列是实现数据缓存和通信的常见数据结构,广泛应用于嵌入式系统中的通信协议和领域。
    发表于 05-20 14:55 670次阅读