危险网站怎么办,网站建设平台有哪些,有什么专门搜试卷做的网站,系统搭建流程目录
一 背景说明
二 原理分析
三 电压采样
四 软件滤波 一 背景说明 使用小华#xff08;华大#xff09;的MCU HC32F07X实现四个通道的 0-5V 电压采样#xff0c;并对采样结果进行滤波处理。 二 原理分析
【1】ADC原理说明#xff1a; 单片机是数字芯片#xff0c;…目录
一 背景说明
二 原理分析
三 电压采样
四 软件滤波 一 背景说明 使用小华华大的MCU HC32F07X实现四个通道的 0-5V 电压采样并对采样结果进行滤波处理。 二 原理分析
【1】ADC原理说明 单片机是数字芯片只认识由0和1组成的逻辑序列。但实际情况下生活中还有许多非0和1的模拟物理量存在例如温度湿度等。这时候往往需要使用到AD转换AD转换的英文就是Analog(模拟) to Digital(数字) 由模拟量转化为数字量同理DA则为Digital to Analog数字量转化为模拟量。 ADCAnalog to Digital Converter 的缩写中文名称模数转换器。它可以将外部的模拟信号转化成数字信号。使用它去读取IO口上的数值将不再是简单的0或1而是连续可变的数值。ADC采样就是把随时间连续变化的模拟量转换为时间离散的模拟量。 ADC几个比较重要的参数 1测量范围测量范围对于 ADC 来说就好比尺子的量程ADC 测量范围决定了你外接的设备其信号输出电压范围不能超过 ADC 的测量范围比如STM32系列的 ADC 正常就不能超过3.3VHC32F07X的ADC可以支持5V范围内的采样。 2分辨率假如 ADC 的测量范围为 0-5V分辨率设置为12位那么我们能测出来的最小电压就是 5V除以 2 的 12 次方也就是 5/40960.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进行四路的电压采样采样形式为顺序扫描参考电压为AVCC5V。
【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的使用分析串口传送过来的采样电压值我现在给定 PA00AIN0 脚的电压为2V根据参考电压5V可以计算得到采样值约为 2V * 4095 / 5V 1638实际输入的参考电压AVCC比5V小采样值实际在1690左右 由实际测试可以发现采样到的电压数据存在振荡的情况需要考虑硬件滤波或者软件滤波的方法来处理数据。 四 软件滤波
【1】增加软件滤波滑动平均滤波 方法把连续取N个采样值看成一个队列队列的长度固定为N。每次采样到一个新数据放入队尾并扔掉原来队首的一次数据(先进先出原则)。把队列中的N个数据进行算术平均运算,就可获得新的滤波结果。 N值的选取流量N12压力N4液面N4~12温度N1~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】实际测试 滤波前后效果对比如下效果还是比较明显的