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
    +关注

    关注

    2270

    文章

    10914

    浏览量

    356707
  • 串口
    +关注

    关注

    14

    文章

    1557

    浏览量

    76708
  • 代码
    +关注

    关注

    30

    文章

    4805

    浏览量

    68785

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

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

收藏 人收藏

    评论

    相关推荐

    JavaWeb消息队列使用指南

    在现代的JavaWeb应用中,消息队列(Message Queue)是一种常见的技术,用于异步处理任务、解耦系统组件、提高系统性能和可靠性。 1. 消息队列的基本概念 消息队列是一种应用程序对应
    的头像 发表于 11-25 09:27 170次阅读

    为什么同一个队列引用的全局变量,运行在两个子vi中发现队列数据丢失了

    我创建了一个队列,然后将队列引用做了个全局变量,运行在两个子vi中,一个是只入队列,另一个是只出队列。但我发现,一个字vi数据入队列成功,检
    发表于 11-14 11:47

    嵌入式环形队列与消息队列的实现原理

    嵌入式环形队列,也称为环形缓冲区或循环队列,是一种先进先出(FIFO)的数据结构,用于在固定大小的存储区域中高效地存储和访问数据。其主要特点包括固定大小的数组和两个指针(头指针和尾指针),分别指向
    的头像 发表于 09-02 15:29 599次阅读

    玩转RT-Thread之消息队列的应用

    在嵌入式系统开发中,实时处理串口和ADC数据是一项重要的任务。本文将介绍如何在RT-Thread实时操作系统中,利用消息队列来同时处理来自串口和ADC的数据。通过这种方法,我们能够高效地管理和处理
    的头像 发表于 07-23 08:11 635次阅读
    玩转RT-Thread之消息<b class='flag-5'>队列</b>的应用

    在arduino平台上开发esp32c3,twai队列异常的原因?

    twai_get_status_info。发现在TX队列里有一个数据。但是当任务到主循环的开头再次读取状态时则发现数据跑到了RX队列,而实际上CAN总线上并没有发送任何数据给ESP32C3。
    发表于 06-11 06:16

    Freertos队列项里的字节长度是否可以获取?

    最近刚学Freertos, 看到可以获取Freertos队列长度,但是队列项里的字节长度是否可以获取? 因为项目中队列中会存放不定长字节,需要对队列中的数据分拣,每次分拣的时候遍历所
    发表于 04-29 07:17

    freertos串口接收数据后如何发送给任务?

    正在学freertos。串口中断接收一帧数据后,放到数组里,如何将数据发送给任务呢? 如果用消息队列,是否建立的消息队列需要是数组类型的?还是说消息列表建立成uint8类型的,列表长度设为接收数据
    发表于 04-18 06:36

    进程间通信的消息队列介绍

    消息队列是一种非常常见的进程间通信方式。
    的头像 发表于 04-08 17:27 321次阅读

    MCU专属队列功能模块之QueueForMcu应用

    当需要从队列头部获取多个数据,但又不希望数据从队列中删除时,可以使用 Queue_Peek_Array 函数来实现,该函数的参数与返回值与 Queue_Pop_Array 完全相同。
    发表于 03-20 11:44 530次阅读
    MCU专属<b class='flag-5'>队列</b>功能模块之QueueForMcu应用

    什么是PLC循环移位指令 PLC循环移位的特点

    PLC循环移位指令包括循环左移指令和循环右移指令。在循环移位过程中,移出的位并不会丢失,而是会放回空出的位上,形成一个环形移位。
    的头像 发表于 03-07 16:57 2238次阅读
    什么是PLC<b class='flag-5'>循环</b>移位指令 PLC<b class='flag-5'>循环</b>移位的特点

    arduino如何停止loop循环

    Arduino的loop循环是其主要的程序执行部分,该循环将在Arduino开发板上持续运行,并且只有在程序被重新上传或开发板断电重启时才会停止。然而,在某些情况下,你可能需要在程序执行过程中停止或
    的头像 发表于 02-14 16:24 4621次阅读

    arduino中while循环怎么跳出

    Arduino 是一款开源的硬件平台,广泛应用于各种物联网和嵌入式系统项目。在 Arduino 上编写代码时,循环结构起到了至关重要的作用。而其中的 while 循环更是常用于需要根据特定条件重复
    的头像 发表于 02-14 16:22 2657次阅读

    循环指令loop规定循环次数

    循环指令是计算机编程中非常重要的概念,它允许程序重复执行一段代码块,使得程序可以更有效地处理大量数据和重复性任务。在本文中,我们将详尽、详实、细致地介绍循环指令的相关概念、语法和应用场
    的头像 发表于 02-14 16:10 1770次阅读

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

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

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

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