2013-09-13 08:14 AM
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 #discovery2013-09-13 08:55 AM
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.
2013-09-18 02:04 AM
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 farla
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 inmv
*/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] ????2013-09-18 05:02 AM
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.2013-09-18 06:41 AM
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=false2013-09-18 12:46 PM
2013-09-19 05:51 AM
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.2013-09-19 06:58 AM
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.2013-09-19 08:32 AM
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);
????2013-09-19 09:05 AM
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.