ADC interrupt related problems on MSP430

Disclaimer: This article is a blogger original article, shall not be reproduced without the bloggers allowed. https://blog.csdn.net/LZPRO/article/details/78319755
MSP430ADC time during the operation of the relevant code, a percentage encountered problems baffled, we set up in accordance with the requirements of the ADC channels, ADC interrupt, the program has never been able to go into the ADC interrupt, I once again confirm the channel selection for errors interrupt is set, but still can not enter break, after testing and searching, finally found the problem.

Although the MSP430 ADC12IE register is used to enable each ADC interrupt, but in single channel mode conversion, whether you are using the ADC channels which, ADC12IE corresponding interrupt can only be 0x01, the corresponding interrupt flag is ADC12IFG0, and ADC values ​​can only be read in ADC12MEM0 in. The following example is given of a single-channel conversion:


#include "msp430x54x.h"

unsigned int adc;

void main(void)
{
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
  ADC12CTL0 = ADC12SHT02 + ADC12ON;         // Sampling time, ADC12 on
  ADC12CTL1 = ADC12SHP;                     // Use sampling timer
  ADC12IE = 0x01;                           // Enable interrupt
  ADC12MCTL0 |= ADC12INCH_4;
  __delay_cycles(100);
  ADC12CTL0 |= ADC12ENC;
  P6SEL |= 0x10;                            // P6.4 ADC option select

  while (1)
  {
    ADC12CTL0 |= ADC12SC;                   // Start sampling/conversion 
    __bis_SR_register(LPM0_bits + GIE);     // LPM0, ADC12_ISR will force exit
    __no_operation();                       // For debugger
  }
}

#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 = ADC12MEM0;                        // Read ADC12MEM 
    __bic_SR_register_on_exit(LPM0_bits);   // Exit active CPU
    break;
  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: break;                           // Vector 32:  ADC12IFG13
  case 34: break;                           // Vector 34:  ADC12IFG14
  default: break; 
  }
}

In the above case, we are using the MSP430 pin P6.4, the ADC channel 4, since the single-channel single conversion mode, the corresponding interrupt is ADC12IFG0, the corresponding value in the reading ADC12MEM0, for single multiple channel conversion mode also applies.

For the sequence of channel switching mode, the value depends on the ADC channels ADC12IE used, the value from the ADC ADC also the corresponding channel read 12MEM, the following is an example of a sequence of channel CPA

#include "msp430x54x.h"

volatile unsigned int results[4];           // Needs to be global in this example
                                            // Otherwise, the compiler removes it
                                            // because it is not used for anything.

void main(void)
{
  WDTCTL = WDTPW+WDTHOLD;                   // Stop watchdog timer
  P6SEL = 0x0F;                             // Enable A/D channel inputs
  ADC12CTL0 = ADC12ON+ADC12MSC+ADC12SHT0_2; // Turn on ADC12, set sampling time
  ADC12CTL1 = ADC12SHP+ADC12CONSEQ_1;       // Use sampling timer, single sequence
  ADC12MCTL0 = ADC12INCH_0;                 // ref+=AVcc, channel = A0
  ADC12MCTL1 = ADC12INCH_1;                 // ref+=AVcc, channel = A1
  ADC12MCTL2 = ADC12INCH_2;                 // ref+=AVcc, channel = A2
  ADC12MCTL3 = ADC12INCH_3+ADC12EOS;        // ref+=AVcc, channel = A3, end seq.
  ADC12IE = 0x08;                           // Enable ADC12IFG.3
  ADC12CTL0 |= ADC12ENC;                    // Enable conversions

  while(1)
  {
    ADC12CTL0 |= ADC12SC;                   // Start convn - software trigger
    
    __bis_SR_register(LPM4_bits + GIE);     // Enter LPM4, Enable interrupts
    __no_operation();                       // For debugger    
  }
}

#pragma vector=ADC12_VECTOR
__interrupt void ADC12ISR (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: break;                           // Vector  6:  ADC12IFG0
  case  8: break;                           // Vector  8:  ADC12IFG1
  case 10: break;                           // Vector 10:  ADC12IFG2
  case 12:                                  // Vector 12:  ADC12IFG3
    results[0] = ADC12MEM0;                 // Move results, IFG is cleared
    results[1] = ADC12MEM1;                 // Move results, IFG is cleared
    results[2] = ADC12MEM2;                 // Move results, IFG is cleared
    results[3] = ADC12MEM3;                 // Move results, IFG is cleared
    __bic_SR_register_on_exit(LPM4_bits);   // Exit active CPU, SET BREAKPOINT HERE  
  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: break;                           // Vector 32:  ADC12IFG13
  case 34: break;                           // Vector 34:  ADC12IFG14
  default: break; 
  }
}


The above four examples using 0,1,2,3 ADC channels, because the ADC can convert a plurality of channels, only the channel is enabled interrupt 3.

ADC configuration order as far as possible consistent with the order listed above, otherwise there will be a read failure probability, the specific reasons I did not get to the bottom


These examples are measured on MSP430F5xx / 6xx

Guess you like

Origin blog.csdn.net/LZPRO/article/details/78319755