microQueue

microQueue,第1张

队列是程序当中最常见的一个组件,特别是在嵌入式软件开发,一个好用的队列既能够保证数据传输的稳定,还能实现代码的适当解耦,本文以单片机为平台,介绍开源microQueue库的原理与使用。

git厂库:https://gitee.com/honrun_he/gd32-w51x_-templates.git

microQueue简介

microQueue是一款环形FIFO,可自由配置每个队列的长度、可设置溢出为锁定模式、覆盖模式。

结构体如下:

typedef enum {
    queueModeNormal = 0,    /* 覆盖模式 */
    queueModeLock,          /* 锁定模式 */
}enumQueueMode;

typedef struct{
    char *pcName;

    uint8_t *pHead;
    uint8_t *pTail;
    uint8_t *pReadFrom;
    uint8_t *pWriteTo;

    int32_t length;

    enumQueueMode mode;
}QueueType;

结构体成员解释:

pHead:指向列队RAM的第1个字节;

pTail:指向队列的尾部再加1个字节(每当pReadFrom、pWriteTo等于pTail时,把pReadFrom、pWriteTo再指向pHead);

pReadFrom:指向队列当前可以读取的字节(每出队1个字节,值+1);

pWriteTo:指向队列当前可以写入的字节(每入队1个字节,值+1);

length:队列长度;

直线显示

环形显示

源码:

/*
 *  author: Honrun
 */
#include "stdint.h"
#include "stdio.h"
#include "string.h"
#include "DevicesQueue.h"


QueueType g_TypeQueueUart0Read = {0};
static uint8_t st_ucQueueUart0ReadBuff[QUEUE_UART0_READ_LENGTH + 4] = {0};
QueueType g_TypeQueueUart1Read = {0};
static uint8_t st_ucQueueUart1ReadBuff[QUEUE_UART1_READ_LENGTH + 4] = {0};
QueueType g_TypeQueueUart2Read = {0};
static uint8_t st_ucQueueUart2ReadBuff[QUEUE_UART2_READ_LENGTH + 4] = {0};

QueueType g_TypeQueueKeyInput = {0};
static uint8_t st_ucQueueKeyInputBuff[QUEUE_KEY_INPUT_LENGTH + 4] = {0};


enumQueueState enumQueueInit(void)
{
    enumQueueState enumState = queueNormal;
    int8_t i = 0;


    if(enumQueueCreate(&g_TypeQueueUart0Read, "Uart0 Read", st_ucQueueUart0ReadBuff, QUEUE_UART0_READ_LENGTH, queueModeLock) != queueNormal)
        enumState = queueError;
    if(enumQueueCreate(&g_TypeQueueUart1Read, "Uart1 Read", st_ucQueueUart1ReadBuff, QUEUE_UART1_READ_LENGTH, queueModeLock) != queueNormal)
        enumState = queueError;
    if(enumQueueCreate(&g_TypeQueueUart2Read, "Uart2 Read", st_ucQueueUart2ReadBuff, QUEUE_UART2_READ_LENGTH, queueModeLock) != queueNormal)
        enumState = queueError;

    if(enumQueueCreate(&g_TypeQueueKeyInput, "Key Input",   st_ucQueueKeyInputBuff, QUEUE_KEY_INPUT_LENGTH, queueModeNormal) != queueNormal)
        enumState = queueError;


    if(enumState != queueNormal)
        printf("enumQueueInit error.\r\n");


    return enumState;
}

/*
 * Return:      创建是否成功状态值
 * Parameters:  *pTypeQueue: 队列结构体指针; pucName: 队列名称; iLength: 队列长度
 * Description: 初始化队列
 */
enumQueueState enumQueueCreate(QueueType *pTypeQueue, char *pcName, uint8_t *pucBuff, int32_t iLength, enumQueueMode enumMode)
{
    if(pTypeQueue == NULL)
        return queueNull;

    if(iLength < 1)
        return queueEmpty;

    pTypeQueue->pcName    = pcName;
    pTypeQueue->pHead     = pucBuff;
    pTypeQueue->length    = iLength + 1;
    pTypeQueue->pReadFrom = pTypeQueue->pHead;
    pTypeQueue->pWriteTo  = pTypeQueue->pHead;
    pTypeQueue->pTail     = pTypeQueue->pHead + pTypeQueue->length;
    pTypeQueue->mode      = enumMode;

    return queueNormal;
}

/*
 * Return:      队列缓存空满状态
 * Parameters:  *pTypeQueue: 队列结构体指针
 * Description: 获取队列缓存空满状态
 */
enumQueueState enumQueueGetState(QueueType *pTypeQueue)
{
    uint8_t * pNow = NULL;

    if((pTypeQueue == NULL) || (pTypeQueue->pHead == NULL))
      return queueNull;

    if(pTypeQueue->pReadFrom == pTypeQueue->pWriteTo)
      return queueEmpty;

    pNow = pTypeQueue->pWriteTo + 1;
    pNow = (pNow >= pTypeQueue->pTail) ? pTypeQueue->pHead : pNow;

    if(pNow == pTypeQueue->pReadFrom)
      return queueFull;

    return queueNormal;
}

/*
 * Return:      void
 * Parameters:  *pTypeQueue: 队列结构体指针; ucStateFlag: 空满状态
 * Description: 设置队列缓存空满状态
 */
enumQueueState enumQueueSetState(QueueType *pTypeQueue, enumQueueState enumState)
{
    if((pTypeQueue == NULL) || (pTypeQueue->pHead == NULL))
        return queueNull;

    switch(enumState)
    {
        case queueEmpty:
            memset(pTypeQueue->pHead, 0, pTypeQueue->length);
            pTypeQueue->pReadFrom = pTypeQueue->pWriteTo = pTypeQueue->pHead;
            break;

        default : break;
    }

    return queueNormal;
}

/*
 * Return:      查找到的数据位置
 * Parameters:
 * Description: memrchr替代函数
 */
static void *vQueueMemrchr(void *pvHandle, uint8_t ucValue, int32_t iCount)
{
    uint8_t *pucCheck = pvHandle;

    pucCheck += iCount - 1;

    while((iCount--) > 0)
    {
        if(*pucCheck == ucValue)
            return pucCheck;

        --pucCheck;
    }

    return NULL;
}

/*
 * Return:      队列缓存中有效数据长度
 * Parameters:  *pTypeQueue: 队列结构体指针
 * Description: 获取队列缓存中有效数据长度
 */
int32_t iQueueGetLengthOfOccupy(QueueType *pTypeQueue)
{
    int32_t iLength = 0;

    if((pTypeQueue == NULL) || (pTypeQueue->pHead == NULL))
        return 0;

    if(pTypeQueue->pReadFrom <= pTypeQueue->pWriteTo)
        iLength = pTypeQueue->pWriteTo - pTypeQueue->pReadFrom;
    else
        iLength = pTypeQueue->length - (pTypeQueue->pReadFrom - pTypeQueue->pWriteTo);

    return iLength;
}

/*
 * Return:      队列缓存中有效数据长度
 * Parameters:  *pTypeQueue: 队列结构体指针; ucByte: 指定的有效字节
 * Description: 获取队列缓存中有效数据长度,需要有指定的有效字节
 */
int32_t iQueueGetLengthOfOccupyNeed(QueueType *pTypeQueue, uint8_t ucByte)
{
    int32_t iLength = 0;
    uint8_t *pucHead = NULL;

    if((pTypeQueue == NULL) || (pTypeQueue->pHead == NULL))
        return 0;

    /* pHead|-------pReadFrom===============pWriteTo-------------|pTail */
    if(pTypeQueue->pReadFrom <= pTypeQueue->pWriteTo)
    {
        if((pucHead = vQueueMemrchr(pTypeQueue->pReadFrom, ucByte, pTypeQueue->pWriteTo - pTypeQueue->pReadFrom)) != NULL)
            iLength = (pucHead - pTypeQueue->pReadFrom) + 1;
    }
    /* pHead|=======pWriteTo---------------pReadFrom=============|pTail */
    else
    {
        /* pHead|=======|pWriteTo */
        if((pucHead = vQueueMemrchr(pTypeQueue->pHead, ucByte, pTypeQueue->pWriteTo - pTypeQueue->pHead)) != NULL)
            iLength = (pucHead - pTypeQueue->pHead) + (pTypeQueue->pTail - pTypeQueue->pReadFrom) + 1;

        /* pReadFrom|=============|pTail */
        else if((pucHead = vQueueMemrchr(pTypeQueue->pReadFrom, ucByte, pTypeQueue->pTail - pTypeQueue->pReadFrom)) != NULL)
            iLength = (pucHead - pTypeQueue->pReadFrom) + 1;
    }

    return iLength;
}

/*
 * Return:      队列缓存中到下一个分隔符的有效数据长度
 * Parameters:  *pTypeQueue: 队列结构体指针
 * Description: 获取队列缓存中有效数据长度
 */
int32_t iQueueGetLengthOfSeparetor(QueueType *pTypeQueue, uint8_t ucByte)
{
    int32_t iLength = 0;
    uint8_t *pucHead = NULL;

    if((pTypeQueue == NULL) || (pTypeQueue->pHead == NULL))
        return 0;

    /* pHead|-------pReadFrom===============pWriteTo-------------|pTail */
    if(pTypeQueue->pReadFrom <= pTypeQueue->pWriteTo)
    {
        if((pucHead = memchr(pTypeQueue->pReadFrom, ucByte, pTypeQueue->pWriteTo - pTypeQueue->pReadFrom)) != NULL)
            iLength = (pucHead - pTypeQueue->pReadFrom) + 1;
    }
    /* pHead|=======pWriteTo---------------pReadFrom=============|pTail */
    else
    {
        /* pReadFrom|=============|pTail */
        if((pucHead = memchr(pTypeQueue->pReadFrom, ucByte, pTypeQueue->pTail - pTypeQueue->pReadFrom)) != NULL)
            iLength = (pucHead - pTypeQueue->pReadFrom) + 1;

        /* pHead|=======|pWriteTo */
        else if((pucHead = memchr(pTypeQueue->pHead, ucByte, pTypeQueue->pWriteTo - pTypeQueue->pHead)) != NULL)
            iLength = (pucHead - pTypeQueue->pHead) + (pTypeQueue->pTail - pTypeQueue->pReadFrom) + 1;
    }

    return iLength;
}

/*
 * Return:      队列缓存中剩余长度
 * Parameters:  *pTypeQueue: 队列结构体指针
 * Description: 获取队列缓存中剩余长度
 */
int32_t iQueueGetLengthOfRemaining(QueueType *pTypeQueue)
{
    int32_t iLength = 0;

    if((pTypeQueue == NULL) || (pTypeQueue->pHead == NULL))
        return 0;

    if(pTypeQueue->pReadFrom <= pTypeQueue->pWriteTo)
        iLength = pTypeQueue->length - (pTypeQueue->pWriteTo - pTypeQueue->pReadFrom) - 1;
    else
        iLength = (pTypeQueue->pReadFrom - pTypeQueue->pWriteTo) - 1;

    return iLength;
}

/*
 * Return:      是否入队成功状态
 * Parameters:  *pTypeQueue: 队列结构体指针; ucData: 待入队字节数据
 * Description: 入队一个字节数据
 */
enumQueueState enumQueuePushByte(QueueType *pTypeQueue, uint8_t ucData)
{
    enumQueueState enumPushState = queueNormal;

    if((pTypeQueue == NULL) || (pTypeQueue->pHead == NULL))
        return queueNull;

    if(enumQueueGetState(pTypeQueue) == queueFull)
    {
        printf("pTypeQueue %s full!\r\n", pTypeQueue->pcName);

        if(pTypeQueue->mode == queueModeLock)
            return queueFull;

        enumPushState = queueFull;
    }

    *pTypeQueue->pWriteTo++ = ucData;
    pTypeQueue->pWriteTo = ((pTypeQueue->pWriteTo >= pTypeQueue->pTail) ? pTypeQueue->pHead : pTypeQueue->pWriteTo);

    /* 在溢出时,需要把read指针指向当前队列新的末尾 */
    if(enumPushState == queueFull)
    {
        pTypeQueue->pReadFrom = pTypeQueue->pWriteTo + 1;
        pTypeQueue->pReadFrom = ((pTypeQueue->pReadFrom >= pTypeQueue->pTail) ? pTypeQueue->pHead : pTypeQueue->pReadFrom);
    }

    return enumPushState;
}

/*
 * Return:      是否出队成功状态
 * Parameters:  *pTypeQueue: 队列结构体指针; *pucData: 待出队字节数据指针
 * Description: 出队一个字节数据
 */
enumQueueState enumQueuePopByte(QueueType *pTypeQueue, uint8_t *pucData)
{
    if((pTypeQueue == NULL) || (pTypeQueue->pHead == NULL))
        return queueNull;

    if(pTypeQueue->pReadFrom == pTypeQueue->pWriteTo)
      return queueEmpty;

    *pucData = *pTypeQueue->pReadFrom++;
    pTypeQueue->pReadFrom = ((pTypeQueue->pReadFrom >= pTypeQueue->pTail) ? pTypeQueue->pHead : pTypeQueue->pReadFrom);

    return queueNormal;
}

/*
 * Return:      是否出队成功状态
 * Parameters:  *pTypeQueue: 队列结构体指针; *pucData: 待出队字节数据指针
 * Description: 出队一个字节数据,并保留队列中的原数据
 */
enumQueueState enumQueueViewByte(QueueType *pTypeQueue, uint8_t *pucData)
{
    if((pTypeQueue == NULL) || (pTypeQueue->pHead == NULL))
        return queueNull;

    if(pTypeQueue->pReadFrom == pTypeQueue->pWriteTo)
      return queueEmpty;

    *pucData = *pTypeQueue->pReadFrom;

    return queueNormal;
}

/*
 * Return:      是否入队成功状态
 * Parameters:  *pTypeQueue: 队列结构体指针; *ppHead: 待入队数据缓存指针; iLength: 缓存长度
 * Description: 入队一系列数据
 */
enumQueueState enumQueuePushDatas(QueueType *pTypeQueue, void *pvBuff, int32_t iLength)
{
    uint8_t *pucHandle = pvBuff;
    enumQueueState enumPushState = queueNormal;

    if((pTypeQueue == NULL) || (pTypeQueue->pHead == NULL))
        return queueNull;

    if(iQueueGetLengthOfRemaining(pTypeQueue) < iLength)
    {
        printf("pTypeQueue %s full!\r\n", pTypeQueue->pcName);

        if(pTypeQueue->mode == queueModeLock)
            return queueFull;

        enumPushState = queueFull;
    }

    while((iLength--) > 0)
    {
        *pTypeQueue->pWriteTo++ = *pucHandle++;
        pTypeQueue->pWriteTo = ((pTypeQueue->pWriteTo >= pTypeQueue->pTail) ? pTypeQueue->pHead : pTypeQueue->pWriteTo);
    }

    /* 在溢出时,需要把read指针指向当前队列新的末尾 */
    if(enumPushState == queueFull)
    {
        pTypeQueue->pReadFrom = pTypeQueue->pWriteTo + 1;
        pTypeQueue->pReadFrom = ((pTypeQueue->pReadFrom >= pTypeQueue->pTail) ? pTypeQueue->pHead : pTypeQueue->pReadFrom);
    }

    return enumPushState;
}

/*
 * Return:      是否出队成功状态
 * Parameters:  *pTypeQueue: 队列结构体指针; *ppHead: 待出队数据缓存指针; iLength: 缓存长度
 * Description: 出队一系列数据
 */
enumQueueState enumQueuePopDatas(QueueType *pTypeQueue, void *pvBuff, int32_t iLength)
{
    uint8_t *pucHandle = pvBuff;

    if((pTypeQueue == NULL) || (pTypeQueue->pHead == NULL))
        return queueNull;

    if(pvBuff == NULL)
        return queueError;

    if(iQueueGetLengthOfOccupy(pTypeQueue) < iLength)
        return queueError;

    while((iLength--) > 0)
    {
        *pucHandle++ = *pTypeQueue->pReadFrom++;
        pTypeQueue->pReadFrom = ((pTypeQueue->pReadFrom >= pTypeQueue->pTail) ? pTypeQueue->pHead : pTypeQueue->pReadFrom);
    }

    return queueNormal;
}

/*
 * Return:      是否出队成功状态
 * Parameters:  *pTypeQueue: 队列结构体指针; *ppHead: 待出队数据缓存指针; iLength: 缓存长度
 * Description: 出队一系列数据,并保留队列中的原数据
 */
enumQueueState enumQueueViewDatas(QueueType *pTypeQueue, void *pvBuff, int32_t iLength)
{
    uint8_t *pucHandle = pvBuff, *pucReadFrom = pTypeQueue->pReadFrom;

    if((pTypeQueue == NULL) || (pTypeQueue->pHead == NULL))
        return queueNull;

    if(pvBuff == NULL)
        return queueError;

    if(iQueueGetLengthOfOccupy(pTypeQueue) < iLength)
        return queueError;

    while((iLength--) > 0)
    {
        *pucHandle++ = *pucReadFrom++;
        pucReadFrom = ((pucReadFrom >= pTypeQueue->pTail) ? pTypeQueue->pHead : pucReadFrom);
    }

    return queueNormal;
}

/*
 * Return:      是否出队成功状态
 * Parameters:  *pTypeQueue: 队列结构体指针; *ppHead: 待出队数据缓存指针; iLength: 缓存长度; ucByte: 指定的有效字节
 * Description: 出队一系列数据,需要有指定的有效字节
 */
enumQueueState enumQueuePopDatasNeed(QueueType *pTypeQueue, void *pvBuff, int32_t iLength, uint8_t ucByte)
{
    uint8_t *pucHandle = pvBuff;

    if((pTypeQueue == NULL) || (pTypeQueue->pHead == NULL))
        return queueNull;

    if(pvBuff == NULL)
        return queueError;

    if(iQueueGetLengthOfOccupyNeed(pTypeQueue, ucByte) < iLength)
        return queueError;

    while((iLength--) > 0)
    {
        *pucHandle++ = *pTypeQueue->pReadFrom++;
        pTypeQueue->pReadFrom = ((pTypeQueue->pReadFrom >= pTypeQueue->pTail) ? pTypeQueue->pHead : pTypeQueue->pReadFrom);
    }

    return queueNormal;
}

/*
 * Return:      是否出队成功状态
 * Parameters:  *pTypeQueue: 队列结构体指针; *ppHead: 待出队数据缓存指针; iLength: 缓存长度; ucByte: 指定的有效字节
 * Description: 出队一系列数据,需要有指定的有效字节,并保留队列中的原数据
 */
enumQueueState enumQueueViewDatasNeed(QueueType *pTypeQueue, void *pvBuff, int32_t iLength, uint8_t ucByte)
{
    uint8_t *pucHandle = pvBuff, *pucReadFrom = pTypeQueue->pReadFrom;

    if((pTypeQueue == NULL) || (pTypeQueue->pHead == NULL))
        return queueNull;

    if(pvBuff == NULL)
        return queueError;

    if(iQueueGetLengthOfOccupyNeed(pTypeQueue, ucByte) < iLength)
        return queueError;

    while((iLength--) > 0)
    {
        *pucHandle++ = *pucReadFrom++;
        pucReadFrom = ((pucReadFrom >= pTypeQueue->pTail) ? pTypeQueue->pHead : pucReadFrom);
    }

    return queueNormal;
}

头文件:

/*
 *  Author: Honrun
 */
#ifndef _DevicesQueue_H_
#define _DevicesQueue_H_



#define QUEUE_MAX_LENGTH         (2048)

#define QUEUE_UART0_READ_LENGTH  (1024)
#define QUEUE_UART1_READ_LENGTH  (1024)
#define QUEUE_UART2_READ_LENGTH  (1024)

#define QUEUE_KEY_INPUT_LENGTH   (256)
#define QUEUE_KEY_TOUCH_LENGTH   (64)




/* 使x对n字节对齐 */
#define queueRoundUp(x, n) (((x) + (n) - 1) & (~((n) - 1)))


typedef enum {
    queueNormal = 0,
    queueError,
    queueNull,
    queueEmpty,
    queueFull,
}enumQueueState;

typedef enum {
    queueModeNormal = 0,    /* 覆盖模式 */
    queueModeLock,          /* 锁定模式 */
}enumQueueMode;



typedef struct{
    char *pcName;

    uint8_t *pHead;
    uint8_t *pTail;
    uint8_t *pReadFrom;
    uint8_t *pWriteTo;

    int32_t length;

    enumQueueMode mode;
}QueueType;



extern QueueType g_TypeQueueUart0Read;
extern QueueType g_TypeQueueUart1Read;
extern QueueType g_TypeQueueUart2Read;

extern QueueType g_TypeQueueKeyInput;



enumQueueState enumQueueInit(void);
enumQueueState enumQueueCreate(QueueType *pTypeQueue, char *pcName, uint8_t *pucBuff, int32_t iLength, enumQueueMode enumMode);
enumQueueState enumQueueGetState(QueueType *pTypeQueue);
enumQueueState enumQueueSetState(QueueType *pTypeQueue, enumQueueState enumState);
int32_t iQueueGetLengthOfOccupy(QueueType *pTypeQueue);
int32_t iQueueGetLengthOfOccupyNeed(QueueType *pTypeQueue, uint8_t ucByte);
int32_t iQueueGetLengthOfSeparetor(QueueType *pTypeQueue, uint8_t ucByte);
int32_t iQueueGetLengthOfRemaining(QueueType *pTypeQueue);
enumQueueState enumQueuePushByte(QueueType *pTypeQueue, uint8_t ucData);
enumQueueState enumQueuePopByte(QueueType *pTypeQueue, uint8_t *pucData);
enumQueueState enumQueueViewByte(QueueType *pTypeQueue, uint8_t *pucData);
enumQueueState enumQueuePushDatas(QueueType *pTypeQueue, void *pvBuff, int32_t iLength);
enumQueueState enumQueuePopDatas(QueueType *pTypeQueue, void *pvBuff, int32_t iLength);
enumQueueState enumQueueViewDatas(QueueType *pTypeQueue, void *pvBuff, int32_t iLength);
enumQueueState enumQueuePopDatasNeed(QueueType *pTypeQueue, void *pvBuff, int32_t iLength, uint8_t ucByte);
enumQueueState enumQueueViewDatasNeed(QueueType *pTypeQueue, void *pvBuff, int32_t iLength, uint8_t ucByte);

#endif

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1295119.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-10
下一篇 2022-06-10

发表评论

登录后才能评论

评论列表(0条)

保存