当前位置: 首页 > news >正文

【嵌入式】HC32F07X ADC采样及软件滤波

目录

一 背景说明

二 原理分析

三 电压采样

四 软件滤波


一 背景说明

        使用小华(华大)的MCU HC32F07X实现四个通道的 0-5V 电压采样,并对采样结果进行滤波处理。

二 原理分析

【1】ADC原理说明:

        单片机是数字芯片,只认识由0和1组成的逻辑序列。但实际情况下,生活中还有许多非0和1的模拟物理量存在,例如温度,湿度等。这时候往往需要使用到AD转换,AD转换的英文就是Analog(模拟) to Digital(数字) ,由模拟量转化为数字量;同理DA,则为Digital to Analog,数字量转化为模拟量。
        ADC,Analog to Digital Converter 的缩写,中文名称模数转换器。它可以将外部的模拟信号转化成数字信号。使用它去读取IO口上的数值将不再是简单的0或1,而是连续可变的数值。ADC采样就是把随时间连续变化的模拟量转换为时间离散的模拟量。

ADC几个比较重要的参数:

(1)测量范围:测量范围对于 ADC 来说就好比尺子的量程,ADC 测量范围决定了你外接的设备其信号输出电压范围,不能超过 ADC 的测量范围(比如,STM32系列的 ADC 正常就不能超过3.3V,HC32F07X的ADC可以支持5V范围内的采样)。

(2)分辨率:假如 ADC 的测量范围为 0-5V,分辨率设置为12位,那么我们能测出来的最小电压就是 5V除以 2 的 12 次方,也就是 5/4096=0.00122V。很明显,分辨率越高,采集到的信号越精确,所以分辨率是衡量 ADC 的一个重要指标。

(3)采样时间:当 ADC 在某时刻采集外部电压信号的时候,此时外部的信号应该保持不变,但实际上外部的信号是不停变化的。所以在 ADC 内部有一个保持电路,保持某一时刻的外部信号,这样 ADC 就可以稳定采集了,保持这个信号的时间就是采样时间。

(4)采样率:也就是在一秒的时间内采集多少次。很明显,采样率越高越好,当采样率不够的时候可能会丢失部分信息,所以 ADC 采样率是衡量 ADC 性能的另一个重要指标(详细参考信号处理方向书籍)。

【2】HC32F07X的ADC外设:

        HC32F07X内部集成了一个 12 位高精度、高转换速率的逐次逼近型模数转换器(SAR ADC)模块。具有以下特性:

■ 12 位转换精度;
■ 1M SPS 转换速度;
■ 41 个输入通道,包括 36 路外部管脚输入、 1 路内部温度传感器电压、 1 路 1/3 AVCC 电压、
1 路内建 BGR 1.2V 电压、 2 路 DAC 输出;
■ 4 种参考源: AVCC 电压、 ExRef 引脚、内置 1.5v 参考电压、内置 2.5v 参考电压;
■ ADC 的电压输入范围: 0~Vref;
■ 4 种转换模式:单次转换、顺序扫描连续转换、插队扫描连续转换、连续转换累加;
■ 输入通道电压阈值监测;
■ 软件可配置 ADC 的转换速率;
■ 内置信号跟随器,可转换高阻信号;
■ 支持片内外设自动触发 ADC 转换,有效降低芯片功耗并提高转换的实时性

        ADC框图如下:

        转换时序和转换速度如下所示:一次完整的 ADC 转换由转换过程及逐次比较过程组成。其中转换过程需要 4~12 个 ADCCLK,由 ADC_CR0.SAM 配置;逐次比较过程需要 16 个 ADCCLK。所以,一次 ADC转换共需要 20~28 个 ADCCLK。

        ADC 转换速度的单位为 SPS,即每秒进行多少次 ADC 转换。 ADC 转换速度的计算方法为: ADCCLK的频率 / 一次 ADC 转换所需要的 ADCCLK 的个数。

        ADC 转换速度与 ADC 参考电压及 AVCC 电压相关,最高转换速度如下表所示:

        更多详细的内容可以参考HC32F07X芯片的DATASHEET。

三 电压采样

        选用引脚 PA00、PA01、PA02、PA03进行四路的电压采样,采样形式为顺序扫描,参考电压为AVCC(5V)

【1】ADC初始化GPIO

//模拟量输入引脚定义
#define SPL_AIN0_PORT       (GpioPortA)
#define SPL_AIN0_PIN        (GpioPin0)
#define SPL_AIN1_PORT       (GpioPortA)
#define SPL_AIN1_PIN        (GpioPin1)
#define SPL_AIN2_PORT       (GpioPortA)
#define SPL_AIN2_PIN        (GpioPin2)
#define SPL_AIN3_PORT       (GpioPortA)
#define SPL_AIN3_PIN        (GpioPin3)/**************************************************************************
* 函数名称: ADC_Init
* 功能描述: ADC初始化GPIO
**************************************************************************/
void ADC_Init(void)
{Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio, TRUE);Gpio_SetAnalogMode(SPL_AIN0_PORT, SPL_AIN0_PIN);        //PA00 (AIN0)Gpio_SetAnalogMode(SPL_AIN1_PORT, SPL_AIN1_PIN);        //PA01 (AIN1)Gpio_SetAnalogMode(SPL_AIN2_PORT, SPL_AIN2_PIN);        //PA02 (AIN2)Gpio_SetAnalogMode(SPL_AIN3_PORT, SPL_AIN3_PIN);        //PA03 (AIN3)
}

【2】ADC初始化配置

/**************************************************************************
* 函数名称: ADC_Cfg
* 功能描述: ADC初始化配置
**************************************************************************/
void ADC_Cfg(void)
{stc_adc_cfg_t              stcAdcCfg;DDL_ZERO_STRUCT(stcAdcCfg);Sysctrl_SetPeripheralGate(SysctrlPeripheralAdcBgr, TRUE); Bgr_BgrEnable();        ///< 开启BGR///< ADC 初始化配置stcAdcCfg.enAdcMode         = AdcScanMode;              ///<采样模式-扫描stcAdcCfg.enAdcClkDiv       = AdcMskClkDiv1;            ///<采样分频-1stcAdcCfg.enAdcSampCycleSel = AdcMskSampCycle8Clk;      ///<采样周期数-8stcAdcCfg.enAdcRefVolSel    = AdcMskRefVolSelAVDD;      ///<参考电压选择-VCCstcAdcCfg.enAdcOpBuf        = AdcMskBufEnable;          ///<放大器BUF配置-开stcAdcCfg.enInRef           = AdcMskInRefDisable;       ///<内部参考电压使能-关stcAdcCfg.enAdcAlign        = AdcAlignRight;            ///<转换结果对齐方式-右Adc_Init(&stcAdcCfg);
}

【3】ADC顺序扫描功能配置

/**************************************************************************
* 函数名称: ADC_SqrCfg
* 功能描述: ADC顺序扫描功能配置
**************************************************************************/
void ADC_SqrCfg(void)
{stc_adc_sqr_cfg_t          stcAdcSqrCfg;DDL_ZERO_STRUCT(stcAdcSqrCfg);///< 顺序扫描模式功能及通道配置///< 注意:扫描模式下,当配置转换次数为n时,转换通道的配置范围必须为[SQRCH(0)MUX,SQRCH(n-1)MUX]stcAdcSqrCfg.bSqrDmaTrig = FALSE;stcAdcSqrCfg.u8SqrCnt    = 4;Adc_SqrModeCfg(&stcAdcSqrCfg);Adc_CfgSqrChannel(AdcSQRCH0MUX, AdcExInputCH0);Adc_CfgSqrChannel(AdcSQRCH1MUX, AdcExInputCH1);Adc_CfgSqrChannel(AdcSQRCH2MUX, AdcExInputCH2);Adc_CfgSqrChannel(AdcSQRCH3MUX, AdcExInputCH3);///< ADC 中断使能Adc_EnableIrq();EnableNvic(ADC_DAC_IRQn, IrqLevel3, TRUE);///< 启动顺序扫描采样Adc_SQR_Start();
}

【4】ADC中断服务子程序

uint32_t spl_buff[4];/**************************************************************************
* 函数名称: Adc_IRQHandler
* 功能描述: ADC中断服务函数
**************************************************************************/
void Adc_IRQHandler(void)
{if(TRUE == Adc_GetIrqStatus(AdcMskIrqSqr)){Adc_ClrIrqStatus(AdcMskIrqSqr);spl_buff[0] = Adc_GetSqrResult(AdcSQRCH0MUX);spl_buff[1] = Adc_GetSqrResult(AdcSQRCH1MUX);spl_buff[2] = Adc_GetSqrResult(AdcSQRCH2MUX);spl_buff[3] = Adc_GetSqrResult(AdcSQRCH3MUX);Adc_SQR_Stop();}
}

【5】主函数调用

int32_t main(void)
{//采样模块ADC_Init();ADC_Cfg();ADC_SqrCfg();//调试模块Dbg_Init();Dbg_Cfg();Dbg_Printf("Hello World!\n");while(1){//采样Adc_SQR_Start();Dbg_Printf("Ch1:%d\n", spl_buff[0]);  //FireWater协议delay1ms(10);}
}

【6】实际测试

        使用 VOFA+ 软件(【注1】:VOFA+的下载地址为VOFA+官网)( 【注2】:VOFA+的使用方法参考博文VOFA+的使用),分析串口传送过来的采样电压值,我现在给定 PA00(AIN0) 脚的电压为2V,根据参考电压5V可以计算得到采样值约为 2V * 4095 / 5V = 1638(实际输入的参考电压AVCC比5V小,采样值实际在1690左右):

        由实际测试可以发现,采样到的电压数据存在振荡的情况,需要考虑硬件滤波或者软件滤波的方法来处理数据

四 软件滤波

【1】增加软件滤波(滑动平均滤波

方法:把连续取N个采样值看成一个队列,队列的长度固定为N。每次采样到一个新数据放入队尾,并扔掉原来队首的一次数据(先进先出原则)。把队列中的N个数据进行算术平均运算,就可获得新的滤波结果。
N值的选取:流量,N=12;压力:N=4;液面,N=4~12;温度,N=1~4
优点:对周期性干扰有良好的抑制作用,平滑度高;试用于高频振荡的系统
缺点:灵敏度低;对偶然出现的脉冲性干扰的抑制作用较差,不适于脉冲干扰较严重的场合
比较浪费RAM(改进方法,减去的不是队首的值,而是上一次得到的平均值)

        方法参考这一篇博文,其中详细列举了不少ADC采样滤波的算法(ADC采样滤波算法)。我这边考虑的是滑动平均滤波,对博文中的算法做了一些改动:

/**************************************************************************
* 函数名称: analogAvgFilter
* 功能描述: 模拟量输入滑动滤波处理
**************************************************************************/
#define CACHE_LEN 5uint32_t analogAvgFilter(uint32_t in_data)
{static uint32_t in_buf[CACHE_LEN];uint32_t sum = 0;uint8_t  i = 0;for(i = 0; i < (CACHE_LEN-1); i ++){in_buf[i] = in_buf[i + 1];sum = sum + in_buf[i];}in_buf[CACHE_LEN-1] = in_data;sum = sum + in_buf[CACHE_LEN-1];return (sum / CACHE_LEN);
}

【2】主函数调用

uint32_t result_spl;int32_t main(void)
{//采样模块ADC_Init();ADC_Cfg();ADC_SqrCfg();//调试模块Dbg_Init();Dbg_Cfg();Dbg_Printf("Hello World!\n");while(1){//采样Adc_SQR_Start();result_spl = analogAvgFilter(spl_buff[0]);Dbg_Printf("Ch1:%d,%d\n", spl_buff[0], result_spl);  //FireWater协议delay1ms(10);}
}

【3】实际测试

        滤波前后效果对比如下,效果还是比较明显的:

相关文章:

【嵌入式】HC32F07X ADC采样及软件滤波

目录 一 背景说明 二 原理分析 三 电压采样 四 软件滤波 一 背景说明 使用小华&#xff08;华大&#xff09;的MCU HC32F07X实现四个通道的 0-5V 电压采样&#xff0c;并对采样结果进行滤波处理。 二 原理分析 【1】ADC原理说明&#xff1a; 单片机是数字芯片&#xff0c;…...

VSCode snippets

生成工具&#xff1a;https://snippet-generator.app/ VSCode snippets&#xff1a;https://code.visualstudio.com/docs/editor/userdefinedsnippets#/ VS Code 中的 Snippets 是一种快捷方式&#xff0c;可以帮助你更快地编写代码。你可以创建自己的 Snippets&#xff0c;也…...

openEuler 22.03 LTS 环境使用 Docker Compose 一键部署 JumpServer (all-in-one 模式)

环境回顾 上一篇文章中&#xff0c;我们讲解了 openEuler 22.03 LTS 安装 Docker CE 和 Dcoker Compose&#xff0c;部署的软件环境版本分别如下&#xff1a; OS 系统&#xff1a;openEuler 22.03 LTS(openEuler-22.03-LTS-x86_64-dvd.iso)Docker Engine&#xff1a;Docker C…...

宏电5G RedCap工业智能网关获首个中国移动5G物联网开放实验室5G及轻量化产品能力认证

10月21日&#xff0c;2023世界物联网博览会——中国移动物联网开发者大会暨物联网产业论坛在无锡圆满举行。宏电股份参与中国移动5G物联网开放实验室5G及轻量化产品能力认证成果授牌仪式&#xff0c;并获得认证证书。 此次认证主要对产品功能、产品性能、RedCap网络兼容性进行测…...

MySQL查询今日、昨日、最近七天的数据

查询今日数据 sql语句&#xff1a; SELECT * FROM short_oper_log WHERE to_days(login_time) to_days(now());运行结果&#xff1a; 查询昨日数据 sql语句&#xff1a; SELECT * FROM short_oper_log WHERE DATEDIFF(login_time,NOW()) -1;运行结果&#xff1a; 额外…...

Oracle 19c新特性:DBCA静默模式克隆远端PDB

源库为ORCL中的orclpdb1&#xff0c;目标库为ORCL2。版本均为19c。 我们将利用19c中dbca新支持的-createFromRemotePDB选项来从远端克隆PDB。 确认源库中有业务数据&#xff1a; SQL> connect hrorclpdb1 Enter password: Connected. SQL> select count(*) from hr.em…...

css:如何通过不同的值,改变盒子的样式和字体颜色通过computed而不是v-if

在使用uni-app编写功能时&#xff0c;可以通过computed方法来实现根据num这个值也可以是后端传过来的值只要是number类型都可以。不同取值来修改盒子的背景颜色和字体颜色。首先&#xff0c;在data中定义一个num来存储当前的值&#xff0c;然后在computed中创建一个样式对象&am…...

做外贸真诚是最好的套路

在朋友圈发装柜的照片&#xff0c;之前合作的一些其他供应商看到了就问&#xff1a;最近生意怎样啊&#xff1f;看着好像挺多货出的&#xff0c;怎么最近都没跟我拿货啊&#xff1f; 空了我就回复&#xff1a;最近一般啊&#xff0c;有人做得很好&#xff0c;单很多&#xff0…...

RPA厂商大比拼,哪家才更适合您?

引言&#xff1a;随着数字化时代的到来&#xff0c;自动化已成为推动企业数字化发展的关键举措之一&#xff0c;RPA作为自动化中的重要技术之一&#xff0c;可为企业提供了实现业务流程自动化的强大工具。然而&#xff0c;如何选择适合自己的RPA厂商也是各大企业现在面临的难题…...

更换网络ip地址怎么设置

在互联网时代&#xff0c;网络已经成为我们生活中不可或缺的一部分。随着网络技术的不断发展&#xff0c;IP地址作为网络通信中的重要标识&#xff0c;其重要性日益凸显。在某些情况下&#xff0c;我们需要更换网络IP地址以保护自己的信息安全。那么&#xff0c;更换网络IP地址…...

开始学习Go编程

探索Go编程中的语法、数据类型和控制流 Go&#xff0c;又称为Golang&#xff0c;因其简单性、性能和效率而广受欢迎。在本文中&#xff0c;我们将深入研究构成Go编程语言基础的基本概念。从理解其语法和数据类型到掌握控制流和函数&#xff0c;我们将为您提供启动Go编程之旅所…...

《SpringBoot项目实战》第五篇—接口发生异常如何统一处理

系列文章导航 第一篇—接口参数的一些弯弯绕绕 第二篇—接口用户上下文的设计与实现 第三篇—留下用户调用接口的痕迹 第四篇—接口的权限控制 第五篇—接口发生异常如何统一处理 本文参考项目源码地址&#xff1a;summo-springboot-interface-demo 前言 大家好&#xff01;…...

vue+golang上传微信头像

<button class"avatar" open-type"chooseAvatar" chooseavatar"onChooseAvatar"><image :src"avatarUrl" class"avatar-img"></image></button> // 微信头像修改onChooseAvatar(e) {this.uploadFil…...

JavaScript charCodeAt() 方法

charCodeAt() 方法是 JavaScript 字符串对象的一个方法&#xff0c;它用于返回给定位置的字符的 Unicode 编码值&#xff08;整数&#xff09;。Unicode 编码是一个标识字符的数字&#xff0c;它包含了世界上几乎所有字符的映射&#xff0c;包括常见字符、特殊字符和表情符号。…...

Talk | 纽约州立宾汉姆顿大学博士生丁琰:开放环境中机器人的任务与动作规划

本期为TechBeat人工智能社区第541期线上Talk。 北京时间10月26日&#xff08;周四&#xff09;20:00&#xff0c;纽约州立宾汉姆顿大学博士生—丁琰的Talk已准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “开放环境中机器人的任务与动作规划”&#xff0…...

2023年Q3企业邮箱安全性报告:境内钓鱼邮件超过境外攻击

10月25日&#xff0c;Coremail邮件安全联合北京中睿天下信息技术有限公司发布《2023年第三季度企业邮箱安全性研究报告》。2023年第三季度企业邮箱安全呈现出何种态势&#xff1f;作为邮箱管理员&#xff0c;我们又该如何做好防护&#xff1f; 以下为精华版阅读&#xff0c;如需…...

WebSocket 原理揭秘:让你彻底搞懂 Websocket 原理

WebSocket 的原理 WebSocket 是什么&#xff1f; WebSocket 是一种新型的协议&#xff0c;它可以在客户端和服务器之间建立长连接&#xff0c;实现双向通信。在传统的 HTTP 协议中&#xff0c;当客户端向服务器发送请求后&#xff0c;服务器会返回响应&#xff0c;然后连接就…...

react中的函数式组件和类式组件

一、函数组件 1. 定义函数组件 在React中&#xff0c;函数组件&#xff08;Functional Component&#xff09;是一种通过纯粹的JavaScript函数定义的UI组件。函数组件采用函数的方式接收一个输入参数 props&#xff0c;并返回一个React元素或者一组React元素作为输出。定义函…...

Visual Studio 2022 设置 PySide6 扩展工具

前言 本人不想电脑上装一堆的IDE,所以把 Python 开发也交给了 Visual Studio,如果你不是用 Visual Studio 做 Python 开发,下文就不用看了。 PySide简介 PySide跟PyQt类似,都是支持Python的Qt包,不同的是,PyQt是第三方的,PySide是Qt官方的。 PySide的推出比PyQt晚很…...

【高效开发工具系列】Postman

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kuan 的首页,持续学…...

【实战指南】STM32CubeMX UART配置进阶:从阻塞到中断+DMA的高效数据通信

1. UART通信模式选择指南 第一次接触STM32的UART通信时&#xff0c;很多人都会纠结该用哪种模式。我在实际项目中尝试过所有模式&#xff0c;总结下来就是&#xff1a;没有最好的模式&#xff0c;只有最适合当前场景的模式。先说说三种典型场景&#xff1a; 调试打印&#xff1…...

如何免费高效优化电脑性能:UXTU终极调优指南

如何免费高效优化电脑性能&#xff1a;UXTU终极调优指南 【免费下载链接】Universal-x86-Tuning-Utility Unlock the full potential of your Intel/AMD based device. 项目地址: https://gitcode.com/gh_mirrors/un/Universal-x86-Tuning-Utility Universal x86 Tuning…...

AI Agent产品经理的新思维:从功能设计到AI原生产品的方法论转型

AI Agent产品经理的新思维&#xff1a;从功能设计到AI原生产品的方法论转型 各位产品同行、AI从业者&#xff0c;大家好&#xff01;我是连续3年深耕AI工具Agent产品、从C端信息流&#xff08;今日头条/抖音生态&#xff09;PM成功转型AI原生垂直工具PM的张小白——过去两年&am…...

企业级后端四层架构实战:从理论到代码的清晰落地

1. 项目概述&#xff1a;一个四层架构的实战蓝图最近在GitHub上看到一个挺有意思的项目&#xff0c;叫BTawaifi/four-layer-system。光看名字&#xff0c;你可能会觉得这又是一个老生常谈的“四层架构”理论教程&#xff0c;无非是Controller、Service、Repository那套东西。但…...

gwadd:轻量级Git仓库组管理工具,提升多项目开发效率

1. 项目概述&#xff1a;一个被低估的Git仓库管理利器如果你和我一样&#xff0c;日常工作中需要频繁地在多个Git仓库之间穿梭&#xff0c;处理各种依赖、子模块&#xff0c;或者仅仅是同步一堆相关的项目代码&#xff0c;那么你一定对那种重复、繁琐的切换和操作感到头疼。今天…...

CFD工程师必看:TVD格式选型指南——从SUPERBEE到UMIST,哪个才是你的菜?

CFD工程师必看&#xff1a;TVD格式选型实战指南——从工程场景到最优解 在计算流体力学(CFD)的世界里&#xff0c;TVD格式就像赛车手的轮胎选择——没有绝对的好坏&#xff0c;只有场景的适配。当你在汽车外气动分析中遇到激波振荡&#xff0c;或在燃烧模拟中面临虚假扩散时&am…...

Godot引擎实验项目解析:从角色控制到着色器优化的实战指南

1. 项目概述与核心价值如果你是一名游戏开发者&#xff0c;尤其是对独立游戏开发充满热情&#xff0c;那么“Godot”这个名字对你来说一定不陌生。它是一个功能强大、开源免费的游戏引擎&#xff0c;以其轻量、高效和友好的编辑器而闻名。然而&#xff0c;引擎本身只是一个工具…...

基于RP2040的客制化宏键盘:从硬件设计到KMK固件开发全攻略

1. 项目概述与核心价值最近在折腾一个挺有意思的开源项目&#xff0c;叫clawdpad&#xff0c;作者是kudretyilmazz。乍一看这个名字&#xff0c;可能有点摸不着头脑&#xff0c;但如果你对机械键盘、客制化输入设备或者桌面自动化感兴趣&#xff0c;那这个项目绝对值得你花时间…...

Linux权限继承与umask配置实践

Linux权限继承与umask配置实践很多协作目录问题并不是因为当前权限错了&#xff0c;而是因为新建文件的默认权限总是不符合预期。背后的核心变量之一就是 umask。中级阶段如果不理解默认权限是怎么生成的&#xff0c;就会陷入“每次都手工 chmod”的低效循环。一、默认权限不是…...

Arm Neoverse-V2/V3缓存与内存参数优化指南

1. Arm Neoverse-V2/V3集群架构概述Arm Neoverse系列处理器作为数据中心和基础设施领域的重要计算引擎&#xff0c;其V2/V3代架构在缓存子系统和内存管理方面进行了显著优化。作为从业多年的系统架构师&#xff0c;我认为理解这些处理器的参数配置对性能调优至关重要。Neoverse…...