环形缓冲区 之 STM32 串口接收的实现-三、 实际使用

上面我们给出了程序源码,然后根据自己的工程框架放到自己工程下面,接下来我们就来实际说明一下怎么使用。

我们这里把标准库 和 HAL 库的串口数据处理都说明一下。

3.1 标准库

首先我们需要定义一个环形缓冲区,在我们的 STM32 上也就是顶一个结构体变量。 在我们上面的 ringbuff.h 文件中有一个名为 RingBuff_t 的结构体,我们需要定义一下:

在这里插入图片描述

我们可以通过定义 BUFFER_SIZE 来定义自己的缓冲区大小。

#define BUFFER_SIZE 1024        /* 环形缓冲区的大小 */

然后在程序初始化阶段,使用 RingBuff_Init 初始化一下这个变量,如下图:

在这里插入图片描述

数据写入:

好,对于标准库而言,我们串口接收数据一般在串口中断中实现,我们实现的方式如下:

在这里插入图片描述

以前我们每次收到数据或许也会放到自己定义的缓冲区中,使用了环形缓冲区,我们直接使用Write_RingBuff 函数即可。

数据读取:

那么怎么读取数据呢?

我们在环形缓冲区实现代码里面有Read_RingBuff_Byte 读取数据的函数,读取的关键在于什么时候读!

有一种通用的方式,就是隔一段时间检查一下环形缓冲区是否为空,如果不为空,就进行读取。这个可以放在 while 循环中进行,我这里给个例子:

在这里插入图片描述

当然,除了这种等待一段时间让数据接收完成的方式,对于 STM32 而言,还有利用空闲中断(IDLE)的方式,具体实现如下:

在这里插入图片描述

当然,在标准库中使用 IDLE 中断,记得使能一下中断,如下图:

在这里插入图片描述

在程序中,如果需要清空缓存,也是直接使用 RingBuff_Init 即可。实际上都不用清空缓冲区内的数据,即便其他位置有数据也没有关系,因为我们判断是否有数据都是先通过指针位置来判断,才进行读写操作,所以内存中即便有数据,也会被覆盖。

3.2 HAL库

接下来说说 HAL 库,其实操作逻辑也是一样的,只不过 HAL 库开启接收中断的时候需要使用 HAL_UART_Receive_IT 函数 。

第一步,当然是定义 RingBuff_t 结构体变量,初始化,流程和标准库一样,只不过初始化函数需要多加上一句话,使用 HAL_UART_Receive_IT 开启接收中断,而且还需要额外定义一个变量,用来配合这个函数 ,具体的如下图:

在这里插入图片描述

使用上面 RingBuff_Init 完成初始化。

数据写入:

数据的接收也是在串口中断的时候进行,在 HAL 库中操作如下:

在这里插入图片描述

因为定义了一个变量 data_tmp 用来存放接收到的串口数据,而且每次接收完以后,接收到的数据又存放于 data_tmp

数据读取:

至于数据读取, HAL 的方式完全和 标准库一样,好像没有什么特别需要注意的,可以循环中判断缓冲区非空,进行读取数据,也可以通过 IDLE 中断,进行读取数据然后处理。

3.3 数据处理的细节说明

上面我们已经掌握了如何存环形缓冲区,什么时候取数据,怎么取数据,这里再补充一下数据处理中的一个问题。

因为我们处理数据都是一帧一帧的,我们不管接受到正确的数据,还是不需要的数据,我们都需要把一帧数据读取完。 否者会影响下一帧数据的处理。 如果不用环形缓冲区,用最简单粗暴的方法就是一旦检测到错误的数据,直接清空缓冲区,但是这在数据量大的时候很容易会导致丢包的情况。我们采用环形缓冲区就是为了尽可能的避免丢包。

所以呢即便我们收到不需要的数据,我们也需要把这个错误的数据读取完毕。

我们接受的数据协议,一般在包头后面都会跟上本条数据的长度,所以,我们可以根据读到的长度信息,使用RingBuff_ReadNByte 把剩余的数据读取完毕。

比如:

在这里插入图片描述

知道如何处理不需要的数据,基本上环形缓冲区的使用也没有什么问题了。

上一篇:【H2O2|全栈】JS进阶知识(六)ES6(2)


下一篇:Easyexcel(3-文件导出)-写入单个Sheet