最近笔者在做一个小项目的时候需要使用FIFO来做为数据的缓存。但笔者使用的芯片并没有硬件的FIFO管理器,所以需要使用C语言来用软件做一个FIFO的管理。
开始引用了这位大神的一些代码
(5条消息) C语言实现标准FIFO_jdh99的专栏-CSDN博客_c fifohttps://blog.csdn.net/jdh99/article/details/83789431?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164501280416780366574110%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=164501280416780366574110&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-2-83789431.pc_search_insert_ulrmf&utm_term=C%E8%AF%AD%E8%A8%80FIFO&spm=1018.2226.3001.4187 但是该代码存在一些BUG,BUG具体表现在:例如定义了10个字节的FIFO,写入10个字节,读出6个字节,再写入6个字节后就会发生溢出,导致数据出错。所以笔者再原作者的基础上对代码进行了一些修改,修改如下:
FIFO.c文件
#include "FIFO.h"
/**
* @brief fifo结构
*/
typedef struct
{
int ptr_write;//写入量
int ptr_read;//读取量
bool is_full;//FIFO状态
int item_sum;// fifo中存储的元素数,不是字节大小
int item_size;// 元素大小.单位: 字节
void *fifo_ptr; //FIFO地址
} Fifo;
/**
* @brief 创建fifo
* @param item_sum:fifo中元素数.注意不是字节数
* @param item_size: 元素大小.单位: 字节
* @return fifo索引
*/
int fifo_create(int item_sum, int item_size)
{
Fifo *fifo = (Fifo *)malloc(sizeof(Fifo));
fifo->item_sum = item_sum;
fifo->item_size = item_size;
fifo->ptr_write = 0;
fifo->ptr_read = 0;
fifo->is_full = false;
fifo->fifo_ptr = (void *)malloc(item_sum * item_size);
return (int)fifo;
}
/**
* @brief 删除fifo
* @param fifo_index: fifo索引
*/
void fifo_delete(int fifo_index)
{
Fifo *fifo = (Fifo *)fifo_index;
free(fifo->fifo_ptr);
fifo->fifo_ptr = NULL;
free(fifo);
fifo = NULL;
}
/**
* @brief fifo检查是否可以写入
* @param fifo_index: fifo索引
* @retval false:不可以写入.true:可以写入
*/
bool fifo_writeable(int fifo_index)
{
Fifo *fifo = (Fifo *)fifo_index;
return !fifo->is_full;
}
/**
* @brief fifo写入
* @param fifo_index: fifo索引
* @param frame:写入元素指针
* @return false:失败.true:成功
*/
bool fifo_write(int fifo_index, void *data)
{
Fifo *fifo = (Fifo *)fifo_index;
if (fifo->is_full)//是否能写入
{
return false;
}
memcpy((char *)(fifo->fifo_ptr) + fifo->ptr_write * fifo->item_size, data, fifo->item_size);//将数据复制到FIFO中
fifo->ptr_write++;//写入量+1
if (fifo->ptr_write >= fifo->item_sum)
{
fifo->is_full = true;//FIFO满
}
return true;
}
/**
* @brief fifo批量写入
* @param fifo_index: fifo索引
* @param data: 写入元素指针
* @param item_num:写入的元素数目
* @return false:失败.true:成功
*/
bool fifo_write_batch(int fifo_index, void *data, int item_num)
{
Fifo *fifo = (Fifo *)fifo_index;
if (fifo_writeable_item_count((int)fifo) < item_num)
{
return false;
}
memcpy((char *)(fifo->fifo_ptr) + fifo->ptr_write * fifo->item_size, data, fifo->item_size * item_num);
fifo->ptr_write += item_num;
if (fifo->ptr_write >= fifo->item_sum)
{
fifo->is_full = true;//FIFO满
}
return true;
}
/**
* @brief fifo检查是否可以读取
* @param fifo_index: fifo索引
* @return false:不可以读取.true:可以读取
*/
bool fifo_readable(int fifo_index)
{
Fifo *fifo = (Fifo *)fifo_index;
if (fifo->ptr_write == 0)//写入量为0 不可读取
{
return false;
}
return true;
}
/**
* @brief fifo读取
* @param fifo_index: fifo索引
* @param data: 读取的数据
* @return false: 失败.true: 成功
*/
bool fifo_read(int fifo_index, void *data)
{
Fifo *fifo = (Fifo *)fifo_index;
if (fifo->ptr_write == fifo->ptr_read && !fifo->is_full)
{
return false;
}
memcpy(data, (char *)(fifo->fifo_ptr), fifo->item_size);
fifo->ptr_read ++;
//-----------------------------------------//
memcpy((char *)(fifo->fifo_ptr),(char *)(fifo->fifo_ptr) + fifo->ptr_read * fifo->item_size,(fifo->item_sum - fifo->ptr_read));//整体数据左对齐
fifo->ptr_write -= fifo->ptr_read;//写数据量-=读出的数据量
fifo->ptr_read = 0;//读出量清零
//========================================//
fifo->is_full = false;
return true;
}
/**
* @brief fifo批量读取
* @param fifo_index: fifo索引
* @param data: 读取的数据
* @param item_num:读取的元素数
* @return false: 失败.true: 成功
*/
bool fifo_read_batch(int fifo_index, void *data, int item_num)
{
Fifo *fifo = (Fifo *)fifo_index;
if (fifo_readable_item_count((int)fifo) < item_num)
{
return false;
}
memcpy(data, (char *)(fifo->fifo_ptr), fifo->item_size * item_num);
fifo->ptr_read += item_num;
//-----------------------------------------//
memcpy((char *)(fifo->fifo_ptr),(char *)(fifo->fifo_ptr) + fifo->ptr_read * fifo->item_size,(fifo->item_sum - fifo->ptr_read));//整体数据左对齐
fifo->ptr_write -= fifo->ptr_read;//写数据量-=读出的数据量
fifo->ptr_read = 0;//读出量清零
//========================================//
fifo->is_full = false;
return true;
}
/**
* @brief fifo可读的元素数
* @param fifo_index: fifo索引
* @return 元素数
*/
int fifo_readable_item_count(int fifo_index)
{
Fifo *fifo = (Fifo *)fifo_index;
if (fifo->is_full)
{
return fifo->item_sum;
}
else
{
return fifo->ptr_write;
}
}
/**
* @brief fifo可写的元素数
* @param fifo_index: fifo索引
* @return 元素数
*/
int fifo_writeable_item_count(int fifo_index)
{
Fifo *fifo = (Fifo *)fifo_index;
if (fifo->is_full)
{
return 0;
}
else
{
return fifo->item_sum - fifo->ptr_write;
}
}
int FIFO1;
int Count;
bool error;
unsigned char linshi[] = "lingshishuju";
unsigned char ceshi[]="1234567890";
unsigned char g_cEE[11];
void TestFifo()
{
FIFO1 = fifo_create(10,1);//创建FIFO 深度10 字节1
error = fifo_writeable(FIFO1);//是否可以写入
error = fifo_readable(FIFO1);//是否可读
Count = fifo_writeable_item_count(FIFO1);//可写入的数据量
fifo_write(FIFO1, ceshi);//写入数据
fifo_write(FIFO1, &ceshi[1]);//写入数据
error = fifo_readable(FIFO1);//是否可读
Count = fifo_readable_item_count(FIFO1);//可读数据量
fifo_read(FIFO1,g_cEE);//读
fifo_write(FIFO1, &ceshi[2]);//写入数据
fifo_read(FIFO1,&g_cEE[1]);//读
fifo_read(FIFO1,&g_cEE[2]);//读
//批量
Count = fifo_writeable_item_count(FIFO1);//可写入的数据量
error = fifo_write_batch(FIFO1,linshi,Count);//批量写入
error = fifo_read_batch(FIFO1,g_cEE,3);//批量读
error = fifo_writeable(FIFO1);//是否可以写入
Count = fifo_writeable_item_count(FIFO1);//可写入的数据量
error = fifo_write_batch(FIFO1,linshi,Count);//批量写入
Count = fifo_readable_item_count(FIFO1);//可读数据量
error = fifo_read_batch(FIFO1,g_cEE,Count);//批量读
error = fifo_writeable(FIFO1);//是否可以写入
error = fifo_readable(FIFO1);//是否可读
}
FIFO.h文件
#ifndef _FIFO_H_
#define _FIFO_H_
#include "stdlib.h"
#include "stdio.h"
#include "stdarg.h"
#include "stdbool.h"
#include "string.h"
#include "math.h"
/**
* @brief 创建fifo
* @param item_sum:fifo中元素数.注意不是字节数
* @param item_size: 元素大小.单位: 字节
* @return fifo索引
*/
extern int fifo_create(int item_sum, int item_size);
/**
* @brief 删除fifo
* @param fifo_index: fifo索引
*/
extern void fifo_delete(int fifo_index);
/**
* @brief fifo检查是否可以写入
* @param fifo_index: fifo索引
* @retval false:不可以写入.true:可以写入
*/
extern bool fifo_writeable(int fifo_index);
/**
* @brief fifo写入
* @param fifo_index: fifo索引
* @param frame:写入元素指针
* @return false:失败.true:成功
*/
extern bool fifo_write(int fifo_index, void *data);
/**
* @brief fifo批量写入
* @param fifo_index: fifo索引
* @param data: 写入元素指针
* @param @param item_num:写入的元素数目
* @return false:失败.true:成功
*/
extern bool fifo_write_batch(int fifo_index, void *data, int item_num);
/**
* @brief fifo检查是否可以读取
* @param fifo_index: fifo索引
* @return false:不可以读取.true:可以读取
*/
extern bool fifo_readable(int fifo_index);
/**
* @brief fifo读取
* @param fifo_index: fifo索引
* @param data: 读取的数据
* @return false: 失败.true: 成功
*/
extern bool fifo_read(int fifo_index, void *data);
/**
* @brief fifo批量读取
* @param fifo_index: fifo索引
* @param data: 读取的数据
* @param item_num:读取的元素数
* @return false: 失败.true: 成功
*/
extern bool fifo_read_batch(int fifo_index, void *data, int item_num);
/**
* @brief fifo可读的元素数
* @param fifo_index: fifo索引
* @return 元素数
*/
extern int fifo_readable_item_count(int fifo_index);
/**
* @brief fifo可写的元素数
* @param fifo_index: fifo索引
* @return 元素数
*/
extern int fifo_writeable_item_count(int fifo_index);
extern void TestFifo(void);
#endif
上述代码中,TestFifo()函数为FIFO的功能测试代码。
最后,感谢该代码原作者,为我后续开发节省了很多时间。