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.

MSP430F133: ADC and Port interrupts not working as expected

Part Number: MSP430F133

Hello,  

It seems like I've beaten my head against the wall trying to get a simple program working.  I started with the simple FET140_ADC12_01.C program and added a PORT2 interrupt handler for switches wired to p2.0, p2.1, p2.2, p2.4, p2.5 & p2.6.

The board I am working with has LEDs wired to p3.0, p3.1, p3.2, p3.4.

I am expecting the ADC interrupt to toggle P3.4 at some frequency.   (I don't know how long the ADC takes with SHT0_2).

And I am expecting P3.0, P3.1, and P3.2 to toggle when P2.0, P2.1, and P2.2 are shorted to ground by the keypad.  This is done in the Port 2 ISR.

When the program first starts I would expect only P3.4 to be toggling at the ADC refresh rate but P3.0, P3.1 and P3.2 off.

Unexpectedly, when the program first comes up, all P3 GPIO are high...  P3.4 is NOT toggling at any ADC rate.

If I short P2.0 to ground I get multiple P3.0, P3.1, and P3.2 all transitioning from high to low.  Sometimes that kills the program but sometimes the P2 interrupt continues to fire for a couple more key presses.

Any thoughts greatly appreciated....

- Dave


#include <msp430.h>

int main(void)
{
WDTCTL = WDTPW + WDTHOLD; // Stop WDT
ADC12CTL0 = SHT0_2 + ADC12ON; // Set sampling time, turn on ADC12
ADC12CTL1 = SHP; // Use sampling timer
P6SEL |= 0x01; // P6.0 ADC option select

// diagnostics
P1DIR |= 0x01; // P1.0 output
P3DIR |= 0xff; // P3.0 .. P3.3 output to LEDs
P3OUT = 0; // all debug pins low

P2DIR &= ~0xff; // all input inputs on P2
P2IFG &= ~0xff; // clear all flags
P2IES |= 0x77; // Set high to low transitions
P2IE |= 0x77; // enable interrupts P2.0,1,2 4,5,6


for (;;)
{

if ((P2IE & 0x77) == 0)   // int was triggered and enable cleared in ISR so reenable
{
P2IFG &= ~0xff; // clear int flag.
P2IE |= 0x77; // enable interupts
}

if ((ADC12IE & 0x01) == 0) // int was triggered and enable cleared in ISR so reenable
{
ADC12IFG &= ~0xff; // clear all flag
ADC12IE |= 0x01; // Enable interrupt
ADC12CTL0 |= ENC; // Conversion enabled
ADC12CTL0 |= ADC12SC; // Sampling start
}

__bis_SR_register(CPUOFF + GIE); // LPM0, ADC12_ISR or Port 2 int will force exit
}
}


// ADC12 interrupt service routine
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
#pragma vector=PORT2_VECTOR
__interrupt void PORT2_ISR (void)
#elif defined(__GNUC__)
void __attribute__ ((interrupt(PORT2_VECTOR))) PORT2_ISR (void)
#else
#error Compiler not supported!
#endif
{
switch (P2IFG){ // what was the cause of the interrupt?
case 0x01: // P2.0 has been triggered
P3OUT ^= 0x01; // Set P3.2 LED on
break;
case 0x02: // P2.1 has been triggered
P3OUT ^= 0x02; // Set P3.2 LED on
break;
case 0x04: // P2.2 has been triggered
P3OUT ^= 0x04; // Set P3.2 LED on
break;
default: // any other interrupt cause that hasn't been handled?
; // then do nothing
}


P2IFG &= ~0x77; // clear int flags
P2IE &= ~0x77; // disable interupts
__bic_SR_register_on_exit(CPUOFF); // Clear CPUOFF bit from 0(SR)
}


// ADC12 interrupt service routine
#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
{
P3OUT ^= ~0x08; // toggle pin


ADC12CTL0 &= ~ENC; // Conversion disabled
ADC12IFG &= ~0xff; // clear all flags
ADC12IE &= ~0x01; // Disable interrupt
__bic_SR_register_on_exit(CPUOFF); // Clear CPUOFF bit from 0(SR)
}

  • After talking to the H/W engineer, I learned that the circuit inverts the logic of the GPIO output pins. This explains why all LEDs are on at startup, not off.
  • Hello Dave,

    Since you are using single-channel, single-conversion mode (CONSEQx bits) and no timer sample-and-hold source select (SHSx bits) then you will start a conversion each time the ADC12SC bit is set to one. A sample-and-hold time of 16 ADC12CLK cycles (SHTx = 10b) will result in a sample-and-convert time of 30 ADC12CLK cycles (conversions take 13 ADC12CLK cycles, see Figure 17-3&4), plus extra time to service the interrupt and return to the main function. It is not typical to constantly enable/disable interrupt enable registers, I recommend using status flag variables instead. Since the MSP430F133 does not have internal pull-up/down resistors for GPIOs then all switches should be pulled up externally to avoid floating pins which could accidentally trigger an ISR. Without proper debouncing (by either hardware or software) it is possible for a switch to cause multiple interrupts. You should most likely separate your code into ADC and GPIO functionalities and have both working well before attempting to combine them.

    Regards,
    Ryan
  • Thanks Ryan.  I did just that.  To simplify things I removed the ADC code to simply get the port2 interrupt handling working. It is now working as expected. Below is the code.


    #include <msp430.h>

    static int ADC_Complete;

    int main(void)
    {
    volatile int i,j;
    WDTCTL = WDTPW + WDTHOLD; // Stop WDT

    // diagnostics

    P3DIR |= 0x0f; // P3.0 .. P3.3 output to LEDs
    P3OUT |= 0x0f; // all debug pins high - Inverted in circuit!

    P2DIR &= ~0x77; // all input inputs on P2
    P2IES = 0x77; // Set high to low transitions
    P2IFG = 0; // clear all flags
    P2IE = 0x77; // enable interrupts P2.0,1,2 4,5,6


    for (;;)
    {

    if (P2IE == 0) // int was triggered and P2IE cleared in ISR
    {
    for (i=10000;i>0;i--) // debouce delay
    {
    j=i;
    }

    P2IFG = 0; // clear int flags.
    P2IE = 0x77; // enable interrupts
    }

    __bis_SR_register(CPUOFF + GIE); // LPM0, ADC12_ISR or Port 2 int will force exit
    }
    }


    // PORT2 interrupt service routine
    #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__)
    #pragma vector=PORT2_VECTOR
    __interrupt void PORT2_ISR (void)
    #elif defined(__GNUC__)
    void __attribute__ ((interrupt(PORT2_VECTOR))) PORT2_ISR (void)
    #else
    #error Compiler not supported!
    #endif
    {
    P2IE = 0; // disable interupts

    switch (P2IFG){ // what was the cause of the interrupt?
    case 0x10: // P2.4 has been triggered
    case 0x01: // P2.0 has been triggered
    P3OUT ^= 0x01; // Set P3.2 LED on
    break;
    case 0x20: // P25 has been triggered
    case 0x02: // P2.1 has been triggered
    P3OUT ^= 0x02; // Set P3.2 LED on
    break;
    case 0x40: // P2.6 has been triggered
    case 0x04: // P2.2 has been triggered
    P3OUT ^= 0x04; // Set P3.2 LED on
    break;
    default: // any other interrupt cause that hasn't been handled?
    ; // then do nothing
    }

    __bic_SR_register_on_exit(CPUOFF); // Clear CPUOFF bit from 0(SR)
    }

**Attention** This is a public forum