|
- #include<reg52.h>
- #define uchar unsigned char
- #define uint unsigned int
- sbit lcden=P3^4; //液晶使能端
- sbit rs=P3^5; //液晶數據命令選擇端
- sbit led=P2^5; //控制LED的鎖存器
- sbit dula=P2^6; //控制LCD的段鎖存器
- sbit wela=P2^7; //控制LCD的位鎖存器
- sbit dsirq=P3^2; //DS12887的中斷請求端
- sbit dsds=P1^7; //DS12887的讀允許輸入端
- sbit dsrw=P1^6; //DS12887的寫允許輸入端
- sbit dsas=P1^5; //DS12887的地址選通端
- sbit dscs=P1^4; //DS12887的芯片片選端
- sbit a=P3^0; //設置鍵盤用的
- sbit b=P3^1; //設置鍵盤用的
- sbit c=P3^6; //設置鍵盤用的
- sbit d=P3^7; //設置鍵盤用的
- sbit e=P3^3; //設置鍵盤用的
- uchar code table1[]=" 2000-00-00 ";
- uchar code table2[]=" 00:00:00 ";
- uchar flag1,flag2,temp,temp1;
- /*
- falg1標志位是用來判斷是否執行從DS12C887中讀取數據并送去液晶顯示;
- flag2標志位是用來判斷LCD上顯示的年數是否是閏年;
- temp與temp1都時當月的天數值,用來判斷DS12C887中的天數值是否大
- 于當月應有的天數,如大于則將天數值置1,如有需要請重新設置天數值。
- */
- char miao,fen,nian,yue,ri,xingqi;
- int shi; //小時的數值大于128,所以不能選擇char型數據
- /*------------
- 延時子程序
- */
- void delayms(uchar a)
- {
- uchar x,y;
- for(x=a;x>0;x--)
- for(y=110;y>0;y--);
- }
- /*----------------
- 往液晶中寫指令
- ----------------*/
- void write_com(uchar com)
- {
- rs=0; //選擇寫命令模式
- lcden=0; //將lcden置為零
- P0=com; //將要寫的命令字送到數據總線上
- delayms(5); //稍做延時以待數據穩定
- lcden=1; //使能端給一個高脈沖
- delayms(5); //稍做延時
- lcden=0; //將使能端置0以完成高脈沖
- }
- /*----------------
- 往液晶中寫數據
- ----------------*/
- void write_date(uchar date)
- {
- rs=1; //選擇寫數據模式
- lcden=0; //將lcden置為零
- P0=date; //將要寫的數據送到數據總線上
- delayms(5); //稍做延時以待數據穩定
- lcden=1; //使能端給一個高脈沖
- delayms(5); //稍做延時
- lcden=0; //將使能端置0以完成高脈沖
- }
- /*--------------------
- 向DS12C887內寫數據
- --------------------*/
- void write_ds(uchar add,uchar date)
- {
- dscs=0;
- dsas=1;
- dsds=1;
- dsrw=1;
- P0=add; //先寫地址
- dsas=0;
- dsrw=0;
- P0=date; //再寫數據
- dsrw=1;
- dsas=1;
- dscs=1;
- }
- /*--------------------
- 從DS12C887中讀數據
- --------------------*/
- uchar read_ds(uchar add)
- {
- uchar temp;
- dscs=0;
- dsas=1;
- dsds=1;
- dsrw=1;
- P0=add; //先寫地址
- dsas=0;
- dsds=0;
- P0=0xff; //讀數據之前先將P0口置一
- temp=P0; //再讀數據
- dsds=1;
- dsas=1;
- dscs=1;
- return temp;
- }
- /*----------------------------------------------------------------------
- 24小時制在液晶的指定位置寫入時分秒,12小時制在液晶的指定位置寫入分秒
- ----------------------------------------------------------------------*/
- void write_sfm(uchar add,uchar date)
- {
- uchar shi,ge;
- shi=date/10; //分解一個2位數的十位和個位
- ge=date%10;
- write_com(0x80+0x40+add); //設置顯示位置
- write_date(shi+0x30); //送去液晶顯示十位
- write_date(ge+0x30); //送去液晶顯示個位
- }
- /*----------------------------
- 在液晶的指定位置寫入年月日
- ----------------------------*/
- void write_nyr(uchar add,uchar date)
- {
- uchar shi,ge;
- shi=date/10; //分解一個2位數的十位和個位
- ge=date%10;
- write_com(0x80+add); //設置顯示位置
- write_date(shi+0x30); //送去液晶顯示十位
- write_date(ge+0x30); //送去液晶顯示個位
- }
- /*----------------------------
- 在液晶的指定位置寫入星期
- ----------------------------*/
- void write_xq(uchar date)
- {
- uchar i;
- i=date;
- write_com(0x80+12);
- switch(i) //switch-case語句判斷i的值及執行相應的操作
- {
- case 1: //當i等于1時,送去液晶顯示MON(星期一)
- write_date('M');
- write_date('O');
- write_date('N');
- break;
- case 2: //當i等于2時,送去液晶顯示TUE(星期二)
- write_date('T');
- write_date('U');
- write_date('E');
- break;
- case 3: //當i等于3時,送去液晶顯示WED(星期三)
- write_date('W');
- write_date('E');
- write_date('D');
- break;
- case 4: //當i等于4時,送去液晶顯示THU(星期四)
- write_date('T');
- write_date('H');
- write_date('U');
- break;
- case 5: //當i等于5時,送去液晶顯示FRI(星期五)
- write_date('F');
- write_date('R');
- write_date('I');
- break;
- case 6: //當i等于6時,送去液晶顯示SAT(星期六)
- write_date('S');
- write_date('A');
- write_date('T');
- break;
- case 7: //當i等于7時,送去液晶顯示SUN(星期日)
- write_date('S');
- write_date('U');
- write_date('N');
- break;
- }
- }
- /*----------------
- 判斷天數的函數
- ----------------*/
- char day_num(char nian,char yue)
- {
- char num;
- if(((nian%4==0)&&(nian%100!=0))||((nian%100==0)&&(nian%400==0))) //閏年判斷
- flag2=1;
- else
- flag2=0;
- if(flag2==1) //是閏年時,將第二月的天數設為29
- {
- switch(yue)
- {
- case 1:
- num=31; //1月的天數
- break;
- case 2:
- num=29; //2月的天數
- break;
- case 3:
- num=31; //3月的天數
- break;
- case 4:
- num=30; //4月的天數
- break;
- case 5:
- num=31; //5月的天數
- break;
- case 6:
- num=30; //6月的天數
- break;
- case 7:
- num=31; //7月的天數
- break;
- case 8:
- num=31; //8月的天數
- break;
- case 9:
- num=30; //9月的天數
- break;
- case 10:
- num=31; //10月的天數
- break;
- case 11:
- num=30; //11月的天數
- break;
- case 12:
- num=31; //12月的天數
- break;
- }
- }
- if(flag2==0) //不是閏年時,將第二月的天數設為28
- {
- switch(yue)
- {
- case 1:
- num=31; //1月的天數
- break;
- case 2:
- num=28; //2月的天數
- break;
- case 3:
- num=31; //3月的天數
- break;
- case 4:
- num=30; //4月的天數
- break;
- case 5:
- num=31; //5月的天數
- break;
- case 6:
- num=30; //6月的天數
- break;
- case 7:
- num=31; //7月的天數
- break;
- case 8:
- num=31; //8月的天數
- break;
- case 9:
- num=30; //9月的天數
- break;
- case 10:
- num=31; //10月的天數
- break;
- case 11:
- num=30; //11月的天數
- break;
- case 12:
- num=31; //12月的天數
- break;
- }
- }
- return num; //函數的返回值時當月的天數
- }
- /*--------------
- 鍵盤掃描程序
- --------------*/
- void keyscan()
- {
- uchar num;
- a=0; //設置矩陣鍵盤S1低電平
- b=1; //設置矩陣鍵盤S2高電平
- if(c==0) //判斷S3有沒有被按下
- {
- delayms(5); //去抖延時
- if(c==0) //判斷S3有沒有被按下
- {
- while(!c); //判斷按鍵S3有沒有釋放
- num++; //按下鍵的次數
- flag1=1; //標志位flag1置一
- if(num==1) //當num等于1時,光標在秒鐘處閃爍
- {
- write_com(0x80+0x40+8);
- write_com(0x0f);
- }
- if(num==2) //當num等于2時,光標在分鐘處閃爍
- {
- write_com(0x80+0x40+5);
- write_com(0x0f);
- }
- if(num==3) //當num等于3時,光標在時鐘處閃爍
- {
- write_com(0x80+0x40+2);
- write_com(0x0f);
- }
- if(num==4) //當num等于4時,光標在年處閃爍
- {
- write_com(0x80+4);
- write_com(0x0f);
- }
- if(num==5) //當num等于5時,光標在月處閃爍
- {
- write_com(0x80+7);
- write_com(0x0f);
- }
- if(num==6) //當num等于6時,光標在日處閃爍
- {
- write_com(0x80+10);
- write_com(0x0f);
- }
- if(num==7) //當num等于7時,光標在星期處閃爍
- {
- write_com(0x80+14);
- write_com(0x0f);
- }
- if(num==8)
- {
- num=0; //num清0
- write_ds(0x00,miao); //將秒寫入DS12C887
- write_ds(0x02,fen); //將分寫入DS12C887
- write_ds(0x04,shi); //將時寫入DS12C887
- write_ds(0x06,xingqi); //將星期寫入DS12C887
- write_ds(0x07,ri); //將日寫入DS12C887
- write_ds(0x08,yue); //將月寫入DS12C887
- write_ds(0x09,nian); //將年寫入DS12C887
- flag1=0; //標志位flag1清0
- }
- }
- }
- if(num!=0) //當功能鍵S3按下后,數值增大鍵S4才有用
- {
- a=0; //設置矩陣鍵盤第一排位低電平
- b=1; //設置矩陣鍵盤第二排位高電平
- if(d==0) //判斷S4有沒有被按下
- {
- delayms(5); //去抖延時
- if(d==0) //判斷S4有沒有被按下
- {
- while(!d); //判斷按鍵S4有沒有釋放
- if(num==1)
- {
- miao++; //當num=1時,秒值加一
- if(miao>59) //當秒值大于59時,將秒值置0
- miao=0;
- write_sfm(7,miao); //將秒值寫入液晶顯示
- write_com(0x80+0x40+8); //光標在秒值的個位閃爍
- write_com(0x0f);
- }
- if(num==2)
- {
- fen++; //當num=2時,分值加一??
- if(fen>59) //當分值大于59時,將分值置0
- fen=0;
- write_sfm(4,fen); //將分值寫入液晶顯示
- write_com(0x80+0x40+5); //光標在分值的個位閃爍
- write_com(0x0f);
- }
- if(num==3)
- {
- shi++; //當num=3時,時鐘加一?
- if(shi>23) //當時鐘大于23時,將時鐘置0
- shi=0;
- write_sfm(1,shi); //將時鐘寫入液晶顯示
- write_com(0x80+0x40+2); //光標在時鐘的個位閃爍
- write_com(0x0f);
- }
- if(num==4)
- {
- nian++; //當num=4時,年加一
- if(nian>99) //當年大于99時,將年置0
- nian=0;
- write_nyr(3,nian); //將年寫入液晶顯示
- write_com(0x80+4); //光標在年的個位閃爍
- write_com(0x0f);
- }
- if(num==5)
- {
- yue++; //當num=5時,月加一
- if(yue>12) //當月大于12時,將月置1
- yue=1;
- write_nyr(6,yue); //將月寫入液晶顯示
- write_com(0x80+7); //光標在月的個位閃爍
- write_com(0x0f);
- }
- if(num==6)
- {
- ri++; //當num=6時,日加一
- temp=day_num(nian,yue);
- if(ri>temp) //當日大于當月的天數時,將日置1
- ri=1;
- write_nyr(9,ri); //將日寫入液晶顯示
- write_com(0x80+10); //光標在月的個位閃爍
- write_com(0x0f);
- }
- if(num==7)
- {
- xingqi++; //當num=7時,星期加一
- if(xingqi>7) //當星期大于7時,將星期置1
- xingqi=1;
- write_xq(xingqi); //將星期寫入液晶顯示
- write_com(0x80+14); //光標在星期的個位閃爍
- write_com(0x0f);
- }
- }
- }
- }
- if(num!=0) //當功能鍵S3按下后,數值減小鍵S5才有用
- {
- a=1; //設置矩陣鍵盤第一排位高電平
- b=0; //設置矩陣鍵盤第二排位低電平
- if(e==0) //判斷S5有沒有被按下
- {
- delayms(5); //去抖延時
- if(e==0) //判斷S5有沒有被按下
- {
- while(!e); //判斷按鍵S5有沒有釋放
- if(num==1)
- {
- miao--; //當num=1時,秒值減一
- if(miao<0) //當秒值小于0時,將秒值置59
- miao=59;
- write_sfm(7,miao); //將秒值寫入液晶顯示
- write_com(0x80+0x40+8); //光標在秒值的個位閃爍
- write_com(0x0f);
- }
- if(num==2)
- {
- fen--; //當num=2時,分值減一
- if(fen<0) //當分值小于0時,將分值置59
- fen=59;
- write_sfm(4,fen); //將分值寫入液晶顯示
- write_com(0x80+0x40+5); //光標在分值的個位閃爍
- write_com(0x0f);
- }
- if(num==3)
- {
- shi--; //當num=3時,時鐘減一
- if(shi<0) //當時鐘小于0時,將時鐘置23
- shi=23;
- write_sfm(1,shi); //將時鐘寫入液晶顯示
- write_com(0x80+0x40+2); //光標在時鐘的個位閃爍
- write_com(0x0f);
- }
- if(num==4)
- {
- nian--; //當num=4時,年減一
- if(nian<0) //當年小于0時,將年置99
- nian=99;
- write_nyr(3,nian); //將年寫入液晶顯示
- write_com(0x80+4); //光標在年的個位閃爍
- write_com(0x0f);
- }
- if(num==5)
- {
- yue--; //當num=5時,月減一
- if(yue<1) //當月小于1時,將月置12
- yue=12;
- write_nyr(6,yue); //將月寫入液晶顯示
- write_com(0x80+7); //光標在月的個位閃爍
- write_com(0x0f);
- }
- if(num==6)
- {
- ri--; //當num=6時,日減一
- temp=day_num(nian,yue);
- if(ri>temp)
- ri=temp;
- if(ri<1) //當日小于1時,將日置為當月的天數
- ri=temp;
- write_nyr(9,ri); //將日寫入液晶顯示
- write_com(0x80+10); //光標在月的個位閃爍
- write_com(0x0f);
- }
- if(num==7)
- {
- xingqi--; //當num=7時,星期加一
- if(xingqi<1) //當星期小于1時,將星期置7
- xingqi=7;
- write_xq(xingqi); //將星期寫入液晶顯示
- write_com(0x80+14); //光標在星期的個位閃爍
- write_com(0x0f);
- }
- }
- }
- }
- }
- /*--------------
- ? 初始化時鐘函數
- --------------*/
- void set_time()
- {
- write_ds(0,0); //初始化時鐘秒鐘的數值為0
- write_ds(2,0); //初始化時鐘分鐘的數值為0
- write_ds(4,1); //初始化時鐘小時的數值為1
- write_ds(6,1); //初始化時鐘星期的數值為1
- write_ds(7,1); //初始化時鐘日的數值為1
- write_ds(8,1); //初始化時鐘月的數值為1
- write_ds(9,0); //初始化時鐘年的數值為0
- }
- /*------------
- ? 初始化程序
- ------------*/
- void init()
- {
- uchar i;
- dula=0; //關段鎖存器(不讓數碼管顯示)
- wela=0; //關位鎖存器
- lcden=0;
- write_com(0x38); //設置16*2顯示,5*7點陣,8位數據接口(LCD初始化設置)
- write_com(0x0c); //設置開顯示,不顯示光標(LCD初始化設置)
- write_com(0x06); //寫一個字符后地址指針自動加一(LCD初始化設置)
- write_com(0x01); //顯示清零,數據指針清零(LCD初始化設置)
- write_com(0x80); //將數據指針定位到第一行第一字處
- for(i=0;i<16;i++)
- {
- write_date(table1[i]); //將字符串1寫入液晶
- }
- write_com(0x80+0x40); //將數據指針定位到第2行第1字處
- for(i=0;i<16;i++)
- {
- write_date(table2[i]); //將字符串2寫入液晶
- }
- set_time(); //初始化時鐘
- }
- void main()
- {
- init(); //調用初始化子程序
- while(1)
- {
- keyscan();
- if(flag1==0) //當標志位flag1等于0時,才從DS12C887中讀取數據并送去液晶顯示
- {
- miao=read_ds(0); //從DS12C887中讀取秒的值
- write_sfm(7,miao); //將秒值送去液晶顯示
- fen=read_ds(0x02); //從DS12C887中讀取分的值
- write_sfm(4,fen); //將分值送去液晶顯示
- shi=read_ds(0x04); //從DS12C887中讀取小時的值
- write_sfm(1,shi); //將小時送去液晶顯示
- nian=read_ds(0x09); //從DS12C887中讀取年的值
- write_nyr(3,nian); //將年值送去液晶顯示
- yue=read_ds(0x08); //從DS12C887中讀取月份的值
- write_nyr(6,yue); //將月份送去液晶顯示
- ri=read_ds(0x07); //從DS12C887中讀取日的值
- temp1=day_num(nian,yue); //讀取當月的天數值
- if(ri>temp1) //判斷DS12C887中的天數值是否大于當月應有的天數,如大于則將天數值置1,如有需要請重新設置
- ri=1;
- write_nyr(9,ri); //將日值送去液晶顯示
- xingqi=read_ds(0x06); //從DS12C887中讀取星期的值
- write_xq(xingqi); //將星期送去液晶顯示
- }
- }
- }
復制代碼
|
評分
-
查看全部評分
|