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.

CCS/MSP430FR2311: FR2000 Multiple Timebases Example porting to 2311

Part Number: MSP430FR2311

Tool/software: Code Composer Studio

I'm trying to port SLAA766 for MSP430FR2000 Example for controlling RGB LED over UART over to the MSP430FR2311. I've made the changes suggested in SLAA812, by:

1. changing the timer to TIMER1_B 

2. changing the pins for PWM to P1.0, P2.0, P2.1

Now when I execute the below code, it always throws me into an unhandled interrupt / ISR Trap. What seems to be the issue?

#include<msp430.h>
#include<stdint.h>

//  Contains the low (on) period for the RGB LEDs for each color selection
const uint8_t colorsLow[12][3] = {
                           //{R, G, B}
                           {134,1,1},   //RED
                           {134,15,1},  //RED-ORANGE
                           {134,20,1},  //ORANGE
                           {134,30,1},  //ORANGE-YELLOW
                           {134,55,1},  //YELLOW
                           {67,80,1},   //YELLOW-GREEN
                           {1,134,1},   //GREEN
                           {1,134,134}, //GREEN-BLUE
                           {1,1,134},   //BLUE
                           {67,1,134},  //BLUE-PURPLE
                           {134,1,134}, //PURPLE
                           {134,1,80}   //PURPLE-RED
};
//  Contains the high (off) period for the RGB LEDs for each color selection
const uint8_t colorsHigh[12][3] = {
                           //{R, G, B}
                           {1,134,134}, //RED
                           {1,120,134}, //RED-ORANGE
                           {1,115,134}, //ORANGE
                           {1,100,134}, //ORANGE-YELLOW
                           {1,80,134},  //YELLOW
                           {68,55,134}, //YELLOW-GREEN
                           {134,1,134}, //GREEN
                           {134,1,1},   //GREEN-BLUE
                           {134,134,1}, //BLUE
                           {68,134,1},  //BLUE-PURPLE
                           {1,134,1},   //PURPLE
                           {1,134,55}   //PURPLE-RED
};

uint8_t selected;   //Used to track the current color selection

/**
 * main.c
 */
void main(void)
{
    WDTCTL = WDTPW | WDTHOLD;               // Stop watchdog timer

    selected = 0;                           // Default to Red

    // Configure UART
    // From user's Guide Table of Baud Rates, 9600 baud at BRCLK = 32768
    // UCOS16 = 0
    // UCBRx = 3
    // UCBRFx = 0
    // UCBRSx = 0x92
    UCA0CTLW0 = UCSWRST | UCSSEL__ACLK;
    UCA0BRW = 3;
    UCA0MCTLW = 0x9200;
    UCA0CTLW0 &= ~UCSWRST;              // Initialize eUSCI
    UCA0IE = UCRXIE;                    // Enable USCI_A0 RX interrupt

    // Configure GPIO
//    PASEL0 = BIT6 | BIT7 | BIT8 | BIT9; // TB0.1 and 0.2, UCA0 RXD and TXD
//    PADIR = BIT8 | BIT9 | BIT0;         // TB0.1, 0.2, 0.0 (on P1.0)
//    PAOUT = 0;

    P1SEL0 = BIT6 + BIT7; // Enable UART function on p1.6 & 1.7

    P1DIR = BIT0;           // Set P1.0 to output
    P2SEL0 = BIT0 + BIT1;   // Enable secondary function of TB1 output on given pins
    P2DIR =  BIT0 + BIT1;   // Enable output on p2.0 & 2.1
    PAOUT = 0;  // shut everything

    PM5CTL0 &= ~LOCKLPM5;               // Disable the GPIO power-on default
                                        // high-impedance mode to activate
                                        // previously configured port settings

    // Set up Timer B in continuous mode for multiple time base PWMs.
    // See app note SLAA513 for theory.
    TB1CCTL0 = CCIS_0 + OUTMOD_4 + CCIE;    // CCR0 toggle, interrupt enabled
    TB1CCTL1 = CCIS_0 + OUTMOD_4 + CCIE;    // CCR1 toggle, interrupt enabled
    TB1CCTL2 = CCIS_0 + OUTMOD_4 + CCIE;    // CCR2 toggle, interrupt enabled

    // REF0CLK/4 = 8192 is used for TBCLK so that the period of 60Hz can be
    // generated with TB0CCRx values totaling only 135 for the period of 60Hz
    // PWM. This is less than 255, so that the lookup table can be made of 8-bit
    // values, saving additional FRAM space on small devices.
    TB1CTL = TBSSEL__ACLK + ID__4 + MC_2 + TBCLR;   // ACLK, contmode, clear TAR


    __bis_SR_register(LPM3_bits | GIE);     // Go to LPM3 with interrupts
    __no_operation();
}

// UART interrupt service routine
#pragma vector=USCI_A0_VECTOR
__interrupt void USCI_A0_ISR(void)
{
    selected = UCA0RXBUF;   // Get new value for selected color

    if(selected > 11)       // If value out of range, set default 0 (red)
    {
        selected = 0;
    }
}

// Timer_B0 interrupt service routine
#pragma vector=TIMER1_B0_VECTOR
__interrupt void TIMER1_B0_ISR (void)
{
    if(P1OUT & BIT0)                        // Check current output level
    {
        TB1CCR0 += colorsLow[selected][2];  // Low period (Blue LED on)
        P1OUT = 0;      // TB0.0 not brought out on pin, so set manually
    }
    else
    {
        TB1CCR0 += colorsHigh[selected][2]; // High period (Blue LED off)
        P1OUT = BIT0;   // TB0.0 not brought out on pin, so set manually
    }
}

// Timer_B1 Interrupt Vector (TBIV) handler
#pragma vector=TIMER1_B1_VECTOR
__interrupt void TIMER1_B1_ISR(void)
{
    switch(__even_in_range(TB1IV,14))
    {
        case 0: break;
        case 2: if(TB1CCTL1 & CCI)          // Check current timer pin state
                {
                    TB1CCR1 += colorsHigh[selected][0]; // High period (Red off)
                }
                else
                {
                    TB1CCR1 += colorsLow[selected][0];  // Low period (Red on)
                }
                break;
        case 4: if(TB1CCTL2 & CCI)          // Check current timer pin state
                {
                   TB1CCR2 += colorsHigh[selected][1];  // High (Green off)
                }
                else
                {
                   TB1CCR2 += colorsLow[selected][1];   // Low period (Green on)
                }
                break;
        default:    break;
    }
}

  • I don't see the behavior you described on my Launchpad. I only see the LEDs change when I set breakpoints in the ISRs, which suggests the LEDs are changing too fast to see.

    Is this the first time you've used your Launchpad? Some Launchpads come with a demonstration program that uses the RTC. If you load another program on top of that one, the RTC is not reset, and the RTC interrupt goes off while your program is running. You should be able to clear this with a power-cycle, but in a pinch add "RTCCTL=0;" as the first line of your program.

  • Thanks for the help, Bruce! That was indeed the issue! And sure enough, I was fiddling with the RTC before trying this code, and I didn't power-cycle in between. 

    A quick follow-up question though -- Why does it take about 5 seconds for the LEDs to show the first color every time? 

    I've now initialized the RTC and added a function to count seconds and increment the "selected" value every 1 second. I see the LED come on only after 5 or so seconds of running the program every time.

    #include<msp430.h>
    #include<stdint.h>
    
    //  Contains the low (on) period for the RGB LEDs for each color selection
    const uint8_t colorsLow[12][3] = {
                               //{R, G, B}
                               {134,1,1},   //RED
                               {134,15,1},  //RED-ORANGE
                               {134,20,1},  //ORANGE
                               {134,30,1},  //ORANGE-YELLOW
                               {134,55,1},  //YELLOW
                               {67,80,1},   //YELLOW-GREEN
                               {1,134,1},   //GREEN
                               {1,134,134}, //GREEN-BLUE
                               {1,1,134},   //BLUE
                               {67,1,134},  //BLUE-PURPLE
                               {134,1,134}, //PURPLE
                               {134,1,80}   //PURPLE-RED
    };
    //  Contains the high (off) period for the RGB LEDs for each color selection
    const uint8_t colorsHigh[12][3] = {
                               //{R, G, B}
                               {1,134,134}, //RED
                               {1,120,134}, //RED-ORANGE
                               {1,115,134}, //ORANGE
                               {1,100,134}, //ORANGE-YELLOW
                               {1,80,134},  //YELLOW
                               {68,55,134}, //YELLOW-GREEN
                               {134,1,134}, //GREEN
                               {134,1,1},   //GREEN-BLUE
                               {134,134,1}, //BLUE
                               {68,134,1},  //BLUE-PURPLE
                               {1,134,1},   //PURPLE
                               {1,134,55}   //PURPLE-RED
    };
    
    uint8_t selected;   //Used to track the current color selection
    
    /**
     * main.c
     */
    void main(void)
    {
        WDTCTL = WDTPW | WDTHOLD;               // Stop watchdog timer
    
        selected = 0;                           // Default to Red
        RTCCTL=0;
    
        // Configure UART
        // From user's Guide Table of Baud Rates, 9600 baud at BRCLK = 32768
        // UCOS16 = 0
        // UCBRx = 3
        // UCBRFx = 0
        // UCBRSx = 0x92
        UCA0CTLW0 = UCSWRST | UCSSEL__ACLK;
        UCA0BRW = 3;
        UCA0MCTLW = 0x9200;
        UCA0CTLW0 &= ~UCSWRST;              // Initialize eUSCI
        UCA0IE = UCRXIE;                    // Enable USCI_A0 RX interrupt
    
        // Configure GPIO
    //    PASEL0 = BIT6 | BIT7 | BIT8 | BIT9; // TB0.1 and 0.2, UCA0 RXD and TXD
    //    PADIR = BIT8 | BIT9 | BIT0;         // TB0.1, 0.2, 0.0 (on P1.0)
    //    PAOUT = 0;
    
        P1SEL0 = BIT6 + BIT7; // Enable UART function on p1.6 & 1.7
    
        P1DIR = BIT0;           // Set P1.0 to output
        P2SEL0 = BIT0 + BIT1;   // Enable secondary function of TB1 output on given pins
        P2DIR =  BIT0 + BIT1;   // Enable output on p2.0 & 2.1
        PAOUT = 0;  // shut everything
    
        PM5CTL0 &= ~LOCKLPM5;               // Disable the GPIO power-on default
                                            // high-impedance mode to activate
                                            // previously configured port settings
        // RTC count re-load compare value at 32.
        // 1024/32768 * 32 = 1 sec.
        RTCMOD = 32-1;
    //    RTCMOD = 4 - 1;
        // Initialize RTC
        // Source = ACLK = REFO, divided by 1024
        SYSCFG2 |= RTCCKSEL;                    // Select ACLK as RTC clock
        RTCCTL = RTCSS_1 | RTCSR | RTCPS__1024 | RTCIE;
    
        // Set up Timer B in continuous mode for multiple time base PWMs.
        // See app note SLAA513 for theory.
        TB1CCTL0 = CCIS_0 + OUTMOD_4 + CCIE;    // CCR0 toggle, interrupt enabled
        TB1CCTL1 = CCIS_0 + OUTMOD_4 + CCIE;    // CCR1 toggle, interrupt enabled
        TB1CCTL2 = CCIS_0 + OUTMOD_4 + CCIE;    // CCR2 toggle, interrupt enabled
    
        // REF0CLK/4 = 8192 is used for TBCLK so that the period of 60Hz can be
        // generated with TB0CCRx values totaling only 135 for the period of 60Hz
        // PWM. This is less than 255, so that the lookup table can be made of 8-bit
        // values, saving additional FRAM space on small devices.
        TB1CTL = TBSSEL__ACLK + ID__4 + MC_2 + TBCLR;   // ACLK, contmode, clear TAR
    
    
        __bis_SR_register(LPM3_bits | GIE);     // Go to LPM3 with interrupts
        __no_operation();
    }
    
    void incrementSeconds(){
    
        if(selected > 11)       // If value out of range, set default 0 (red)
            {
                selected = 0;
            }
        else selected++;
    }
    
    // UART interrupt service routine
    #pragma vector=USCI_A0_VECTOR
    __interrupt void USCI_A0_ISR(void)
    {
        selected = UCA0RXBUF;   // Get new value for selected color
    
        if(selected > 11)       // If value out of range, set default 0 (red)
        {
            selected = 0;
        }
    }
    
    // RTC interrupt service routine
    #pragma vector=RTC_VECTOR
    __interrupt void RTC_ISR(void)
    {
        switch (__even_in_range(RTCIV, RTCIV_RTCIF))
        {
        case RTCIV_NONE:
            break;          // No interrupt
        case RTCIV_RTCIF:                  // RTC Overflow
            incrementSeconds();
            break;
        default:
            break;
        }
    }
    
    // Timer_B0 interrupt service routine
    #pragma vector=TIMER1_B0_VECTOR
    __interrupt void TIMER1_B0_ISR (void)
    {
        if(P1OUT & BIT0)                        // Check current output level
        {
            TB1CCR0 += colorsLow[selected][2];  // Low period (Blue LED on)
            P1OUT = 0;      // TB0.0 not brought out on pin, so set manually
        }
        else
        {
            TB1CCR0 += colorsHigh[selected][2]; // High period (Blue LED off)
            P1OUT = BIT0;   // TB0.0 not brought out on pin, so set manually
        }
    }
    
    // Timer_B1 Interrupt Vector (TBIV) handler
    #pragma vector=TIMER1_B1_VECTOR
    __interrupt void TIMER1_B1_ISR(void)
    {
        switch(__even_in_range(TB1IV,14))
        {
            case 0: break;
            case 2: if(TB1CCTL1 & CCI)          // Check current timer pin state
                    {
                        TB1CCR1 += colorsHigh[selected][0]; // High period (Red off)
                    }
                    else
                    {
                        TB1CCR1 += colorsLow[selected][0];  // Low period (Red on)
                    }
                    break;
            case 4: if(TB1CCTL2 & CCI)          // Check current timer pin state
                    {
                       TB1CCR2 += colorsHigh[selected][1];  // High (Green off)
                    }
                    else
                    {
                       TB1CCR2 += colorsLow[selected][1];   // Low period (Green on)
                    }
                    break;
            default:    break;
        }
    }
    

  • I don't have my equipment here, but I think the problem is that the CCRs are all 0 when you start the timer, so the counter will have to cycle (65536/8192=8 sec) before the first compare match happens.

    The simplest fix might be to initialize TB1R=0xFFFF, rather than using TACLR.

  • That did solve the issue of late start! Thanks a ton, Bruce!

    I'm just getting started, and hope I don't run into further issues :)

**Attention** This is a public forum