单片机软件架构连载(5)-队列

前面讲了指针、结构体之类的基础知识。 这篇内容开始,就要对这些基础知识,做一些复杂的应用了,比如说队列。

其实,在2018年的时候,我录制过一套程序架构的视频,里面有手把手写队列的教程,讲了一系列贴近实际的高阶编程思维和技巧,受到了很多粉丝朋友们的好评和认可。

但由于教程录制的比较早,音质比较差,还有一些细节不够完善。 所以这根刺,一直扎在我的心里,为了让无际单片机特训营的铁子们,在学我们项目时,能更高效,更好地理解,最近计划把这些基础内容,重新梳理一遍,做成一个系列的软件架构2.0图文/视频教程。

1. 为什么我要讲队列?

在做研发工程师时,我经常会碰到一些通讯类的产品,比如工控板,PDU,物联网类的。

一般做这种产品,写接收数据流的时候,都会比较头痛,不管是串口通讯,还是无线通讯。

举个例子,比如STM32接收串口数据流。

在早期,我是定义一个数组,一个数组下标变量,去处理接收的数据流,代码如下:

这种方式,存在很多问题,增加了工程师写代码的复杂性。

  • 代码维护起来很麻烦

因为要手动去检查数组缓冲区边界,以避免越界错误,当需要处理更复杂的数据流,或增加新的数据源时,数组不如队列那样容易扩展和维护。

  • 数据容易错乱

在中断服务(ISR)中直接操作数组可能会与主程序发生资源竞争,如果多个任务访问同一个数组,需要额外的同步机制(如互斥锁)来避免数据竞争条件和不一致。

如果数据接收和处理不同步,使用数组可能会导致数据顺序混乱,导致程序问题引起的数据丢包。 以前我就被这种问题搞的头嗡嗡响,需要额外的代码去解决这种问题,增加了程序复杂性,而且没经验,费劲巴拉做出来还不稳定。

就这种问题,困扰了我挺长时间,直到后面跳槽,看了别的工程师写的代码,才知道原来队列能解决这些痛点。 从那个时候开始,我处理数据流的方式,就变成下面这样了:

是不是感觉简单了很多?其实队列对数据处理的算法,也不简单,只是用队列做成数据处理的通用模版,下次碰到类似的需求,就能直接用了,用专业术语来说,就是代码的可移植性和复用性更强。

这只是队列其中一个应用,队列的本质是数据缓存,数据入列和出列遵循先进先出的规则。

就是先把数据存起来,等CPU有空闲时间,或者程序某些条件成立时,再把数据取出来处理。

基于这个特性,就能衍生出非常多实际应用。特别是处理需要确保数据顺序的应用中。

2. 什么场景要用队列?

我总结了几个自己最常用到的地方。

2.1 串口通信数据缓冲

单片机通过串口接收数据时,通常会使用一个队列来缓冲接收到的字节,这样可以确保数据在被主程序处理之前不会丢失。

2.2 音频处理

在音频播放或录音设备中,队列用于缓冲音频样本数据,实现轮流式播放或录音。 举个例子: 比如我们无际单片机特训营的项目6,WiFi&4G报警主机有语音提示功能,比如按下离家布防按键,会播放"离家布防"语音,按下在家布防按键,会播放"在家布防"语音。

如果我快速按下这两个按键,为了保证语音能完整播放,我就可以把按键事件,先丢进队列缓存,这样就能实现语音按照顺序完整的播放了。

2.3 任务调度和同步

在使用RTOS的系统中,队列用于任务间的消息传递和同步,支持复杂的任务调度。

2.4 按键输入处理

检测到按键事件后,可以先放入队列中,主程序可以按顺序处理这些事件,防止按键动作过快,导致按键事件丢失,目前我们项目就是采用这种方式。

2.5 ADC数据

我们采集的ADC数据,经过一定的处理后,也可以先丢进队列,以便在适当的时候再处理或分析。

2.6 固件升级数据流

固件升级的数据交互比较大,非常适合利用队列,保证数据完整性,我们项目6也有用到,在固件升级过程中,下载的固件数据块可以被放入队列中,然后按顺序写入闪存。 类似的应用还有非常多,总而言之,队列解决了我很多棘手的问题。

3. 队列原理

队列是一种线性的数据结构,它遵循先进先出(FIFO,First In First Out)的原则,即最先进入队列的数据将是最先被移除的数据。 在队列中,数据的入列通常在一端进行,称为队尾,数据的出列则在另一端进行,称为队头。 这种结构使得队列非常适合处理需要有序处理数据的场合。

我们可以把队列,想象成往一个双通的管道塞乒乓球,我们从左边往管道里面塞乒乓球,这个动作叫入列。 我们把乒乓球从管道右边取出来,这个动作叫出列。

在管道里的乒乓球会排成一条队形。 先进去的乒乓球就会先出来,这个就是队列里先进先出的规则。

乒乓球比作数据,那管道就是存储数据的缓存,管道能容纳几个乒乓球,就代表这个缓存能存储多少个数据,说白了就是数组的大小,上图这个队列,能存4个数据,就相当于Buff[4]这样。

队列的程序实现方式,是通过一个固定大小的数组,以及一个头指针,一个尾指针。 数组负责存储数据。 头指针负责数据出列时,要从哪个地址取出来。 尾指针负责数据入列时,要存到哪个地址。 所以,入列和出列的操作,就是两个指针,在数组里玩数据先进先出的算法。

4.队列的使用

不同的工程师,实现队列的代码是不一样的。 在没有丰富的项目经验前提下,或者在没有用过队列的前提下,不要为难自己必须能把队列算法写出来。

我刚开始,也是直接移植别人的队列程序,不断用在自己的项目上,经过几个项目熟练运用后,再研究队列算法实现的细节代码,自己再写几遍就通了。

所以,我们特训营的老铁们,刚开始不要自己写,先学会用,多举一反三,多应用到不同的场景和项目,用熟了再尝试自己写,这是很重要的学习顺序。

以我们无际单片机项目特训营的队列程序为例,一共有4个函数。

QueueEmpty(x)

清空队列函数,每次使用队列前,必须要把队列清空,清空函数里会让头指针和尾指针,默认指向一个有效地址,也就数组的第一个元素,否则会引起指针地址异常。

形参说明: x - 是一个队列结构体变量

QueueDataIn(x,y,z)

数据入列函数,就是把一个或多个字节数据,丢进指定的队列里。

形参说明:

x - 队列结构体变量

y - 数据地址

z - 要入列的数据数量,单位是字节。

注意:

①.入列的数据,只能是unsigned char类型。

②.如果队列满了,继续入列数据,会从最开始入列的数据位置,开始覆盖数据。

QueueDataOut(x,y)

数据出列函数,就是从指定队列里,取一个字节数据出来。

形参说明: x - 队列结构变量 y - 取出来的数据,要存放的地址

注意:我们出列函数,每次只能取一个字节数据。

QueueDataLen(x)

清空指定队列里面所有的数据。 形参说明: x - 队列结构变量

5. 视频演示队列用法

后面内容涉及一些代码和视频讲解,编辑起来不方便,可找我安排飞书,阅读起来体验感更好点。


最近很多粉丝问我单片机怎么学,我根据自己从业十年经验,累积耗时一个月,精心整理一份「单

片机最佳学习路径+单片机入门到高级教程+工具包」全部无偿分享给铁粉!!!

除此以外,再含泪分享我压箱底的22个热门开源项目,包含源码+原理图+PCB+说明文档,让你迅速进阶成高手

教程资料包和详细的学习路径可以看我下面这篇文章的开头

《单片机入门到高级开挂学习路径(附教程+工具)》

《单片机入门到高级开挂学习路径(附教程+工具)》

《单片机入门到高级开挂学习路径(附教程+工具)》

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

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

相关文章

中国计量大学理学院访问赛氪网:共探校企合作新篇章来

2024年7月5日,中国计量大学理学院代表团莅临环球赛乐(北京)科技有限公司,进行了一场深入的调研交流活动。代表团成员包括中国计量大学理学院副院长王义康教授、数据科学系副主任刘学艺副教授以及金世举老师。此次访问旨在进一步强…

暑期限定|get你的联邦学习技能,隐私计算暑期夏令营开启报名!

伴随着数字经济时代的来临,数据的安全流通和隐私保护也迎来了新的发展和挑战。隐私技术作为关键技术,可以在保护数据安全的同时,联合多方进行安全计算。 “隐语”是蚂蚁集团于2022年开源的一套可信隐私计算技术框架,支持了包括多…

复合机器人:手脚眼脑的完美结合

在现代工业制造的舞台上,复合机器人如同一位精密而高效的工匠,以其独特的手脚眼脑,正深刻改变着传统的生产方式。这些机器人不仅仅是机械臂的简单延伸,它们汇聚了先进的机械结构、智能的感知系统、精密的控制技术和灵活的思维能力…

js 数组合并方式

1. 使用 concat 方法 》不改变原数组 concat 方法可以将多个数组或值合并成一个新数组。 const arr1 [1, 2, 3] const arr2 [4, 5, 6] const mergedArr arr1.concat(arr2) // [1, 2, 3, 4, 5, 6]2. 使用展开运算符 (...) 》不改变原数组 展开运算符 ... 可以用于展开数组…

Web应用安全实用建议

引言 随着互联网的飞速发展,Web应用已成为企业与用户互动的重要桥梁。然而,Web应用面临着各种安全威胁,这些威胁不仅可能导致数据泄露,还会损害企业的声誉,甚至造成经济损失。为了确保Web应用的安全性,必须…

【虚拟机安装centos7.6 yum使用报错 配置镜像源 错误记录】

错误 [rootlocalhost ~]# yum -y update 已加载插件:fastestmirror Loading mirror speeds from cached hostfileOne of the configured repositories failed (未知),and yum doesnt have enough cached data to continue. At this point the onlysafe thing yum c…

「数据结构」和「数据类型两个概念的本质是什么区别与联系是什么

貌似数据结构中包含了数据类型,而数据类型又建立在数据结构之上? 就像有人在其他评论里说的,数据本质上是没有类型的。我们都知道,数据在存储上是一堆01的数字, 刚好我有一些资料,是我根据网友给的问题精心…

神卓互联共享文件使用教程

#文件共享# 文件共享已成为我们日常生活和工作中不可或缺的一部分。它如同一条无形的纽带,将人们紧密地联系在一起,促进了信息的快速传播和交流。 文件共享的魅力在于其打破了地域和时间的限制。无论我们身处世界的哪个角落,只要有网络连接&a…

【Scrapy】Scrapy 中间件等级设置规则

准我快乐地重饰演某段美丽故事主人 饰演你旧年共寻梦的恋人 再去做没流着情泪的伊人 假装再有从前演过的戏份 重饰演某段美丽故事主人 饰演你旧年共寻梦的恋人 你纵是未明白仍夜深一人 穿起你那无言毛衣当跟你接近 🎵 陈慧娴《傻女》 Scrapy 是…

收银系统源码-次卡功能

智慧新零售收银系统是一套线下线上一体化收银系统,给门店提供了含线下收银称重、线上商城、精细化会员管理、ERP进销存、营销活动、移动店务助手等一体化行业解决方案! 详细功能见下文: 门店收银系统源码-CSDN博客文章浏览阅读2.6k次&#…

[Python爬虫] 抓取京东商品数据||京东商品API接口采集

本文结构: 一、引言 二、代码分享 三、问题总结 引言 这两天因为一些需求,研究了一下如何爬取京东商品数据。最开始还是常规地使用selenium库进行商品页的商品抓取,后来因为想要获取优惠信息,只能进入到商品详情页进行抓取&#x…

【5G VoNR】VoNR流程简述

博主未授权任何人或组织机构转载博主任何原创文章,感谢各位对原创的支持! 博主链接 本人就职于国际知名终端厂商,负责modem芯片研发。 在5G早期负责终端数据业务层、核心网相关的开发工作,目前牵头6G技术研究。 博客内容主要围绕…

重写equals()方法为什么同时要重写hashcode()

equals()方法 equals()方法是Object类中的一个方法,在Object类中,equals等同于。 在不同的类中,往往会对equals()按需求进行重写。重写的目的都是:用于比较两个对象是否 "相等"。如果两个对象的内容相同,那…

fiddler移动端抓包

步骤 1、手机和电脑必须在同一个局域网: 1)手机和电脑连同一个WiFi; 2)手机连WiFi,电脑用网线连接开启这个WiFi的无线路由; 3)电脑开热点,手机连热点 2、开启fiddler代理&#xff…

faskapi好用的模板

在Web开发领域,FastAPI作为一个基于Python的高性能Web框架,因其快速、易用以及强大的功能而备受开发者青睐。关于FastAPI的好用模板,这里介绍几个不同角度的模板或项目框架,以帮助您更好地理解和选择适合自己的起点。 1. FastAPI…

第十一节 动态面板加密解密显示

在原型中我们经常会遇到文件加密与解密显示问题,下面以一个简单案例来说明实现怎么切换明文与密文不同显示方式案例说明; 1、添加动态面板 2、设置加密与不加密 3、添加动作事项 注意为可见时要设置面板状态向前循环,上一项,否则…

新闻第一线|随身WiFi市场乱象与破局者:格行以品质重塑行业信任、随身WiFi行业标杆!

在快速发展的移动互联网时代,随身WiFi凭借用网方便性价比高也随之爆火。然而,近年来,随身WiFi市场却陷入了“内卷”与“信任危机”的双重困境,消费者在选择时往往面临质量问题。在此背景下,格行以其独特的品牌理念和扎…

Linux网络配置管理

目录 一、网络配置 1. 网卡配置 2. 路由 二、 网络信息查看 1.netstat 2. ss 三、 额外的命令 time 一、网络配置 之前我们学过 ifconfig ,这个命令可以查看网络接口的地址配置信息,我们只知道它可以查看接口名称、IP 地址、子网掩码等。 但是&a…

笔记:Newtonsoft.Json 序列化接口集合

在使用 Newtonsoft.Json 序列化接口集合时,一个常见的挑战是如何处理接口的具体实现,因为接口本身并不包含关于要实例化哪个具体类的信息。为了正确序列化和反序列化接口集合,你需要提供一些额外的信息或使用自定义的转换器来指导 Newtonsoft…

【Unix/Linux】$bash-3.2是什么

bash-3.2 指的是Bourne Again Shell(Bash)的3.2版本。 Bash是一个广泛使用的Unix shell和命令语言,是GNU项目的一部分,也是许多Linux发行版和Unix系统的默认shell。 以下是一些关于Bash 3.2的要点: 1. 兼容性&#…