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 ); // 16bitint display_led(int t, int display);void display_refresh( void );// Time function variblesvolatile 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/controlvolatile 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 controlchar 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); }// Displayvoid 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 74HC595int 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 portsvoid Initializeports(void){int i = 0;P1DIR |= 0x07; P1SEL = 0x00;P1OUT = 0x18; // P1.4 set, else resetP1REN |= 0x18;while( i < 5 ) { display_buffer[i] = 0; display_ctl[i] = 0; i++; }} // Delay Routine from mspgcc help filestatic void __inline__delay(register unsigned int n){ __asm__ __volatile__ ( "1: \n" " dec %[n] \n" " jne 1b \n" : [n] "+r"(n));}// Time keeping routineinterrupt(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;}