cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 ADC DMA Overrun problem

oluwaseun
Associate
Posted on December 03, 2015 at 12:57

I have been struggling on this over the past few days and its starting to really push my buttons now.

Device: sTM32F405RGTX

Basically I have ADC 1 configured in regular mode Channel 10 and 11, and I am using DMA to get the values from it and pass it onto a global variable.

the ADC is triggered by a timer TIM3_TRGO

The problem I'm facing is on the peripheral viewer, I can see that the ADC is overrunning, i.e OVR register is set high. when i try to debug and run the code, the ADc output is stuck o one value, however when I untick the OVR register in the periph viewer, it (ADC output) updates for a few secs and the OVR goes back high again.

I think it might be something to do with the fact that maybe the DMA isn't somehow configured right. On first run I can see it copies a value into my buffer but then afterwards its just stuck can someone help please?

void Config_ADCtimer_init () //Regular ADC Timer{ TIM_TimeBaseInitTypeDef Timer_Struct; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //enabling the clock for Timer 3 Timer_Struct.TIM_Period = 16000-1; //scaled to 1000khz Timer_Struct.TIM_Prescaler = 1000-1; Timer_Struct.TIM_CounterMode = TIM_CounterMode_Up; Timer_Struct.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInit(TIM3, &Timer_Struct); //Enabling Timer 3 TIM_SelectOutputTrigger(TIM3,TIM_TRGOSource_Update); // ADC_ExternalTrigConv_T2_TRGO TIM_Cmd(TIM3,ENABLE);}void Config_RegADC_Init(void){ ADC_InitTypeDef ADC_InitStruct; GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); //GPIO setups PC3 and PC4 for the raw TEV signals GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOC, &GPIO_InitStructure); ADC_DeInit(); //Default All ADC settings registers ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b; ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStruct.ADC_ContinuousConvMode = DISABLE; ADC_InitStruct.ADC_NbrOfConversion= 2; ADC_InitStruct.ADC_ScanConvMode= ENABLE; ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T3_TRGO ;//TIM3 trigger output TIM3 is a 16 bit timer.Reg ADC ADC_InitStruct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_Rising; ADC_Init(ADC1, &ADC_InitStruct); /* Enable ADC1 DMA */ ADC_DiscModeChannelCountConfig(ADC1, 2); //Discontinuous Mode configuration ADC_DiscModeCmd(ADC1, ENABLE); /*ADC Channel for LP TEV*/ ADC_RegularChannelConfig(ADC1, ADC_Channel_12,1,ADC_SampleTime_56Cycles); //tocheck /*ADC Channel for UTP TEV*/ ADC_RegularChannelConfig(ADC1, ADC_Channel_13,2,ADC_SampleTime_56Cycles); /* Enable DMA request after last transfer (Single-ADC mode) */ ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE); ADC_DMACmd(ADC1, ENABLE); ADC_Cmd(ADC1, ENABLE);}void RegADC_DMA_Setup () { DMA_InitTypeDef DMA_InitStruct; NVIC_InitTypeDef NVIC_ADCRegDMA_InitStruct; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); DMA_ITConfig (DMA2_Stream4, DMA_IT_TC | DMA_IT_HT, ENABLE); DMA_InitStruct.DMA_Channel = DMA_Channel_0; DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)ADC1_DR_ADDRESS; DMA_InitStruct.DMA_Memory0BaseAddr = (uint32_t)&ADC_DMA_Buffer[0]; DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralToMemory; DMA_InitStruct.DMA_BufferSize = DMA_BUFFER_SIZE; DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStruct.DMA_Mode = DMA_Mode_Normal; DMA_InitStruct.DMA_Priority = DMA_Priority_High; DMA_InitStruct.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStruct.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull; DMA_InitStruct.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStruct.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA2_Stream4, &DMA_InitStruct); //adc1 is on dma2 channel 0 stream 4 /***NVIC Setup for the DMA***/ NVIC_ADCRegDMA_InitStruct.NVIC_IRQChannel = DMA2_Stream4_IRQn; //dma 2 stream 4 pertains to ADC1 NVIC_ADCRegDMA_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; NVIC_ADCRegDMA_InitStruct.NVIC_IRQChannelSubPriority = 0; NVIC_ADCRegDMA_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init (&NVIC_ADCRegDMA_InitStruct); DMA_Cmd(DMA2_Stream4, ENABLE); ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE); /*Enabling the DMA interput for a halfway transfer and end of copy transfer*/ }

#adc #stm32f4 #dma
1 REPLY 1
Posted on December 03, 2015 at 13:06

Your code is incomplete and unreadable.

Overflow means you are not servicing things quickly enough. The debug view is going to give a non-timely view, and the events are occurring on a non-human time scale.

You probably want to use Circular DMA, with Normal you are going to have to continuously service and reconfigure the transfer. Don't see any code indicating the size of the buffer, or how the IRQ handler works.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..