
目录前言一、中位值滤波核心本质与应用场景1. 什么是中位值滤波2. 解决的核心痛点3. 典型工业落地场景二、核心实现原理1. 数据采样机制2. 冒泡排序机制3. 中值取值逻辑4. 算法优势逻辑三、工业级设计规范1、封装设计2、接口设计3、鲁棒约束4、线程安全四、完整可复用源码1、filter_mid.h2、filter_mid.c五、实战演示六、进阶优化方向七、面试考点与易错坑点1、面试问答2、常见坑点总结前言嵌入式传感器采样过程中最头疼的不是小幅抖动而是偶然尖峰干扰、突发跳变、雷击电磁脉冲、接触抖动。普通滑动平均滤波会被尖峰值带偏导致数据失真、控制误动作。中位值滤波专门针对偶然突变、异常极值做过滤排序取中间值彻底剔除突发错误采样点是工业采集系统必备抗干扰算法。一、中位值滤波核心本质与应用场景1. 什么是中位值滤波中位值滤波原理连续采集 N 组数据对数据进行从小到大排序舍弃最大值与最小值取中间位置数值作为有效采样值。从算法机制上直接屏蔽突发极值干扰保留真实稳态数据。核心特性极强抗尖峰干扰能力不跟随异常跳变、不被毛刺带偏算法逻辑简单、无复杂浮点运算输出数据平稳、可信度高纯静态运算无内存碎片2. 解决的核心痛点解决 ADC 瞬时高压脉冲干扰导致的数值乱飞。解决机械接触抖动、按键抖动带来的采样突变。解决工业现场电磁干扰导致的偶然错值。解决滑动平均无法过滤尖峰噪声的短板。解决低端设备无硬件滤波、纯软件降噪兜底需求。3. 典型工业落地场景压力传感器、称重传感器抗突变滤波。ADC 电压、电流采集抗脉冲干扰。机械开关、模拟量按键采样防抖。温湿度传感器偶然跳变数据剔除。工控设备强电磁环境模拟量采集。二、核心实现原理1. 数据采样机制一次性采集固定点数原始数据存入缓存数组。2. 冒泡排序机制对采样数组进行升序排序规整数据分布。3. 中值取值逻辑排序后舍弃两头极值取数组中间下标数据。奇数窗口保证唯一中值无平分歧义工程最稳定。4. 算法优势逻辑平均值会被极大值、极小值严重影响中位值完全无视极值只反映群体真实稳态水平。三、工业级设计规范1、封装设计结构体多实例封装支持多路传感器独立滤波。可自由配置滤波窗口大小适配不同降噪强度。2、接口设计接口功能说明filter_mid_init初始化中位值滤波对象filter_mid_calc输入单路采样值输出滤波结果filter_mid_clear重置滤波缓存状态3、鲁棒约束窗口大小强制奇数规避偶数中值歧义。空指针、非法参数全部拦截。排序安全边界校验杜绝数组越界。4、线程安全单任务独立调用天然安全 多线程并发操作需加互斥锁保护缓冲区。四、完整可复用源码1、filter_mid.h#ifndef FILTER_MID_H #define FILTER_MID_H #include stdint.h #include stdbool.h #ifdef __cplusplus extern C { #endif // 最大滤波窗口 #define FILTER_MID_MAX_WIN 15 typedef struct { int32_t buf[FILTER_MID_MAX_WIN]; uint8_t idx; uint8_t win_size; } filter_mid_t; /** * brief 中位值滤波初始化 * param filter 滤波句柄 * param win_size 滤波窗口(建议奇数 3/5/7/9) */ void filter_mid_init(filter_mid_t *filter, uint8_t win_size); /** * brief 中位值滤波运算 * param filter 滤波句柄 * param val 原始采样值 * return 滤波后稳定值 */ int32_t filter_mid_calc(filter_mid_t *filter, int32_t val); /** * brief 清空滤波缓存重置状态 * param filter 滤波句柄 */ void filter_mid_clear(filter_mid_t *filter); #ifdef __cplusplus } #endif #endif2、filter_mid.c#include filter_mid.h // 内部冒泡排序静态函数 static void filter_sort(int32_t *buf, uint8_t len) { for(uint8_t i 0; i len - 1; i) { for(uint8_t j 0; j len - 1 - i; j) { if(buf[j] buf[j 1]) { int32_t temp buf[j]; buf[j] buf[j 1]; buf[j 1] temp; } } } } void filter_mid_init(filter_mid_t *filter, uint8_t win_size) { if(filter NULL || win_size 0 || win_size FILTER_MID_MAX_WIN) return; // 强制修正为奇数窗口 if(win_size % 2 0) win_size 1; filter-idx 0; filter-win_size win_size; for(uint8_t i 0; i FILTER_MID_MAX_WIN; i) { filter-buf[i] 0; } } int32_t filter_mid_calc(filter_mid_t *filter, int32_t val) { if(filter NULL || filter-win_size 0) return val; // 填充采样缓冲区 filter-buf[filter-idx] val; // 缓冲区未满直接返回当前值不做滤波 if(filter-idx filter-win_size) { return val; } // 缓冲区已满开始排序取中值 filter_sort(filter-buf, filter-win_size); // 取中间下标 uint8_t mid_pos filter-win_size / 2; int32_t mid_val filter-buf[mid_pos]; // 清空索引重新新一轮采样 filter-idx 0; return mid_val; } void filter_mid_clear(filter_mid_t *filter) { if(filter NULL) return; filter-idx 0; for(uint8_t i 0; i FILTER_MID_MAX_WIN; i) { filter-buf[i] 0; } }五、实战演示#include stdio.h #include filter_mid.h int main(void) { filter_mid_t adc_filter; // 5点中位值滤波 filter_mid_init(adc_filter, 5); // 模拟带尖峰干扰的采样数据 int32_t raw_data[] {230, 232, 500, 231, 229, 233, 228, 230, 10, 231}; for(int i 0; i sizeof(raw_data)/sizeof(raw_data[0]); i) { int32_t out filter_mid_calc(adc_filter, raw_data[i]); printf(原始值%d \t滤波值%d\r\n, raw_data[i], out); } return 0; }六、进阶优化方向中位值 均值复合滤波先中值去极值再平均平滑同时抗尖峰 消抖动工业最常用复合算法。自适应窗口滤波根据数据抖动强度自动切换 3/5/7 窗口抖动大加大窗口快速响应减小窗口。滑动中位值优化摒弃整组刷新采用滑动缓存提升输出刷新率降低数据滞后。限幅中位滤波增加前后帧差值阈值超差直接剔除进一步提升稳定性。七、面试考点与易错坑点1、面试问答Q1中位值滤波的核心作用是什么适合什么噪声答核心作用是剔除突发尖峰、极值干扰。专门对抗瞬时脉冲干扰、偶然跳变噪声对周期性抖动、小幅连续噪声效果一般。Q2中位值滤波和滑动平均滤波如何选型答数据偶尔跳变、有毛刺尖峰 → 选中位值滤波 数据小幅持续抖动、需要极度平滑 → 选滑动平均滤波 工业高精度场景通常两者级联使用。Q3为什么工程上滤波窗口必须使用奇数答偶数窗口存在两个中间值无唯一中值需要平均计算引入额外误差与不确定性奇数窗口中点唯一输出稳定、无歧义。Q4中位值滤波的优缺点分别是什么答优点抗脉冲干扰极强、稳态精度高、无极值偏移 缺点响应速度慢、连续周期性抖动无法滤除、存在采样滞后。Q5为什么中值滤波不能用于快速变化的动态数据答需要攒满一组数据再计算输出刷新频率低、滞后明显跟随快速变化波形能力差只适合稳态监测场景。Q6如何解决中值滤波响应慢的问题答1、减小滤波窗口2、改用滑动中值算法3、中值 平均复合滤波4、动态自适应窗口切换。2、常见坑点使用偶数窗口导致中值计算逻辑混乱。窗口设置过大数据严重滞后实时性丢失。多传感器共用同一个滤波句柄数据错乱覆盖。未判空指针传入 NULL 导致死机。误用中值滤波处理连续抖动信号降噪效果极差。总结中位值滤波是嵌入式抗脉冲干扰的核心算法专门弥补均值滤波无法去尖峰的短板。算法稳定、逻辑简单、工程容错率高是工业传感器采集、模拟量检测、抗电磁干扰的基础必备组件。与滑动平均滤波搭配使用可以覆盖 90% 以上嵌入式数据降噪场景。创作不易如果对你有帮助欢迎点赞、收藏、转发。