FIFO基础知识

news/2024/5/4 20:11:12/文章来源:https://blog.csdn.net/qq_45217381/article/details/134111937


🎀 文章作者:二土电子

🌸 关注文末公众号获取其他资料和工程文件!

🐸 期待大家一起学习交流!


文章目录

  • 一、FIFO简介
    • 1.1 什么是FIFO
    • 1.2 FIFO的功能
    • 1.3 什么时候使用FIFO
    • 1.4 FIFO的分类
    • 1.5 FIFO重要参数
  • 二、C语言数组实现FIFO

一、FIFO简介

1.1 什么是FIFO


  借用大家的常规描述,FIFO是英文First In First Out的缩写,是一种先进先出的数据缓存器,他与普通存储器的区别是没有外部读写地址线,这样使用起来非常简单,但缺点就是只能顺序写入数据,顺序的读出数据,其数据地址由内部读写指针自动加1完成,不能像普通存储器那样可以由地址线决定读取或写入某个指定的地址。

  博主理解的FIFO就像一个圆柱形收纳容器,或者说像一根水管。存放的东西从一端进入,另一端出来。从另一端拿取东西时,我们只能按照放入的顺序取出。第一个被放入的东西首先被取出,最后一件放入的东西最后被取出,当水管被填满后,再往里塞东西,就无法进入了,这就是FIFO的基本模型。下面简单画一下FIFO的示意图

FIFO简意图

1.2 FIFO的功能

  • 对连续的数据流进行缓存,防止数据丢失。
  • 可以减轻CPU负担。

博主在写到这里的时候在想,如果在单片机中用数组实现FIFO,能否起到减轻CPU负担的效果,或者换句话说,FIFO是如何减轻CPU负担的呢?


  FIFO实际上是一个存储器,是一个硬件设备。以STM32F1系列单片机为例,在进行串口通信接收数据时,如果我们不使用FIFO存储器,那么每接收到一个字节的数据,CPU都需要来进行存储,如果说接收一串很长的信息,很可能造成信息丢失,而且每个字节的接收都需要CPU参与,极大的增加了CPU的负担。但是如果我们使用FIFO存储器来对接收数据进行缓存,当我们检测到数据传输完成后,产生一个中断,告诉CPU全部数据已经接收完成,可以进行处理,这时CPU再统一进行处理,这样一来,就减轻了CPU的负担。但是在利用数组实现FIFO时,本质上在接收数据时还是需要CPU的参与,因此在博主看来,并没有减轻CPU的负担。


  在利用串口接收数据的时候,很多教程给出的例程都是只利用串口接收中断来实现的,实际使用时相信有些小伙伴会遇到数据丢失的情况。实际STM32有一个串口空闲中断,也叫做帧中断。在接收数据的时候,如果超过一个字节时间没有再接收到数据,会认为接收完成,产生空闲中断。而总线上会有一个字节时间内没有接收到数据的情况,通常是一帧数据发送完成,因此空闲中断也可以成为帧中断。对于利用串口空闲中断来接收数据的程序实现,可移步至博主STM32速成笔记专栏串口通信篇查看,关注文末公众号获取程序工程文件。

1.3 什么时候使用FIFO

  • 不同时钟域之间的数据传输。
  • 不同宽度的数据传输。

1.4 FIFO的分类

  • 同步FIFO
    同步FIFO是指读时钟和写时钟为同一个时钟。在时钟沿来临时同时发生读写操作。
  • 异步FIFO
    异步FIFO是指读写时钟不一致,读写时钟是互相独立的。

1.5 FIFO重要参数

通过对FIFO模型的通俗介绍,我们可以知道,FIFO可以想象成一个水管,先进先出,有一定的深度。我们在往FIFO里写入数据的时候,应该能够知道什么时候水管满了。在读取数据的时候,应该知道什么时候水管空了。下面我们就来看好一下FIFO的一些重要参数。

  • FIFO的宽度
    FIFO进行一次数据读写时数据的位数,比如与8位、16位、32位等等。
  • FIFO的深度
    FIFO能存储的数据个数。比如一个FIFO的宽度为8位,深度为N,那么他能存储N个8位数据。
  • 满标志
    FIFO已满或将满时发送的信号,提示CPU不要再对FIFO进行写操作,防止数据溢出。
  • 空标志
    FIFO已空或将空时发送的信号,提示CPU不要再对FIFO进行读操作,防止读出无效数据。
  • 读时钟
    读操作所遵循的时钟,每个时钟沿来临时读数据。
  • 写时钟
    写操作所遵循的时钟,每个时钟沿来临时写数据。

二、C语言数组实现FIFO


  这里给出一个利用C语言数组实现FIFO的例子
#include <stdio.h>#define FIFO_MAX_DEPTH 3   // FIFO深度typedef struct 
{int data[FIFO_MAX_DEPTH];int redIndex;   // 读索引(读地址)int writeIndex;   // 写索引(写地址)
} FIFO_Queue;// 初始化FIFO
// 最开始没有数据,写索引等于读索引
void Fifo_Init (FIFO_Queue *queue) 
{queue->redIndex = -1;queue->writeIndex = -1;
}// 检查FIFO是否已满
// 写索引的下一个位置是读索引,说明FIFO已满
// 实际也就是判断写索引的下一个位置是否等于FIFO深度
int isFull(FIFO_Queue *queue) 
{return (queue->writeIndex + 1) % FIFO_MAX_DEPTH == queue->redIndex;// 也可以写成如下形式// return queue->writeIndex + 1 == FIFO_MAX_DEPTH;
}// 检查FIFO是否已空
// 判断写索引是否为-1
int isEmpty(FIFO_Queue *queue) 
{return queue->writeIndex == -1;
}// 元素入队
void enqueue(FIFO_Queue *queue, int element) 
{// 判断FIFO是否已满if (isFull(queue)) {// 提示FIFO已满printf("FIFO已满,无法继续写入数据!\n");return;}// 判断FIFO是否为空if (isEmpty(queue)) {// 第一次存储数据需要更新一下读索引queue->redIndex = 0;}// 存储数据,更新写索引queue->writeIndex = (queue->writeIndex + 1) % FIFO_MAX_DEPTH;queue->data[queue->writeIndex] = element;printf ("数据写入成功\n");
}// 元素出队
int dequeue(FIFO_Queue *queue) 
{// 判断FIFO是否为空if (isEmpty(queue)) {// 提示FIFO为空printf("FIFO已空,无法继续读取数据!\n");return -1;}// 读出数据int element = queue->data[queue->redIndex];// 判断是否读到最后一个数据if (queue->redIndex == queue->writeIndex) {// 全部读取结束,重新初始化queue->redIndex = -1;queue->writeIndex = -1;} else {queue->redIndex = (queue->redIndex + 1) % FIFO_MAX_DEPTH;}return element;
}int main() 
{FIFO_Queue queue;Fifo_Init(&queue);printf ("FIFO数据写入中……\n");enqueue(&queue, 10);enqueue(&queue, 20);enqueue(&queue, 30);enqueue(&queue, 40);printf ("\n");printf ("FIFO数据读取中……\n");printf("Dequeued element: %d\n", dequeue(&queue));printf("Dequeued element: %d\n", dequeue(&queue));printf("Dequeued element: %d\n", dequeue(&queue));printf("Dequeued element: %d\n", dequeue(&queue));return 0;
}

  输出结果如下

运行输出结果

本文如有任何问题,欢迎各位大佬留言指正!最后,本文的程序设计参考了这篇文章,特此声明C语言中使用数组来实现FIFO。

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

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

相关文章

大厂面试题-JVM为什么使用元空间替换了永久代?

目录 面试解析 问题答案 面试解析 我们都知道Java8以及以后的版本中&#xff0c;JVM运行时数据区的结构都在慢慢调整和优化。但实际上这些变化&#xff0c;对于业务开发的小伙伴来说&#xff0c;没有任何影响。 因此我可以说&#xff0c;99%的人都回答不出这个问题。 但是…

中科驭数受邀亮相两场重要行业盛会,摘得2023“璀璨技术奖”奖项

近日&#xff0c;中科驭数作为DPU算力基础设施领军企业&#xff0c;受邀参与2023信息技术应用创新专题研讨会暨第二届集成电路产业发展创新大会、以及2023AI网络创新大会。在两大行业盛会上&#xff0c;中科驭数与行业知名专家和企业代表齐聚一堂&#xff0c;分享了DPU在集成电…

数据库数据恢复—NTFS分区损坏的SqlServer数据库数据恢复案例

SqlServer数据库数据恢复环境&#xff1a; 一台服务器&#xff0c;windows操作系统NTFS文件系统&#xff0c;运行了12个sqlserver数据库。 SqlServer数据库故障&#xff1a; 根据用户描述&#xff0c;故障情况是工作人员误操作导致服务器硬盘上sqlserver数据库所在分区损坏。经…

nacos在linux中的安装、集群的配置、mysql生产配置

1.下载和安装 官方下载地址&#xff1a;https://github.com/alibaba/nacos/releases&#xff0c;根据自己需要的本版去下载就行 下载的是 .tar.gz 后缀的文件是linux版本的 使用tar命令解压&#xff0c;完成之后是一个nacos的文件夹 和windows下的文件夹目录是一样的 要启…

优先队列PriorityQueue

前言 PriorityQueue这个队列不知道大家使用过吗&#xff0c;反正我用的很少&#xff0c;主要对它不是很了解&#xff0c;今天我带领大家剖析下PriorityQueue这个优先级队列。 PriorityQueue介绍 顾名思义&#xff0c;PriorityQueue是优先队列的意思。优先队列的作用是能保证每…

NB-IOT的粮库挡粮门异动监测装置

一种基于NBIOT的粮库挡粮门异动监测装置,包括若干个NBIOT开门监测装置,物联网后台管理系统,NBIOT低功耗广域网络和用户访问终端;各个NBIOT开门监测装置通过NBIOT低功耗广域网络与物联网后台管理系统连接,物联网后台管理系统与用户访问终端连接.NBIOT开门监测装置能够对粮库挡粮…

一文了解Elasticsearch

数据分类 数据按数据结构分类主要有三种&#xff1a;结构化数据、半结构化数据和非结构化数据。 结构化数据 结构化数据具有明确定义数据模型和格式的数据类型。 特点&#xff1a; 数据具有固定的结构和模式。 数据项明确定义数据类型和长度。 适合用于数据查询、过滤和分…

多线程---阻塞队列+生产者消费者模型

文章目录 阻塞队列自己实现一个阻塞队列&#xff08;三步&#xff09;标准库中的阻塞队列使用阻塞队列的优势 生产者消费者模型 阻塞队列 队列&#xff08;Queue&#xff09;是我们熟悉的一个数据结构&#xff0c;它是“先进先出”的。但是并不是所有的队列都是“先进先出”的…

动静分离技术

一、HAproxy 动静分离 1、概念&#xff1a; HAproxy 动静分离技术是一种用于优化 Web 服务器性能和提高用户体验的策略&#xff0c;它通过将动态内容和静态内容分别路由到不同的后端服务器来实现&#xff0c;减轻服务器负载&#xff0c;提高网站的响应速度。 动态内容包括由…

maven子模块无法导入jar包问题

明明本地仓库有jar包 maven子模块无法导入jar包&#xff0c;然后放到父项目的pom.xml则可以导入 可以试试更新仓库后&#xff0c;引入成功

【Linux】多路IO复用技术①——select详解如何使用select在本地主机实现简易的一对多服务器(附图解与代码实现)

这一篇的篇幅可能有点长&#xff0c;但真心希望大家能够静下心来看完&#xff0c;相信一定会有不小的收获。那么话不多说&#xff0c;我们这就开始啦&#xff01;&#xff01;&#xff01; 目录 一对一服务器中的BUG 如何实现简易的一对多服务器 实现简易一对多服务器的大体…

软考下午第一题 案列分析

期待分值 10&#xff0c;前三问12左右分&#xff0c;最后一题2、3分左右&#xff0c;重点在于拿下前面三题。 小心谨慎&#xff0c;不要大意。 数据流图 外部系统 数据存储 加工&#xff08;&#xff09;process 数据流 第二小题 说明给出存储名称&#xff0c;就使用该名称&…

最短路径:迪杰斯特拉算法

简介 英文名Dijkstra 作用&#xff1a;找到路中指定起点到指定终点的带权最短路径 核心步骤 1&#xff09;确定起点&#xff0c;终点 2&#xff09;从未走过的点中选取从起点到权值最小点作为中心点 3&#xff09;如果满足 起点到中心点权值 中心点到指定其他点的权值 < 起…

STM32单片机智能小车一PWM方式实现小车调速和转向

目录 1. 电机模块开发 2. 让小车动起来 3. 串口控制小车方向 4. 如何进行小车PWM调速 5. PWM方式实现小车转向 1. 电机模块开发 L9110s概述 接通VCC&#xff0c;GND 模块电源指示灯亮&#xff0c; 以下资料来源官方&#xff0c;具体根据实际调试 IA1输入高电平&#xff…

BUUCTF qr 1

BUUCTF:https://buuoj.cn/challenges 题目描述&#xff1a; 这是一个二维码&#xff0c;谁用谁知道&#xff01; 密文&#xff1a; 下载附件&#xff0c;得到一张二维码图片。 解题思路&#xff1a; 1、这是一道签到题&#xff0c;扫描二维码得到flag。 flag&#xff1a;…

外汇天眼:在2023年Expo上探索金融科技的未来!

从2020年初至2022年年底&#xff0c;全球范围内爆发的新冠疫情蔓延&#xff0c;对各国经济造成了严重冲击&#xff0c;导致贸易活动几近停滞&#xff0c;国际人员流动受限&#xff0c;产业链陷入危机。为应对这一局面&#xff0c;美欧经济体采取了前所未有的扩张性财政和货币政…

高效分割分段视频:提升您的视频剪辑能力

在数字媒体时代&#xff0c;视频剪辑已经成为一项重要的技能。无论是制作个人影片、广告还是其他类型的视频内容&#xff0c;掌握高效的视频剪辑技巧都是必不可少的。本文将介绍如何引用云炫AI智剪高效地分割和分段视频&#xff0c;以提升您的视频剪辑能力。以下是详细的操作步…

设计模式—创建型模式之原型模式

设计模式—创建型模式之原型模式 原型模式&#xff08;Prototype Pattern&#xff09;用于创建重复的对象&#xff0c;同时又能保证性能。 本体给外部提供一个克隆体进行使用。 比如我们做一个SjdwzMybatis&#xff0c;用来操作数据库&#xff0c;从数据库里面查出很多记录&…

半导体产线应用Power Link 转EtherCAT协议网关数字化转型

随着数字化转型的推进&#xff0c;越来越多的企业开始意识到数字化转型的重要性&#xff0c;并将其作为发展战略的关键之一。半导体产线作为一个高度自动化的生产系统&#xff0c;自然也需要数字化转型来提高效率、降低成本和提高质量。Power Link 转EtherCAT协议网关是半导体产…