DMA方式读取多通道ADC采样值

发布时间 2023-09-09 00:07:10作者: Yannnnnnn

1  ADC配置

打开扫描模式,配置通道个数,打开连续模式,打开DMAContinuousRequests。

2  DMA配置

选择DMA2,Stream0,Channel0,方向外设到内存,外设不自增,内存自增,DMA循环模式。

3  连接ADC和DMA

/*ADC1与DMA2连接*/
    __HAL_LINKDMA(&h_ADC1,DMA_Handle,h_DMA2_ADC1);
    //h_ADC1.DMA_Handle = &h_DMA2_ADC1;
    //h_DMA2_ADC1.Parent = &h_ADC1;

4  启动DMA和ADC

↓↓↓配置ADC和DMA代码

#include "main.h"
#include "ADC.h"
#include "DMA.h"

/*ADC1句柄*/
ADC_HandleTypeDef h_ADC1;
/*ADC通道配置结构体*/
ADC_ChannelConfTypeDef h_ADC1_Channel_Init;
/*DMA2句柄*/
DMA_HandleTypeDef h_DMA2_ADC1;
/*存储DMA取ADC1值*/
uint16_t ADC1_DMA_Buffer[4];
/*配置ADC1和DMA2*/
void ADC1_Init(void)
{
    /*ADC1配置*/
    __HAL_RCC_ADC1_CLK_ENABLE();
    h_ADC1.Instance = ADC1;
    h_ADC1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV8;
    h_ADC1.Init.Resolution = ADC_RESOLUTION_12B;
    h_ADC1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    h_ADC1.Init.ScanConvMode = ENABLE;
    h_ADC1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
    h_ADC1.Init.ContinuousConvMode = ENABLE;
    h_ADC1.Init.NbrOfConversion = 4;
    h_ADC1.Init.DiscontinuousConvMode = DISABLE;
    h_ADC1.Init.NbrOfDiscConversion = 0;
    h_ADC1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    h_ADC1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
    h_ADC1.Init.DMAContinuousRequests = ENABLE;
    HAL_ADC_Init(&h_ADC1);
    /*ADC1通道配置*/
    h_ADC1_Channel_Init.Channel = ADC_CHANNEL_1;
    h_ADC1_Channel_Init.Rank = 1;
    h_ADC1_Channel_Init.SamplingTime = ADC_SAMPLETIME_480CYCLES;
    HAL_ADC_ConfigChannel(&h_ADC1,&h_ADC1_Channel_Init);
    h_ADC1_Channel_Init.Channel = ADC_CHANNEL_2;
    h_ADC1_Channel_Init.Rank = 2;
    h_ADC1_Channel_Init.SamplingTime = ADC_SAMPLETIME_480CYCLES;
    HAL_ADC_ConfigChannel(&h_ADC1,&h_ADC1_Channel_Init);    
    h_ADC1_Channel_Init.Channel = ADC_CHANNEL_4;
    h_ADC1_Channel_Init.Rank = 3;
    h_ADC1_Channel_Init.SamplingTime = ADC_SAMPLETIME_480CYCLES;
    HAL_ADC_ConfigChannel(&h_ADC1,&h_ADC1_Channel_Init);    
    h_ADC1_Channel_Init.Channel = ADC_CHANNEL_6;
    h_ADC1_Channel_Init.Rank = 4;
    h_ADC1_Channel_Init.SamplingTime = ADC_SAMPLETIME_480CYCLES;
    HAL_ADC_ConfigChannel(&h_ADC1,&h_ADC1_Channel_Init);
    /*ADC1通道引脚配置*/
    __HAL_RCC_GPIOA_CLK_ENABLE();
    GPIO_InitTypeDef GPIO_Init;
    GPIO_Init.Pin  = GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_6;
    GPIO_Init.Mode = GPIO_MODE_ANALOG;
    GPIO_Init.Pull = GPIO_NOPULL;
    GPIO_Init.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    HAL_GPIO_Init(GPIOA,&GPIO_Init);
    /*DMA2配置*/
    __HAL_RCC_DMA2_CLK_ENABLE();
    h_DMA2_ADC1.Instance = DMA2_Stream0;
    h_DMA2_ADC1.Init.Channel = DMA_CHANNEL_0;
    h_DMA2_ADC1.Init.Direction = DMA_PERIPH_TO_MEMORY;
    h_DMA2_ADC1.Init.PeriphInc = DMA_PINC_DISABLE;
    h_DMA2_ADC1.Init.MemInc = DMA_MINC_ENABLE;
    h_DMA2_ADC1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
    h_DMA2_ADC1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
    h_DMA2_ADC1.Init.Mode = DMA_CIRCULAR;
    h_DMA2_ADC1.Init.Priority = DMA_PRIORITY_HIGH;
    h_DMA2_ADC1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
    h_DMA2_ADC1.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL;
    h_DMA2_ADC1.Init.MemBurst = DMA_MBURST_SINGLE;
    h_DMA2_ADC1.Init.PeriphBurst = DMA_PBURST_SINGLE;
    HAL_DMA_Init(&h_DMA2_ADC1);
    /*ADC1与DMA2连接*/
    //__HAL_LINKDMA(&h_ADC1,DMA_Handle,h_DMA2_ADC1);
    h_ADC1.DMA_Handle = &h_DMA2_ADC1;
    h_DMA2_ADC1.Parent = &h_ADC1;
}
/*轮询模式启动ADC1*/
uint32_t ADC1_Start_GetValue(void)
{
    HAL_ADC_Start(&h_ADC1);
    HAL_ADC_PollForConversion(&h_ADC1,20);
    return HAL_ADC_GetValue(&h_ADC1);
}
/*DMA模式启动ADC1*/ 
void ADC1_Start_DMA2(void)
{
    HAL_DMA_Start(&h_DMA2_ADC1,(uint32_t)&h_ADC1.Instance->DR,(uint32_t)ADC1_DMA_Buffer,4);
    HAL_ADC_Start_DMA(&h_ADC1,(uint32_t *)ADC1_DMA_Buffer, 4);

}

↓↓↓DMA获取结果

    printf("ADCCH1=%f\n",((float)ADC1_DMA_Buffer[0])/4096);
    printf("ADCCH2=%f\n",((float)ADC1_DMA_Buffer[1])/4096);
    printf("ADCCH3=%f\n",((float)ADC1_DMA_Buffer[2])/4096);
    printf("ADCCH4=%f\n",((float)ADC1_DMA_Buffer[3])/4096);