STM32 | ADC数字滤波算法实现与代码案例
uint16_t ADC_IN_1(void) //ADC采集程序 { HAL_ADC_Start(hadc1);//开始ADC采集 HAL_ADC_PollForConversion(hadc1,500);//等待采集结束 if(HAL_IS_BIT_SET(HAL_ADC_GetState(hadc1), HAL_ADC_STATE_REG_EOC))//读取ADC完成标志位 { return HAL_ADC_GetValue(hadc1);//读出ADC数值 } return 0; } uint16_t ADC_IN_2(void) //ADC采集程序 { HAL_ADC_Start(hadc2);//开始ADC采集 HAL_ADC_PollForConversion(hadc2,500);//等待采集结束 if(HAL_IS_BIT_SET(HAL_ADC_GetState(hadc2), HAL_ADC_STATE_REG_EOC))//读取ADC完成标志位 { return HAL_ADC_GetValue(hadc2);//读出ADC数值 } return 0; }滤波/******************************************************************************************************************************************** *------------------------------------------------------ADC数字滤波案例程序-----下 *******************************************************************************************************************************************/ /* *一、方案 1滑动平均滤波抑制随机噪声 *适用场景ADC 值存在小幅随机波动如原始值跳动 10-20LSB无明显脉冲干扰。 *原理采集 N 次数据保存最近 N 个值计算它们的平均值每次更新时剔除最旧值加入最新值平滑波动。 * */ // 1. 定义滤波参数可根据需求调整 #define FILTER_SAMPLE_NUM 5 // 滤波采集次数建议5/7/9奇数偶数均可 #define ADC_MAX_VALUE 4095// ADC最大量程12位ADC // 2. ADC1滑动平均滤波函数 uint16_t ADC_IN_1_Filtered(void) { //静态变量的使用滑动平均滤波中的数组用 static 修饰确保每次调用函数时保留历史数据不被重新初始化。 static uint16_t adc_buf[FILTER_SAMPLE_NUM] {0}; // 静态数组保存最近N次ADC值不丢失数据 static uint8_t buf_idx 0; // 静态索引标记当前要更新的数组位置 uint32_t sum 0; // 总和用32位避免溢出 uint8_t i; // 步骤1采集1次新值存入数组替换最旧值 adc_buf[buf_idx] ADC_IN_1(); // 调用原有的ADC_IN_1获取单次值 //adc_buf[buf_idx] adc_val[0]; buf_idx (buf_idx 1) % FILTER_SAMPLE_NUM; // 索引循环0→1→...→N-1→0 // 步骤2计算数组中所有值的总和 for (i 0; i FILTER_SAMPLE_NUM; i) { sum adc_buf[i]; } // 步骤3返回平均值总和/次数 return (uint16_t)(sum / FILTER_SAMPLE_NUM); } // 3. ADC2滑动平均滤波函数与ADC1逻辑完全一致仅替换ADC_IN_2 uint16_t ADC_IN_2_Filtered(void) { static uint16_t adc_buf[FILTER_SAMPLE_NUM] {0}; static uint8_t buf_idx 0; uint32_t sum 0; uint8_t i; adc_buf[buf_idx] ADC_IN_2(); //adc_buf[buf_idx] adc_val[1]; buf_idx (buf_idx 1) % FILTER_SAMPLE_NUM; for (i 0; i FILTER_SAMPLE_NUM; i) { sum adc_buf[i]; } return (uint16_t)(sum / FILTER_SAMPLE_NUM); } /* *二、方案 2中值滤波抑制脉冲干扰 *适用场景ADC 值偶尔出现大幅跳变如突然从 2000 跳到 3000或降到 0即脉冲干扰。 *原理采集 N 次数据N 为奇数排序后取中间值可直接剔除最大 / 最小值这类异常值。 * */ // 1. 定义滤波参数N必须为奇数如5/7/9 #define MEDIAN_SAMPLE_NUM 5 // 中值滤波采集次数奇数 // 2. 辅助函数对数组排序冒泡排序简单高效适合小数组 static void Array_Sort(uint16_t arr[], uint8_t len) { uint8_t i, j; uint16_t temp; for (i 0; i len - 1; i) { for (j 0; j len - 1 - i; j) { if (arr[j] arr[j 1]) { // 交换值从小到大排序 temp arr[j]; arr[j] arr[j 1]; arr[j 1] temp; } } } } // 3. ADC1中值滤波函数 uint16_t ADC_IN_1_MedianFilter(void) { uint16_t adc_buf[MEDIAN_SAMPLE_NUM] {0}; uint8_t i; // 步骤1采集N次数据存入数组 for (i 0; i MEDIAN_SAMPLE_NUM; i) { adc_buf[i] ADC_IN_1(); //adc_buf[i] adc_val[0]; // 可选添加短延时避免ADC连续采集过快导致的误差 HAL_Delay(1); } // 步骤2对数组排序 Array_Sort(adc_buf, MEDIAN_SAMPLE_NUM); // 步骤3返回中间值索引为 len/2整数除法自动取整 return adc_buf[MEDIAN_SAMPLE_NUM / 2]; } // 4. ADC2中值滤波函数替换ADC_IN_2即可 uint16_t ADC_IN_2_MedianFilter(void) { uint16_t adc_buf[MEDIAN_SAMPLE_NUM] {0}; uint8_t i; for (i 0; i MEDIAN_SAMPLE_NUM; i) { adc_buf[i] ADC_IN_2(); //adc_buf[i] adc_val[1]; HAL_Delay(1); } Array_Sort(adc_buf, MEDIAN_SAMPLE_NUM); return adc_buf[MEDIAN_SAMPLE_NUM / 2]; } /* *三、方案 3复合滤波先中值后平均兼顾两种干扰 *适用场景ADC 同时存在随机噪声和脉冲干扰最常见场景。 *原理先通过中值滤波剔除脉冲异常值再对中值滤波后的结果进行滑动平均兼顾 “抗脉冲” 和 “平滑随机噪声” 的需求。 * */ // 1. 复用前两种方案的参数和辅助函数Array_Sort、FILTER_SAMPLE_NUM、MEDIAN_SAMPLE_NUM // 建议参数MEDIAN_SAMPLE_NUM5FILTER_SAMPLE_NUM5 // 2. ADC1复合滤波函数先中值后滑动平均 uint16_t ADC_IN_1_CompositeFilter(void) { static uint16_t avg_buf[FILTER_SAMPLE_NUM] {0}; // 保存中值滤波后的结果 static uint8_t avg_idx 0; uint32_t sum 0; uint8_t i; uint16_t median_val; // 中值滤波结果 // 步骤1先做1次中值滤波得到1个稳定值 median_val ADC_IN_1_MedianFilter(); // 步骤2将中值结果存入滑动平均数组 avg_buf[avg_idx] median_val; avg_idx (avg_idx 1) % FILTER_SAMPLE_NUM; // 步骤3计算滑动平均 for (i 0; i FILTER_SAMPLE_NUM; i) { sum avg_buf[i]; } return (uint16_t)(sum / FILTER_SAMPLE_NUM); } // 3. ADC2复合滤波函数 uint16_t ADC_IN_2_CompositeFilter(void) { static uint16_t avg_buf[FILTER_SAMPLE_NUM] {0}; static uint8_t avg_idx 0; uint32_t sum 0; uint8_t i; uint16_t median_val; median_val ADC_IN_2_MedianFilter(); avg_buf[avg_idx] median_val; avg_idx (avg_idx 1) % FILTER_SAMPLE_NUM; for (i 0; i FILTER_SAMPLE_NUM; i) { sum avg_buf[i]; } return (uint16_t)(sum / FILTER_SAMPLE_NUM); } /******************************************************************************************************************************************** *------------------------------------------------------ADC数字滤波案例程序-----上 *******************************************************************************************************************************************/显示void WU_ADC_TestDisplay(void) { LED_GREEN_TogglePin; WU_OLED_U8G2_ClearBuffer(); WU_OLED_U8G2_Printf(0,15,CHINA,原始值1号: %d,ADC_IN_1_CompositeFilter()); WU_OLED_U8G2_Printf(0,30,CHINA,原始值2号: %d,ADC_IN_2_CompositeFilter()); WU_OLED_U8G2_Printf(0,45,CHINA,电压值: %.3f V,ADC_IN_2_CompositeFilter() * 3.3f / 4095); WU_OLED_U8G2_SendBuffer(); }参考资料1. STM32 ADC外设开发手册2. 数字滤波算法相关教程本文为个人STM32开发实践笔记仅供学习交流使用。

相关新闻

C-SAM超声扫描失效分析避坑指南:从样品制备到图像判读的实战经验

C-SAM超声扫描失效分析避坑指南:从样品制备到图像判读的实战经验

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/12 3:06:46 阅读更多 →
企业IT架构转型之道:从演进式重构到落地实操的完整框架

企业IT架构转型之道:从演进式重构到落地实操的完整框架

最近好几个朋友,几乎是同一时间跑过来找我聊同一件事:公司业务越跑越快,可IT系统越来越吃力,一个新功能排期动不动就两周起,数据库扩容像挤牙膏,接口改一个字段要牵动五六个系统,领导还天天问数…

2026/10/12 3:06:46 阅读更多 →
MySQL回表查询详解:从聚簇索引到覆盖索引

MySQL回表查询详解:从聚簇索引到覆盖索引

做MySQL查询优化,总会绕不开聚簇索引、二级索引和回表查询这几个词。我见过太多人能把定义背得滚瓜烂熟,但一到线上定位慢SQL、设计联合索引、给表选主键的时候,就全对不上号了。回表查询这个概念,恰恰是把InnoDB索引设计串起来的…

2026/10/12 3:05:46 阅读更多 →

最新新闻

DAY70:前端Leader转型AI Agent工程师的认知跃迁

DAY70:前端Leader转型AI Agent工程师的认知跃迁

1. 为什么“DAY70”这个数字比“AI Agent”更值得深挖看到标题里那个醒目的“DAY70”,我第一反应不是去查AI Agent的最新论文,而是下意识翻开了自己三年前的项目日志——那会儿我正带一个五人前端团队,同时在啃LangChain源码、调试RAG pipeli…

2026/10/12 4:03:26 阅读更多 →
Kubernetes离线部署CoreDNS v1.8.0镜像导入与DNS解析实战

Kubernetes离线部署CoreDNS v1.8.0镜像导入与DNS解析实战

简介:coredns_v1.8.0.tar.gz 面向 Kubernetes 集群运维与部署人员,提供 v1.8.0 版本的 CoreDNS 镜像离线包,适用于 k8s v1.21.2 环境,可解决内网或受限网络下无法拉取官方镜像、集群 DNS 组件部署受阻的问题。压缩包共 8 个文件&a…

2026/10/12 4:03:26 阅读更多 →
iOS原生侧滑菜单实现:手势、布局与生命周期协同

iOS原生侧滑菜单实现:手势、布局与生命周期协同

简介:本资源是一份面向iOS初中级开发者的侧滑菜单栏实现方案,聚焦于点击按钮触发View位移动画的轻量级交互设计,适用于需要快速集成导航菜单或功能入口的App项目。压缩包共25个文件,包含7个Objective-C实现文件(.m/.h&…

2026/10/12 4:03:26 阅读更多 →
DataGridView 实现树形表格:自绘缩进、展开折叠与性能优化全指南

DataGridView 实现树形表格:自绘缩进、展开折叠与性能优化全指南

简介:面向 WinForms 开发者的 DataGridView 树形列表实现示例,解决表格控件无法直接展示层次数据的痛点。资源以 Visual Studio 2012 C# 为环境,提供完整项目与源码,涵盖树节点模型定义、控件扩展、数据绑定、列显隐控制、绘制展…

2026/10/12 4:03:26 阅读更多 →
Ubuntu下WPS中文显示方块?fontconfig字体配置与别名映射实战

Ubuntu下WPS中文显示方块?fontconfig字体配置与别名映射实战

简介:这份资源面向在 Ubuntu 系统下使用 WPS 办公软件、却频繁遇到字体缺失提示的用户,尤其是需要处理含特殊符号文档的办公与排版人群。当 WPS 弹出缺少 Symbol、Wingdings、Wingdings 2、Wingdings 3 等字体的警告时,文档中的符号与图形往往…

2026/10/12 4:03:26 阅读更多 →
WinForms Chart 时间轴实战:DateTime 转 OADate 与滚动条控制

WinForms Chart 时间轴实战:DateTime 转 OADate 与滚动条控制

简介:这份资源围绕VS自带Chart控件展开,面向需要在WinForms项目中实现时间轴图表的.NET开发者,重点解决x轴按时间刻度显示并配合滚动条浏览长时数据的问题。示例采用从Excel读取数据的方式,x轴时间格式为MM-dd HH:mm:ss:fff&#…

2026/10/12 4:02:25 阅读更多 →

日新闻

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

复古胶片颗粒感噪点合成器:Canvas ImageData 像素高斯杂色注入算法

在数码相机、高清显示屏与现代矢量图形技术高度发达的今天,画面可以做到绝对的锐利、平滑与无瑕。然而,当一张秋日手账插画或拍立得照片过于“平整无瑕”时,往往会散发出一种冰冷生硬的“数码塑料感(Digital Plasticity&#xff0…

2026/10/12 0:00:59 阅读更多 →
活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

活字印刷古籍线装排版:Canvas 竖排文字与栏线自适应算法

在现代网页与移动端设计中,横排(Horizontal Layout)早已经成为了绝对的主流。然而,当我们翻开泛黄的线装古籍、宋版木刻诗集,或是欣赏一张茶道雅集的手写便签时,那种**自上而下纵向书写、自右向左逐列铺展&…

2026/10/12 0:00:59 阅读更多 →
周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

周日晚间的“精神松绑减震器”:无压力情绪倾倒箱与温和轻声陪伴

每到周日的晚上八点到十点,很多人心里都会悄悄亮起一盏警示灯。 在心理学上,这种现象有一个专门的称谓——“周日夜晚焦虑症(Sunday Scaries)”。明天又是周一,闹钟又要重新在七点响彻卧房;脑海里仿佛有一个…

2026/10/12 0:00:59 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/12 0:16:30 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/12 0:16:38 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/12 0:16:43 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 10:45:37 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:53 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/11 14:36:54 阅读更多 →