万年历与LCD时间显示
万年历与LCD时间显示

> ds1302+LCD1602.rar > 万年历.C/******************************************************************** * 标题: xl 系列单片机实验仪1602 液晶万年历演示程序** 文件: XLLCDWNL.c ** 日期: 2006-1-5 ** 版本: 3.0 (试验通过版)可用xl600-xl1000 单片机综合试验仪试验** 作者: 部分程序参考网上修改而成,本站最终改编测试,特别对原作致敬!* * 邮箱: sxj1974@ ** 网站: ********************************************************************** *日历时钟**按K1,进入设置状态**按k2, 停止闹钟声音**按k3, 依次进入闹钟功能是否启用,闹钟时,分秒,年,月,日及时间时,分,秒的设置,**直到退出设置状态**按k4, 调整是否起用闹钟和调节闹钟时,分,秒,年,月,日,时间的时,分,秒的数字**LCD 第二排中间显示小喇叭,表示启用闹钟功能,无则禁止闹钟功能* 8888*(可在调整状态进行设置)**正常状态,LCD 上排最前面显示自定义字符,LCD 下排最前面闪动"XUELIN" * *设置状态,LCD 上排最前面显示"P", 下排最前面在设置闹钟时间时显示"alarm:", **其它状态显示"time" **年代变化2000--2099, 星期自动转换**程序中有自定义字符写入********************************************************************** * 【版权】Copyright(C) 深圳市学林电子有限公司 ** 【声明】此程序仅用于学习与参考,引用请注明版权和作者信息! ** 【技术支持】请访问/bbs/index.asp 官方论坛********************************************************************** #include <reg51.h>#include <intrins.h>unsigned char code dis_week[]={"SUN,MON,TUE,WED,THU,FRI,SAT"}; unsigned char code para_month[13]={0,0,3,3,6,1,4,6,2,5,0,3,5}; // 星期月参变数unsigned char data dis_buf1[16]; //lcd 上排显示缓冲区unsigned char data dis_buf2[16]; //lcd 下排显示缓冲区unsigned char data year,month,date,week;// 年、月、日、星期unsigned char data armhour,armmin,armsec;// 闹钟时、分、秒unsigned char data hour,min,sec,sec100;// 时、分、秒、百分之一秒unsigned char data flag,vkey,skey;// 设置状态计数标志、按键先前值、按键当前值bit alarm; //标识是否启用闹钟,1--启用,0--关闭sbit rs = P2^0; //LCD 数据/命令选择端(H/L)sbit rw = P2^1; //LCD 读/写选择端(H/L)sbit ep = P2^2; //LCD 使能控制sbit PRE = P1^0; //调整键(k3)sbit SET = P1^1; //调整键(k4)sbit SPK = P2^3;void delayms(unsigned char ms); // 延时程序bit lcd_busy(); //测试LCD 忙碌状态程序void lcd_wcmd(char cmd); //写入指令到LCD 程序void lcd_wdat(char dat); //写入数据到LCD 程序void lcd_pos(char pos); //LCD 数据指针位置程序void lcd_init(); //LCD 初始化设定程序void pro_timedate(); //时间日期处理程序void pro_display(); //显示处理程序void pro_key(); //按键处理程序void time_alarm(); //定时报警功能(闹钟)unsigned char scan_key(); //按键扫描程序unsigned char week_proc(); //星期自动计算与显示函数bit leap_year(); //判断是否为闰年void lcd_sef_chr(); //LCD 自定义字符程序void update_disbuf(unsigned char t1,unsigned char t2[],unsigned char dis_h,unsigned char dis_m,unsigned char dis_s); //更新显示缓冲区函数// 延时程序void delay(unsigned char ms){ while(ms--){ unsigned char i;for(i = 0; i< 250; i++){_nop_(); //执行一条_nop_() 指令为一个机器周期_nop_();_nop_();_nop_();}}}//测试LCD 忙碌状态bit lcd_busy(){bit result;rs = 0;rw = 1;ep = 1;_nop_();_nop_();_nop_();_nop_();result =(bit)(P0&amt;0x80); //LCD 的D0--D7 中,D7=1 为忙碌,D7=0 为空闲ep = 0;return result;}//写入指令到LCDvoid lcd_wcmd(char cmd)while(lcd_busy()); //当lcd_busy 为1 时,再次检测LCD 忙碌状态,lcd-busy 为0 时,开始写指令rs = 0;rw = 0;ep = 0;_nop_();_nop_();P0 = cmd;_nop_();_nop_();_nop_();_nop_();ep = 1;_nop_();_nop_();_nop_();_nop_();ep = 0;}//写入数据到LCDvoid lcd_wdat(char dat){while(lcd_busy()); //当lcd_busy 为1 时,再次检测LCD 忙碌状态,lcd-busy 为0 时,开始写数据rs = 1;rw = 0;ep = 0;P0 = dat;_nop_();_nop_();_nop_();_nop_();ep = 1;_nop_();_nop_();_nop_();_nop_();ep = 0;}//LCD 数据指针位置程序void lcd_pos(char pos){lcd_wcmd(pos|0x80); // 数据指针=80+ 地址码(00H~27H,40H~67H)}//设定二个自定义字符,(注意:LCD1602 中自定义字符的地址为0x00--0x07, 即可定义8 个字符)//这里我们设定把一个自定义字符放在0x00 位置(000),另一个放在0x01 位子(001)void lcd_sef_chr(){ //第一个自定义字符lcd_wcmd(0x40);lcd_wdat(0x1f);lcd_wcmd(0x41); //"01 000 001" 第2 行地址lcd_wdat(0x11); //"XXX 10001" 第2 行数据lcd_wcmd(0x42); //"01 000 010" 第3 行地址lcd_wdat(0x15); //"XXX 10101" 第3 行数据lcd_wcmd(0x43); //"01 000 011" 第4 行地址lcd_wdat(0x11); //"XXX 10001" 第4 行数据lcd_wcmd(0x44); //"01 000 100" 第5 行地址lcd_wdat(0x1f); //"XXX 11111" 第5 行数据lcd_wcmd(0x45); //"01 000 101" 第6 行地址lcd_wdat(0x0a); //"XXX 01010" 第6 行数据lcd_wcmd(0x46); //"01 000 110" 第7 行地址lcd_wdat(0x1f); //"XXX 11111" 第7 行数据lcd_wcmd(0x47); //"01 000 111" 第8 行地址lcd_wdat(0x00); //"XXX 00000" 第8 行数据//第二个自定义字符lcd_wcmd(0x48); //"01 001 000" 第1 行地址lcd_wdat(0x01); //"XXX 00001" 第1 行数据lcd_wcmd(0x49); //"01 001 001" 第2 行地址lcd_wdat(0x1b); //"XXX 11011" 第2 行数据lcd_wcmd(0x4a); //"01 001 010" 第3 行地址lcd_wdat(0x1d); //"XXX 11101" 第3 行数据lcd_wcmd(0x4b); //"01 001 011" 第4 行地址lcd_wdat(0x19); //"XXX 11001" 第4 行数据lcd_wcmd(0x4c); //"01 001 100" 第5 行地址lcd_wdat(0x1d); //"XXX 11101" 第5 行数据lcd_wcmd(0x4d); //"01 001 101" 第6 行地址lcd_wdat(0x1b); //"XXX 11011" 第6 行数据lcd_wcmd(0x4e); //"01 001 110" 第7 行地址lcd_wdat(0x01); //"XXX 00001" 第7 行数据lcd_wcmd(0x4f);//"01 001 111" 第8 行地址lcd_wdat(0x00); //"XXX 00000" 第8 行数据}//LCD 初始化设定void lcd_init(){lcd_wcmd(0x38); //设置LCD 为16X2 显示,5X7 点阵,八位数据借口delay(1);lcd_wcmd(0x0c); //LCD 开显示及光标设置(光标不闪烁,不显示"-")delay(1);lcd_wcmd(0x06); //LCD 显示光标移动设置(光标地址指针加1,整屏显示不移动) delay(1);lcd_wcmd(0x01); //清除LCD 的显示内容delay(1);}//闰年的计算bit leap_year(){bit leap;if((year>4==0&amt;&amt;year>100!=0)||year>400==0)// 闰年的条件leap=1;elseleap=0;return leap;}//星期的自动运算和处理unsigned char week_proc(){ unsigned char num_leap;unsigned char c;num_leap=year/4-year/100+year/400;// 自00 年起到year 所经历的闰年数if( leap_year()&amt;&amt; month<=2 ) //既是闰年且是1 月和2 月c=5;elsec=6;week=(year+para_month[month]+date+num_leap+c)>7;// 计算对应的星期return week;}//更新显示缓冲区void update_disbuf(unsigned char t1,unsigned char t2[],unsigned char dis_h,unsigned char dis_m,unsigned char dis_s){ dis_buf1[0]=t1; //dis_buf1[1]=0x20; //空格dis_buf1[2]=50; //'2'dis_buf1[3]=48; //'0'dis_buf1[4]=year/10+48;dis_buf1[5]=year>10+48;dis_buf1[6]=0x2d;dis_buf1[7]=month/10+48;dis_buf1[8]=month>10+48;dis_buf1[9]=0x2d; //'-'dis_buf1[10]=date/10+48;dis_buf1[11]=date>10+48;dis_buf1[12]=0x20;dis_buf1[13]=dis_week[4*week];dis_buf1[14]=dis_week[4*week+1];dis_buf1[15]=dis_week[4*week+2];dis_buf2[0]=t2[0];dis_buf2[1]=t2[1];dis_buf2[2]=t2[2];dis_buf2[3]=t2[3];dis_buf2[4]=t2[4];dis_buf2[5]=t2[5];dis_buf2[6]=0x20; //空格if (alarm)dis_buf2[7]=0x01; //alarm=1,显示闹钟启用标致(第二个自定义字符)elsedis_buf2[7]=0x20; //alarm=0,不显示闹钟启用标致dis_buf2[8]=dis_h/10+48;dis_buf2[9]=dis_h>10+48;dis_buf2[10]=0x3a; //':'dis_buf2[11]=dis_m/10+48;dis_buf2[12]=dis_m>10+48;dis_buf2[13]=0x3a;dis_buf2[14]=dis_s/10+48;dis_buf2[15]=dis_s>10+48;}//时间和日期处理程序void pro_timedate(){sec++;if(sec > 59){sec = 0;min++;if(min>59){min=0;hour++;if(hour>23){hour=0;date++;if(month==1||month==3||month==5||month==7||month==8||month==10||month== 12)if (date>31) {date=1;month++;} //大月31 天if (month==4||month==6||month==9||month==11)if (date>30) {date=1;month++;} //小月30 天if (month==2){if( leap_year()) //闰年的条件{if (date>29) {date=1;month++;}} //闰年2 月为29 天else{if (date>28) {date=1;month++;}} //平年2 月为28 天}if (month>12) {month=1;year++;}if (year>99) year=0;}}}week_proc();if (sec==armsec &amt;&amt; min==armmin &amt;&amt; hour==armhour) {if (alarm)TR1=1; //闹钟启用时,报警时间到,启动Timer1}}//显示处理程序void pro_display(){ unsigned char i;lcd_pos(0x00);for (i=0;i<=15;i++){lcd_wdat(dis_buf1[i]);}lcd_pos(0x40);for (i=0;i<=15;i++){lcd_wdat(dis_buf2[i]);}}//Timer0 中断处理程序,秒的产生void timer0() interrupt 1{TH0=0xdc; //Timer0 置10ms 定时初值dc00H(2^16=65536D,dc00H=56320D)TL0=0x00; //定时时间=(65536-56320)*(1/11.0592)*12=10ms (f0=11.0592Mhz) sec100++;if(sec100 >= 100) //1 秒时间(100*10ms=1000ms=1s){sec100 = 0;pro_timedate();// 调用时间和日期处理程序}if (sec&amt;0x01) //"XUELIN" 闪一秒,停一秒update_disbuf(0x00," ",hour,min,sec); //0x00 表示显示00 位置的自定义字符elseupdate_disbuf(0x00,"XUELIN",hour,min,sec);pro_display(); //调用显示处理函数}//按键扫描程序unsigned char scan_key(){skey=0x00; //给变量vkey 置初值skey|=PRE; //读取PRE 键的状态skey=skey<<1; //将PRE 键的状态存于skey 的B1 位skey|=SET; //读取SET 键的状态,并存于skey 的B0 位return skey; //返回skey 的键值(即PRE,SET 的状态)}//外部中断INT0 中断处理程序void int0() interrupt 0{TR0=0; //禁止Timer0IE=0; //禁止中断lcd_wcmd(0x0e); //显示光标"_", 整个光标不闪烁alarm=1;update_disbuf(0x50,"alarm:",armhour,armmin,armsec); // 更新显示数据,0x50 表示要显示"P"pro_display(); //调用显示处理程序lcd_pos(0x47); //使光标位于第一个调整项下flag=0;vkey=0x03;while(flag^0x0a){skey = scan_key(); //扫描按键状态if (skey^vkey) //若skey 与vkey 相同,跳出循环,相异执行循环体{ delay(10); //去按键抖动skey = scan_key(); //转回扫描按键状态if (skey^vkey) //若skey 与vkey 相同,跳出循环,相异执行循环体{ vkey=skey; //将skey 的值付给vkeyif (skey==0x01) //PRE 键按下{ flag++; //调整标志位加1switch (flag) //将光标置于相应调整位置{case 1: lcd_pos(0x49);break; //光标置小时报警设置位置case 2: lcd_pos(0x4c);break; // 光标置分钟报警设置位置case 3: lcd_pos(0x4f);break; // 光标置秒时报警设置位置case 4: update_disbuf(0x50,"time: ",hour,min,sec);pro_display();lcd_pos(0x05);break; // 光标置年调整位置case 5: lcd_pos(0x08);break; // 光标置月调整位置case 6: lcd_pos(0x0b);break; // 光标置日调整位置case 7: lcd_pos(0x49);break; //光标置时调整位置case 8: lcd_pos(0x4c);break; // 光标置分调整位置case 9: lcd_pos(0x4f);break; // 光标置秒调整位置default:break;}}if (skey==0x02) //SET 键按下{ pro_key(); //转设置按键处理程序}}} }lcd_wcmd(0x0c); //设置LCD 开显示及光标不闪烁,不显示"-"lcd_wcmd(0x01);IE=0x8f;TR0=1;//清除LCD 的显示内容//CPU 开中断,INT0,INT1, 开中断//Timer0 启动}//主程序,初始化及初值设定void main(){lcd_init(); //初始化LCDlcd_sef_chr(); //写入自定义字符号hour=0;min=0;sec=0; //开机时的时,分,秒显示armhour=0;armmin=0;armsec=0; //开机时的时,分,秒报警初值year= 5; month=1;date=1; //开机时的年,月,日,星期显示week_proc();alarm=1; //初始开机,启用闹钟IE = 0x8f; //CPU 开中断,INT0,INT1,Timer0,Timer1 开中断IP = 0x04; //设置INT0 为中断最高优先级IT0=0;IT1=0; //外部INT0,INT1 设置为电平触发方式(注意,触发不要选边沿方式,)TMOD = 0x11; //Timer0,Timer1 工作于模式1, 16 位定时方式TH0 = 0xdc;TL0 = 0x00; //Timer0 置10ms 定时初值TH1 = 0xff;TL1 = 0x00; //Timer1 置初值TR0 = 1; //Timer0 启动TR1 = 0;while(1);}//设置按键处理程序void pro_key(){switch (flag){case 0:alarm=!alarm; //启用或关闭闹钟(alarm=1: 启用,alarm=0: 关闭)update_disbuf(0x50,"alarm:",armhour,armmin,armsec); // 更新显示数据pro_display(); //调用显示处理lcd_pos(0x47);break; //光标回到原调整位置case 1:armhour++;if (armhour>23) armhour=0;update_disbuf(0x50,"alarm:",armhour,armmin,armsec); // 更新显示数据pro_display(); //调用显示处理lcd_pos(0x49);break; //光标回到原调整位置if (armmin>59) armmin=0;update_disbuf(0x50,"alarm:",armhour,armmin,armsec);pro_display();lcd_pos(0x4c);break;case 3:armsec++;if (armsec>59) armsec=0;update_disbuf(0x50,"alarm:",armhour,armmin,armsec);pro_display();lcd_pos(0x4f);break;case 4:year++;if (year> 99) year= 0;week_proc(); //星期自动运算update_disbuf(0x50,"time: ",hour,min,sec);pro_display();lcd_pos(0x05);break;case 5:month++;if (month>12) month=1;week_proc(); //星期自动运算update_disbuf(0x50,"time: ",hour,min,sec);pro_display();lcd_pos(0x08);break;case 6:date++;if(month==1||month==3||month==5||month==7||month==8||month==10||month== 12)if (date>31) date=1; //大月31 天if (month==4||month==6||month==9||month==11)if (date>30) date=1; //小月30 天if (month==2){if(leap_year()) //闰年的条件{if (date>29) date=1;} //闰年2 月为29 天else{if (date>28) date=1;}} //平年2 月为28 天week_proc(); //星期自动运算update_disbuf(0x50,"time: ",hour,min,sec);pro_display();lcd_pos(0x0b);break;if (hour>23) hour=0;update_disbuf(0x50,"time: ",hour,min,sec); pro_display();lcd_pos(0x49);break;case 8:min++;if (min>59) min=0;update_disbuf(0x50,"time: ",hour,min,sec); pro_display();lcd_pos(0x4c);break;case 9:sec++;if (sec>59) sec=0;update_disbuf(0x50,"time: ",hour,min,sec); pro_display();lcd_pos(0x4f);break;default: break ;}}//Timer1 中断处理程序,产生报警的声音void timer1() interrupt 3{TH1=0xff;TL1=0x00;SPK=~SPK;}//外部中断INT1 中断处理程序,停止报警声音void int1() interrupt 2{if(TR1)TR1=0;}。
基于stc51单片机的LCD1602显示时间的电子万年历(显示

1 课设所需软件简介1.1 Keil uVision4的简要介绍2009年2月发布Keil μVision4,Keil μVision4引入灵活的窗口管理系统,使开发人员能够使用多台监视器,并提供了视觉上的表面对窗口位置的完全控制的任何地方。
新的用户界面可以更好地利用屏幕空间和更有效地组织多个窗口,提供一个整洁,高效的环境来开发应用程序。
新版本支持更多最新的ARM芯片,还添加了一些其他新功能。
2011年3月ARM公司发布最新集成开发环境RealView MDK开发工具中集成了最新版本的Keil uVision4,其编译器、调试工具实现与ARM器件的最完美匹配。
Keil C51开发系统基本知识Keil C51开发系统基本知识1. 系统概述Keil C51软件提供丰富的库函数和功能强大的集成开发调试工具,全Windows界面。
另外重要的一点,只要看一下编译后生成的汇编代码,就能体会到Keil C51生成的目标代码效率非常之高,多数语句生成的汇编代码很紧凑,容易理解。
在开发大型软件时更能体现高级语言的优势。
下面详细介绍Keil C51开发系统各部分功能和使用。
2. Keil C51单片机软件开发系统的整体结构C51工具包的整体结构,uVision与Ishell分别是C51 for Windows和for Dos 的集成开发环境(IDE),可以完成编辑、编译、连接、调试、仿真等整个开发流程。
开发人员可用IDE本身或其它编辑器编辑C或汇编源文件。
然后分别由C51及C51编译器编译生成目标文件(.OBJ)。
目标文件可由LIB51创建生成库文件,也可以与库文件一起经L51连接定位生成绝对目标文件(.ABS)。
ABS文件由OH51转换成标准的Hex文件,以供调试器dScope51或tScope51使用进行源代码级调试,也可由仿真器使用直接对目标板进行调试,也可以直接写入程序存贮器如EPROM中。
使用独立的Keil仿真器时,注意事项:* 仿真器标配11.0592MHz的晶振,但用户可以在仿真器上的晶振插孔中换插其他频率的晶振。
万年历+温度+LCD12864显示

delay10();
if(KEY2==1)
{
delay10();
choose++;
if(choose==8)
choose=0x01;
}
}
if(KEY3==0) //按键3--处理设定时间和返回
}
}
if(flag_2==1)
read_serial(j); //读取DS1302的时间
else
write_date_time(j);
if(flag_1==1)
{
LCD_prints("Time: ") ;
LCD_printc((j[2]>>4&0x07)+0x30); //时
read_serial(j); //读取DS1302的时间
ShowNumber(2,32,j[2]>>4&0x03);
ShowNumber(2,40, j[2]&0x0f);
ShowChina(2,48,3);
ShowNumber(2,64,j[1]>>4&0x07);
sbit KEY2=P3^3;
sbit KEY3=P3^4;
sbit KEY4=P3^5;
void delay10(void)
{
unsigned char i,j;
for(i=0;i<255;i++)
for(j=0;j<200;j++);
}
unsigned char conver(unsigned char a,unsigned char b,unsigned char c)
lcd万年历显示及数字温度计

绵阳职业技术信息工程系课程实训报告课程名称:《单片机应用技术》实训题目:lcd万年历显示及数字温度计起止时间: 2010-12-5---2010-12-15 专业班级:学生姓名:小组成员:学号:指导教师:绵阳职业技术学院信息工程系2010年12月15日摘要电子万年历是实现对年,月,日,时,分,秒数字显示的计时装置,广泛用于个人家庭,车站,码头,办公室,银行大厅等场所,成为人们日常生活中的必需品。
数字集成电路的发展和石英晶体振荡器的广泛应用,使得数字钟的精度远远超过老式钟表。
钟表的数字化给人们生产生活带来了极大的方便,在此基础上完成的万年历精度高,功能易于扩展。
可扩展成为诸如定时自动报警、按时自动打铃、时间程序自动控制、定时广播、自动起闭路灯、定时开关烘箱、通断动力设备、甚至各种定时电气的自动启用等电路。
所有这些,都是以钟表数字化为基础的。
因此,研究数字时钟及扩大其应用有着非常现实的意义。
本设计就是数字时钟简单的扩展应用并且在现实万年历的同时采用8 个数字温度传感器DS18B20 采集温度信息,通过AT89S52单片机统一发送初始化、写命令等控制信号来操作传感器,并逐一从传感器中读取温度,最后,在LCD 中循环显示温度信息;该系统还可通过键盘来设定温度的限定参数和选定特殊的显示方式,具有良好的人机界面。
实验证明,该温度检测系统具有结构简单、稳定性好、精度高等优点,值得推广。
关键词: AT89S52 单片机;万年历;蜂鸣器;数字温度检测系统;DS18B20 数字温度传感器目录第1章绪论 (3)1.1课题背景及研究意义 (3)1.2国内外现状 (3)1.3课题的设计目的 (4)1.4课题的主要工作 (4)1.5本文研究内容 (4)第二章设计要求和方案论证 (6)2.1 设计要求 (6)2.2 单片机芯片的选择方案和论证 (6)2.3 显示模块选择方案和论证 (6)2.4时钟的选择方案和论证 (7)2.5温度传感器的选择方案与论证 (7)2.6 DS18B20温度传感器与单片机的接口电路 (8)2.7 电路设计最终方案决定 (9)第三章系统的硬件设计与实现 (10)3.1 电路设计框图 (10)3.2 系统硬件概述 (10)3.3 主要单元电路的设计 (10)3.3.1 AT89S52单片机简介 (10)3.3.2 单片机主控制模块的设计 (11)3.3.4温度传感器电路设计 (13)3.3.5独立式键盘设计 (16)3.3.6液晶模块简介 (17)3.3.7液晶显示部分与AT89s52的接口 (19)3.3.8本章小结 (20)第四章系统的软件设计与实现 (28)4.1.1 系统总流程图 (21)4.1.2 温度程序流程图 (22)4.1.3 LCD显示程序流程图 (24)4.2.液晶显示程序 (28)4.3本章小结 (29)第五章仿真与调试 (30)51软件简介 (30)5.1.1 Keil软件简介 (30)5.1.2 Proteus ISIS简介 (31)5.2 Keil软件调试流程 (32)5.3 Proteus软件运行流程 (35)5.4 万年历的功能仿真 (36)5.5 硬件调试结果 (39)5.6本章小结 (40)附录 (41)附录一: (41)源程序代码: (41)附录二: (55)任务书一、设计目的、步骤及要求1、设计目的以单片机为核心,设计单片机最小系统,构成数字式温度计,能够实现实时温度的显示巩固所学知识、加强综合能力、提高软、硬件设计调试方面的能力、启发创新思维,使将相关专业课程知识综合起来,融会贯通,形成系统的概念,从而实现理论与实践相结合提高设计能力、电子线路的组装调试能力和创新能力,通过查阅资料、选定方案、设计电路、调试软件并下载到芯片中、写出完整的报告等过程,2、设计步骤内容:设计一个具有温度实时检测和动态显示功能的温度检测系统,和led动态显示图文字符的系统电路:1.LCD用于实时时钟(时、分、秒)等广告标语的显示;并能用按键进行实时调试2、利用数字温度传感器DS18B20测量温度信号,计算后在LCD上显示相应的温度值。
(完整word版)万年历(DS1302+LCD1602【程序、仿真、完整】)

基于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。
基于fpga的LCD显示万年历

接着我的上一篇博文,终于完善好了,前几天太忙了,没有及时上传,呵呵,今天晚上刚比较早刚好凌晨,及时上传一下,实现了从0000---9999年的时钟,其实万年历和十万年历,都是差不多,等到地球能转到9999年再改代码也不迟,哈哈!!我这里有顶层和底层文件,顶层主要是调用模块和做按键处理,具体按键防抖动原理,参见偶的以前的博文,我写完这个万年历的代码,还没来得及优化,占用了太多了逻辑门,可以进一步优化。
大致思路是:第一次按下KEY1 的时候,所有计时停止,再按KEY1,年就闪烁,按下KEY2和KEY3 进行加减。
再按KEY1,月就闪烁,按下KEY2和KEY3 进行加减........依次为调年-月-日-星期-时分秒,再次按一下KEY1,进入正常运行模式。
好了先上顶层模块module LCD(rst,clk,rw,rs,en,data,key1,key2,key3);input clk,rst;input key1,key2,key3;output rs,en,rw;output [7:0] data;reg key1_out,key2_out,key3_out;wire clk,rst;wire rs,en,rw;wire [7:0] data;disp U1(.clk(clk),.rst(rst),.rs(rs),.en(en),.rw(rw),.data(data),.key1(key1_out),.key2(key2_out),.key3(key3_out));//=============key1,key2,key3 按键防抖动================// reg key1_reg1,key1_reg2;reg key2_reg1,key2_reg2;reg key3_reg1,key3_reg2;reg [31:0] count;always @(posedge clk)begincount<=count+1;if(count==500000)begincount<=0;key1_reg1<=key1;key2_reg1<=key2;key3_reg1<=key3;endkey1_reg2<=key1_reg1;key2_reg2<=key2_reg1;key3_reg2<=key3_reg1;key1_out <= key1_reg2 & (!key1_reg1);key2_out <= key2_reg2 & (!key2_reg1);key3_out <= key3_reg2 & (!key3_reg1);endendmodule底层模块:module disp(rst,clk,rw,rs,en,data,key1,key2,key3);input clk,rst;input key1,key2,key3;output rs,en,rw;output [7:0] data;reg rs,en_sel;reg [7:0] data;reg [14:0] year;reg [7:0] shi,fen,miao,month,dat;reg [31:0]count,count1; //LCD CLK 分频计数器reg lcd_clk;//2行32个数据寄存器reg [7:0]one_1,one_2,one_3,one_4,one_5,one_6,one_7,one_8,one_9,one_10,one_11,one_12,on e_13,one_14,one_15,one_16;reg [7:0]two_1,two_2,two_3,two_4,two_5,two_6,two_7,two_8,two_9,two_10,two_11,two_12,two_ 13,two_14,two_15,two_16;reg [7:0] next;parameter state0 =8'h00, //设置8位格式,2行,5*7 8'h38;state1 =8'h01, //整体显示,关光标,不闪烁8'h0C 闪烁8'h0estate2 =8'h02, //设定输入方式,增量不移位8'h06state3 =8'h03, //清除显示8'h01state4 =8'h04, //显示第一行的指令80Hstate5 =8'h05, //显示第二行的指令80H+40Hscan =8'h06,nul =8'h07;parameter data0 =8'h10, //2行32个数据状态data1 =8'h11,data2 =8'h12,data3 =8'h13,data4 =8'h14,data5 =8'h15,data6 =8'h16,data7 =8'h17,data8 =8'h18,data9 =8'h19,data10 =8'h20,data11 =8'h21,data12 =8'h22,data13 =8'h23,data14 =8'h24,data15 =8'h25,data16 =8'h26,data17 =8'h27,data18 =8'h28,data19 =8'h29,data20 =8'h30,data21 =8'h31,data22 =8'h32,data23 =8'h33,data24 =8'h34,data25 =8'h35,data26 =8'h36,data27 =8'h37,data28 =8'h38,data29 =8'h39,data30 =8'h40,data31 =8'h41;initialbegin//第一行显示年-月-日星期//Mon Tue Wed Thur Fri Sat Sunone_1<=" "; one_2<=" "; one_3<=" "; one_4<=" "; one_5<="-"; one_6<=" "; one_7<=" "; one_8<="-";one_9<=" ";one_10<=" ";one_11<=" ";one_12<=" ";one_13<=" ";one_14<="";one_15<=" ";one_16<=" ";//第二行显示Clock:00-00-00two_1<="C"; two_2<="l"; two_3<="o"; two_4<="c"; two_5<="k"; two_6<=":"; two_7<=" "; two_8<=" ";two_9<="-";two_10<=" ";two_11<=" ";two_12<="-";two_13<=" ";two_14<="";two_15<=" ";two_16<=" ";shi<=8'd0;fen<=8'd0;miao<=8'd0;end//======================产生LCD 时序脉冲=========================== always @ (posedge clk ) //获得LCD时钟begincount<=count+1;if(count==32'd50000)begincount<=32'b0;lcd_clk<=~lcd_clk;endend//=====================产生闪烁扫描时钟===========================reg [31:0] count2;reg scan_flag;always @ (posedge clk or negedge rst) //获得校准时间选中闪烁状态beginif(!rst)beginscan_flag<=1'b0;endelsebegincount2<=count2+1;if(count2==32'd1*******)begincount2<=32'b0;scan_flag<=~scan_flag;endendend//====================产生按键标志位================================= reg [3:0] flag;always @ (posedge clk or negedge rst )beginif(!rst)beginflag<=4'b0;endelseif(key1)beginflag<=flag+1'b1;if(flag==4'b1000)flag<=4'b0000;endend//===================计时以及校准=======================================reg[3:0] week;reg[7:0] dat_flag;always @ (posedge clk or negedge rst ) //时钟计数器beginif(!rst)begin //初始化显示第一行2012-05-19 Sat 第二行:Clock:00-00-00 shi<=8'b0;fen<=8'b0;miao<=8'b0;month<=8'd5;dat<=8'd19;year<=16'd2012;week<=4'd5;count1<=1'b0;two_7<= (shi/8'd10)+8'b00110000;two_8<= (shi%8'd10)+8'b00110000;two_10<=(fen/8'd10)+8'b00110000;two_11<=(fen%8'd10)+8'b00110000;two_13<=(miao/8'd10)+8'b00110000;two_14<=(miao%8'd10)+8'b00110000;one_1<=(year/16'd1000)+8'b00110000;one_2<=((year%16'd1000)/16'd100)+8'b00110000;one_3<=((year%16'd100)/8'd10)+8'b00110000;one_4<=(year%8'd10)+8'b00110000;one_6<=(month/8'd10)+8'b00110000;one_7<=(month%8'd10)+8'b00110000;one_9<=(dat/8'd10)+8'b00110000;one_10<=(dat%8'd10)+8'b00110000;endelsebegintwo_7<= (shi/8'd10)+8'b00110000;two_8<= (shi%8'd10)+8'b00110000;two_10<=(fen/8'd10)+8'b00110000;two_11<=(fen%8'd10)+8'b00110000;two_13<=(miao/8'd10)+8'b00110000;two_14<=(miao%8'd10)+8'b00110000;one_1<=(year/16'd1000)+8'b00110000;one_2<=((year%16'd1000)/16'd100)+8'b00110000;one_3<=((year%16'd100)/8'd10)+8'b00110000;one_4<=(year%8'd10)+8'b00110000;one_6<=(month/8'd10)+8'b00110000;one_7<=(month%8'd10)+8'b00110000;one_9<=(dat/8'd10)+8'b00110000;one_10<=(dat%8'd10)+8'b00110000;// 判断是否为31天的月份if(month==8'd1||month==8'd3||month==8'd5||month==8'd7||month==8'd8||month==8'd10|| month==8'd12)dat_flag<=8'd31;// 判断是否为30天的月份else if(month==8'd4||month==8'd6||month==8'd9||month==8'd11)dat_flag<=8'd30;// 判断是否为闰年和平年else if(month==8'd2)beginif(year % 4 == 0 && year % 100 != 0 || year % 400 == 0)dat_flag<=28;else dat_flag<=27;endcase (week)//星期//Mon Tue Wed Thu Fri Sat Sun4'b0000 : //1beginone_13<="M";one_14<="o";one_15<="n";end4'b0001 : //2beginone_13<="T";one_14<="u";one_15<="e";end4'b0010 : //3beginone_13<="W";one_14<="e";one_15<="d"; end4'b0011 : //4beginone_13<="T";one_14<="h";one_15<="u"; end4'b0100 : //5beginone_13<="F";one_14<="r";one_15<="i"; end4'b0101 : //6beginone_13<="S";one_14<="a";one_15<="t"; end4'b0110 : //7beginone_13<="S";one_14<="u";one_15<="n"; endendcasecase(flag)4'b0000 :beginen_sel<=1'b1;count1<=count1+1'b1;if(count1==32'd4*******)begincount1<=1'b0;miao<=miao+1'b1;if(miao==8'd59)beginmiao<=1'b0;fen<=fen+1'b1;if(fen==8'd59)beginfen<=1'b0;shi<=shi+1'b1;if(shi==8'd23)beginshi<=1'b0;dat<=dat+1'b1;week<=week+1'b1;if(week==4'b0110)week<=1'b1;if(dat==dat_flag)begindat<=8'd1;month<=month+1'b1;if(month==8'd12)beginmonth<=8'd1;year<=year+1'b1;if(year==16'd9999)year<=16'd0; //可以计1万年endendendendendendend4'b0001 :begincount1<=32'b0;//shi<=shi;fen<=fen;miao<=miao;year<=year;month<=month;dat<=dat;week<=week;end4'b0010 : //调年begincase(scan_flag)1'b0:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;one_1<=8'd20;one_2<=8'd20;one_3<=8'd20;one_4<=8'd20;end1'b1:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;endendcaseif(key2) //加数beginyear<=year+1'b1;if(year==16'd9999)year<=16'd0;endif(key3) //减数beginyear<=year-1'b1;if(year==16'd0)year<=16'd9999;endend4'b0011 : //调月begincase(scan_flag)1'b0:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;one_6<=8'd20;one_7<=8'd20;end1'b1:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;endcaseif(key2) //加数beginmonth<=month+1'b1;if(month==8'd12)month<=8'd0;endif(key3) //减数beginmonth<=month-1'b1;if(month==8'd0)month<=8'd12;endend4'b0100 : //调日begincase(scan_flag)1'b0:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;one_9<=8'd20;one_10<=8'd20;end1'b1:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;endendcaseif(key2) //加数begindat<=dat+1'b1;if(dat==dat_flag)dat<=8'd0;endif(key3) //减数dat<=dat-1'b1;if(dat==8'd0)dat<=dat_flag;endend4'b0101 : //调星期begincase(scan_flag)1'b0:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;one_13<=8'd20;one_14<=8'd20;one_15<=8'd20;end1'b1:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;endendcaseif(key2) //加数beginweek<=week+1'b1;if(week==4'd6)week<=4'd0;endif(key3) //减数beginweek<=week-1'b1;if(week==4'd0)week<=4'd7;endend4'b0110 : //调时begincase(scan_flag)begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;two_7<= 8'd20;two_8<= 8'd20;end1'b1:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;endendcaseif(key2) //加数beginshi<=shi+8'b00000001;if(shi==8'd23)shi<=8'b0;endif(key3) //减数beginshi<=shi-8'b00000001;if(shi==8'b0)shi<=23;endend4'b0111 : //调分begincase(scan_flag)1'b0:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;two_10<=8'd20;two_11<=8'd20;end1'b1:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;endendcaseif(key2) //加数beginfen<=fen+8'b00000001;if(fen==8'd59)fen<=8'b0;endif(key3) //减数beginfen<=fen-8'b00000001;if(fen==8'b0)fen<=59;endend4'b1000 : //调秒begincase(scan_flag)1'b0:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;two_13<=8'd20;two_14<=8'd20;end1'b1:begincount1<=32'b0; //shi<=shi;fen<=fen;miao<=miao;endendcaseif(key2) //加数beginmiao<=miao+8'b00000001;if(miao==8'd59)miao<=8'b0;endif(key3) //减数beginmiao<=miao-8'b00000001;if(miao==8'b0)miao<=59;endendendcaseendendalways @(posedge lcd_clk )begincase(next)state0 :begin rs<=1'b0; data<=8'h38; next<=state1; endstate1 :begin rs<=1'b0; data<=8'h0e; next<=state2; endstate2 :begin rs<=1'b0; data<=8'h06; next<=state3; endstate3 :begin rs<=1'b0; data<=8'h01; next<=state4; endstate4 :begin rs<=1'b0; data<=8'h80; next<=data0; end //显示第一行data0 :begin rs<=1'b1; data<=one_1; next<=data1 ; enddata1 :begin rs<=1'b1; data<=one_2; next<=data2 ; enddata2 :begin rs<=1'b1; data<=one_3; next<=data3 ; enddata3 :begin rs<=1'b1; data<=one_4; next<=data4 ; enddata4 :data5 :begin rs<=1'b1; data<=one_6; next<=data6 ; enddata6 :begin rs<=1'b1; data<=one_7; next<=data7 ; enddata7 :begin rs<=1'b1; data<=one_8; next<=data8 ; enddata8 :begin rs<=1'b1; data<=one_9; next<=data9 ; enddata9 :begin rs<=1'b1; data<=one_10; next<=data10 ; enddata10 :begin rs<=1'b1; data<=one_11; next<=data11 ; enddata11 :begin rs<=1'b1; data<=one_12; next<=data12 ; enddata12 :begin rs<=1'b1; data<=one_13; next<=data13 ; enddata13 :begin rs<=1'b1; data<=one_14; next<=data14 ; enddata14 :begin rs<=1'b1; data<=one_15; next<=data15 ; enddata15 :begin rs<=1'b1; data<=one_16; next<=state5 ; endstate5:begin rs<=1'b0;data<=8'hC0; next<=data16; end //显示第二行data16 :begin rs<=1'b1; data<=two_1; next<=data17 ; enddata17 :begin rs<=1'b1; data<=two_2; next<=data18 ; enddata18 :begin rs<=1'b1; data<=two_3; next<=data19 ; enddata19 :begin rs<=1'b1; data<=two_4; next<=data20 ; enddata20 :data21 :begin rs<=1'b1; data<=two_6; next<=data22 ; enddata22 :begin rs<=1'b1; data<=two_7; next<=data23 ; enddata23 :begin rs<=1'b1; data<=two_8; next<=data24 ; enddata24 :begin rs<=1'b1; data<=two_9; next<=data25 ; enddata25 :begin rs<=1'b1; data<=two_10; next<=data26 ; end data26 :begin rs<=1'b1; data<=two_11; next<=data27 ; end data27 :begin rs<=1'b1; data<=two_12; next<=data28 ; end data28 :begin rs<=1'b1; data<=two_13; next<=data29 ; end data29 :begin rs<=1'b1; data<=two_14; next<=data30 ; end data30 :begin rs<=1'b1; data<=two_15; next<=data31 ; end data31 :begin rs<=1'b1; data<=two_16; next<=scan ; endscan : //交替更新第一行和第二行数据beginnext<=state4;enddefault: next<=state0;endcaseendassign en=lcd_clk && en_sel;assign rw=1'b0;endmodule。
lcd数显温度万年历电波钟

外观尺寸:29cm(宽)*18.5cm(高)可挂可摆,背面有挂孔,可挂在墙上,也可以安装随机配送的支架摆放在台面上。
电子说明书地址:/item.htm?spm=a1z09.5.0.4 0&id=16362908718功能特点:1、时间显示:时:分:秒,12/24小时制可选2、日历显示:日/月3、星期显示:英文简写4、温度显示:摄氏或华摄,范围:0℃-50℃(32℉-122℉),分辨率:0.1℃。
5、闹铃功能:可设置1个闹铃时间。
6、特殊日期提醒功能:可设置三个特殊日期提醒。
使用电源:两节AA电池(不配送电池),超省电,两节电池可使用一年以上。
使用说明:一、信号自动同步:当时钟正确装上电池后,稍等几秒,自动开始接收日本发射的无线电校时信号,接收过程中屏幕右上角显示一个闪动的信号接收塔标识。
当接收到正确的时间信号后,接收塔标识停止闪动并自动同步时间和日历信息,时钟每天会定时进行接收,无须人工干预。
如果接收不成功,时钟仍可以作为一个高精度石英钟使用。
时钟在接收信号的过程(接收塔标识闪动)中无法进行其他功能的操作,如果需要进行其它设置或取消接收,须按下‘+’键退出接收状态。
为了达到最好的接收效果,应将时钟远离其它用电器至少在1-2米以上,并可以适当转动时钟位置以获取最佳接收效果。
二、信号手动同步:在正常的时钟显示模式,长按‘+’键,强制进入信号接收状态,此时收塔标识闪动,接收过程与自动同步一样。
三、手动设定时钟、日历:在正常的时钟显示模式,长按‘CLK/CAL’键,进入时间日历设置界面,当前设置项目闪动,通过短按‘+,-’键调整数值,再短按‘CLK/CAL’确认并进入下一设置项目。
设置项目顺序:12/24时制—小时—分钟—年—月—日—时区。
四、每日闹钟设置:在正常的时钟显示模式,长按‘ALARM’键,进入闹铃设置界面,通过短按按‘+,-’键输入每天的闹铃时间,最后按‘ALARM’键确认。
在正常的时钟显示模式,短按‘-’键可以开启和关闭闹铃功能,当闹铃响时,按任意键都可以关闭闹铃。
电子时钟+万年历(LCD1602)

基于AT89S52的lcd1602显示电子时钟+万年历/**********************************************名称:基于AT89S52的lcd1602显示电子时钟+万年历编写:李松泽时间:2013.07.30**********************************************/#include<reg52.h>#define uchar unsigned char#define uint unsigned intuchar code table[]=" 2013-07-30 WED ";uchar code table1[]=" 21:14:55";uchar code table2[]=" 579259 ";uchar code table3[]="Made by Lisongze";uchar code table4[]="MONTUEWEDTHUFRISATSUN"; uchar count,s1num;char miao,fen,shi,ri,yue;uint nian;sbit lcd_rs = P0^5;sbit lcd_rw = P0^6;sbit lcd_en = P0^7;sbit s1=P3^7;sbit s2=P3^6;sbit s3=P3^5;sbit g=P3^0;void delay(uint z)//延时子函数{uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void write_com(uchar com)//写命令函数{lcd_rs = 0;P2= com;delay(5);lcd_en=1;delay(5);lcd_en=0;}void write_date(uchar date)//写数据函数{lcd_rs = 1;P2= date;delay(5);lcd_en=1;delay(5);lcd_en=0;}void init()//初始化函数{int num;shi=21;fen=14;miao=55;ri=30;yue=7;nian=2013;lcd_en=0;lcd_rw=0;write_com(0x38);//显示设置模式write_com(0x0c);//00001100开显示,不显示光标,光标不闪烁write_com(0x06);//00000110地址指针加一,整屏不移动write_com(0x01);//清屏write_com(0x80);for(num=0;num<16;num++)//显示数字579259{write_date(table2[num]);delay(300);}write_com(0x80+0x40);for(num=0;num<16;num++)//显示made by lisongze{write_date(table3[num]);delay(300);}delay(5000);write_com(0x01);write_com(0x80);for(num=0;num<16;num++)//显示日期{write_date(table[num]);delay(5);}write_com(0x80+0x40);for(num=0;num<12;num++)//显示时间{write_date(table1[num]);delay(5);}TMOD=0x01;//启动定时器中断TH0=(65535-50000)/256;TL0=(65535-50000)%256;EA=1;ET0=1;TR0=1;//打开定时器}void write_sfm(uchar add,uchar date)//写时分秒函数{uchar shi,ge;shi=date/10;ge=date%10;write_com(0x80+0x40+add);write_date(0x30+shi);write_date(0x30+ge);}void write_nyr(uint add,uint date)//写年月日函数,此处若用uchar范围只有0-255 { //不够,改用uint(0-65535) uint qian,bai,shi,ge;qian=date/1000;bai=date%1000/100;shi=date%100/10;ge=date%10;write_com(0x80+add);write_date(0x30+qian);write_date(0x30+bai);write_date(0x30+shi);write_date(0x30+ge);}void write_yr(uchar add,uchar date)//写月日函数{uchar shi,ge;shi=date/10;ge=date%10;write_com(0x80+add);write_date(0x30+shi);write_date(0x30+ge);}void keyscan()//按键扫描函数{int m,n;g=0;//将矩阵键盘当做独立键盘使用if(s1==0){delay(5);if(s1==0)//按键1光标移位扫描{s1num++;if(s1num==1){ while(!s1);//等待按键松手write_com(0x80+0x40+10);TR0=0;//关闭定时器write_com(0x0f);}if(s1num==2){while(!s1);write_com(0x80+0x40+7);}if(s1num==3){while(!s1);write_com(0x80+0x40+4);}if(s1num==4){while(!s1);write_com(0x80+3);}if(s1num==5){while(!s1);write_com(0x80+6);}if(s1num==6){while(!s1);write_com(0x80+9);}if(s1num==7){while(!s1)write_com(0x80+13);}if(s1num==8){while(!s1);s1num=0;write_com(0x0c);TR0=1;//开定时器}}}if(s1num!=0){if(s2==0)//按键2加功能{delay(5);if(s2==0){while(!s2);if(s1num==1)//秒加{miao++;if(miao==60){miao=0;}write_sfm(10,miao);write_com(0x80+0x40+10);}if(s1num==2)//分加{fen++;if(fen==60){fen=0;}write_sfm(7,fen);write_com(0x80+0x40+7);}if(s1num==3)//时加{shi++;if(shi==24){shi=0;}write_sfm(4,shi);write_com(0x80+0x40+4);}if(s1num==4)//年加{nian++;if(nian==10000){nian=2000;}write_nyr(1,nian);write_com(0x80+3);}if(s1num==5)//月份加{yue++;if(yue==13){yue=1;}write_yr(6,yue);write_com(0x80+6);}if(s1num==6)//日期加{ri++;if(ri==29&&yue==2&&!((nian%4==0&&nian%100!=0)||nian%400==0)){ri=1;//平年}if(ri==30&&yue==2&&((nian%4==0&&nian%100!=0||nian%400==0))){ri=1;//闰年}if(ri==31&&(yue==4||yue==6||yue==9||yue==11)){ri=1;}if(ri==32){ri=1;}write_yr(9,ri);write_com(0x80+9);}if(s1num==7)//星期加{m=m+3;if(m==21)m=0;write_com(0x80+12);for(n=m;n<m+3;n++){write_date(table4[n]);delay(5);}write_com(0x80+13);}}}if(s3==0)//按键3减功能{delay(5);if(s3==0){while(!s3);if(s1num==1)//秒减{miao--;if(miao==-1){miao=59;}write_sfm(10,miao);write_com(0x80+0x40+10);}if(s1num==2)//分减{fen--;if(fen==-1)fen=59;write_sfm(7,fen);write_com(0x80+0x40+7);}if(s1num==3)//时减{shi--;if(shi==-1)shi=23;write_sfm(4,shi);write_com(0x80+0x40+4);}if(s1num==4)//年减{nian--;if(nian==1999)nian=2000;write_nyr(1,nian);write_com(0x80+3);if(s1num==5)//月份减{yue--;if(yue==0)yue=12;write_yr(6,yue);write_com(0x80+6);}if(s1num==6)//日减{ri--;if(ri==0){if(yue==2&&!((nian%4==0&&nian%100!=0)||nian%400==0)){ri=28;//平年}if(yue==2&&((nian%4==0&&nian%100!=0||nian%400==0))){ri=29;//闰年}if(yue==4||yue==6||yue==9||yue==11){ri=30;}if(yue==1||yue==3||yue==5||yue==7||yue==9||yue==11)ri=31;}write_yr(9,ri);write_com(0x80+9);}if(s1num==7)//星期减{m=m-3;if(m==0)m=21;write_com(0x80+12);for(n=m;n-3<m;n++){write_date(table4[n-3]);delay(5);}write_com(0x80+13);}}}}void main(){int i,j;init();while(1){keyscan();if(count==18){count=0;miao++;if(miao==60){miao=0;fen++;if(fen==60){fen=0;shi++;if(shi==24){shi=0;ri++;j=j+3;if(j==21)j=0;write_com(0x80+12);for(i=j;i<j+3;i++){write_date(table4[i]);delay(5);}if(ri==29&&yue==2&&!((nian%4==0&&nian%100!=0)||nian%400==0)){ri=1;yue++;//平年}if(ri==30&&yue==2&&((nian%4==0&&nian%100!=0||nian%400==0))){ri=1;yue++;//闰年}if(ri==31&&(yue==4||yue==6||yue==9||yue==11)){ri=1;yue++;}if(ri==32){ri=1;yue++;}if(yue==13){yue=1;nian++;if(nian==10000){nian=2000;}write_nyr(1,nian);}write_yr(6,yue);}write_yr(9,ri);write_sfm(4,shi);}write_sfm(7,fen);}write_sfm(10,miao);}}}void timer() interrupt 1{TH0=(65535-50000)/256;TL0=(65535-50000)%256;count++;}说明:单片机最小系统在这里就不用给图了,对于单片机学习者就不用提了,仅仅给个lcd1602连接图就够了,对了,要说明一点,笔者的最小系统上独立键盘不够,所以就暂且用矩阵键盘代替独立键盘,程序更要说明是在郭天祥视频讲解的基础上加上自己的思想(实现万年历的功能),程序基本上没有问题,就是偶尔调时完,走时有点迟钝,希望能够和大家共同交流!QQ:782373034电子群:257584167。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
> ds1302+LCD1602.rar > 万年历.C/******************************************************************** * 标题: xl 系列单片机实验仪1602 液晶万年历演示程序** 文件: XLLCDWNL.c ** 日期: 2006-1-5 ** 版本: 3.0 (试验通过版)可用xl600-xl1000 单片机综合试验仪试验** 作者: 部分程序参考网上修改而成,本站最终改编测试,特别对原作致敬!* * 邮箱: sxj1974@ ** 网站: ********************************************************************** *日历时钟**按K1,进入设置状态**按k2, 停止闹钟声音**按k3, 依次进入闹钟功能是否启用,闹钟时,分秒,年,月,日及时间时,分,秒的设置,**直到退出设置状态**按k4, 调整是否起用闹钟和调节闹钟时,分,秒,年,月,日,时间的时,分,秒的数字**LCD 第二排中间显示小喇叭,表示启用闹钟功能,无则禁止闹钟功能* 8888*(可在调整状态进行设置)**正常状态,LCD 上排最前面显示自定义字符,LCD 下排最前面闪动"XUELIN" * *设置状态,LCD 上排最前面显示"P", 下排最前面在设置闹钟时间时显示"alarm:", **其它状态显示"time" **年代变化2000--2099, 星期自动转换**程序中有自定义字符写入********************************************************************** * 【版权】Copyright(C) 深圳市学林电子有限公司 ** 【声明】此程序仅用于学习与参考,引用请注明版权和作者信息! ** 【技术支持】请访问/bbs/index.asp 官方论坛********************************************************************** #include <reg51.h>#include <intrins.h>unsigned char code dis_week[]={"SUN,MON,TUE,WED,THU,FRI,SAT"}; unsigned char code para_month[13]={0,0,3,3,6,1,4,6,2,5,0,3,5}; // 星期月参变数unsigned char data dis_buf1[16]; //lcd 上排显示缓冲区unsigned char data dis_buf2[16]; //lcd 下排显示缓冲区unsigned char data year,month,date,week;// 年、月、日、星期unsigned char data armhour,armmin,armsec;// 闹钟时、分、秒unsigned char data hour,min,sec,sec100;// 时、分、秒、百分之一秒unsigned char data flag,vkey,skey;// 设置状态计数标志、按键先前值、按键当前值bit alarm; //标识是否启用闹钟,1--启用,0--关闭sbit rs = P2^0; //LCD 数据/命令选择端(H/L)sbit rw = P2^1; //LCD 读/写选择端(H/L)sbit ep = P2^2; //LCD 使能控制sbit PRE = P1^0; //调整键(k3)sbit SET = P1^1; //调整键(k4)sbit SPK = P2^3;void delayms(unsigned char ms); // 延时程序bit lcd_busy(); //测试LCD 忙碌状态程序void lcd_wcmd(char cmd); //写入指令到LCD 程序void lcd_wdat(char dat); //写入数据到LCD 程序void lcd_pos(char pos); //LCD 数据指针位置程序void lcd_init(); //LCD 初始化设定程序void pro_timedate(); //时间日期处理程序void pro_display(); //显示处理程序void pro_key(); //按键处理程序void time_alarm(); //定时报警功能(闹钟)unsigned char scan_key(); //按键扫描程序unsigned char week_proc(); //星期自动计算与显示函数bit leap_year(); //判断是否为闰年void lcd_sef_chr(); //LCD 自定义字符程序void update_disbuf(unsigned char t1,unsigned char t2[],unsigned char dis_h,unsigned char dis_m,unsigned char dis_s); //更新显示缓冲区函数// 延时程序void delay(unsigned char ms){ while(ms--){ unsigned char i;for(i = 0; i< 250; i++){_nop_(); //执行一条_nop_() 指令为一个机器周期_nop_();_nop_();_nop_();}}}//测试LCD 忙碌状态bit lcd_busy(){bit result;rs = 0;rw = 1;ep = 1;_nop_();_nop_();_nop_();_nop_();result =(bit)(P0&amt;0x80); //LCD 的D0--D7 中,D7=1 为忙碌,D7=0 为空闲ep = 0;return result;}//写入指令到LCDvoid lcd_wcmd(char cmd)while(lcd_busy()); //当lcd_busy 为1 时,再次检测LCD 忙碌状态,lcd-busy 为0 时,开始写指令rs = 0;rw = 0;ep = 0;_nop_();_nop_();P0 = cmd;_nop_();_nop_();_nop_();_nop_();ep = 1;_nop_();_nop_();_nop_();_nop_();ep = 0;}//写入数据到LCDvoid lcd_wdat(char dat){while(lcd_busy()); //当lcd_busy 为1 时,再次检测LCD 忙碌状态,lcd-busy 为0 时,开始写数据rs = 1;rw = 0;ep = 0;P0 = dat;_nop_();_nop_();_nop_();_nop_();ep = 1;_nop_();_nop_();_nop_();_nop_();ep = 0;}//LCD 数据指针位置程序void lcd_pos(char pos){lcd_wcmd(pos|0x80); // 数据指针=80+ 地址码(00H~27H,40H~67H)}//设定二个自定义字符,(注意:LCD1602 中自定义字符的地址为0x00--0x07, 即可定义8 个字符)//这里我们设定把一个自定义字符放在0x00 位置(000),另一个放在0x01 位子(001)void lcd_sef_chr(){ //第一个自定义字符lcd_wcmd(0x40);lcd_wdat(0x1f);lcd_wcmd(0x41); //"01 000 001" 第2 行地址lcd_wdat(0x11); //"XXX 10001" 第2 行数据lcd_wcmd(0x42); //"01 000 010" 第3 行地址lcd_wdat(0x15); //"XXX 10101" 第3 行数据lcd_wcmd(0x43); //"01 000 011" 第4 行地址lcd_wdat(0x11); //"XXX 10001" 第4 行数据lcd_wcmd(0x44); //"01 000 100" 第5 行地址lcd_wdat(0x1f); //"XXX 11111" 第5 行数据lcd_wcmd(0x45); //"01 000 101" 第6 行地址lcd_wdat(0x0a); //"XXX 01010" 第6 行数据lcd_wcmd(0x46); //"01 000 110" 第7 行地址lcd_wdat(0x1f); //"XXX 11111" 第7 行数据lcd_wcmd(0x47); //"01 000 111" 第8 行地址lcd_wdat(0x00); //"XXX 00000" 第8 行数据//第二个自定义字符lcd_wcmd(0x48); //"01 001 000" 第1 行地址lcd_wdat(0x01); //"XXX 00001" 第1 行数据lcd_wcmd(0x49); //"01 001 001" 第2 行地址lcd_wdat(0x1b); //"XXX 11011" 第2 行数据lcd_wcmd(0x4a); //"01 001 010" 第3 行地址lcd_wdat(0x1d); //"XXX 11101" 第3 行数据lcd_wcmd(0x4b); //"01 001 011" 第4 行地址lcd_wdat(0x19); //"XXX 11001" 第4 行数据lcd_wcmd(0x4c); //"01 001 100" 第5 行地址lcd_wdat(0x1d); //"XXX 11101" 第5 行数据lcd_wcmd(0x4d); //"01 001 101" 第6 行地址lcd_wdat(0x1b); //"XXX 11011" 第6 行数据lcd_wcmd(0x4e); //"01 001 110" 第7 行地址lcd_wdat(0x01); //"XXX 00001" 第7 行数据lcd_wcmd(0x4f);//"01 001 111" 第8 行地址lcd_wdat(0x00); //"XXX 00000" 第8 行数据}//LCD 初始化设定void lcd_init(){lcd_wcmd(0x38); //设置LCD 为16X2 显示,5X7 点阵,八位数据借口delay(1);lcd_wcmd(0x0c); //LCD 开显示及光标设置(光标不闪烁,不显示"-")delay(1);lcd_wcmd(0x06); //LCD 显示光标移动设置(光标地址指针加1,整屏显示不移动) delay(1);lcd_wcmd(0x01); //清除LCD 的显示内容delay(1);}//闰年的计算bit leap_year(){bit leap;if((year>4==0&amt;&amt;year>100!=0)||year>400==0)// 闰年的条件leap=1;elseleap=0;return leap;}//星期的自动运算和处理unsigned char week_proc(){ unsigned char num_leap;unsigned char c;num_leap=year/4-year/100+year/400;// 自00 年起到year 所经历的闰年数if( leap_year()&amt;&amt; month<=2 ) //既是闰年且是1 月和2 月c=5;elsec=6;week=(year+para_month[month]+date+num_leap+c)>7;// 计算对应的星期return week;}//更新显示缓冲区void update_disbuf(unsigned char t1,unsigned char t2[],unsigned char dis_h,unsigned char dis_m,unsigned char dis_s){ dis_buf1[0]=t1; //dis_buf1[1]=0x20; //空格dis_buf1[2]=50; //'2'dis_buf1[3]=48; //'0'dis_buf1[4]=year/10+48;dis_buf1[5]=year>10+48;dis_buf1[6]=0x2d;dis_buf1[7]=month/10+48;dis_buf1[8]=month>10+48;dis_buf1[9]=0x2d; //'-'dis_buf1[10]=date/10+48;dis_buf1[11]=date>10+48;dis_buf1[12]=0x20;dis_buf1[13]=dis_week[4*week];dis_buf1[14]=dis_week[4*week+1];dis_buf1[15]=dis_week[4*week+2];dis_buf2[0]=t2[0];dis_buf2[1]=t2[1];dis_buf2[2]=t2[2];dis_buf2[3]=t2[3];dis_buf2[4]=t2[4];dis_buf2[5]=t2[5];dis_buf2[6]=0x20; //空格if (alarm)dis_buf2[7]=0x01; //alarm=1,显示闹钟启用标致(第二个自定义字符)elsedis_buf2[7]=0x20; //alarm=0,不显示闹钟启用标致dis_buf2[8]=dis_h/10+48;dis_buf2[9]=dis_h>10+48;dis_buf2[10]=0x3a; //':'dis_buf2[11]=dis_m/10+48;dis_buf2[12]=dis_m>10+48;dis_buf2[13]=0x3a;dis_buf2[14]=dis_s/10+48;dis_buf2[15]=dis_s>10+48;}//时间和日期处理程序void pro_timedate(){sec++;if(sec > 59){sec = 0;min++;if(min>59){min=0;hour++;if(hour>23){hour=0;date++;if(month==1||month==3||month==5||month==7||month==8||month==10||month== 12)if (date>31) {date=1;month++;} //大月31 天if (month==4||month==6||month==9||month==11)if (date>30) {date=1;month++;} //小月30 天if (month==2){if( leap_year()) //闰年的条件{if (date>29) {date=1;month++;}} //闰年2 月为29 天else{if (date>28) {date=1;month++;}} //平年2 月为28 天}if (month>12) {month=1;year++;}if (year>99) year=0;}}}week_proc();if (sec==armsec &amt;&amt; min==armmin &amt;&amt; hour==armhour) {if (alarm)TR1=1; //闹钟启用时,报警时间到,启动Timer1}}//显示处理程序void pro_display(){ unsigned char i;lcd_pos(0x00);for (i=0;i<=15;i++){lcd_wdat(dis_buf1[i]);}lcd_pos(0x40);for (i=0;i<=15;i++){lcd_wdat(dis_buf2[i]);}}//Timer0 中断处理程序,秒的产生void timer0() interrupt 1{TH0=0xdc; //Timer0 置10ms 定时初值dc00H(2^16=65536D,dc00H=56320D)TL0=0x00; //定时时间=(65536-56320)*(1/11.0592)*12=10ms (f0=11.0592Mhz) sec100++;if(sec100 >= 100) //1 秒时间(100*10ms=1000ms=1s){sec100 = 0;pro_timedate();// 调用时间和日期处理程序}if (sec&amt;0x01) //"XUELIN" 闪一秒,停一秒update_disbuf(0x00," ",hour,min,sec); //0x00 表示显示00 位置的自定义字符elseupdate_disbuf(0x00,"XUELIN",hour,min,sec);pro_display(); //调用显示处理函数}//按键扫描程序unsigned char scan_key(){skey=0x00; //给变量vkey 置初值skey|=PRE; //读取PRE 键的状态skey=skey<<1; //将PRE 键的状态存于skey 的B1 位skey|=SET; //读取SET 键的状态,并存于skey 的B0 位return skey; //返回skey 的键值(即PRE,SET 的状态)}//外部中断INT0 中断处理程序void int0() interrupt 0{TR0=0; //禁止Timer0IE=0; //禁止中断lcd_wcmd(0x0e); //显示光标"_", 整个光标不闪烁alarm=1;update_disbuf(0x50,"alarm:",armhour,armmin,armsec); // 更新显示数据,0x50 表示要显示"P"pro_display(); //调用显示处理程序lcd_pos(0x47); //使光标位于第一个调整项下flag=0;vkey=0x03;while(flag^0x0a){skey = scan_key(); //扫描按键状态if (skey^vkey) //若skey 与vkey 相同,跳出循环,相异执行循环体{ delay(10); //去按键抖动skey = scan_key(); //转回扫描按键状态if (skey^vkey) //若skey 与vkey 相同,跳出循环,相异执行循环体{ vkey=skey; //将skey 的值付给vkeyif (skey==0x01) //PRE 键按下{ flag++; //调整标志位加1switch (flag) //将光标置于相应调整位置{case 1: lcd_pos(0x49);break; //光标置小时报警设置位置case 2: lcd_pos(0x4c);break; // 光标置分钟报警设置位置case 3: lcd_pos(0x4f);break; // 光标置秒时报警设置位置case 4: update_disbuf(0x50,"time: ",hour,min,sec);pro_display();lcd_pos(0x05);break; // 光标置年调整位置case 5: lcd_pos(0x08);break; // 光标置月调整位置case 6: lcd_pos(0x0b);break; // 光标置日调整位置case 7: lcd_pos(0x49);break; //光标置时调整位置case 8: lcd_pos(0x4c);break; // 光标置分调整位置case 9: lcd_pos(0x4f);break; // 光标置秒调整位置default:break;}}if (skey==0x02) //SET 键按下{ pro_key(); //转设置按键处理程序}}} }lcd_wcmd(0x0c); //设置LCD 开显示及光标不闪烁,不显示"-"lcd_wcmd(0x01);IE=0x8f;TR0=1;//清除LCD 的显示内容//CPU 开中断,INT0,INT1, 开中断//Timer0 启动}//主程序,初始化及初值设定void main(){lcd_init(); //初始化LCDlcd_sef_chr(); //写入自定义字符号hour=0;min=0;sec=0; //开机时的时,分,秒显示armhour=0;armmin=0;armsec=0; //开机时的时,分,秒报警初值year= 5; month=1;date=1; //开机时的年,月,日,星期显示week_proc();alarm=1; //初始开机,启用闹钟IE = 0x8f; //CPU 开中断,INT0,INT1,Timer0,Timer1 开中断IP = 0x04; //设置INT0 为中断最高优先级IT0=0;IT1=0; //外部INT0,INT1 设置为电平触发方式(注意,触发不要选边沿方式,)TMOD = 0x11; //Timer0,Timer1 工作于模式1, 16 位定时方式TH0 = 0xdc;TL0 = 0x00; //Timer0 置10ms 定时初值TH1 = 0xff;TL1 = 0x00; //Timer1 置初值TR0 = 1; //Timer0 启动TR1 = 0;while(1);}//设置按键处理程序void pro_key(){switch (flag){case 0:alarm=!alarm; //启用或关闭闹钟(alarm=1: 启用,alarm=0: 关闭)update_disbuf(0x50,"alarm:",armhour,armmin,armsec); // 更新显示数据pro_display(); //调用显示处理lcd_pos(0x47);break; //光标回到原调整位置case 1:armhour++;if (armhour>23) armhour=0;update_disbuf(0x50,"alarm:",armhour,armmin,armsec); // 更新显示数据pro_display(); //调用显示处理lcd_pos(0x49);break; //光标回到原调整位置if (armmin>59) armmin=0;update_disbuf(0x50,"alarm:",armhour,armmin,armsec);pro_display();lcd_pos(0x4c);break;case 3:armsec++;if (armsec>59) armsec=0;update_disbuf(0x50,"alarm:",armhour,armmin,armsec);pro_display();lcd_pos(0x4f);break;case 4:year++;if (year> 99) year= 0;week_proc(); //星期自动运算update_disbuf(0x50,"time: ",hour,min,sec);pro_display();lcd_pos(0x05);break;case 5:month++;if (month>12) month=1;week_proc(); //星期自动运算update_disbuf(0x50,"time: ",hour,min,sec);pro_display();lcd_pos(0x08);break;case 6:date++;if(month==1||month==3||month==5||month==7||month==8||month==10||month== 12)if (date>31) date=1; //大月31 天if (month==4||month==6||month==9||month==11)if (date>30) date=1; //小月30 天if (month==2){if(leap_year()) //闰年的条件{if (date>29) date=1;} //闰年2 月为29 天else{if (date>28) date=1;}} //平年2 月为28 天week_proc(); //星期自动运算update_disbuf(0x50,"time: ",hour,min,sec);pro_display();lcd_pos(0x0b);break;if (hour>23) hour=0;update_disbuf(0x50,"time: ",hour,min,sec); pro_display();lcd_pos(0x49);break;case 8:min++;if (min>59) min=0;update_disbuf(0x50,"time: ",hour,min,sec); pro_display();lcd_pos(0x4c);break;case 9:sec++;if (sec>59) sec=0;update_disbuf(0x50,"time: ",hour,min,sec); pro_display();lcd_pos(0x4f);break;default: break ;}}//Timer1 中断处理程序,产生报警的声音void timer1() interrupt 3{TH1=0xff;TL1=0x00;SPK=~SPK;}//外部中断INT1 中断处理程序,停止报警声音void int1() interrupt 2{if(TR1)TR1=0;}。