Question
STM32F373RB ADC+DMA+Interrupt
Posted on March 03, 2016 at 17:24
Dear Community
I have an STM32F373RB device and I try to use the DMA to read the ADC1. However the DMA interrupt is not triggered. Since there is no example on the µC how to use DMA and ADC together with interrupt I would be very happy if someone could give a hint what I could check in my next trial and error session.
Initialisation:void ADC_1_Init() {
GPIO_InitTypeDef GPIO_InitStructure;
ADC_InitTypeDef ADC_InitStructure;
DMA_InitTypeDef DMA_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure; //DMA Interupt
// Enable DMA1 clock
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
// Enable ADC1 clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
RCC_ADCCLKConfig(RCC_PCLK2_Div4); // this I copied form the ADC_DMA example but I havent checked what it means so far
//Enable GPIO Clock
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
// Configure PB.12 (ADC Channel8) in analog mode
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10 --> ADC_IN10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //PB11 --> ADC_IN11
GPIO_Init(GPIOC, &GPIO_InitStructure);
//DMA1 Channel1 configuration
DMA_DeInit(DMA1_Channel1);
DMA_InitStructure.DMA_BufferSize = sizeof(ADC1_Buffer);
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)ADC1_Buffer;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular; //DMA_Mode_Normal; //
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_Init(DMA1_Channel1, &DMA_InitStructure);
//DMA_IT_TC: Transfer complete interrupt mask
//DMA_IT_HT: Half transfer interrupt mask
//DMA_IT_TE: Transfer error interrupt mask
// Enable DMA1 channel6 IRQ Channel
NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = ADC_Prio;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = ADC_subPrio;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
DMA_ITConfig(DMA1_Channel1,DMA_IT_TC, ENABLE);
DMA_Cmd(DMA1_Channel1, ENABLE);
// ADC1 configuration
ADC_InitStructure.ADC_ScanConvMode = DISABLE; //Enable for conti mode
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE; //Enable for conti mode
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T2_CC2; //Trigger
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel = 1;
ADC_Init(ADC1, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_7Cycles5);
// Enable ADC1 DMA
ADC_DMACmd(ADC1, ENABLE);
//The folowing section is probably obsolete...
// Enable ADC1
ADC_Cmd(ADC1, ENABLE);
// ADC1 reset calibration register
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
// ADC1 calibration start
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
ADC_Cmd(ADC1, ENABLE);
}
IRQ Handler:
void DMA1_Channel1_IRQHandler() {
if(DMA_GetFlagStatus(DMA1_IT_TC1) != RESET) {
ADC_Cmd(ADC1, DISABLE);
}
DMA_ClearITPendingBit(DMA1_IT_GL1);
}
Call from
DMA2_Channel3_IRQHandler()
: ADC_Cmd(ADC1, ENABLE); PS: This mechanism works on stm32L100 and now I try to migrate this to stm32373 for reaching higher performance.