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/MSP430FR6922: Battery monitoring with Battmap

Part Number: MSP430FR6922

Tool/software: Code Composer Studio

Hello,

I'm trying to monitor the AVCC/2 value on my MSP430FR6922 with the ADC12BATMAP bit. The ADC is always giving me 4095 as a result, with 2.0V or 2.5V for internal reference. 

Here is my init function for ADC12 : 

void ADC12_init(void)
{
    /* Select internal ref = 2.0V */
    while (Ref_A_isRefGenBusy(ADC12_B_BASE)) ;
    Ref_A_setReferenceVoltage(ADC12_B_BASE, REF_A_VREF2_5V);

    ADC12_B_configureMemoryParam configureMemoryParam = {0};
    configureMemoryParam.memoryBufferControlIndex = ADC12_B_MEMORY_0;
    configureMemoryParam.inputSourceSelect = ADC12_B_INPUT_BATMAP;
    configureMemoryParam.refVoltageSourceSelect = ADC12_B_VREFPOS_INTBUF_VREFNEG_VSS;
    configureMemoryParam.endOfSequence = ADC12_B_ENDOFSEQUENCE;
    configureMemoryParam.windowComparatorSelect = ADC12_B_WINDOW_COMPARATOR_DISABLE;
    configureMemoryParam.differentialModeSelect = ADC12_B_DIFFERENTIAL_MODE_DISABLE;

    ADC12_B_initParam initParam = {0};

    initParam.sampleHoldSignalSourceSelect = ADC12_B_SAMPLEHOLDSOURCE_SC;
    initParam.clockSourceSelect = ADC12_B_CLOCKSOURCE_ADC12OSC;
    initParam.clockSourceDivider = ADC12_B_CLOCKDIVIDER_1;
    initParam.clockSourcePredivider = ADC12_B_CLOCKPREDIVIDER__1;
    initParam.internalChannelMap = ADC12_B_BATTMAP;

    /* Turn on Reference Voltage */
    Ref_A_enableReferenceVoltage(ADC12_B_BASE);

    /* Enable memory buffer */
    ADC12_B_configureMemory(ADC12_B_BASE, &configureMemoryParam);

    /* Enable the ADC12B module */
    ADC12_B_init(ADC12_B_BASE, &initParam);
    ADC12_B_enable(ADC12_B_BASE);

    //Enable memory buffer 0 interrupt
    ADC12_B_clearInterrupt(ADC12_B_BASE, 0, ADC12_B_IFG0);
    ADC12_B_enableInterrupt(ADC12_B_BASE, ADC12_B_IE0, 0, 0);

    ADC12_B_setupSamplingTimer(ADC12_B_BASE,
                               ADC12_B_CYCLEHOLD_16_CYCLES,
                               ADC12_B_CYCLEHOLD_16_CYCLES,
                               ADC12_B_MULTIPLESAMPLESDISABLE);
}

And here the call :

    /* Start ADC */
    ADC12_init();

#if(1)
    __enable_interrupt();

    while(1)
    {
        __delay_cycles(10000);

        ADC12_B_clearInterrupt(ADC12_B_BASE, 0, ADC12_B_IFG0);
        ADC12_B_startConversion(ADC12_B_BASE, ADC12_B_MEMORY_0, ADC12_B_SINGLECHANNEL);

        __bis_SR_register(LPM0_bits + GIE);
        __no_operation();
    }
#endif

I use the breakpoint inside the interrupt : 

#pragma vector=ADC12_VECTOR
__interrupt void ADC12_ISR(void)
{
    volatile uint16 ADC = ADC12_B_getResults(ADC12_B_BASE, ADC12_B_MEMORY_0); 

    __no_operation();
    __bic_SR_register_on_exit(LPM0_bits);
}

Thanks in advance !

  • Hi Pittet

    You can refer to this demo code that I have test is worked

    msp430fr6x7x_adc12_battery.c
    //******************************************************************************
    
    //
    //                MSP430FR6972
    //             ------------------------------
    //         /|\|                          XIN|-
    //          | |                             |
    //          --|RST                      XOUT|-
    //            |                             |
    //            |Internal battery/A31     P1.0|-->LED
    //
    //   Andreas Dannenberg
    //   Texas Instruments Inc.
    //   September 2014
    //   Built with IAR Embedded Workbench V5.60 & Code Composer Studio V6.0
    //******************************************************************************
    #include <msp430.h>
    unsigned short adc_result;
    int main(void)
    {
      WDTCTL = WDTPW | WDTHOLD;                 // Stop WDT
    
      // GPIO Setup
      P1OUT &= ~BIT0;                           // Clear LED to start
      P1DIR |= BIT0;                            // P1.0 output
    
    
      // Disable the GPIO power-on default high-impedance mode to activate
      // previously configured port settings
      PM5CTL0 &= ~LOCKLPM5;
    
      // By default, REFMSTR=1 => REFCTL is used to configure the internal reference
      while(REFCTL0 & REFGENBUSY);              // If ref generator busy, WAIT
      REFCTL0 |= REFVSEL_2 | REFON;             // Select internal ref = 1.2V
                                                // Internal Reference ON
    
      // Configure ADC12
      ADC12CTL0 = ADC12SHT0_2 | ADC12ON;
      ADC12CTL1 = ADC12SHP;                     // ADCCLK = MODOSC; sampling timer
      ADC12CTL2 |= ADC12RES_2;                  // 12-bit conversion results
      ADC12CTL3|= ADC12BATMAP;
      ADC12IER0 |= ADC12IE0;                    // Enable ADC conv complete interrupt
      ADC12MCTL0 |= ADC12INCH_31 | ADC12VRSEL_1; // A1 ADC input select; Vref=V
    
      while(!(REFCTL0 & REFGENRDY));            // Wait for reference generator
                                                // to settle
    
      while(1)
      {
        __delay_cycles(5000);                    // Delay between conversions
        ADC12CTL0 |= ADC12ENC | ADC12SC;         // Sampling and conversion start
    
        __bis_SR_register(LPM0_bits + GIE);      // LPM0, ADC10_ISR will force exit
        __no_operation();                        // For debug only
      }
    }
    
    #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)
    #else
    #error Compiler not supported!
    #endif
    {
      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
            adc_result=ADC12MEM0;
    
          if (adc_result >= 0x6B4)               // ADC12MEM = A1 > 0.5V?
            P1OUT |= BIT0;                      // P1.0 = 1
          else
            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;
      }
    }
    

  • Thank you for your code ! With it I manage to find that there is a problem with the internal reference. I don't know why the two functions from adc12_b.c does not work. Here is the final code: 

    /* Select internal ref = 2.0V */
        while (Ref_A_isRefGenBusy(ADC12_B_BASE)) ;
        REFCTL0 |= REFVSEL_1 | REFON;
    
        /* Select internal ref = 2.0V - does not work */
        //while (Ref_A_isRefGenBusy(ADC12_B_BASE)) ;
        //Ref_A_setReferenceVoltage(ADC12_B_BASE, REF_A_VREF2_0V);
        //Ref_A_enableReferenceVoltage(ADC12_B_BASE);
    
        ADC12_B_configureMemoryParam configureMemoryParam = {0};
        configureMemoryParam.memoryBufferControlIndex = ADC12_B_MEMORY_0;
        configureMemoryParam.inputSourceSelect = ADC12_B_INPUT_BATMAP;
        configureMemoryParam.refVoltageSourceSelect = ADC12_B_VREFPOS_INTBUF_VREFNEG_VSS;
        configureMemoryParam.endOfSequence = ADC12_B_NOTENDOFSEQUENCE;
        configureMemoryParam.windowComparatorSelect = ADC12_B_WINDOW_COMPARATOR_DISABLE;
        configureMemoryParam.differentialModeSelect = ADC12_B_DIFFERENTIAL_MODE_DISABLE;
    
        ADC12_B_initParam initParam = {0};
        initParam.sampleHoldSignalSourceSelect = ADC12_B_SAMPLEHOLDSOURCE_SC;
        initParam.clockSourceSelect = ADC12_B_CLOCKSOURCE_ADC12OSC;
        initParam.clockSourceDivider = ADC12_B_CLOCKDIVIDER_1;
        initParam.clockSourcePredivider = ADC12_B_CLOCKPREDIVIDER__1;
        initParam.internalChannelMap = ADC12_B_BATTMAP;
    
        /* Enable the ADC12B module */
        ADC12_B_init(ADC12_B_BASE, &initParam);
        ADC12_B_enable(ADC12_B_BASE);
    
        /* Configure sampling timer */
        ADC12_B_setupSamplingTimer(ADC12_B_BASE,
                                   ADC12_B_CYCLEHOLD_16_CYCLES,
                                   ADC12_B_CYCLEHOLD_16_CYCLES,
                                   ADC12_B_MULTIPLESAMPLESDISABLE);
    
        //Enable memory buffer 0 interrupt
        ADC12_B_clearInterrupt(ADC12_B_BASE, 0, ADC12_B_IFG0);
        ADC12_B_enableInterrupt(ADC12_B_BASE, ADC12_B_IE0, 0, 0);
    
        /* Enable memory buffer */
        ADC12_B_configureMemory(ADC12_B_BASE, &configureMemoryParam);
    
        while(!(REFCTL0 & REFGENRDY));            // Wait for reference generator

  • Does the code I send to you is work? If it works you can take that as reference. I am not recommend you to use the driver lib that will cost more memory size and not easy to read and debug. You can just use the register level demo that I have send to you.

**Attention** This is a public forum