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.

MSP430 ADC12 multiple channel conversion

Other Parts Discussed in Thread: MSP430F5528

Hi,

I am currently using an MSP430F5528. I have 2 ADCs enabled and I am trying to read both at the same time. The problem is that I need to send 2 requests to get the ADC values. I believe that the interrupt does not get called. Do you have any ideas why this might be?

Here is the code to initialize the ADC

void ADC_Init(void)
{
 
  P6SEL = 0x11;                             // Enable A/D channel inputs
  ADC12CTL0 = ADC12ON+ADC12MSC+ADC12SHT0_8; // Turn on ADC12, set sampling time
  ADC12CTL1 = ADC12SHP+ADC12CONSEQ_1;       // Use sampling timer, single sequence
  ADC12MCTL0 = ADC12INCH_0+ADC12SREF_1;                 // ref+=AVcc, channel = A0
  ADC12MCTL4 = ADC12INCH_4+ADC12SREF_1+ADC12EOS;        // ref+=AVcc, channel = A3, end seq.
  ADC12IE = 0x10;                           // Enable ADC12IFG.3
  ADC12CTL0 |= ADC12ENC;                    // Enable conversions
 
}

The ISR is:

#pragma vector = ADC12_VECTOR
__interrupt void ADC12_ISR(void)
{
 
  switch(__even_in_range(ADC12IV,34))
  {
 
  case  0: break;                           // Vector  0:  No interrupt
  case  2: break;                           // Vector  2:  ADC overflow
  case  4: break;                           // Vector  4:  ADC timing overflow
  case  6:                                  // Vector  6:  ADC12IFG0
  //ADC_Result1 = ADC12MEM0;             //store the temperature
  //      ADC_done_flag=1;                                              
             break;     
  case  8: break;                           // Vector  8:  ADC12IFG1
  case 10: break;                           // Vector 10:  ADC12IFG2
  case 12: break;                           // Vector 12:  ADC12IFG3
  case 14:                            // Vector 14:  ADC12IFG4
  ADC_Result1 = ADC12MEM0;             //store the temperature
  ADC_Result2 = ADC12MEM4;             //store the temperature
        ADC_done_flag=1;                                              
             break; 
 
 
  case 16: break;                           // Vector 16:  ADC12IFG5
  case 18: break;                           // Vector 18:  ADC12IFG6
  case 20: break;                           // Vector 20:  ADC12IFG7
  case 22: break;                           // Vector 22:  ADC12IFG8
  case 24: break;                           // Vector 24:  ADC12IFG9
  case 26: break;                           // Vector 26:  ADC12IFG10
  case 28: break;                           // Vector 28:  ADC12IFG11
  case 30: break;                           // Vector 30:  ADC12IFG12
  case 32: break;                           // Vector 32:  ADC12IFG13
  case 34: break;                           // Vector 34:  ADC12IFG14
  default: break;
  }
}

 

and I start the conversion by doing:  

ADC12CTL0 |= ADC12SC;        // Sampling and conversion start

 

One fix is to call the conversion two times one right after another, but I want to know if I am doing something wrong. (when I had only one enabled it worked fine)

Thank you.

Alin

  • Alin Dosa said:
    ADC12MCTL0 = ADC12INCH_0+ADC12SREF_1;                 // ref+=AVcc, channel = A0
      ADC12MCTL4 = ADC12INCH_4+ADC12SREF_1+ADC12EOS;        // ref+=AVcc, channel = A3, end seq.

    What about 1,2 and 3? The ADC12 works a sequence as if the MCTL registers were a script. It first converts based on MCTL0, then MCTL1, then MCTL2 until it hits the EOS bit. (which might even be set after a reset for one fo the MCTLs you skipped in the setup)

    There is no need to configure ADC12MCTL4 for channel 4 nd 0 for channel 0.

    The MCTLs can use any input channel. So you can configure MCTL0 for channel 0 and MCTL1 for channel 4 (or even mutiple MCTLs for the same channel, if you want)

    Alin Dosa said:
      ADC12IE = 0x10;                           // Enable ADC12IFG.3

    It's ADC12IFG.4. However, I gues that's what you wanted anyway.

    Another thin I nothiced: you use ADC12SREF_1, but you don't enable the reference anywhere. Won't work. Use ADC12SREF_0 to compare against VCC or enable the internal reference.

     

  • I am setting the reference previously in the code:

    REFCTL0 |= REFON+REFVSEL_1;                   // Set 2.0V reference for ADC

     

    I have changed my ADC init function based on your recommendation (and of course then interrupt service routine), and I still get the same behavior (I need to send conversion start twice)

    void ADC_Init(void)
    {
     
      P6SEL = 0x11;                             // Enable A/D channel inputs
      ADC12CTL0 = ADC12ON+ADC12MSC+ADC12SHT0_8; // Turn on ADC12, set sampling time
      ADC12CTL1 = ADC12SHP+ADC12CONSEQ_1;       // Use sampling timer, single sequence
      ADC12MCTL0 = ADC12INCH_0+ADC12SREF_1;                 // ref+=AVcc, channel = A0

      ADC12MCTL1 = ADC12INCH_4+ADC12SREF_1+ADC12EOS;        // ref+=AVcc, channel = A3, end seq.
      ADC12IE = 0x2;                           // Enable ADC12IFG.2
      ADC12CTL0 |= ADC12ENC;                    // Enable conversions
     
    }

    #pragma vector = ADC12_VECTOR
    __interrupt void ADC12_ISR(void)
    {
     
      switch(__even_in_range(ADC12IV,34))
      {
     
      case  0: break;                           // Vector  0:  No interrupt
      case  2: break;                           // Vector  2:  ADC overflow
      case  4: break;                           // Vector  4:  ADC timing overflow
      case  6:                                  // Vector  6:  ADC12IFG0
      //ADC_Result1 = ADC12MEM0;             //store the temperature
      //      ADC_done_flag=1;                                              
                 break;     
      case  8:                            // Vector  8:  ADC12IFG1
          ADC_Result1 = ADC12MEM0;             //store the temperature
          ADC_Result2 = ADC12MEM1;             //store the temperature
            ADC_done_flag=1;                                              
                 break; 
      case 10: break;                           // Vector 10:  ADC12IFG2
      case 12: break;                           // Vector 12:  ADC12IFG3
      case 14:                            // Vector 14:  ADC12IFG4
                                                
                 break; 
     
     
      case 16: break;                           // Vector 16:  ADC12IFG5
      case 18: break;                           // Vector 18:  ADC12IFG6
      case 20: break;                           // Vector 20:  ADC12IFG7
      case 22: break;                           // Vector 22:  ADC12IFG8
      case 24: break;                           // Vector 24:  ADC12IFG9
      case 26: break;                           // Vector 26:  ADC12IFG10
      case 28: break;                           // Vector 28:  ADC12IFG11
      case 30: break;                           // Vector 30:  ADC12IFG12
      case 32: break;                           // Vector 32:  ADC12IFG13
      case 34: break;                           // Vector 34:  ADC12IFG14
      default: break;
      }
    }

    Any other thoughts?

  • Alin Dosa said:
    I am setting the reference previously in the code:

    Okay. I cannot know what you don't post :) A buggy program is like an elephant. You know the joke about the blind men describing an elephant? One was touching the nose ad said "it's a snake", the other was touching the foot and said 'No, it's a tree' while the third was holding the tail and said "you're both wrong, it's a rope".

    Alin Dosa said:
    ADC12IE = 0x2;                           // Enable ADC12IFG.2


    Isn't it ADC12IFG.1? Actually it doesn't enable ADC12IGGx. Those bits are set independently of the IE bit. The IE bit just enables triggering of the ISR (if  the IE bit isn't set, it isn't put into to ADC12IV at all)
    Anyway, 0x2 is what you want. You can also use ADC12IE1, which is more clear.

    However, I don't see what's wrong with your code.
    My own ADC12 init code is similar except one thing: I first set ADC12ON in a separate statement, then I set ADC12MSC and the rest. Maybe the ADC12MSC bit isn't set if you don't enable ADC12ON before (and not at the same time).

     

**Attention** This is a public forum