cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F0Discovery - ADC DMA How to sort Conversion Data

Nickname925_O
Associate II
Posted on September 13, 2013 at 17:14

Hi,

I am using the STM32F0Discovery board and I am acquiring ADC converted data value using the DMA.

Well, I am able to read values but I cannot understand how the uC fills the Buffer.

I am using a buffer[5] because I am acquiring 5 ADC converted value (channel 1, 2, 3 and Vref and Temperature).

How can I manage the filling of my buffer?

Thanks in advance,

Giuseppe.

#stm32 #dma #discovery
11 REPLIES 11
Posted on September 13, 2013 at 17:55

If you have the DMA in circular mode it should loop around your array. Double the size of the array and catch the DMA HT and TC interrupts to process the most current set of readings.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Nickname925_O
Associate II
Posted on September 18, 2013 at 11:04

Hi Clive,

please, can you have a look to my code and help me to understand?

void

 

ADC1_CH_DMA_Config(

void

){

 

ADC_InitTypeDef

ADC_InitStructure;

 

DMA_InitTypeDef

DMA_InitStructure;

 

/* ADC1 DeInit */

 

ADC_DeInit(ADC1);

 

/* ADC1

Periph

clock enable */

 

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1,

ENABLE

);

 

/* DMA1 clock enable */

 

RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1 ,

ENABLE

);

 

/* DMA1 Channel1

Config

*/

 

DMA_DeInit(DMA1_Channel1);

 

DMA_InitStructure.

DMA_PeripheralBaseAddr

= (

uint32_t

)ADC1_DR_Address;

 

DMA_InitStructure.

DMA_MemoryBaseAddr

= (

uint32_t

)&RegularConvData_Tab[0];

 

DMA_InitStructure.

DMA_DIR

= DMA_DIR_PeripheralSRC;

 

DMA_InitStructure.

DMA_BufferSize

= 5;

 

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_M2M

= DMA_M2M_Disable;

 

DMA_Init(DMA1_Channel1, &DMA_InitStructure);

 

/* DMA1 Channel1 enable */

 

DMA_Cmd(DMA1_Channel1,

ENABLE

);

 

/* ADC DMA request in circular mode */

 

ADC_DMARequestModeConfig(ADC1, ADC_DMAMode_Circular);

 

/* Enable ADC_DMA */

 

ADC_DMACmd(ADC1,

ENABLE

);

 

/* Initialize ADC structure */

 

ADC_StructInit(&ADC_InitStructure);

 

/* Configure the ADC1 in

continous

mode with a resolution equal to 12 bits */

 

ADC_InitStructure.

ADC_Resolution

= ADC_Resolution_12b;

 

ADC_InitStructure.

ADC_ContinuousConvMode

=

ENABLE

;

 

ADC_InitStructure.

ADC_ExternalTrigConvEdge

= ADC_ExternalTrigConvEdge_None;

 

ADC_InitStructure.

ADC_DataAlign

= ADC_DataAlign_Right;

 

ADC_InitStructure.

ADC_ScanDirection

= ADC_ScanDirection_Backward;

 

ADC_Init(ADC1, &ADC_InitStructure);

 

//

Setto

anche

il

PA0 per far

la

conversione

con

ADC

 

ADC_ChannelConfig(ADC1, ADC_Channel_0 , ADC_SampleTime_1_5Cycles);

 

ADC_ChannelConfig(ADC1, ADC_Channel_1 , ADC_SampleTime_1_5Cycles);

 

ADC_ChannelConfig(ADC1, ADC_Channel_2 , ADC_SampleTime_1_5Cycles);

 

/* Convert the ADC1 temperature sensor with 55.5 Cycles as sampling time */

 

ADC_ChannelConfig(ADC1, ADC_Channel_TempSensor , ADC_SampleTime_55_5Cycles);

 

ADC_TempSensorCmd(

ENABLE

);

 

/* Convert the ADC1

Vref

with 55.5 Cycles as sampling time */

 

ADC_ChannelConfig(ADC1, ADC_Channel_Vrefint , ADC_SampleTime_55_5Cycles);

 

ADC_VrefintCmd(

ENABLE

);

 

/* ADC Calibration */

 

ADC_GetCalibrationFactor(ADC1);

 

/* Enable ADC1 */

 

ADC_Cmd(ADC1,

ENABLE

);

 

/* Wait the ADCEN flag */

 

while

(!ADC_GetFlagStatus(ADC1, ADC_FLAG_ADEN));

 

/* ADC1 regular Software Start

Conv

*/

 

ADC_StartOfConversion(ADC1);

 

}

the problem is that if I go in debug mode I see that the buffer has this data meaning:

/* Wait the ADCEN flag */

while

(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));

ADC_ClearFlag(ADC1, ADC_FLAG_EOC);

/* Test DMA1 TC flag */

while

((DMA_GetFlagStatus(DMA1_FLAG_TC1)) ==

RESET

);

/* Clear DMA TC flag */

DMA_ClearFlag(DMA1_FLAG_TC1);

/* Convert temperature sensor voltage value in

mv

*/

TempSensVoltmv = (

uint32_t

)((RegularConvData_Tab[1]* 3300) / 0xFFF);

/* Convert

Vref

voltage value in

mv

*/

VrefIntVoltmv = (

uint32_t

)((RegularConvData_Tab[2]* 3300) / 0xFFF);

ADC_PA0_INGRESSO =(

uint32_t

)((RegularConvData_Tab[0]* 3000) / 0xFFF);

ADC_PA1_INGRESSO =(

uint32_t

)((RegularConvData_Tab[3]* 3000) / 0xFFF);

ADC_PA2_INGRESSO =(

uint32_t

)((RegularConvData_Tab[4]* 3000) / 0xFFF);

Please, can you help me to understand why:

channel 0 corresponds to RegularConvData_Tab[0]

channel 1 corresponds to RegularConvData_Tab[3]

channel 2 corresponds to RegularConvData_Tab[4]

and not

channel 0 corresponds to RegularConvData_Tab[0]

channel 1 corresponds to RegularConvData_Tab[1]

channel 2 corresponds to RegularConvData_Tab[2]

????

Posted on September 18, 2013 at 14:02

I probably wouldn't be scanning back-ward, and I'd wait until all the initialization/calibration was completed before enabling the DMA.

Not sure how the buffer is defined, and the code is insufficiently complete for me to quickly drop into a compiler and test.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Nickname925_O
Associate II
Posted on September 18, 2013 at 15:41

Hi,

in attachment the main.c.

Thanks for your help.

Giuseppe.

________________

Attachments :

main.c : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HzqX&d=%2Fa%2F0X0000000bQJ%2FbkQZ68jG3VWLgIM.y9suelfJJ7S7PmRKmiuxwb30Iqc&asPdf=false
Posted on September 18, 2013 at 21:46

The original post was too long to process during our migration. Please click on the provided URL to read the original post. https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I6nE&d=%2Fa%2F0X0000000bva%2Fo7X3rWevlzRJLr.3VBqS0ZbYacEMYhLZw6GaLNzEFLU&asPdf=false
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Nickname925_O
Associate II
Posted on September 19, 2013 at 14:51

Hi clive1,

I am sorry but probably I did noy understand your answer.

Can you help me on my question?

Thanks a lot in advance,

Giuseppe.

Posted on September 19, 2013 at 15:58

You complained about sample order, I resolved that in my example. Was there some other issue?

Like I said earlier, don't scan backward, and don't have DMA read the ADC until after you've got all the calibration/configuration done. Things should then stay in order.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Nickname925_O
Associate II
Posted on September 19, 2013 at 17:32

Well,

I tried to run it in debug mode without defining the USE_USART.

Now, in debug mode it seems to fill the buffer in the right way... that's good but I am not able to go over this instruction:

while

((DMA_GetFlagStatus(DMA1_FLAG_TC1)) ==

RESET

);

In fact, instead to run the instruction

#define

 

REFMV 3000

// 3V on STM32F0-Discovery

 

/* Convert temperature sensor voltage value in

mv

*/

TempSensVoltmv = (((

uint32_t

)RegularConvData_Tab[3] * REFMV) / 0x1000);

the debigger goes to the beginnig of while(1)...

any idea?

PS: while, you removed these instructions:

while

(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));

ADC_ClearFlag(ADC1, ADC_FLAG_EOC);

????

Posted on September 19, 2013 at 18:05

EOC has no useful context here. The ADC generates a per sample EOC, which is serviced and cleared by the DMA operation. The DMA TC signals that ALL 5 samples have been made. In an ideal world you'd likely want a 10 sample and use HT/TC to work with the right data.

I'm not using CooCox, or it's debugger, so can't offer no insight into why you are stuck there, perhaps their model doesn't call SystemInit() prior to main(), which would explain your other clock enabling code. If the ADC doesn't clock, the DMA doesn't service it, and you never get 5 transfers and a TC?

I removed that stuff because it's not CMSIS compliant, and doesn't play well in Keil, which I'm using.

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