昨年製作して、MTM07とC81で展示していたMSP430を使った時計のソフトウェアを更新し、時刻合わせの機能を付加しました。
最近の電子式時計では操作用の押しボタンスイッチが機能別に複数取り付けられているようで、1つのボタンを長押しとそれ以外で機能を共用させる方式は流行らない様なのですが、汎用ポートの数が限られているのでスイッチの数を抑制する方向で設計しました。
コメント等がほとんど無く、不要なマクロ定義がありますが、暫定版として公開いたします。
#include// State Machines That Gray Coded Style #define INITIAL 0x00 // bin 0000_0000 #define HOLD 0x01 // bin 0000_0001 #define MIN_SET 0x03 // bin 0000_0011 #define HUR_SET 0x04 // bin 0000_0100 #define CNT_DN 0x07 // bin 0000_0111 #define ALARM 0x06 // bin 0000_0110 #define STOP 0x05 // bin 0000_0101 #define SET_CLOCK 0x08 // bin 0000_1000 unsigned char state; // External Variable Used to Keep State unsigned int set_min; unsigned int set_hour; unsigned char cnt_dn; unsigned char intf; unsigned char ccintf; unsigned char sec; unsigned char length; unsigned char gstate; static unsigned char hour,min,min_base,hour_base; void sr164_set (unsigned char hour, unsigned char min) { unsigned char i,h,m,s; h = hour; m = min; for(i=0;i<16;i++){ if(i<8){ P1OUT &= 0x2F; s = 0x80 & h; if(s){ P1OUT |= 0x80 + 0x20 + 0x0C; }else{ P1OUT &= 0x7F; } h = h * 2; P1OUT |= 0x4C; } else{ P1OUT &= 0x2F; s = 0x80 & m; if(s){ P1OUT |= 0x80 + 0x20 + 0x0C; }else{ P1OUT &= 0x7F; } m = m * 2; P1OUT |= 0x4C; } } } void set_clock(void){ unsigned char lstate; P1IE &=~0x0C; lstate = 0; while ((P1IN & 0x08)==0); while (lstate < 2){ while(lstate == 0){ if(((P1IN & 0x04)==0)){ if(min_base<59){ min_base++; }else{ min_base=0; } min = ((min_base/10) * 16) + (min_base % 10); sr164_set(hour,min); while((P1IN & 0x04)==0); }else if((P1IN & 0x08)==0){ lstate++; } } while ((P1IN & 0x08)==0); P1OUT &=0x2C; while(lstate == 1){ if(((P1IN & 0x04)==0)){ if(hour_base<23){ hour_base++; }else{ hour_base=0; } hour = ((hour_base/10) * 16) + (hour_base % 10); sr164_set(hour,min); while((P1IN & 0x04)==0); }else if((P1IN & 0x08)==0){ lstate++; } } } TACCTL0 |= CCIE; gstate = INITIAL; } void main (void) { volatile unsigned int i,j,m,n,p,q; // Initial Settings cnt_dn = 0; intf = 0; ccintf = 0; sec = 0x00; set_min = 0x00; set_hour = 0x00; length = 0; gstate = INITIAL; //state = INITIAL; // State Machine Initialize // X'tal and Timer Settings WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer BCSCTL3 |= XCAP_3; // Set X_CAP 12.5pF TACTL = TASSEL_1 + MC_1 + TACLR; // ACLK, up mode, Timer CLR TACCTL0 = CCIE; CCR0 = 0x7FFF; // Set TACCR0 to 16383 // GPIO Settings P1DIR |= 0xF3; // Set LED Port Output P1IE |= 0x0C; // P1.3, P1.4 Interrupt Enable P1IES |= 0x0C; // P1.3, P1.4 Fall Edge Interrupt Enable P1IFG &= ~0x0C; // P1 Interrupt state Cleared P1OUT=0xEF; // When X'tal OSC is fault, Red LED Blink while (BCSCTL3 & LFXT1OF) { // Blink LED and Buzzer for(j=80;j>0;j--){ P1OUT ^= 0x03; for(i=63;i>0;i--){;} } } /* Assign Slow Clock to System Clock */ BCSCTL2 |= SELM_3 + SELS; // MCLK and SMCLK assigned to CPU and Peripheral Clock _BIS_SR(LPM3_bits - CPUOFF + GIE); P1OUT &= 0xAC; P1OUT |= 0x2C; sr164_set(0xFF, 0xFF); // sr164_set(0x00,0x00); hour = 0x00; min = 0x00; hour_base = 0; min_base = 0; i = 0; while(1){ if(ccintf==1){ ccintf=0; if(((P1IN & 0x08)==0) && (length < 3)){ length++; }else if(length > 2){ length = 0; gstate = SET_CLOCK; }else if(P1IN & 0x08){ length = 0; } if(intf>0){ if(sec & 0x0001){P1OUT &= 0xAC;} else if(~(sec & 0x0001)){P1OUT |= 0x2F;} } if(gstate == SET_CLOCK){ P1OUT |=0x2F; set_clock(); }else if((cnt_dn>0) && (sec==0)){ sr164_set(hour,min); cnt_dn--; }else if(cnt_dn == 0){ sr164_set(0xFF,0xFF); P1OUT &= 0xAC; intf=0; P1IE |= 0x0C; } } if((TAR & 0xFFFF)!=0){ TACCTL0 |= CCIE; } if(intf==1){ sr164_set(hour,min); intf = 2; } } } #pragma vector=PORT1_VECTOR __interrupt void Port_1(void){ volatile unsigned int i,j; P1IE &=~0x0C; if(~(P1IFG & 0x08)|~(P1IFG & 0x04)){ P1IFG &= ~0x0C; cnt_dn = 3; intf = 1; } } #pragma vector=TIMERA0_VECTOR __interrupt void Timer_A(void){ TACCTL0 &= ~CCIE; TACCTL0 &= ~CCIFG; if(sec<59){ sec++; }else{ sec=0; if(min_base<59){ min_base++; }else{ min_base=0; if(hour_base<23){ hour_base++; }else{ hour_base=0; } } } // sr164_set(0xFF,sec); min = ((min_base/10) * 16) + (min_base % 10); hour = ((hour_base/10) * 16) + (hour_base % 10); ccintf = 1; }