HC32L190 ADC采集
一、ADC AIN2 驱动
使用外接3.3V采集范围
二、代码
hd_adc.c
#include "hd_adc.h"
#include "bgr.h"
#include <stdio.h>#define FILTER_SIZE 16 // 滑动平均窗口
#define ADC_TIMEOUT 10000 // 超时计数限制// 初始化 ADC(阻塞模式,无中断)
void Hd_ADC_Init(void)
{stc_adc_cfg_t stcAdcCfg;Gpio_SetAnalogMode(GpioPortA, GpioPin2); // PA02 -> AIN2Sysctrl_SetPeripheralGate(SysctrlPeripheralAdcBgr, TRUE);Bgr_BgrEnable(); // 启用内部基准,提高精度stcAdcCfg.enAdcMode = AdcSglMode;stcAdcCfg.enAdcClkDiv = AdcMskClkDiv2;stcAdcCfg.enAdcSampCycleSel = AdcMskSampCycle12Clk;stcAdcCfg.enAdcRefVolSel = AdcMskRefVolSelAVDD; // 使用外部3.3V作为参考stcAdcCfg.enAdcOpBuf = AdcMskBufDisable;stcAdcCfg.enInRef = AdcMskInRefEnable;stcAdcCfg.enAdcAlign = AdcAlignRight;Adc_Init(&stcAdcCfg);Adc_CfgSglChannel(AdcExInputCH2); // AIN2 通道
}// 单次阻塞式采集(带超时)
uint16_t Adc_Read(void)
{Adc_SGL_Start(); // 启动采样uint32_t timeout = 0;while (!Adc_GetIrqStatus(AdcMskIrqSgl)) {if (++timeout > ADC_TIMEOUT)return 0xFFFF; // 超时}uint16_t result = Adc_GetSglResult();Adc_ClrIrqStatus(AdcMskIrqSgl); // 清中断标志return result;
}// 增量滑动平均滤波器(适合电压变化缓慢)
uint16_t Adc_FilteredRead(void)
{static uint16_t buffer[FILTER_SIZE] = {0};static uint8_t index = 0;static uint32_t sum = 0;static uint8_t filled = 0;uint16_t raw = Adc_Read();if (raw == 0xFFFF) return 0xFFFF;// 减去旧值,加上新值sum -= buffer[index];sum += raw;buffer[index] = raw;index = (index + 1) % FILTER_SIZE;if (filled < FILTER_SIZE) filled++;return sum / filled;
}
hd_adc.h
#ifndef HD_ADC_H
#define HD_ADC_H#include "adc.h"
#include "gpio.h"
#include "bgr.h"void Hd_ADC_Init(void);
uint16_t Adc_Read(void);
uint16_t Adc_FilteredRead(void);#endif
task
/*********************** 电量任务框架 ************************/
static void vAdcTask(void *pvParameters)
{Hd_ADC_Init(); //ADC初始化while(1){uint16_t filtered = Adc_FilteredRead();if (filtered != 0xFFFF) {float voltage = (filtered / 4095.0f) * 3.3f;printf("\rADC: %d (%.3f V)", filtered, voltage);}vTaskDelay(pdMS_TO_TICKS(3000)); // 1Hz 检测频率}
}
三、效果图