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.

MSP430FR6989: ADC problem

Part Number: MSP430FR6989

Tool/software:

Hello, 

I am using MSP430FR6989 development board. I set the pins which are P9.0 to P9.7 and I would like to get the values by using interrupt. I get the result between 700 and 890 even if I connect the pin GND and 3v3 voltage pin respectively while debugging. Nothing changes on any pin. I am sharing the test code here. I tried it by changing referans voltage like internal 1.2V or 2V but still did not get logical results. Any help will be appreciated.

Regards.

#include <msp430.h>
#include <stdint.h>

volatile uint16_t adc_values[8]; 
volatile uint8_t adc_index = 0;  

void led_config();
void led_on();
void led_off();


void main(void) {
    WDTCTL = WDTPW + WDTHOLD;
    PM5CTL0 &= ~LOCKLPM5;


    ADC12CTL0 = ADC12SHT0_3 | ADC12ON;
    ADC12CTL1 = ADC12SHP | ADC12CONSEQ_1;   
    ADC12CTL2 = ADC12RES_2; 
    ADC12MCTL0 |= ADC12INCH_0 | ADC12VRSEL_0; 
    ADC12MCTL1 |= ADC12INCH_1 | ADC12VRSEL_0; 
    ADC12MCTL2 |= ADC12INCH_2 | ADC12VRSEL_0; 
    ADC12MCTL3 |= ADC12INCH_3 | ADC12VRSEL_0; 
    ADC12MCTL4 |= ADC12INCH_4 | ADC12VRSEL_0; 
    ADC12MCTL5 |= ADC12INCH_5 | ADC12VRSEL_0;
    ADC12MCTL6 |= ADC12INCH_6 | ADC12VRSEL_0;
    ADC12MCTL7 |= ADC12INCH_7 | ADC12VRSEL_0; 

    P9SEL0 |= 0xFF;
    P9SEL1 |= 0xFF;

    ADC12IER0 |= ADC12IE0 | ADC12IE1 | ADC12IE2 | ADC12IE3 | ADC12IE4 | ADC12IE5 | ADC12IE6 | ADC12IE7 ;

    while(1) {

        ADC12CTL0 |= ADC12SC | ADC12ENC;   // ADC örnekleme ve dönüşümü başlat
        __delay_cycles(2000);
       __bis_SR_register(GIE);

    }
}




#pragma vector=ADC12_VECTOR
__interrupt void ADC_ISR(void) {
    switch(__even_in_range(ADC12IV, ADC12IV_ADC12RDYIFG))
    {
        case ADC12IV_ADC12IFG0:
            adc_values[0] = ADC12MEM0;
            break;
        case ADC12IV_ADC12IFG1:
            adc_values[1] = ADC12MEM1;
            break;
        case ADC12IV_ADC12IFG2:
            adc_values[2] = ADC12MEM2;
            break;
        case ADC12IV_ADC12IFG3:
            adc_values[3] = ADC12MEM3;
            break;
        case ADC12IV_ADC12IFG4:
            adc_values[4] = ADC12MEM4;
            break;
        case ADC12IV_ADC12IFG5:
            adc_values[5] = ADC12MEM5;
            break;
        case ADC12IV_ADC12IFG6:
            adc_values[6] = ADC12MEM6;
            break;
        case ADC12IV_ADC12IFG7:
            adc_values[7] = ADC12MEM7;
            break;

    }
}

  • How long did you run this before checking?

    1) With ADC12MSC=0, you'll only get one conversion per ADC12SC trigger.

    2) With ADC12MCTL7:ADC12EOS=0, it will cycle through all 32 channels before cycling back to ADC12MCTL0.

    3) The ADC12MEMn registers are Undefined after Reset; I routinely see them with random numbers then.

    I suspect you intended:

    >  ADC12CTL0 = ADC12SHT0_3 | ADC12ON | ADC12MSC;  // CONSEQ=1 in a burst

    and

    >  ADC12MCTL7 |= ADC12INCH_7 | ADC12VRSEL_0 | ADC12EOS; // Final channel of the burst

  • Hello,

    Thanks for the quick reply. I am not sure about how long the run time while debugging but I suppose that it was quite enough. I could not understand what do you mean by saying undefined ADC12MEMn register. Could you explain it more details? It would be better to refer it in code snippet.

    I reduced sampling time rate and I set the channel 7 as the last channel of conversion. I also added that ADC12MSC register for getting more conversion. I still get the same result. 

    You can check the updates below.

    Regards.

     

    #include <msp430.h>
    #include <stdint.h>
    
    volatile uint16_t adc_values[8]; 
    volatile uint8_t adc_index = 0;  
    
    void led_config();
    void led_on();
    void led_off();
    
    
    void main(void) {
        WDTCTL = WDTPW + WDTHOLD;
        PM5CTL0 &= ~LOCKLPM5;
    
    
        ADC12CTL0 = ADC12SHT0_2 | ADC12MSC | ADC12ON;
        ADC12CTL1 = ADC12SHP | ADC12CONSEQ_1;   
        ADC12CTL2 = ADC12RES_2;
        ADC12CTL3 = ADC12CSTARTADD_0;
        ADC12MCTL0 |= ADC12INCH_0 | ADC12VRSEL_0; 
        ADC12MCTL1 |= ADC12INCH_1 | ADC12VRSEL_0; 
        ADC12MCTL2 |= ADC12INCH_2 | ADC12VRSEL_0; 
        ADC12MCTL3 |= ADC12INCH_3 | ADC12VRSEL_0; 
        ADC12MCTL4 |= ADC12INCH_4 | ADC12VRSEL_0; 
        ADC12MCTL5 |= ADC12INCH_5 | ADC12VRSEL_0;
        ADC12MCTL6 |= ADC12INCH_6 | ADC12VRSEL_0;
        ADC12MCTL7 |= ADC12INCH_7 | ADC12VRSEL_0 | ADC12EOS; 
    
        P9SEL0 |= 0xFF;
        P9SEL1 |= 0xFF;
    
        ADC12IER0 |= ADC12IE0 | ADC12IE1 | ADC12IE2 | ADC12IE3 | ADC12IE4 | ADC12IE5 | ADC12IE6 | ADC12IE7 ;
        ADC12CTL0 |= ADC12ENC;
        
        while(1) {
    
            ADC12CTL0 |= ADC12SC | ADC12ENC;   // ADC örnekleme ve dönüşümü başlat
            __delay_cycles(2000);
           __bis_SR_register(GIE);
    
        }
    }
    
    
    
    
    #pragma vector=ADC12_VECTOR
    __interrupt void ADC_ISR(void) {
        switch(__even_in_range(ADC12IV, ADC12IV_ADC12RDYIFG))
        {
            case ADC12IV_ADC12IFG0:
                adc_values[0] = ADC12MEM0;
                break;
            case ADC12IV_ADC12IFG1:
                adc_values[1] = ADC12MEM1;
                break;
            case ADC12IV_ADC12IFG2:
                adc_values[2] = ADC12MEM2;
                break;
            case ADC12IV_ADC12IFG3:
                adc_values[3] = ADC12MEM3;
                break;
            case ADC12IV_ADC12IFG4:
                adc_values[4] = ADC12MEM4;
                break;
            case ADC12IV_ADC12IFG5:
                adc_values[5] = ADC12MEM5;
                break;
            case ADC12IV_ADC12IFG6:
                adc_values[6] = ADC12MEM6;
                break;
            case ADC12IV_ADC12IFG7:
                adc_values[7] = ADC12MEM7;
                break;
    
        }
    }

  • Using INCH_0 to INCH_7 selects A0 to A7. You set Port 9 to the ADC function but those pins connect to A8 to A15.

    Usually when I use an ADC interrupt, I enable only the interrupt for the last in sequence. The data will still be in the ADC12MEMx registers and it wastes less time on interrupt entry and exit.

    Ditch the delay_cycles, enable a low power mode, and exit the low power mode in the ISR. Much easier and you don't have to count cycles to make sure that 2,000 is enough for the ADC to convert 8 channels.

  • Hello,

    Thanks for the reply. I missed that port number thing. As you said, it connects to A8 to A15 and finally I was able to measure logical things. It works according to ADC12VRSEL_0 which is 3v3. However, I would like to measure 2V internal reference voltage. Here is my code. 

    Could you please share your knowledge about using internal voltage referance? 

    Thanks in advance.

    #include <msp430.h>
    #include <stdint.h>
    
    volatile uint16_t adc_values[8]; // ADC değerlerini saklayacak dizi
    volatile uint8_t adc_index = 0;  // ADC dizisi indeksi
    
    
    void main(void) {
    
        WDTCTL = WDTPW + WDTHOLD;
        PM5CTL0 &= ~LOCKLPM5;
    
        P9SEL0 |= 0xFF;
        P9SEL1 |= 0xFF;
    
    
        ADC12CTL0 = ADC12SHT0_2 | ADC12MSC | ADC12ON; 
        ADC12CTL1 = ADC12SHP | ADC12CONSEQ_1;                     
        ADC12CTL2 = ADC12RES_2; 
        ADC12CTL3 = ADC12CSTARTADD_0;
        ADC12MCTL0 |= ADC12INCH_8 ; // A1 ADC input select; Vref=AVCC
        ADC12MCTL1 |= ADC12INCH_9 ; // A1 ADC input select; Vref=AVCC
        ADC12MCTL2 |= ADC12INCH_10 ; // A1 ADC input select; Vref=AVCC
        ADC12MCTL3 |= ADC12INCH_11 ; // A1 ADC input select; Vref=AVCC
        ADC12MCTL4 |= ADC12INCH_12 ; // A1 ADC input select; Vref=AVCC
        ADC12MCTL5 |= ADC12INCH_13 ;// A1 ADC input select; Vref=AVCC
        ADC12MCTL6 |= ADC12INCH_14 ; // A1 ADC input select; Vref=AVCC
        ADC12MCTL7 |= ADC12INCH_15 | ADC12EOS; // A1 ADC input select; Vref=AVCC
    
    
        while(REFCTL0 &REFGENBUSY);
        REFCTL0 |= REFVSEL_1 | REFON;
        while(!(REFCTL0 &REFGENRDY));
    
        ADC12IER0 |= ADC12IE7;
        
        ADC12CTL0 |= ADC12ENC;
    
    
        while(1) {
            ADC12CTL0 |= ADC12SC | ADC12ENC;   // ADC örnekleme ve dönüşümü başlat
           __bis_SR_register(LPM0_bits | GIE);
    
        }
    }
    
    
    
    
    #pragma vector=ADC12_VECTOR
    __interrupt void ADC_ISR(void) {
        switch(__even_in_range(ADC12IV, ADC12IV_ADC12RDYIFG))
        {
    
            case ADC12IV_ADC12IFG7:
                adc_values[0] = ADC12MEM0;
                adc_values[1] = ADC12MEM1;
                adc_values[2] = ADC12MEM2;
                adc_values[3] = ADC12MEM3;
                adc_values[4] = ADC12MEM4;
                adc_values[5] = ADC12MEM5;
                adc_values[6] = ADC12MEM6;
                adc_values[7] = ADC12MEM7;
                __bic_SR_register_on_exit(LPM0_bits);
                break;
    
        }
    
    }
    
    
    

  • Hi,

    I have added the voltage referans selection and it worked. Here is the last version of code. 

    Thanks for helping.

    #include <msp430.h>
    #include <stdint.h>
    
    volatile uint16_t adc_values[8]; // ADC değerlerini saklayacak dizi
    volatile uint8_t adc_index = 0;  // ADC dizisi indeksi
    
    
    void main(void) {
    
        WDTCTL = WDTPW + WDTHOLD;
        PM5CTL0 &= ~LOCKLPM5;
    
        P9SEL0 |= 0xFF;
        P9SEL1 |= 0xFF;
    
    
        ADC12CTL0 = ADC12SHT0_2 | ADC12MSC | ADC12ON; 
        ADC12CTL1 = ADC12SHP | ADC12CONSEQ_1;                     
        ADC12CTL2 = ADC12RES_2; 
        ADC12CTL3 = ADC12CSTARTADD_0;
        ADC12MCTL0 |= ADC12INCH_8 | ADC12VRSEL_1 ; 
        ADC12MCTL1 |= ADC12INCH_9 | ADC12VRSEL_1; 
        ADC12MCTL2 |= ADC12INCH_10 | ADC12VRSEL_1 ; 
        ADC12MCTL3 |= ADC12INCH_11 | ADC12VRSEL_1 ;
        ADC12MCTL4 |= ADC12INCH_12 | ADC12VRSEL_1 ; 
        ADC12MCTL5 |= ADC12INCH_13 | ADC12VRSEL_1 ;
        ADC12MCTL6 |= ADC12INCH_14 | ADC12VRSEL_1 ;
        ADC12MCTL7 |= ADC12INCH_15 | ADC12VRSEL_1 | ADC12EOS; 
    
    
        while(REFCTL0 &REFGENBUSY);
        REFCTL0 |= REFVSEL_1 | REFON;
        while(!(REFCTL0 &REFGENRDY));
    
        ADC12IER0 |= ADC12IE7;
        
        ADC12CTL0 |= ADC12ENC;
    
    
        while(1) {
            ADC12CTL0 |= ADC12SC | ADC12ENC;   // ADC örnekleme ve dönüşümü başlat
           __bis_SR_register(LPM0_bits | GIE);
    
        }
    }
    
    
    
    
    #pragma vector=ADC12_VECTOR
    __interrupt void ADC_ISR(void) {
        switch(__even_in_range(ADC12IV, ADC12IV_ADC12RDYIFG))
        {
    
            case ADC12IV_ADC12IFG7:
                adc_values[0] = ADC12MEM0;
                adc_values[1] = ADC12MEM1;
                adc_values[2] = ADC12MEM2;
                adc_values[3] = ADC12MEM3;
                adc_values[4] = ADC12MEM4;
                adc_values[5] = ADC12MEM5;
                adc_values[6] = ADC12MEM6;
                adc_values[7] = ADC12MEM7;
                __bic_SR_register_on_exit(LPM0_bits);
                break;
    
        }
    
    }

**Attention** This is a public forum