目录
什么是FIFO
FIFO也就是First in, First out。用中文来描述就是先进先出,后进后出,不进不出。FIFO相当于是一个缓冲环节,可以防止数据丢失。
一般用到不同时域之间的数据传输。比如说单片机按键的速度和CPU去处理按键对应的任务的速度显然是不同的,如果任务非常庞大,可能还没有处理完一个任务,我们已经按了好几次。如果没有FIFO机制,那么后面几次的按键可能都会被忽略,但又不能让CPU去等待按键。所以说可以使用FIFO机制去存储按键事件,等待CPU挨个处理。在单片机的串口也会使用这种方法,挨个发送数据,因为CPU处理的速度显然比串口发送数据的速度高。
FIFO实现方法
落实到C语言上,FIFO机制归根结底是对数组的管理和读写,主要分为三个部分,数组及管理数组的结构体、读数组、写数组。
数组及管理数组的结构体(找个钱袋子,贴上标签)
数组的定义比较简单,可以根据自己的需求选择数据类型,应用到按键的话,uint8_t足矣。这一步就好比是确定钱袋子存多大的钱,是1块还是5毛。
/*! fifo缓冲区类型 */
#define FIFO_TYPE uint8_t
下面就是数组的管理机构,结构体。要想管理一个数组,就需要在结构体里面包括数组的一些信息,就好像标签。如下所示
/**
* FIFO结构体
*/
typedef struct
{
FIFO_TYPE *buff; /* FIFO 缓冲区 */
uint16_t fifoLen; /* FIFO 缓冲区有效数据长度 */
uint16_t fifoSize; /* 缓冲区大小 */
uint16_t fifoWrite; /* 缓冲区写指针 */
uint16_t fifoRead; /* 缓冲区读指针 */
} fifo_t;
这里面包括了数组的大部分信息,包括数组的地址、有效数据长度、数组的大小、读写的位置。这一步就好比是确定钱袋子上面的标签该写些什么,有多少钱,最大能存多少,存到哪了,花到哪了。
但上面这些都只是概念,还没有实例化,虚无缥缈。实例化如下
#define Key_Buff_Size 10 //数组大小
fifo_t Key_Fifo;
FIFO_TYPE Key_Buff[Key_Buff_Size];
关联结构体和数组(贴标签,并写好)
这个时候我们只是定义好了数组和结构体,还没有确定关系,还没把标签贴到钱袋子上面。先把标签写好,刚开始是的时候钱袋子里面可什么都没有,所以初始化的时候所有的数据清零。格式如下
void fifo_init(fifo_t *fifo, FIFO_TYPE *buff, uint16_t size)
{
fifo->fifoLen = 0;
fifo->fifoRead = 0;
fifo->fifoWrite = 0;
fifo->buff = buff;
fifo->fifoSize = size;
}
把标签贴上去吧,如下所示
fifo_init(&Key_Fifo, Key_Buff, Key_Buff_Size);
存储数据(存钱)
想要在数组里面存储数据,首先需要知道存储的数组的地址,存什么。好比是想存多少钱、应该自己存哪个钱袋子,钱袋子已经存了多少,有没有存满,钱肯定得接着之前存的继续往下存,不能重新开一个账户吧。
所以我们在编写函数的时候,形参就基本确定了,数组的地址,存的数据(存哪个,存多少)。确定好数组之后,第一步就是要检查检查数组有没有满,钱袋子还能不能放。和钱袋子不同的是,这个数组存满了就要从头再存。判断结束后就开始存储到数组里面,然后存储的指针,大于数组大小后归零,相当于是更新标签。具体如下
void fifo_push(fifo_t *fifo, FIFO_TYPE data)
{
fifo->fifoLen++;
/* 判断缓冲区是否已满 */
if (fifo->fifoLen > fifo->fifoSize)
{
fifo->fifoLen = fifo->fifoSize;
}
fifo->buff[fifo->fifoWrite] = data;
if (++fifo->fifoWrite >= fifo->fifoSize)
{
fifo->fifoWrite = 0;
}
}
读取数组(花钱)
不能只存不花吧,存钱就是为了花钱。花钱的步骤和存钱差不多,也要找好花哪个钱袋子,花到哪。
第一步先判断数组是否为空,要是钱袋子里面本来都没钱怎么花。判断结束后,就要开始更新标签了。有效数据自减,转移数据,有效数据限幅。理解怎么存取数据了之后,就会读取数据了。会花钱就会赚钱,花钱是赚钱的动力。如下所示
void fifo_pop(fifo_t *fifo, FIFO_TYPE *data)
{
/* 缓冲区为空 */
if (fifo->fifoLen == 0)
{
*data = KEY_NONE;
}else
{
fifo->fifoLen--;
*data = fifo->buff[fifo->fifoRead];
if (++fifo->fifoRead >= fifo->fifoSize)
{
fifo->fifoRead = 0;
}
}
}
总结
源代码来自网上,作者加以简化,以便于理解。没有添加复杂的功能,可以根据自己需求添砖加瓦。