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

相关推荐
草履虫建模3 小时前
Redis:高性能内存数据库与缓存利器
java·数据库·spring boot·redis·分布式·mysql·缓存
程序猿ZhangSir5 小时前
Redis 缓存进阶篇,缓存真实数据和缓存文件指针最佳实现?如何选择?
数据库·redis·缓存
段帅龙呀13 小时前
Redis构建缓存服务器
服务器·redis·缓存
夜斗小神社1 天前
【黑马点评】(二)缓存
缓存
Hello.Reader1 天前
Redis 延迟监控深度指南
数据库·redis·缓存
Hello.Reader2 天前
Redis 延迟排查与优化全攻略
数据库·redis·缓存
在肯德基吃麻辣烫2 天前
《Redis》缓存与分布式锁
redis·分布式·缓存
先睡2 天前
Redis的缓存击穿和缓存雪崩
redis·spring·缓存
CodeWithMe3 天前
【Note】《深入理解Linux内核》 Chapter 15 :深入理解 Linux 页缓存
linux·spring·缓存
大春儿的试验田3 天前
高并发收藏功能设计:Redis异步同步与定时补偿机制详解
java·数据库·redis·学习·缓存