本人在实际开发中多次用到串口的循环buffer,最开始在网上搜索了相关文章和资料,感觉通用性不是很高。自己也写过fifo,感觉还是过于臃肿。一直想找个完美的循环buffer。在看linux内核代码时,发现内核里面也经常使用fifo。linux内核代码是最优美、精简的,高效的代码。真是“山穷水尽疑无路,柳暗花明又一村”。特意移植除出来,希望对大家有用。代码设计的相当的巧妙~~~
头文件:
/*******************************************************************************
* @File : fifo.h
* @Author : cqx
* @Version : V0.0.1
* @Date : 29-november-2016
* @Brief : This file provides all the fifo functions.
********************************************************************************
* @Attention:
* Non
*
*******************************************************************************/
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef _FIFO_H
#define _FIFO_H
#include #ifdef __cplusplus extern "C" { #endif /* Includes ------------------------------------------------------------------*/ /* Define --------------------------------------------------------------------*/ #ifndef min #define min(a, b) (((a) < (b)) ? (a) : (b)) #endif #define is_power_of_2(x) ((x) != 0 && (((x) & ((x) - 1)) == 0)) /* Private typedef -----------------------------------------------------------*/ struct fifo { unsigned int in; unsigned int out; unsigned int mask; unsigned char *data; }; /* Function prototypes -------------------------------------------------------*/ extern unsigned int fifo_used(struct fifo *fifo); extern signed int fifo_alloc(struct fifo *fifo, unsigned int size); extern void fifo_free(struct fifo *fifo); extern int fifo_init(struct fifo *fifo, unsigned char *buffer, unsigned int size); extern unsigned int fifo_in(struct fifo *fifo, unsigned char *buf, unsigned int len); extern unsigned int fifo_out(struct fifo *fifo, unsigned char *buf, unsigned int len); #ifdef __cplusplus } #endif #endif 源文件: /****************************************************************************** * @File : ringbuffer.c * @Author : cqx * @Version : V0.0.1 * @Date : 29-november-2016 * @Brief : This file provides all the fifo functions. ****************************************************************************** * @Attention: * * ******************************************************************************/ /* Includes -----------------------------------------------------------------*/ #include "fifo.h" #include "stdlib.h" #include "string.h" #include "includes.h" /* Variables -----------------------------------------------------------------*/ /* Private functions ---------------------------------------------------------*/ /******************************************************************************/ /* * internal helper to calculate the unused elements in a fifo */ static __inline unsigned int fifo_unused(struct fifo *fifo) { return (fifo->mask + 1) - (fifo->in - fifo->out); } unsigned int fifo_used(struct fifo *fifo) { return (fifo->in - fifo->out); } signed int fifo_alloc(struct fifo *fifo, unsigned int size) { /* * round down to the next power of 2, since our 'let the indices * wrap' technique works only in this case. */ if (!is_power_of_2(size)) return -1; fifo->in = 1; fifo->out = 1; if (size < 2){ fifo->data = NULL; fifo->mask = 0; return -1; } fifo->data = malloc(size); if (!fifo->data){ fifo->mask = 0; return -1; } fifo->mask = size - 1; return 0; } void fifo_free(struct fifo *fifo) { free(fifo->data); fifo->in = 0; fifo->out = 0; fifo->data = NULL; fifo->mask = 0; } int fifo_init(struct fifo *fifo, unsigned char *buffer, unsigned int size) { if (!is_power_of_2(size)) return -1; fifo->in = 0; fifo->out = 0; fifo->data = buffer; if (size < 2) { fifo->mask = 0; return -1; } fifo->mask = size - 1; return 0; } static void fifo_copy_in(struct fifo *fifo, unsigned char *src, unsigned int len, unsigned int off) { unsigned int size = fifo->mask + 1; unsigned int l; off &= fifo->mask; l = min(len, size - off); memcpy(fifo->data + off, src, l); memcpy(fifo->data, src + l, len - l); } unsigned int fifo_in(struct fifo *fifo, unsigned char *buf, unsigned int len) { unsigned int l; l = fifo_unused(fifo); if (len > l) len = l; fifo_copy_in(fifo, buf, len, fifo->in); fifo->in += len; return len; } static void fifo_copy_out(struct fifo *fifo, unsigned char *dst, unsigned int len, unsigned int off) { unsigned int size = fifo->mask + 1; unsigned int l; off &= fifo->mask; l = min(len, size - off); memcpy(dst, fifo->data + off, l); memcpy(dst + l, fifo->data, len - l); } unsigned int fifo_out_peek(struct fifo *fifo, unsigned char *buf, unsigned int len) { unsigned int l; l = fifo->in - fifo->out; if (len > l) len = l; fifo_copy_out(fifo, buf, len, fifo->out); return len; } unsigned int fifo_out(struct fifo *fifo, unsigned char *buf, unsigned int len) { len = fifo_out_peek(fifo, buf, len); fifo->out += len; return len; }
上一篇:基于STM32的串口数据环形缓冲队列
下一篇:stm32F4 串口DMA+环形缓冲区的实现
推荐阅读最新更新时间:2024-11-13 12:16
设计资源 培训 开发板 精华推荐
- esp32_vision_v3.3_st7789_rel
- MIC2601YML EV,用于有源天线的 18V DC 到 DC 单输出电源的评估板
- DC188A-B,基于 LT1374CS8-SYNC 的演示板,4.5A 开关,500kHz,5.5V 至 25VIN,3.3V 或 5V @ 4A 输出,SO8 封装降压稳压器
- 使用 2 速时钟的 7.5us 模数转换器
- TC78S121FTG/FNG 用于 TC78S121FNG 步进电机驱动器的应用说明
- NSI45015WT1G 大电流 LED 灯串的典型应用
- 使用 Microchip Technology 的 PIC16C782 的参考设计
- LM2596升降压电路(附仿真图)
- DC957A,使用 LTC3785、3.3V、3.0A 高效率同步降压-升压转换器的演示板
- LTC3838EUHF-1 4.5V 至 14V 输入、1.2V/20A 和 1.5V/20A 双路输出、300kHz、RSENSE、降压转换器的典型应用电路