Two simple routines for reading the supply voltage of the MSP430 family are shown below. Some MSP430 devices use the 10-bit ADC, e.g. the MSP430F2274, and some use the 12-bit ADC, e.g. the MSP430F248. Refer to the datasheet for your part to determine which is used.
Using the ADC10:
/** Reads the MSP430 supply voltage using the Analog to Digital Converter (ADC).
On ez430 boards, this is approx. 3600mV
@return Vcc supply voltage, in millivolts
*/
unsigned int getVcc3()
{
ADC10CTL0 = SREF_1 + REFON + REF2_5V + ADC10ON + ADC10SHT_3; // use internal ref, turn on 2.5V ref, set samp time = 64 cycles
ADC10CTL1 = INCH_11;
delayMs(1); // Allow internal reference to stabilize
ADC10CTL0 |= ENC + ADC10SC; // Enable conversions
while (!(ADC10CTL0 & ADC10IFG)); // Conversion done?
unsigned long temp = (ADC10MEM * 5000l); // Convert raw ADC value to millivolts
return ((unsigned int) (temp / 1024l));
}
Using the ADC12:
/** Private helper method to setup ADC for one-shot conversion and read out value according to registers.
Inserts a delay before beginning conversion if REFON
@return the raw ADC value with the specified commands.
@todo move the VREF warmup to startup and leave on to avoid 17mSec blocking delay each time?
*/
unsigned int getAnalogInput(unsigned int adc12ctl0, unsigned int adc12ctl1, unsigned char adc12mctl0)
{
#define ADC_VREF_DELAY_MS 17
ADC12CTL0 = adc12ctl0;
ADC12CTL1 = adc12ctl1;
ADC12MCTL0 = adc12mctl0;
if (adc12ctl0 & REFON) // if internal reference is used...
delayMs(ADC_VREF_DELAY_MS); // 17mSec delay required to Vref capacitors
ADC12CTL0 |= ENC; // Enable conversions
ADC12CTL0 |= ADC12SC; // Start conversions
while (!(ADC12IFG & 0x01)); // Conversion done?
return ADC12MEM0; // Read out 1st ADC value
}
/** Measures Vcc to the MSP430, nominally 3.3V
- ADC measures VCC/2 compared to 2.5V reference
- If Vcc = 3.3V, ADC output should be (1.65/2.5)*4095 = 2703
- Therefore (halfVcc/2.5)*4095 = ADC reading and (Vcc/2.5)*4095 = 2*ADC
- So Vcc*4096 = 5*ADC and VCC=5*ADC/4095
@return Vcc in millivolts
*/
unsigned int getVcc3()
{
unsigned int ctl0 = REFON + REF2_5V + ADC12ON + SHT0_15; // turn on 2.5V ref, set samp time=1024 cycles
unsigned int ctl1 = SHP; // Use sampling timer, internal ADC12OSC
unsigned char mctl0 = SREF_1 + INCH_11; // Channel A10, Vcc/2
unsigned long vcc = (unsigned long) getAnalogInput(ctl0, ctl1, mctl0);
unsigned long mult = vcc * 5000l;
return ((unsigned int)(mult / 4096l));
}
Hi, I had one doubt in the above mentioned code snippet for ADC10..If i use this code in Launchpad, it was resulting 2.1V..If i dont use the 2.5V voltage reference, then it results in Proper 3.6V. But if i theoretically calculate the same output with a formula given in the application report, then digital output value from the ADC10MEM register is totally different.
ReplyDeleteThe formula which i used for calculating the digital output is as follows.
N=1023*(Vin/Vref)...
Wherein the launchpad receives a voltage of 3.5V and i kept the Vref as 1.5V...
So the output goes like this : N=1023*(3.5/1.5)=2387, but if i read the value from registers as per the above program with 1.5Vref it shows 744.
Can you help me in understanding the process.