2014-10-07 05:07 PM
Hi All,
I have configured the ADC according to the initialization code below and then try to to a conversion to read the VREFINT voltage so as to calculated AVDD. The initialization appears to work ok and the conversion succeeds, but the results returned are incorrect. In fact, after a hardware reset, the first conversion is way off, the second is close, but the third and subsequent readings are close to the actual AVDD (3.31 as per volt meter and 3.40 as per return value). I have searched through the datasheet extensively and I cannot explain what is happening. I suspect something in either my initialization or conversion code is either missing or in the wrong order. Here is the initialization code:RCC
->
APB2ENR
|=
RCC_APB2ENR_SYSCFGEN
|
RCC_APB2ENR_ADC1EN
;
// Enable SYSCFG & ADC1 clocks
asm
(
''DSB''
)
;
// Errata 2.1.8 Work-around
SYSCFG
->
CFGR3
|=
SYSCFG_CFGR3_EN_BGAP
|
SYSCFG_CFGR3_ENBUF_BGAP_ADC
;
// Enable VREFINT for ADC
while
((
PWR
->
CSR
&
PWR_CSR_VREFINTRDYF
)
==
0
)
;
// Wait VREFINT ready
ADC1
->
CR
|=
ADC_CR_ADCAL
;
// Start calibration and enable regulator
while
((
ADC1
->
ISR
&
ADC_ISR_EOCAL
)
==
0
)
;
// Wait for calibration to be done
ADC1
->
CR
|=
ADC_CR_ADEN
;
// Enable ADC
while
((
ADC1
->
ISR
&
ADC_ISR_ADRDY
)
==
0
)
;
// wait for ADC to be ready
ADC
->
CCR
|=
ADC_CCR_VREFEN
|
(
9U
<<
18
)
;
// Enable vref internal and divide ADCCLK : 16 MHZ/64 = 250 KHz
ADC1
->
SMPR
=
2
;
// (13.5 + 12.5) ADC cycles/conversion = 9615.4 Ksps
while
((
SYSCFG
->
CFGR3
&
SYSCFG_VREFINT_ADC_RDYF
)
==
0
)
;
// Wait for ADC to be ready to read VREFINT
Here is the conversion code:ADC1
->
CHSELR
=
ADC_CHSELR_CHSEL17
;
// V-Ref voltage
ADC1
->
CR
|=
ADC_CR_ADSTART
;
// Start conversion
while
((
ADC1
->
ISR
&
ADC_ISR_EOSMP
)
==
0
)
;
// Wait for conversion to finish
return
UInt16
(
ADC1
->
DR
)
;
// Clears ADC_ISR_EOSMP flag and returns sample
#adc-vrefint2014-10-08 12:26 AM
> readings are close to the actual AVDD (3.31 as per volt meter and 3.40 as per return value).
How did you arrive to the volts value? JW2014-10-08 05:47 AM
I used the 16-bit VREFINT_CAL value at $
0x1FF80078
along with the equation shown in the data sheet. The data sheet states that the calibration value was determined for AVDD set at 3.3, but appnote #3964 indicates it was 3.0V. When I use the 3.0V as the constant, I at least get close to the actual value.
Here is the code sequence:UInt16
const
&
vref_intcal
=
*
(
UInt16
const
*
)
0x1FF80078
;
/// VDDA = (3.0V +- 0.01) * VREFINT_CAL / VREFINT_DATA ///
UInt16
const
vref_internal
=
adc_device
.
convert
()
;
float
const
vdda
=
3.0F
*
float
(
vref_intcal
)
/
vref_internal
;
printf
(
''ADC = %04X VDDA = %6.4f\r\n''
,
vref_internal
,
vdda
)
;
Here are the results captured from my terminal from this morning. The first is after hardware reset, the second is the next attempt, followed by the remaining. Notice that it looks a bit like some kind of under-damped response. Also, the values read are a bit different from the one I originally posted. ADC = 0043 VDDA = 74.8657 ADC = 0800 VDDA = 2.4492 ADC = 060D VDDA = 3.2382 ADC = 060C VDDA = 3.2403 ADC = 060C VDDA = 3.2403 ADC = 060C VDDA = 3.2403 The actual voltage on AVDD as measured is 3.317. Cheers! Dan