#include <MSP430x14x.h>
typedef unsigned char uchar;
typedef unsigned int uint;
//typedef也是一種宏定義類型,其書寫方式和#define相反
/*******液晶端口初始化*******/
#define out P3DIR|=BIT0+BIT1+BIT2//把P3_012三個口設(shè)為輸出
#define lcd_enset P3OUT|=BIT2
#define lcd_enclear P3OUT&=~BIT2
#define lcd_rw1 P3OUT|=BIT1
#define lcd_rw0 P3OUT&=~BIT1
#define lcd_rs1 P3OUT|=BIT0
#define lcd_rs0 P3OUT&=~BIT0
#define keyin (P1IN & 0x0f)
uchar temp,keynum=0;
int shi=23,fen=59,miao=55;//此處用char型會在按鍵調(diào)整減數(shù)到0時出錯
/**********/
/*延時子程序*/
//調(diào)用8個時鐘周期,返回6個,循環(huán)4個
//總周期個數(shù)為: 8+6+4*n=14+4*n 個時鐘周期
//默認(rèn)800k時鐘,所以周期為1.25us 公式修正:17.5+5*n=定時時間
void delay(unsigned int x)//延時
{
unsigned int i;
i=x;
for(;i>0;i--) ;
}
/******LCD寫指令程序***********/
void write_com(unsigned char com)
{ out;
P4DIR=0XFF;
P4OUT=com;
lcd_rw0;
lcd_rs0;
_NOP();
lcd_enclear;
delay(10);
lcd_enset;
delay(10);
lcd_enclear;
}
/***********LCD寫數(shù)據(jù)**************/
void write_data(unsigned char dat)
{ out;
P4DIR=0XFF;
P4OUT=dat;
lcd_rw0;
lcd_rs1;
_NOP();
_NOP();
lcd_enclear;
delay(10);
lcd_enset;
delay(10);
lcd_enclear;
}
/*****寫時分秒********/
void write_sfm(uchar add,uchar dat)
{
uchar a,b;
a=dat/10;
b=dat%10;
write_com(0x80+0x40+add);
write_data(a+0x30);
write_data(b+0x30);
}
/*********lcd初始化,寫lcd功能與方式控制********/
void lcd_init()
{ out;
write_com(0x38);
delay(20);
write_com(0x0f);
delay(20);
write_com(0x06);
delay(20);
write_com(0x0c);
delay(20);
write_com(0x01);
delay(20);
}
void Clock(void)
{
miao++;
if(miao==60)
{
miao=0;
fen++;
if(fen==60)
{
fen=0;
shi++;
if(shi==24)
{
shi=0;
}
write_sfm(2,shi);
}
write_sfm(5,fen);
}
write_sfm(8,miao);
}
void keyscan()
{
if(keyin!=0x0f)
{
delay(5); //延時消抖
if(keyin != 0x0f) //再次檢測按鍵狀態(tài)
{
temp=keyin;
while(keyin != 0x0f); //等待按鍵被放開
if(temp==0x0e)
{
keynum++;
switch(keynum)
{
case 1:
_DINT();
// CCTL0 &=~ CCIE; //兩種停止時鐘的方法效果一樣
write_com(0x80+0x40+9);
write_com(0x0f);//光標(biāo)開始閃
break;
case 2:
write_com(0x80+0x40+6);break;
case 3:
write_com(0x80+0x40+3);break;
case 4:
keynum=0;
write_com(0x0c);//開顯示,光標(biāo)不顯示
_EINT();
// CCTL0|=CCIE; //使用相應(yīng)打開時鐘的方法
break;
}
}
if(temp==0x0d)
{
// while(keyin != 0x0d); //等待按鍵被放開
switch(keynum)
{
case 1:
miao++;
if(miao==60)miao=0;
write_sfm(8,miao);
write_com(0x80+0x40+9);
break;
case 2:
fen++;
if(fen==60)fen=0;
write_sfm(5,fen);
write_com(0x80+0x40+6);
break;
case 3:
shi++;
if(shi==24)shi=0;
write_sfm(2,shi);
write_com(0x80+0x40+3);
break;
}
}
if(temp==0x0b)
{
// while(keyin != 0x0d); //等待按鍵被放開
switch(keynum)
{
case 1:
miao--;
if(miao==-1)miao=59;
write_sfm(8,miao);
write_com(0x80+0x40+9);
break;
case 2:
fen--;
if(fen==-1)fen=59;
write_sfm(5,fen);
write_com(0x80+0x40+6);
break;
case 3:
shi--;
if(shi==-1)shi=23;
write_sfm(2,shi);
write_com(0x80+0x40+3);
break;
}
}
}
}
}
int main( void )
{ P6DIR|=BIT3;
P6OUT|=BIT3;
//上兩句是打開1602的背光電源
WDTCTL = WDTPW + WDTHOLD;
lcd_init();
delay(500);
write_com(0x80+0x40+4);
write_data(':');
write_com(0x80+0x40+7);
write_data(':');
write_sfm(2,shi);
write_sfm(5,fen);
write_sfm(8,miao);
CCR0 = 32768 - 1;//設(shè)置定時器A的中斷時間為1S
TACTL = TASSEL_1 + MC_1; //計數(shù)時鐘ACLK, 增計數(shù)模式
CCTL0 |= CCIE; //使能CCR0比較中斷
_EINT();//打開全局中斷
P1DIR = 0xf0; //設(shè)置P1.0~P.3為輸入狀態(tài)
// P1DIR = BIT7; //設(shè)置P1.0~P.3為輸入狀態(tài),P1.7為輸出
// P1OUT = 0;
//以上兩句是在沒有獨立按鍵情況下把P1_7拉低成為地線
while(1)
{
keyscan();
//本程序如果加低功耗模式會使按鍵功能失效
}
}
/*******************************************
函數(shù)名稱:TimerA_ISR
功 能:定時器A的中斷服務(wù)函數(shù)
********************************************/
#pragma vector=TIMERA0_VECTOR
__interrupt void TimerA_ISR(void)
{
Clock();
}
//到此時鐘加按鍵完成