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

相关推荐
披着羊皮不是狼1 天前
(7)为 RAG 系统接入 Redis Stack 实现向量持久化
数据库·redis·缓存
難釋懷1 天前
数据同步策略
缓存
程序员潘子1 天前
【保姆级教程】B 站缓存 m4s 文件转 MP4,无损合成一行命令搞定
缓存·ffmpeg·ffmpeg\
Micro麦可乐1 天前
Redis只会用来做缓存?解锁Redis非缓存的九个应用场景,90%程序员不知道的隐藏技能
数据库·redis·缓存·消息队列·分布式锁·延迟队列·布隆过滤器
键盘鼓手苏苏1 天前
Flutter 三方库 persistent_cache_simple 的鸿蒙化适配指南 - 实现具备磁盘溢出淘汰与极简 API 的本地持久化缓存、支持端侧资源异步落地与状态秒开实战
flutter·缓存·harmonyos
21号 11 天前
10.Redis 缓存
数据库·redis·缓存
从零开始的-CodeNinja之路1 天前
【Redis】Redis 缓存应用、淘汰机制—(四)
java·redis·缓存
星辰徐哥1 天前
CDN工作原理:节点缓存、智能调度,减少跨网传输延迟
服务器·缓存·php
星辰徐哥1 天前
ARP缓存表:作用、查看方法与刷新技巧
开发语言·缓存·php
Jul1en_2 天前
【Redis】String 类型命令、编码方式与应用场景
数据库·redis·缓存