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)); }