前言
记录STM32F407 DMA+多路ADC配置
一、DMA简介
F4系列有2个DMA控制器,16路数据流(每个DMA占8个),每个数据流有8个通道(请求)。
1. DMA映射
根据功能外设选择对应DMA请求映射
2. DMA配置
二、代码
1.源文件
void adc_dma_init(void)
{
ADCInit_GPIO();
ADCInit_ADC();
ADCInit_DMA();
ADC_SoftwareStartConv(ADC1); /*启动软件转换*/
}
1 GPIO配置:模拟输入+不上拉
//
static void ADCInit_GPIO(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(ALL_GPIO_CLK, ENABLE); //使能GPIO时钟
//CHANNEL1
GPIO_InitStructure.GPIO_Pin = TEMP_CHANNEL_1_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; //模拟输入
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; //不带上下拉
GPIO_Init(TEMP_CHANNEL_1_GPIO, &GPIO_InitStructure); //初始化
//CHANNEL2
GPIO_InitStructure.GPIO_Pin = TEMP_CHANNEL_2_PIN;
GPIO_Init(TEMP_CHANNEL_2_GPIO, &GPIO_InitStructure);
}
2 ADC配置
static void ADCInit_ADC(void)
{
ADC_CommonInitTypeDef ADC_CommonInitStructure;
ADC_InitTypeDef ADC_InitStructure;
RCC_APB2PeriphClockCmd(ALL_ADC_CLK, ENABLE); //使能ADC时钟
RCC_APB2PeriphResetCmd(ALL_ADC_CLK,ENABLE); //ADC复位
RCC_APB2PeriphResetCmd(ALL_ADC_CLK,DISABLE); //复位结束
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; //独立模式
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; //两个采样阶段之间的延迟5个时钟(三重模式或双重模式下使用)
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; //DMA失能(对于多个ADC模式)
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4; //预分频4分频。ADCCLK=PCLK2/4=84/4=21Mhz,ADC时钟最好不要超过36Mhz
ADC_CommonInit(&ADC_CommonInitStructure);//初始化
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;//12位模式
ADC_InitStructure.ADC_ScanConvMode = ENABLE;//扫描模式(多通道ADC采集要用扫描模式)
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//连续转换
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; //软件触发
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;//右对齐
ADC_InitStructure.ADC_NbrOfConversion = ADC_CHANNEL; //x个转换在规则序列中
ADC_Init(ADC1, &ADC_InitStructure); //ADC初始化
//连续模式下,通道的配置
ADC_RegularChannelConfig(TEMP_CHANNEL_1_ADCx, TEMP_CHANNEL_1_ADC_CHLx, 1, ADC_SampleTime_15Cycles);
ADC_RegularChannelConfig(TEMP_CHANNEL_2_ADCx, TEMP_CHANNEL_2_ADC_CHLx, 2, ADC_SampleTime_15Cycles);
ADC_Cmd(ADC1, ENABLE);//开启AD转换器
ADC_DMACmd(ADC1, ENABLE); //使能ADC_DMA
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE); //连续使能DMA
}
这里针对配置代码做下记录说明:
-
ADC_ScanConvMode
扫描模式:
多通道 --> 扫描 ENABLE
单通道 --> 单模式 DISABLE -
ADC_ContinuousConvMode
连续转换:
DMA:ENABLE
不使用DMA:DISABLE -
ADC_NbrOfConversion
规则通道转换数:即多少路ADC
3 DMA配置
static void ADCInit_DMA(void)
{
DMA_InitTypeDef DMA_InitStructure;
//时钟
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
//DMA设置
DMA_InitStructure.DMA_Channel = DMA_Channel_0; //选择通道号
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR; //外围设备地址,ADC_DR_DATA规则数据寄存器 ADC1_BASE+0x4C 偏移4C对应规则寄存器
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)(u16 *)uAD_Buff; //DMA存储器地址,自己设置的缓存地址
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; //传输方向,外设->存储器
DMA_InitStructure.DMA_BufferSize = ADC_CHANNEL; //DMA缓存大小,数据传输量32*8
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; //外设是否为增量模式
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //存储器是否为增量模式
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //外设数据长度半个字(16位)
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; //存储器数据长度半字(16位)
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //DMA模式,普通模式、循环模式,还有双缓冲模式,需要特殊设置
DMA_InitStructure.DMA_Priority = DMA_Priority_High; //DMA优先级,高优先级
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; //不使用FIFO
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; //FIFO阈值
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; //存储器突发,单次传输
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; //外设突发,单次传输
DMA_Init(DMA2_Stream0, &DMA_InitStructure); //初始化DMA2_Stream0
//设置DMA中断
DMA_Cmd(DMA2_Stream0, ENABLE); //使能DMA
}
这里针对配置代码做下记录说明:
-
DMA_Channel
DMA通道选择根据DMA请求映射表
这里的ADC1对应DMA2通道0的数据流0 or 4 -
DMA_PeripheralBaseAddr
外设基地址
ADC值取值为ADC的规则寄存器(DR),两种表达方式
1 (uint32_t)&ADC1->DR, 2 ADC1_BASE+0x4C -
DMA_Memory0BaseAddr
存储器的基地址:即变量地址 -
DMA_PeripheralInc
外设增量模式:需要外设地址自增的就使能,这里只需从DR寄存器取值,所以不自增 -
DMA_MemoryInc
内存增量模式:
若是单变量就不自增,若是存储在数组,一般设置为自增模式 -
DMA_Mode
DMA模式
循环模式:不停地将数据从外设搬到存储器
2.头文件
代码如下(示例):
#ifndef __BSP_ADC_H_
#define __BSP_ADC_H_
#include "sys.h"
/* PIN DEFINE BEGIN*/
#define ADC_CHANNEL 2
#define TEMP_CHANNEL_1_GPIO_CLK RCC_AHB1Periph_GPIOA
#define TEMP_CHANNEL_1_ADC_CLK RCC_APB2Periph_ADC1
#define TEMP_CHANNEL_1_ADCx ADC1
#define TEMP_CHANNEL_1_GPIO GPIOA
#define TEMP_CHANNEL_1_PIN GPIO_Pin_2
#define TEMP_CHANNEL_1_ADC_CHLx ADC_Channel_2
#define TEMP_CHANNEL_2_GPIO_CLK RCC_AHB1Periph_GPIOA
#define TEMP_CHANNEL_2_ADC_CLK RCC_APB2Periph_ADC1
#define TEMP_CHANNEL_2_ADCx ADC1
#define TEMP_CHANNEL_2_GPIO GPIOA
#define TEMP_CHANNEL_2_PIN GPIO_Pin_3
#define TEMP_CHANNEL_2_ADC_CHLx ADC_Channel_3
#define ALL_GPIO_CLK TEMP_CHANNEL_1_GPIO_CLK | TEMP_CHANNEL_2_GPIO_CLK
#define ALL_ADC_CLK TEMP_CHANNEL_1_ADC_CLK | TEMP_CHANNEL_2_ADC_CLK
/* PIN DEFINE END*/
void adc_dma_init(void);
总结
STM32F407 DMA+多路ADC初始化笔记