[size=16.0000pt]1、DS1302模塊 /*------------------寄存器地址宏定義------------*/ #define WRITE_SECOND 0x80 #define WRITE_MINUTE 0x82 #define WRITE_HOUR 0x84 #define WRITE_DAY 0x86 #define WRITE_MONTH 0x88 #define WRITE_YEAR 0x8C #define WRITE_PROTECT 0x8E #define WRITE_WEEK 0x8A #define WRITE_CURRENT 0x90 #define READ_SECOND 0x81 #define READ_MINUTE 0x83 #define READ_HOUR 0x85 #define READ_DAY 0x87 #define READ_MONTH 0x89 #define READ_WEEK 0x8B #define READ_YEAR 0x8D sbit RST=P1^4;//DS1302片選 sbit DIO=P1^3;//DS1302數據信號 sbit SCLK=P1^2;//DS1302時鐘信號 sbit ACC_7=ACC^7;//位尋址寄存器定義 void INITIAL_1302();//DS1302初始化函數申明 unsigned char READ_1302(unsigned char addr);//DS1302讀數據函數申明 void WRITE_1302(unsigned char addr,unsigned char date);//DS1302寫數據函數申明 void WRITE_1302(unsigned char addr,unsigned char date)//地址、數據發送子程序 { unsigned char i,temp; RST=0;//RST引腳為低,數據傳送中止 SCLK=0;//清零時鐘總線 RST=1;//RST引腳為高,邏輯控制有效 for(i=8;i>0;i--)//發送地址,循環8次移位 { SCLK=0; temp=addr; DIO=(bit)(temp&0x01);//每次傳送低字節 addr>>=1;//右移一位 SCLK=1; } for(i=8;i>0;i--)//發送數據 { SCLK=0; temp=date; DIO=(bit)(temp&0x01); date>>=1; SCLK=1; } RST=0; } unsigned char READ_1302(unsigned char addr)//讀取數據 { unsigned char i,temp,date1,date2; RST=0; SCLK=0; RST=1; for(i=8;i>0;i--)//循環8次移位 { SCLK=0; temp=addr; DIO=(bit)(temp&0x01);//每次傳送低字節 addr>>=1;//右移一位 SCLK=1; } for(i=8;i>0;i--) { ACC_7=DIO; SCLK=1; ACC>>=1; SCLK=0; } RST=0; date1=ACC; date2=date1/16;//數據進制轉換 date1=date1%16;//十六進制轉十進制 date1=date1+date2*10; return(date1) ; } void INITIAL_1302()//初始化DS1302 { WRITE_1302(WRITE_SECOND,READ_1302(READ_SECOND)&0x7f);//啟動DS1302 } 2、LCD1302模塊 sbit LCD_E=P1^7;//液晶使能端 sbit LCD_RS=P2^0;//液晶數據命令選擇端 sbit LCD_RW=P2^1;//液晶讀寫選擇端 unsigned char str1[]=" 20 - - "; unsigned char str2[]=" : : "; void delay(unsigned char z);//延時函數申明 void LCD_WRITE_COM(unsigned char com);//液晶寫命令函數申明 void LCD_WRITE_DATA(unsigned char date);//液晶寫數據函數申明 void LCD_WRITE_SFM(unsigned char addr,unsigned char date);//寫時分秒函數申明 void LCD_WRITE_NYR(unsigned char addr,unsigned char date);//寫年月日函數申明 void LCD_WRITE_WEEK(unsigned char week);//寫星期函數申明 void LCD_INITIAL();//液晶初始化函數申明 void delay(unsigned char z)//延時函數 { unsigned char x,y; for(x=z;x>0;x--) for(y=110;y>0;y--); } void LCD_WRITE_COM(unsigned char com)//寫命令函數 { LCD_RS=0; LCD_RW=0; LCD_E=1; P0=com; delay(5); LCD_E=0; } void LCD_WRITE_DATA(unsigned char date)//寫數據函數 { LCD_RS=1; LCD_RW=0; LCD_E=1; P0=date; delay(5); LCD_E=0; } void LCD_WRITE_SFM(unsigned char addr,unsigned char date)//寫時分秒函數 { unsigned char shi,ge; shi=date/10; ge=date%10;//分解2位數的十位和個位 LCD_WRITE_COM(0x80+0x40+addr);//設置顯示位置 LCD_WRITE_DATA(0x30+shi);//送去液晶顯示十位 LCD_WRITE_DATA(0x30+ge);//送去液晶顯示個位 } void LCD_WRITE_NYR(unsigned char addr,unsigned char date)//寫年月日函數 { char shi,ge; shi=date/10; ge=date%10;//分解2位數的十位和個位 LCD_WRITE_COM(0x80+addr);//設置顯示位置 LCD_WRITE_DATA(0x30+shi);//送去液晶顯示十位 LCD_WRITE_DATA(0x30+ge);//送去液晶顯示個位 } void LCD_WRITE_WEEK(unsigned char week)//寫液晶星期顯示函數 { LCD_WRITE_COM(0x80+12);//設置顯示位置 switch(week) { case 1: LCD_WRITE_DATA('S');delay(5); LCD_WRITE_DATA('U');delay(5); LCD_WRITE_DATA('N');break; case 2: LCD_WRITE_DATA('M');delay(5); LCD_WRITE_DATA('O');delay(5);; LCD_WRITE_DATA('N');break; case 3: LCD_WRITE_DATA('T');delay(5); LCD_WRITE_DATA('U');delay(5); LCD_WRITE_DATA('E');break; case 4: LCD_WRITE_DATA('W');delay(5); LCD_WRITE_DATA('E');delay(5); LCD_WRITE_DATA('D');break; case 5: LCD_WRITE_DATA('T');delay(5); LCD_WRITE_DATA('H');delay(5); LCD_WRITE_DATA('U');break; case 6: LCD_WRITE_DATA('F');delay(5); LCD_WRITE_DATA('R');delay(5); LCD_WRITE_DATA('I');break; case 7: LCD_WRITE_DATA('S');delay(5); LCD_WRITE_DATA('A');delay(5); LCD_WRITE_DATA('T');break; } } void LCD_INITIAL()//液晶初始化函數 { unsigned char i; LCD_WRITE_COM(0x38);//設置16*2顯示,5*7點陣,8位數據接口 LCD_WRITE_COM(0x0c);//設置開顯示,不顯示光標 LCD_WRITE_COM(0x06);//寫一個字符后地址指針加1 LCD_WRITE_COM(0x80);//液晶第一行顯示 for(i=0;i<16;i++) { LCD_WRITE_DATA(str1); delay(5); } LCD_WRITE_COM(0x80+0x40);//液晶第二行顯示 for(i=0;i<16;i++) { LCD_WRITE_DATA(str2); delay(5); } } [size=16.0000pt]3、按鍵模塊 sbit key0=P3^2;//調時 sbit key1=P3^3;//增大 sbit key2=P3^4;//減小 char hour,minute,second,week,day,month,year; unsigned char num,flag; void keyscan() { if(key0==0)//確認調時按下 { delay(20); if(key0==0)//調時確實按下 { while(!key0);//釋放 num++;//按下次數記錄 switch(num) { case 1: flag=1;//修改時間,液晶禁止從DS1302讀數據 TR0=0;//定時器關 LCD_WRITE_COM(0x0f);//光標開始閃爍 LCD_WRITE_COM(0x80+3);//第一次按下,光標定位到年位置 break; case 2: LCD_WRITE_COM(0x80+6);//第二次按下,光標定位到月位置 break; case 3: LCD_WRITE_COM(0x80+9);//第三次按下,光標定位到日位置 break; case 4: LCD_WRITE_COM(0x80+12);//第四次按下,光標定位到星期位置 break; case 5: LCD_WRITE_COM(0x80+0x40+4);//第五次按下,光標定位到時位置 break; case 6: LCD_WRITE_COM(0x80+0x40+7);//第六次按下,光標定位到分位置 break; case 7: LCD_WRITE_COM(0x80+0x40+10);//第七次按下,光標定位到秒位置 break; case 8: num=0;//第八次按下,記錄清零 LCD_WRITE_COM(0x0c);//不顯示光標 WRITE_1302(WRITE_PROTECT,0x00);//禁止寫保護 WRITE_1302(0x80,(second/10*16)+second%10);//將調節后的秒寫入DS1302 WRITE_1302(0x82,(minute/10*16)+minute%10);//將調節后的分寫入DS1302 WRITE_1302(0x84,(hour/10*16)+hour%10);//將調節后的時寫入DS1302 WRITE_1302(0x8a,(week/10*16)+week%10);//將調節后的星期寫入DS1302 WRITE_1302(0x86,(day/10*16)+day%10);//將調節后的日寫入DS1302 WRITE_1302(0x88,(month/10*16)+month%10);//將調節后的月寫入DS1302 WRITE_1302(0x8c,(year/10*16)+year%10);//將調節后的年寫入DS1302 WRITE_1302(WRITE_PROTECT,0x80);//開寫保護 flag=0;//時間修改完畢,允許液晶從DS1302讀數據 TR0=1; //定時器開 break; } } } if(num!=0) { if(key1==0)//確認增大鍵按下 { delay(20); if(key1==0)//增大鍵確實按下 { while(!key1); switch(num) { case 1: year++;//調節年 if(year==100)year=0; LCD_WRITE_NYR(3,year);//將調節后的年送入液晶顯示 LCD_WRITE_COM(0x80+3);//光標回到指定處 break; case 2: month++;//調節月 if(month==13)month=0; LCD_WRITE_NYR(6,month);//將調節后的月送入液晶顯示 LCD_WRITE_COM(0x80+6);//光標回到指定處 break; case 3: day++;//調節日 if(day==32)day=0; LCD_WRITE_NYR(9,day);//將調節后的日送入液晶顯示 LCD_WRITE_COM(0x80+9);//光標回到指定處 break; case 4: week++; if(week==8)week=0; LCD_WRITE_WEEK(week);//將調節后的星期送入液晶顯示 LCD_WRITE_COM(0x80+12);//光標回到指定處 break; case 5: hour++; if(hour==24)hour=0; LCD_WRITE_SFM(4,hour);//將調節后的小時送入液晶顯示 LCD_WRITE_COM(0x80+0x40+4);//光標回到指定處 break; case 6: minute++; if(minute==60)minute=0; LCD_WRITE_SFM(7,minute);//將調節后的分送入液晶顯示 LCD_WRITE_COM(0x80+0x40+7);//光標回到指定處 break; case 7: second++; if(second==60)second=0; LCD_WRITE_SFM(10,second);//將調節后的秒送入液晶顯示 LCD_WRITE_COM(0x80+0x40+10);//光標回到指定處 break; default:break; } } } if(key2==0)//確認減小鍵按下 { delay(20); if(key2==0)//減小鍵確實按下 { while(!key2); switch(num) { case 1: year--;//調節年 if(year==-1)year=99; LCD_WRITE_NYR(3,year); LCD_WRITE_COM(0x80+3); break; case 2: month--;//調節月 if(month==-1)month=12; LCD_WRITE_NYR(6,month); LCD_WRITE_COM(0x80+6); break; case 3: day--;//調節日 if(day==-1)day=31; LCD_WRITE_NYR(9,day); LCD_WRITE_COM(0x80+9); break; case 4: week--;//調節星期 if(week==0)week=7; LCD_WRITE_WEEK(week); LCD_WRITE_COM(0x80+12); break; case 5: hour--;//調節時 if(hour==-1)hour=23; LCD_WRITE_SFM(4,hour); LCD_WRITE_COM(0x80+0x40+4); break; case 6: minute--;//調節分 if(minute==-1)minute=59; LCD_WRITE_SFM(7,minute); LCD_WRITE_COM(0x80+0x40+7); break; case 7: second--;//調節秒 if(second==-1)second=59; LCD_WRITE_SFM(10,second); LCD_WRITE_COM(0x80+0x40+10); break; default:break; } } } } } [size=16.0000pt]4、主模塊 #include<reg51.h> #include<lcd1602.h> #include<ds1302.h> #include<keyscan.h> #include<fengmingqi.h> void main() { LCD_INITIAL();//液晶初始化 INITIAL_1302();//DS1302初始化 INITIAL_TEMER0();//定時器初始化 while(1) { keyscan();//按鍵掃描 if(flag==0)//當標志位為0,允許讀取DS1302數據,將數據送入液晶顯示 { second=READ_1302(0x81); LCD_WRITE_SFM(10,second);//從DS1302讀取秒送入液晶顯示 minute=READ_1302(0x83); LCD_WRITE_SFM(7,minute);//從DS1302讀取分送入液晶顯示 hour=READ_1302(0x85); LCD_WRITE_SFM(4,hour);//從DS1302讀取時送入液晶顯示 week=READ_1302(0x8b); LCD_WRITE_WEEK(week);//從DS1302讀取星期送入液晶顯示 day=READ_1302(0x87); LCD_WRITE_NYR(9,day);//從DS1302讀取日送入液晶顯示 month=READ_1302(0x89); LCD_WRITE_NYR(6,month);//從DS1302讀取月送入液晶顯示 year=READ_1302(0x8d); LCD_WRITE_NYR(3,year);//從DS1302讀取年送入液晶顯示 } } }
|