網(wǎng)上的DS1302與1602搭配的程序很多都有很大問題。我寫個全的,而且寫得很細,讓大家看看好了解,端口自己修改即可
#include <reg51.h> #include <intrins.h> /*********************************端口定義**********************************/ sbit sclk = P3^4; sbit io= P3^3; sbit rst= P3^5; sbit rs=P1^0; sbit en=P1^2; sbit rw=P1^1; #define uchar unsigned char #define uint unsigned int uchar flag,second,minute,hour,week,day,month,year;//秒、分、時、星期、日、月、年 void delay(uint z) //延時子程序 { uint x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } void delayus() { _nop_(); _nop_(); _nop_(); _nop_(); } void write_1602dat(uchar dat)//定義一個帶參數(shù)的寫數(shù)據(jù)子程序 { rs=1; //1602的rs為0時,接收命令,為1時接收數(shù)據(jù) P0=dat;//把void write_shu(uchar shu)中的COM中的數(shù)據(jù)給P0口 delay(5); en=1; delay(5); en=0; delay(5); } void write_1602com(uchar com)//定義一個帶參數(shù)的寫命令子程序 { rs=0; //1602的rs為0時,接收命令,為1時接收數(shù)據(jù) P0=com;//把void write_com(uchar com)中的COM中的數(shù)據(jù)給P0口 delay(5); en=1; delay(5); en=0; delay(5); } void Write1602(uchar add,uchar dat) { write_1602com(add); write_1602dat(dat); } void init1602()//定義一個初始化子程序 { en=0; rw=0; write_1602com(0x38);//調用 write_com子程序并把0x38賦給P0口,顯示模式打開 write_1602com(0x0e);//調用 write_com子程序并把“開顯示,顯示光標,光標閃爍”指令碼賦給P0口 write_1602com(0x06);//調用 write_com子程序并把“地址指針加1,整屏不移動”指令碼賦給P0口 //write_com(0x80+0x10);//數(shù)據(jù)指針初始化,讓指針指向可顯示的最右端 write_1602com(0x80);//數(shù)據(jù)指針初始化,讓指針指向最左端,顯示從第一行開始 write_1602com(0x01);//調用 write_com子程序并把"清零指"令碼賦給P0口 Write1602(0x80,'2'); Write1602(0x81,'0'); Write1602(0x80+4,'-'); Write1602(0x80+7,'-'); Write1602(0x80+0x40+5,':'); Write1602(0x80+0x40+8,':'); } /********************寫一個字節(jié)**************/ void write_1302byte(dat) { uchar i; sclk=0; delayus(); for(i=8;i>0;i--) { io=dat&0x01;//只要是從低位取數(shù),向高位一定要和0X01與 delayus(); sclk=1;//為寫數(shù)據(jù)制造上升沿。 delayus(); sclk=0;//為下一次上升沿寫下一個字節(jié)做準備 dat>>=1;//將數(shù)據(jù)向左移一位,準備寫入下一個數(shù)據(jù) } } /********************讀一個字節(jié)***************/ uchar read_1302byte() { uchar i,dat; delayus(); for(i=8;i>0;i--) { dat>>=1; if(io==1) { dat|=0x80;//將1取出,寫在dat的最高位。 } sclk=1;//把sclk拉高,為讀一個字節(jié)的下降沿做準備 delayus;//稍等制造一個高電平 sclk=0;//為讀一個字節(jié)制造下降沿 delayus; } return dat; } /*************寫入一個時間位*****************/ void write_1302(uchar add,uchar dat) { rst=0; delayus(); sclk=0; delayus(); rst=1; write_1302byte(add); delayus(); write_1302byte(dat); delayus(); rst=0; } /****************讀1302的地址******************/ uchar read_1302add(uchar add) { uchar timedat; rst=0; _nop_(); sclk=0; _nop_(); rst=1; write_1302byte(add);//寫入要讀的地址 timedat=read_1302byte();//將上面地址中的數(shù)據(jù)賦給timedat sclk=1; _nop_(); rst=0; return timedat; } /****************初始化1302*********************/ void init_1302() { flag=read_1302add(0x81);//讀秒寄存器的最高位,讀出時鐘狀態(tài) if(flag&0x80)//判斷時鐘是否關閉,若內部關閉,則初始,若沒關閉,不初始化,還在走 { write_1302(0x8e,0x00);//去除寫保護 write_1302(0x80,((55/10)<<4|(55%10)));//寫秒寄存器,并寫入初值55 write_1302(0x82,((59/10)<<4|(55%10)));//寫分寄存器,并寫入初值59 write_1302(0x84,((22/10)<<4|(22%10)));//寫小時寄存器,并寫入初值23 write_1302(0x86,((24/10)<<4|(24%10)));//寫日寄存器,并寫入初值18 write_1302(0x88,((2/10)<<4|(2%10)));//寫月寄存器,并寫入初值2 write_1302(0x8a,((5/10)<<4|(5%10)));//寫周寄存器,并寫入初值5 write_1302(0x8c,((12/10)<<4|(12%10)));//寫年寄存器,并寫入初值12,不能寫2012年 write_1302(0x90,0xa5);//寫充電方式 write_1302(0x8e,0x80);//加上寫保護 } } /*****************讀出秒的十進制數(shù)***************************/ uchar readsecond(uchar dat) { dat=read_1302add(0x81); second=((dat&0x70)>>4)*10+(dat&0x0f); return second; } /*****************讀出分的十進制數(shù)***************************/ uchar readminute(uchar dat) { dat=read_1302add(0x83); minute=((dat&0x70)>>4)*10+(dat&0x0f); return minute; } /*****************讀出小時的十進制數(shù)***************************/ uchar readhour(uchar dat) { dat=read_1302add(0x85); hour=((dat&0x70)>>4)*10+(dat&0x0f); return hour; } /*****************讀出天的十進制數(shù)***************************/ uchar readday(uchar dat) { dat=read_1302add(0x87); day=((dat&0x70)>>4)*10+(dat&0x0f); return day; } /*****************讀出月的十進制數(shù)***************************/ uchar readmonth(uchar dat) { dat=read_1302add(0x89); month=((dat&0x70)>>4)*10+(dat&0x0f); return month; } /*****************讀出周的十進制數(shù)***************************/ uchar readweek(uchar dat) { dat=read_1302add(0x8b); week=((dat&0x70)>>4)*10+(dat&0x0f); return week; } /*****************讀出年的十進制數(shù)***************************/ uchar readyear(uchar dat) { dat=read_1302add(0x8d); year=((dat&0xf0)>>4)*10+(dat&0x0f); return year; } /************************讀出所有時間**********************/ readtime() { readsecond(); readminute(); readhour(); readday(); -readmonth(); readweek(); readyear(); } /*********************向1602寫入時間****************************/ void write_second() { uchar shi,ge; shi=second/10; ge=second%10; Write1602(0x80+0x40+9,0x30+shi); Write1602(0x80+0x40+10,0x30+ge); } void write_minute() { uchar shi,ge; shi=minute/10; ge=minute%10; Write1602(0x80+0x40+6,0x30+shi); Write1602(0x80+0x40+7,0x30+ge); } void write_hour() { uchar shi,ge; shi=hour/10; ge=hour%10; Write1602(0x80+0x40+3,0x30+shi); Write1602(0x80+0x40+4,0x30+ge); } void write_day() { uchar shi,ge; shi=day/10; ge=day%10; Write1602(0x80+8,0x30+shi); Write1602(0x80+9,0x30+ge); } void write_month() { uchar shi,ge; shi=month/10; ge=month%10; Write1602(0x80+5,0x30+shi); Write1602(0x80+6,0x30+ge); } void write_year() { uchar shi,ge; shi=year/10; ge=year%10; Write1602(0x80+2,0x30+shi); Write1602(0x80+3,0x30+ge); } void write_week() { /*uchar shi,ge; shi=week/10; ge=week%10; Write1602(0x80+12,0x30+shi); Write1602(0x80+13,0x30+ge); */ Write1602(0x80+12,0x30+week); } void main() { delay(100); init1602(); init_1302(); while(1) { readtime(); write_second(); write_minute(); write_hour(); write_day(); write_month(); write_year(); write_week(); } }