Time Routine

This Demo shows how to use a time keeping routine, read a switch press and how long the switch is down.

Advance display handling, using the 74HC595.

Source code for project:

//  MSP430G2231  RTC Clock
// and display on 7 segment displays via two 74hc595 shift registers
#include  <msp430x20x2.h>
#include <io.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
// Led table:         0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, b, C, d, E, F, blank, -
char ledtable[18] = { 0x7e, 0x30, 0x6d, 0x79, 0x33, 0x5b, 0x5f, 0x70, 0x7f, 0x7b, 0x77, 0x1f, 0x4e, 0x3d, 0x4f, 0x47, 0x00, 0x01 };
void Initializeports(void);
static void __inline__delay(register unsigned int n);
int binary2bcd16( unsigned char *bcd, int t );  // 16bit
int display_led(int t, int display);
void display_refresh( void );
// Time function varibles
volatile unsigned char days = 0, hours = 0, minutes = 0, seconds = 0, e_hours = 0, e_minutes = 0, e_seconds = 0;
volatile unsigned int milliseconds = 0, milliseconds_t = 0;
// Display buffer/control
volatile int display_buffer[6];
volatile int display_ctl[6];
volatile int display_blink = 0;
volatile int display_blink_rate;
volatile int display_position;
// Switch, mode control
char d_mode = 0, e_mode = 0, d_mode_digit = 0, switch1, switch2;
unsigned int switch1_dt, switch2_dt;
void main(void)
{
  unsigned char i;
  int t;
  unsigned char  digit[5], alt_digit = 0;
  WDTCTL = WDTPW + WDTHOLD;                 // Stop WDT
//1Mhz
  BCSCTL1 = CALBC1_1MHZ;                    // Set range
  DCOCTL = CALDCO_1MHZ;                     // Set DCO step + modulation */
 
  CCTL0 = CCIE;                             // CCR0 interrupt enabled
  CCR0 = 1000;
  TACTL = TASSEL_2 + MC_2;                  // SMCLK, contmode
  
  Initializeports();
 
 _EINT();
 
  /* Main Application Loop */
  while(1)
  {
  if ( switch1_dt > 299 )  // Mode switch down
     {
     switch1 = 1;
     if ( switch1_dt > 2000 )  // Mode switch held down
        {
        display_ctl[d_mode_digit + 1] = 0x01;
        display_ctl[d_mode_digit] = 0x01;
        e_mode++;
        if ( e_mode == 1 )
           {
           e_hours = hours;
           e_minutes = minutes;
           e_seconds = seconds;
           }     
        if ( e_mode > 1 )
           {
           e_mode = 0;
           display_ctl[d_mode_digit + 1] = 0x00;
           display_ctl[d_mode_digit ] = 0x00;
           hours = e_hours;
           minutes = e_minutes;
           seconds = e_seconds;
           }
           switch1_dt = 1;
         }
       }
       
     // Switch one release  
    if ( (switch1 == 1) && (switch1_dt == 0 ) )
       {
       if (e_mode == 1 )
          {
          display_ctl[d_mode_digit + 1] = 0x00;
          display_ctl[d_mode_digit ] = 0x00;
          d_mode_digit = d_mode_digit + 2;
          if (d_mode_digit > 5) d_mode_digit = 0;
          display_ctl[d_mode_digit + 1] = 0x01;
          display_ctl[d_mode_digit] = 0x01;
          switch1 = 0; 
          }else{     
          d_mode ++;
          if (d_mode > 1) d_mode = 0;
          switch1 = 0;
          }
        }           
    
if ( switch2_dt > 299 )
        {
        switch2 = 1;
        if ( switch2_dt > 2000 )
           {
           switch2_dt = 1;
           if ( d_mode_digit < 2 ) e_hours++;
           if ( e_hours > 24 ) e_hours = 1;
           if ( ( d_mode_digit > 1 ) && ( d_mode_digit < 4 ) ) e_minutes++;
           if ( e_minutes > 59 ) e_minutes = 0;
           if ( d_mode_digit > 3 ) e_seconds++;
           if ( e_seconds > 59 ) e_seconds = 0;
           switch2_dt = 299;
           }
         }
        
if ( (switch2 == 1) && (switch2_dt == 0 ) )
   {
   if ( d_mode_digit < 2 ) e_hours++;
   if ( e_hours > 24 ) e_hours = 1;
   if ( (d_mode_digit > 1 ) && ( d_mode_digit < 4 ) ) e_minutes++;
   if ( e_minutes > 59 ) e_minutes = 0;
   if ( d_mode_digit > 3 ) e_seconds++;
   if ( e_seconds > 59 ) e_seconds = 0;
   switch2 = 0;
   }
if ( e_mode )
    {
    t = e_seconds;  // Display Edit mode time
     binary2bcd16( digit, t);
    display_buffer[4] = digit[1];
    display_buffer[5] = digit[0];
    t = e_minutes;
    binary2bcd16( digit, t);                   
    display_buffer[2] =  digit[1];
    display_buffer[3] = digit[0];
    t = e_hours;
    binary2bcd16( digit, t);
    display_buffer[0] = digit[1];
    display_buffer[1] = digit[0];
    display_refresh( ); 
    }else{ 
     t = seconds;   // Display Normal mode time
     binary2bcd16( digit, t);
    display_buffer[4] = digit[1];
    display_buffer[5] = digit[0];
    t = minutes;
    binary2bcd16( digit, t);                   
    display_buffer[2] =  digit[1];
    display_buffer[3] = digit[0];
    t = hours;
    binary2bcd16( digit, t);
    display_buffer[0] = digit[1];
    display_buffer[1] = digit[0];
    }
 
    }
}
int binary2bcd16( unsigned char *bcd, int t )  // 16bit to BCD conversion
{
int i;
while( i < 5)
 {
 bcd[i] = 0;
 i++;
}
     if ( t > 9999 ) bcd[4] = t / 10000;
     if ( t > 999  ) bcd[3] = t  / 1000 - bcd[4] * 10;
     if ( t > 99 ) bcd[2] = t / 100 - (bcd[3] * 10 + bcd[4] * 100);
     if ( t > 9 ) bcd[1] = t / 10 - (bcd[2] * 10 + bcd[3] * 100 + bcd[4] * 1000);
     bcd[0] = t - (bcd[1] * 10 + bcd[2] * 100 + bcd[3] * 1000 + bcd[4] * 10000);     
 
}
// Display
void display_refresh( void )
{
int d;
if ( (display_ctl[display_position] == 0x01) && (display_blink == 0x01))
    {
   d = 16;
   }else{
    d = display_buffer[display_position];
   }
display_led( d, display_position);
display_position++;
if (display_position > 5) display_position = 0;
}
// Serial out of LED data to 74HC595
int display_led(int t, int display)
{
int j, i, mask;
mask = (~0x0100<<display) & 0xff00;
j = (ledtable[t]<<1) | mask;
P1OUT &= ~BIT2;
for(i=0; i < 16; i++)
   {   
   P1OUT &= ~BIT1;
   if  (j & 0x8000)
      {
      P1OUT |= BIT0;
      }else{
      P1OUT &= ~BIT0;
      }
P1OUT |= BIT1;
   j = j<<1;
   }
P1OUT |= BIT2;
}
// setup ports
void Initializeports(void)
{
int i = 0;
P1DIR |= 0x07;    
P1SEL = 0x00;
P1OUT = 0x18;                             // P1.4 set, else reset
P1REN |= 0x18;
while( i < 5 )
  {
  display_buffer[i] = 0;
  display_ctl[i] = 0;
  i++;
  }
}   
   
// Delay Routine from mspgcc help file
static void __inline__delay(register unsigned int n)
{
  __asm__ __volatile__ (
  "1: \n"
  " dec %[n] \n"
  " jne 1b \n"
        : [n] "+r"(n));
}
// Time keeping routine
interrupt(TIMERA0_VECTOR) Timer_A (void)
{
milliseconds++;
milliseconds_t++;
if (milliseconds > 999)
   {
   seconds++;
   milliseconds = 0;
   }
if (milliseconds_t > 59999)
   {
   milliseconds_t = 0;
   }
if ( 0x10 & ~P1IN)
   {
   switch1_dt++;
  }else{
  switch1_dt = 0;
  }
    
if ( 0x08 & ~P1IN)
   {
   switch2_dt++;
  }else{
  switch2_dt = 0;
  }
if (seconds > 59)
   {
   minutes++;
   seconds = 0;
   }   
if (minutes > 59 )
   {
    hours++;
    minutes = 0;
   }
if (hours > 23)
    {
    hours = 0;
    days++;
    }
  
display_blink_rate++; 
if  (display_blink_rate > 250)  // LED Blink rate
    {
    display_blink = (~display_blink) & 0x01;  
    display_blink_rate = 0;
    }
display_refresh( );   
CCR0 += 999;
}