Code Recipe: Reading MSP430 power supply voltage level

While playing with solar cells and MSP430 Launchpad I needed to check if MCU’s power supply level is high enough to switch to higher clock speed and do some power-hungry stuff. As MSP430G2553 comes with built-in 10-bit analog-to-digital converter and precise 1.5V and 2.5V internal voltage references, the task was quite easy.

My specific power source (solar cell + 0.47F supercap + 3.3V LDO) provides rather wide range of voltages – from 0V to ~3.25V. The MSP microcontroller starts from about 1.8V. To measure the whole range, I had to use both voltage references: 1.5V for voltages lower than 3V and 2.5V for voltages higher (or equal) than 3V. Sort of a dual range voltage meter 😉

This C function reads and returns Vcc level in millivolts.
UPDATE: To properly power down ADC after measurement, ENC flag must be cleared before clearing ADC10ON. Code updated 🙂

uint16_t Msp430_GetSupplyVoltage(void)
{
	uint16_t raw_value;
	// first attempt - measure Vcc/2 with 1.5V reference (Vcc < 3V )
	ADC10CTL0 = SREF_1 | REFON | ADC10SHT_2 | ADC10SR | ADC10ON;
	ADC10CTL1 = INCH_11 | SHS_0 | ADC10DIV_0 | ADC10SSEL_0;
	// start conversion and wait for it
	ADC10CTL0 |= ENC | ADC10SC;
	while (ADC10CTL1 & ADC10BUSY) ;
	// stop conversion and turn off ADC
	ADC10CTL0 &= ~ENC;
	ADC10CTL0 &= ~(ADC10IFG | ADC10ON | REFON);
	raw_value = ADC10MEM;
	// check for overflow
	if (raw_value == 0x3ff) {
		// switch range - use 2.5V reference (Vcc >= 3V)
		ADC10CTL0 = SREF_1 | REF2_5V | REFON | ADC10SHT_2 | ADC10SR | ADC10ON;
		// start conversion and wait for it
		ADC10CTL0 |= ENC | ADC10SC;
		while (ADC10CTL1 & ADC10BUSY) ;
		raw_value = ADC10MEM;
		// end conversion and turn off ADC
		ADC10CTL0 &= ~ENC;
		ADC10CTL0 &= ~(ADC10IFG | ADC10ON | REFON);
		// convert value to mV
		return ((uint32_t)raw_value * 5000) / 1024;
	} else
		return ((uint32_t)raw_value * 3000) / 1024;
}

3 thoughts on “Code Recipe: Reading MSP430 power supply voltage level

  1. Robert Moore

    Great post, and thanks for making it so easy to read. We’re using the MSP430 to build low-energy wireless sensors and we’re now using your code to evaluate the remaining battery capacity.

    Reply
  2. Adam Reynolds

    You mentioned that the MSP starts up at about 1.8v, yet the datasheet says that the internal 1.5v regulator requires a minimum Vcc of 2.2v. How does this routine behave when 1.8<Vcc<2.2?

    Reply
  3. Hal Sampson

    Below the 2.2V required for the 1.5V reference, the temperature diode seems to behave OK as a very rough reference (allow lots of margin):

    const int NomTemp = 25; // °C
    const float Vtemp = 0.00355 * NomTemp + 0.986; // BEWARE large unit-to-unit offset !!
    #define TEMP_COUNTS(Vcc) ((int)(1024 * Vtemp / (Vcc))) // INCH_10 // higher with lower Vcc

    int readTempDiode() {
    ADC10CTL0 &= ~ENC;
    ADC10CTL0 = SREF_0 | ADC10SHT_3 | REFBURST | ADC10ON;
    ADC10CTL1 = INCH_10 | ADC10DIV_1 | ADC10SSEL_0; // measure temperature diode vs. Vcc
    ADC10CTL0 |= ENC | ADC10SC;
    while (!(ADC10CTL0 & ADC10IFG));
    return ADC10MEM;
    }

    while (readTempDiode() > TEMP_COUNTS(2.4)); // wait for Vcc to reach 2.2V

    Reply

Leave a Reply to Hal Sampson Cancel reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.