昨年製作して、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;
}