科讯网站模版网,如何做网站拓扑结构图,云南建设厅和网站,手机网站横向切换之前写的环行缓冲区文章柔性数组和环形队列之间的故事C语言#xff0c;环形队列循环缓冲区是嵌入式软件工程师在日常开发过程中的关键组件。多年来#xff0c;互联网上出现了许多不同的循环缓冲区实现和示例。我非常喜欢这个模块#xff0c;可以GitHub上找到这个开源的 CBUF… 之前写的环行缓冲区文章柔性数组和环形队列之间的故事C语言环形队列循环缓冲区是嵌入式软件工程师在日常开发过程中的关键组件。多年来互联网上出现了许多不同的循环缓冲区实现和示例。我非常喜欢这个模块可以GitHub上找到这个开源的 CBUF.h 模块。地址https://github.com/barraq/BRBrain/blob/master/firmware/CBUF.hCBUF.h 模块使用宏实现循环缓冲区具体源码如下所示#if !defined( CBUF_H )
#define CBUF_H /** Include Guard *//* ---- Include Files ---------------------------------------------------- *//* ---- Constants and Types ---------------------------------------------- *//**
* Initializes the circular buffer for use.
*/ #define CBUF_Init( cbuf ) cbuf.m_getIdx cbuf.m_putIdx 0/**
* Returns the number of elements which are currently contained in the * circular buffer.
*/#define CBUF_Len( cbuf ) ((typeof( cbuf.m_putIdx ))(( cbuf.m_putIdx ) - ( cbuf.m_getIdx )))/**
* Appends an element to the end of the circular buffer
*/#define CBUF_Push( cbuf, elem ) (cbuf.m_entry)[ cbuf.m_putIdx (( cbuf##_SIZE ) - 1 )] (elem)/**
* Retrieves an element from the beginning of the circular buffer
*/#define CBUF_Pop( cbuf ) (cbuf.m_entry)[ cbuf.m_getIdx (( cbuf##_SIZE ) - 1 )]/**
* Retrieves the ith element from the beginning of the circular buffer
*/#define CBUF_Get( cbuf, idx ) (cbuf.m_entry)[( cbuf.m_getIdx idx ) (( cbuf##_SIZE ) - 1 )]/**
* Retrieves the ith element from the end of the circular buffer
*/#define CBUF_GetEnd( cbuf, idx ) (cbuf.m_entry)[( cbuf.m_putIdx - idx - 1 ) (( cbuf##_SIZE ) - 1 )]/**
* Determines if the circular buffer is empty
*/#define CBUF_IsEmpty( cbuf ) ( CBUF_Len( cbuf ) 0 )/**
* Determines if the circular buffer is full.
*/#define CBUF_IsFull( cbuf ) ( CBUF_Len( cbuf ) ( cbuf##_SIZE ))/**
* Determines if the circular buffer is currenly overflowed or underflowed.
*/#define CBUF_Error( cbuf ) ( CBUF_Len( cbuf ) cbuf##_SIZE )#if defined( __cplusplus )template class IndexType, unsigned Size, class EntryType
class CBUF
{
public:CBUF(){m_getIdx m_putIdx 0;}IndexType Len() const { return m_putIdx - m_getIdx; }bool IsEmpty() const { return Len() 0; }bool IsFull() const { return Len() Size; }bool Error() const { return Len() Size; }void Push( EntryType val ) {m_entry[ m_putIdx ( Size - 1 )] val;}EntryType Pop(){return m_entry[ m_getIdx ( Size - 1 )];}private:volatile IndexType m_getIdx;volatile IndexType m_putIdx;EntryType m_entry[ Size ];};#endif // __cplusplus/* ---- Variable Externs ------------------------------------------------- */
/* ---- Function Prototypes ---------------------------------------------- *//** } */#endif // CBUF_H现在一般我不喜欢以这种方式使用宏但实现已被证明是快速、高效且工作相对良好的这是很难争论的。循环缓冲区的设置非常简单。首先需要定义循环缓冲区的大小。这是通过定义宏 myQ_SIZE 来完成的同时记住缓冲区大小需要是 2 的幂。然后通过创建一个 myQ 类型的变量来声明循环缓冲区。例如如果 myQ_SIZE 定义为 64 字节则可以定义 UART 的发送和接收缓冲区如下面的图 1 所示。图 1 – 定义循环缓冲区在此示例中myQ 被定义为静态以限制缓冲区的范围并声明为易失性因为它们在中断内被修改。定义循环缓冲区只是第一步。为了分配缓冲区必须将这些变量传递给 CBUF_INIT 宏如下图 2 所示。图 2 – 缓冲区初始化除了这个初始设置之外缓冲区相当简单且易于使用。例如可以使用 CBUF_PUSH 将通过串行接口接收 UART接收的字符推送到循环缓冲区如图 3 所示。图 3 – 推入缓冲区开发人员不仅希望将数据推送到循环缓冲区上还希望从缓冲区弹出或获取数据。看到这一点的一个简单示例是需要获取字符并通过 UART 传输的串行发送器。图 4 中可以看到一个示例传输函数。图 4 – 从缓冲区弹出数据在健壮的应用程序中还应检查循环缓冲区长度和溢出状态。CBUF 模块确实提供了能够检查这些重要指标的宏。要记住的一个重要问题是如果需要对 CBUF 本身进行任何调试这是不可能的。无法为宏设置断点因此如果出现问题则需要对模块进行功能化以逐步执行和调试。多年来使用这个模块虽然我没有发现任何问题。循环缓冲区是在嵌入式系统中与串行设备通信的一个重要方面。循环缓冲区也很好理解应该创建它们以便它们可以模块化并从一个应用程序到下一个应用程序重复使用。到目前为止CBUF 模块已被证明是这样一个模块所以在这里我强烈推荐一下这个模块。好了今天的文章就到这里我们下期再见。再贴上代码的注释部分/****************************************************************************
*
* Since this code originated from code which is public domain, I
* hereby declare this code to be public domain as well.
*
****************************************************************************/
/**
*
* file CBUF.h
*
* brief This file contains global definitions for circular buffer
* manipulation.
*
* These macros implement a circular buffer which employs get and put
* pointers, in such a way that mutual exclusion is not required
* (assumes one reader one writer).
*
* It requires that the circular buffer size be a power of two, and the
* size of the buffer needs to smaller than the index. So an 8 bit index
* supports a circular buffer upto ( 1 7 ) 128 entries, and a 16 bit index
* supports a circular buffer upto ( 1 15 ) 32768 entries.
*
* The basis for these routines came from an article in Jack Ganssles
* Embedded Muse: http://www.ganssle.com/tem/tem110.pdf
*
* In order to offer the most amount of flexibility for embedded environments
* you need to define a macro for the size.
*
* First, you need to name your circular buffer. For this example, well
* call it myQ.
*
* The size macro that needs to be defined will be the name of the
* circular buffer followed by _SIZE. The size must be a power of two
* and it needs to fit in the get/put indicies. i.e. if you use an
* 8 bit index, then the maximum supported size would be 128.
*
* The structure which defines the circular buffer needs to have 3 members
* m_getIdx, m_putIdx, and m_entry.
*
* m_getIdx and m_putIdx need to be unsigned integers of the same size.
*
* m_entry needs to be an array of xxx_SIZE entries, or a pointer to an
* array of xxx_SIZE entries. The type of each entry is entirely up to the
* caller.
*
* #define myQ_SIZE 64
*
* volatile struct
* {
* uint8_t m_getIdx;
* uint8_t m_putIdx;
* uint8_t m_entry[ myQ_SIZE ];
*
* } myQ;
*
* You could then use
*
* CBUF_Push( myQ, x );
*
* to add a character to the circular buffer, or
*
* ch CBUF_Pop( myQ );
*
* to retrieve an element from the buffer.
*
* If you happen to prefer to use C instead, there is a templatized
* version which requires no macros. You just declare 3 template parameters:
*
* - The type that should be used for the index
* - The size of the circular buffer
* - The type that should be used for the entry
*
* For example:
*
* CBUF uint8_t, 64, char myQ;
*
****************************************************************************/推荐阅读专辑|Linux文章汇总专辑|程序人生专辑|C语言我的知识小密圈关注公众号后台回复「1024」获取学习资料网盘链接。欢迎点赞关注转发在看您的每一次鼓励我都将铭记于心~