cancel
Showing results for 
Search instead for 
Did you mean: 

Wrong value conversion ADC in injected scan mode

mlisi
Associate II
Posted on February 16, 2017 at 17:56

Hello, I'm trying to read 3 voltages with the ADC2 on my stm32f207zc, using an injected mode + scan mode configuration, but I'm observing this behavior:

basically the each of the 3 voltages are generated by one differential amplifier witch gives about 1.7V when no differential input is present.

The point is that the converted value I read is 2.0 V for all 3 inputs.

Then if i change the voltage to 3.3V (maximum), I read with the ADC something around 4V.

I'm sure of the voltages cause I'm watching them with an oscilloscope.

Here is my code, I use std_periph_library:

initialization af the adc:

void ADC2Init(void)

{

GPIO_InitTypeDef GPIO_InitStructure;

ADC_InitTypeDef ADC_InitStruct;

ADC_CommonInitTypeDef ADC_CommonInitStructure;

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);

/* Configure ADC2 Channe10,12,13 pin as analog input ******************************/

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_2 | GPIO_Pin_3;

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AN;

GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;

GPIO_Init(GPIOC, &GPIO_InitStructure);

/* 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);

/* ADC2 Init ****************************************************************/

ADC_InitStruct.ADC_Resolution = ADC_Resolution_12b;

ADC_InitStruct.ADC_ScanConvMode = ENABLE;

ADC_InitStruct.ADC_ContinuousConvMode = DISABLE;

ADC_InitStruct.ADC_ExternalTrigConvEdge = ADC_ExternalTrigConvEdge_None;

ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_T1_CC1;

ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;

ADC_InitStruct.ADC_NbrOfConversion = 1;

ADC_Init(ADC2, &ADC_InitStruct);

ADC_InjectedSequencerLengthConfig(ADC2, 1);

ADC_AutoInjectedConvCmd(ADC2, DISABLE);

ADC_InjectedChannelConfig(ADC2, ADC_Channel_10,1, ADC_SampleTime_3Cycles);

ADC_InjectedChannelConfig(ADC2, ADC_Channel_12,2, ADC_SampleTime_3Cycles);

ADC_InjectedChannelConfig(ADC2, ADC_Channel_13,3, ADC_SampleTime_3Cycles);

/* Enable ADC2 */

ADC_Cmd(ADC2, ENABLE);

}

and then the read of the converted value:

...

ADC_SoftwareStartInjectedConv(ADC2); //per far partire la conversione

while ( ADC_GetFlagStatus(ADC2, ADC_FLAG_JEOC) == RESET)

{

}

va1 = ((float)ADC_GetInjectedConversionValue(ADC2, ADC_InjectedChannel_1))/1000.0;

vb1 = ((float)ADC_GetInjectedConversionValue(ADC2, ADC_InjectedChannel_2))/1000.0;

vc1 = ((float)ADC_GetInjectedConversionValue(ADC2, ADC_InjectedChannel_3))/1000.0;

ADC_ClearFlag(ADC2, ADC_FLAG_JEOC);

ADC_ClearFlag(ADC2, ADC_FLAG_JSTRT); 

...

What am I doing wrong?

Thank you!!

#3-channels-injected #stm32-adc #scan-mode #injected-mode #injected-adc #firmware #stm32 #adc #injected-scan-mode
6 REPLIES 6
Posted on February 16, 2017 at 18:17

> va1 = ((float)ADC_GetInjectedConversionValue(ADC2, ADC_InjectedChannel_1))/1000.0;

Is this used to calculate the measured voltage in Volts?

JW

Posted on February 16, 2017 at 18:21

Hello, thanks for your answer.

Yes, exactly for that reason, I need to have the converted value in Volts.

Posted on February 16, 2017 at 18:44

And what does the manual to the 'library' you used say on the return value of ADC_GetInjectedConversionValue()?

JW

Posted on February 16, 2017 at 19:23

this is what I know about this function:

* @brief Returns the ADC injected channel conversion result

* @param ADCx: where x can be 1, 2 or 3 to select the ADC peripheral.

* @param ADC_InjectedChannel: the converted ADC injected channel.

* This parameter can be one of the following values:

* @arg ADC_InjectedChannel_1: Injected Channel1 selected

* @arg ADC_InjectedChannel_2: Injected Channel2 selected

* @arg ADC_InjectedChannel_3: Injected Channel3 selected

* @arg ADC_InjectedChannel_4: Injected Channel4 selected

* @retval The Data conversion value.

*/

uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef* ADCx, uint8_t ADC_InjectedChannel)

{

__IO uint32_t tmp = 0;

/* Check the parameters */

assert_param(IS_ADC_ALL_PERIPH(ADCx));

assert_param(IS_ADC_INJECTED_CHANNEL(ADC_InjectedChannel));

tmp = (uint32_t)ADCx;

tmp += ADC_InjectedChannel + JDR_OFFSET;

/* Returns the selected injected channel conversion data value */

return (uint16_t) (*(__IO uint32_t*) tmp);

}
Posted on February 16, 2017 at 20:57

OK, so it returns the value it read from the ADC's data register. It is not a value in volts, rather, in 'bins', i.e. a number in the 0..2^nr_of_ADC_bits-1 range (here, 0..4095). The input_voltage = reference_voltage * this_number / 2^n. Reference voltage is input through the VREF pins, in smaller packages directly tied into VDDA/VSSA.

Read ADC section of reference manual.

JW

Posted on February 17, 2017 at 10:02

Absolutely correct.

Thank you, now it works fine.

Have a nice day

Marco