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: ADC12_B Sequence of channels - Repeated sampling

Part Number: MSP430FR6989

Hi,

Im a newbie to MSP430 Programming. Im currently working on MSP430FR6989 LaunchPad board. I would like to sample 3 ADC input channels repeatedly. After going through the Datasheet,User Guide and sample programs, i wrote the below code to sample analog inputs from A3(P1.3),A4(P8.7) and A5(P8.6).

My expected behaviour for the below code is The ADC12 should convert MEM0(no interrupt),MEM1(no interrupt) and MEM2(Generate Interrupt) where in the ADC ISR Routine i will copy the register contents from MEM0,1 and 2 to the global variables.By this way, the sequence of sampling and interrupt shall continue to occur. The problem i face here is, the interrupt is not generated when i set the value  ADC12IER0 |= ADC12IE2( i.e at end of seq ). Whereas when i change the value to  ADC12IER0 |= ADC12IE0, the interrupt is generated for MEM0 and channel A3 is alone sampled. Below is the code. Requesting your kind guidance here friends. Thank you in advance.

int main(void)
{
WDTCTL = WDTPW | WDTHOLD; // Stop WDT
P1SEL1 |= BIT3; // Configure P1.3 for ADC
P1SEL0 |= BIT3;
P8SEL1 |= BIT6; // Configure P8.6 for ADC
P8SEL0 |= BIT6;
P8SEL1 |= BIT7; // Configure P8.7 for ADC
P8SEL0 |= BIT7;
PM5CTL0 &= ~LOCKLPM5;


while(REFCTL0 & REFGENBUSY); 
REFCTL0 |= REFVSEL_3 | REFON;

// Configure ADC12
ADC12CTL0 = ADC12SHT0_2 | ADC12ON;
ADC12CTL1 = ADC12SHP| ADC12CONSEQ_2; 
ADC12CTL2 &= 0xCF; // 8-bit resolution

ADC12IER0 |= ADC12IE2; //Generate Interrupt for MEM2 ADC Data load

ADC12MCTL0 |= ADC12INCH_3; // A3 chan
ADC12MCTL0 |= ADC12VRSEL_1; //Vref = 2.5V

ADC12MCTL1 |= ADC12INCH_4;// A4 chan
ADC12MCTL1 |= ADC12VRSEL_1;//Vref = 2.5V

ADC12MCTL2 |= ADC12INCH_5+ADC12EOS;// A5 chan , End of Sequence
ADC12MCTL2 |= ADC12VRSEL_1;//Vref = 2.5V

while(1)
{
__delay_cycles(5000); // Delay between conversions
ADC12CTL0 |= ADC12ENC | ADC12SC; // Sampling and conversion start
__no_operation(); // For debug only
}
}

#pragma vector = ADC12_VECTOR
__interrupt void ADC12_ISR(void)
#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: break; // Vector 12: ADC12MEM0 Interrupt
case ADC12IV_ADC12IFG1: break; // Vector 14: ADC12MEM1
case ADC12IV_ADC12IFG2: // Vector 16: ADC12MEM2
ADCValue0 = ADC12MEM0;
ADCValue1 = ADC12MEM1;
ADCValue2 = ADC12MEM2; 
break; 
case ADC12IV_ADC12IFG3: break;
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
.........
}

  • Hi Arunkumar,

    First, for faster responses in the future, please use the code formatting tool (It looks like </> above). This makes code easier to read and you'll get more replies. I'll do this for you this time.

    It looks like you are using repeated single channel mode, try changing your code to set ADC12CONSEQ_3.

  • Hi Cameron P. LaFollette,
    Thanks for your reply. As you suggested i changed the code to ADC12CONSEQ_3(Repeat-sequence-of-channels) and tested in the launchpad, but even after changing, the ADC interrupt is not triggered and data is not converted and stored in MEM0,1,2 registers.
    One try which i gave was , When i load the ADC12IER0 register with ADC12IE0 , the interrupt gets triggered for MEM0 conversion alone and other channels were not getting converted.
    Kindly let me know the mistake im making here.

  • Hi Arunkumar,

    I tried your test with IE0, and it didn't fire, so I'm not sure how it is firing for you... I'd be curious to see your entire test code for this case.

    It looks like your Global interrupts aren't enabled.

    Try this, I tested it and it works. Make sure you are using the correct CONSEQx

    while(1)
    {
    __delay_cycles(5000); // Delay between conversions
    ADC12CTL0 |= ADC12ENC | ADC12SC; // Sampling and conversion start
    __bis_SR_register(GIE);     //
    __no_operation(); // For debug only
    }

  • Hello Cameron P. Lafollette,

    Sorry for the typo I made in the code which I posted at the beginning of this forum. I have missed the enable Global interrupts LOC in the code I posted. The code I'm testing on the Launchpad has this GIE LOC and that's why I could see interrupt being triggered for MEM0.

    After doing a wide search over the internet(Gone through a lot of ADC Sample codes) and going through the ADC12 registers again in the user guide, I figured it out and got to work for ADC12MEM0,ADC12MEM1 and ADC12MEM2.

    Now I'm able to get interrupts for each MEMx Registers data load. I made few updates in the ADC CTRL registers and below is the working code which I tested on my MSP430FR6989 Launchpad : 

    unsigned short ADCValue0=0;
    unsigned short ADCValue1=0;
    unsigned short ADCValue2=0;
    
    int main(void)
    
    {
    
     WDTCTL = WDTPW | WDTHOLD; // Stop WDT
    
     P1SEL1 |= BIT3; // Configure P1.3 for ADC
     P1SEL0 |= BIT3;
    
     P8SEL1 |= BIT6; // Configure P8.6 for ADC
     P8SEL0 |= BIT6;
    
     P8SEL1 |= BIT7; // Configure P8.7 for ADC
     P8SEL0 |= BIT7;
    
     PM5CTL0 &= ~LOCKLPM5;
    
    
     while(REFCTL0 & REFGENBUSY); 
    
     REFCTL0 |= REFVSEL_3 | REFON;
    
    
     // Configure ADC12
     ADC12CTL0 = ADC12SHT0_2 | ADC12MSC | ADC12ON;
     ADC12CTL1 = ADC12SHP| ADC12CONSEQ_1;
     ADC12CTL2 &= 0xCF; // 8-bit resolution
     ADC12IER0 |= ADC12IE0|ADC12IE1|ADC12IE2; //Generate Interrupt for MEM0,MEM1,MEM2 ADC New Data load
    
    
     ADC12MCTL0 = ADC12VRSEL_1 | ADC12INCH_3; //Analog Channel 3
     ADC12MCTL1 = ADC12VRSEL_1 | ADC12INCH_4; //Analog Channel 4
     ADC12MCTL2 = ADC12VRSEL_1 | ADC12INCH_5 + ADC12EOS; //Analog Channel 5, End of Sequence
    
     while(1)
     {
     __delay_cycles(5000); // Delay between conversions
    
     ADC12CTL0 |= ADC12ENC | ADC12SC; // Sampling and conversion start
     __bis_SR_register(LPM0_bits + GIE);
     __no_operation(); // For debug only
    
     }
    
     }
    
     #pragma vector = ADC12_VECTOR
     __interrupt void ADC12_ISR(void)
     {
    
      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
     {
       ADCValue0 = ADC12MEM0;
       __bic_SR_register_on_exit(LPM0_bits); // Exit active CPU
       break; // Clear CPUOFF bit from 0(SR)
     }
     case ADC12IV_ADC12IFG1: ADCValue1 = ADC12MEM1; break; // Vector 14: ADC12MEM1
     case ADC12IV_ADC12IFG2: ADCValue2 = ADC12MEM2; break; // Vector 16: ADC12MEM2
    
     default: break;
     }
     }

    
    

    If possible, Requesting you to please test the same and let me know the results from your end.

    Thanks for suggesting me your thoughts and inputs.

  • I see. I had assumed you omitted the MSC bit because you wanted a delay between channels. My mistake! :-)

    It still should have worked with out the MSC bit, but it would have need to traverse the while(1) 3 times.

**Attention** This is a public forum