缘由:
做电子秤的时候,最初用的是低通滤波算法,数字总是很难稳定,基于一个中心值跳来跳去,看了一下别人的算法都是基于平均数的。于是就设想了一个这样的滤波算法。
原理:
1、因为数据源是围绕一个中心点上下跳动的,所以最终想得到的还是那个中位数,就是他的分布中心,而不是平均中心。
2、因为是基于ADC的采样,数据是有穷的整数,所以一定存在大量的相同数据。这些相同数据是可以合并到一个节点上的。
3、一定时间内统计数量最多的节点就是需要的分布中心。
实现:
1、链表
static struct
{
unsigned long lengthMax; //链表最大长度
unsigned long lengthNow; //链表现长度
unsigned long pos; //中间节点的数量位置
unsigned char LorR; //用于记录决定新值为中间值时 左插还是右插
TP_List *pMid; //中间值节点的地址
TP_List *Head; //当前链表的头地址
TP_List *Tail; //当前链表的尾地址
} Para;
初始化
void MidLinkInit(unsigned int l)
{
// 申请一个地址用于链表的头
// 此节点的除地址外的所有信息均为0
// 将链表属性结构体中的中间值变量设置为此地址
TP_List *p; // 声明一个节点指针
GetAPlace(&p); // 申请一个节点空间
Para.Head = p; // 链表头节点
Para.Tail = p; // 链表尾节点
Para.pMid = p; // 中间值节点 这个节点的值就是最终需要的那个
Para.lengthMax = l; // 链表的最大长度
Para.lengthNow = 1; // 链表的现有长度
Para.pos = 1;
}
2、一个基本节点需要包括以下要素:该节点的值、该节点的重复数量、前一个节点的地址和后一个节点的地址。
typedef struct TP_List
{
unsigned long data; //该节点的值
unsigned long num; //该节点重复数量
struct TP_List *prior; //前一个节点的指针
struct TP_List *next; //下一节点的指针
} TP_List;
3、数据的插入类型
typedef enum
{
MidInsert, //中值中插
LLInsert, //小值左插
LMInsert, //小值中插
LRInsert, //小值右插
BLInsert, //大值左插
BMInsert, //大值中插
BRInsert, //大值右插
} TP_Insert;
未完成。。。