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.

MSP430F5638: ADC12_A - how do you set ADC12IV?

Part Number: MSP430F5638

Using CCSv10, downloaded four ADC examples for the 5529 Launch Pad and they (ADC_01, ADC_06, ADC_07, ADC_10) are all working fine on the LP.

Copied ADC_06 and modified it for my custom SBC using the 5638. I'm using MEM10, 11, 12, and 13, converted sequentially, and want to service the interrupt from MEM13.

I can't get it to set ADC12IV to case 32 by setting ADC12IE. If I set ADC12IE = 0x001F it matches case 6 and runs code under it (toggling bit P8.4). But I want it to match case 32 and process the data from these channels. There doesn't seem to be a logical relationship between what ADC12IE is set to, and ADC12IV's value.

What am I missing?

  • Are you actually using MEM10-13, or (only) INCH_10-13? 

    If the former: Did you also set ADC12CSTARTADD=10 to start at MEM10? The fact that it interrupts on MEM0 suggests you didn't.

    If the latter: The IEn number is tied to the MCTLn number, not the INCH_m number. If all you changed was the INCH constants, you're still using MCTL0-3. MCTL3  uses ADC12IE3=0x08 (ADC12IV=0x0C) as in the original example.

  • Thanks Bruce,

    That was the problem, it is now running fine. But I can't leave the ISR, it just keeps looping even with an explicit return or break in the index counter test.

  • This could be an illusion. main is written to sit in LPM and never wake up, so the only activity is in the ISR. You're using CONSEQ=3 and MSC=1, so the conversions run continuously (forever).

    Using MEM0-3 with SHT0=8 (256 ADCCLKs) you would get a new batch roughly every 4/(5MHz/256)= ~200 usec, which is already pretty fast if you're trying to observe it with the debugger.

    If you switched to MEM10-13  and didn't set SHT1=8 (i.e. left SHT1=0), that would be quite a bit more frequent: 4/((5MHz/4)= ~3usec. With MCLK=1MHz, the ISR would never exit.

    It might be useful for you to post your code so we're not guessing so much. (Don't forget the Code Tags ("</>" button in the Reply box).)

  • Thanks for input. Converted code to use mode 01 single sequence of channels which is working. I need to sample 4 channels, but I want to do over-sampling and average values. So tried to call ISR in a loop but it only does the first pass through the loop and captures the first set of 4 channels successfully. See code.

    // adc12-02.c
    // this file uses mode 01 single sequence of channels
    // adc conversion sequence mode set in ADC12CTL1 - ADC12CONSEQx - bits 2-1
    
    #include <msp430.h>
    
    #define MAX_CHANNELS 4      // number of ADC channels to be converted
    #define MAX_COUNT   2       // number of ADC conversions to be over-sampled and averaged
    
    // 2D array of 10 rows of 4 channel conversions per loop
    // ISR works with consecutive channels, has to be in this 2D order
    // each ISR run processes the 4 channels
    volatile unsigned int ADC_results[MAX_COUNT][MAX_CHANNELS];
    volatile unsigned int i;
    
    int main(void)
    {
        WDTCTL = WDTPW+WDTHOLD;                   // Stop watchdog timer
    
        P7SEL |= BIT4 + BIT5;
    
        // I'm toggling a bit to view with scope
        P8OUT = 0x00;
        P8DIR |= 0x10;                            // P8.4 output on SPI1 pin 1, to toggle
    
        ADC12CTL0 = ADC12ON + ADC12MSC + ADC12SHT1_8;
        //     1111 11
        // msb 5432 1098 7654 3210 lsb
        //     0000 0000 0001 0000 = 0x0010     ADC12ON turn ADC12 on
        //     0000 0000 1000 0000 = 0x0080     ADC12MSC enable multiple sample conversion
        //     1000 0000 0000 0000 = 0x8000     ADC12SHT1_8 extended sample time to avoid overflow (8*0x1000u) = 8000, use SHT1x for MEM8-MEM15
        //     ----------------------------
        //     1000 0000 1001 0000 = 0x8090     Total = ADC12CTL0 bit setting
    
        ADC12CTL1 = ADC12SHP + ADC12CONSEQ_1 + ADC12CSTARTADD_10;
        //     1111 11
        // msb 5432 1098 7654 3210 lsb
        //     0000 0010 0000 0000 = 0x0200     ADC12SHP sample & hold pulse mode = 16 clock cycles for both ADC12MEM8 to 15 and 0 to 7
        //     0000 0000 0000 0010 = 0x0002     ADC12CONSEQ_1 conversion sequence select: 1  (1*2u) = 2
        //     1010 0000 0000 0000 = 0xA000     ADC12CSTARTADD_10 set conversion start address = 1010b = Ah = ADC12MEM10
        //     ----------------------------
        //     1010 0010 0000 0010 = 0xA202   Total = ADC12CTL1 bit setting
    
        // set ADC12MCTLx memory control = ADC12INCH_xx input channel
        // ADC12EOS sets end of sequential channel conversions, set on last channel
        // ref+ = Avcc by default, ref- = Avss by default
        ADC12MCTL10 = ADC12INCH_10;               // ref+=AVcc, channel = A10
        ADC12MCTL11 = ADC12INCH_11;               // ref+=AVcc, channel = A11
        ADC12MCTL12 = ADC12INCH_12;               // ref+=AVcc, channel = A12
        ADC12MCTL13 = ADC12INCH_13 + ADC12EOS;    // ref+=AVcc, channel = A13, end seq.
    
        ADC12IE = 0x2000;                         // ADC12IV = 32d = 20h, for MEM13
        //     1111 11
        // msb 5432 1098 7654 3210 lsb
        //     0010 0000 0000 0000 = 0x2000     enable interrupt ADC12IFG13
    
        ADC12CTL0 |= ADC12ENC;                    // Enable conversions
        ADC12CTL0 |= ADC12SC;                     // Start conversion - software trigger
    
        // loop and run ISR MAX_COUNT times
        for(i=0; i < MAX_COUNT; i++)
        {
            // tested with both LPM0 and LPM4_bits
            __bis_SR_register(LPM4_bits + GIE);       // Enter LPM0, Enable interrupts
            __no_operation();                         // For debugger
        }
    }
    
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=ADC12_VECTOR
    __interrupt void ADC12ISR (void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(ADC12_VECTOR))) ADC12ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      // dissect ADC12IV and process single, correct interrupt vector, use last channel for a sequence
      // 2nd arg is the range, which is case value in decimal
      // case uses decimal, interrupt vector uses hex
      // example only went to case 34 for ADC12IFG14, corrected here
      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: break;                           // Vector  6:  ADC12IFG0
      case  8: break;                           // Vector  8:  ADC12IFG1
      case 10: break;                           // Vector 10:  ADC12IFG2
      case 12: break;                           // Vector 12:  ADC12IFG3
      case 14: break;                           // Vector 14:  ADC12IFG4
      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:                                  // Vector 32:  ADC12IFG13 - use interrupt case for last channel in sequence
          ADC_results[i][0] = ADC12MEM10;       // Move A10 results, IFG is cleared
          ADC_results[i][1] = ADC12MEM11;       // Move A11 results, IFG is cleared
          ADC_results[i][2] = ADC12MEM12;       // Move A12 results, IFG is cleared
          ADC_results[i][3] = ADC12MEM13;       // Move A13 results, IFG is cleared
    
          // code to toggle a bit based on voltage
          if (ADC12MEM11 >= 0x00F)              // ADC12MEM = A11 > 0.5AVcc? = 1.65V Decimal counts = 2048
             P8OUT |= BIT4;                     // P8.4 = 1
           else
             P8OUT &= ~BIT4;                    // P8.4 = 0
    
          __bic_SR_register_on_exit(LPM4_bits);   // Exit active CPU, SET BREAKPOINT HERE
          break;
      case 34: break;                           // Vector 34:  ADC12IFG14
      case 36: break;                           // Vector 36:  ADC12IFG15
      default: break;
      }
    }
    

  • I'm glad you got it working.

    I can't tell whether there's a question in here. If you move the "ADC12CTL0 |= ADC12SC;" inside your for-loop (before the LPM line) I expect you'll fill all your rows.

  • It's working, had to clear it also, thanks

**Attention** This is a public forum