cancel
Showing results for 
Search instead for 
Did you mean: 

Multi Channel ADC reading.

to_sam_kim
Associate II
Posted on September 14, 2013 at 02:04

Hello,

I tried to read two analog inputs from PA3(ADC1_IN3) and PA5(ADC1_IN5).

I expected tmpADC[0] has the input data of PA3 and tmpADC[1] has the input data of PA5. However, both tmpADC[0] and tmpADC[1] always have the input data of PA3. 

I read reference manual multiple times, but I couldn't figure out what is wrong.

Please let me know what is problem. I attached my code below(only ADC part).

Thanks 

&sharpinclude <stm32f4xx.h>

void ADC_Init(void)

{

 GPIOA->MODER   |= (3UL<<6)|(3UL<<10);     /*Set PA3 as an analog input, ADC1_IN3, Set PA5 as an analog input ADC1_IN5*/

 GPIOA->PUPDR   &= ~((3UL<<6)|(3UL<<10));   /*No Pull up and down resistor*/

 

 RCC->APB2ENR   =(1<<8);       /*ADC1 clk enable*/

 ADC1->CR1 = 0;

 ADC1->CR2 = (1UL<<0)|          /*ADC1 power on */

            (1UL<<1);          /*Continuous conversion*/

                     

 ADC1->SMPR1 = 0;

 ADC1->SMPR2 = 0;

 ADC1->SQR1 = (1<<20);                   /* sequence length: two regular conversions*/

 ADC1->SQR2 = 0;

 ADC1->SQR3 = (3UL<<0)|(5UL<<5);         /*1st conversion = ADC1_lN3, 2nd conversion = ADC1_IN5*/

 ADC->CCR = (1UL<<16);          /*fpclk2/4 = 21Mhz */

}

 

short unsigned int get_ADC(void)

{

ADC1->CR2 |= (1<<30);

 while(!(ADC1->SR & 0x2));

 return ADC1->DR;

}

int main (void)

{

       tmpADC[0]  = get_ADC();    // expecting have data from ADC1_IN3

  

       tmpADC[1] = get_ADC();   //expecting have data from ADC1_IN5

}

#stm32f4 #discovery-board #adc-dma
17 REPLIES 17
Posted on October 08, 2013 at 22:35

I've built a 5x version in Keil that seems serviceable, and produces values in the 0-4095 range, not sure what's going on here.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
csfarnham
Associate II
Posted on October 09, 2013 at 07:41

Well I tried the code in a new project and it worked flawlessly even though the code running was identical.  Very strange.  Thank you for your help.

Chris

djackson
Associate II
Posted on April 17, 2014 at 23:20

What's the cut-off for ''slow speed''?

Posted on April 17, 2014 at 23:32

What's the cut-off for ''slow speed''?

SampleTime+12 vs your ability to service the EOC interrupt. I haven't plotted the curve, DMA requires no thought.

 

The total conversion time is calculated as follows:

 

Tconv = Sampling time + 12 cycles

 

Example:

 

With ADCCLK = 30 MHz and sampling time = 3 cycles:

 

Tconv = 3 + 12 = 15 cycles = 0.5 μs with APB2 at 60 MHz

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
gavinli
Associate II
Posted on January 12, 2015 at 17:46

Clive1

I used your first posted program with a little modification to convert the same channel for 8 times, but I find only the first 4 conversions are ''correct'' and the second 4 conversions are ''wrong''. What is wrong in the program? Please help. the converted values are: 0x819, 0x817, 0x818, 0x818, 0x6F8, 0x638, 0x517, 0x464 The values get smaller and smaller.

typedef struct { 
int chn_nr; //total channels 
uint8 chn[TOTAL_CHN]; 
} ADCDev; 
//const ADCDev adc1 = {8, { 4, 4, 4, 4, 4, 4, 4, 4 } }; 
const ADCDev adc1 = {8, {16, 16, 16, 16, 16, 16, 16, 16} }; 
void ADC_Configuration(uint16_t *ADCConvertedValues) 
{ 
ADC_InitTypeDef ADC_InitStructure; 
ADC_CommonInitTypeDef ADC_CommonInitStructure; 
DMA_InitTypeDef DMA_InitStructure; 
/* Enable peripheral clocks *************************************************/ 
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); 
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); 
/* DMA2_Stream0 channel0 configuration **************************************/ 
DMA_DeInit(DMA2_Stream0); 
DMA_InitStructure.DMA_Channel = DMA_Channel_0; 
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR; 
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)ADCConvertedValues; 
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; 
DMA_InitStructure.DMA_BufferSize = ADC1; 
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_HalfFull; 
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, ENABLE); 
/* ADC Common Init **********************************************************/ 
ADC_CommonInitStructure.ADC_Mode = ADC_Mode_Independent; 
ADC_CommonInitStructure.ADC_Prescaler = ADC_Prescaler_Div2; 
ADC_CommonInitStructure.ADC_DMAAccessMode = ADC_DMAAccessMode_Disabled; 
ADC_CommonInitStructure.ADC_TwoSamplingDelay = ADC_TwoSamplingDelay_5Cycles; 
ADC_CommonInit(&ADC_CommonInitStructure); 
ADC_TempSensorVrefintCmd(ENABLE); 
/* ADC1 Init ****************************************************************/ 
ADC_InitStructure.ADC_Resolution = ADC_Resolution_12b; 
ADC_InitStructure.ADC_ScanConvMode = ENABLE; 
ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; 
ADC_InitStructure.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None; 
ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1; 
ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; 
ADC_InitStructure.ADC_NbrOfConversion = adc1.chn_nr; 
ADC_Init(ADC1, &ADC_InitStructure); 
/* ADC1 regular channel configuration ******************************/ 
//ADC_RegularChannelConfig(ADC1, ADC_Channel_3, 1, ADC_SampleTime_480Cycles); // PA3 
//ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 2, ADC_SampleTime_480Cycles); // PA5 
for (int i=0;i<sizeof(adc1.chn_nr);i++) 
ADC_RegularChannelConfig(ADC1, adc1.chn[i], i+1, ADC_SampleTime_3Cycles); 
/* Enable DMA request after last transfer (Single-ADC mode) */ 
ADC_DMARequestAfterLastTransferCmd(ADC1, ENABLE); 
/* Enable ADC1 DMA */ 
ADC_DMACmd(ADC1, ENABLE); 
/* Enable ADC1 **************************************************************/ 
ADC_Cmd(ADC1, ENABLE); 
/* Start ADC1 Software Conversion */ 
ADC_SoftwareStartConv(ADC1); 
} 

Posted on January 12, 2015 at 19:09

DMA_InitStructure.DMA_BufferSize = ADC1;

//????
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
gavinli
Associate II
Posted on January 12, 2015 at 21:07

Hi Clive1

Sorry, I made a mistake when I clean up the code for this post. it is adc1.chn_nr;

The question is still the same, why one the first 4 conversions are OK? I even tried to convert 16 times, but it is only the first 4 are reasonable, and the values are getting smaller and smaller after 4 conversion.

Posted on January 12, 2015 at 21:17

The question is still the same, why one the first 4 conversions are OK? I even tried to convert 16 times, but it is only the first 4 are reasonable, and the values are getting smaller and smaller after 4 conversion.

 

I guess you'd have to ponder the ability of the signal source to supply current to charge the capacitor in the sample circuit, and the sample time?

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