目录
概述
本文主要是使用AT32F403A开发板,基于V2库实现adc采集多通道电压值并使用dma搬运数据的功能。
串口工具使用的Atlink-ez自带的串口功能。
工程建立、调试工具配置在前面章节有详细介绍。
硬件
硬件方面使用的是参考官方AT32F437 SURF板子而设计的一个AT32F403A开发板,板子上的芯片是AT32F403AVGT7的型号,开发板上面还板载了一个atlink-ez的仿真器,atlink-ez除了可以在线仿真和下载之外还有一个串口的功能,硬件上是通过跳线帽接到了MCU的串口1,pa9/10上面。
如下图是开发板pcb图,以及硬件资源。(左边上角的就是atlink-ez,用usb线接到pc即可):
如下是实物图:
本章是adc采集多通道,并且使用dma来搬运采集到的数据,PC0是采集可变电阻的电压,PC1和PC2可直接通过排针接到vcc或者gnd即可。
软件
初始化
关于adc的介绍可以去看上一章的内容,dma的可以去看串口dma的篇章。
本文使用ADC1的通道10、11、12来转换电压,也就是PC0、PC1、PC2,IO都设置为模拟输入模式,无上下拉。
开启ADC1的时钟,设置ADC分频系数为6,设置工作模式为独立模式, 开启序列模式,开启重复模式,设置普通通道数量为3,设置软件触发方式,使能adc dma功能,使能dma1 通道1。
Dma方面支持ADC1使用dma来搬运数据,并且默认通道是DMA1的通道1,设置DMA1的通道1运输方向为外设到内存,外设地址为adc1的数据寄存器地址 ,内存地址递增,开启循环模式。这样adc就可以一直在循环的转换然后dma搬运数据。
初始化代码
/*
*adc dma 初始化
*ADC1-CH10 (PC0)
*ADC1-CH11 (PC1)
*ADC1-CH12 (PC2)
*软件触发
*3普通通道转换
*dma循环搬运
*/
void adc_dma_init(void)
{
gpio_init_type gpio_initstructure;
dma_init_type dma_init_struct;
adc_base_config_type adc_base_struct;
crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE); //开启gpioc时钟
crm_periph_clock_enable(CRM_ADC1_PERIPH_CLOCK, TRUE); //开启ADC1时钟
crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE); //开启dma1时钟
crm_adc_clock_div_set(CRM_ADC_DIV_6); //adc时钟六分频。
gpio_default_para_init(&gpio_initstructure);
gpio_initstructure.gpio_mode = GPIO_MODE_ANALOG; //模拟输入模式
gpio_initstructure.gpio_pins = GPIO_PINS_0|GPIO_PINS_1|GPIO_PINS_2 ; //PA0、PA1、PA2
gpio_init(GPIOC, &gpio_initstructure);
dma_reset(DMA1_CHANNEL1);
dma_default_para_init(&dma_init_struct);
dma_init_struct.buffer_size = 30; //内存大小为30
dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY; //传输方向为外设到内存
dma_init_struct.memory_base_addr = (uint32_t)adc1_ordinary_valuetab; //内存地址
dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD; //内存数据的宽度,16位
dma_init_struct.memory_inc_enable = TRUE; //内存地址递增打开
dma_init_struct.peripheral_base_addr = (uint32_t)&(ADC1->odt); //外设地址为adc数据寄存器地址
dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD; //外设数据的宽度,16位
dma_init_struct.peripheral_inc_enable = FALSE; //外设地址递增关闭
dma_init_struct.priority = DMA_PRIORITY_MEDIUM; //中等优先级
dma_init_struct.loop_mode_enable = TRUE; //循环传输,传输完30个后重新开始
dma_init(DMA1_CHANNEL1, &dma_init_struct);
adc_base_default_para_init(&adc_base_struct);
adc_base_struct.sequence_mode = TRUE; //开启序列模式(多通道)
adc_base_struct.repeat_mode = TRUE; //开启重复模式
adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT; //数据右对齐
adc_base_struct.ordinary_channel_length = 3; //通道数为3
adc_base_config(ADC1, &adc_base_struct); //初始化参数
adc_ordinary_channel_set(ADC1, ADC_CHANNEL_10, 1, ADC_SAMPLETIME_239_5); //设置普通通道,adc1 ,通道10,序号为1,采样周期为239.5
adc_ordinary_channel_set(ADC1, ADC_CHANNEL_11, 2, ADC_SAMPLETIME_239_5); //设置普通通道,adc1 ,通道11,序号为2,采样周期为239.5
adc_ordinary_channel_set(ADC1, ADC_CHANNEL_12, 3, ADC_SAMPLETIME_239_5); //设置普通通道,adc1 ,通道12,序号为3,采样周期为239.5
adc_ordinary_conversion_trigger_set(ADC1, ADC12_ORDINARY_TRIG_SOFTWARE, TRUE); //普通通道触发设置为软件触发
adc_dma_mode_enable(ADC1, TRUE); //使能adc dma功能
dma_channel_enable(DMA1_CHANNEL1, TRUE); //使能通道1
adc_enable(ADC1, TRUE); //使能ADC1
adc_calibration_init(ADC1); //初始化校准
while(adc_calibration_init_status_get(ADC1)); //初始化校准完毕
adc_calibration_start(ADC1); //开始校准
while(adc_calibration_status_get(ADC1)); //校准完毕
adc_ordinary_software_trigger_enable(ADC1, TRUE); //软件触发adc
}
测试
测试代码
通过每3秒输出每个通道所转换的10次的数据值,硬件上通过手动来短接PC1/2到gnd或者vcc以及调节可变电阻的阻值。
测试结果
PC1短接gnd,PC2短接vcc,PC0调节可变电阻。测试正确的。
最后
有问题的可以加QQ群技术交流,同时相关代码上传到QQ群中。