C语言实现FIFO代码

       最近笔者在做一个小项目的时候需要使用FIFO来做为数据的缓存。但笔者使用的芯片并没有硬件的FIFO管理器,所以需要使用C语言来用软件做一个FIFO的管理。

       开始引用了这位大神的一些代码

(5条消息) C语言实现标准FIFO_jdh99的专栏-CSDN博客_c fifoicon-default.png?t=M1FBhttps://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的功能测试代码。

       最后,感谢该代码原作者,为我后续开发节省了很多时间。

  • 8
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值