基于利用时钟芯片DS1302实现万年历,1602LCD显示电子表
- 格式:doc
- 大小:2.76 MB
- 文档页数:26
#include <reg52.h>#include <intrins.h>#include <string.h>#define uint unsigned int#define uchar unsigned charsbit led = P2^3;//led代替闹铃sbit IO = P1^3; //定义1302管脚//6sbit SCLK = P1^4;//7sbit RST = P1^5; //5sbit RS = P2^2;//定义1602管脚sbit RW = P2^1;sbit EN = P2^0;sbit key1=P3^4;//选择//调时键盘sbit key2=P3^5;//加sbit key3=P3^6;//减sbit key4=P3^7;//确定sbit key11=P1^6;//选择//闹钟键盘sbit key22=P1^7;//加sbit key33=P3^0;//减sbit key44=P3^1;//确定uchar x1=0,x;int hour=8,minute=0;//闹钟的初始时间8:00uchar DateTime[9]; //秒,分,时,日,周,月,年 address,uchar lcd1[]={"DATE 00-00-00 "};uchar lcd2[]={"TIME 00:00:00 "};/***************延时*************/void delayms(uchar x)//延时毫秒程序{ uchar i,j;for(i=x;i>0;i--)for(j=110;j>0;j--);}void delayus(uchar x)//延时微秒程序{ uchar i;for(i=0;i<x;i++);}/********1302的驱动程序***********///写入数据,dat:要写入的数据void DS1302WriteByte(uchar dat){uchar i;SCLK=0;//初始时钟线置为0delayus(2);for(i=0;i<8;i++)//开始传输8个字节的数据{IO=dat&0x01;//取最低位,注意DS1302的数据和地址都是从最低位开始传输的delayus(2);SCLK=1;//时钟线拉高,制造上升沿,SDA的数据被传输delayus(2);SCLK=0;//时钟线拉低,为下一个上升沿做准备dat>>=1;//数据右移一位,准备传输下一位数据}}/********1302的驱动程序**********///功能: 读取数据,dat:读取的数据uchar DS1302ReadByte(){ uchar i;uchar dat;delayus(2);for(i=0;i<8;i++){dat>>=1;//要返回的数据左移一位if(IO==1)//当数据线为高时,证明该位数据为1dat|=0x80;//要传输数据的当前值置为1,若不是,则为0SCLK=1;//拉高时钟线delayus(2);SCLK=0;//制造下降沿delayus(2);}return dat;//返回读取出的数据/16*10+dat%16}/*********1302的驱动程序*********///从cmd相应地址中读取一个字节的数据uchar DS1302Read(uchar cmd)//cmd:要写入的控制字节,dat:读取的数据{uchar dat;RST=0;//初始CE线置为0SCLK=0;//初始时钟线置为0RST=1;//初始CE置为1,传输开始DS1302WriteByte(cmd);//传输命令字,要读取的时间/日历地址dat=DS1302ReadByte();//读取要得到的时间/日期SCLK=1;//时钟线拉高RST=0;//读取结束,CE置为0,结束数据的传输return dat;//返回得到的时间/日期}/**********1302的驱动程序*********///向cmd相应地址中写一个字节的数据void DS1302Write(uchar cmd, uint dat)//cmd:要写入的控制字,dat:要写入的数据{RST=0; //初始CE线置为0SCLK=0; //初始时钟线置为0RST=1; //初始CE置为1,传输开始DS1302WriteByte(cmd); //传输命令字,要写入的时间/日历地址DS1302WriteByte(dat); //写入要修改的时间/日期SCLK=1; //时钟线拉高RST=0; //读取结束,CE置为0,结束数据的传输}/*************初始化ds1302********///给1302写入日期和时钟的值void chushihuaDS1302(void){DS1302Write(0x8e,0x00);//写保护关DS1302Write(0x80,0x10); //初始秒DS1302Write(0x82,0x02);//初始分钟DS1302Write(0x84,0x15); //初始为24小时模式,初始时DS1302Write(0x86,0x01); //1日DS1302Write(0x88,0x08);//8月DS1302Write(0x8c,0x13);//2013年DS1302Write(0x8a,0x04);//星期4// DS1302Write(0x90,0x01); //充电//DS1302Write(0xc0,0xf0); //初始化一次标示//DS1302Write(0x8e,0x80);//写保护开}/************以下是1602的程序******************//******************************///向1602内写命令void write_order(uchar order){RS=0;P0=order;delayms(5);EN=1;delayms(5);EN=0;}/******************************///向1602内写数据void write_date(uchar date){RS=1;P0=date;delayms(5);EN=1;delayms(5);EN=0;}/******************************///lcd1602的初始化void chushihuaLCD1602(){ EN=0;write_order(0x38);write_order(0x0c);write_order(0x06);write_order(0x01);}/*************其他操作*****************/void gettime(){ uchar i,n;for(i=0,n=1;i<7,n<15;i++,n=n+2){ DateTime[i]=DS1302Read(0x80+n);delayus(1);}}void zhuanhuan(){ gettime();lcd1[5]=((DateTime[6]>>4)+0x30);lcd1[6]=((DateTime[6]&0x0f)+0x30);delayus(2);//年lcd1[14]=((DateTime[5]>>4)+0x30);lcd1[15]=((DateTime[5]&0x0f)+0x30);delayus(2);//周lcd1[11]=((DateTime[3]>>4)+0x30);lcd1[12]=((DateTime[3]&0x0f)+0x30);delayus(2);//日lcd1[8]=((DateTime[4]>>4)+0x30);lcd1[9]=((DateTime[4]&0x0f)+0x30);delayus(2);//月lcd2[5]=((DateTime[2]>>4)+0x30);lcd2[6]=((DateTime[2]&0x0f)+0x30);delayus(2);//时lcd2[8]=((DateTime[1]>>4)+0x30);lcd2[9]=((DateTime[1]&0x0f)+0x30);delayus(2);//分lcd2[11]=((DateTime[0]>>4)+0x30);lcd2[12]=((DateTime[0]&0x0f)+0x30);delayus(2);//秒if(DateTime[7]==DateTime[2] & DateTime[8]==DateTime[1]){led = 1;delayms(150);led = 0;}/**/}/***********************/void jianpan() //键盘调时{ uchar x2,address,max,min;int item;if(key1==0){ delayms(10);if(key1==0){ x1++;if(x1>=7) x1=1;switch(x1){ case 1: lcd2[15]='Y';x2=1;address=0x8c; max=99;min=0;break;//年case 2: lcd2[15]='M';x2=2;address=0x88; max=12;min=1;break;//月case 3: lcd2[15]='D';x2=3;address=0x86; max=31;min=1;break;//天case 4: lcd2[15]='H';x2=4;address=0x84; max=23;min=0;break;//时case 5: lcd2[15]='F';x2=5;address=0x82; max=59;min=0;break;//分case 6: lcd2[15]='W';x2=6;address=0x8A; max=7;min=1;break;//周}}while(!key1);}item=(DS1302Read(address+1)/16)*10 + (DS1302Read(address+1))%16;if(key2==0){ delayms(10);if(key2==0){ if(x2==1) {item++;}else if(x2==2) {item++;}else if(x2==3) {item++;}else if(x2==4) {item++;}else if(x2==5) {item++;}else if(x2==6) {item++;}}while(!key2);}if(key3==0){ delayms(10);if(key3==0){ if(x2==1) {item--;}else if(x2==2) {item--;}else if(x2==3) {item--;}else if(x2==4) {item--;}else if(x2==5) {item--;}else if(x2==6) {item--;}}while(!key3);}if(key4==0){ delayms(10);if(key4==0){ lcd2[15]=' ';x1=0;x2=0;}while(!key4);}//led=0;delayms(5000);led=1;if(item>max) item=min;if(item<min) item=max;DS1302Write(0x8e,0x00);//允许写操作delayms(10);DS1302Write(address,(item/10)*16+item%10); //写入DS1302 //转成BCD码delayms(20);DS1302Write(0x8e,0x80);//写保护,禁止写操作}void naozhong()//设定闹钟{ uchar da,xiao,i;if(key11==0){ delayms(10);if(key11==0){ x++;if(x>=4) x=1;switch(x){case 2: lcd2[13]='H';i=1;da=23;xiao=0;lcd2[14]=((hour>>4)+0x30);lcd2[15]=((hour&0x0f)+0x30);delayus(2);break;//时case 1: lcd2[13]='M';i=2;da=59;xiao=0;lcd2[14]=((minute>>4)+0x30);lcd2[15]=((minute&0x0f)+0x30);delayus(2);break;//分case 3: lcd2[13]=' ';lcd2[14]=' ';lcd2[15]=' ';x=0;i=0;break;}}while(!key11);}if(key22==0){ delayms(10);if(key22==0){ if(i==1){ hour=((hour/16)*10)+(hour%16);hour++;if(hour>da) hour=xiao;hour=(hour/10)*16+hour%10;lcd2[14]=((hour>>4)+0x30);lcd2[15]=((hour&0x0f)+0x30);delayus(2);}else if(i==2){ minute=((minute/16)*10)+(minute%16);minute++;if(minute>da) minute=xiao;minute=(minute/10)*16+minute%10;lcd2[14]=((minute>>4)+0x30);lcd2[15]=((minute&0x0f)+0x30);delayus(2);}}while(!key22);}if(key33==0){ delayms(10);if(key33==0){ if(i==1){ hour=((hour/16)*10)+(hour%16);hour--;if(hour<xiao) hour=da;hour=(hour/10)*16+hour%10;lcd2[14]=((hour>>4)+0x30);lcd2[15]=((hour&0x0f)+0x30);delayus(2);}else if(i==2){ minute=((minute/16)*10)+(minute%16);minute--;if(minute<xiao) minute=da;minute=(minute/10)*16+minute%10;lcd2[14]=((minute>>4)+0x30);lcd2[15]=((minute&0x0f)+0x30);delayus(2);}}while(!key33);}DateTime[7]=hour;DateTime[8]=minute;}/**/void wzd0() interrupt 0//外部中断0{jianpan();//}void wzd1() interrupt 2//外部中断1{naozhong();}void main(){uchar k;EA=1;EX0=1;IT0=1;PX0=1;EX1=1;IT1=1;PX1=0;RW=0;led=0;chushihuaLCD1602();if( (DS1302Read(0x81) & 0x80) ) chushihuaDS1302();//chushihuaDS1302();while(1){zhuanhuan();write_order(0x80);//lcd的第一行for(k=0;k<16;k++){ write_date(lcd1[k]);delayus(2);}write_order(0x80+0x40);//lcd的第二行for(k=0;k<16;k++){ write_date(lcd2[k]);delayus(2);}}}。
基于52单片机的万年历显示(采用实时芯片DS1302芯片+LCD1602液晶显示)仿真图:/************************************************************-- THE LCD1602 DISPLAY LIB -—COPYRIGHT (C) 2014 BY LLH-— ALL RIGHTS RESERVED —-ATTENTION:延时不能过长,否则无法与DS1302同步(最好小于1ms)*************************************************************/#ifndef __LCD1602_DIS_H__#define __LCD1602_DIS_H__#define uint unsigned int#define uchar unsigned charsbit lcd_rs=P2^0;sbit lcd_rw=P2^1;sbit lcd_en=P2^2;/**********延时子程序************/void delay(uint z){uint x,y;for(x=z;x〉0;x—-)for(y=65;y〉0;y--);//60刚好和DS1302同步}/***********写命令子程序**********/void write_com(uchar com){lcd_rs=0;lcd_rw=0;P0=com;delay(1);lcd_en=1;delay(1);lcd_en=0;}/***********写数据子程序**********/void write_data(uchar date){lcd_rs=1;lcd_rw=0;P0=date;delay(1);lcd_en=1;delay(1);lcd_en=0;}/**********初始化子程序************/void init_LCD1602(){lcd_en=0;write_com(0x38); //显示模式设置:16*2显示,5*7点阵,8位数据接口write_com(0x0c); //开显示,不显示光标write_com(0x06); //指针、光标自动加一,整屏不移动write_com(0x80); //初始位置设置}/*********显示子程序***********/void display(uchar *str){while(*str!='\0’){write_data(*str);str++;}}#endifDS1302的H文件:/******************************************************************—— THE DS1302 REAL_TIME LIB —-COPYRIGHT (C) 2014 BY LLH-- ALL RIGHTS RESERVED ——ATTENTION:不能使用(i=0;i<8;i++),否则,液晶无法显示确切的时间(???);星期的显示多了一天(???)********************************************************************/#ifndef __DS1302_REAL_TIME_H__#define __DS1302_REAL_TIME_H__#define uint unsigned int#define uchar unsigned charsbit DS1302_RST=P1^5;sbit DS1302_SCLK=P1^6;sbit DS1302_IO=P1^7;sbit ACC0=ACC^0;sbit ACC7=ACC^7;typedef struct{uchar second;uchar minute;uchar hour;uchar week;uchar day;uchar month;uchar year;uchar date_str[11];uchar time_str[9];}date_time;/**************写数据定义*****************/#define DS1302_SECOND 0x80#define DS1302_MINUTE 0x82#define DS1302_HOUR 0x84#define DS1302_WEEK 0x8A#define DS1302_DAY 0x86#define DS1302_MONTH 0x88#define DS1302_YEAR 0x8C#define ST 0x00/*************单字节写数据子程序**************/void single_byte_write(uchar date){uchar i;ACC=date;for(i=8;i〉0;i--) //不能使用(i=0;i〈8;i++),否则,液晶只显示00000{DS1302_IO=ACC0;DS1302_SCLK=1;DS1302_SCLK=0;ACC=ACC>>1;}}/*************单字节读数据子程序**************/uchar single_byte_read( ){uchar i;for(i=8;i>0;i--){ACC=ACC>〉1;ACC7=DS1302_IO;DS1302_SCLK=1;DS1302_SCLK=0;}return ACC;}/**************控制字的写入****************/void write_command(uchar addr,uchar dat){DS1302_SCLK=0;DS1302_RST=0;DS1302_RST=1;single_byte_write(addr);single_byte_write(dat);DS1302_SCLK=1;DS1302_RST=0;}/**************读取芯片内部的数据****************/uchar read_data(uchar address){uchar r_data;DS1302_SCLK=0;DS1302_RST=0;DS1302_RST=1;single_byte_write(address|0x01);//若没加(或0x01)ds1302和lcd1602都无法正常显示(?)r_data=single_byte_read();DS1302_SCLK=1;DS1302_RST=0;return r_data;}/************初始化子程序************/void init_DS1302(){uchar temp;temp=read_data(DS1302_SECOND);if(temp&0x80){write_command(0x8e,0x00); //启动读写write_command(0x84,0x00);//设置24小时模式write_command(DS1302_SECOND,ST); //写入当前时间数据}}/*************读取时间、并实现BCD和十进制间的转化***************//****************************************************************十进制转8421编码:32/10 = 3*16= 48(十进制)= 30(16进制)32%10 = 230+2 = 32 * 16 + 32 % 10 = 32(8421编码)(即:a/10*10+a%10)8421编码转十进制:51 / 16 = 5 * 10(16进制) = 50(十进制)51 % 16 = 150 + 1 = 51 / 16 + 51 % 16 = 51(十进制)(即:a/16*10+a%16)*****************************************************************/void get_time(date_time *Time){uchar value;value=read_data(DS1302_SECOND);Time—〉second=(value/16)*10+(value%16);value=read_data(DS1302_MINUTE);Time—〉minute=(value/16)*10+(value%16);value=read_data(DS1302_HOUR);(完整word版)万年历(DS1302+LCD1602【程序、仿真、完整】) Time-〉hour=(value/16)*10+(value%16);value=read_data(DS1302_WEEK);Time—〉week=(value/16)*10+(value%16-1);//星期的显示数值比正确值多一value=read_data(DS1302_DAY);Time-〉day=(value/16)*10+(value%16);value=read_data(DS1302_MONTH);Time—>month=(value/16)*10+(value%16);value=read_data(DS1302_YEAR);Time-〉year=(value/16)*10+(value%16);}/**************年-月-日-星期“字符”显示***************/void date_to_str(date_time *Time){Time-〉date_str[0]=Time-〉year/10+’0’; //加’0’转化成字符Time—〉date_str[1]=Time—〉year%10+’0';Time->date_str[2]='—’;Time->date_str[3]=Time->month/10+'0';Time->date_str[4]=Time-〉month%10+'0’;Time—>date_str[5]=’—’;Time-〉date_str[6]=Time-〉day/10+'0';Time—>date_str[7]=Time—>day%10+’0’;Time-〉date_str[8]=’-’;Time->date_str[9]=Time—〉week%10+’0’;Time-〉date_str[10]='\0';}/**************时-分-秒“字符”显示***************/void time_to_str(date_time *Time){Time—>time_str[0]=Time->hour/10+’0';Time-〉time_str[1]=Time—〉hour%10+’0';Time—>time_str[2]=’-';Time—>time_str[3]=Time—>minute/10+'0’;Time—>time_str[4]=Time—>minute%10+'0’;Time->time_str[5]='—';Time->time_str[6]=Time->second/10+'0';Time->time_str[7]=Time—>second%10+'0';Time-〉time_str[8]=’\0';}#endif万年历C文件:/********************************************************* TITLE: 实时时钟FUNCTION: DS1302+LCD1602显示实时时钟WRITER: LINLIANHUO(完整word版)万年历(DS1302+LCD1602【程序、仿真、完整】) TIME: 2014-07-30REMARK: matters need attention**********************************************************/#include 〈reg51.h〉#include <string.h〉#include ”DS1302。
电子系统设计实验报告实验目的:1、能够以DS1302实时时钟芯片和液晶显示屏CD1602为基础设计一款电子钟2、熟悉DS1302芯片的工作过程3、熟悉CD1602芯片的工作过程4、可以进行必要的扩展,如用第三DS18B20新品进行温度采集和显示5、熟悉掌握51的c程序的编写6、掌握用Proteus进行系统设计仿真验证实验仪器、仪表目录1、DS1302实时时钟芯片1片2、LCD1602液晶显示屏1个,3、80C52芯片1片5、DS18B20芯片一片6、晶振、电容、电阻、开关各若干等7、proteus仿真软件8、Keil C51、PC机实验设计任务以DS1302实时时钟芯片和液晶显示屏LCD1602为基础设计一个电子钟,要求:时间和日期可调整,按键采用3个按键;至少在Proteus上调试通过。
扩展:闹钟和重要日期提醒功能(增加蜂鸣器),闹铃音乐功能实验步骤1、打开Keil软件,新建一个工程文件,选择好芯片,并记得在“Options for Target 1”的Output 选项中,将Create HEX Fil选项勾起来。
2、将编写的程序保存成“.C”的形式3、编译保存好的C文件,并根据提示修改程序中的错误,直到编译成功为止4、打开proteus软件,画出实验电路图5、在89C52中,载入原来已生成的HEX文档6、按下运行键,对Proteus进行软件仿真,观察运行结果原理、结果及分析一、设计方案原理与设计特点分析电子钟总的设计模块:各个模块电路原理分析:1、DS1302时钟采集模块:1.1电路原理图:1.2 DS1302分析:首先DS1302是DALLAS公司推出的涓流充电时钟芯片。
内含有一个实时时钟/日历和31字节静态RAM通过简单的串行接口与单片机进行通信实时时钟/日历电路提供秒分时日日期月年的信息每月的天数和闰年的天数可自动调整时钟操作。
DS1302芯片广脚介绍:X1、X2为32.768KHz晶振管脚。
#include<>#define uchar unsigned char#define uint unsigned intsbit lcdws=P2^1; //1602管脚定义sbit lcden=P2^0;sbit lcdrs=P2^2;sbit key1=P2^3; //闹钟设置键sbit key2=P2^4;sbit key3=P1^5;//功能键定义sbit key4=P1^6;//增大键定义sbit key5=P1^7;//减小键定义uchar shi,fen,miao,ashi,afen,amiao,year,month,day,week; uchar s1num=0,s1num2=0,temp;bit flag;float f_temp;uint i,d;uchar code table2[]={0x20,0x20,0x2e,0x20,0xdf,0x43}; uchar code table[]="20 - - ";uchar code table1[]=" : : ";sbit ds=P1^0;//ds18b20信号线sbit beep=P1^4; //蜂鸣器管脚定义sbit ACC_7 = ACC^7; //位寻址寄存器定义sbit SCLK = P1^2; // DS1302时钟信号sbit DIO= P1^1; // DS1302数据信号sbit CE = P1^3;//地址、数据发送子程序//void delay2(uint ms)// {// uchar t;// while(ms--); for(t=0;t<120;t++);//}// void playmusic()// {// uint i2=0,j2,k2;// while(jiepai[i2]!=0||song[i2]!=0)// {// for(j2=0;j2<jiepai[i2]*20;j2++)// {// beep=~beep;// for(k2=0;k2<song[i2]/3;k2++);// }// delay2(10);// i2++;// }// }void write_1302( uchar addr,uchar dat ){uchar i,temp;CE=0; //CE 引脚为低,数据传送中止 SCLK=0; //清零时钟总线CE = 1; //CE 引脚为高,逻辑控制有效 //发送地址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 = dat;DIO = (bit)(temp&0x01);dat >>= 1;SCLK = 1;}CE = 0;}//数据读取子程序uchar Read1302 ( uchar addr ){unsigned char i,temp,dat1,dat2;CE=0;SCLK=0;CE = 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;}CE=0;dat1=ACC;dat2=dat1/16; //数据进制转换//十六进制转十进制dat1=dat1%16;dat1=dat1+dat2*10;return (dat1);}//初始化 DS1302void Initial(void) //初始化1302 2010年09月30日23点58分56秒星期一{write_1302 (0x8e,0x00); //允许写保护write_1302 (0x80,0x56); //秒位初始化write_1302 (0x82,0x58); //分钟初始化write_1302 (0x84,0x23); //小时初始化write_1302 (0x86,0x30); //日初始化write_1302 (0x88,0x09); //月初始化write_1302 (0x8c,0x10); //年初始化write_1302 (0x8a,0x01); //日期始化write_1302 (0x8e,0x80); //禁止写保护}void delay(uint z)//延时1ms{uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void write_com(uchar com)//1602写命令{lcdrs=0;lcden=0;P0=com;delay(5);lcden=1;delay(5);lcden=0;}void write_data(uchar date)//1602写数据{lcdrs=1;lcden=0;P0=date;delay(5);lcden=1;delay(5);lcden=0;}void dsreset(void) //DS18B20,初始化函数{uint i;ds=0;i=103;while(i>0)i--;ds=1;i=4;while(i>0)i--;}bit tempreadbit(void)//读1位数据函数{uint i;bit dat;ds=0;i++;ds=1;i++;i++;//i++起到延时作用dat=ds;i=8;while(i>0)i--;return(dat);}uchar tempread(void) //读一个字节数据函数{uchar i,j,dat;dat=0;for(i=1;i<=8;i++){j=tempreadbit();dat=(j<<7)|(dat>>1);}return(dat);}void tempwritebyte(uchar dat) //向DS18B20写一个字节数据函数{uint i;uchar j;bit testb;for(j=1;j<=8;j++){testb=dat&0x01;dat=dat>>1;if(testb)//写1{ds=0;i++;i++;ds=1;i=8;while(i>0)i--;}else{ds=0; //写0i=8;while(i>0)i--;ds=1;i++;i++;}}}void tempchange(void) //DS18B20开始获取温度并转换{dsreset();delay(1);tempwritebyte(0xcc);tempwritebyte(0x44);}uint get_temp() //获取温度{uchar a,b;dsreset();delay(1);tempwritebyte(0xcc);tempwritebyte(0xbe);a=tempread(); //读高8位b=tempread(); //读低8位temp=b;temp<<=8; //两个字节组合成1个字节temp=temp|a;f_temp=temp*;temp=f_temp*10+;f_temp=f_temp+; //温度在寄存器中为12位,分辨率为^ return temp;}void display(uchar addr,uchar dat){write_com(0x80+0x40+addr);write_data(0x30+dat);delay(5);}void dis_temp(uint t){uchar i;i=t/100;display(10,i);i=t%100/10;display(11,i);i=t%100%10;display(13,i);}void init()//初始化程序{uchar num;flag=1;lcden=0;write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x01);write_com(0x80);for(num=0;num<15;num++){write_data(table[num]);delay(5);}write_com(0x80+0x40);for(num=0;num<8;num++){write_data(table1[num]);delay(5);}write_com(0x80+0x40+10);for(num=0;num<6;num++){write_data(table2[num]);delay(10);}}void di()//蜂鸣器响函数{beep=0;delay(100);beep=1;}void write_sfm(uchar add,uchar date){uchar shi,ge;shi=date/10;ge=date%10;write_com(0x80+0x40+add);write_data(0x30+shi);write_data(0x30+ge);}void write_nyrz(uchar add,uchar date)//显示年,月,日,周{uchar shi,ge;shi=date/10;ge=date%10;write_com(0x80+add);write_data(0x30+shi);write_data(0x30+ge);}void display_week(uchar we){write_com(0x80+12);switch(we){case 1: write_data('M');delay(5);write_data('O');delay(5);write_data('N');break;case 2: write_data('T');delay(5);write_data('U');delay(5);write_data('E');break;case 3: write_data('W');delay(5);write_data('E');delay(5);write_data('D');break;case 4: write_data('T');delay(5);write_data('H');delay(5);write_data('U');break;case 5: write_data('F');delay(5);write_data('R');delay(5);write_data('T');break;case 6: write_data('S');delay(5);write_data('A');delay(5);write_data('T');break;case 7: write_data('S');delay(5);write_data('U');delay(5);write_data('N');break;}}void keyscan()//按键设置{if(key3==0)//功能键按下{flag=0;delay(5);if(key3==0){s1num++;while(!key3);di();switch(s1num)//光标闪烁定位{case 1:write_com(0x80+0x40+7);//定位到秒的位置write_com(0x0f);break;case 2:write_com(0x80+0x40+4);//定位到分的位置write_com(0x0f);break;case 3:write_com(0x80+0x40+1);//定位到小时的位置write_com(0x0f);break;case 4:write_com(0x80+0x0e);//定位到星期的位置write_com(0x0f);break;case 5:write_com(0x80+0x9);//定位到日的位置write_com(0x0f);break;case 6:write_com(0x80+0x6);//定位到月的位置write_com(0x0f);break;case 7:write_com(0x80+0x3);//定位到年的位置write_com(0x0f);break;case 8: s1num=0;//复位,时钟走write_com(0x0c);flag=1;write_1302 (0x8e,0x00); //允许写保护 write_1302 (0x80,miao); //秒位初始化 write_1302 (0x82,fen); //分钟初始化write_1302 (0x84,shi); //小时初始化 write_1302 (0x86,day); //日初始化write_1302 (0x88,month); //月初始化write_1302 (0x8c,year); //年初始化write_1302 (0x8a,week); //日期始化write_1302 (0x8e,0x80); //禁止写¥break;}}}if(s1num!=0)//只有功能键按下后,增大,增小建才有效{if(key4==0)//增大建{delay(5);if(key4==0){while(!key4);di();switch(s1num){case 1: miao++;if(miao==60)miao=0;write_sfm(6,miao);//write_1302(write_second,miao);write_com(0x80+0x40+7);break;case 2: fen++;if(fen==60)fen=0;write_sfm(3,fen);//write_1302(write_minute,fen);write_com(0x80+0x40+4);break;case 3: shi++;if(shi==24)shi=0;write_sfm(0,shi);write_com(0x80+0x40+1);break;case 4: week++;if(week==8)week=1;display_week(week);write_com(0x80+14);break;case 5: day++;if(day==31)day=1;write_nyrz(8,day);write_com(0x80+9);break;case 6: month++;if(month==13)month=1;write_nyrz(5,month);write_com(0x80+6);break;case 7: year++;if(year==99)year=0;write_nyrz(2,year);write_com(0x80+3);break;}}}if(key5==0)//减小键{delay(5);if(key5==0){while(!key5);di();switch(s1num){case 1: miao--;if(miao==-1)miao=59;write_sfm(6,miao);write_com(0x80+0x40+7);break;case 2: fen--;if(fen==-1)fen=59;write_sfm(3,fen);write_com(0x80+0x40+4);break;case 3: shi--;if(shi==-1)shi=23;write_sfm(0,shi);write_com(0x80+0x40+1);break;case 4: week--;if(week==-1)week=7;display_week(week);write_com(0x80+14);break;case 5: day--;if(day==0)day=31;write_nyrz(8,day);write_com(0x80+9);break;case 6: month--;if(month==0)month=12;write_nyrz(5,month);write_com(0x80+6);break;case 7: year--;if(year==-1)year=99;write_nyrz(2,year);write_com(0x80+3);break;}}}}}void set_alarm(){if(key1==0)//功能键按下{delay(5);if(key1==0){while(!key1);flag=0;s1num2++;write_sfm(6,amiao);write_com(0x80+0x40+7);write_sfm(3,afen);write_com(0x80+0x40+4);write_sfm(0,ashi);write_com(0x80+0x40+1);di();switch(s1num2)//光标闪烁定位{case 1:write_com(0x80+0x40+7);//定位到秒的位置write_com(0x0f);break;case 2:write_com(0x80+0x40+4);//定位到分的位置write_com(0x0f);break;case 3:write_com(0x80+0x40+1);//定位到小时的位置write_com(0x0f);break;case 4: s1num2=0;//复位,时钟走write_com(0x0c);flag=1;// write_1302(0x8e,0x00);//允许写保护write_1302 (0x8e,0x80);break;}}}if(s1num2!=0)//只有功能键按下后,增大,增小建才有效{if(key2==0)//增大建{delay(5);if(key2==0){while(!key2);di();switch(s1num2){case 1: amiao++;if(amiao==60)amiao=0;write_sfm(6,amiao);write_com(0x80+0x40+7);break;case 2: afen++;if(afen==60)afen=0;write_sfm(3,afen);write_com(0x80+0x40+4);break;case 3: ashi++;if(ashi==24)ashi=0;write_sfm(0,ashi);write_com(0x80+0x40+1);break;}}}}}void main()//主函数{Initial();lcdws=0;init();// IntConfiguration();tempchange();for(i=10;i>0;i--){dis_temp(get_temp());}while(1){keyscan();//按键扫描// while((key1&&key2&&key3&&key4&&key5)&&((fen==afen)&&(shi==ashi))) // {// beep=0;// delay(500);// beep=1;// }if(flag==1){miao=Read1302(0x81);//显示秒write_sfm(6,miao);fen=Read1302(0x83);//显示分write_sfm(3,fen);shi=Read1302(0x85);//显示小时write_sfm(0,shi);day=Read1302(0x87);//显示日write_nyrz(8,day);month=Read1302(0x89);//显示月write_nyrz(5,month);year=Read1302(0x8d);//显示年write_nyrz(2,year);week=Read1302(0x8b);//显示日期display_week(week);}else{write_1302(0x80,0x80);//时钟振荡器停止}set_alarm();}}。
基于利用时钟芯片DS1302实现万年历,1602LCD显示电子表电子设计大赛培训第二时期第**组报告《基于利用时钟芯片DS1302实现万年历,1602LCD显示电子表》成员姓名:*** 学号:******成员姓名:HG** 学号:******成员姓名:*** 学号:*******一、要紧功能1、在1602液晶上显示年、月、日、星期、时、分、秒以及实时温度,同时实时更新显示;2、通过按键随时调剂各显示参数,分别实现光标定位、数值增大、数值减小、闹钟和温度上下限查看的功能;3.在时刻显现乱码的情形下,具有一键初始化时刻的功能。
二、电路图三、实物图1.开关模块2、显示模块3、at89c52模块4、总体连接图四、心得体会本次设计是我们遇到过的较大的设计,因此遇到的问题也比较的多,专门是往常没有接触过如此复杂的硬件电路以及软件编程,在软、硬件设计和调试中遇到了许多的困难,在同学的关心才逐一克服了难题,学习到了许多的专业知识。
在整个设计过程之前,我差不多在网上找了相关方面的资料,万事开始难,一开始不明白从哪里下手。
后来慢慢学会分析系统,将系统模块化,各个模块能够在软件或者硬件上实现。
在确保各个模块的硬件电路和与之相搭配的程序能够正常工作后在把它们组成一个系统。
在今后的生活里,我会进一步加强自己的动手能力,丰富自己的知识面。
总之,这次设计给我的最大感触确实是,在以后的学习中勤动脑,多动手。
附录:1、元件清单AT89C52 一块LCD 一个排阻 3个DS1302 一个DS18B20 一个开关 5个晶振 2个瓷片电容 2个, 30PF电解电容一个, 33Uf插针若干杜邦线若干2、程序#include <REG51.H>#include <intrins.h>//#include "LCD1602.h"//#include "DS1302.h"#define uint unsigned int#define uchar unsigned charsbit DS1302_CLK = P1^7; //实时时钟时钟线引脚sbit DS1302_IO = P1^6; //实时时钟数据线引脚sbit DS1302_RST = P1^5; //实时时钟复位线引脚sbit wireless_1 = P3^0;sbit wireless_2 = P3^1;sbit wireless_3 = P3^2;sbit wireless_4 = P3^3;sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;charhide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year; //秒,分,时到日,月,年位闪的计数sbit Set = P2^0; //模式切换键sbit Up = P2^1; //加法按钮sbit Down = P2^2; //减法按钮sbit out = P2^3; //赶忙跳出调整模式按钮sbit DQ = P1^0; //温度传送数据IO口char done,count,temp,flag,up_flag,down_flag;uchar temp_value; //温度值uchar TempBuffer[5],week_value[2];void show_time(); //液晶显示程序/***********1602液晶显示部分子程序****************///PortDefinitions********************************************************* *sbit LcdRs = P2^5;sbit LcdRw = P2^6;sbit LcdEn = P2^7;sfr DBPort = 0x80; //P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口//内部等待函数******************************************************************** ******unsigned char LCD_Wait(void){LcdRs=0;LcdRw=1; _nop_();LcdEn=1; _nop_();LcdEn=0;return DBPort;}//向LCD写入命令或数据************************************************************#define LCD_COMMAND 0 // Command#define LCD_DATA 1 // Data#define LCD_CLEAR_SCREEN 0x01 // 清屏#define LCD_HOMING 0x02 // 光标返回原点void LCD_Write(bit style, unsigned char input){LcdEn=0;LcdRs=style;LcdRw=0; _nop_();DBPort=input; _nop_();//注意顺序LcdEn=1; _nop_();//注意顺序LcdEn=0; _nop_();LCD_Wait();}//设置显示模式************************************************************#define LCD_SHOW 0x04 //显示开#define LCD_HIDE 0x00 //显示关#define LCD_CURSOR 0x02 //显示光标#define LCD_NO_CURSOR 0x00 //无光标#define LCD_FLASH 0x01 //光标闪动#define LCD_NO_FLASH 0x00 //光标不闪动void LCD_SetDisplay(unsigned char DisplayMode){LCD_Write(LCD_COMMAND, 0x08|DisplayMode);}//设置输入模式************************************************************#define LCD_AC_UP 0x02#define LCD_AC_DOWN 0x00 // default#define LCD_MOVE 0x01 // 画面可平移#define LCD_NO_MOVE 0x00 //defaultvoid LCD_SetInput(unsigned char InputMode){LCD_Write(LCD_COMMAND, 0x04|InputMode);}//初始化LCD************************************************************void LCD_Initial(){LcdEn=0;LCD_Write(LCD_COMMAND,0x38); //8位数据端口,2行显示,5*7点阵LCD_Write(LCD_COMMAND,0x38);LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); //开启显示, 无光标LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏LCD_SetInput(LCD_AC_UP|LCD_NO_MOVE); //AC递增, 画面不动}//液晶字符输入的位置************************void GotoXY(unsigned char x, unsigned char y){if(y==0)LCD_Write(LCD_COMMAND,0x80|x);if(y==1)LCD_Write(LCD_COMMAND,0x80|(x-0x40));}//将字符输出到液晶显示void Print(unsigned char *str){while(*str!='\0'){LCD_Write(LCD_DATA,*str);str++;}}/***********DS1302时钟部分子程序******************/typedef struct __SYSTEMTIME__{unsigned char Second;unsigned char Minute;unsigned char Hour;unsigned char Week;unsigned char Day;unsigned char Month;unsigned char Year;unsigned char DateString[11];unsigned char TimeString[9];}SYSTEMTIME; //定义的时刻类型SYSTEMTIME CurrentTime;#define AM(X) X#define PM(X) (X+12) // 转成24小时制#define DS1302_SECOND 0x80 //时钟芯片的寄存器位置,存放时刻#define DS1302_MINUTE 0x82#define DS1302_HOUR 0x84#define DS1302_WEEK 0x8A#define DS1302_DAY 0x86#define DS1302_MONTH 0x88#define DS1302_YEAR 0x8Cvoid DS1302InputByte(unsigned char d) //实时时钟写入一字节(内部函数) {unsigned char i;ACC = d;for(i=8; i>0; i--){DS1302_IO = ACC0; //相当于汇编中的 RRCDS1302_CLK = 1;DS1302_CLK = 0;ACC = ACC >> 1;}}unsigned char DS1302OutputByte(void) //实时时钟读取一字节(内部函数) {unsigned char i;for(i=8; i>0; i--){ACC = ACC >>1; //相当于汇编中的 RRCACC7 = DS1302_IO;DS1302_CLK = 1;DS1302_CLK = 0;}return(ACC);}void Write1302(unsigned char ucAddr, unsigned char ucDa) //ucAddr: DS1302地址, ucData: 要写的数据{DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(ucAddr); // 地址,命令DS1302InputByte(ucDa); // 写1Byte数据DS1302_CLK = 1;DS1302_RST = 0;}unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据{unsigned char ucData;DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(ucAddr|0x01); // 地址,命令ucData = DS1302OutputByte(); // 读1Byte数据DS1302_CLK = 1;DS1302_RST = 0;return(ucData);}void DS1302_GetTime(SYSTEMTIME *Time) //猎取时钟芯片的时钟数据到自定义的结构型数组{unsigned char ReadValue;ReadValue = Read1302(DS1302_SECOND);Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_MINUTE);Time->Minute = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_HOUR);Time->Hour = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_DAY);Time->Day = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_WEEK);Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_MONTH);Time->Month = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_YEAR);Time->Year = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);}void DateToStr(SYSTEMTIME *Time) //将时刻年,月,日,星期数据转换成液晶显示字符串,放到数组里DateString[]{ if(hide_year<2) //那个地点的if,else语句差不多上判定位闪耀,<2显示数据,>2就不显示,输出字符串为 2007/07/22{Time->DateString[0] = '2';Time->DateString[1] = '0';Time->DateString[2] = Time->Year/10 + '0';Time->DateString[3] = Time->Year%10 + '0';}else{Time->DateString[0] = ' ';Time->DateString[1] = ' ';Time->DateString[2] = ' ';Time->DateString[3] = ' ';}Time->DateString[4] = '/';if(hide_month<2){Time->DateString[5] = Time->Month/10 + '0';Time->DateString[6] = Time->Month%10 + '0';}else{Time->DateString[5] = ' ';Time->DateString[6] = ' ';}Time->DateString[7] = '/';if(hide_day<2){Time->DateString[8] = Time->Day/10 + '0';Time->DateString[9] = Time->Day%10 + '0';}else{Time->DateString[8] = ' ';Time->DateString[9] = ' ';}if(hide_week<2){week_value[0] = Time->Week%10 + '0'; //星期的数据另外放到week_value[]数组里,跟年,月,日的分开存放,因为等一下要在最后显示}else{week_value[0] = ' ';}week_value[1] = '\0';Time->DateString[10] = '\0'; //字符串末尾加 '\0' ,判定终止字符}void TimeToStr(SYSTEMTIME *Time) //将时,分,秒数据转换成液晶显示字符放到数组 TimeString[];{ if(hide_hour<2){Time->TimeString[0] = Time->Hour/10 + '0';Time->TimeString[1] = Time->Hour%10 + '0';}else{Time->TimeString[0] = ' ';Time->TimeString[1] = ' ';}Time->TimeString[2] = ':';if(hide_min<2){Time->TimeString[3] = Time->Minute/10 + '0';Time->TimeString[4] = Time->Minute%10 + '0';}else{Time->TimeString[3] = ' ';Time->TimeString[4] = ' ';}Time->TimeString[5] = ':';if(hide_sec<2){Time->TimeString[6] = Time->Second/10 + '0';Time->TimeString[7] = Time->Second%10 + '0';}else{Time->TimeString[6] = ' ';Time->TimeString[7] = ' ';}Time->DateString[8] = '\0';}void Initial_DS1302(void) //时钟芯片初始化{unsigned char Second=Read1302(DS1302_SECOND);if(Second&0x80) //判定时钟芯片是否关闭{Write1302(0x8e,0x00); //写入承诺Write1302(0x8c,0x07); //以下写入初始化时刻日期:07/07/25.星期: 3. 时刻: 23:59:55Write1302(0x88,0x07);Write1302(0x86,0x25);Write1302(0x8a,0x07);Write1302(0x84,0x23);Write1302(0x82,0x59);Write1302(0x80,0x55);Write1302(0x8e,0x80); //禁止写入}}/***********ds18b20子程序*************************//***********ds18b20延迟子函数(晶振12MHz )*******/void delay_18B20(unsigned int i){while(i--);}/**********ds18b20初始化函数**********************/void Init_DS18B20(void){unsigned char x=0;DQ = 1; //DQ复位delay_18B20(8); //稍做延时DQ = 0; //单片机将DQ拉低delay_18B20(80); //精确延时大于 480usDQ = 1; //拉高总线delay_18B20(14);x=DQ; //稍做延时后假如x=0则初始化成功 x=1则初始化失败delay_18B20(20);}/***********ds18b20读一个字节**************/unsigned char ReadOneChar(void){uchar i=0;uchar dat = 0;for (i=8;i>0;i--){DQ = 0; // 给脉冲信号dat>>=1;DQ = 1; // 给脉冲信号if(DQ)dat|=0x80;delay_18B20(4);}return(dat);}/*************ds18b20写一个字节****************/void WriteOneChar(uchar dat){unsigned char i=0;for (i=8; i>0; i--){DQ = 0;DQ = dat&0x01;delay_18B20(5);DQ = 1;dat>>=1;}}/**************读取ds18b20当前温度************/void ReadTemp(void){unsigned char a=0;unsigned char b=0;unsigned char t=0;Init_DS18B20();WriteOneChar(0xCC); // 跃过读序号列号的操作WriteOneChar(0x44); // 启动温度转换delay_18B20(100); // this message is wery importantInit_DS18B20();WriteOneChar(0xCC); //跃过读序号列号的操作WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器)前两个确实是温度delay_18B20(100);a=ReadOneChar(); //读取温度值低位b=ReadOneChar(); //读取温度值高位temp_value=b<<4;temp_value+=(a&0xf0)>>4;}void temp_to_str() //温度数据转换成液晶字符显示{TempBuffer[0]=temp_value/10+'0'; //十位TempBuffer[1]=temp_value%10+'0'; //个位TempBuffer[2]=0xdf; //温度符号TempBuffer[3]='C';TempBuffer[4]='\0';}void Delay1ms(unsigned int count){unsigned int i,j;for(i=0;i<count;i++)for(j=0;j<120;j++);}/*延时子程序*/void mdelay(uint delay){ uint i;for(;delay>0;delay--){for(i=0;i<62;i++) //1ms延时.{;}}}void outkey() //跳出调整模式,返回默认显示{ uchar Second;if(out==0||wireless_1==1){ mdelay(8);count=0;hide_sec=0,hide_min=0,hide_hour=0,hide_day=0,hide_week=0,hide_mon th=0,hide_year=0;Second=Read1302(DS1302_SECOND);Write1302(0x8e,0x00); //写入承诺Write1302(0x80,Second&0x7f);Write1302(0x8E,0x80); //禁止写入done=0;while(out==0);while(wireless_1==1);}}//////////////////////////////////////////////////////////////////// ////////////////////////////////////////void Upkey()//升序按键{Up=1;if(Up==0||wireless_2==1){mdelay(8);switch(count){case 1:temp=Read1302(DS1302_SECOND); //读取秒数temp=temp+1; //秒数加1up_flag=1; //数据调整后更新标志if((temp&0x7f)>0x59) //超过59秒,清零temp=0;break;case 2:temp=Read1302(DS1302_MINUTE); //读取分数temp=temp+1; //分数加1up_flag=1;if(temp>0x59) //超过59分,清零temp=0;break;case 3:temp=Read1302(DS1302_HOUR); //读取小时数temp=temp+1; //小时数加1up_flag=1;if(temp>0x23) //超过23小时,清零temp=0;break;case 4:temp=Read1302(DS1302_WEEK); //读取星期数temp=temp+1; //星期数加1up_flag=1;if(temp>0x7)temp=1;break;case 5:temp=Read1302(DS1302_DAY); //读取日数temp=temp+1; //日数加1up_flag=1;if(temp>0x31)temp=1;break;case 6:temp=Read1302(DS1302_MONTH); //读取月数temp=temp+1; //月数加1up_flag=1;if(temp>0x12)temp=1;break;case 7:temp=Read1302(DS1302_YEAR); //读取年数temp=temp+1; //年数加1up_flag=1;if(temp>0x85)temp=0;break;default:break;}while(Up==0);while(wireless_2==1);}}//////////////////////////////////////////////////////////////////// ////////////////////////////////////////void Downkey()//降序按键{Down=1;if(Down==0||wireless_3==1){mdelay(8);switch(count){case 1:temp=Read1302(DS1302_SECOND); //读取秒数temp=temp-1; //秒数减1down_flag=1; //数据调整后更新标志if(temp==0x7f) //小于0秒,返回59秒temp=0x59;break;case 2:temp=Read1302(DS1302_MINUTE); //读取分数temp=temp-1; //分数减1down_flag=1;if(temp==-1)temp=0x59; //小于0秒,返回59秒break;case 3:temp=Read1302(DS1302_HOUR); //读取小时数temp=temp-1; //小时数减1down_flag=1;if(temp==-1)temp=0x23;break;case 4:temp=Read1302(DS1302_WEEK); //读取星期数temp=temp-1; //星期数减1down_flag=1;if(temp==0)temp=0x7;;break;case 5:temp=Read1302(DS1302_DAY); //读取日数temp=temp-1; //日数减1down_flag=1;if(temp==0)temp=31;break;case 6:temp=Read1302(DS1302_MONTH); //读取月数temp=temp-1; //月数减1down_flag=1;if(temp==0)temp=12;break;case 7:temp=Read1302(DS1302_YEAR); //读取年数temp=temp-1; //年数减1down_flag=1;if(temp==-1)temp=0x85;break;default:break;}while(Down==0);while(wireless_3==1);}}void Setkey()//模式选择按键{Set=1;if(Set==0||wireless_4==1){mdelay(8);count=count+1; //Setkey按一次,count就加1done=1; //进入调整模式while(Set==0);while(wireless_4==1);}}void keydone()//按键功能执行{ uchar Second;if(flag==0) //关闭时钟,停止计时{ Write1302(0x8e,0x00); //写入承诺temp=Read1302(0x80);Write1302(0x80,temp|0x80);Write1302(0x8e,0x80); //禁止写入flag=1;}Setkey(); //扫描模式切换按键 switch(count){case 1:do //count=1,调整秒{outkey(); //扫描跳出按钮Upkey(); //扫描加按钮Downkey(); //扫描减按钮if(up_flag==1||down_flag==1) //数据更新,重新写入新的数据{Write1302(0x8e,0x00); //写入承诺Write1302(0x80,temp|0x80); //写入新的秒数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_sec++; //位闪计数if(hide_sec>3)hide_sec=0;show_time(); //液晶显示数据}while(count==2);break;case 2:do //count=2,调整分{hide_sec=0;outkey();Upkey();Downkey();if(temp>0x60)temp=0;if(up_flag==1||down_flag==1)Write1302(0x8e,0x00); //写入承诺Write1302(0x82,temp); //写入新的分数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_min++;if(hide_min>3)hide_min=0;show_time();}while(count==3);break;case 3:do //count=3,调整小时{hide_min=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入承诺Write1302(0x84,temp); //写入新的小时数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_hour++;if(hide_hour>3)hide_hour=0;show_time();}while(count==4);break;case 4:do //count=4,调整星期{hide_hour=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入承诺Write1302(0x8a,temp); //写入新的星期数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;hide_week++;if(hide_week>3)hide_week=0;show_time();}while(count==5);break;case 5:do //count=5,调整日{hide_week=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入承诺Write1302(0x86,temp); //写入新的日数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_day++;if(hide_day>3)hide_day=0;show_time();}while(count==6);break;case 6:do //count=6,调整月{hide_day=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入承诺Write1302(0x88,temp); //写入新的月数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_month++;if(hide_month>3)hide_month=0;show_time();}while(count==7);break;case 7:do //count=7,调整年{hide_month=0;outkey();Upkey();Downkey();if(up_flag==1||down_flag==1){Write1302(0x8e,0x00); //写入承诺Write1302(0x8c,temp); //写入新的年数Write1302(0x8e,0x80); //禁止写入up_flag=0;down_flag=0;}hide_year++;if(hide_year>3)hide_year=0;show_time();}while(count==8);break;case 8: count=0;hide_year=0; //count8, 跳出调整模式,返回默认显示状态Second=Read1302(DS1302_SECOND);Write1302(0x8e,0x00); //写入承诺Write1302(0x80,Second&0x7f);Write1302(0x8E,0x80); //禁止写入done=0;break; //count=7,开启中断,标志位置0并退出default:break;}}void show_time() //液晶显示程序{DS1302_GetTime(&CurrentTime); //猎取时钟芯片的时刻数据TimeToStr(&CurrentTime); //时刻数据转换液晶字符DateToStr(&CurrentTime); //日期数据转换液晶字符ReadTemp(); //开启温度采集程序temp_to_str(); //温度数据转换成液晶字符GotoXY(12,1); //液晶字符显示位置Print(TempBuffer); //显示温度GotoXY(0,1);Print(CurrentTime.TimeString); //显示时刻GotoXY(0,0);Print(CurrentTime.DateString); //显示日期GotoXY(15,0);Print(week_value); //显示星期GotoXY(11,0);Print("Week"); //在液晶上显示字母 weekDelay1ms(400); //扫描延时}main(){flag=1; //时钟停止标志LCD_Initial(); //液晶初始化Init_DS18B20( ) ; //DS18B20初始化Initial_DS1302(); //时钟芯片初始化up_flag=0;down_flag=0;done=0; //进入默认液晶显示wireless_1=0;wireless_2=0;wireless_3=0;wireless_4=0;while(1){while(done==1)keydone(); //进入调整模式while(done==0){show_time(); //液晶显示数据 flag=0;Setkey(); //扫描各功能键}}}。
电子设计大赛培训第二阶段第**组报告《基于利用时钟芯片DS1302实现万年历,1602LCD显示电子表》成员姓名:*** 学号:******成员姓名:HG**学号:******成员姓名:*** 学号:*******一、主要功能1、在1602液晶上显示年、月、日、星期、时、分、秒以及实时温度,并且实时更新显示;2、通过按键随时调节各显示参数,分别实现光标定位、数值增大、数值减小、闹钟和温度上下限查看的功能;3.在时间出现乱码的情况下,具有一键初始化时间的功能。
二、电路图三、实物图1.开关模块2、显示模块3、at89c52模块4、总体连接图四、心得体会本次设计是我们遇到过的较大的设计,所以遇到的问题也比较的多,尤其是以前没有接触过如此复杂的硬件电路以及软件编程,在软、硬件设计和调试中遇到了不少的困难,在同学的帮助才逐一克服了难题,学习到了不少的专业知识。
在整个设计过程之前,我已经在网上找了相关方面的资料,万事开始难,一开始不知道从哪里下手。
后来慢慢学会分析系统,将系统模块化,各个模块可以在软件或者硬件上实现。
在确保各个模块的硬件电路和与之相搭配的程序能够正常工作后在把它们组成一个系统。
在今后的日子里,我会进一步加强自己的动手能力,丰富自己的知识面。
总之,这次设计给我的最大感触就是,在以后的学习中勤动脑,多动手。
附录:1、元件清单AT89C52一块LCD 一个排阻 3个DS1302一个DS18B20一个开关 5个晶振2个瓷片电容2个, 30PF电解电容一个,33Uf插针若干杜邦线若干2、程序#include <REG51.H>#include <intrins.h>//#include "LCD1602.h"//#include "DS1302.h"#define uint unsigned int#define uchar unsigned charsbit DS1302_CLK = P1^7; //实时时钟时钟线引脚sbit DS1302_IO = P1^6; //实时时钟数据线引脚sbit DS1302_RST=P1^5; //实时时钟复位线引脚sbitwireless_1 = P3^0;sbit wireless_2=P3^1;sbit wireless_3 = P3^2;sbit wireless_4 = P3^3;sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;char hide_sec,hide_min,hide_hour,hide_day,hide_week,hide_month,hide_year; //秒,分,时到日,月,年位闪的计数sbit Set = P2^0; //模式切换键sbit Up = P2^1; //加法按钮sbitDown = P2^2;//减法按钮sbit out = P2^3; //立刻跳出调整模式按钮sbit DQ =P1^0; //温度传送数据IO口char done,count,temp,flag,up_flag,down_flag;uchar temp_value;//温度值uchar TempBuffer[5],week_value[2];void show_time(); //液晶显示程序/***********1602液晶显示部分子程序****************///Port Definitions**********************************************************sbitLcdRsﻩ= P2^5;sbit LcdRwﻩ= P2^6;sbitLcdEn = P2^7;sfr DBPort = 0x80;ﻩ//P0=0x80,P1=0x90,P2=0xA0,P3=0xB0.数据端口//内部等待函数**************************************************************************unsignedchar LCD_Wait(void){ﻩLcdRs=0;ﻩLcdRw=1;ﻩ_nop_();LcdEn=1; _nop_();ﻩﻩﻩﻩLcdEn=0;ﻩreturnDBPort;}//向LCD写入命令或数据************************************************************#define LCD_COMMAND ﻩﻩ0 // Command#define LCD_DATAﻩ 1 //Data#defineLCD_CLEAR_SCREEN 0x01 // 清屏#define LCD_HOMING ﻩ0x02// 光标返回原点void LCD_Write(bit style, unsigned char input){LcdEn=0;ﻩLcdRs=style;LcdRw=0; ﻩ_nop_();DBPort=input;ﻩ_nop_();//注意顺序LcdEn=1; ﻩ_nop_();//注意顺序ﻩLcdEn=0; ﻩ_nop_();ﻩLCD_Wait();}//设置显示模式************************************************************#define LCD_SHOW ﻩﻩ0x04 //显示开#defineLCD_HIDEﻩ0x00 //显示关#define LCD_CURSORﻩ0x02 ﻩ//显示光标#define LCD_NO_CURSORﻩﻩ0x00 //无光标#define LCD_FLASH ﻩ0x01//光标闪动#define LCD_NO_FLASH ﻩ0x00 //光标不闪动void LCD_SetDisplay(unsignedchar DisplayMode){ﻩLCD_Write(LCD_COMMAND, 0x08|DisplayMode);ﻩ}//设置输入模式************************************************************#define LCD_AC_UP ﻩ0x02#define LCD_AC_DOWNﻩﻩ0x00 // default#define LCD_MOVEﻩﻩ0x01 // 画面可平移#define LCD_NO_MOVE ﻩ0x00 //defaultvoid LCD_SetInput(unsigned char InputMode){ﻩLCD_Write(LCD_COMMAND, 0x04|InputMode);}//初始化LCD************************************************************void LCD_Initial(){LcdEn=0;ﻩLCD_Write(LCD_COMMAND,0x38);//8位数据端口,2行显示,5*7点阵LCD_Write(LCD_COMMAND,0x38);LCD_SetDisplay(LCD_SHOW|LCD_NO_CURSOR); //开启显示, 无光标LCD_Write(LCD_COMMAND,LCD_CLEAR_SCREEN); //清屏ﻩLCD_SetInput(LCD_AC_UP|LCD_NO_MOVE); //AC递增, 画面不动}//液晶字符输入的位置************************void GotoXY(unsigned char x,unsigned char y){ﻩif(y==0)ﻩﻩLCD_Write(LCD_COMMAND,0x80|x);ﻩif(y==1)ﻩLCD_Write(LCD_COMMAND,0x80|(x-0x40));}//将字符输出到液晶显示void Print(unsigned char *str){while(*str!='\0')ﻩ{ﻩLCD_Write(LCD_DATA,*str);ﻩstr++;}}/***********DS1302时钟部分子程序******************/typedef struct __SYSTEMTIME__{ﻩunsigned char Second;ﻩunsigned char Minute;ﻩunsigned char Hour;unsigned char Week;ﻩunsigned char Day;ﻩunsigned char Month;ﻩunsigned char Year;ﻩunsigned char DateString[11];unsigned charTimeString[9];}SYSTEMTIME;//定义的时间类型SYSTEMTIME CurrentTime;#defineAM(X)ﻩX#define PM(X)ﻩ(X+12) // 转成24小时制#define DS1302_SECONDﻩ0x80 //时钟芯片的寄存器位置,存放时间#define DS1302_MINUTEﻩ0x82#define DS1302_HOUR ﻩ0x84#define DS1302_WEEKﻩ0x8A0x86#define DS1302_DAYﻩﻩ#define DS1302_MONTH 0x88#define DS1302_YEARﻩ 0x8Cvoid DS1302InputByte(unsigned char d) ﻩ//实时时钟写入一字节(内部函数){unsigned char i;ACC = d;for(i=8; i>0;i--){DS1302_IO = ACC0; ﻩ//相当于汇编中的RRC DS1302_CLK = 1;DS1302_CLK = 0;ACC = ACC >> 1;}}unsignedchar DS1302OutputByte(void) //实时时钟读取一字节(内部函数){unsigned char i;for(i=8;i>0; i--){ACC = ACC>>1; ﻩﻩ//相当于汇编中的RRCACC7 = DS1302_IO;DS1302_CLK = 1;DS1302_CLK = 0;}return(ACC);}void Write1302(unsigned char ucAddr, unsigned char ucDa)//ucAddr: DS1302地址, ucData: 要写的数据{DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(ucAddr); ﻩ// 地址,命令DS1302InputByte(ucDa); ﻩ//写1Byte数据DS1302_CLK = 1;DS1302_RST = 0;}unsignedchar Read1302(unsigned char ucAddr) //读取DS1302某地址的数据{unsignedchar ucData;DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1;DS1302InputByte(ucAddr|0x01); // 地址,命令ucData = DS1302OutputByte(); // 读1Byte数据DS1302_CLK = 1;DS1302_RST =0;return(ucData);}void DS1302_GetTime(SYSTEMTIME *Time)//获取时钟芯片的时钟数据到自定义的结构型数组{unsigned char ReadValue;ﻩReadValue = Read1302(DS1302_SECOND);ﻩTime->Second = ((ReadValue&0x70)>>4)*10+ (ReadVal ue&0x0F);ReadValue = Read1302(DS1302_MINUTE);Time->Minute = ((ReadValue&0x70)>>4)*10+ (ReadValue&0x0F);ReadValue = Read1302(DS1302_HOUR);Time->Hour= ((ReadValue&0x70)>>4)*10 +(ReadValue&0x0F);ReadValue = Read1302(DS1302_DAY);Time->Day =((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = Read1302(DS1302_WEEK);Time->Week = ((ReadValue&0x70)>>4)*10 + (ReadValue &0x0F);ReadValue = Read1302(DS1302_MONTH);ﻩTime->Month = ((ReadValue&0x70)>>4)*10 +(ReadValue&0x0F);ﻩReadValue = Read1302(DS1302_YEAR);Time->Year = ((ReadValue&0x70)>>4)*10 +(ReadValu e&0x0F);}void DateToStr(SYSTEMTIME *Time) //将时间年,月,日,星期数据转换成液晶显示字符串,放到数组里DateString[]{ if(hide_year<2) //这里的if,else语句都是判断位闪烁,<2显示数据,>2就不显示,输出字符串为 2007/07/22 {ﻩ Time->DateString[0]= '2';ﻩTime->DateString[1] = '0';Time->DateString[2] = Time->Year/10 + '0';Time->DateString[3] = Time->Year%10 + '0';}else{ﻩ Time->DateString[0] = ' ';Time->DateString[1] = ' ';ﻩﻩﻩ Time->DateString[2] = ' ';ﻩTime->DateString[3] = ' ';ﻩ}ﻩTime->DateString[4]= '/';ﻩif(hide_month<2)ﻩ{ﻩ Time->DateString[5] =Time->Month/10+ '0';Time->DateString[6] =Time->Month%10 + '0';ﻩ}else{ﻩ Time->DateString[5] = ' ';Time->DateString[6] = '';}Time->DateString[7] = '/';if(hide_day<2){Time->DateString[8] = Time->Day/10+'0';Time->DateString[9] =Time->Day%10 +'0';}ﻩelse{ﻩTime->DateString[8]= ' ';ﻩTime->DateString[9]= ' ';}if(hide_week<2)ﻩ{week_value[0] = Time->Week%10 + '0'; //星期的数据另外放到 week_value[]数组里,跟年,月,日的分开存放,因为等一下要在最后显示ﻩ}ﻩelseﻩ {week_value[0] = ' ';ﻩ}week_value[1] = '\0';ﻩTime->DateString[10] = '\0'; //字符串末尾加'\0' ,判断结束字符}void TimeToStr(SYSTEMTIME *Time) //将时,分,秒数据转换成液晶显示字符放到数组 TimeString[];{ if(hide_hour<2){ﻩ Time->TimeString[0] = Time->Hour/10 + '0';ﻩ Time->TimeString[1]= Time->Hour%10 + '0';ﻩ}else{ﻩ Time->TimeString[0] = ' ';ﻩ Time->TimeString[1] = ' ';}Time->TimeString[2] = ':';if(hide_min<2)ﻩ{Time->TimeString[3]= Time->Minute/10 + '0';Time->TimeString[4] =Time->Minute%10 + '0';}ﻩ elseﻩ{Time->TimeString[3] = ' ';ﻩTime->TimeString[4] =' ';ﻩ }ﻩTime->TimeString[5] = ':';if(hide_sec<2){ﻩTime->TimeString[6] = Time->Second/10 + '0';ﻩ Time->TimeString[7] = Time->Second%10 + '0';}else{Time->TimeString[6] = ' ';ﻩTime->TimeString[7] = ' ';}Time->DateString[8] = '\0';}void Initial_DS1302(void) //时钟芯片初始化{unsigned char Second=Read1302(DS1302_SECOND);ﻩif(Second&0x80)//判断时钟芯片是否关闭{ﻩWrite1302(0x8e,0x00); //写入允许Write1302(0x8c,0x07);//以下写入初始化时间日期:07/07/25.星期: 3. 时间: 23:59:55ﻩWrite1302(0x88,0x07);ﻩWrite1302(0x86,0x25);Write1302(0x8a,0x07);ﻩWrite1302(0x84,0x23);Write1302(0x82,0x59);Write1302(0x80,0x55);ﻩWrite1302(0x8e,0x80); //禁止写入}}/***********ds18b20子程序*************************//***********ds18b20延迟子函数(晶振12MHz )*******/void delay_18B20(unsignedint i){while(i--);}/**********ds18b20初始化函数**********************/void Init_DS18B20(void){ﻩ unsigned char x=0;DQ=1;//DQ复位ﻩdelay_18B20(8); //稍做延时ﻩDQ = 0; //单片机将DQ拉低ﻩ delay_18B20(80); //精确延时大于 480usDQ = 1; //拉高总线delay_18B20(14);ﻩ x=DQ; //稍做延时后如果x=0则初始化成功x=1则初始化失败delay_18B20(20);}/***********ds18b20读一个字节**************/unsigned char ReadOneChar(void){uchar i=0;ﻩuchardat = 0;for (i=8;i>0;i--){DQ = 0;// 给脉冲信号dat>>=1;ﻩDQ=1; //给脉冲信号ﻩ if(DQ)ﻩ dat|=0x80;ﻩ delay_18B20(4);}return(dat);}/*************ds18b20写一个字节****************/void WriteOneChar(uchar dat){unsigned char i=0;for(i=8; i>0; i--){ﻩDQ = 0;ﻩDQ= dat&0x01;ﻩdelay_18B20(5);ﻩﻩDQ = 1;ﻩdat>>=1;}}/**************读取ds18b20当前温度************/void ReadTemp(void){unsigned char a=0;ﻩunsignedchar b=0;ﻩunsigned char t=0;ﻩInit_DS18B20();WriteOneChar(0xCC); // 跳过读序号列号的操作WriteOneChar(0x44); ﻩ//启动温度转换ﻩdelay_18B20(100); // this message is wery importantInit_DS18B20();WriteOneChar(0xCC); ﻩ//跳过读序号列号的操作ﻩWriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度ﻩdelay_18B20(100);a=ReadOneChar();//读取温度值低位ﻩb=ReadOneChar();ﻩﻩ//读取温度值高位ﻩtemp_value=b<<4;temp_value+=(a&0xf0)>>4;}void temp_to_str() //温度数据转换成液晶字符显示{TempBuffer[0]=temp_value/10+'0'; //十位TempBuffer[1]=temp_value%10+'0'; //个位TempBuffer[2]=0xdf; //温度符号TempBuffer[3]='C';TempBuffer[4]='\0';}void Delay1ms(unsigned intcount){unsigned int i,j;for(i=0;i<count;i++)for(j=0;j<120;j++);}/*延时子程序*/void mdelay(uint delay){ﻩuint i;for(;delay>0;delay--)ﻩﻩ{for(i=0;i<62;i++) //1ms延时.ﻩ{;}ﻩ}}void outkey() //跳出调整模式,返回默认显示{ uchar Second;if(out==0||wireless_1==1){ mdelay(8);ﻩcount=0;ﻩhide_sec=0,hide_min=0,hide_hour=0,hide_day=0,hide_week=0,hide_month=0,hide_year=0;Second=Read1302(DS1302_SECOND);Write1302(0x8e,0x00); //写入允许Write1302(0x80,Second&0x7f);Write1302(0x8E,0x80); //禁止写入done=0;ﻩwhile(out==0);while(wireless_1==1);}}//////////////////////////////////////////////////////////////////////////////////////////////////////////// void Upkey()//升序按键{ﻩUp=1;if(Up==0||wireless_2==1)ﻩﻩ {ﻩﻩﻩ mdelay(8);ﻩ switch(count)ﻩﻩﻩ{case1:temp=Read1302(DS1302_SECOND); //读取秒数ﻩﻩﻩﻩﻩﻩtemp=temp+1; //秒数加1up_flag=1;//数据调整后更新标志if((temp&0x7f)>0x59) //超过59秒,清零temp=0; ﻩﻩﻩﻩﻩﻩ break;ﻩﻩ case 2:temp=Read1302(DS1302_MINUTE); //读取分数ﻩﻩﻩﻩﻩ temp=temp+1;//分数加1up_flag=1;ﻩﻩﻩﻩ if(temp>0x59) //超过59分,清零ﻩﻩtemp=0;ﻩﻩﻩbreak;ﻩﻩﻩcase 3:temp=Read1302(DS1302_HOUR); //读取小时数ﻩﻩﻩ temp=temp+1; //小时数加1up_flag=1;ﻩﻩﻩﻩﻩﻩif(temp>0x23) //超过23小时,清零ﻩﻩﻩﻩﻩﻩtemp=0;ﻩﻩﻩﻩbreak;ﻩﻩﻩﻩcase 4:temp=Read1302(DS1302_WEEK); //读取星期数ﻩﻩﻩﻩ temp=temp+1; //星期数加1up_flag=1;ﻩﻩﻩ if(temp>0x7)ﻩﻩﻩﻩ temp=1;ﻩﻩﻩﻩﻩﻩ break;ﻩcase 5:temp=Read1302(DS1302_DAY); //读取日数ﻩﻩﻩ temp=temp+1; //日数加1up_flag=1;ﻩﻩﻩﻩ if(temp>0x31)ﻩﻩﻩﻩﻩﻩ temp=1;ﻩﻩﻩﻩ break;ﻩﻩcase 6:temp=Read1302(DS1302_MONTH); //读取月数ﻩﻩﻩﻩtemp=temp+1; //月数加1up_flag=1;ﻩﻩﻩﻩﻩﻩﻩif(temp>0x12)ﻩﻩﻩﻩ temp=1;ﻩﻩﻩﻩ break;ﻩcase 7:temp=Read1302(DS1302_YEAR);//读取年数ﻩﻩﻩﻩﻩﻩﻩ temp=temp+1; //年数加1up_flag=1;ﻩﻩﻩﻩif(temp>0x85)ﻩﻩﻩﻩﻩ temp=0;ﻩﻩ break;ﻩﻩﻩﻩdefault:break;ﻩ }ﻩﻩﻩ while(Up==0);ﻩ while(wireless_2==1);}}////////////////////////////////////////////////////////////////////////////////////////////////////////////void Downkey()//降序按键{ﻩﻩﻩDown=1;if(Down==0||wireless_3==1)ﻩ {ﻩﻩﻩmdelay(8);ﻩﻩ switch(count)ﻩﻩ {case 1:temp=Read1302(DS1302_SECOND); //读取秒数ﻩﻩﻩﻩﻩtemp=temp-1;ﻩ//秒数减1down_flag=1; //数据调整后更新标志ﻩﻩﻩﻩ if(temp==0x7f) //小于0秒,返回59秒ﻩﻩtemp=0x59;ﻩﻩbreak;ﻩﻩﻩ case2:temp=Read1302(DS1302_MINUTE); //读取分数ﻩﻩﻩtemp=temp-1; //分数减1down_flag=1;ﻩﻩﻩﻩ if(temp==-1)ﻩﻩﻩﻩﻩﻩ temp=0x59; //小于0秒,返回59秒ﻩﻩﻩﻩﻩ break;case 3:temp=Read1302(DS1302_HOUR); //读取小时数ﻩﻩﻩtemp=temp-1; //小时数减1down_flag=1;ﻩﻩﻩﻩ if(temp==-1)ﻩtemp=0x23;ﻩﻩ break;ﻩ case 4:temp=Read1302(DS1302_WEEK);//读取星期数ﻩﻩﻩﻩ temp=temp-1; //星期数减1down_flag=1;ﻩﻩﻩﻩ if(temp==0)ﻩﻩﻩﻩﻩ temp=0x7;;ﻩﻩﻩ break;ﻩ case 5:temp=Read1302(DS1302_DAY); //读取日数ﻩﻩﻩﻩﻩ temp=temp-1; //日数减1down_flag=1;ﻩﻩﻩﻩ if(temp==0)ﻩﻩﻩtemp=31;ﻩﻩ break;ﻩﻩﻩ case 6:temp=Read1302(DS1302_MONTH); //读取月数ﻩﻩﻩﻩﻩﻩ temp=temp-1; //月数减1down_flag=1;ﻩif(temp==0)ﻩﻩﻩﻩﻩ temp=12;ﻩﻩﻩﻩﻩﻩ break;ﻩﻩcase 7:temp=Read1302(DS1302_YEAR);//读取年数ﻩﻩﻩﻩ temp=temp-1; //年数减1down_flag=1;ﻩﻩﻩﻩ if(temp==-1)ﻩﻩﻩtemp=0x85;ﻩﻩﻩﻩﻩﻩﻩ break;ﻩﻩ default:break;ﻩ}ﻩﻩﻩﻩwhile(Down==0);ﻩﻩwhile(wireless_3==1);ﻩ}}void Setkey()//模式选择按键{ﻩSet=1;ﻩif(Set==0||wireless_4==1)ﻩ{mdelay(8);count=count+1; //Setkey按一次,count就加1 done=1; ﻩﻩ//进入调整模式while(Set==0);while(wireless_4==1);ﻩ }}void keydone()//按键功能执行{ uchar Second;ﻩ if(flag==0) //关闭时钟,停止计时{ Write1302(0x8e,0x00); //写入允许temp=Read1302(0x80);Write1302(0x80,temp|0x80);ﻩWrite1302(0x8e,0x80); //禁止写入flag=1;}Setkey(); ﻩ//扫描模式切换按键ﻩswitch(count)ﻩﻩ {case 1:do ﻩ //count=1,调整秒{outkey();ﻩﻩ //扫描跳出按钮ﻩﻩﻩUpkey(); //扫描加按钮ﻩﻩ Downkey(); //扫描减按钮ﻩﻩﻩﻩif(up_flag==1||down_flag==1) //数据更新,重新写入新的数据{ﻩﻩ Write1302(0x8e,0x00); //写入允许ﻩﻩﻩWrite1302(0x80,temp|0x80); //写入新的秒数ﻩﻩﻩWrite1302(0x8e,0x80); //禁止写入ﻩﻩﻩ up_flag=0;ﻩﻩﻩﻩ down_flag=0;ﻩﻩ}ﻩhide_sec++; //位闪计数ﻩﻩif(hide_sec>3)ﻩﻩ hide_sec=0;show_time(); //液晶显示数据ﻩﻩﻩﻩ}while(count==2);break;ﻩ case 2:doﻩﻩ//count=2,调整分ﻩ {ﻩﻩhide_sec=0;ﻩ outkey();ﻩﻩﻩ Upkey();ﻩﻩ Downkey();ﻩﻩ if(temp>0x60)ﻩﻩ temp=0;ﻩﻩﻩ if(up_flag==1||down_flag==1)ﻩﻩ {ﻩWrite1302(0x8e,0x00); //写入允许ﻩﻩﻩ Write1302(0x82,temp); //写入新的分数ﻩWrite1302(0x8e,0x80);//禁止写入ﻩ up_flag=0;ﻩ down_flag=0;ﻩﻩﻩ }ﻩﻩ hide_min++;ﻩﻩ if(hide_min>3)ﻩﻩﻩhide_min=0;show_time();ﻩﻩ }while(count==3);break;ﻩ case 3:doﻩﻩﻩﻩ//count=3,调整小时ﻩﻩ{hide_min=0;ﻩoutkey();ﻩUpkey();ﻩ Downkey();ﻩﻩﻩ if(up_flag==1||down_flag==1)ﻩﻩ{ﻩﻩﻩ Write1302(0x8e,0x00); //写入允许ﻩ Write1302(0x84,temp); //写入新的小时数ﻩﻩ Write1302(0x8e,0x80); //禁止写入ﻩﻩﻩ up_flag=0;ﻩ down_flag=0;ﻩ}hide_hour++;ﻩﻩif(hide_hour>3)hide_hour=0;show_time();ﻩﻩ }while(count==4);break;case 4:doﻩﻩﻩﻩ //count=4,调整星期ﻩ {hide_hour=0;outkey();Upkey();ﻩﻩDownkey();ﻩ if(up_flag==1||down_flag==1)ﻩﻩ{ﻩ Write1302(0x8e,0x00); //写入允许ﻩﻩﻩﻩ Write1302(0x8a,temp); //写入新的星期数ﻩﻩWrite1302(0x8e,0x80); //禁止写入ﻩﻩ up_flag=0;ﻩﻩ down_flag=0;ﻩﻩ}ﻩhide_week++;ﻩﻩ if(hide_week>3)ﻩﻩﻩ hide_week=0;show_time();ﻩﻩﻩ }while(count==5);break;ﻩ case 5:doﻩﻩﻩﻩﻩ//count=5,调整日ﻩ {ﻩﻩﻩﻩ hide_week=0;ﻩoutkey();ﻩﻩﻩﻩ Upkey();ﻩﻩ Downkey();ﻩﻩﻩ if(up_flag==1||down_flag==1)ﻩﻩ{ﻩ Write1302(0x8e,0x00); //写入允许Write1302(0x86,temp); //写入新的日数ﻩﻩﻩ Write1302(0x8e,0x80); //禁止写入ﻩﻩﻩ up_flag=0;ﻩ down_flag=0;ﻩ}ﻩﻩﻩ hide_day++;ﻩﻩﻩif(hide_day>3)ﻩ hide_day=0;show_time();ﻩﻩ }while(count==6);break;ﻩﻩcase 6:doﻩﻩﻩﻩﻩ//count=6,调整月{hide_day=0;ﻩﻩﻩﻩ outkey();ﻩﻩ Upkey();ﻩﻩ Downkey();ﻩﻩ if(up_flag==1||down_flag==1)ﻩﻩ {ﻩﻩ Write1302(0x8e,0x00); //写入允许ﻩﻩ Write1302(0x88,temp); //写入新的月数ﻩ Write1302(0x8e,0x80); //禁止写入ﻩup_flag=0;ﻩﻩﻩ down_flag=0;ﻩﻩ}ﻩﻩ hide_month++;ﻩﻩif(hide_month>3)ﻩﻩﻩ hide_month=0;show_time();ﻩ }while(count==7);break;ﻩﻩ case 7:doﻩ//count=7,调整年{hide_month=0;ﻩﻩﻩ outkey();ﻩﻩUpkey();ﻩﻩDownkey();ﻩ if(up_flag==1||down_flag==1)ﻩﻩ {ﻩ Write1302(0x8e,0x00); //写入允许ﻩﻩWrite1302(0x8c,temp); //写入新的年数Write1302(0x8e,0x80); //禁止写入ﻩﻩ up_flag=0;ﻩﻩdown_flag=0;ﻩﻩﻩﻩ }ﻩﻩﻩhide_year++;ﻩif(hide_year>3)ﻩﻩﻩ hide_year=0;show_time();ﻩﻩ}while(count==8);break;ﻩ case 8: count=0;hide_year=0; //count8,跳出调整模式,返回默认显示状态ﻩSecond=Read1302(DS1302_SECOND);Write1302(0x8e,0x00); //写入允许ﻩ Write1302(0x80,Second&0x7f);ﻩ Write1302(0x8E,0x80); //禁止写入ﻩﻩﻩ done=0;ﻩﻩ break; //count=7,开启中断,标志位置0并退出ﻩ default:break;ﻩ }}void show_time() //液晶显示程序{DS1302_GetTime(&CurrentTime);//获取时钟芯片的时间数据TimeToStr(&CurrentTime); //时间数据转换液晶字符DateToStr(&CurrentTime); //日期数据转换液晶字符ReadTemp(); //开启温度采集程序temp_to_str(); //温度数据转换成液晶字符GotoXY(12,1); //液晶字符显示位置Print(TempBuffer); //显示温度GotoXY(0,1);Print(CurrentTime.TimeString); //显示时间GotoXY(0,0);Print(CurrentTime.DateString); //显示日期GotoXY(15,0);Print(week_value); //显示星期GotoXY(11,0);Print("Week");ﻩ//在液晶上显示字母 weekDelay1ms(400); //扫描延时}main(){flag=1; //时钟停止标志LCD_Initial(); //液晶初始化Init_DS18B20( ) ; //DS18B20初始化Initial_DS1302(); //时钟芯片初始化up_flag=0;down_flag=0;ﻩdone=0; //进入默认液晶显示ﻩwireless_1=0;wireless_2=0;ﻩwireless_3=0;wireless_4=0;while(1){while(done==1)keydone(); //进入调整模式while(done==0)ﻩ{show_time(); //液晶显示数据flag=0;ﻩﻩ Setkey(); ﻩﻩ //扫描各功能键ﻩﻩ}}}。