|
用了兩天時(shí)間做了這個(gè)仿真,時(shí)鐘計(jì)時(shí)(年月日時(shí)分秒)使用DS1302實(shí)現(xiàn),計(jì)時(shí)范圍2000年1月1日0時(shí)0分0秒~2099年12月31日23時(shí)59分59秒,上電初始顯示時(shí)間2000年1月1日0時(shí)0分0秒,通過(guò)三個(gè)按鍵實(shí)現(xiàn)時(shí)間修改。按下K1按鍵來(lái)依次選中需要修改的時(shí)間項(xiàng)(年月日時(shí)分秒),此時(shí)被選中的時(shí)間項(xiàng)將閃爍顯示,然后可以通過(guò)K2和K3按鍵分別進(jìn)行數(shù)值加1和減1,再按下K1切換到下一時(shí)間項(xiàng),一直到切換到時(shí)間項(xiàng)“秒”后按下K1即推出時(shí)間修改,LCD1602顯示繼續(xù)走時(shí)。
當(dāng)某個(gè)時(shí)間項(xiàng)的數(shù)值加到最大時(shí),再按K2鍵加,則到最小值,(例如“年”加到99,再加則到00);
當(dāng)某個(gè)時(shí)間項(xiàng)的數(shù)值減到最小時(shí),再按K3鍵減,則到最大值,(例如“時(shí)”減到00,再減則到23)。
(閏年平年2月份的天數(shù)“日”的調(diào)整正常,例如2040年(閏年),則該年的2月份的日數(shù)最大加到29,再加,則到1;2041年(平年)的2月份的日數(shù)最大加到28,再加,則到1)
仿真原理圖如下(proteus仿真工程文件可到本帖附件中下載)
51hei.gif (208.04 KB, 下載次數(shù): 77)
下載附件
2022-1-20 17:22 上傳
仿真概覽.png (59.1 KB, 下載次數(shù): 75)
下載附件
仿真概覽
2022-1-20 11:22 上傳
單片機(jī)源程序如下:
- #include<reg52.h>
- #include<intrins.h>
- sbit RST=P1^3;
- sbit CLK=P1^4;
- sbit IO=P1^5;
- sbit RS=P2^5;
- sbit RW=P2^6;
- sbit E=P2^7;
- sbit K1=P3^4; //時(shí)間(修改)選擇
- sbit K2=P3^5; //時(shí)間“加”
- sbit K3=P3^6; //時(shí)間“減”
- unsigned char second,minute,hour,day,month,year; //在LCD1602上顯示的數(shù)值
- unsigned char temp_s,temp_min,temp_h,temp_d,temp_mon,temp_y; //暫存從DS1302讀出的數(shù)據(jù)
- unsigned char x=0; //選擇修改時(shí)間中的某一個(gè)數(shù)值
- void Delay()
- {
- _nop_();
- }
- void Write_Bit_DS1302(unsigned char DAT) //向DS1302寫(xiě)入一字節(jié)的數(shù)據(jù)
- {
- unsigned char i;
- CLK=0;
- Delay();
- for(i=0;i<8;i++)
- {
- IO=DAT&0x01; //低位在前,高位在后
- Delay();
- CLK=1; //時(shí)鐘信號(hào)上升沿,寫(xiě)入數(shù)據(jù)
- Delay();
- CLK=0; //重新拉低CLK,形成脈沖
- DAT>>=1; //將DAT的各數(shù)據(jù)位右移1位,準(zhǔn)備寫(xiě)入下一數(shù)據(jù)位
- }
- }
- void Write_DS1302(unsigned char CMD,unsigned char DAT) //向DS1302寫(xiě)入命令和數(shù)據(jù)
- {
- RST=0; //禁止數(shù)據(jù)傳輸
- CLK=0; //在寫(xiě)入數(shù)據(jù)前確保CLK置低電平
- RST=1; //開(kāi)始數(shù)據(jù)傳輸
- Delay();
- Write_Bit_DS1302(CMD); //寫(xiě)入命令
- Write_Bit_DS1302(DAT); //寫(xiě)入數(shù)據(jù)
- CLK=1;
- RST=0;
- }
- unsigned char Read_Bit_DS1302() //從DS1302讀出一字節(jié)的數(shù)據(jù)
- {
- unsigned char i,DAT;
- Delay();
- for(i=0;i<8;i++)
- {
- DAT>>=1;
- if(IO==1)
- {
- DAT|=0x80;
- }
- CLK=1;
- Delay();
- CLK=0; //時(shí)鐘信號(hào)下降沿,讀出數(shù)據(jù)
- Delay();
- }
- return DAT;
- }
- unsigned char Read_DS1302(unsigned char CMD) //向DS1302寫(xiě)入命令后再?gòu)腄S1302讀出數(shù)據(jù)
- {
- unsigned char DAT;
- RST=0;
- CLK=0;
- RST=1;
- Write_Bit_DS1302(CMD); //寫(xiě)入命令
- DAT=Read_Bit_DS1302(); //讀出數(shù)據(jù)
- CLK=1;
- RST=0;
- return DAT;
- }
- void Init_DS1302() //DS1302初始化
- {
- Write_DS1302(0x8E,0x00); //允許將數(shù)據(jù)寫(xiě)入DS1302的寄存器
- Write_DS1302(0x80,((0/10)<<4)+(0%10)); //寫(xiě)入“秒”的初始值,需要將LCD1602顯示的數(shù)值轉(zhuǎn)換成BCD碼
- Write_DS1302(0x82,((0/10)<<4)+(0%10)); //寫(xiě)入“分”的初始值
- Write_DS1302(0x84,((0/10)<<4)+(0%10)); //寫(xiě)入“時(shí)”的初始值
- Write_DS1302(0x86,((1/10)<<4)+(1%10)); //寫(xiě)入“日”的初始值
- Write_DS1302(0x88,((1/10)<<4)+(1%10)); //寫(xiě)入“月”的初始值
- Write_DS1302(0x8C,((0/10)<<4)+(0%10)); //寫(xiě)入“年”的初始值
- }
- void Delay5ms()
- {
- unsigned char i,j;
- _nop_();
- i=10;
- j=183;
- do
- {
- while(--j);
- }
- while(--i);
- }
- int LCD1602_ReadBusy() //LCD1602“讀忙”操作
- {
- int temp;
- RS=0;
- RW=1;
- _nop_();
- P0=0xff;
- _nop_();
- E=1;
- _nop_();
- temp=P0;
- _nop_();
- E=0;
- return(temp&0x80);
- }
- void LCD1602_Write_Com(char com) //LCD1602“寫(xiě)命令”操作
- {
- while(LCD1602_ReadBusy());
- RS=0;
- RW=0;
- E=0;
- _nop_();
- P0=com;
- _nop_();
- E=1;
- Delay5ms();
- E=0;
- Delay5ms();
- }
- void LCD1602_Write_Dat(char dat) //LCD1602“寫(xiě)數(shù)據(jù)”操作
- {
- while(LCD1602_ReadBusy());
- RS=1;
- RW=0;
- E=0;
- _nop_();
- P0=dat;
- _nop_();
- E=1;
- Delay5ms();
- E=0;
- Delay5ms();
- }
- void LCD1602_Init() //LCD1602初始化
- {
- Delay5ms();
- Delay5ms();
- Delay5ms();
- LCD1602_Write_Com(0x38);
- Delay5ms();
- LCD1602_Write_Com(0x0C);
- Delay5ms();
- LCD1602_Write_Com(0x06);
- Delay5ms();
- LCD1602_Write_Com(0x01);
- Delay5ms();
- }
- void LCD1602_Display_Init() //在LCD1602的恒定位置上顯示恒定的字符
- {
- LCD1602_Write_Com(0x80+0x03);
- LCD1602_Write_Dat(0x30+2);
- LCD1602_Write_Dat(0x30+0);
- Delay5ms();
- LCD1602_Write_Com(0x80+0x07);
- LCD1602_Write_Dat('/');
- Delay5ms();
- LCD1602_Write_Com(0x80+0x0A);
- LCD1602_Write_Dat('/');
- Delay5ms();
- LCD1602_Write_Com(0x80+0x46);
- LCD1602_Write_Dat(':');
- Delay5ms();
- LCD1602_Write_Com(0x80+0x49);
- LCD1602_Write_Dat(':');
- Delay5ms();
- }
- void Display_Second(unsigned char x) //LCD1602顯示“秒”的數(shù)值
- {
- unsigned char i,j;
- i=x/10;
- j=x%10;
- LCD1602_Write_Com(0x80+0x4A);
- LCD1602_Write_Dat(0x30+i);
- LCD1602_Write_Dat(0x30+j);
- Delay5ms();
- }
- void Display_Minute(unsigned char x) //LCD1602顯示“分”的數(shù)值
- {
- unsigned char i,j;
- i=x/10;
- j=x%10;
- LCD1602_Write_Com(0x80+0x47);
- LCD1602_Write_Dat(0x30+i);
- LCD1602_Write_Dat(0x30+j);
- Delay5ms();
- }
- void Display_Hour(unsigned char x) //LCD1602顯示“時(shí)”的數(shù)值
- {
- unsigned char i,j;
- i=x/10;
- j=x%10;
- LCD1602_Write_Com(0x80+0x44);
- LCD1602_Write_Dat(0x30+i);
- LCD1602_Write_Dat(0x30+j);
- Delay5ms();
- }
- void Display_Day(unsigned char x) //LCD1602顯示“日”的數(shù)值
- {
- unsigned char i,j;
- i=x/10;
- j=x%10;
- LCD1602_Write_Com(0x80+0x0B);
- LCD1602_Write_Dat(0x30+i);
- LCD1602_Write_Dat(0x30+j);
- Delay5ms();
- }
- void Display_Month(unsigned char x) //LCD1602顯示“月”的數(shù)值
- {
- unsigned char i,j;
- i=x/10;
- j=x%10;
- LCD1602_Write_Com(0x80+0x08);
- LCD1602_Write_Dat(0x30+i);
- LCD1602_Write_Dat(0x30+j);
- Delay5ms();
- }
- void Display_Year(unsigned char x) //LCD1602顯示“年”的數(shù)值
- {
- unsigned char i,j;
- i=x/10;
- j=x%10;
- LCD1602_Write_Com(0x80+0x05);
- LCD1602_Write_Dat(0x30+i);
- LCD1602_Write_Dat(0x30+j);
- Delay5ms();
- }
- void Convert()
- {
- temp_s=Read_DS1302(0x81);
- second=(temp_s>>4)*10+(temp_s&0x0F); //將“秒”的BCD碼轉(zhuǎn)換成對(duì)應(yīng)的ASCII值
-
- temp_min=Read_DS1302(0x83);
- minute=(temp_min>>4)*10+(temp_min&0x0F); //將“分”的BCD碼轉(zhuǎn)換成對(duì)應(yīng)的ASCII值
-
- temp_h=Read_DS1302(0x85);
- hour=(temp_h>>4)*10+(temp_h&0x0F); //將“時(shí)”的BCD碼轉(zhuǎn)換成對(duì)應(yīng)的ASCII值
-
- temp_d=Read_DS1302(0x87);
- day=(temp_d>>4)*10+(temp_d&0x0F); //將“日”的BCD碼轉(zhuǎn)換成對(duì)應(yīng)的ASCII值
-
- temp_mon=Read_DS1302(0x89);
- month=(temp_mon>>4)*10+(temp_mon&0x0F); //將“月”的BCD碼轉(zhuǎn)換成對(duì)應(yīng)的ASCII值
-
- temp_y=Read_DS1302(0x8D);
- year=(temp_y>>4)*10+(temp_y&0x0F); //將“年”的BCD碼轉(zhuǎn)換成對(duì)應(yīng)的ASCII值
- }
- void Delay10ms()
- {
- unsigned char i,j;
- i=20;
- j=113;
- do
- {
- while(--j);
- }
- while(--i);
- }
- unsigned char Get_Key() //獲取按鍵值
- {
- static bit flag=0;
- unsigned char k=0;
-
- if((flag==0)&&((K1==0)||(K2==0)||(K3==0)))
- {
- Delay10ms();
- flag=1;
- if(K1==0)
- {
- k=1;
- }
- else if(K2==0)
- {
- k=2;
- }
- else if(K3==0)
- {
- k=3;
- }
- }
- else if((K1==1)&&(K2==1)&&(K3==1))
- {
- flag=0;
- }
- return k;
- }
- void Set_Time(unsigned char num) //設(shè)置DS1302的起始計(jì)時(shí)
- {
- unsigned char temp_second,temp_minute,temp_hour,temp_day,temp_month,temp_year; //暫存經(jīng)過(guò)轉(zhuǎn)換后得到的BCD碼
-
- switch(num)
- {
- case 1:
- if(++x>6) //時(shí)間(修改)選擇
- {
- x=0;
- }
- break;
-
- case 2: //時(shí)間“加”
- if(x==1) //年
- {
- year++;
- if(year>99)
- {
- year=0;
- }
- temp_year=((year/10)<<4)+(year%10);
- Write_DS1302(0x8C,temp_year);
- }
-
- if(x==2) //月
- {
- month++;
- if(month>12)
- {
- month=1;
- }
- temp_month=((month/10)<<4)+(month%10);
- Write_DS1302(0x88,temp_month);
- }
-
- if(x==3) //日
- {
- day++;
- if(month==1||month==3||month==5||month==7||month==8||month==10||month==12) //大月有31天
- {
- if(day>31)
- {
- day=1;
- }
- }
- else if(month==4||month==6||month==9||month==11) //小月有30天
- {
- if(day>30)
- {
- day=1;
- }
- }
- else if(month==2&&(year%4==0)) //閏年的二月有29天
- ……………………
- …………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼
51hei.png (6.34 KB, 下載次數(shù): 99)
下載附件
2022-1-20 17:22 上傳
所有資料51hei附件下載:
DS1302時(shí)間顯示(LCD1602).zip
(22.12 KB, 下載次數(shù): 190)
2022-1-20 11:22 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
|
評(píng)分
-
查看全部評(píng)分
|