滤波算法 · 2022年 11月 9日 0

基于链表的中值滤波

缘由:
做电子秤的时候,最初用的是低通滤波算法,数字总是很难稳定,基于一个中心值跳来跳去,看了一下别人的算法都是基于平均数的。于是就设想了一个这样的滤波算法。

原理:
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;

未完成。。。