zoukankan      html  css  js  c++  java
  • 一个RingBuffer(C语言)

    也是用于STM32平台下. 通常用于串口通讯缓存.

    之前看到一些其他项目写的Buffer缓存. 实在是太不简洁了, 而且还可能有bug.

    例如

      当处理数据不够快时, 缓存会直接被覆盖, 而不产生任何提示.

      每次Update都判断 read指针 是否等于 write指针, 是的话又重新将 read和write指针置为数组的开头, 在我看来这是完全没有必要的.( 如果硬要说的话, 可以说是便于调试看数据)

    本文仅作简单记录.  代码不是我直接写的, 是我指导同事写的.

    头文件

    #ifndef __RingBuff_H
    #define __RingBuff_H
    
    #include <stdint.h>
    
    #define  RINGBUFF_LEN          512     //定义最大接收字节数 200
    
    
    typedef  struct
    {
      volatile uint32_t ReadCount;
      volatile uint32_t WriteCount;
      uint8_t Ring_Buff[RINGBUFF_LEN];
    }RingBuff_t;
    
    void RingBuff_Init(RingBuff_t *ringBuff);

    //写入RingBuffer缓存

    //返回写入字节数

    uint32_t RingBuffer_WriteBuf(RingBuff_t *ringBuff,uint8_t *buf, uint32_t length);

    //读取RingBuffer数据, 并清除在RingBuffer相关的缓存

    //返回读取到的字节数

    uint32_t RingBuffer_ReadBuf(RingBuff_t *ringBuff,uint8_t *buf, uint32_t length);

    //从RingBuffer中读取一个字节,如果没有读取到内容,则返回-1. int32_t RingBuffer_ReadByte(RingBuff_t
    *ringBuff); //-1 0~255
    //写入一个字节
    int32_t RingBuffer_WriteByte(RingBuff_t *ringBuff,uint8_t byte); //伪读取,因为真的读取的话,会清空读取到的缓存的. 这里是读取到后依然不清除缓存 uint32_t RingBuffer_PseudoReadBuf(RingBuff_t *ringBuff,uint8_t *buf, uint32_t length); #endif

    代码

    #include "RingBuff.h"
    #include "SEGGER_RTT.h"
    
    void _Assert(int a){
        int x=0;
        while(!a){
            x++;
        }
    }
    /*防止数组溢出函数*/
    int _Repeat(int t, int length)
    {
      return t % length;
    }
    /*获取已经写入的空间*/
    int GetReadableSize(RingBuff_t *ringBuff){
        return ringBuff->WriteCount - ringBuff->ReadCount;
    }
    /*获取可写入空间*/
    int GetWritableSize(RingBuff_t *ringBuff)
    {
        return RINGBUFF_LEN - GetReadableSize(ringBuff);
    }
    
    void RingBuff_Init(RingBuff_t *ringBuff)
    {
       //初始化相关信息
       ringBuff->ReadCount = 0;
       ringBuff->WriteCount = 0;
       //ringBuff->Length = 0;
    }
    
    /*断言函数 --
    参数:结构体指针
    数组指针
    数据长度
    1:判断接收到的数据是否为空,如果为空,返回断言 while(1)
    2:判断数据长度是否为空,如果为空,返回断言 while(1)
    3:判断接收的数据长度是否大于等于最大的缓存空间,如果是,返回断言 while(1)
    */
    
    static void CheckArguments(RingBuff_t *ringBuff,uint8_t *buffer,  int count){
        _Assert(buffer !=0);
        _Assert(count >=0);
        _Assert(RINGBUFF_LEN >= count);
    }
    
    //
    static uint32_t Min(uint32_t x,uint32_t y){
        return     x<y ? x:y;
    }
    
    /*函数:
    RingBuff_t* ringBuff --结构体指针
    *buf --指向数据的地址
    length -- 写入的长度
    */
    uint32_t RingBuffer_WriteBuf(RingBuff_t* ringBuff,uint8_t *buf, uint32_t length){
        uint32_t i=0;
        int writeOffset;
        static uint8_t temp=0;
        
        //断言
        CheckArguments(ringBuff, buf, length);
        //断言:判断接收的数据长度是否已经超过缓存数组中的剩余长度,如果是,返回断言 while(1)
        _Assert(GetWritableSize(ringBuff) >= length);
        for ( i = 0; i < length; ++i)
        {
            writeOffset = _Repeat(ringBuff->WriteCount, RINGBUFF_LEN);
        ringBuff->Ring_Buff[writeOffset] = buf[i];
        ++ringBuff->WriteCount;
            
            if(temp >20){
                temp =0;
                SEGGER_RTT_printf(0,"
    ");
            }    
            SEGGER_RTT_SetTerminal(1);
            SEGGER_RTT_printf(0,"[%x]",buf[i]);
            temp++;    
            
        }    
    
        return length;
    }
    uint32_t RingBuffer_ReadBuf(RingBuff_t *ringBuff,uint8_t *buf, uint32_t length){
        uint32_t canReadCount=0,i=0;
        int readOffset;
        CheckArguments(ringBuff,buf, length);    
    
        canReadCount = Min(length, GetReadableSize(ringBuff));
    
        for ( i = 0; i < canReadCount; ++i)
        {
            readOffset = _Repeat(ringBuff->ReadCount, RINGBUFF_LEN);
            buf[i] = ringBuff->Ring_Buff[readOffset];
            ++ringBuff->ReadCount;
        }
        return canReadCount;
    }
    /*  函数--读取数据存放到BUF中*/
    uint32_t RingBuffer_PseudoReadBuf(RingBuff_t *ringBuff,uint8_t *buf, uint32_t length){
        uint32_t canReadCount=0,i=0,readCount,readOffset;
        CheckArguments(ringBuff,buf, length);    
    
        readCount = ringBuff->ReadCount;
        canReadCount = Min(length, GetReadableSize(ringBuff));
        
        for ( i = 0; i < canReadCount; ++i)
        {
            readOffset = _Repeat(readCount, RINGBUFF_LEN);
            buf[i] = ringBuff->Ring_Buff[readOffset];
            ++readCount;
        }
        return canReadCount;
    }
    
    
    int32_t RingBuffer_ReadByte(RingBuff_t *ringBuff){
        uint8_t val;
        uint32_t readed = RingBuffer_ReadBuf(ringBuff,&val,1);
        if(readed ==0)
            return -1;
        return val;
    }
    
    /*
    函数:串口接收到的一个字节,写入到buf中
    参数: RingBuff_t *ringBuff--结构体指针
                byte -- 写入的数据
    返回--uint32_t ret
    */
    int32_t RingBuffer_WriteByte(RingBuff_t *ringBuff,uint8_t byte){
        uint32_t ret = RingBuffer_WriteBuf(ringBuff,&byte,1);
        return ret;
    }
  • 相关阅读:
    使用DirectX作渲染过程
    记于来北京两个星期
    添加 node mocha 测试模块
    for-of循环
    app-web 开发 追溯debug
    cmd关闭被占用的端口命令及教程详解
    vue使用element-ui的el-input监听不了键盘事件解决
    Nodejs 进阶:Express 常用中间件 body-parser 实现解析
    nodejs设置允许跨域
    nodejs 全局变量和全局对象
  • 原文地址:https://www.cnblogs.com/godzza/p/15062990.html
Copyright © 2011-2022 走看看