本帖最后由 汪文龙 于 2015-5-14 12:50 编辑 想使用ADC进行4路采样,并将采样值由DMA存储在一个数组中。因为采样时间有将近1分钟,如果让ADC不停地采样,最终获得的数据量大的不行。所以决定用定时器触发ADC的方式,每0.5秒采样一次,1分钟的话,采样120次,共480个数据。 但是配置良久,ADC一直不工作,我真不知道怎么办了,所以在此求助大神。 请大家看看我下面的程序有什么问题,并给一点建议。 再者,小弟有几个问题,望前辈解惑。 1.多路ADC 是不是ADC每完成一路的转换,DMA就帮忙传送一次。 2.DMA_BufferSize ,好多地方都说这个是DMA缓冲大小,请问下这个有什么用,我的是四路ADC,所以我这里设置的是4,不知道是不是对的。 ADC+DMA程序段 #include "adc.h" #include "led.h" #include "stm32f4xx_adc.h" #include "stm32f4xx_dma.h" #include "stm32f4xx_gpio.h" #define ADC3_DR_ADDRESS ((uint32_t)0x4001224C) extern int uhADC3ConvertedValue[504]; //------------------------------------------------------------------------------ //ADC3+DMA配置 //------------------------------------------------------------------------------ void ADC3_CH13_DMA_Config(void) { ADC_InitTypeDef ADC_InitStructure; ADC_CommonInitTypeDef ADC_CommonInitStructure; DMA_InitTypeDef DMA_InitStructure; GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; //打开ADC3,DMA2,GPIO时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2 | RCC_AHB1Periph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE); //配置DMA DMA_DeInit(DMA2_Stream0); DMA_InitStructure.DMA_Channel = DMA_Channel_2; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS; DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)uhADC3ConvertedValue; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_InitStructure.DMA_BufferSize = 4; 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_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_Init(DMA2_Stream0, &DMA_InitStructure); DMA_Cmd(DMA2_Stream0, ENABLE); //初始化采样端口 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_5 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ; GPIO_Init(GPIOA, &GPIO_InitStructure); //配置ADC ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; 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 = DISABLE; ADC_InitStructure.ADC_ExternalTrigConvEdge=ADC_ExternalTrigConvEdge_Rising; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T5_CC1; //设置为TIM5_CC1触发 ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfConversion = 4; ADC_Init(ADC3, &ADC_InitStructure); ADC_RegularChannelConfig(ADC3, ADC_Channel_10, 1, ADC_SampleTime_3Cycles); ADC_RegularChannelConfig(ADC3, ADC_Channel_11, 2, ADC_SampleTime_3Cycles); ADC_RegularChannelConfig(ADC3, ADC_Channel_12, 3, ADC_SampleTime_3Cycles); ADC_RegularChannelConfig(ADC3, ADC_Channel_13, 4, ADC_SampleTime_3Cycles); ADC_DMACmd(ADC3, ENABLE); ADC_Cmd(ADC3, ENABLE); ADC_ITConfig(ADC3,ADC_IT_EOC,ENABLE); NVIC_InitStructure.NVIC_IRQChannel =ADC_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=0;//先占优先级0 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //从优先级0 NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } void ADC_IRQHangler(void) //程序调试 { if(ADC_GetITStatus(ADC3,ADC_FLAG_EOC)==SET) //溢出中断 { if(IS_LED2_ON==1) { LED2_OFF; } else { LED2_ON; } } ADC_ClearITPendingBit(ADC3,ADC_FLAG_EOC); //清除中断标志位 } 定时器TIM5程序段 #include "timer3.h" #include "led.h" #include "stm32f4xx_tim.h" void TIM5_Int_Init(void) { TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure; TIM_OCInitTypeDef TIM_OCInitStructure; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM5,ENABLE); TIM_TimeBaseInitStructure.TIM_Period=4200-1; TIM_TimeBaseInitStructure.TIM_Prescaler=10000-1; TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Down; TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1; TIM_TimeBaseInit(TIM5,&TIM_TimeBaseInitStructure); TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1; TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable; TIM_OCInitStructure.TIM_Pulse=0x7F; TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low; TIM_OC1Init(TIM5,&TIM_OCInitStructure); TIM_Cmd(TIM5,ENABLE); TIM_ITConfig(TIM5,TIM_IT_CC1,ENABLE); TIM_CtrlPWMOutputs(TIM5, ENABLE); } main函数: int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); GPIO_Switch_Init(); LED_Init(); TIM3_Int_Init(); LCD_Init(); //LCD初始化 LCD_LayerInit(); //LCD层次显示初始化 LTDC_Cmd(ENABLE); //打开LTDC LCD_GUIDisplay(); TIM2_Int_Init(); ADC3_CH13_DMA_Config(); //配置ADC3 TIM5_Int_Init(); while(1) { } } |
没有开启ADC转换,ADC_StartConversion();
您好,我上面有使能ADC时钟呀
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC3, ENABLE);
下面这句应该就是启动啊ADC的吧。
ADC_Cmd(ADC3, ENABLE);
朋友你说的两个函数我的库里面貌似都没有,我用的是STM32F428ZI的芯片
谢谢你咯!
DMA缓冲区满了以后会触发一次中断,这个时候处理就可以了。
库不一样吧,仔细看下你的库,最好能有库函数说明用户手册,看是不是漏掉了什么
好的,谢谢哈!
TIM_ARRPreloadConfig(TIM1, ENABLE);
TIM_OC1PreloadConfig (TIM1, TIM_OCPreload_Enable);
TIM_Cmd(TIM1, ENABLE);
TIM_CtrlPWMOutputs(TIM1, ENABLE);
DMA_BufferSize是指DMA的缓冲区大小,既然你开辟了内存大小int uhADC3ConvertedValue[504];DMA_BufferSize就可以设置为504