西华大学单片机课程设计之基于单片机与DS1302的数字闹钟
基于ds1302和单片机时钟设计

摘要:本次课程设计所设计的时钟模块是基于DS1302时钟芯片和AT89C52单片机的时钟设计,是以AT89C52单片机为核心,由DS1302时钟芯片、数码管做显示器及74LS08与门构成的24小时制单功能电子实时时钟。
这种单功能电子实时时钟不仅具有了一般数字时钟的基本的显示实时时间的功能,并且还能通过两个按钮实现时钟运行与停止功能。
如果需要设置时间的话,只需在软件程序上改变时钟芯片的初始化程序就能实现。
在电子产品盛行的今天,像这样的电子时钟设计可以给予它更大的发展空间与应用前景。
关键词:DS1302时钟芯片、AT89C52单片机、电子实时时钟目录第一章汽车运行安全无线监测系统总体方案设计............................ - 1 -1.1 总体方案设计................................................... - 1 -1.2 单片机的选择................................................... - 1 -1.3 超声波测距方案设计............................................. - 3 -1.4 测气压模块设计................................................. - 3 -1.5 无线发射与接收设计............................................. - 3 -1.6显示装置的设计.................................................. - 3 -1.7日历时钟模块.................................................... - 4 -1.8 键盘模块....................................................... - 4 - 第二章时钟模块设计方案................................................ - 5 -2.1系统功能框图.................................................... - 5 -2.2系统主要部分.................................................... - 5 -2.3方案选择........................................................ - 6 - 第三章硬件设计部分.................................................... - 8 -3.1单片机最小系统电路设计和元件的选择.............................. - 8 -3.2 DS1302时钟芯片电路设计......................................... - 8 -3.3数码管显示电路设计.............................................. - 9 -3.4按键电路设计.................................................... - 9 - 第四章软件设计部分................................................... - 10 -4.1主程序单元部分................................................. - 10 -4.2外部中断部分................................................... - 11 -4.3显示程序单元部分............................................... - 11 -4.4 DS1302时钟芯片判断时钟是否停止................................ - 12 - 第五章系统调试与仿真................................................ - 13 -5.1系统调试....................................................... - 13 -5.2仿真电路....................................................... - 14 - 源程序................................................................ - 15 - 设计总结及体会........................................................ - 22 - 参考文献.............................................................. - 22 -第一章 汽车运行安全无线监测系统总体方案设计1.1 总体方案设计整个系统要集测胎压,测距,时钟,无线发射接收和显示与一体,所以整体方案是通过胎压传感器来测胎压,通过无线发射接收模块把信息发送给单片机。
嵌入式课程设计——基于DS1302数字钟

嵌入式课程设计报告题目:基于DS1302数字钟姓名:学号:班级:电子101专业:电子信息工程指导老师:提交时间: 2013-12-13组员:目录摘要................................................. - 1 -1.引言............................................... - 3 -2.硬件电路设计:..................................... - 4 - 2.1 DS1302 ........................................ - 4 - 2. 2 AT89C52 ...................................... - 6 - 2. 3 LCD1602 ...................................... - 7 -2. 4 设计方案 ..................................... - 8 -3.软件程序设计....................................... - 9 - 3.1主程序.......................................... - 9 - 3.2 LCD1602程序:................................. - 10 -3.3 DS1302应用程序:.............................. - 13 -4.课设的心得体会.................................... - 17 - 参考文献............................................ - 20 -摘要本设计选取串行接口时钟芯片 DS1302 与单片机同步通信构成数字时钟电路并用LCD1602显示。
DS1302 数字钟设计

一、采用内部定时的程序:(注意,程序中应用的是共阴极数码管)#include<reg52.h>#define uint unsigned int#define uchar unsigned charuchar code Dis_code[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};//共阴极数码管编码sbit P10=P1^0;sbit P11=P1^1;sbit P12=P1^2;sbit P13=P1^3;uchar cnt,seccnt,mincnt,hourcnt,daycnt,moncnt,yearcnt;ucharseccnt1,seccnt10,mincnt1,mincnt2,hourcnt1,hourcnt10,daycnt1,daycnt10,moncnt1,moncn t10,year1,year10;void delay(unsigned char i) //延时子程序{unsigned char j;while((i--)!=0){for(j=625;j>0;j--);}}void Display(time0,time1,time2,time3){P2=0x07;P0=Dis_code[time0];delay(1);P2=0x0b;P0=Dis_code[time1];delay(1);P2=0x0d;P0=Dis_code[time2]|0x80;delay(1);P2=0x0e;P0=Dis_code[time3];delay(1);}void main(){seccnt1,seccnt10,mincnt1,mincnt10,hourcnt1,hourcnt10,daycnt1,daycnt10,moncnt1,monc nt10,yearcnt1,yearcnt10;uchar m=0,flag;yearcnt=11;moncnt=10;daycnt=12;TMOD=0X01;TH1=0X3C;TL1=0XAE;//定时器设置初值15535,定时50msTR1=1;EA=1;ET1=1;P10=0;while(1){if(cnt==20){cnt=0;seccnt++;if(seccnt==60){ seccnt=0;mincnt++;if(mincnt==60){mincnt=0;hourcnt++;if(hourcnt==24){hourcnt=0;daycnt++;if(daycnt==31){daycnt=1;moncnt++;if(moncnt==13){moncnt=1;yearcnt++;if(yearcnt==100)yearcnt=0;}}}}}}}if(P11==0)//翻页按钮{ //flag=0;delay(100);if(P11==0){m++;//页码控制if(m>2){m=0;}}}while(P11==0);if(P12==0)//调节时间的按钮{delay(100);if(P12==0){ TR1=~TR1;//按下一次停止计时,再按一次开始计时 }}while(P12==0);if(TR1==0)//如果计时停止,开始校正时间{if(P13==0){delay(100);if(P13==0){flag++;}}while(P13==0);}else flag=0;switch(m){case 0:if(flag>0){flag--;mincnt++;mincnt=mincnt%60;}seccnt1=seccnt%10;seccnt10=seccnt/10;mincnt1=mincnt%10;mincnt10=mincnt/10;Display(seccnt1,seccnt10,mincnt1,mincnt10);break;case 1:if(flag>0){flag--; hourcnt++; daycnt=(daycnt|(hourcnt/24))%30; hourcnt=hourcnt %24;}// hourcnt=(hourcnt|flag)%24;hourcnt1=hourcnt%10;hourcnt10=hourcnt/10;daycnt1=daycnt%10;daycnt10=daycnt/10;Display(hourcnt1,hourcnt10,daycnt1,daycnt10);break;case 2:if(flag>0){flag--; moncnt++; moncnt=moncnt%13;if(moncnt==0){moncnt++;yearcn t++;}}moncnt1=moncnt%10;moncnt10=moncnt/10;yearcnt1=yearcnt%10;yearcnt10=yearcnt/10;Display(moncnt1,moncnt10,yearcnt1,yearcnt10);break;}}}void Time1() interrupt 3{TH1=0X3C;TL1=0XAE;cnt++;}二、采用DS1302的程序(应用上面的电路图,数码管为共阳极型)#include <reg52.h>//定义共阳极字型码0123456789-unsigned char codedispcode[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};unsigned char time[]={0,0,0,0};//用来储存分秒unsigned char date[]={0,0,0,0};//用来储存日时unsigned char year[]={0,0,0,0};//用来储存年月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[9];unsigned char TimeString[9];}SYSTEMTIME; //定义的时间类型SYSTEMTIME time1;sbit DS1302_CLK = P1^6; //实时时钟时钟线引脚sbit DS1302_IO = P1^7; //实时时钟数据线引脚sbit DS1302_RST = P1^5; //实时时钟复位线引脚sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;sbit P10=P1^0;sbit P11=P1^1;sbit P12=P1^2;sbit P13=P1^3;sbit P14=P1^4;//#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 0x8C#define DS1302_RAM(X) (0xC0+(X)*2) //用于计算DS1302_RAM 地址的宏void 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; //RST 0->1->0,CLK 0->1}unsigned char Read1302(unsigned char ucAddr) //读取DS1302某地址的数据{unsigned char ucData;DS1302_RST = 0;DS1302_CLK = 0;DS1302_RST = 1; //enableDS1302InputByte(ucAddr|0x01); // 地址,命令ucData = DS1302OutputByte(); // 读1Byte数据DS1302_CLK = 1; //RST 0->1->0,CLK 0->1DS1302_RST = 0;return(ucData);}void DS1302_SetProtect(bit flag) //是否写保护{if(flag)Write1302(0x8E,0x10); //WP=1,不能写入elseWrite1302(0x8E,0x00);//WP=0,可以写入}void DS1302_SetTime(unsigned char Address, unsigned char Value) // 设置时间函数{DS1302_SetProtect(0);Write1302(Address, ((Value/10)<<4 | (Value%10))); //高4位为十位,低4位为个位}void DS1302_GetTime(SYSTEMTIME *Time){unsigned char ReadValue;ReadValue = Read1302(DS1302_SECOND);Time->Second = ((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);//转换成10进制的秒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&0xf0)>>4)*10 + (ReadValue&0x0F);}void Initial_DS1302(void){unsigned char Second=Read1302(DS1302_SECOND);if(Second&0x80) //如果第七为1(表明没有启动), 则启动时钟DS1302_SetTime(DS1302_SECOND,0);}void delay(unsigned char i) //延时子程序{unsigned char j;while((i--)!=0){for(j=625;j>0;j--);}}/*unsigned char button_time(n,x,y) //时钟调整子程序unsigned char n,x,y;{if(P1^7==0){delay(50);if(P1^7==0){n++;if(n==x)n=0;while(P1^7==0);}}if(P1^1==0){delay(50);if(P1^1==0){if(n==0)n=y;elsen--;while(P1^1==0);}}return n;}*//*unsigned char button_date(n,x,y) //日期调整子程序unsigned char n,x,y;{if(P1^7==0){delay(50);if(P1^7==0){n++;if(n==x)n=1;while(P1^7==0);}}if(P1^1==0){delay(50);if(P1^1==0){if(n==1)n=y;elsen--;while(P1^1==0);}}return n;}*/void display1(minute10,minute1,second10,second1) //显示第一页分秒子程序//unsigned char second10,second1,minute10,minute1;{P2=0x08;P0=dispcode[second1];//显示秒的个位delay(1);P2=0x04;P0=dispcode[second10]; //显示秒的十位delay(1);P2=0x02;P0=dispcode[minute1]; //显示分的个位delay(1);P2=0x01;P0=dispcode[minute10];//显示分的十位delay(1);}void display2(data10,data1,hour10,hour1) //显示第二页天时子程序//unsigned char data10,data1,hour10,hour1;{P2=0xf8;P0=dispcode[data1];//显示天的个位delay(1);P2=0xf4;P0=dispcode[data10]; //显示天的十位delay(1);P2=0xf2;P0=dispcode[hour1]; //显示时的个位delay(1);P2=0xf1;P0=dispcode[hour10];//显示时的十位delay(1);}void display3(year10,year1,month10,month1) //显示第三页年月子程序//unsigned char year10,year1,month10,month1;{P2=0xf2;P0=dispcode[month1];//显示月的个位delay(1);P2=0xf1;P0=dispcode[month10]; //显示月的十位delay(1);P2=0xf8;P0=dispcode[year1]; //显示月的个位delay(1);P2=0xf4;P0=dispcode[year10];//显示月的十位delay(1);}void main(){unsigned char flag=0;Initial_DS1302(); //初始化DS1302这个时钟芯片,P10=0; //点亮测试灯while(1){DS1302_GetTime(&time1); //读取时间参数time[3]=(time1.Second)%10; //把秒的个位数据存入time[3]time[2]=(time1.Second)/10; //把秒的十位数据存入time[2]time[1]=(time1.Minute)%10; //把分的个位数据存入time[1]time[0]=(time1.Minute)/10; //把分的十位数据存入time[0]date[3]=(time1.Day)%10;date[2]=(time1.Day)/10;date[1]=(time1.Hour)%10;date[0]=(time1.Hour)/10;year[3]=(time1.Year)%10;year[2]=(time1.Year)/10;year[1]=(time1.Month)%10;year[0]=(time1.Month)/10;// display1(time[0],time[1],time[2],time[3]);if(P11==0){delay(50);if(P11==0){flag++;if(flag>2)//flag: 1 显示第二页日时;2 显示第三页年月0:显示第一页分秒{flag=0;}}while(P11==0);}/*if(P1^6==0) //如果按下Time Set键一下,开始显示日期,再按一下进入日期跟时钟的调节模式{delay(50);if(P1^6==0){flag++;if(flag>6){flag=0;}}while(P1^6==0);}*/switch(flag){case 0:display1(time[0],time[1],time[2],time[3]); //调用子函数display,把存入数组time 的数据给显示出来break;case 1:display2(date[0],date[1],date[2],date[3]); //调用子函数display,把存入数组date 的数据给显示出来break;case 2:display3(year[0],year[1],year[2],year[3]);break;/* case 3:time1.Month=button_date(time1.Month,13,12); //调整月DS1302_SetTime(0x88,time1.Month);display(10,10,date[2],date[3]);break;case 4:time1.Day=button_date(time1.Day,32,31); //调整日DS1302_SetTime(0x86,time1.Day);display(10,10,date[4],date[5]);break;case 5:time1.Minute=button_time(time1.Minute,60,59); //调整分DS1302_SetTime(0x82,time1.Minute);display(time[2],time[3],10,10);break;case 6:time1.Second=button_time(time1.Second,60,59); //调整秒DS1302_SetTime(0x80,time1.Second);display(10,10,time[4],time[5]);break;*/}}}。
基于DS1302的数字钟设计_课程设计说明书

吉林化工学院课程设计说明书基于DS1302的数字钟设计Design of digital clock based on DS1302专业班级:电信1002起止日期:2013.4.1~2013.4.19吉林化工学院Jilin Institute of Chemical Technology信息与控制工程学院硬件课程设计说明书课程设计任务书一、设计题目:基于DS1302的数字钟设计二、设计目的1、掌握DS1302时钟芯片的硬件电路原理及软件编程方法,熟悉DS1302时钟芯片的性能指标和特点;2、熟悉STC12C5A60S2单片机的性能特点,并掌握STC12C5A60S2单片机控制DS1302读写时间、日期的硬件电路组成及软件编程方法;3、了解LED 显示及按键电路的组成原理,熟悉LED 动态显示原理及实现方法;4、了解7805构成直流稳压电源的电路组成及工作原理。
三、设计任务及要求(宋体,小四号字,加黑)设计并实现具有显示日期和时间的电子数字钟,数字钟具有以下基本功能:1、使用6位LED 显示时间、日期和星期,正常显示时、分、秒、星期,使用按键可切换显示年、月、日;2、具有时间、日期调整功能,通过键盘可进行时间、日期的调整;3、具有闹钟功能,使用键盘设定闹铃时间,由蜂鸣器产生闹铃;4、定时控制功能,使用小型继电器完成定时控制功能(发挥部分)。
四、设计时间及进度安排(宋体,小四号字,加黑)设计时间共三周(2013.4.1 – 2013.4.19),具体安排如下表: 周安排设 计 内 容 设计时间 第一周硬件电路设计 13.4.01 13.4.05 第二周硬件电路焊接与调试 13.4.08 13.4.12 第三周 编写课程设计说明书,课程设计答辩。
13.4.1513.4.19五、指导教师评语及学生成绩指导教师评语:成绩指导教师(签字):基于DS1302的数字钟设计摘要本系统采用STC89C52单片机和DS1302配合,实现LED数码管显示时间、日期和星期,正常显示时、分、秒、星期,使用按键可切换显示年、月、日。
基于单片机DS1302的时钟万年历(带闹钟)

#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit lcdws=P2X; 〃1602 管脚定义sbit Icde n=P2P;sbit Icdrs=P2A2;sbit key仁卩2人3; //闹钟设置键sbit key2=P2A4;sbit key3=P1A5;〃功能键定义sbit key4=P1A6;〃增大键定义sbit key5=P1A7;〃减小键定义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=P1A0;//ds18b20 信号线sbit beep=P1A4; // 蜂鸣器管脚定义sbit ACC_7 = ACCA7; //位寻址寄存器定义sbit SCLK = P1A2; // DS1302 时钟信号sbit DIO= P1A1; // DS1302 数据信号sbit CE = P1A3;//地址、数据发送子程序//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; SCLK=0;//CE 引脚为低,数据传送中止// 清零时钟总线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-- ){SCLK = 0; temp = addr;DIO = (bit)(temp&0x01);addr >>= 1;// 每次传输低字节// 右移一位// 循环8 次移位// 每次传输低字节// 右移一位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 {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--;}// 数据进制转换2010 年 09 月 30 日 23 点 58 分 56 秒 星期一// 允许写保护 // 秒位初始化 // 分钟初始化 // 小时初始化 // 日初始化// 月初始化 // 年初始化 // 日期始化 // 禁止写保护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*0.0625;temp=f_temp*10+0.5;f_temp=f_temp+0.05; // 温度在寄存器中为12 位,分辨率为0.0625人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);// 定位到星期的位置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_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;定位到日的位置定位到月的位置 定位到年的位置 // 允许写保护 // 秒位初始化 // 分钟初始化 // 小时初始化 // 日初始化// 月初始化 // 年初始化 // 日期始化 //禁止写Y增小建才有效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;}}}WWWWWW-nma-()八-cdwsuainip-nfconfigurafiono 八CDmpchangeo 八fo r (ll'10v 0〒)宀dislCDmp(ge匚 empo)-w h =e 3宀keyscanoy 、^M ffl Bw h i -e ((k ey l QO QO k e y 2QO QO k e y 3QO QO k e y 4QO QO key 5)QO QO ((f e n u u a f e n )QO QO (s h ll'u a s h i )))beep"八if(f-agu") 宀miaouReach302(0X81)7/和引^wriCDlsfm(6ymiao)八fenuReach302(0X83)0和引Vwmelsfm(3fen=shll'Read」3o2(ox85)0 和引亠£4wriCDlsfm(Qshi)八dayuReach302(0X87)0和引mwriCDlnyrzGday)八monfhuReach302(0X89)7/和引出 w r i CD l n yrz(5 -monfh)八year"Reach302(0x8d)y/ 和引<wriCDlnyrz(2yyear)八weekuReacH302(0x8b)y/disp-aylweek(week)八e-sewrite_1302(0x80,0x80);// 时钟振荡器停止}set_alarm();WWW}}。
基于单片机及DS1302的LED电子钟设计——软件部分

基于单片机及DS1302的LED电子钟设计——软件部分摘要现代社会的快节奏生活要求人们对时间的掌握越来越精确,随着计算机在社会领域的渗透和大规模集成电路的发展,单片机的应用正在逐步地深入,电子钟也逐渐取代传统钟表被广泛应用于生活和工作中。
电子时钟主要是利用电子技术将时钟电子化、数字化,拥有时间精确、体积小、界面友好、可扩展性能强等特点。
本设计以AT89C52芯片作为核心,8位LED数码管显示和DS1302时钟芯片主要组成来实现电子钟的基本功能,并分析了相应软件的设计要点,包括软件设计流程、仿真与调试。
关键词电子钟;单片机;DS1302ABSTRACT Nowadays people need more accurate time to keep up with the high pace of life. With computers in the infiltration and the development of large-scale integrated circuits,SCM application is steadily deepening, while electronic clock is widely used in our life and work taking place of traditional one. the electronic clock mainly uses the electronic technology to make the clock computerized and digitized, with features of accurate time、small size、a friendly user interface and strong expansibility.This design mainly consists of the core chip of AT89S52, 8 light emitting diodes and the clock chip DS1302 to achieve the basic function of the electronic clock, and also analyses the key designing of the corresponding software including software design flow, emulation and debuggingKEY WORDS Electronic clock; Single Chip Microcomputer; DS1302目录1.前言 (1)2.系统核心芯片介绍 (2)2.1 单片机AT89S2简介 (2)2.1.1 芯片主要性能 (2)2.1.2 芯片引脚功能 (2)2.2 时钟芯片DS1302简介 (5)2.2.1 主要功能 (5)2.2.2 内部结构及引脚功能 (5)2.2.3 工作原理 (6)2.2.4 控制字节及寄存器 (7)2.2.5 数据的传送 (8)3.电子钟软件设计 (9)3.1 系统结构图及总流程图 (9)3.2 主程序模块 (10)3.2.1 初始化模块 (10)3.2.2 DS1302读写模块 (12)3.2.3 显示模块 (14)3.2.4 蜂鸣模块 (15)3.2.5 主程序流程图 (16)3.3 中断调整模块 (17)3.3.1 时间中断模块 (17)3.3.2 闹钟调整模块 (20)4.调试结果分析及解决方案 (21)5.总结 ................................................................................................. 错误!未定义书签。
单片机应用课程设计基于DS1302电子时钟的设计 报告参考模板

单片机应用课程设计报告(2012~2013学年第2学期)设计题目:基于DS1302电子时钟的设计班别:2010级自动化1班姓名:李永兴贺孝言王永伟指导教师:***时间:2013年5月目录1 设计任务 (3)2 系统总体方案设计 (3)2.1各个模块方案论证 (3)2.1.1 时钟芯片的选择 (3)2.1.2 显示器的选择 (3)2.2总体方案设计 (4)3 硬件电路设计 (4)3.1单片机最小系统 (4)3.21302时钟电路 (5)3.3按键调时电路 (6)4 系统软件设计 (7)4.1主程序流程图 (7)4.2子程序流程图 (8)4.2.1 DS1302子程序流程图 (8)4.2.2 1602子程序流程图 (9)4.3按键校正调时程序 (9)5 实物调试 (10)5.1实物性能分析 (10)5.2总结 (13)附录1 (15)(1)系统总电路图 (15)(2)系统仿真图 (15)附录2 (17)部分程序清单 (17)1 设计任务基本要求:采用DS1302时钟芯片与单片机STC89C52相结合设计电子时钟,能够显示出实时年、月、日、时、分、秒等时间,并且可以通过按键进行时间调整。
2 系统总体方案设计2.1 各个模块方案论证2.1.1 时钟芯片的选择由于设计的是电子时钟,而单片机STC89C52自带计时功能,利用单片机实现数据的显示和调整是可行的,采用单片机计时,利用它的一个16位定时器/计数器每50ms产生一个中断信号,中断20次后产生一个秒信号,然后根据时间进制关系依次向分、时、日、星期、月、年进位。
这样可以直接用单片机的内部定时/计数器来完成电子万年历的设计。
用单片机内部的定时/计数器来制作电子万年历,虽然无须外接其他芯片,充分利用了单片机的资源,但是计时精度不够高,误差较大,掉电后所有数据将被丢失,且软件编程较为复杂。
在以单片机为核心构成的装置中,经常需要一个实时的时钟和日历,以便对一些实时发生事件记录时给予时标。
利用单片机及DS1302制作电子时钟

单片机原理及应用——基于Proteus和Keil C实习报告课程名:利用单片机及DS1302制作电子时钟指导教师:朱华贵老师专业:应用电子技术年级: 10级评定:组员:邱凌芳、杨侨、陈佳佳设计时间: 2012年5月18日江西财经大学职业技术学院摘要为了进一步熟悉51单片机的编程以及学习电子时钟的相关设计方法,在老师的指导下我们进行了本次电子时钟的设计。
我们在实习期间基于51单片机——AT89C51和时钟芯片DS1302设计并实现了电子时钟显示。
在PCB板制作完成并且调试成功之际,为了进一步提高自己的动手能力和编程能力,对这次电子时钟的设计和制作的过程中遇到的问题及设计思路做一次总结。
本电子时钟是一种利用时钟芯片DS1302及51单片机来显示时、分、秒和年、月的装置。
默认显示为时间,由四个按键分别控制定时设置、时间调整、分钟调整、日期显示;设计电路工作电源为5V;由4位LED数码管显示时间,格式为时时分分,中间点每隔1S亮暗;有备用电池,掉电后再上电能正常显示时间。
电子时钟大体可以分为三大模块,数码管的显示模块、DS1302时钟芯片与单片机的时钟模块和按键与单片机的模块。
单片机在5V电压下,各个模块正常工作。
单片机从DS1302芯片中读出一组时间日期数据,同时单片机通过按键设置当前要求显示的信息给单片机。
单片机接收到各个数据时,把各个数据显示出来。
目录一、总体设计-------------------------------------------------41.1 设计目的---------------------------------------------41.2 硬件功能描述-----------------------------------------41.3 设计方案选择-----------------------------------------41.4 设计任务及要求---------------------------------------4二、电子时钟软件和硬件设计-----------------------------------52.1 硬件电路设计-----------------------------------------52.1.1 工作原理----------------------------------------52.1.2 单元模块电路------------------------------------52.1.3 元器件清单--------------------------------------72.2 软件设计---------------------------------------------72.2.1 程序设计流程------------------------------------72.2.2 主控程序----------------------------------------8三、电路调试-------------------------------------------------9四、总结----------------------------------------------------10五、参考文献------------------------------------------------11附录Ⅰ:DS1302时钟芯片的工作原理和使用方法------------------12 附录Ⅱ: 程序清单--------------------------------------------13附录Ⅲ: 原理图、PCB图及实物图------------------------------20一、总体设计此电子时钟利用AT89C51单片机和时钟芯片DS1302 设计完成。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
课程设计说明书课程名称:单片机应用课程设计课程代码: 6003509题目:数字闹钟的设计学生姓名:学号: 312011080307 年级/专业/班: 2011级机电2班学院(直属系) :机械工程与自动化学院指导教师:张恕远数字闹钟的设计摘要电子时钟主要是利用电子技术将时钟电子化、数字化,拥有时钟精确、体积小、界面友好、可扩展性能强等特点,被广泛应用于生活和工作当中。
另外,在生活和工农业生产中,也常常需要温度,这就需要电子时钟具有多功能性。
本设计主要为实现一款可正常显示时钟/日历、带有定时闹铃的多功能电子时钟。
本文对当前电子钟开发手段进行了比较和分析,最终确定了采用单片机技术实现多功能电子时钟。
本设计应用AT89C52芯片作为核心,LCD1062进行显示,使用DS1302实时时钟日历芯片完成时钟/日历的基本功能。
这种实现方法的优点是电路简单,性能可靠,实时性好,时间精确,操作简单,编程容易。
该电子时钟可以应用于一般的生活和工作中,也可通过改装,提高性能,增加新功能,从而给人们的生活和工作带来更多的方便。
关键词:电子时钟;多功能;AT89C52;时钟日历目录摘要................................................I1、设计任务、目的、思路..........................................12、总体设计方案.............................................23、电路原理的设计...............................................3 3.1DS1302原理及电路....................................3 3.2晶振电路........................................3 3.3复位电路原理及电路.................................4 3.4 LCD1602原理及电路...................................4 3.5DS18B20电路.............................................5 3.6按键电路及功能.............................................53.7蜂鸣器电路.............................................64、软件系统设计.............................................7 4.1系统工作流程图.............................................74.2软件系统构成.............................................85、系统调试与结果.............................................96、课程设计体会................................................107、参考文献................................................11 附录:程序代码....................................121、设计任务、目的、思路(1)任务用LCD显示出月、日、分、星期和温度,三~四个按键可对时间进行校正,并能实现闹钟功能。
(2)目的1、掌握电子时钟的基本工作方式。
2、进一步熟悉DS1302及DS18B20芯片的特性。
3、通过使用各基本指令,进一步熟练掌握单片机的编程和程序调试。
(3)思路利用AT89C52的特点及DS1302的特点,设计一种基于DS1302单片机控制,再利用LCD显示的数字钟。
本系统硬件利用AT89S52作为CPU进行总体控制,通过DS1302时钟芯片获取准确详细的时间(年、月、日、周、日、时、分、秒准确时间),对时钟信号进行控制,同时利用液晶显示芯片LCD1602对时间进行准确显示年、月、日、周、日、时、分、秒。
2、总体设计方案根据系统设计的要求和设计思路,确定该系统的系统设计结构图。
如图所示。
硬件电路主要由AT89C52单片机控制器单元、DS1302时钟电路、复位电路、DS18B20温度模块、按键模块、晶振电路、蜂鸣器模块、LCD1602液晶显示模块等构成。
3、电路原理的设计3.1 DS1302原理及电路如下所示本设计使用的实时时钟电路芯片是美国DALLAS公司生产的一种高性能、低功耗、带RAM的实时时钟电路芯片DS1302。
VCC1为后备电源,VCC2为主电源。
在主电源关闭的情况下,也能保持时钟的连续运行。
DS1302由VCC1或VCC2两者中的较大者供电;当VCC2大于VCC1+0.2V时,VCC2给DS1302供电;当VCC2小于VCC1时,DS1302由VCC1供电。
X1和X2是振荡源,外接32.768kHz晶振。
RST非是复位/片选线,通过把RST非输入驱动置高电平来启动所有的数据传送。
图3.1-1图3.1-23.2 晶振电路如下AT89S52在工作时需要外部提供时钟信号,因此,本设计选择在其18脚19脚之间接上12MHz的晶振,为单片机提供1μs的机器振荡周期。
其电路连接图如图所示。
在图中,电容器C3、C4起稳定振荡频率、快速起振的作用,其电容值一般在20~50pF。
图3.23.3 复位电路原理及电路如下在AT89C52单片机中的振荡器运行时,RST非引脚上保持到少2个机器周期的高电平输入信号,复位过程即可完成。
根据此原理,本设计采用上电复位和按键复位嵌套在系统中,增强了系统的实用性。
图3.33.4 LCD1602原理及电路如下LCD1602液晶显示是一种专门用来显示字母、数字、符号等的点阵型液晶模块。
它由若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符,每位之间有一个点距的间隔,每行之间也有间隔,起到了字符间距和行间距的作用,正因为如此所以它不能很好地显示图形(用自定义CGRAM,显示效果也不好)。
1602LCD是指显示的内容为16X2,即可以显示两行,每行16个字符液晶模块(显示字符和数字)。
以其微功耗、体积小、显示内容丰富、超薄轻巧的诸多优点,在各种小系统中得到了更广泛的应用。
本设计中使用的液晶显示模块是LCD1602。
图3.43.5 DS18B20电路如下DS18B20,常用的温度传感器,具有体积小,硬件开销低,抗干扰能力强,精度高的特点。
图3.53.6 按键电路如下图3.6按键功能说明:KEY0为时钟调节功能键,第一次按KEY0时,时间停止且光标在年处闪烁。
第二次按KEY0时,光标在月处闪烁。
第三次按KEY0时,光标在日处闪烁。
第四次按KEY0时,光标在星期处闪烁。
第五次按KEY0时,光标在时处闪烁。
第六次按KEY0时,光标在日处闪烁。
第七次按KEY0时,光标在秒处闪烁。
光标闪烁时可用KEY1增加相应的值或KEY2减少相应的值。
第八次按KEY0时,保存了修改的时间值并返回显示时间。
KEY3为闹钟功能键。
第一次按KEY3时,进入闹钟设置页面,光标在闹钟开关处闪烁。
第二次按KEY3时,光标在分处闪烁。
第三次按KEY3时,光标在时处闪烁。
光标闪烁时,同样可以用KEY1与KEY2修改相应的值。
当闹钟响起时,1分钟后自动关闭。
3.7 蜂鸣器电路如下图3.74、软件系统设计4.1、系统工作流程图图4.1系统工作流程图4.2软件系统构成软件系统包含引脚定义及变量申明、LCD显示部分、DS1302部分、键盘扫描部分、DS18B20温度部分、主函数等等。
LCD部分对不变的显示部分进行LCD初始化,将需要变化的部分分开显示,如将年、月、日、星期显示在第一行,将时、分、秒、温度、闹钟设置显示在第二行。
DS1302对将要显示的时间送入LCD进行显示,以及对调整后的时间进行接收存储计算及送入LCD重新显示。
键盘扫描部分对键盘进行扫描,修改时间时按键使数据的改变而送入DS1302进行时间的修改,以及闹钟时间的修改。
DS18B20部分对硬件采集到的环境温度进行数据转换并送入LCD显示。
5、系统调试与结果系统调试过程利用Proteus绘制出相应硬件电路后进行仿真,出现液晶显示无法正常显示的问题。
经过思考和查阅的资料发现AT89C52的P0在进高电平时没有接上拉电阻导致LCD1602无法正常显示时间。
修改电路后(P0口接上拉电阻)烧入程序后,程序正常运行,LCD1602准确的显示。
用Proteus仿真能够正确的现实时间,但烧入学习板出现乱码现实不能正常工作。
经过反复检查及思考发现仿真软件上的硬件电路与学习板上的硬件电路不一致无法对应起来。
最后根据学习板的硬件电路修改相应程序及仿真软件上的硬件电路,最终现实了功能。
系统调试结果:图5.16、课程设计体会本设计利用单片机AT89C512控制串行实时时钟芯DS1302构成数字时钟电路,实现计时功能。
该电路使用简单的三线接口,为单片机节省大量的接口资源,时钟芯片带有后备电池。
该时钟功能强大,性能优越,能为很多领域,特别是对时钟工作的准确性和可靠性有较高要求。
通过对电子时钟的设计的设计与制作,让我了解了电子时钟模块的编程思想,也让我明白了电子时钟的基本原理与设计理念,要设计一个电路必须先编好程序,用仿真软件测试成功后再得出结论。
通过这次学习,让我对该软件有了更熟悉的了解,我们应该自己动手,实际操作,才会有更深刻的理解。
7、参考文献[1] 黄惟公.单片机原理与应用技术:西安电子科大出版社2007[2] 张毅刚.MC-51单片机应用设计(二版):哈工大出版社 2005[3] 宋戈. 黄鹤松. 51单片机应用开发范例大全:人民邮电出版社 2010[4] 刘建清. 51单片机新颖实例非常入门与视频演练:电子工业出版社2012[5] 郭天祥. 新概念51单片机C语言教程:电子工业出版社 2009附录:程序代码:#include<reg52.h>#define uchar unsigned char#define uint unsigned int/*----------------引脚定义-------------------*/sbit RST=P3^5; //DS1302片选sbit DIO=P3^4; //DS1302数据信号sbit SCLK=P3^6; //DS1302时钟信号sbit ACC7=ACC^7;sbit ACC0=ACC^0;sbit LCD_E=P2^7; //液晶使能端sbit LCD_RS=P2^6; //液晶数据命令选择端sbit LCD_RW=P2^5; //液晶读写选择端sbit key0=P1^0; //功能键sbit key1=P1^1; //增大键sbit key2=P1^2; //减小键sbit key3=P1^3; //闹钟调节按键sbit beep=P3^3; //蜂鸣器sbit DQ=P3^7; //18b20温度输入输出端void INITIAL_1302(); //初始化1302uchar READ_1302(uchar addr); //读1302void WRITE_1302(uchar addr,uchar date); //写1302uint temp; //定义整型的温度数据float f_temp; //定义浮点型的温度数据char hour,minute,second,week,day,month,year,tem;unsigned char num,num1,flag;bit alarmon,alarmoff;uchar xx,yy;unsigned char clkhh=0,clkmm=0,clkflag,clkvalue;unsigned char str1[]="20 - - ";unsigned char str2[]=" : : . C ";unsigned char str3[]="alarm : ";void delay(uchar z); //延时函数void LCD_WRITE_COM(uchar com); //LCD写函数void LCD_WRITE_DATA(uchar date); //LCD写数据void LCD_WRITE_SFM(uchar addr,uchar date); //LCD写时分秒void LCD_WRITE_NYR(uchar addr,uchar date); //LCD写年月日void LCD_WRITE_WEEK(uchar week); //LCD写星期void LCD_INITIAL(); //LCD初始化void LCD_WRITE_TEMP(uchar addr,uchar temp); //LCD写温度void keyscan(); //键盘扫描void dis_temp(uint t);void tempchange(void);void tempwritebyte(uchar dat);uchar tempread(void);bit tempreadbit(void);void dsreset(void);uint get_temp(); //获取温度/*************主函数**************/void main(){LCD_INITIAL(); //液晶初始化INITIAL_1302(); //DS1302初始化dsreset();while(1){keyscan(); //按键扫描if(flag==0) //当标志位为0,允许读取DS1302数据,将数据送入液晶显示{second=READ_1302(0x81);LCD_WRITE_SFM(6,second);minute=READ_1302(0x83);LCD_WRITE_SFM(3,minute);hour=READ_1302(0x85);LCD_WRITE_SFM(0,hour);week=READ_1302(0x8b);LCD_WRITE_WEEK(week);day=READ_1302(0x87);LCD_WRITE_NYR(8,day);month=READ_1302(0x89);LCD_WRITE_NYR(5,month);year=READ_1302(0x8d);LCD_WRITE_NYR(2,year);tempchange();dis_temp(get_temp());}}}/**********************LCD1602***************************/void delay(uchar z) //1602de延时函数{unsigned char x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void LCD_WRITE_COM(uchar com) //1602写函数{LCD_RS=0;LCD_RW=0;LCD_E=1;P0=com;delay(5);LCD_E=0;}void LCD_WRITE_DATA(uchar date) //1602写数据{LCD_RS=1;LCD_RW=0;LCD_E=1;P0=date;delay(5);LCD_E=0;}void LCD_WRITE_SFM(uchar addr,uchar date) //LCD写时分秒{unsigned char shi,ge;shi=date/10;ge=date%10;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)//LCD写年月日{char shi,ge;shi=date/10;ge=date%10;LCD_WRITE_COM(0x80+addr);LCD_WRITE_DATA(0x30+shi);LCD_WRITE_DATA(0x30+ge);}void LCD_WRITE_CLK(unsigned char addr,unsigned char date)//LCD写闹钟{char shi,ge;shi=date/10;ge=date%10;LCD_WRITE_COM(0x80+0x40+addr);LCD_WRITE_DATA(0x30+shi);LCD_WRITE_DATA(0x30+ge);}void LCD_WRITE_WEEK(uchar week)//LCD写星期{LCD_WRITE_COM(0x80+11);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_WRITE_TEMP(uchar addr,uchar temp) //LCD写温度{LCD_WRITE_COM(0x80+0x40+addr);LCD_WRITE_DATA(0x30+temp);}void CLK_INITIAL(uchar addr,uchar clknum)//闹钟初始化{uchar i;char shi,ge;shi=clknum/10;ge=clknum%10;LCD_WRITE_COM(0x38);LCD_WRITE_COM(0x0c);LCD_WRITE_COM(0x06);LCD_WRITE_COM(0x80);LCD_WRITE_COM(0x80+0x40);//液晶第二行显示for(i=0;i<16;i++){LCD_WRITE_DATA(str3[i]);delay(5);}LCD_WRITE_COM(0x80+0x40+addr);LCD_WRITE_DATA(shi/10+0x30);LCD_WRITE_DATA(ge%10+0x30);}void LCD_INITIAL() //LCD初始化{unsigned char i;LCD_WRITE_COM(0x38);LCD_WRITE_COM(0x0c);LCD_WRITE_COM(0x06);LCD_WRITE_COM(0x80);for(i=0;i<16;i++) //液晶第一行显示{LCD_WRITE_DATA(str1[i]);delay(5);}LCD_WRITE_COM(0x80+0x40);//液晶第二行显示for(i=0;i<16;i++){LCD_WRITE_DATA(str2[i]);delay(5);}}/****************1302*************/void WRITE_1302(uchar addr,uchar date)//向1302写数据{unsigned char i;RST=0;SCLK=0;RST=1;for(i=8;i>0;i--){SCLK=0;ACC=addr;DIO=ACC0;addr>>=1;SCLK=1;}for(i=8;i>0;i--){SCLK=0;ACC=date;DIO=ACC0;date>>=1;SCLK=1;}RST=0;}unsigned char READ_1302(unsigned char addr)//从1302读数据{unsigned char i,date1,date2;RST=0;SCLK=0;RST=1;for(i=8;i>0;i--){SCLK=0;ACC=addr;DIO=ACC0;addr>>=1;SCLK=1;}for(i=8;i>0;i--){ACC7=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()//初始化1302{WRITE_1302(0x80,READ_1302(0x81)&0x7f); //启动DS1302 0x80写秒地址}/****************键盘扫描部分*************************/void keyscan(){if(key0==0)//确认功能键按下{delay(20);if(key0==0)//去抖{while(!key0);//释放num++;switch(num){case 1: flag=1; //修改时间,禁止从DS1302读数据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+13);//第四次按下,光标定位到星期位置break;case 5: LCD_WRITE_COM(0x80+0x40+1);//第五次按下,光标定位到时位置break;case 6: LCD_WRITE_COM(0x80+0x40+4);//第六次按下,光标定位到分位置break;case 7: LCD_WRITE_COM(0x80+0x40+7);//第七次按下,光标定位到秒位break;case 8: num=0; //第八次按下,记录清零LCD_WRITE_COM(0x0c); //不显示光标WRITE_1302(0x8E,0x00); //允许写操作0x8E写保护WRITE_1302(0x80,(second/10*16)+second%10);//将调节后的秒写入DS1302WRITE_1302(0x82,(minute/10*16)+minute%10);//将调节后的分写入DS1302WRITE_1302(0x84,(hour/10*16)+hour%10);//将调节后的时写入DS1302WRITE_1302(0x8a,(week/10*16)+week%10);//将调节后的星期写入DS1302WRITE_1302(0x86,(day/10*16)+day%10);//将调节后的日写入DS1302WRITE_1302(0x88,(month/10*16)+month%10);//将调节后的月写入DS1302WRITE_1302(0x8c,(year/10*16)+year%10);//将调节后的年写入DS1302WRITE_1302(0x8E,0x80); //开写保护flag=0; //时间修改完毕,允许液晶从DS1302读数据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(2,year);//将调节后的年送入液晶显示LCD_WRITE_COM(0x80+3);//光标回到指定处break;case 2: month++;//调节月if(month==13)month=0;LCD_WRITE_NYR(5,month);//将调节后的月送入液晶显示LCD_WRITE_COM(0x80+6);//光标回到指定处break;case 3: day++;//调节日if(day==32)day=0;LCD_WRITE_NYR(8,day);//将调节后的日送入液晶显示LCD_WRITE_COM(0x80+9);//光标回到指定处break;case 4: week++;if(week==8)week=0;LCD_WRITE_WEEK(week);//将调节后的星期送入液晶显示LCD_WRITE_COM(0x80+13);//光标回到指定处break;case 5: hour++;if(hour==24)hour=0;LCD_WRITE_SFM(0,hour);//将调节后的小时送入液晶显示LCD_WRITE_COM(0x80+0x40+1);//光标回到指定处break;case 6: minute++;if(minute==60)minute=0;LCD_WRITE_SFM(3,minute);//将调节后的分送入液晶显示LCD_WRITE_COM(0x80+0x40+4);//光标回到指定处break;case 7: second++;if(second==60)second=0;LCD_WRITE_SFM(6,second);//将调节后的秒送入液晶显示LCD_WRITE_COM(0x80+0x40+7);//光标回到指定处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(2,year);LCD_WRITE_COM(0x80+3);break;case 2: month--;//调节月if(month==-1)month=12;LCD_WRITE_NYR(5,month);LCD_WRITE_COM(0x80+6);break;case 3: day--;//调节日if(day==-1)day=31;LCD_WRITE_NYR(8,day);LCD_WRITE_COM(0x80+9);break;case 4: week--;//调节星期if(week==0)week=7;LCD_WRITE_WEEK(week);LCD_WRITE_COM(0x80+13);break;case 5: hour--;//调节时if(hour==-1)hour=23;LCD_WRITE_SFM(0,hour);LCD_WRITE_COM(0x80+0x40+1);break;case 6: minute--;//调节分if(minute==-1)minute=59;LCD_WRITE_SFM(3,minute);LCD_WRITE_COM(0x80+0x40+4);break;case 7: second--;//调节秒if(second==-1)second=59;LCD_WRITE_SFM(6,second);LCD_WRITE_COM(0x80+0x40+7);break;default:break;}}}}/**************闹钟部分******************/if(key3==0) //闹钟调节键{delay(20);if(key3==0){while(!key3);num1++;switch(num1){case 1: CLK_INITIAL(6,clkhh);CLK_INITIAL(9,clkmm);flag=1;LCD_WRITE_COM(0x0f); //光标开始闪烁LCD_WRITE_COM(0x80+0x40+12);//第一次按//下,光标定位到闹钟开关位置break;case 2: LCD_WRITE_COM(0x80+0x40+10);//第二次按下,//光标定位到闹钟分钟位置break;case 3: LCD_WRITE_COM(0x80+0x40+7);//第二次按下,//光标定位到闹钟分钟位置break;case 4: num1=0;LCD_WRITE_COM(0x0c);LCD_INITIAL();flag=0;break;}}}if(num1!=0){if(key1==0)//确认增大键按下{delay(20);if(key1==0)//增大键确实按下{while(!key1);switch(num1){case 1: clkflag++;switch(clkflag){case 1:clkvalue=1;LCD_WRITE_DATA('O');LCD_WRITE_DATA('N');LCD_WRITE_DATA(' ');LCD_WRITE_COM(0X80+0X40+12);break;case 2:clkvalue=0;clkflag=0;LCD_WRITE_DATA('O');LCD_WRITE_DATA('F');LCD_WRITE_DATA('F');LCD_WRITE_COM(0X80+0X40+12);break;};break;case 3: clkhh++;if(clkhh==24)clkhh=0;LCD_WRITE_CLK(6,clkhh);LCD_WRITE_COM(0x80+0x40+7);//光标回到指定处break;case 2: clkmm++;if(clkmm==60)clkmm=0;LCD_WRITE_CLK(9,clkmm);LCD_WRITE_COM(0x80+0x40+10);//光标回到指定处break;default: break;}}}}if(key2==0)//确认减小键按下{delay(20);if(key2==0)//减小键确实按下{while(!key2);switch(num1){case 1: clkflag--;switch(clkflag){case -1:clkvalue=1;LCD_WRITE_DATA('O');LCD_WRITE_DATA('N');LCD_WRITE_DATA(' ');LCD_WRITE_COM(0X80+0X40+12);break;case -2:clkvalue=0;clkflag=0;LCD_WRITE_DATA('O');LCD_WRITE_DATA('F');LCD_WRITE_DATA('F');LCD_WRITE_COM(0X80+0X40+12);break;};break;case 3: clkhh--;if(clkhh==-1)clkhh=23;LCD_WRITE_CLK(6,clkhh);LCD_WRITE_COM(0x80+0x40+7);//光标回到指定处break;case 2: clkmm--;if(clkmm==-1)clkmm=59;LCD_WRITE_CLK(9,clkmm);LCD_WRITE_COM(0x80+0x40+10);//光标回到指定处break;default:break;}}}xx=READ_1302(0x83); //yy=READ_1302(0x85);if(clkhh==yy&&clkmm==xx&&clkvalue==1) //读取时间值与闹钟值比较,若相同//且闹钟开关为开则闹钟响{alarmon=1;}else{alarmon=0; //响一分钟后闹钟关闭。