電波鐘源碼:中國碼機型的,有興趣可以拿去參考吧。改下硬件引腳就可以了
不詳細解說了,能看懂得應該都懂
單片機源程序如下:
- #include <msp430x14x.h>
- typedef unsigned char uchar;
- typedef unsigned int uint;
- #define XTOFF 0x40
- #define DataDir P4DIR
- #define DataPort P4OUT
- #define Busy 0x80
- #define CtrlDir P3DIR
- #define CLR_RS P3OUT&=~BIT0; //RS = P3.0
- #define SET_RS P3OUT|=BIT0;
- #define CLR_RW P3OUT&=~BIT1; //RW = P3.1
- #define SET_RW P3OUT|=BIT1;
- #define CLR_EN P3OUT&=~BIT2; //EN = P3.2
- #define SET_EN P3OUT|=BIT2;
- #define keyin (P2IN&0x0f)
- uint high_level[19],dattmp[19];
- uint low_level;
- uchar month,day,year,hour,min,sec,weekday;
- uchar tmp_month,tmp_day,tmp_year,tmp_hour,tmp_min,tmp_sec,tmp_weekday;
- uchar flag;
- uchar i;
- uchar PP=0;
- uchar cflag=0;
- void main_test(void);
- void Init_TimerA(void);
- void Init_TimerB(void);
- void Decode(void);
- void Display(void);
- void Delay10ms(void);
- uchar Key4Scan(void);
- void DispStr(uchar x,uchar y,uchar *ptr);
- void DispNChar(uchar x,uchar y,uchar n,uchar *ptr);
- void LocateXY(uchar x,uchar y);
- void Disp1Char(uchar x,uchar y,uchar data);
- void LcdReset(void);
- void LcdWriteCommand(uchar cmd,uchar chk);
- void LcdWriteData(uchar data);
- void WaitForEnable(void);
- void Delay5ms(void);
- void main(void)
- {
- main_test();
- }
- void main_test(void)
- {
- WDTCTL = WDTPW + WDTHOLD; //關閉看門狗
- P2DIR = 0x80;
- P2OUT = 0x00;
- LcdReset();
- Init_TimerA();
- Init_TimerB();
- while(i<19)
- ;
- while(19<=i)
- Decode();
- Display();
- while(1)
- {
- if(!cflag)
- {
- Display();
- }
- switch(Key4Scan())
- {
- case 0x01:
- switch(PP++) //確定游標地址
- {
- case 0:
- LocateXY(4,0);
- break;
- case 1:
- LocateXY(7,0);
- break;
- case 2:
- LocateXY(10,0);
- break;
- case 3:
- LocateXY(14,0);
- break;
- case 4:
- LocateXY(4,1);
- break;
- case 5:
- LocateXY(7,1);
- break;
- case 6:
- LocateXY(10,1);
- break;
- default:
- break;
- }
- LcdWriteCommand(0x0f,1);
- if(7==PP)
- PP=0;
- cflag=1; //標志置位
- break;
- case 0x02:
- if(cflag)
- {
- tmp_year=year;
- tmp_month=month;
- tmp_day=day;
-
- tmp_hour=hour;
- tmp_min=min;
- tmp_sec=sec;
-
- tmp_weekday=weekday;
-
- switch(PP)
- {
- case 0: //年
- year++;
- if(99<year)
- year=0;
- Disp1Char(3,0,year/10+48);
- Disp1Char(4,0,year%10+48);
- LocateXY(4,0);
- break;
- case 1: //月
- month++;
- if(12<month)
- month=0;
- Disp1Char(6,0,month/10+48);
- Disp1Char(7,0,month%10+48);
- LocateXY(7,0);
- break;
- case 2: //日
- day++;
- switch(month)
- {
- case 2:
- if(0==year%4)
- {
- if(29<day)
- day=1;
- }
- else
- if(28<day)
- day=1;
- break;
- case 4:
- case 6:
- case 9:
- case 11:
- if(30<day)
- day=1;
- break;
- case 1:
- case 3:
- case 5:
- case 7:
- case 8:
- case 10:
- case 12:
- if(31<day)
- day=1;
- default:
- break;
- }
- Disp1Char(9,0,day/10+48);
- Disp1Char(10,0,day%10+48);
- LocateXY(10,0);
- break;
- case 3: //weekday
- weekday++;
- if(7<weekday)
- weekday=1;
- switch(weekday)
- {
- case 1:
- Disp1Char(12,1,'M');
- Disp1Char(13,1,'o');
- Disp1Char(14,1,'n');
- break;
- case 2:
- Disp1Char(12,1,'T');
- Disp1Char(13,1,'u');
- Disp1Char(14,1,'e');
- break;
- case 3:
- Disp1Char(12,1,'W');
- Disp1Char(13,1,'e');
- Disp1Char(14,1,'d');
- break;
- case 4:
- Disp1Char(12,1,'T');
- Disp1Char(13,1,'h');
- Disp1Char(14,1,'u');
- break;
- case 5:
- Disp1Char(12,1,'F');
- Disp1Char(13,1,'r');
- Disp1Char(14,1,'i');
- break;
- case 6:
- Disp1Char(12,1,'S');
- Disp1Char(13,1,'a');
- Disp1Char(14,1,'t');
- break;
- case 7:
- Disp1Char(12,1,'S');
- Disp1Char(13,1,'u');
- Disp1Char(14,1,'n');
- break;
- default:
- break;
- }
- LocateXY(14,0);
- break;
- case 4: //時
- hour++;
- if(24<hour)
- hour=0;
- Disp1Char(3,1,hour/10+48);
- Disp1Char(4,1,hour%10+48);
- LocateXY(4,1);
- break;
- case 5: //分
- min++;
- if(60<min)
- min=0;
- Disp1Char(6,1,min/10+48);
- Disp1Char(7,1,min%10+48);
- LocateXY(7,1);
- break;
- case 6: //時
- sec++;
- if(60<sec)
- sec=0;
- Disp1Char(9,1,sec/10+48);
- Disp1Char(10,1,sec%10+48);
- LocateXY(10,1);
- break;
- default:
- break;
- }
- }
- break;
- case 0x03:
- if(cflag)
- {
- cflag = 0;
- PP = 0;
-
- year=tmp_year;
- month=tmp_month;
- day=tmp_day;
-
- hour=tmp_hour;
- min=tmp_min;
- sec=tmp_sec;
-
- weekday=tmp_weekday;
-
- Display();
- LcdWriteCommand(0x0c,1);
- }
- break;
- case 0x04:
- if(cflag)
- {
- cflag = 0;
- PP = 0;
- LcdWriteCommand(0x0c, 1); //關閉游標
- }
- break;
- default:
- break;
- }
- }
- }
- void Init_TimerA(void)
- {
- P1SEL|=BIT2; //set the port 1.2 to pulse-capture mode.
- TACTL=TASSEL0+MC1+TACLR+TAIE; //Timer A clock source:ACLK | continuous mode | clear the Timer A | enable the Timer A.
- CCTL1=CCIE+CM0+SCS+CAP; //enable the interrupt | capture mode | rising edge capture | synchronize capture source.
- }
- void Init_TimerB(void)
- {
- /*
- BCSCTL1&=~XT2OFF;
- BCSCTL2=SELS+DIVS1+DIVS0;
- TBCTL=0x02d4;
- CCTL0=CCIE;
- CCR0=62500;
- _EINT();
- */
- TBCTL=TBSSEL0+TBCLR;
- CCR0=32767;
- TBCTL|=MC0;
- CCTL0=CCIE;
- }
- void Decode(void)
- {
- uchar ii;
- //while(1) //keep decoding.
- //{
- if(19<=i) //decode the value if the array is filled.
- {
- i=0;
- for(ii=0;ii<19-flag;ii++) //set the former data number of high_level array.
- dattmp[ii]=high_level[flag+ii];
- for(ii=0;ii<flag;ii++) //set the latter data number of high_level array.
- dattmp[19-flag+ii]=high_level[ii];
- for(ii=0;ii<19;ii++) //reset the value of the dattmp array.
- {
- if(1638<dattmp[ii]&&dattmp[ii]<4915) //5%--15%
- dattmp[ii]=0;
- else if(4915<dattmp[ii]&&dattmp[ii]<8192) //15%--25%
- dattmp[ii]=1;
- else if(8192<dattmp[ii]&&dattmp[ii]<11468) //25%--35%
- dattmp[ii]=2;
- else if(11468<dattmp[ii]&&dattmp[ii]<14765) //35%--45%
- dattmp[ii]=3;
- }
-
- year=dattmp[15]*16+dattmp[16]*4+dattmp[17];
- month=dattmp[13]*4+dattmp[14];
- day=dattmp[10]*16+dattmp[11]*4+dattmp[12];
-
- hour=dattmp[2]*4+dattmp[3];
- min=dattmp[4]*16+dattmp[5]*4+dattmp[6];
- sec=dattmp[0]*20+20-flag;
-
- weekday=dattmp[7]*4+dattmp[8];
-
- flag=0;
-
- if(2==dattmp[9]||3==dattmp[9])
- hour+=12;
- if(59<sec)
- {
- sec=0;
- min++;
- if(59<min)
- {
- min=0;
- hour++;
- if(11<hour)
- hour=0;
- }
- }
- }
- //}
- }
- //type: Timer A interrupt service routine.
- //purpose: get the high level pulse width,provide frame information for the function Decode.
- //version: 1.0 by chen on 9/4/2014.
- #pragma vector=TIMERA0_VECTOR
- __interrupt void TimerA_ISR(void)
- {
- switch(TAIV)
- {
- case 2: //use 0x01==TAIV here for the consideration of the low frequency of watch oscillator.
- if(CCTL1&CM0) //rising edge capture.
- {
- low_level=TAR; //get the low level width to judge the frame flag.
- TACTL|=TACLR; //restart the counter to provide a pure origin for the high level width recording.
- CCTL1=(CCTL1&(~CM0))|CM1; //switch the capture mode to falling edge capture.
- }
- else
- if(CCTL1&CM1) //falling edge capture.
- {
- high_level[ i]=TAR; //record the value of the high level width.[ i]
- i++;
- TACTL|=TACLR; //restart the counter to provide a pure origin for the low level width recording.
- CCTL1=(CCTL1&(~CM1))|CM0; //switch the capture mode to rising edge capture.
- }
- break;
- default:
- break;
- }
- if(4915<low_level) //resort the high_level array by the frame flag.
- flag=i; //locate the frame flag position.
- }
- //type: Timer B interrupt service routine.
- //purpose: provide a pulse for the main clock frequency per second.
- //version: 1.0 by chen on 9/4/2014.
- #pragma vector=TIMERB0_VECTOR
- __interrupt void Timer_B(void)
- {
- sec++;
- if(59<sec)
- {
- sec=0;
- min++;
- if(59<min)
- {
- min=0;
- hour++;
- if(23<hour)
- hour=0;
- }
- }
- if(cflag)
- {
- tmp_sec++;
- if(59<sec)
- {
- tmp_sec=0;
- tmp_min++;
- if(59<tmp_min)
- {
- tmp_min=0;
- tmp_hour++;
- if(23<tmp_hour)
- tmp_hour=0;
- }
- }
- }
- }
- void Display(void)
- {
- Disp1Char(1,0,'2');
- Disp1Char(2,0,'0');
- Disp1Char(3,0,year/10+48);
- Disp1Char(4,0,year%10+48);
- Disp1Char(5,0,'-');
- Disp1Char(6,0,month/10+48);
- Disp1Char(7,0,month%10+48);
- Disp1Char(8,0,'-');
- Disp1Char(9,0,day/10+48);
- Disp1Char(10,0,day%10+48);
-
- Disp1Char(3,1,hour/10+48);
- Disp1Char(4,1,hour%10+48);
- Disp1Char(5,1,'-');
- Disp1Char(6,1,min/10+48);
- Disp1Char(7,1,min%10+48);
- Disp1Char(8,1,'-');
- Disp1Char(9,1,sec/10+48);
- Disp1Char(10,1,sec%10+48);
- switch(weekday)
- {
- case 1:
- Disp1Char(12,1,'M');
- Disp1Char(13,1,'o');
- Disp1Char(14,1,'n');
- break;
- case 2:
- Disp1Char(12,1,'T');
- Disp1Char(13,1,'u');
- Disp1Char(14,1,'e');
- break;
- case 3:
- Disp1Char(12,1,'W');
- Disp1Char(13,1,'e');
- Disp1Char(14,1,'d');
- break;
- case 4:
- Disp1Char(12,1,'T');
- Disp1Char(13,1,'h');
- Disp1Char(14,1,'u');
- break;
- case 5:
- Disp1Char(12,1,'F');
- Disp1Char(13,1,'r');
- Disp1Char(14,1,'i');
- break;
- case 6:
- Disp1Char(12,1,'S');
- Disp1Char(13,1,'a');
- Disp1Char(14,1,'t');
- break;
- case 7:
- Disp1Char(12,1,'S');
- Disp1Char(13,1,'u');
- Disp1Char(14,1,'n');
- break;
- default:
- break;
- }
- }
- //explanation: following functions are the display effect function for the LCD 1602.
- void DispStr(uchar x,uchar y,uchar *ptr)
- {
- uchar *temp;
- uchar i,n=0;
- temp=ptr;
- while(*ptr++ != '\0')
- n++; //計算字符串有效字符的個數
- for (i=0;i<n;i++)
- {
- Disp1Char(x++,y,temp[ i]);[ i]
- if (x == 0x0f)
- {
- x = 0;
- y ^= 1;
- }
- }
- }
- void DispNChar(uchar x,uchar y,uchar n,uchar *ptr)
- {
- uchar i;
- for (i=0;i<n;i++)
- {
- Disp1Char(x++,y,ptr[ i]);[ i]
- if (x==0x0f)
- {
- x=0;
- y^=1;
- }
- }
- }
- void LocateXY(uchar x,uchar y)
- {
- uchar temp;
- temp=x&0x0f;
- y&=0x01;
- if(y)
- temp|=0x40; //如果在第2行
- temp|=0x80;
- LcdWriteCommand(temp,1);
- }
- void Disp1Char(uchar x,uchar y,uchar data)
- {
- LocateXY(x,y);
- LcdWriteData(data);
- }
- void LcdReset(void)
- {
- CtrlDir|=0x07; //控制線端口設為輸出狀態
- DataDir=0xFF; //數據端口設為輸出狀態
- LcdWriteCommand(0x38, 0); //規定的復位操作
- Delay5ms();
- LcdWriteCommand(0x38, 0);
- Delay5ms();
- LcdWriteCommand(0x38, 0);
- Delay5ms();
- LcdWriteCommand(0x38, 1); //顯示模式設置
- LcdWriteCommand(0x08, 1); //顯示關閉
- LcdWriteCommand(0x01, 1); //顯示清屏
- LcdWriteCommand(0x06, 1); //寫字符時整體不移動
- LcdWriteCommand(0x0c, 1); //顯示開,不開游標,不閃爍
- }
- void LcdWriteCommand(uchar cmd,uchar chk)
- {
- if(chk)
- WaitForEnable(); // 檢測忙信號?
- CLR_RS;
- CLR_RW;
- _NOP();
- DataPort=cmd; //將命令字寫入數據端口
- _NOP();
- SET_EN; //產生使能脈沖信號
- _NOP();
- _NOP();
- CLR_EN;
- }
- void LcdWriteData(uchar data)
- {
- WaitForEnable(); //等待液晶不忙
- SET_RS;
- CLR_RW;
- _NOP();
- DataPort = data; //將顯示數據寫入數據端口
- _NOP();
- SET_EN; //產生使能脈沖信號
- _NOP();
- _NOP();
- CLR_EN;
- }
- void WaitForEnable(void)
- {
- P4DIR&=0x00; //將P4口切換為輸入狀態
- CLR_RS;
- SET_RW;
- _NOP();
- SET_EN;
- _NOP();
- _NOP();
- while((P4IN&Busy)!=0); //檢測忙標志
- CLR_EN;
- P4DIR |= 0xFF; //將P4口切換為輸出狀態
- }
-
- void Delay5ms(void)
- {
- uint tmp=40000;
- while (tmp!=0)
- {
- tmp--;
- }
- }
- void Delay10ms(void)
- {
- uint tmp;
- for(tmp=0x3fff;tmp>0;tmp--)
- ;
- }
- uchar Key4Scan(void)
- {
- uchar temp,keyval;
- if(keyin!=0x0f)
- {
- Delay10ms();
- keyval=0;
- if(keyin!=0x0f)
- {
- temp=keyin;
- while(keyin!=0x0f)
- ;
- switch(temp)
- {
- case 0x0e:
- keyval=1;
- break;
- case 0x0d:
- keyval=2;
- break;
- case 0x0b:
- keyval=3;
- break;
- case 0x07:
- keyval=4;
- break;
- default:
- keyval=0;
- break;
- }
- }
- }
- else
- keyval = 0;
- return keyval;
- }
復制代碼
|