Jump to content
Cloudberry

Setting up timers/ccr MSP430G2152

Recommended Posts

I'm trying to replicate the project shown here http://www.mjlorton.com/forum/index.php?topic=284.0 but instead of the g2211 I'm using the g2152. I somewhat understand what the code is doing, however I'm having a hard time setting up the timers and capture compare registers. Additionally I'm not sure how the timer/ccr is being used to differentiate between a long or short button press (is it using nested interrupts?) The original code uses grace included configs which obviously aren't there,I'm trying to infer how things were set up originally. I have the gpio and wdt config figured out but not the timer or ccr (I'm probably missing other things as well)  Any insight or hints to push me in the right direction would be helpful. Thanks.

 

//#define DATALOG BIT3 //P1.3
//#define BACKLIGHT BIT4 //P1.4
//#define MAXMIN BIT5 //P1.5
//#define DCAC BIT1//P1.1
//#define VHz BIT2//P1.2
//#define DCAC_OUT BIT6//P2.6
//#define VHz_OUT BIT7//P2.7
 
 
/*
 * ======== Standard MSP430 includes ========
 */
#include <msp430g2152.h>
 
/*
 *  ======== main ========
 */
int main(void)
{
       WDTCTL = WDTPW | WDTHOLD;       // stop watchdog timer
 
      
       P1OUT = BIT1 | BIT2 | BIT3 | BIT4 | BIT5;
       P1DIR = BIT3 | BIT4 | BIT5;
       P1REN = BIT1 | BIT2;
       P1IES = BIT1 | BIT2;
       P1IFG = 0;
       P1IE = BIT1 | BIT2;
       P2SEL2 = BIT3;
       P2OUT = BIT6 | BIT7;
       P2SEL &= ~(BIT6 | BIT7);
       P2DIR = BIT6 | BIT7;
       P2IES = 0;
       P2IFG = 0;
 
        __bis_SR_register(LPM3_bits | GIE);
}
 
#pragma vector = PORT1_VECTOR
__interrupt void PORT1_ISR( void )
{
    P1IE &= ~(BIT1 | BIT2); // // disable interrupt on these pins
    __delay_cycles(10000);
    TA0CCR1 = 0;
    TA0CCTL0 &= ~CCIFG;
    TA0CTL |= MC_1; // Start timer
 
    switch(P1IN & (BIT1 | BIT2)){
    case 0:
        //VHz+DCAC buttons pressed
        if(P1OUT & BIT3) P1OUT &= ~(BIT3);
        else P1OUT |= (BIT3);
        __delay_cycles(20000);
    break;
    case 2:
        //VHz button pressed
        while (!(P1IN & BIT2) && !(TA0CCTL0 & CCIFG));
        TA0CTL &= ~MC1;
        if (!(TA0CCTL0 & CCIFG)){
            P2OUT &= ~(BIT7);
            __delay_cycles(10000);
            P2OUT |= (BIT7);
        }
        else{
            P1OUT &= ~(BIT4);
            __delay_cycles(10000);
            P1OUT |= (BIT4);
        }
    break;
    case 4:
        //DCAC button pressed
        while (!(P1IN & BIT1) && !(TA0CCTL0 & CCIFG));
        TA0CTL &= ~MC1;
        if (!(TA0CCTL0 & CCIFG)){
            P2OUT &= ~(BIT6);
            __delay_cycles(10000);
            P2OUT |= (BIT6);
        }
        else{
            P1OUT &= ~(BIT5);
            __delay_cycles(10000);
            P1OUT |= (BIT5);
        }
    break;
    case 6:
        //no button pressed
    break;
    }
    TA0CTL &= ~(MC1 + MC0); // Clear MCx bits to stop timer
    while(!(P1IN & (BIT1 | BIT2)))
    P1IFG &= ~(BIT1 | BIT2); // sets register flag for interrupt to 0: No interrupt is pending
    P1IE |= (BIT1 | BIT2); // re-enable interrupt on these pins
}

Share this post


Link to post
Share on other sites

Hi @Cloudberry,

Well, based on a quick review of the code it appears that the Port1_ISR (based on a button press) starts a timer, and then based on the Case statement, enters a wait state:  while (!(P1IN & BIT1) && !(TA0CCTL0 & CCIFG))
until the timer interrupt is triggered.

From an MSP430 programming style perspective, this is not a good coding practice for a few reasons.

1) ISRs should be as short as possible, since there may be other interrupts pending.  So, get in, set a flag (often) get out and in the main routine evaluate and process flag states.

2) This is NOT a well designed interrupt-driven program with the incorporated wait states.

3) The ISR runs the CPU to execute its code, and is therefor a power draw - shortens battery life.

4) __delay_cycles is clock dependent, thus not a safe means of waiting for a defined time.

You will need to read the docs regarding TA0 - There appears to be virtually no configuration of the timer, so what ever its defalts are??? It's running in Up mode and rolling over (probably at FFFF counts -  and time to execute counts is dependent on the selected clock source, could be cpu - running at what?) to generate an interrupt.  How long does that take? Without configuring the timer, good question...

While it's not often popular advice, time to RTFM on timers and clocks for the SPECIFIC '430 you are using.

HTH

Share this post


Link to post
Share on other sites

Thank you for the insight, as I stated the code is not mine, and the original grace related setup was not included therefore it's no surprise that the timer is not set up at all. I'm trying to work backward from the code to decide how everything was (most likely) setup originally. The original author doesn't seem to be reachable so I'm out of luck there. I'm assuming that the clock source is the internal low frequency oscillator based on the fact that the original project had no external crystal. As to the setup and divider settings for the oscillator, I couldn't tell you. Also everything that you have written about, (poorly coded from an isr standpoint) I came to that same conclusion from going over the code and best practices. Your insight is helpful to me as it explains in a little more depth how the timer is being used in this scenario. Reading the manual trying to infer how to setup a timer is all but useless when you don't know how the timer is being utilized in the code in the first place. Anyway, Thank you again for the help!     

Share this post


Link to post
Share on other sites

> I'm assuming that the clock source is the internal low frequency oscillator

More likely it's running off the main clock.  The low frequency oscillator is not being called or set up, and is not the default.  Also, in the ISR the cpu is running off the main clock - so the main or submain clock is more likely.

I'm assuming you are compiling and running under CCS or IAR? In which case you can put a __no_operation() call in the ISR to see which clock is configured/enabled by inspecting the clock registers.  You can also bring out all the various clocks to the designated port pins and put an oscilloscope to see who's running.

Agreed, the manuals are not an easy resource for where you are.  Howevr, there are numerous code examples (including TI's) on detecting switches and configuring as well as handling clock interrupts.  Don't despair - there are lots of resources, all free, out there to let you dive into the code and figure it all out.

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...