2013-04-24 06:59 AM
Hi, all.
I working at ADC sampler implementation. ADCsamplerhas a next flow:When I use DMA at normal mode, then sampled frame is OK.
But when I enable circular DMA mode i get garbage. Although when I enable DMA double feature I receive the same garbage. The final target is to use double buffer, so when one will be at sampling stage and the second one at processing stage. Is anyone faced this problem? Initiation code:/* Enable DMA for ADC transfer */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
/* Enable ADC1,ADC2 for capacitor sensing */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1 | RCC_APB2Periph_ADC2 | RCC_APB2Periph_ADC3, ENABLE);
/* Select DMA Channel 0 for ADC transfer */
DMA_InitStructure.DMA_Channel = DMA_Channel_0;
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)AdcParams.AdcBuf1;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC->CDR;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
DMA_InitStructure.DMA_BufferSize = ADC_SAMLPER_BUFFER_SIZE;
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_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_High;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_Init(DMA2_Stream0, &DMA_InitStructure);
/* DMA2_Stream0 enable */
DMA_Cmd(DMA2_Stream0, DISABLE);
/* Configure double DMA mode.
- Assign second ADC buffer.
- Set Memory 0 as current memory address
- This function can be called only when the DMA Stream is disabled.
*/
DMA_DoubleBufferModeConfig(DMA2_Stream0,(uint32_t)AdcParams.AdcBuf2,DMA_Memory_0);
/* Enable DMA double mode. This function can be called only when the DMA Stream is disabled.*/
DMA_DoubleBufferModeCmd(DMA2_Stream0, ENABLE);
/* DMA2_Stream0 enable */
DMA_Cmd(DMA2_Stream0, ENABLE);
/* ADC Common Init */
ADC_CommonInitStructure.ADC_Mode = ADC_TripleMode_RegSimult;
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2;
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_1;
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_12Cycles;
ADC_CommonInit(&ADC_CommonInitStructure);
/* ADC1 Configuration */
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b;
ADC_InitStructure.ADC_ScanConvMode = DISABLE;//;
ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC2;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_RisingFalling;
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfConversion = 1;
ADC_Init(ADC1, &ADC_InitStructure);
/* ADC1 regular channels 10-11 configuration */
ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_3Cycles);
/* Enable ADC1 DMA */
ADC_DMACmd(ADC1, ENABLE);
/* ADC2 Configuration */
ADC_InitStructure.ADC_NbrOfConversion = 1; /* Set ADC to single conversion */
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
ADC_Init(ADC2, &ADC_InitStructure);
/* ADC2 regular channels 0 configuration */
ADC_RegularChannelConfig(ADC2, ADC_Channel_11, 1, ADC_SampleTime_3Cycles);
ADC_Init(ADC3, &ADC_InitStructure);
ADC_RegularChannelConfig(ADC3, ADC_Channel_2, 1, ADC_SampleTime_3Cycles);
/* Enable ADC1,ADC2,ADC3 */
ADC_Cmd(ADC1, ENABLE);
ADC_Cmd(ADC2, ENABLE);
ADC_Cmd(ADC3, ENABLE);
2013-04-24 07:55 AM
Not sure why you'd need to use double buffer, frankly I think a sufficiently large circular sample buffer, with interrupts on the DMA HT and TC would be adequate. No idea from your presented code what the size of the buffer is.
Remember the DMA doesn't stop when you sit in a debugger, and you need to process the data quicker than it comes in.2013-04-24 10:02 PM
The buffer size is 30 (3 channels * 10 samplers at 50 usec). The reason why I want use is simple, I do not want to perform addition calculation of start and end frame indexes in a circular buffer. With double buffer usage every 50 usec I'll have sampled frame. What I need to is to read CT from DMA register. Looks to me more sufficient solution for needs.
Any way, someone already deal with this kind of problem?2013-04-25 12:32 AM
I have found the problem. I didn't enable DDS at ADC->CCR.
After reading once again ADC manual : found at 11.8.1: - Requests can continue to be generated if the DDS bit is set to 1. This allows configuring the DMA in double-buffer circular mode.Right now it is working exactly how I wan to.Clive1 thanks to your example at [DEAD LINK /public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/stm32f207%20ADC%2bTIMER%2bDMA%20%20Poor%20Peripheral%20Library%20Examples&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B¤tviews=25]stm32f207 ADC+TIMER+DMA / Poor Peripheral Library Examples