This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/MSP430FR5949: ADC12_B to Measure Battery Voltage - Unpredictable results

Part Number: MSP430FR5949
Other Parts Discussed in Thread: MSP-FET, MSP-EXP430FR5994

Tool/software: Code Composer Studio


I am trying to use the ADC12_B module to measure battery voltage on an MSP430FR5949 (running on a 3.3v supply).  I have used a TI adc sample program with the appropriate amendments to set the common reference to 2.0v, and to select channel 31 is input, with battery mapping enabled.  The sample program loops continuously so I inserted a printf statement to display successive values. 

With an input voltage of 3.3/2, ie 1.65v I expected to get a consistent reading of around (1.65 / 2.0) * 4096, that is around 3380 each time round.

Instead, I am getting wildly different values each time round, none of which are close to what I expected.  I attach below the sample program, and a portion of the output.  I am clearly doing something wrong so any help would be much appreciated.


Dick Laine

//  MSP430FR59xx Demo - ADC12, Sample A1
#include <msp430.h>
#include <stdio.h>
int main(void)
  WDTCTL = WDTPW | WDTHOLD;                 // Stop WDT
  // GPIO Setup
  P1OUT &= ~BIT0;                           // Clear LED to start
  P1DIR |= BIT0;                            // Set P1.0/LED to output
  P1SEL1 |= BIT1;                           // Configure P1.1 for ADC
  P1SEL0 |= BIT1;
  // Disable the GPIO power-on default high-impedance mode to activate
  // previously configured port settings

  while(REFCTL0 & REFGENBUSY);              // If ref generator busy, WAIT
  REFCTL0 |= REFVSEL_1 | REFON;             // Select internal ref = 2.0V
  while(!(REFCTL0 & REFGENRDY));
  // Configure ADC12
  ADC12CTL0 = ADC12SHT0_2 | ADC12ON;        // Sampling time, S&H=16, ADC12 on
  ADC12CTL1 = ADC12SHP;                     // Use sampling timer
  ADC12CTL2 |= ADC12RES_2;                  // 12-bit conversion results
  ADC12MCTL0 = ADC12INCH_31 | ADC12VRSEL_1; // A1 ADC input select; Vref=VREF=2.0
  ADC12IER0 |= ADC12IE0;                    // Enable ADC conv complete interrupt
  while (1)
    ADC12CTL0 |= ADC12ENC | ADC12SC;        // Start sampling/conversion
    __bis_SR_register(LPM0_bits | GIE);     // LPM0, ADC12_ISR will force exit
    __no_operation();                       // For debugger
    printf("ADC12MEM0 = %d \n",ADC12MEM0);
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector = ADC12_VECTOR
__interrupt void ADC12_ISR(void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(ADC12_VECTOR))) ADC12_ISR (void)
#error Compiler not supported!
  switch(__even_in_range(ADC12IV, ADC12IV_ADC12RDYIFG))
    case ADC12IV_NONE:        break;        // Vector  0:  No interrupt
    case ADC12IV_ADC12OVIFG:  break;        // Vector  2:  ADC12MEMx Overflow
    case ADC12IV_ADC12TOVIFG: break;        // Vector  4:  Conversion time overflow
    case ADC12IV_ADC12HIIFG:  break;        // Vector  6:  ADC12BHI
    case ADC12IV_ADC12LOIFG:  break;        // Vector  8:  ADC12BLO
    case ADC12IV_ADC12INIFG:  break;        // Vector 10:  ADC12BIN
    case ADC12IV_ADC12IFG0:                 // Vector 12:  ADC12MEM0 Interrupt
      if (ADC12MEM0 >= 0x7ff)               // ADC12MEM0 = A1 > 0.5AVcc?
        P1OUT |= BIT0;                      // P1.0 = 1
        P1OUT &= ~BIT0;                     // P1.0 = 0
      __bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
      break;                                // Clear CPUOFF bit from 0(SR)
    case ADC12IV_ADC12IFG1:   break;        // Vector 14:  ADC12MEM1
    case ADC12IV_ADC12IFG2:   break;        // Vector 16:  ADC12MEM2
    case ADC12IV_ADC12IFG3:   break;        // Vector 18:  ADC12MEM3
    case ADC12IV_ADC12IFG4:   break;        // Vector 20:  ADC12MEM4
    case ADC12IV_ADC12IFG5:   break;        // Vector 22:  ADC12MEM5
    case ADC12IV_ADC12IFG6:   break;        // Vector 24:  ADC12MEM6
    case ADC12IV_ADC12IFG7:   break;        // Vector 26:  ADC12MEM7
    case ADC12IV_ADC12IFG8:   break;        // Vector 28:  ADC12MEM8
    case ADC12IV_ADC12IFG9:   break;        // Vector 30:  ADC12MEM9
    case ADC12IV_ADC12IFG10:  break;        // Vector 32:  ADC12MEM10
    case ADC12IV_ADC12IFG11:  break;        // Vector 34:  ADC12MEM11
    case ADC12IV_ADC12IFG12:  break;        // Vector 36:  ADC12MEM12
    case ADC12IV_ADC12IFG13:  break;        // Vector 38:  ADC12MEM13
    case ADC12IV_ADC12IFG14:  break;        // Vector 40:  ADC12MEM14
    case ADC12IV_ADC12IFG15:  break;        // Vector 42:  ADC12MEM15
    case ADC12IV_ADC12IFG16:  break;        // Vector 44:  ADC12MEM16
    case ADC12IV_ADC12IFG17:  break;        // Vector 46:  ADC12MEM17
    case ADC12IV_ADC12IFG18:  break;        // Vector 48:  ADC12MEM18
    case ADC12IV_ADC12IFG19:  break;        // Vector 50:  ADC12MEM19
    case ADC12IV_ADC12IFG20:  break;        // Vector 52:  ADC12MEM20
    case ADC12IV_ADC12IFG21:  break;        // Vector 54:  ADC12MEM21
    case ADC12IV_ADC12IFG22:  break;        // Vector 56:  ADC12MEM22
    case ADC12IV_ADC12IFG23:  break;        // Vector 58:  ADC12MEM23
    case ADC12IV_ADC12IFG24:  break;        // Vector 60:  ADC12MEM24
    case ADC12IV_ADC12IFG25:  break;        // Vector 62:  ADC12MEM25
    case ADC12IV_ADC12IFG26:  break;        // Vector 64:  ADC12MEM26
    case ADC12IV_ADC12IFG27:  break;        // Vector 66:  ADC12MEM27
    case ADC12IV_ADC12IFG28:  break;        // Vector 68:  ADC12MEM28
    case ADC12IV_ADC12IFG29:  break;        // Vector 70:  ADC12MEM29
    case ADC12IV_ADC12IFG30:  break;        // Vector 72:  ADC12MEM30
    case ADC12IV_ADC12IFG31:  break;        // Vector 74:  ADC12MEM31
    case ADC12IV_ADC12RDYIFG: break;        // Vector 76:  ADC12RDY
    default: break;
generated console output:-
ADC12MEM0 = 2570
ADC12MEM0 = 2013
ADC12MEM0 = 2721
ADC12MEM0 = 2564
ADC12MEM0 = 3528
ADC12MEM0 = 2045
ADC12MEM0 = 2568
ADC12MEM0 = 2009
ADC12MEM0 = 2750
ADC12MEM0 = 2470
ADC12MEM0 = 3216
ADC12MEM0 = 3899
ADC12MEM0 = 2000
ADC12MEM0 = 2571
ADC12MEM0 = 2056
ADC12MEM0 = 2450
ADC12MEM0 = 3334
ADC12MEM0 = 2458
ADC12MEM0 = 2000


  • Hi Dick,

    would assume you selected a resistor divider to divide your voltage by 2 right and connect it to A1?

    What resistor values did you use? If the values are large you might have not considered the sampling timing as described in user guide:

    So please do the calculation and try following things:

    1. Reduce resistor values

    2. increase number of sample clocks ADC12SHTxx bits

    3. reduce ADC clock frequency by using a divider or a different clock source.

  • Hi Dietmar

    The MSP430FR5949 provides an internal (Vcc divided by two) source, (resistances not specified,) specifically for the purpose of measuring battery voltage,  That is what I am using.  I have to believe that the internal resistance values and circuitry are suitable for the purpose, so I don't think that can be the problem. 

    Like you, I thought it might be related to the sampling period, so I have actually tried using a low frequency 32KHz clock, instead of the 8MHz system clock, and stretching the sample period.  This gives exactly the same sort of wild variation in the results. 

    I have even tried doing a large number of observations and printing a running average.  When the running average stabilises, after a few hundred readings, it is still nowhere near what I would expect.   More to the point I have tried using Vcc as the measurement reference, measuring battery voltage against itself, which I would expect to be consistent close to 2048.  In that case it usually is close, but often with large variations.

    In truth, I suspect I am making a schoolboy error in setting up the control registers - one so obvious it is invisible!  I even tried a different chip, but with exactly the same results. 



  • Hi Dick,

    can you please not switch P1.1 to A1 function via the selection bits this input is not used right? And I'm not sure what you have connected to. So give it a try.

    Besides this where do you measure this? On a launchpad with supply from MSP-FET or is this a dedicated board with separate supply?

  • Hi Dietmar

    I am pretty sure that I have resolved the issue.

    I assembled a completely new target circuit board and, lo and behold, the ADC program worked exactly as expected.

    On the previous board all the other peripherals I used were working normally, but I can only assume that the ADC12_B had been damaged in some way - the board was in the oven three times during assembly and may have suffered some heat damage. However the ADC on the new board does work exactly as expected.  A little bit disconcerting that it appeared to execute without error, but then that is a lesson learnt by me.

    It's not very often one can attribute a problem to a faulty device.



  • Hi Dietmar

    Sorry, messages overlapped.

    I was not using A1 on by board - I just forgot to change the demo software comment.  I was using MEM0 with input channel 31 selected, and mapped to Vcc/2.

    My target board is my own design, with other peripherals, all programmed and controlled by the eZ-FET end of an MSP-EXP430FR5994 evaluation board with the original target FR5994 completely disconnected, and CCS10.

    Anyway, with the newly assembled board, I have things working as expected.  Thank you for your prompt response.