AnsweredAssumed Answered

STM32F4-Discovery ADC+DMA double buffer

Question asked by JJ on Mar 16, 2016
Latest reply on Mar 17, 2016 by Clive One
I'm doing ADC + DMA on my STM32F4 Discovery. I have an array (arraySize = 20000) where the data from the ADC peripheral (PA7) is continuously sent to my RawADC array with a buffer size=arraySize=20000 (20000 * 16bit). The initialization and configuration codes are as below.

01.#define ADC1_DR    ((uint32_t)0x4001244C)
02.#arraySize 20000
03.__IO uint16_t RawADC[arraySize];
04. __IO uint16_t Voltage[arraySize];
05.void ADC_DMA_Init (void){
06.  GPIO_InitTypeDef GPIO_InitStructure;
07.  ADC_InitTypeDef ADC_InitStruct;
08.  ADC_CommonInitTypeDef ADC_CommonInitStruct;
09.  DMA_InitTypeDef       DMA_InitStructure;
10.  RCC_AHB1PeriphClockCmd( RCC_AHB1Periph_GPIOA , ENABLE);
11.  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
12.  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;
13.  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
14.  GPIO_Init(GPIOA, &GPIO_InitStructure);
15.  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2,ENABLE);
16.  DMA_StructInit(&DMA_InitStructure);
17.  // Configure DMA2 - Stream 0
18.  DMA_DeInit(DMA2_Stream0);  //Set DMA registers to default values
19.  DMA_InitStructure.DMA_Channel = DMA_Channel_0;
20.  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR; //Source address for ADC pin
21.  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&RawADC[0]; //Destination address
22.  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
23.  DMA_InitStructure.DMA_BufferSize = arraySize;
24.  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
25.  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
26.  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //source size - 16bit
27.  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; // destination size = 16bit
28.  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
29.  DMA_InitStructure.DMA_Priority = DMA_Priority_High; //High Priority
30.  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
31.  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
32.  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
33.  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
34.  DMA_Init(DMA2_Stream0, &DMA_InitStructure); //Initialize the DMA
35.  DMA_Cmd(DMA2_Stream0, ENABLE); //Enable the DMA2 - Stream 0
36.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
37.  ADC_CommonInitStruct.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled;
38.  ADC_CommonInitStruct.ADC_Mode = ADC_Mode_Independent;
39.  ADC_CommonInitStruct.ADC_Prescaler = ADC_Prescaler_Div8;
40.  ADC_CommonInitStruct.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles;
41.  ADC_CommonInit(&ADC_CommonInitStruct);
42.  /* Init ADC settings */
43.  ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;
44.  ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b;
45.  ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
47.  ADC_InitStruct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;
48.  ADC_InitStruct.ADC_NbrOfConversion = 1;
49.  ADC_InitStruct.ADC_ScanConvMode = DISABLE;
50.  ADC_Init(ADC1, &ADC_InitStruct);
51.  ADC_RegularChannelConfig(ADC1,ADC_Channel_7,1,ADC_SampleTime_480Cycles);// PA7
52.  ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE);
53.  ADC_DMACmd(ADC1, ENABLE); //Enable ADC1 DMA
54.  ADC_Cmd(ADC1, ENABLE);   // Enable ADC1
55.  ADC_SoftwareStartConv(ADC1); // Start ADC1 conversion
56.}   
 
In my main loop, I'd like to process data from the RawADC array such as converting to Voltage values or calculate RMS value from the array. 
I'm currently using a for... loop to calculate instantaneous voltage values and put them in another array (Voltage[]). 
for (int i=0; i<arraySize; i++){
  Voltage[i] = (RawADC[i]/0xFFF) * 3;
}
The problem is that when the for loop is being executed, the values of RawADC[] keeps changing since the DMA is constantly updating this array. I'd like to use another DMA stream to copy from RawADC[] array to a bufferArray[] and use the latter to do processing.
My plan is to increase the RawADC array's size to hold more data and configure that array in FIFO mode. The bufferArray will have its size=arraySize=20000 and will take 20000 values from the RawADC array via DMA. I'll do the processing based on bufferArray[]. Any help to configure this is appreciated.

Outcomes