本程序完全測(cè)試通過(guò) 按上面的電路圖 用1602液晶顯示 可調(diào)時(shí)間.
#include<reg52.h> #define uint unsigned int #define uchar unsigned char #define w_Sec 0x80 #define w_Min 0x82 #define w_Hou 0x84 #define w_Day 0x86 #define w_Mou 0x88 #define w_xi 0x8a #define w_Yea 0x8c // DS1302寫數(shù)據(jù) #define r_Sec 0x81 #define r_Min 0x83 #define r_Hou 0x85 #define r_Day 0x87 #define r_Mou 0x89 #define r_xi 0x8b #define r_Yea 0x8d //DS1302讀數(shù)據(jù) #define w_protect 0x8e //DS1302寫保護(hù) uchar code table[]="11-6-20"; //制作時(shí)間 uchar code time1[]="00:00:00"; //時(shí)間模式1,用于普通計(jì)時(shí) uchar code time2[]="00:00:00:00"; //時(shí)間模式2,用于秒表計(jì)時(shí) uchar code time3[]="00:00"; //時(shí)間模式3,用于鬧鐘設(shè)置 uchar code miaobiao[]="StopWatch"; uchar code naozhong[]="Alarm"; uchar code stuinfo1[]="ZLW0800730203"; uchar code stuinfo2[]="LWL0807030209"; uchar code xi1[]="Mon"; uchar code xi2[]="Tue"; uchar code xi3[]="Wed"; uchar code xi4[]="Thu"; uchar code xi5[]="Fri"; uchar code xi6[]="Sat"; uchar code xi7[]="Sun"; unsigned char code str1[]={"Temperature:"}; unsigned char code str2[]={" "}; uchar data disdata[5]; uint tvalue; //溫度值 uchar tflag; //溫度正負(fù)標(biāo)志 //18B20 sbit RS=P2^0; sbit RW=P2^1; sbit EN=P2^2; //1602控制端定義 sbit ACC_7 = ACC^7; //位尋址寄存器 sbit SCK = P1^1; //DS1302時(shí)鐘信號(hào) sbit SDA = P1^0; //DS1302數(shù)據(jù)信號(hào) sbit RST = P1^2 ; //DS1302片選信號(hào) sbit k1=P1^4; sbit k2=P1^5; sbit k3=P1^6; sbit k4=P1^7; sbit alarm=P3^7; sbit DQ = P2^7; //DS18B20 uint i,shi,fen,miao,haomiao,nian,yue,ri,num,x,menu,n,nshi=0,nfen=1; //nshi、nfen用來(lái)判別鬧鐘,與系統(tǒng)時(shí)間對(duì)比 uchar sshi,sfen,smiao,snian,syue,sri,sxi; /***********************延時(shí)程序*********************************/ void delay(uint z) { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } /********************************ds1302***************************************/ //***************向DS1302寫入一字節(jié)數(shù)據(jù) void Write1302(uchar addr, uchar d) { unsigned char i; SCK=0; RST=1; //寫入目標(biāo)地址:addr for (i = 0; i < 8; i ++) { if (addr & 0x01) { SDA=1; } else { SDA=0; } //并口轉(zhuǎn)串口 SCK=1; //上升沿寫數(shù)據(jù) SCK=0; addr = addr >> 1; } //寫入數(shù)據(jù):d for (i = 0; i < 8; i ++) { if (d & 0x01) { SDA=1; } else { SDA=0; } SCK=1; SCK=0; d = d >> 1; } RST=0; //停止DS1302總線 } //*************************從DS1302讀出一字節(jié)數(shù)據(jù) unsigned char Read1302(uchar addr) { unsigned char i; unsigned char temp; unsigned char dat1=0; unsigned char dat2=0; SCK=0; RST=1; //寫入目標(biāo)地址:addr for (i = 0; i < 8; i ++) { if (addr & 0x01) { SDA=1; } else { SDA=0; } SCK=1; SCK=0; addr = addr >> 1; } //輸出數(shù)據(jù):temp for (i = 0; i < 8; i ++) { temp = temp >> 1; if (SDA) { temp |= 0x80; } else { temp &= 0x7F; } SCK=1; SCK=0; } RST=0; //停止DS1302總線 dat2 = temp/16; // 數(shù)據(jù)進(jìn)制轉(zhuǎn)換 dat1 = temp%16; dat1 = dat2*10+dat1; return dat1; } /*****************************1602顯示******************************************/ void write_add(uchar add) //1602控制字 { RS=0; P0=add; EN=1; delay(5); EN=0; } void write_date(uchar date) //1602顯示字 { RS=1; P0=date; EN=1; delay(5); EN=0; } void writesfm(uchar add,uchar date) //1602顯示時(shí)分秒 { uchar s,g; s = date/10; g = date%10; write_add(0x80+0x40+add); write_date(0x30+s); write_date(0x30+g); } void writenyr(uchar add,uchar date) //1602顯示年月日 { uchar s,g; s=date/10; g=date%10; write_add(0x80+0x00+add); write_date(0x30+s); write_date(0x30+g); } void writexi(uchar a) { write_add(0x80+0x00+11); if(a==1) { for(i=0;i<3;i++) { write_date(xi1[i]); delay(5); } } if(a==2) { for(i=0;i<3;i++) { write_date(xi2[i]); delay(5); } } if(a==3) { for(i=0;i<3;i++) { write_date(xi3[i]); delay(5); } } if(a==4) { for(i=0;i<3;i++) { write_date(xi4[i]); delay(5); } } if(a==5) { for(i=0;i<3;i++) { write_date(xi5[i]); delay(5); } } if(a==6) { for(i=0;i<3;i++) { write_date(xi6[i]); delay(5); } } if(a==7) { for(i=0;i<3;i++) { write_date(xi7[i]); delay(5); } } } void writefuhao(void) //寫符號(hào) { write_add(0x80+0x00+2); write_date(table[2]); delay(10); write_add(0x80+0x00+5); write_date(table[2]); delay(10); write_add(0x80+0x40+2); write_date(time1[2]); delay(10); write_add(0x80+0x40+5); write_date(time1[2]); delay(10); } /******************************ds1820程序***************************************/ void delay_18B20(unsigned int i)//延時(shí)1微秒 { while(i--); } void ds1820rst() //ds1820復(fù)位 { unsigned char x=0; DQ = 1; //DQ復(fù)位 delay_18B20(4); //延時(shí) DQ = 0; //DQ拉低 delay_18B20(100); //精確延時(shí)大于480us DQ = 1; //拉高 delay_18B20(40); } uchar ds1820rd() //讀數(shù)據(jù) { unsigned char i=0; unsigned char dat = 0; for (i=8;i>0;i--) { DQ = 0; //給脈沖信號(hào) dat>>=1; DQ = 1; //給脈沖信號(hào) if(DQ) dat|=0x80; delay_18B20(10); } return(dat); } void ds1820wr(uchar wdata) //寫數(shù)據(jù) { unsigned char i=0; for (i=8; i>0; i--) { DQ = 0; DQ = wdata&0x01; delay_18B20(10); DQ = 1; wdata>>=1; } } read_temp() //讀取溫度值并轉(zhuǎn)換 { uchar a,b; ds1820rst(); ds1820wr(0xcc); //跳過(guò)讀序列號(hào) ds1820wr(0x44); //啟動(dòng)溫度轉(zhuǎn)換 ds1820rst(); ds1820wr(0xcc); //跳過(guò)讀序列號(hào) ds1820wr(0xbe);//讀取溫度 a=ds1820rd(); b=ds1820rd(); tvalue=b; tvalue<<=8; tvalue=tvalue|a; if(tvalue<0x0fff) tflag=0; else { tvalue=~tvalue+1; tflag=1; } tvalue=tvalue*(0.625);//溫度值擴(kuò)大10倍,精確到1位小數(shù) return(tvalue); } /*******************************************************************/ void ds1820disp() //溫度值顯示 { uchar flagdat; disdata[0]=tvalue/1000+0x30; //百位數(shù) disdata[1]=tvalue%1000/100+0x30; //十位數(shù) disdata[2]=tvalue%100/10+0x30; //個(gè)位數(shù) disdata[3]=tvalue%10+0x30; //小數(shù)位 if(tflag==0) flagdat=0x20; //正溫度不顯示符號(hào) else flagdat=0x2d; //負(fù)溫度顯示負(fù)號(hào):- if(disdata[0]==0x30) { disdata[0]=0x20; //如果百位為0,不顯示 if(disdata[1]==0x30) { disdata[1]=0x20; //如果百位為0,十位為0也不顯示 } } write_add(0x80+0x40+8); write_date(flagdat); //顯示符號(hào)位 write_add(0x80+0x40+9); write_date(disdata[0]); //顯示百位 write_add(0x80+0x40+10); write_date(disdata[1]); //顯示十位 write_add(0x80+0x40+11); write_date(disdata[2]); //顯示個(gè)位 write_add(0x80+0x40+12); write_date(0x2e); //顯示小數(shù)點(diǎn) write_add(0x80+0x40+13); write_date(disdata[3]); //顯示小數(shù)位 write_add(0x80+0x40+14); write_date(0xdf); //顯示"。" write_add(0x80+0x40+15); write_date(0x63); //顯示"c" } void init_info(void) { write_add(0x80+0x00+0); for(i=0;i<14;i++) { write_date(stuinfo1[i]); delay(5); } write_add(0x80+0x40+0); for(i=0;i<14;i++) { write_date(stuinfo2[i]); delay(5); } } void Speak1() //鬧鈴 { alarm = 0; smiao = Read1302(r_Sec); sfen = Read1302(r_Min); sshi = Read1302(r_Hou); snian = Read1302(r_Yea); syue = Read1302(r_Mou); sri = Read1302(r_Day); sxi = Read1302(r_xi); writefuhao(); writesfm(0,sshi); writesfm(3,sfen); writesfm(6,smiao); writenyr(0,snian); writenyr(3,syue); writenyr(6,sri); writexi(sxi); delay(500); alarm = 1; delay(500); } void Speak2() { alarm=0; delay(2000); alarm=1; } void Normal() //正常顯示時(shí)間功能 { smiao = Read1302(r_Sec); sfen = Read1302(r_Min); sshi = Read1302(r_Hou); snian = Read1302(r_Yea); syue = Read1302(r_Mou); sri = Read1302(r_Day); sxi = Read1302(r_xi); //讀取時(shí)間數(shù)據(jù) if((nshi==sshi)&&(nfen==sfen)) //鬧鐘鈴響 { for(i=0;i<10;i++) { Speak1(); } while((k1==1)||(k2==1)||(k3==1)||(k4==1)) //按下任意鍵,鬧鐘停止鬧鈴 { alarm=1; } } //關(guān)閉蜂鳴器 if((sshi==0||sshi==1||sshi==2||sshi==3||sshi==4||sshi==5||sshi==6||sshi==7 ||sshi==8||sshi==9||sshi==10||sshi==11||sshi==12||sshi==13||sshi==14||sshi==15||sshi==16 ||sshi==1||sshi==18||sshi==19||sshi==20||sshi==21||sshi==22||sshi==23)&&(sfen==0)&&(smiao==0)) { Speak2(); //整點(diǎn)報(bào)時(shí) } alarm=1; //關(guān)閉蜂鳴器 writefuhao(); writesfm(0,sshi); writesfm(3,sfen); writesfm(6,smiao); writenyr(0,snian); writenyr(3,syue); writenyr(6,sri); writexi(sxi); } void StopWatch () reentrant //秒表功能 { haomiao=0; miao=0; fen=0; shi=0; write_add(0x01); //清屏 write_add(0x0c); write_add(0x80+0x00+0); for(i=0;i<9;i++) { write_date(miaobiao[i]); delay(5); } write_add(0x80+0x40+0); for(i=0;i<11;i++) { write_date(time2[i]); delay(5); } while(!k4); while(k4!=0) { if(k1==0) { delay(10); //消抖 if(k1==0) StopWatch(); } haomiao++; if(haomiao==100) { haomiao=0; miao++; if(miao==60) { miao=0; fen++; if(fen==60) { fen=0; shi++; if(shi==24) { shi=0; } writesfm(0,shi); } writesfm(3,fen); } writesfm(6,miao); } writesfm(9,haomiao); } /*TR0 = 0; menu=3;*/ } void key() //鬧鐘時(shí)的按鍵功能 { if(k1==0) { delay(10); if(k1==0) { n++; while(!k1); if(n==1) { write_add(0x0f); write_add(0x80+0x40+4); //寫shi } if(n==2) { write_add(0x0f); write_add(0x80+0x40+7); //寫fen } if(n==3) { n=0; nfen=fen; nshi=shi; //確認(rèn) write_add(0x0c); //光標(biāo)不閃爍 } } } if(k2==0) { delay(10); if(k2==0) { while(!k2); if(n==1) { shi++; if(shi==24) shi=0; writesfm(4,shi); } if(n==2) { fen++; if(fen==60) fen=0; writesfm(7,fen); } } } if(k3==0) { delay(10); if(k3==0) { while(!k3); if(n==1) { shi--; if(shi==-1) shi=23; writesfm(4,shi); } if(n==2) { fen--; if(fen==-1) fen=59; writesfm(7,fen); } } } menu=4; } void Alarm(void) //設(shè)定鬧鐘功能,k4鍵跳轉(zhuǎn)其他功能 { write_add(0x06); write_add(0x01); //清屏 write_add(0x80+0x00+0); for(i=0;i<5;i++) { write_date(naozhong[i]); //顯示Alarm標(biāo)識(shí)符 } write_add(0x80+0x40+4); writesfm(4,nshi); write_date(0x3a); writesfm(7,nfen); shi=nshi; fen=nfen; while(!k4); while(k4) { key(); } write_add(0x0c); //開(kāi)顯示,不顯示光標(biāo) } void key1(void) { if(k1==0) //設(shè)置光標(biāo)所在位置 { delay(10); //去抖 if(k1==0) { num++; while(!k1); if(num==1) { write_add(0x0f); //顯示光標(biāo)并閃爍 write_add(0x80+0x40+6); } if(num==2) { write_add(0x0f); //顯示光標(biāo)并閃爍 write_add(0x80+0x40+3); } if(num==3) { write_add(0x0f); //顯示光標(biāo)并閃爍 write_add(0x80+0x40+0); } if(num==4) { write_add(0x0f); //顯示光標(biāo)并閃爍 write_add(0x80+0x00+6); } if(num==5) { write_add(0x0f); //顯示光標(biāo)并閃爍 write_add(0x80+0x00+3); } if(num==6) { write_add(0x0f); //顯示光標(biāo)并閃爍 write_add(0x80+0x00+0); } if(num==7) { write_add(0x0f); //顯示光標(biāo)并閃爍 write_add(0x80+0x00+11); } if(num==8) { num=0; write_add(0x0c); } } } } void key2(void) { Write1302(w_protect,0x00); //禁止寫保護(hù) if(k2==0) //實(shí)現(xiàn)加法 { delay(10); if(k2==0) { while(!k2); if(num==1) { miao++; if(miao==60) { miao=0; } writesfm(6,miao); Write1302(w_Sec,(miao/10)*16+miao%10); //將miao轉(zhuǎn)換成BCD碼 } if(num==2) { fen++; if(fen==60) { fen=0; } writesfm(3,fen); Write1302(w_Min,(fen/10)*16+fen%10); } if(num==3) { shi++; if(shi==24) { shi=0; } writesfm(0,shi); Write1302(w_Hou,(shi/10)*16+shi%10); } if(num==4) { ri++; if(ri==30) { ri=0; } writenyr(6,ri); Write1302(w_Day,(ri/10)*16+ri%10); } if(num==5) { yue++; if(yue==13) { yue=1; } writenyr(3,yue); Write1302(w_Mou,(yue/10)*16+yue%10); } if(num==6) { nian++; if(nian==100) { nian=0; } writenyr(0,nian); Write1302(w_Yea,(nian/10)*16+nian%10); } if(num==7) { x++; writexi(x); Write1302(w_xi,(x/10)*16+x%10); if(x==7) { x=0; } } } } } void key3(void) { Write1302(w_protect,0x00); //禁止寫保護(hù) if(k3==0) //實(shí)現(xiàn)減法 { delay(10); if(k3==0) { while(!k3); if(num==1) { miao--; if(miao==-1) { miao=59; } writesfm(6,miao); Write1302(w_Sec,(miao/10)*16+miao%10); } if(num==2) { fen--; if(fen==-1) { fen=59; } writesfm(3,fen); Write1302(w_Min,(fen/10)*16+fen%10); } if(num==3) { shi--; if(shi==-1) { shi=23; } writesfm(0,shi); Write1302(w_Hou,(shi/10)*16+shi%10); } if(num==4) { ri--; if(ri==-1) { ri=30; } writenyr(6,ri); Write1302(w_Day,(ri/10)*16+ri%10); } if(num==5) { yue--; if(yue==-1) { yue=12; } writenyr(3,yue); Write1302(w_Mou,yue); } if(num==6) { nian--; if(nian==-1) { nian=99; } writenyr(0,nian); Write1302(w_Yea,(yue/10)*16+yue%10); } if(num==7) { x--; writexi(x); Write1302(w_xi,(x/10)*16+x%10); if(x==1) { x=8; } } } } } void key4() { if(k4==0) { delay(10); if(k4==0) { while(!k4); menu++; } } } void TimeSet() { write_add(0x0f); write_add(0x80+0x40+9); while(k4) { key1(); key2(); key3(); } Write1302(w_protect,0x00); //寫保護(hù) menu=2; } void init_DS1302(void) { Write1302(w_protect,0x00); //禁止寫保護(hù) Write1302(w_Sec,0x56); Write1302(w_Min,0x59); Write1302(w_Hou,0x23); //24小時(shí)模式 Write1302(w_xi,0x03); Write1302(w_Day,0x28); Write1302(w_Mou,0x02); Write1302(w_Yea,0x11); //初始化系統(tǒng)時(shí)間 2011年5月11日周三12:12:12 Write1302(w_protect,0x80); //寫保護(hù) } void disp(void) { key4(); if(menu==0) { Normal(); read_temp(); //讀取溫度 ds1820disp();//顯示 } if(menu==1) { TimeSet(); } num=0; if(menu==2) { StopWatch(); } if(menu==3) { Alarm(); } if(menu==4) { init_info(); } if(menu==5) { menu=0; write_add(0x01); //清屏 } } void main() { init_DS1302(); //初始化1302 EN=1; RW=0; //寫命令 write_add(0x38); //設(shè)置16*2行顯示,5*7點(diǎn)陣,8位數(shù)據(jù)接口 write_add(0x0c); //開(kāi)顯示,不顯示光標(biāo) write_add(0x06); write_add(0x01); //清屏 while(1) { disp(); //顯示 } }