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*/ }
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_Circular; 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 = 0; 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*/ } void DMA2_Stream4_IRQHandler () { extern uint16_t ADC_DMA_Buffer [DMA_BUFFER_SIZE]; extern bool dataALCready; extern uint16_t probeALCdata[PERIOD], plusALCdata[PERIOD]; //buffers to store 20 ms worth of raw TEv signals uint16_t probeChan_A, plusChan_B; //Locator probe and UTP log raw TEV signals respectively static uint16_t count = 0; uint8_t i; uint16_t probeTEV[PERIOD]; uint16_t plusTEV[PERIOD]; if ( DMA_GetITStatus(DMA2_Stream4, DMA_IT_HTIF4) != RESET)//if the stream transfer is complete { probeChan_A = ADC_DMA_Buffer [0]; //copy DMA contents into globals DMA_ClearITPendingBit(DMA2_Stream4, DMA_IT_HTIF4); } if ( DMA_GetITStatus(DMA2_Stream4, DMA_IT_TCIF4) != RESET)//if the stream transfer is complete { plusChan_B = ADC_DMA_Buffer [1]; probeTEV [count] = probeChan_A; // Array to store 20ms worth of LP TEV signals plusTEV [count] = plusChan_B; // Array to store 20ms worth of UTP TEV signals count++; if (count == 20) { for ( i = 0; i < count; i++) { probeALCdata [i] = probeTEV [i]; plusALCdata [i] = plusTEV [i]; } count = 0; } DMA_ClearITPendingBit(DMA2_Stream4, DMA_IT_TCIF4); } }