本文章介绍ADC多通道采集DMA进行传输,并且在任务中实时去获取数据。
一、时钟配置
分别配置GPIO、ADC、DMA时钟
static void SystemClock_Configration(void)
{
rcu_periph_clock_enable(RCU_GPIOA);
rcu_periph_clock_enable(RCU_GPIOB);
rcu_periph_clock_enable(RCU_GPIOC);
rcu_periph_clock_enable(RCU_GPIOD);
rcu_periph_clock_enable(RCU_GPIOF);
rcu_periph_clock_enable(RCU_CFGCMP);
rcu_periph_clock_enable(RCU_PMU);
rcu_periph_clock_enable(RCU_ADC);
rcu_adc_clock_config(RCU_ADCCK_APB2_DIV2); // 主频108M ADCCLK = PCLK2/2 = 27M
rcu_periph_clock_enable(RCU_DMA);
}
二、GPIO配置
配置对应ADC通道GPIO为模拟输入模式
static void AdcGpioConfigration(void)
{
gpio_deinit(GPIOA | GPIOB | GPIOC | GPIOD | GPIOF);
gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_1);
gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_4);
gpio_mode_set(GPIOB, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_0);
gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_0);
gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_4);
gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_5);
gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_5);
gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_3);
gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_2);
gpio_mode_set(GPIOC, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_1);
gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_6);
gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_7);
gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_2);
gpio_mode_set(GPIOA, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_3);
gpio_mode_set(GPIOB, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO_PIN_1);
}
三、ADC配置
static void AdcConfiguration(void)
{
/* reset ADC */
adc_deinit();
/* ADC channel length config */
adc_channel_length_config(ADC_REGULAR_CHANNEL, ADC_LENGTH);
/* ADC regular channel config */
adc_regular_channel_config(0, ADC_CHANNEL_1, ADC_SAMPLETIME_71POINT5);
adc_regular_channel_config(1, ADC_CHANNEL_14, ADC_SAMPLETIME_71POINT5);
adc_regular_channel_config(2, ADC_CHANNEL_8, ADC_SAMPLETIME_71POINT5);
adc_regular_channel_config(3, ADC_CHANNEL_10, ADC_SAMPLETIME_71POINT5);
adc_regular_channel_config(4, ADC_CHANNEL_4, ADC_SAMPLETIME_71POINT5);
adc_regular_channel_config(5, ADC_CHANNEL_15, ADC_SAMPLETIME_71POINT5);
adc_regular_channel_config(6, ADC_CHANNEL_5, ADC_SAMPLETIME_71POINT5);
adc_regular_channel_config(7, ADC_CHANNEL_13, ADC_SAMPLETIME_71POINT5);
adc_regular_channel_config(8, ADC_CHANNEL_12, ADC_SAMPLETIME_71POINT5);
adc_regular_channel_config(9, ADC_CHANNEL_11, ADC_SAMPLETIME_71POINT5);
adc_regular_channel_config(10, ADC_CHANNEL_6, ADC_SAMPLETIME_71POINT5);
adc_regular_channel_config(11, ADC_CHANNEL_7, ADC_SAMPLETIME_71POINT5);
adc_regular_channel_config(12, ADC_CHANNEL_2, ADC_SAMPLETIME_71POINT5);
adc_regular_channel_config(13, ADC_CHANNEL_3, ADC_SAMPLETIME_71POINT5);
adc_regular_channel_config(14, ADC_CHANNEL_9, ADC_SAMPLETIME_71POINT5);
/* ADC external trigger enable */
adc_external_trigger_config(ADC_REGULAR_CHANNEL, ENABLE);
/* ADC external trigger source config */
adc_external_trigger_source_config(ADC_REGULAR_CHANNEL, ADC_EXTTRIG_REGULAR_NONE);
/* ADC data alignment config */
adc_data_alignment_config(ADC_DATAALIGN_RIGHT);
/* ADC SCAN & CONTINUOUS function enable */
adc_special_function_config(ADC_SCAN_MODE, ENABLE);
// adc_special_function_config(ADC_CONTINUOUS_MODE, ENABLE); //auto repeat sample
/* ADC DMA function enable */
adc_dma_mode_enable();
/* enable ADC interface */
adc_enable();
/* ADC calibration and reset calibration */
adc_calibration_enable();
/* enable ADC software trigger */
adc_software_trigger_enable(ADC_REGULAR_CHANNEL);
}
四、DMA配置
static void AdcDmaConfiguration(void)
{
dma_parameter_struct dma_init_struct;
/* initialize DMA channel0 */
dma_deinit(DMA_CH0);
dma_init_struct.direction = DMA_PERIPHERAL_TO_MEMORY;
dma_init_struct.memory_addr = (uint32_t )adc_dma;//此处为我们定义的数组地址
dma_init_struct.memory_inc = DMA_MEMORY_INCREASE_ENABLE;
dma_init_struct.memory_width = DMA_MEMORY_WIDTH_16BIT;
dma_init_struct.number = ADC_LENGTH;
dma_init_struct.periph_addr = (uint32_t) & (ADC_RDATA);
dma_init_struct.periph_inc = DMA_PERIPH_INCREASE_DISABLE;
dma_init_struct.periph_width = DMA_PERIPHERAL_WIDTH_16BIT;
dma_init_struct.priority = DMA_PRIORITY_ULTRA_HIGH;
dma_init(DMA_CH0, &dma_init_struct);
/* clear DMA a channel flag */
dma_interrupt_flag_clear(DMA_CH0, DMA_INT_FTF);
/* channel transfer finish interrupt */
dma_interrupt_enable(DMA_CH0, DMA_INT_FTF);
/* configure DMA mode */
dma_circulation_enable(DMA_CH0);//循环模式
dma_memory_to_memory_disable(DMA_CH0);
/* enable DMA channel0 */
dma_channel_enable(DMA_CH0);
}
static void AdcNvicConfiguration(void) //中断等级配置
{
nvic_priority_group_set(NVIC_PRIGROUP_PRE4_SUB0);
nvic_irq_enable(DMA_Channel0_IRQn, 5, 0);
}
void DMA_Channel0_IRQHandler()
{
if(dma_interrupt_flag_get(DMA_CH0, DMA_INT_FTF) != RESET)
{
dma_interrupt_flag_clear(DMA_CH0, DMA_INT_FTF);
AdcStartSampling(); //每次传输完成后立马又软件触发采集
}
}
五、主函数代码
#define ADC_LENGTH 15 //ADC通道数量
static uint16_t adc_dma[ADC_LENGTH];
uint16_t GetAdcValue(uint8_t channel)//获取对应通道ADC值
{
return adc_dma[channel];
}
void AdcInitialize(void) //初始化所有ADC相关配置
{
SystemClock_Configration();
AdcGpioConfigration();
AdcConfiguration();
AdcDmaConfiguration();
AdcNvicConfiguration();
}
int main(void)
{
AdcInitialize();
taskENTER_CRITICAL();
xTaskCreate(AdcDebugTask1,"AdcDebugTask1",128,NULL,1,NULL);
taskEXIT_CRITICAL();
while(1)
{
}
}
void AdcDebugTask1(void * pvParameters)
{
while(1)
{
for(int i = 0;i < 15;i++)
{
arr_adc[i] = GetAdcValue(i);
}
}
}
六、仿真验证