Jump to content
43oh

Simple two state (state machine?)


Recommended Posts

main.cpp:

 

/**
 * A simple example of a two state "state machine".
 * Using the watchdog timer, as an interval timer
 * to set a flag every ~1 second. Said flag is then
 * acted on from within main().
 *
 * Source written by Yyrkoon of forum.43oh.com
 * Written for the v1.5 (msp430G2553) Launchpad
 * Compiled, uploaded, and tested  using Energia, with 
 * the Energia framework bypassed. effectively gcc-msp430.
 *
 * the following source is fairly basic, mostly common 
 * knowlege, and as such is open to public domain.
 *
 */
#include <msp430.h>
#include <stdint.h>
#include "uart.h"

#define FLAG_second_elapsed BIT0            // Flag bit position to determine if a second has elapsed.

volatile uint16_t ticks = 0;                // Counter used to store WDT "ticks"
volatile uint8_t flags = 0;                 // "bit field" used to store global state flags.

void printf(char *, ...);                   // printf() output pointed to UART through putc()

int main(void) 
{
  WDTCTL = WDT_MDLY_32;                     // Configure Watchdog as 32ms interval timer( @ 1Mhz CPU frequency )
  BCSCTL1 = CALBC1_1MHZ;                    // Load calibrated constants for 1Mhz operation.
  DCOCTL = CALDCO_1MHZ;                     // DCO == 1Mhz

  uart_initialize();                        // Initialize UART. TX only for debugging purposes.


  IE1 |= WDTIE;                             // Enable WDT interrupt
  
  while(1)
  {
    if(flags & FLAG_second_elapsed)         // Test if a second has elapsed.
    {
      flags &= ~(FLAG_second_elapsed);      // Clear flag
      printf("tick \n\r");                  // Do whatever needs to done every interval here
    }
    _BIS_SR(LPM0_bits + GIE);               // Put CPU into sleep, enable global interrupts.
  }

  return 0;
}

__attribute__( (interrupt (WDT_VECTOR)) )

void WDT_INTERVAL_ISR(void) 
{
  if ((++ticks % 32) == 0)                   // Test if ~1 second has elapsed. Change if CPU is not 1MHz
  {                                          // Using power of 2 as Suggested by Rickta59 on these forums
    flags |= FLAG_second_elapsed;            // If we're here, a second has elapsed, so set corresponding flag.
  }

  _BIC_SR_IRQ(LPM0_bits);                    // leave the ISR and exit sleep mode

}

 

 

An example of a simple two state "state machine".

 

All comments are welcome. This code is meant to provoke discussion. In hopes that we may learn from one another.

 

For example, one thing I am unclear on myself is re-enabling GIE every time the main loop is cycled. Since in effect the WDT ISR only brings the CPU out of sleep, and does not disable global interrupts. I am assuming GIE does not need to set every loop cycle but again . . . unclear.

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...