2017-02-16 08:56 AM
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-mode2017-02-16 09:17 AM
> va1 = ((float)ADC_GetInjectedConversionValue(ADC2, ADC_InjectedChannel_1))/1000.0;
Is this used to calculate the measured voltage in Volts?
JW
2017-02-16 10:21 AM
Hello, thanks for your answer.
Yes, exactly for that reason, I need to have the converted value in Volts.
2017-02-16 10:44 AM
And what does the manual to the 'library' you used say on the return value of ADC_GetInjectedConversionValue()?
JW
2017-02-16 11:23 AM
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); }2017-02-16 12:57 PM
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
2017-02-17 02:02 AM
Absolutely correct.
Thank you, now it works fine.
Have a nice day
Marco