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.

Using a timer to detect large periods of inactivity in MSP430F1611

Other Parts Discussed in Thread: MSP430G2231

As it says in the title, I would like to setup a timer to determine when my device has been inactive (user has not pressed button) for a long period of time, so that I can put it to sleep to save power. Currently, the system is running MCLK off of a 7.68 MHz external crystal, and does not have an external crystal for ACLK. I have read that if you do not have an external crystal for ACLK, you cannot achieve the 32 KHz clock frequency, which would give a timer period of 16s with a clock divider of 8. I don't necessarily need a period of 16s, but the larger the better since I may need to detect a 10-30 minute activity period. I'm new to the MSP430 so I don't really know what direction to go to get a larger clock period so that my application is not spending most of its time servicing interrupts for this timer.

  • Obviously the 32 kHz watch crystal is the best solution   Some of the MSP430s have a built in VLO that runs at ~12kHz but I don't think yours does.



    That being said a simple overflow interrupt with an int32 counter should be more then sufficient for the 10-30 minute interval.  The amount of time to check/increment your counter in an interrupt even without using any prescalers should be very minimal (easily < 1% of the load, probably a lot less then that).  Using an /8 prescaler on the timer and possibly another on SMCLK would give you even less of a load on the system.



    If for some reason the above isn't appropriate for your application you can also try cascading the timers, but I'm having a hard time coming up with situation where this would be appropriate for this kind of interval timer.

  •  It sounds like you want to wait a period before putting it into sleep mode or low power.There are many ways to achieve this but I have used this method to put the device to sleep after a period of time. It uses slices of 32mS and I use a count to determine how many I want. Your main routine sets the total time you want before going to sleep. Every 32mS on WD interrupt it either will reset the counter (detecting a user activity) but if no activity, then the count will reach the set point and the device goes to sleep. Another user input or activity from port 1 wakes up the device and the process repeats. Sample code below should help if you want. Uses the MSP430g2231 and internal clock

    // Watch Dog SetupRoutine -----------------------------------------------------------------------

    void WatchDog (void)
    {
     WDTCTL = WDT_MDLY_32 +WDTNMI;                             // Set Watchdog Timer interval to ~32ms
     IE1 |= WDTIE;                                             // Enable WDT interrupt
    P1IE |= BIT0;                                             // Enable P1.0 interrupt, - used for user detection
     __enable_interrupt();
    }

    Set the required time of non activity

    int SleepTime = 15000;                                  // WatchDog Time to Sleep 32mS x SleepTime
                                                                                // 15000 = 32mS x 15000 = 480 seconds / 60 seconds = 8 minutes

     SleepFlag = 0;

     

    // Port 1 Interrupt Routine ------------User activity

    #pragma vector=PORT1_VECTOR                                // Port 1 interrupt service routine
    __interrupt void Port_1(void)
    {
    if (SleepFlag == 1)                                       // Only set in the WD Interrupt Routine
       {
       wdtCounter = 0;                                         // Reset watchdog timer counter
       SleepFlag = 0;                                          // Reset SleepFlag, no longer in WD mode
                                                                            // Only ever Cleared here !!
       _BIC_SR(LPM3_EXIT);                             // Wake up from low power mode
       }

     else if (SleepFlag == 0)                                  // Not in WD so must have been a button press
      {
       wdtCounter = 0;                                         // Reset watchdog timer counter
      }

     P1IFG = 0x0;                                              // Reset P1 Interrupt Flag
    }

    // Watch Dog Interrupt Routine --------------------------------------------------------------

    #pragma vector=WDT_VECTOR                                      // Watchdog Timer interrupt service routine
    __interrupt void watchdog_timer(void)
    {
      if(wdtCounter == SleepTime)
      {
      //Stuff here before putting to sleep
       SleepFlag = 1;                                          // Set Flag for WD Sleep Mode
                                                                            // Only ever set here !!
       wdtCounter = 0;                                         // Reset Counter to Zero
       _BIS_SR(LPM3_bits + GIE);                               // Enter LPM3 w/interrupt
      }
      else
      {
       wdtCounter++;                                           // Increment Counter because of user inactivity
      }
    }

**Attention** This is a public forum