使用 HC32A4A0 系列 MCU 的 ADC(模数转换器)进行多通道高效轮询采样,可以借助其 13 路模拟输入通道 和 8 通道序列功能(SCAN 模式),结合 DMA 自动传输数据 实现高效无阻塞采样。以下将分享具体配置思路、代码示例和技巧。
一、基本特性理解(HC32A4A0 ADC)
13 路模拟通道:AIN0~AIN12 可连接外部模拟信号。
8 通道序列扫描(SCAN)功能:最多配置 8 个通道一次性连续采样。
支持 DMA:ADC 转换结果可自动传送至内存,无需 CPU 干预。
支持多种触发方式:软件触发、定时器触发、外部引脚触发等。
转换数据寄存器(ADDR0~ADDR7):与通道序列一一对应。
二、高效轮询采样思路
目标:采集多个 ADC 通道的电压值,要求效率高、CPU 占用低。
方案概述:
配置 ADC 为 扫描模式(Sequence Mode),一次性采集 8 个通道。
启用 DMA 自动传输,将 ADC 数据移动到内存数组中。
使用 定时器触发 ADC 启动,确保周期性采样。
ADC 转换完成后,DMA 触发中断或设置标志,通知主程序处理数据。
三、关键配置步骤
1. ADC 初始化配置(以 AIN0~AIN7 为例)
c
复制
编辑
#define ADC_CHANNEL_COUNT 8
uint16_t adc_result[ADC_CHANNEL_COUNT]; // DMA 传输目标
void Adc_Init(void)
{
stc_adc_init_t stcAdcInit;
stc_adc_ch_cfg_t stcChCfg;
// 1. 开启 ADC 和 GPIO 时钟
PWC_Fcg3PeriphClockCmd(PWC_FCG3_ADC, Enable);
Gpio_SetAnalogMode(PortA, Pin00); // 示例 AIN0
// 2. ADC 初始化结构体默认
ADC_StructInit(&stcAdcInit);
stcAdcInit.u16ScanMode = ADC_SCAN_SEQ; // 扫描模式
stcAdcInit.u16Resolution = ADC_RESOLUTION_12B;
stcAdcInit.u8RepeatMode = ADC_SEQ_REPEAT; // 连续扫描
ADC_Init(ADC, &stcAdcInit);
// 3. 配置通道序列(SEQ)
ADC_SeqChCmd(ADC, ADC_SEQ_CH0, Enable); // AIN0
ADC_SeqChCmd(ADC, ADC_SEQ_CH1, Enable); // AIN1
ADC_SeqChCmd(ADC, ADC_SEQ_CH2, Enable); // ...
ADC_SeqChCmd(ADC, ADC_SEQ_CH7, Enable); // AIN7
// 4. 配置 DMA 传输
ADC_DmaCmd(ADC, Enable); // 启用 ADC DMA 功能
}
2. DMA 配置(以 DMA 通道0 为例)
c
复制
编辑
void Dma_Init(void)
{
stc_dma_init_t stcDmaInit;
PWC_Fcg0PeriphClockCmd(PWC_FCG0_DMA1, Enable); // 打开 DMA1 时钟
DMA_StructInit(&stcDmaInit);
stcDmaInit.u16BlockSize = ADC_CHANNEL_COUNT;
stcDmaInit.u16TransCount = 1;
stcDmaInit.u32SrcAddr = (uint32_t)&ADC->ADDR0;
stcDmaInit.u32DestAddr = (uint32_t)adc_result;
stcDmaInit.u16SrcAddrInc = DMA_SRC_ADDR_FIX;
stcDmaInit.u16DestAddrInc = DMA_DEST_ADDR_INC;
stcDmaInit.u16DataWidth = DMA_DATAWIDTH_16BIT;
stcDmaInit.u16IntEn = Enable; // 可选:DMA 传输完成中断
DMA_Init(DMA_UNIT1, DMA_CH0, &stcDmaInit);
DMA_Cmd(DMA_UNIT1, DMA_CH0, Enable);
}
3. 使用定时器周期触发 ADC
c
复制
编辑
void Timer_TriggerADC_Init(void)
{
// 初始化定时器,每 N 毫秒触发一次 ADC
// 配置定时器触发 ADC(TRG1 或 TRG2)
// ...
ADC_SetTriggerSrc(ADC, ADC_TRG_SRC_EVT0); // 选择定时器触发源
ADC_TriggerCmd(ADC, Enable);
}
四、主程序逻辑(DMA 中断或轮询处理)
c
复制
编辑
int main(void)
{
Adc_Init();
Dma_Init();
Timer_TriggerADC_Init();
while (1)
{
// 可在 DMA 中断中设置标志,或在此直接检查结果
if (adc_data_ready)
{
adc_data_ready = 0;
for (int i = 0; i < ADC_CHANNEL_COUNT; ++i)
{
printf("ADC[%d] = %u\n", i, adc_result[i]);
}
}
}
}
总结
使用 HC32A4A0 的 ADC 扫描 + DMA 模式是实现多通道模拟量采样的高效方案。通过合理配置触发、通道序列、DMA 传输,结合定时器调度,可以实现低 CPU 占用、高实时性的轮询采样系统。
如需扩展至更多通道,可实现通道动态切换与序列更新逻辑。
|