单片机
返回首页

stm32实用循环buffer

2019-08-26 来源:eefocus

本人在实际开发中多次用到串口的循环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;

}


进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 红外线探测报警器

  • 短波AM发射器电路设计图

  • RS-485基础知识:处理空闲总线条件的两种常见方法

  • 如何调制IC555振荡器

  • 基于ICL296的大电流开关稳压器电源电路

  • 基于TDA2003的简单低功耗汽车立体声放大器电路

    相关电子头条文章