Part Number: C2000WARE
Other Parts Discussed in Thread: TMS320F28P550SG,
Device: TMS320F28P550SG (F28P55x)
C2000Ware: 26.01.00.00 (also present in 26.00.00.00 and 5.05.00.00)
File: driverlib/f28p55x/driverlib/adc.c, ADC_setVREF() at line 202
Summary
-------
ADC_setVREF() writes the reference-range bits from the refVoltage value alone,
without considering refMode. Because the two range enumerations alias, this
selects the wrong full-scale range whenever the external reference is used.
Issue 1 - external-mode range is inverted
-----------------------------------------
adc.h:445-450 defines both range sets over the same two values:
ADC_REFERENCE_3_3V = 0U,
ADC_REFERENCE_2_5V = 1U,
ADC_REFERENCE_VREFHI = 0U,
ADC_REFERENCE_2xVREFHI = 1U
adc.c:267 then decides the ANAREFPCTL range bits [14:10] on that value alone:
if(refVoltage == ADC_REFERENCE_3_3V) // i.e. value == 0
{
... |= ((ASYSCTL_ANAREF_ADCA | ... ) << 10); // set
}
else
{
... &= ~((ASYSCTL_ANAREF_ADCA | ... ) << 10); // clear
}
Setting those bits selects the *higher* range. In internal mode the higher
range is 3.3 V, which is value 0, so the mapping is correct. In external mode
the higher range is 2x VREFHI, which is value 1 - so the mapping is inverted:
ADC_setVREF(base, ADC_REFERENCE_EXTERNAL, ADC_REFERENCE_VREFHI)
-> sets the bits -> FSR = 2 x VREFHI
Requesting a 1x VREFHI full scale therefore configures 2x VREFHI. On our board
(external reference, VREFHI - VREFLO = 3.0 V) the readings were consistent with
a 6.0 V FSR - roughly half the expected value - and no calibration constant
corrects it, because the error is in the reference configuration rather than
the scaling. Explicitly clearing the range bits restored agreement with the
3.0 V reference.
A single mode-blind comparison cannot be correct for both sets. The branch
needs to depend on refMode:
if(refMode == ADC_REFERENCE_EXTERNAL)
{
setBits = (refVoltage == ADC_REFERENCE_2xVREFHI);
}
else
{
setBits = (refVoltage == ADC_REFERENCE_3_3V);
}
Issue 2 - VDDA branch writes the wrong register
------------------------------------------------
In the ADC_REFERENCE_VDDA branch, adc.c:250 and adc.c:256 both write
ANAREFPCTL. The second should be ANAREFNCTL, matching the INTERNAL and
EXTERNAL branches above it, which each write both registers. As written,
ANAREFNCTL is never updated for VDDA mode.
Issue 3 - documentation contradicts itself
-------------------------------------------
adc.h:4097 states of refVoltage: "This is ignored when the reference mode is
external." The implementation applies it unconditionally, and the \note at
adc.h:4108-4113 gives the FSR rule for the external values. The parameter
description appears to be the incorrect one.
That same note also says "When the \e refMode parameter is
ADC_REFERENCE_VREFHI" - ADC_REFERENCE_VREFHI is a refVoltage value, not a
refMode value.
Questions
---------
1. Is the intended register semantics that bits [14:10] set = higher range in
both modes (3.3 V internal, 2x VREFHI external)? That is what our results
imply, but I could not find it stated explicitly in the TRM.
2. Is a fix planned? We are carrying a local replacement in the meantime.