STM32 开发之环形缓冲的应用

一.问题描述

STM32的串口应用有一种场景:串口数据传输时,接收数据长度未知,频率未知,不要求实时处理的场景。如果采用上述方案,接收一帧数据立即处理,那么在处理的时候来的数据包就“丢失”了。这个时候就需要环形缓冲区来解决这个问题。

二.环形缓冲区简介

环形缓冲区就是一个带“头指针”和“尾指针”的数组。“头指针”指向环形缓冲区中可读的数据,“尾指针”指向环形缓冲区中可写的缓冲空间。通过移动“头指针”和“尾指针”就可以实现缓冲区的数据读取和写入。

在通常情况下,应用程序读取环形缓冲区的数据仅仅会影响“头指针”,而串口接收数据仅仅会影响“尾指针”。当串口接收到新的数组,则将数组保存到环形缓冲区中,同时将“尾指针”加1,以保存下一个数据;应用程序在读取数据时,“头指针”加1,以读取下一个数据。当“尾指针”超过数组大小,则“尾指针”重新指向数组的首元素,从而形成“环形缓冲区”!,有效数据区域在“头指针”和“尾指针”之间。如下图:

cffe7cc96b71c5062a3084ac075c9d2e.png

三.代码实现

RingBuffer.h


#ifndef __RINGBUFFER_H__
#define __RINGBUFFER_H__

#ifdef __cplusplus
extern "C" {
#endif
#include "main.h"
#include "usart.h"

#define MAX_BUFFER   128 /*缓冲区大小*/
/*缓冲区结构体*/
typedef struct 
{
    uint16_t head;
    uint16_t tail;
    uint16_t length;
    uint8_t   ringBuffer[MAX_BUFFER];
}Type_RingBuffer_Uchar;

/*读写缓冲区函数声明*/
void Ringbuf_wirte_float(float data, Type_RingBuffer_float* pRingBuffer);
uint8_t Ringbuf_read_float(float *pdata, Type_RingBuffer_float* pRingBuffer);


#endif

如果串口传输的数据量过大,我们会发现环形缓冲区被“冲爆”,也就是缓冲区满了,但是还有待缓冲的数据时,只需要修改MAX_BUFFER的宏定义,增大缓冲区间即可。

RingBuffer.c


/**
* @brief  往环形缓冲写入数据
* @param  uint8_t data 待写入的数据 ;Type_RingBuffer_Uchar* pRingBuffer 要写入的缓冲区
* @note   往环形缓冲区写入uint8_t类型的数据
*/
void Ringbuf_wirte_Uchar(uint8_t data, Type_RingBuffer_Uchar* pRingBuffer)
{

    pRingBuffer->ringBuffer[pRingBuffer->tail] = data;
    if(++pRingBuffer->tail >= MAX_BUFFER) /*判断缓冲区是否已满*/
    {
        pRingBuffer->tail = 0;
    }
    if(pRingBuffer->tail == pRingBuffer->head)
    {
        if(++pRingBuffer->head >= MAX_BUFFER)/*防止越界*/
        {
            pRingBuffer->head = 0;
        }
    }
    pRingBuffer->length++;
}

/**
* @brief  从环形缓冲区读取数据
* @param  uint8_t* pdata  存放读取的数据的地址 ;Type_RingBuffer_Uchar* pRingBuffer 要读取的缓冲区
* @return 1:环形缓冲区为空,读取失败;0:读取成功
* @note   从环形缓冲区读取uint8_t类型的数据
*/
uint8_t Ringbuf_read_Uchar(uint8_t *pdata, Type_RingBuffer_Uchar* pRingBuffer)
{
    if(pRingBuffer->head == pRingBuffer->tail) /*判断缓冲区是否为空*/
    {
        return 1;
    }
    else
    {
        *pdata = pRingBuffer->ringBuffer[pRingBuffer->head];
        if(++pRingBuffer->head >= MAX_BUFFER) /*防止越界*/
        {
            pRingBuffer->head = 0;
        }
        pRingBuffer->length--;
        return 0;
    }
}

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

工匠Sola

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值