2017-04-01 11:22 AM
Hi,
Trying to do a ADC continuous scan with 4 sequential channels using DMA, ending up with one single DMA Transfer Complete Interrupt, though I am clearing the TC interrupt. The single transfer has the correct ADC result for all the 4 channels, but it fires just once alone. Read the Reference manual a few times, but cant find what I am indeed missing to get the Continuous Conversion working. Aargh! Obviously, I am missing something .. Is someone kind enough to lend a set of eyeballs, to find what I am missing ?
Thanks!
The output what I get:
DMA1_TC
::0 1653 0 1extern char adcstr[50];
uint16_t ADCVal[4] = {0, 0, 0, 0};void DMA1_Channel1_IRQHandler(void)
{ if (DMA_GetITStatus(DMA1_IT_TC1)) { putstr(USART1, 'DMA1_TC\r'); sprintf((char*)adcstr, '::%d %d %d %d\r', ADCVal[0], ADCVal[1], ADCVal[2], ADCVal[3]); putstr(USART1, adcstr); DMA_ClearITPendingBit(DMA1_IT_TC1); } if (DMA_GetITStatus(DMA1_IT_TE1)) { putstr(USART1, 'DMA1_TE\r'); DMA_ClearITPendingBit(DMA1_IT_TE1); }}void adc_dmascan_init(void)
{ __IO uint32_t cal_factor = 0; ADC_InitTypeDef adci; ADC_CommonInitTypeDef adcc; DMA_InitTypeDef dma;/* ADC and GPIO clk config */
RCC_ADCCLKConfig(RCC_ADC12PLLCLK_Div2); /* ADC12 clock = PLLCLK/2 */ __ADC12_CLK_ENABLE(); /* enable ADC1 clock */ __ADC_VREG_ENABLE(ADC1); /* enable ADC voltage regulator */ delay(10); /* wait 10uS */__ADC_CALMODE_SINGLE(ADC1); /* calibrate single ended */
__ADC_CALIBRATE(ADC1); while (!__ADC_CAL_DONE(ADC1)); cal_factor = __ADC_CAL_FACTOR(ADC1);/* setup DMA Ch:1 */
__DMA1_CLK_ENABLE();dma.DMA_DIR = DMA_DIR_PeripheralSRC;
dma.DMA_Mode = DMA_Mode_Circular;dma.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;dma.DMA_MemoryBaseAddr = (uint32_t)&ADCVal;
dma.DMA_BufferSize = 4;dma.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
dma.DMA_MemoryInc = DMA_MemoryInc_Enable; dma.DMA_Mode = DMA_Mode_Normal; DMA_Init(DMA1_Channel1, &dma); DMA_ITConfig(DMA1_Channel1, DMA_IT_TC, ENABLE); DMA_ITConfig(DMA1_Channel1, DMA_IT_TE, ENABLE); NVIC_EnableIRQ(DMA1_Channel1_IRQn);/* ADC Common Init */
adcc.ADC_Mode = ADC_Mode_Independent; adcc.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; adcc.ADC_DMAMode = ADC_DMAMode_Circular; adcc.ADC_Clock = ADC_Clock_AsynClkMode; adcc.ADC_TwoSamplingDelay = 0; ADC_CommonInit(ADC1, &adcc);/* ADC Init */
ADC_StructInit(&adci); adci.ADC_Resolution = ADC_Resolution_12b; adci.ADC_ContinuousConvMode = ADC_ContinuousConvMode_Enable; adci.ADC_DataAlign = ADC_DataAlign_Right; adci.ADC_NbrOfRegChannel = 4; adci.ADC_ExternalTrigConvEvent = ADC_ExternalTrigConvEvent_0; adci.ADC_ExternalTrigEventEdge = ADC_ExternalTrigEventEdge_None; adci.ADC_OverrunMode = ADC_OverrunMode_Disable; adci.ADC_AutoInjMode = ADC_AutoInjec_Disable; ADC_Init(ADC1, &adci);/* Select channels to read */
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_181Cycles5); ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 2, ADC_SampleTime_181Cycles5); ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 3, ADC_SampleTime_181Cycles5); ADC_RegularChannelConfig(ADC1, ADC_Channel_4, 4, ADC_SampleTime_181Cycles5);ADC_DMAConfig(ADC1, ADC_DMAMode_Circular);
ADC_DMACmd(ADC1, ENABLE); ADC_Cmd(ADC1, ENABLE);while (!ADC_GetFlagStatus(ADC1, ADC_FLAG_RDY));
DMA_Cmd(DMA1_Channel1, ENABLE); ADC_StartConversion(ADC1);}2017-04-01 11:32 AM
Gah, After posting alone, noticed the weird issue, that I overwrote the DMA_Mode ..
dma.DMA_Mode = DMA_Mode_Circular;
That fixed it and it works as expected ..
DMA1_TC
::0 1700 3 0DMA1_TC::0 1684 0 0DMA1_TC::0 1734 0 0Sorry about the noise.
2017-04-03 04:48 AM
It will be useful for people exploring the forum for solutions. This will surely help others.