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

相关推荐
栗子~~6 小时前
集成 jacoco 插件,查看单元测试覆盖率
缓存·单元测试·log4j
Hello.Reader14 小时前
Redis热点数据管理全解析:从MySQL同步到高效缓存的完整解决方案
redis·mysql·缓存
麦香--老农16 小时前
windows 钉钉缓存路径不能修改 默认C盘解决方案
缓存·钉钉
C++忠实粉丝16 小时前
Redis 介绍和安装
数据库·redis·缓存
丰云17 小时前
一个简单封装的的nodejs缓存对象
缓存·node.js
Oneforlove_twoforjob17 小时前
【Java基础面试题025】什么是Java的Integer缓存池?
java·开发语言·缓存
泰伦闲鱼17 小时前
nestjs:GET REQUEST 缓存问题
服务器·前端·缓存·node.js·nestjs
ClouGence17 小时前
Redis 到 Redis 数据迁移同步
数据库·redis·缓存
弗罗里达老大爷19 小时前
Redis
数据库·redis·缓存
别这么骄傲20 小时前
lookup join 使用缓存参数和不使用缓存参数的执行前后对比
缓存