基于DMA 控制STM32F407两(多)路AD通道配置
在用
STM32
做开发或学习的时候难免需要同时采集多路
AD
信号,在此仅以两路
AD
配置为例,多路
AD
按照相同的方法配置。
我想阅读此文的朋友对于ADC单通道配置都应该已经没有问题了,所以也就不啰嗦单通道配置过程,直接列出双通道配置不同的地方。关于双通道配置特殊部分给出注释。
说明
实验现象:用stm32的PA4,PA6分别采集不同的电压信号(我以PA4采集高电平3.3V电压,PA6采集低电平0V为例)。将低电平电压值保存在LowValue数 组中,高电平电压值保存在HighValue数组中。并通过串口输出到屏幕。如图:
ADC配置
Tips:
1. 配置两(多)个输入引脚
1. 开启扫描模式
2. 开启连续转换
3. 设定AD转换通道数为2
4. 分别配置各通道先后顺序
void ADC_config(void)
{
ADC_InitTypeDef ADC_InitStructure;
ADC_CommonInitTypeDef ADC_CommonInitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_4;//配置PA6、PA4为输入通道
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_ADC1, DISABLE);
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div4;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_2;
ADC_CommonInitStructure.ADC_TwoSamplingDelay=ADC_TwoSamplingDelay_5Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = ENABLE;//开启扫描模式
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE;//开启连续转换
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 2;//设定AD要转换的通道数目
ADC_Init(ADC1, &ADC_InitStructure);
/*******配置ADC1的通道6和通道4的转换先后顺序以及采样间隔时间为15个采样周期*******/
ADC_RegularChannelConfig(ADC1, ADC_Channel_6, 1, ADC_SampleTime_15Cycles);
ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 2, ADC_SampleTime_15Cycles);
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
ADC_DMACmd(ADC1, ENABLE);
ADC_Cmd(ADC1, ENABLE);
ADC_SoftwareStartConv(ADC1);
}
2 DMA配置
Tips:
i. 设定要转换的DMA通道数目
ii. 内存地址增量模式
void DMA_config(void)
{
DMA_InitTypeDef DMA_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
DMA_DeInit(DMA2_Stream0);
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_ADDRESS;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCvalue;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = 2; //设定要转换的DMA通道数目
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;//内存地址增量模式
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream0, &DMA_InitStructure);
DMA_Cmd(DMA2_Stream0, ENABLE);
}
//溢出时间Tout = (period*prescaler)/Tclk,Tclk=84Mhz,这里设置采样率为2KHz
void TIM3_Config(void)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); //84MHz
TIM_TimeBaseInitStructure.TIM_Period = 500-1;
TIM_TimeBaseInitStructure.TIM_Prescaler =84-1 ;
TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
TIM_Cmd(TIM3,ENABLE);
NVIC_InitStructure.NVIC_IRQChannel=TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
//DirectValue PA4
//CurrentValue PA6
void TIM3_IRQHandler(void)
{
if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)
{
TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
if(count<=100)
{
turn_led(LED_Red,ON);
//ADC通道4采样的数据通过DMA通道0送到数组CurrentValue中保存
CurrentValue[count] = (float)ADCvalue[0];
//ADC通道6采样的数据通过DMA通道1送到数组DirectValue中保存
DirectValue[count] = (float)ADCvalue[1];
count++;
}
else
{
count=0;
turn_led(LED_Red,OFF);
TIM_Cmd(TIM3,DISABLE);
}
}
}