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.

ADC wont work without delay or setting GIE bit inside ISR

Other Parts Discussed in Thread: MSP430F5529

I am trying to run the TI ADC12 example on my MSP430F5529 that  samples A0 Input and turns LED P1.0 on if A0 > 0.5*AVcc.


I am having this strange issue where the program only works while running in debug mode, when i power the board with via usb but not in debug mode the LED doesn't respond to the input. My input is from a force sensor and it works perfectly in debug mode.


I started this thread on stack exchange and narrowed down the issue: It seems that there are two solutions to my problem, i can either put a delay inside the ISR using __delay_cylces, or i can change the line

__bic_SR_register_on_exit(LPM0_bits);

to be

    __bic_SR_register_on_exit(LPM0_bits + GIE);



My question is, why does the delay inside the ISR cause the program to work properly? And what does __bic_SR_register_on_exit do exactly? Why does the example not have the GIE bit set when it calls it?

  • Aaron,

    you mean this code?

    //******************************************************************************
    //   MSP430F552x Demo - ADC12, Sample A0, Set P1.0 if A0 > 0.5*AVcc
    //
    //   Description: A single sample is made on A0 with reference to AVcc.
    //   Software sets ADC12SC to start sample and conversion - ADC12SC
    //   automatically cleared at EOC. ADC12 internal oscillator times sample (16x)
    //   and conversion. In Mainloop MSP430 waits in LPM0 to save power until ADC12
    //   conversion complete, ADC12_ISR will force exit from LPM0 in Mainloop on
    //   reti. If A0 > 0.5*AVcc, P1.0 set, else reset.
    //
    //                MSP430F552x
    //             -----------------
    //         /|\|                 |
    //          | |                 |
    //          --|RST              |
    //            |                 |
    //     Vin -->|P6.0/CB0/A0  P1.0|--> LED
    //
    //   Bhargavi Nisarga
    //   Texas Instruments Inc.
    //   April 2009
    //   Built with CCSv4 and IAR Embedded Workbench Version: 4.21
    //******************************************************************************
    
    #include <msp430.h>
    
    int main(void)
    {
      WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
      ADC12CTL0 = ADC12SHT02 + ADC12ON;         // Sampling time, ADC12 on
      ADC12CTL1 = ADC12SHP;                     // Use sampling timer
      ADC12IE = 0x01;                           // Enable interrupt
      ADC12CTL0 |= ADC12ENC;
      P6SEL |= 0x01;                            // P6.0 ADC option select
      P1DIR |= 0x01;                            // P1.0 output
    
      while (1)
      {
        ADC12CTL0 |= ADC12SC;                   // Start sampling/conversion
        
        __bis_SR_register(LPM0_bits + GIE);     // LPM0, ADC12_ISR will force exit
        __no_operation();                       // For debugger
      }
    }
    
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector = ADC12_VECTOR
    __interrupt void ADC12_ISR(void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(ADC12_VECTOR))) ADC12_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
      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
        if (ADC12MEM0 >= 0x7ff)                 // ADC12MEM = A0 > 0.5AVcc?
          P1OUT |= BIT0;                        // P1.0 = 1
        else
          P1OUT &= ~BIT0;                       // P1.0 = 0
    
        __bic_SR_register_on_exit(LPM0_bits);   // Exit active CPU
      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; 
      }
    }

    And it does not run in it's original version?

    Dennis

  • The “__bic_SR_register_on_exit” instructs the compiler to clear these bits in the Status Register just before it will leave the ISR function and jumps back to main.

     

    I think the ADC generates continuously interrupts and therefore you don’t see LED changes. Adding a delay or disable interrupts lengths the ADC ISR time and gives you the possibility to see LED changes.

     

    What you need to do is clearing all ADC interrupt flags, either once in main or in the ADC ISR. You can also have a look which flags are set and why.

  • Access/read or write of the ADC12IV will (normally) reset the highest pending interrupt flag. What is the program doing when debugging it? Does it access the ISR? Only once or repeated? Does it jump back to main starting a new conversion?


    Edit: Sorry, forget that question! You wrote that it works in debug mode.

  • (The code we're talking about uses driverlib.)

    Actually, it is not ADC12IV but the access of the memory register that clears the corresponding interrupt flag.(Which implies that the behaviour could be explained by a conversion that happened in another memory register, which should not be possible.)

    Aaron, does the problem remain if you do ADC12IFG=0; at the end of the interrupt function?

  • Clemens Ladisch said:

    Aaron, does the problem remain if you do ADC12IFG=0; at the end of the interrupt function?

    No that does not help, unfortunately. It still has the same behavior. Are interrupts being disabled somehow?

    What i am confused by is why adding the delay makes it work without the +GIE inside the __bic_SR_on_exit function.

  • see my latest post, clearing the ADCIFG doesn't seem to help.
  • Dennis Eichmann , using that code that modifies registers (instead of using driver lib functions to do so) seems to work fine outside the debugger! So this must be an issue with the driverlib.

**Attention** This is a public forum