cancel
Showing results for 
Search instead for 
Did you mean: 

ADC channel reading

sherif
Associate II
Posted on January 23, 2013 at 16:16

Hi guys,

I'm using two channels of ADC1 to convert two different inputs, i'm using the interrupt mode of End Of Conversion.

I don't know how to get these values into two different variables.

Please take a look at my code,

/* Initialize the ADC1 according to the ADC_InitStructure members */

ADC_InitTypeDef ADC_InitStructure;

ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;

ADC_InitStructure.ADC_ScanConvMode = ENABLE; /* Choose ADC to scan all the channels registered */

ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; /* Choose Continuous mode, ADC starts another conversion as soon as it finishes one */

ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; /* Start conversion by software */

ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

ADC_InitStructure.ADC_NbrOfChannel = 2; /* ADC1_IN0 and ADC1_IN3 */

ADC_Init(ADC1, &ADC_InitStructure);

/* Configures ADC1 (Bat_Status) Channel0 as: first converted channel with a 7.5 cycles sample time */

ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_7Cycles5); //Sample time may need modification, Old=0.4us, New=0.375us

/* Configures ADC1 (ADC) Channel3 as: second converted channel with a 7.5 cycles sample time */

ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 2, ADC_SampleTime_7Cycles5); //Sample time may need modification

/* Enable ADC1 EOC interrupt */

ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE); /* EOC = End Of Conversion */

/* Enable ADC1 */

ADC_Cmd(ADC1, ENABLE);

/* Reset the ADC1 Calibration registers */

ADC_ResetCalibration(ADC1);

/* Check the end of ADC1 reset calibration register */

while(ADC_GetResetCalibrationStatus(ADC1));

/* It is recommended to start calibration for the ADC after each power up */

/* Start the ADC1 Calibration */

ADC_StartCalibration(ADC1);

/* Get the ADC1 calibration status */

while(ADC_GetCalibrationStatus(ADC1));

/* Start by software the ADC1 Conversion */

ADC_SoftwareStartConvCmd(ADC1, ENABLE);

In the handler, i clear the interrupt bending bit then what? how to choose a specific channel to get it's value?

Any help would be so much appreciated

#dma #adc #adc #stm32 #stm32
6 REPLIES 6
raptorhal2
Lead
Posted on January 23, 2013 at 17:54

The usual way is to use DMA to transfer more than one channel into an array. See Waytae's post below for more information.

Cheers, Hal

sherif
Associate II
Posted on January 24, 2013 at 14:50

Thanks a lot for your help, the thread you mentioned was very helpful

Here's my final code, haven't tried it yet, but if there's any glitches, you may let me know please.

#define ADC1_DR_ADDRESS ((uint32_t)0x4001244C)

__IO uint16_t ADC1ConvertedValues[2];

void ADC_Config(void)

{

/* Initialize the ADC1 according to the ADC_InitStructure members */

ADC_InitTypeDef ADC_InitStructure;

ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;

ADC_InitStructure.ADC_ScanConvMode = ENABLE; 

ADC_InitStructure.ADC_ContinuousConvMode = ENABLE

ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;

ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;

ADC_InitStructure.ADC_NbrOfChannel = 2; /* ADC1_IN0 and ADC1_IN3 */

ADC_Init(ADC1, &ADC_InitStructure);

ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_7Cycles5); //Sample time may need modification, Old=0.4us, New=0.375us

ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 2, ADC_SampleTime_7Cycles5); //Sample time may need modification

/* Enable ADC1 DMA transfer */

ADC_DMACmd(ADC1, ENABLE);

/* Enable ADC1 */

ADC_Cmd(ADC1, ENABLE);

/* Reset the ADC1 Calibration registers */

ADC_ResetCalibration(ADC1);

/* Check the end of ADC1 reset calibration register */

while(ADC_GetResetCalibrationStatus(ADC1));

/* Start the ADC1 Calibration */

ADC_StartCalibration(ADC1);

/* Get the ADC1 calibration status */

while(ADC_GetCalibrationStatus(ADC1));

/* Start by software the ADC1 Conversion */

ADC_SoftwareStartConvCmd(ADC1, ENABLE);

}

void DMA_Config(void)

{

/* Initialize the DMA1 Channel1 according to the DMA_InitStructure members */

DMA_InitTypeDef DMA_InitStructure;

DMA_InitStructure.DMA_PeripheralBaseAddr = ADC1_DR_ADDRESS;

DMA_InitStructure.DMA_MemoryBaseAddr =(uint32_t)&ADC1ConvertedValues;

DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;

DMA_InitStructure.DMA_BufferSize = 2;

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; //Better for SCAN and CONTINOUS ADC modes

DMA_InitStructure.DMA_Priority = DMA_Priority_High;

DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

DMA_Init(DMA1_Channel1, &DMA_InitStructure);

/* Enable DMA1 Channel1 */

DMA_Cmd(DMA1_Channel1, ENABLE);

}

int main(void)

{

ADC_Config();

DMA_Config();

//Do whatever with ADC1ConvertedValues[0] and ADC1ConvertedValues[1]

}
raptorhal2
Lead
Posted on January 24, 2013 at 15:54

Swap the initializations in main.c. DMA needs to be ready before starting the ADC. A usually better solution is to start the ADC in main after calling initializations.

Cheers, Hal

sherif
Associate II
Posted on January 24, 2013 at 16:33

You mean to do the ADC initialization in the main after all other ones?

raptorhal2
Lead
Posted on January 24, 2013 at 19:39

int main(void)

{

DMA_Config();

ADC_Config();

//Do whatever with ADC1ConvertedValues[0] and ADC1ConvertedValues[1]

}

The problem is that the ADC conversion was started in ADC configuration before DMA was configured, probably producing undefined results.

Cheers, Hal

peeter_suur
Associate
Posted on May 04, 2015 at 10:41

Hello

I have started to look into ARM and STM32 world and from ATMEGA it is very eyes opening to see how things really are working. I am playing with STM32F103 and using Eclipse ARM GCC OpenOCD tool-chain.

I managed to control digital inputs and outputs and there is no problem with those but I am really struggling with analog inputs. I would just like to read one or several potentiometer values from AI but I am not able to do that. I have tried many samples (single- and multichannel) which could be found on internet and I think that generally I understand AI and ADC working principles but there are some issues.

I have included stm32f10x.h, stm32f10x_conf.h, stm32f10x_adc.h headers and it seems that I have correct paths configured but with some ADC functions the code just isn’t compiling. For example ADC_ResetCalibration(ADC1) and other calibration functions but mainly ADC_DeInit(), ADC_Init(ADC1, &ADC_InitStructure) and ADC_Cmd(ADC1, ENABLE) are all giving undefined reference error. However when I comment those out, other ADC functions are accepted and code is compiling.

Hopefully I wrote it under correct topic. I have been dealing with it for so long time and I am getting out of ideas, what to try. Could somebody please give a hint, what should I do or try?