Geehy极海半导体

当前位置:主页 > 服务支持 > 常见问题 > Geehy极海半导体 >

极海APM32E030系列ADC使用的一些小心得

作者: admin 时间:2025-08-20 来源:未知
摘要:极海APM32E030系列是工业级基础拓展型MCU,在APM32F030性能基础上,实现了更高主频、更低功耗、以及更先进的模拟与通信接口。同时配置丰富的片上资源,可满足多行业的应用升级需求,...

  极海APM32E030系列是工业级基础拓展型MCU,在APM32F030性能基础上,实现了更高主频、更低功耗、以及更先进的模拟与通信接口。同时配置丰富的片上资源,可满足多行业的应用升级需求,特别是成本敏感型应用。可广泛应用于工业控制、智能家居、仪器仪表、可穿戴设备、医疗及手持设备、小家电、照明灯等领域。
 
  该篇文章主要介绍APM32E030系列ADC使用的一些小心得——从单通道阻塞采样到多通道DMA扫描
 
  APM32E030的硬件资源
  APM32E030片内集成1路12-bit ADC,最高1 Msps,支持16个外部通道+2个内部通道(温度传感器、V<sub>),模拟输入范围0~V<sub>(典型3.3 V)。ADC时钟最高14 MHz,由PCLK2分频而来。
 
  典型应用场景
  单通道电压监测(阻塞方式)
  多通道轮询扫描+DMA,减轻CPU负担
  片内温度传感器/参考电压测量,实现温度补偿和电压校准
 
  寄存器/库函数对照
  整套官方SDK提供两套接口:
  寄存器版apm32e030_adc.h
  LL(Low-layer)/HAL版apm32e0xx_ll_adc.h
 
  下文示例以寄存器版为主,关键函数名称与HAL版一一对应,方便迁移。
  最小系统单通道阻塞采样
  目标:ADC1通道2(PA2)采可调电阻,串口每秒打印一次电压值。
  1.GPIO复用
RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1 | RCM_APB2_PERIPH_GPIOA);
GPIO_Config_T t = {
    .pin   = GPIO_PIN_2,
    .mode  = GPIO_MODE_AN,
    .pupd  = GPIO_PUPD_NO,
    .speed = GPIO_SPEED_50MHz
};
GPIO_Config(GPIOA, &t);
 
  2.ADC时钟与分辨率
RCM_ConfigADCCLK(RCM_ADCCLK_PCLK2_DIV6);   // 72 MHz / 6 = 12 MHz
ADC_Reset();
ADC_Config_T adc = {
    .resolution   = ADC_RESOLUTION_12B,
    .convMode     = ADC_CONVERSION_SINGLE,
    .dataAlign    = ADC_DATA_ALIGN_RIGHT,
    .scanDir      = ADC_SCAN_DIR_UPWARD,
    .extTrigConv  = ADC_EXT_TRIG_CONV_T0,
    .extTrigEdge  = ADC_EXT_TRIG_EDGE_NONE
};
ADC_Config(&adc);
 
  3.通道与采样时间
ADC_ConfigChannel(ADC_CHANNEL_2, ADC_SAMPLE_TIME_239_5); // 最长采样提高精度
 
  4.校准&启动
ADC_ReadCalibrationFactor();          // 加载出厂校准值
ADC_Enable();
while(!ADC_ReadStatusFlag(ADC_FLAG_ADRDY));
 
  5.阻塞读取封装
uint16_t ADC_GetSingle(void)
{
    ADC_StartConversion();
    while(!ADC_ReadStatusFlag(ADC_FLAG_CC));
    return ADC_ReadConversionValue();
}
  6.主循环
float v = ADC_GetSingle() * 3.3f / 4096;
printf("V=%.3f\r\n", v);
  至此,单通道阻塞采样完成
 
  五、中断方式避免阻塞
  使能转换完成中断,采样完成后在ISR中读取结果。
ADC_EnableInterrupt(ADC_INT_CC);
NVIC_EnableIRQRequest(ADC1_IRQn, 2);
  ISR:
void ADC1_IRQHandler(void)
{
    if (ADC_ReadIntFlag(ADC_INT_CC))
    {
        adcValue = ADC_ReadConversionValue();
        ADC_ClearIntFlag(ADC_INT_CC);
    }
}
  主循环无需死等,可并行处理其他任务
 
  六、多通道+DMA扫描
  目标:一次启动,ADC连续扫描CH0~CH5,DMA将结果写入RAM数组。
  1.定义缓冲区
#define ADC_CH_SIZE 6
uint16_t adcBuf[ADC_CH_SIZE];
 
  2.DMA配置
RCM_EnableAHBPeriphClock(RCM_AHB_PERIPH_DMA);
DMA_Config_T dma = {
    .peripheralBase = (uint32_t)&ADC->DATA,
    .memoryBase     = (uint32_t)adcBuf,
    .direction      = DMA_DIRECTION_PERIPH_TO_MEMORY,
    .bufferSize     = ADC_CH_SIZE,
    .peripheralInc  = DMA_PERIPHERAL_INC_DISABLE,
    .memoryInc      = DMA_MEMORY_INC_ENABLE,
    .peripheralDataSize = DMA_PERIPHERAL_DATA_SIZE_HALFWORD,
    .memoryDataSize     = DMA_MEMORY_DATA_SIZE_HALFWORD,
    .mode           = DMA_MODE_CIRCULAR,
    .priority       = DMA_PRIORITY_HIGH
};
DMA_Config(DMA1_Channel1, &dma);
DMA_Enable(DMA1_Channel1);
  3.ADC连续扫描模式
adc.convMode = ADC_CONVERSION_CONTINUOUS;
adc.scanDir  = ADC_SCAN_DIR_UPWARD;
ADC_Config(&adc);
 
/* 分别配置 6 个通道,顺序必须与硬件布线对应 */
ADC_ConfigChannel(ADC_CHANNEL_0, ADC_SAMPLE_TIME_71_5);
...
ADC_ConfigChannel(ADC_CHANNEL_5, ADC_SAMPLE_TIME_71_5);
  4.启动
ADC_EnableDMA();
ADC_ReadCalibrationFactor();
ADC_Enable();
ADC_StartConversion();
  DMA以循环模式自动搬运数据,CPU仅需读取adcBuf[]。
 
  七、内部温度传感器&<sub>使用技巧
  通道号:温度=CH16,V&<sub>=CH17
  采样时间≥239.5 cycles,确保稳定
  温度计算公式(典型):
  T=((V25-VTS)/Avg_Slope)+25
  V25≈1.34 V,Avg_Slope≈4.3 mV/°C(以数据手册为准)
  实测发现V&<sub>读数约1.2 V,若出现偏大/偏小,可通过校准寄存器VREFINT_CAL进行修正

[向上]