嵌入式常用模块之——环形队列(1)

2023-05-16

    • 简单聊聊
    • 对我实现方式的介绍
    • 代码部分
    • 完整代码

简单聊聊

在嵌入式开发时候,有很对模块是经常会使用到的。从这篇文字开始,将我觉得一些常用的模块逐一做一个整理。梳理一下自己的思路,也顺便方便大家,如果可以给初学者一点帮助和启发,那也是再好不过了。
环形队列在异步接收数据上感觉不能更爽。关于环形队列详细讲解说明网上也很多了,我就简单说一下了。为了减少动态分配回收内存开销。我写的队列使用的是线性存储方式。所谓环形队列不过把线性表利用指针等方式模拟成一个环形结构。让人在使用上看起来是一个环形的。简单说就是到达数组尾部后回溯到头部重新开始。

对我实现方式的介绍

  1. 首先要说的一点。加入队列到尾部还有20字节,这时候要存21字节数据的话,有两种方式,第一种是前20字节存尾部20字节,最后1字节存到队头。这种方式实现是真正的环形队列。第二种方式是浪费掉这尾部20字节,数据全部从头开始存,占用头部21字节空间。这样的话浪费了一定空间,也就是说如果头部没有21字节空闲,数据就放不下了。我使用的是第二种方式,虽然浪费一点空间,但是实现和管理上比较简单。(PS:这里有必要提一下,我所描述的头部和尾部,特指实际数据的头尾,不是所实现的队列的头尾)。
  2. 这种方式实现的队列适合存取一些长度变化较大的数据。至于存取长度基本等长的数据,这样实现也是可以的,下篇我会用另一种方式实现队列,那种方式个人认为更适合一点存取等长数据。我也是这么做的。
  3. 不排除我的代码有遗漏的边界测试。如果要用于项目请自行检查一下。

代码部分

初始化是必须的,毕竟用了指针。必须初始化一下,不能让他撒野。万一野指针搞出个bug简直想哭。

void ringInit(pTest t)
{

    int i;
    t->putCount = 0;
    t->getCount = 0;
    t->head = t->buff;
    t->tail = t->buff;
    for(i = 0; i < MAX_LEN; i++)
    {
        t->size[i] = 0;
    }
}

其他部分突然觉得没啥可说的,那就这样吧。

完整代码

#include <stdio.h>

#define TEST 1

#define MAX_BUFF (1024) // 队列数据段总的长度
#define MAX_LEN (10) // 队列中数据段个数

typedef struct __test
{
    unsigned char *head; //头指针(进队列指针)
    unsigned char *tail; //尾指针(出队列指针)
    unsigned int size[MAX_LEN]; //保存每个数据段的长度
    unsigned char putCount; //进队列个数
    unsigned char getCount; //出队列个数
    unsigned char buff[MAX_BUFF]; //数据buff
}Test,*pTest;
/******************************
* @funcation: 初始化队列
* @auther: main_h_
* @time: 2018/9/6
* @param:  pTest[in]
* @return: None
******************************/
void ringInit(pTest t)
{

    int i;
    t->putCount = 0;
    t->getCount = 0;
    t->head = t->buff;
    t->tail = t->buff;
    for(i = 0; i < MAX_LEN; i++)
    {
        t->size[i] = 0;
    }
}
/******************************
* @funcation: 返回一个进队列指针
* @auther: main_h_
* @time: 2018/9/6
* @param:  t[in]  len[in]
* @return: 如果buff有空闲则返回
    一个进队列指针,否则返回NULL
******************************/
unsigned char* ringPut(pTest t,int len)
{
    unsigned char *ret = t->head;
    t->head += len;
    if(t->head >= t->buff+MAX_BUFF)
    {
        if(t->tail - t->buff > len)
        {
            t->head = t->buff+len;
            t->size[t->putCount%MAX_LEN] = len;
            t->putCount++;
            return t->buff;
        }
        return NULL;
    }
    else
    {
        t->size[t->putCount%MAX_LEN] = len;
        t->putCount++;
        return ret;
    }
}
/******************************
* @funcation: 返回一个出队列指针
* @auther: main_h_
* @time: 2018/9/6
* @param:  t[in]  len[out]
* @return: 如果buff有数据则返回
    一个出队列指针,否则返回NULL
******************************/
unsigned char* ringGet(pTest t,int *len)
{
    unsigned char *ret = t->tail;
    if(t->getCount >= t->putCount)
    {
        return NULL;
    }
    t->tail += t->size[t->getCount%MAX_LEN];
    *len = t->size[t->getCount%MAX_LEN];
    if(t->tail >= t->buff + MAX_BUFF)
    {
        t->tail = t->buff + t->size[t->getCount%MAX_LEN];
        ret = t->buff;
    }
    t->getCount++;
    return ret;
}
/******************************
* @funcation: 返回队列状态
* @auther: main_h_
* @time: 2018/9/6
* @param:  t[in]
* @return: 队列为空返回1,否则返回0
******************************/
unsigned char ringEmpty(const pTest t)
{
    if(t->tail != t->head)
        return 0;
    return 1;
}
int main()
{
#ifdef TEST
    int i = 0,len = 0;
    unsigned char *ptr = NULL;
    Test t;
    ringInit(&t);
    printf("isEmpty:%d\n",ringEmpty(&t));
    ptr = ringPut(&t,1020);
    if(ptr != NULL)
    {
        for(i = 0; i < 100; i++)
        {
            ptr[i] = i%256;
        }
    }
    ptr = ringGet(&t,&len);
    printf("isEmpty:%d",ringEmpty(&t));
    ptr = ringPut(&t,4);
    printf("\n\nNULL............ :%x\n\n",ptr);
    if(ptr != NULL)
    {
        for(i = 0; i < 4; i++)
        {
            ptr[i] = i+20;
        }
    }
    ptr = ringGet(&t,&len);
    if(ptr != NULL)
    {
        printf("len:%d\n",len);
        for(i = 0; i < len; i++)
        {
            printf("%2d ",ptr[i]);
        }
    }
    printf("isEmpty:%d\n",ringEmpty(&t));
    printf("\n");
    ptr = ringPut(&t,20);
    printf("\n\n\n%x\n",ptr);
    if(ptr != NULL)
    {
        //
        for(i = 0; i < 20; i++)
        {
            ptr[i] = i+30;
        }
    }
    printf("\n");
    ptr = ringGet(&t,&len);
    if(ptr != NULL)
    {
        printf("len:%d\n",len);
        for(i = 0; i < len; i++)
        {
            printf("%2d ",ptr[i]);
        }
    }
    printf("\n");
    ptr = ringGet(&t,&len);
    if(ptr != NULL)
    {
        printf("len:%d\n",len);
        for(i = 0; i < len; i++)
        {
            printf("%2d ",ptr[i]);
        }
    }
    ptr = ringPut(&t,20);
    printf("\n\nNULL :%x\n\n",ptr);
    if(ptr != NULL)
    {
        for(i = 0; i < 20; i++)
        {
            ptr[i] = i*3;
        }
    }
    ptr = ringPut(&t,210);
    printf("\n\nNULL :%x\n\n",ptr);
    if(ptr != NULL)
    {
        for(i = 0; i < 210; i++)
        {
            ptr[i] = i+3;
        }
    }
    printf("\nisEmpty:%d\n",ringEmpty(&t));
    ptr = ringGet(&t,&len);
    if(ptr != NULL)
    {
        printf("len:%d\n",len);
        for(i = 0; i < len; i++)
        {
            printf("%2d ",ptr[i]);
        }
    }
    printf("\n");
    printf("\nisEmpty:%d\n",ringEmpty(&t));
        ptr = ringGet(&t,&len);
    if(ptr != NULL)
    {
        printf("len:%d\n",len);
        for(i = 0; i < len; i++)
        {
            printf("%2x ",ptr[i]);
        }
    }
    printf("\nisEmpty:%d\n",ringEmpty(&t));
    printf("\n");
    ptr = ringPut(&t,21);
    ptr = ringPut(&t,21);
    ptr = ringPut(&t,21);
    ptr = ringPut(&t,210);
    ptr = ringPut(&t,210);
    ptr = ringPut(&t,210);
    ptr = ringPut(&t,210);
    ptr = ringPut(&t,210);
    ptr = ringPut(&t,210);
    ptr = ringGet(&t,&len);
    ptr = ringGet(&t,&len);
    ptr = ringGet(&t,&len);
    ptr = ringGet(&t,&len);
    ptr = ringGet(&t,&len);
    ptr = ringGet(&t,&len);
    ptr = ringGet(&t,&len);
    ptr = ringGet(&t,&len);
    ptr = ringGet(&t,&len);
//  ptr = ringGet(&t,&len);
    printf("\nisEmpty:%d\n",ringEmpty(&t));
    printf("%x\n",ptr);
#endif
    return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌入式常用模块之——环形队列(1) 的相关文章

随机推荐

  • UDP的客户端和服务器端的实例(VC6.0实现)

    服务器端程序 xff1a UdpServer cpp Defines the entry point for the console application include 34 stdafx h 34 include lt stdio h
  • STM32中关于串口中断的调试(不断进入发送中断的原因)

    说来惭愧 xff0c 前日在调试stm32f10系列的单片机的时候 xff0c 想做一个关于串口发送的状态机 xff0c 每隔100毫秒发送一次命令 没有用DMA xff0c 就是想单纯的使用发送中断来数据 xff0c 结果在调试的时候一直
  • Psoc Creator 入门——空工程的建立

    最近在做psoc 4000芯片的开发 xff0c 现在简单的说说怎么利用psoc creator进行开发 首先 xff0c 安装psoc creator xff0c 我使用的版本是4 0 安装过程省略 xff0c 赛普拉斯官网有下载链接 x
  • mbedtls使用openssl生成的自签名证书进行TLS实验

    目录 1 使用openssl生成自签名证书2 VS2013编译mbedtls3 mbdtls默认对证书的要求4 mbdtls测试例子详解5 运行测试程序 1 使用openssl生成自签名证书 openssl是一个安全套接字层密码库 xff0
  • IIC的通信波形分析

    关于IIC xff0c 不解释它的历史了 xff0c 有兴趣自己去百度看看 xff0c 本文的图片是由周立功的LAB6021逻辑分析仪抓取的 xff0c 通信的波形是抓取的cypress的psoc 4000芯片得到的 最近项目需要用到触摸I
  • linux下的CSV文件操作

    先介绍一下什么是csv文件 xff0c 这是一种简单的文本文件 xff0c 也被称为逗号分隔值文件 主要是用于存储简单的数据 xff0c 下面在weindows下用UE简单生成一下文件 然后用excel打开 这就是一个简单的csv文件 xf
  • GNU makefile入门——刚开坑,没有干货

    一个完整的makefile文件包含5个部分的内容 xff1a 显示规则 xff0c 隐含规则 xff0c 变量和指示符 xff0c 注释 显示规则 xff1a 包括目标 xff1a 依赖规则 命令 隐含规则 xff1a make根据目标文件
  • Renesas CS+ for ca cx入门(一)

    这是一篇关于Renesas的CS 43 for ca xff08 以下简称CA xff09 的入门简介 xff0c 在网上关于这个IDE的使用方法比较少人讲述 xff0c 兴许使用的人比较少吧 另一个类似的IDE是CS 43 for cc
  • 单片机——按键扫描

    按键扫描 xff0c 我想应该是比较简单的单片机应用了 xff0c 但是有时候看起来简单的东西反而不好写 本文拿大部分人觉得简单的按键扫描聊聊我工作至今对于软件结构的理解 嗯 xff0c 对的 xff0c 是结构 xff0c 不是架构 xf
  • keil的错误: Error: Encountered an improper argument 的解决方法

    将附件中的文件下载然后放到keil一下的安装目录中即可C Keil v5 UV4 xff0c 选择替换即可 文件链接 xff1a http download csdn net download ma57457 10118005 官方说的是支
  • 嵌入式软件没有层次感的原因

    因为软件是一个人写的 xff01 xff01 xff01
  • 博客网站转移

    我的博客会慢慢的转移到新的网站上 xff0c 新的地址为oopsrtos com xff0c 新博客会对arm 体系结果做更深入的探讨 xff0c 主要是关于实时操作系统内核开发的研究 最近在研究FPU xff0c 从内核层解释在操作系统中
  • keil工程中找不到头文件的可能原因

    今天用keil写一个串口调试程序 xff0c 编译工程时 xff0c 总是找不到type h头文件 xff0c 而该文件又是必须的 于是 xff0c 重新看设置 xff0c 头文件路径已经包含到工程里了 xff0c 头文件也已经添加到工程里
  • 在NAND FLASH上建立YAFFS2文件系统

    在NAND FLASH上建立YAFFS2文件系统 xff08 一 xff09 By on 2006 07 22 经过了半个多月的努力 xff0c 终于搞定nandflash的mtd驱动和上层的yaffs2文件系统 这半个多月来几乎每天都要和
  • 个人学习笔记-矩阵的四则运算

    目录 1 矩阵的四则运算1 1 矩阵的乘法运算1 2矩阵的加法运算1 3矩阵的减法运算 2 接口测试输出结果 1 矩阵的四则运算 1 1 矩阵的乘法运算 span class token comment 矩阵乘法 C语言实现分解步骤 xff
  • 单片机通信接口:UART、I2C、SPI、TTL、RS232、RS422、RS485、CAN、USB

    参考资料 xff1a 这些单片机接口 xff0c 一定要熟悉 xff1a UART I2C SPI TTL RS232 RS422 RS485 CAN USB SD卡 秒懂所有USB接口类型 xff0c USB接口大全 1 UART UAR
  • PCB中走线与电流的关系

    参考资料 xff1a 超强整理 xff01 PCB设计之电流与线宽有八种关系 1 前言 PCB的载流能力取决与以下因素 xff1a 线宽 线厚 xff08 铜箔厚度 xff09 容许温升 PCB走线越宽 xff0c 载流能力越大 但走线宽度
  • Visual Studio各版本集成的Visual C++版本对应关系

    Visual Studio版本集成的Visual C 43 43 版本对应关系如下 xff1a Visual Studio 6 xff1a vc6 Visual Studio 2003 xff1a vc7 Visual Studio 200
  • 字节序—字节内部的位序

    Big endian machine It thinks the first byte it reads is the biggest Little endian machine It thinks the first byte it re
  • 嵌入式常用模块之——环形队列(1)

    简单聊聊对我实现方式的介绍代码部分完整代码 简单聊聊 在嵌入式开发时候 xff0c 有很对模块是经常会使用到的 从这篇文字开始 xff0c 将我觉得一些常用的模块逐一做一个整理 梳理一下自己的思路 xff0c 也顺便方便大家 xff0c 如