69、FIFO缓存发送数据(先入先出)

本文件用于设备数据收发缓冲使用,本fifo采用申请2片内存区,交替使用,写0时1读,写1时0读,避免同时使用相同内存块

fifo区域采用头尾相连的方式循环覆盖,分别记录读和写的位置,相等则数据为空,否则说明有数据

此方法的弊端为,当FIFO输入数据速度大于输出,则会引起数据丢失,若只是短时间数据量大则可以通过分配较大空间避免此问题

内存区使用动态分配

fifo_driver.h

c 复制代码
#ifndef _fifo_driver_H_
#define _fifo_driver_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "stdint.h"
#include "stdio.h"
#define dFIFO_LOG(...) printf(__VA_ARGS__) //日志输出

typedef struct
{
    uint8_t state;//fifo状态:0--不可用,!0--可用
    uint32_t size;//fifo分配的缓冲大小
    uint32_t read[2];//读取位置
    uint32_t write[2];//写入位置
    uint8_t id;//当前使用的缓冲区
    uint8_t *pbuf[2];//缓冲区
    void (*SendData)(uint8_t *pData,uint32_t size);//FIFI输出数据函数
}fifo_StructDef;//数据缓冲句柄

int fifo_init(fifo_StructDef *p,uint32_t size,void (*SendData)(uint8_t *pData,uint32_t size));
void fifo_DeInit(fifo_StructDef *p);
void fifo_clear(fifo_StructDef *p);
int fifo_in(fifo_StructDef *p,uint8_t *pdata,uint32_t size);
int fifo_out(fifo_StructDef *p);

#ifdef __cplusplus
}
#endif
#endif

fifo_driver.c

c 复制代码
/**********************************************************************
*file:FIFO先入先出队列驱动文件
*author:残梦
*versions:V1.0
*date:2024.3.22
*note:
本文件用于设备数据收发缓冲使用,本fifo采用申请2片内存区,交替使用,写0时1读,写1时0读,避免同时使用相同内存块
fifo区域采用头尾相连的方式循环覆盖,分别记录读和写的位置,相等则数据为空,否则说明有数据
此方法的弊端为,当FIFO输入数据速度大于输出,则会引起数据丢失,若只是短时间数据量大则可以通过分配较大空间避免此问题
使用方法:
#include "fifo_driver.h"
static fifo_StructDef fifo;
void SendData(uint8_t *pData,uint32_t size)
{
    //实现自己的底层发送数据
    //所有输入fifo的数据都通过此函数实际发送输出
}
void main(void)
{
    uint8_t data = 0xFF;

    if(fifo(&fifo,1024,SendData) < 0){printf("初始化失败\n");return}

    for(uint32_t i = 0;i < 1000;i++)
    {
        fifo_in(&fifo,&data,1);//向fifo输入数据
        if(i%1024 == 0)fifo_out(&fifo);//发送数据
    }

    fifo_DeInit(&fifo);
}


**********************************************************************/
#include "fifo_driver.h"
#include "string.h"
#include "stdlib.h"

/****************************************
@function:fifo初始化资源
@param:p--fifo句柄
    size--分配fifo大小;注意实际消耗内存等于size*2字节
    SendData--数据发送函数
@return:
    0:成功
    -1:参数错误
    -2:分配内存失败
@note:
****************************************/
int fifo_init(fifo_StructDef *p,uint32_t size,void (*SendData)(uint8_t *pData,uint32_t size))
{
    if((p == NULL) || (size < 1) || (SendData == NULL))return -1;
    p->state = 0;
    p->pbuf[0] = (uint8_t *)malloc(size);
    p->pbuf[1] = (uint8_t *)malloc(size);
	if ((p->pbuf[0] == NULL) || (p->pbuf[1] == NULL))
	{
        fifo_DeInit(p);
		dFIFO_LOG("Error[%s-line:%d]:memory allocation failure\n", __func__, __LINE__);
		return -2;
	}
    p->size = size;
    p->read[0] = p->read[1] = 0;
    p->write[0] = p->write[1] = 0;
    p->id = 0;
    p->SendData = SendData;
    p->state = 1;
    return 0;
}

/****************************************
@function:fifo资源销毁
@param:p--fifo句柄
@return:void
@note:
****************************************/
void fifo_DeInit(fifo_StructDef *p)
{
    if(p == NULL)return;
    p->state = 0;
    if(p->pbuf[0] != NULL)free(p->pbuf[0]);
    p->pbuf[0] = NULL;
    if(p->pbuf[1] != NULL)free(p->pbuf[1]);
    p->pbuf[1] = NULL;
    p->size = 0;
    p->read[0] = p->read[1] = 0;
    p->write[0] = p->write[1] = 0;
    p->id = 0;
    p->SendData = NULL;
}

/****************************************
@function:fifo清空
@param:p--fifo句柄
@return:void
@note:
****************************************/
void fifo_clear(fifo_StructDef *p)
{
    if(p == NULL)return;
    p->state = 0;
    p->id = 0;    
    p->read[0] = p->read[1] = 0;
    p->write[0] = p->write[1] = 0;
    p->state = 1;
}

/****************************************
@function:fifo数据输入
@param:
    p--fifo句柄
    pdata--数据
    size--字节数
@return:
    0:成功
    -1:参数错误
    -2:写入失败
@note:
****************************************/
int fifo_in(fifo_StructDef *p,uint8_t *pData,uint32_t size)
{
    uint32_t num = 0,pos = 0;
    uint8_t id = 0;

    if((pData == NULL) || (size == 0) || (p == NULL))return -1;
    if(p->state == 0)return -2;

    id = p->id;
    while(pos < size)
    {
        num = (size > (p->size - p->write[id]))?(p->size - p->write[id]):(size-pos);
        memcpy(&(p->pbuf[id][p->write[id]]),(pData + pos),num);
        p->write[id] += num;
        pos += num;
        if(p->write[id] >= p->size)p->write[id] = 0;
    }
    return 0;
}

/****************************************
@function:fifo数据输出
@param:p--fifo句柄
@return:void
@note:
    0:输出成功
    -1:参数错误
    -2:fifo状态不可用
    -3:fifo空
****************************************/
int fifo_out(fifo_StructDef *p)
{
    uint8_t id = 0;
    uint32_t len = 0;

    if(p == NULL)return -1;
    if(p->state == 0)return -2;
    if(p->read[p->id] == p->write[p->id])return -3;
    id = p->id;
    p->id = id?0:1;
    if(p->read[id] < p->write[id])
    {
        len = p->write[id] - p->read[id];
        p->SendData(&(p->pbuf[id][p->read[id]]),len);
        p->read[id] += len;
    }
    else if(p->read[id] > p->write[id])
    {
        len = p->size - p->read[id];
        p->SendData(&(p->pbuf[id][p->read[id]]),len);
        len = p->write[id];
        p->SendData(&(p->pbuf[id][0]),len);
        p->read[id] = len;
    }
    return 0;
}

使用方法:

c 复制代码
#include "fifo_driver.h"
static fifo_StructDef fifo;
void SendData(uint8_t *pData,uint32_t size)
{
    //实现自己的底层发送数据
    //所有输入fifo的数据都通过此函数实际发送输出
}
void main(void)
{
    uint8_t data = 0xFF;

    if(fifo(&fifo,1024,SendData) < 0){printf("初始化失败\n");return}

    for(uint32_t i = 0;i < 1000;i++)
    {
        fifo_in(&fifo,&data,1);//向fifo输入数据
        if(i%1024 == 0)fifo_out(&fifo);//发送数据
    }

    fifo_DeInit(&fifo);
}

文件下载:

链接:https://pan.baidu.com/s/1-u8w19RiyPeCtVQjX8hzgw

提取码:zxo1

相关推荐
@淡 定7 小时前
Redis热点Key独立集群实现方案
数据库·redis·缓存
longson.12 小时前
怎样避免空间碎片而且高效的分配空间
嵌入式硬件·缓存
不染尘.12 小时前
进程切换和线程调度
linux·数据结构·windows·缓存
xixixi7777714 小时前
CDN(内容分发网络)——缓存和分发网站、应用程序、视频等内容,以提高用户访问速度和稳定性,减少网络延迟和拥塞,同时减轻源服务器的压力
网络·缓存·架构·系统架构·cdn·业务·内容分发网络
ANnianStriver14 小时前
redis安装包方式下载安装
数据库·redis·缓存
Psycho_MrZhang18 小时前
页缓存技术(PageCache/sendfile/mmap)
缓存
步步为营DotNet19 小时前
深度解析.NET中MemoryCache:高效缓存策略与性能优化的关键
缓存·性能优化·.net
wangbing112520 小时前
redis的存储问题
数据库·redis·缓存
Benny的老巢1 天前
Chrome 缓存迁移教程:5种方法解决 C 盘空间不足问题(2026年最新)
c语言·chrome·缓存
oMcLin1 天前
如何在 RHEL 8 上搭建高效的 Redis 集群,支持跨地域的数据同步与低延迟缓存访问?
数据库·redis·缓存