之前的几篇文章对FreeRTOS的部分源码进行了分析,可以发现FreeRTOS对于任务、事件标志组、消息队列等的实现都是通过控制块的方式来操作。
比如任务(FreeRTOS源码探析之——任务调度相关)有任务控制块TCB_t,
事件标志组(FreeRTOS源码探析之——事件标志组)有事件控制块EventGroup_t,消息队列(FreeRTOS源码探析之——消息队列)有消息队列控制块Queue_t,
软件定时器(FreeRTOS源码探析之——软件定时器)有软件定时器控制块Timer_t。
使用它们前都是先创建(内存分配资源),返回一个控制块的句柄,之后就可以通过句柄来操作这个对象了。
1基本原理
以FreeRTOS的这种机制为参考,我们可以模仿着实现一个简单的滤波器,可以用于对传感器的数据进行滤波。
先来分析一下基本原理:
设定我们的滑动平均滤波器的窗口宽度为5,可以使用一个数组来实现
使用一个index来指示下次数据将要存放在数组中的位置
初始状态,滤波器数组都是0,index指向数组的起始位置
滤波器是初始状态如下图
开始阶段
原始数据依次存入滤波器数组,这时的滤波器输出有两种选择:
方式1:既然数组还未存满,就先不输出滤波结果
方式2:虽然数组还未存满,但可以计算已经存入的这几个数的平均值作为滤波输出
这两种方式只在初始阶段存在差别,本文后续编码将采用方式2。
数据第1次存满滤波器数组
数据继续存入滤波器数组,当恰好存满时,就可以计算整个数组的平均值了,作为此次的滤波结果。
滑动存储阶段
滤波器数组首次存满后,就需要进行覆盖存储了(实现滑动获取数据的效果)。
这里也有两种方式:
方式1:将新的数据(a5)覆盖存入最早的数据(a0),然后遍历数组求和,再求平均值作为输出
方式2:借用上次的求和数据sum(a0~a4),将sum先减去最早的数据(a0),加上新的数据(a5),再将新的数据(a5)覆盖存入最早的数据(a0),最后对sum除以5求平均值作为输出
相比较而言,方式2的计算量更小,本文后续编码将采用方式2。
2编码实现
下面来看一下编码实现:
滤波器控制块
参考FreeRTOS的设计方式,为我们的滑动平均滤波器设计一个控制块,也就是一个结构体,该结构体包含滤波器所需要的资源。
} SAFiter_t;
创建滤波器
参考FreeRTOS的设计方式,使用滤波器时,通过创建函数来创建一个滤波器,创建好之后,会返回一个句柄以供后续对滤波器操作。
return newFilter;}