忙着毕设,很久没有写文章了,终于答辩完了,得了个校优秀毕业设计。毕设做的是个智能接口模块,用一周时间入门了,MC9S12XEP100的开发,又用一周时间入门了uC/OS-II嵌入式操作系统,在做毕设的过程中学到了很多,现在把一些工具发上来分享。
这里分享一个自己用纯C实现的环形缓冲区。环形缓冲区有很多作用,比如嵌入式中的通信可以用环形缓冲区作为信道,一个线程往里放字节,一个线程取字节进行处理,只要保证取的速度大于读的速度,就可以保证通信顺畅进行,不丢一个字节。
简要介绍:
环形缓冲区其实就是一个队列,里头的元素是先入先出的,但是因为其(逻辑上)是环形的,所以不需要像很多队列的实现那样在内部元素变动的时候需要移动内部剩下的元素。这样就使元素出队入队的时间复杂度只有O(1)。具体实现一般有链表和数组两种方法,当不能确定需要的缓冲区大小时使用链表较好,能确定时使用数组可以节省很多动态分配内存的开销。
在嵌入式开发中,一般不动态分配内存,而是使用静态分配的数组。所以这里我使用数组实现了环形缓冲区,为了能够在不同的程序中复用代码,使用结构体模拟了面向对象编程,这样就可以用一套代码管理不同的缓冲区了。
废话不多说,直接上代码。以下是.h 文件:
/*
*********************************************************************************************************
*
*
* RingQueueStruct
* 环形队列结构
*
* File : RingQueue.h
* By : Lin Shijun(http://blog.csdn.net/lin_strong)
* Date : 2018/02/23
* version: V1.2
* NOTE(s): 这段程序用来对一个给定的缓冲区进行模拟环形队列的管理
* 程序本身不会自动分配缓冲区空间,用户需要自己负责分配空间,并且要保证不直接访问缓存区
* // 在某处分配内存空间
* RQTYPE buffer[BUFFER_SIZE];
* RING_QUEUE que,*ptr_que;
* unsigned char err;
* // 初始化
* ptr_que = RingQueueInit(&que,buffer,BUFFER_SIZE,&err);
* if(err == RQ_ERR_NONE ){
* // 初始化成功,使用其他函数
* }
* History : 2017/04/25 the original version of RingQueueStruct.
* 2017/10/16 put functions used frequently,RingQueueIn and RingQueueOut, in non-banked address;
* modify single line function RingQueueIsEmpty and RingQueueIsFull to marco function;
* to get better efficiency.
* 2018/02/23 1.add the marco(RQ_ARGUMENT_CHECK_EN) to controll argument check so user can save
* more code.
* 2.add the ADDRESSING MODE so the buffer can be defined in banked addressing area.
*********************************************************************************************************
*/
#ifndef RING_QUEUE_H
#define RING_QUEUE_H
/*
********************************************************************************************
* MISCELLANEOUS
********************************************************************************************
*/
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
/*
*********************************************************************************************************
* ADDRESSING MODE 寻址模式
*********************************************************************************************************
*/
// uncomment the corresponding line to select the addressing mode to the buffer of RingQueue module.
// if you don't understand. Just use the extended addressing mode
// 取消对应行的注释以选择环形缓冲区模块访问缓冲区时使用的寻址方式
// 如果你不知道这是什么意思的话,那就用扩展寻址就行了,这是默认的方式
// extended addressing mode 扩展区寻址(默认)
#define RQ_ADDRESSING_MODE
// banked RAM addressing mode RAM分页区寻址
//#define RQ_ADDRESSING_MODE __rptr
// global addressing mode 全局寻址
//#define RQ_ADDRESSING_MODE __far
/*
*********************************************************************************************************
* CONFIGURATION 配置
*********************************************************************************************************
*/
#define RQ_ARGUMENT_CHECK_EN TRUE // TRUE: arguments will be checked, however,this will
// cost a little code volume.
/*
******************************************************************************