单片机LCD1602显示年月日时钟带星期和闹钟
C语言Lcd1602万年历闹钟Proteus仿真单片机毕业课程电子设计
C语言Lcd1602万年历闹钟Proteus仿真单片机毕业课程电子设计
C语言Lcd1602万年历闹钟Proteus仿真单片机设计
AT89C51+Lcd1602+DS1302+独立按键+蜂鸣器
Lcd1602万年历闹钟。
时间信息来自DS1302,显示采用
Lcd1602,蜂鸣器提供闹音和按键提示音。
液晶上面显示年月日时分秒星期以及闹钟时间。
有时间调节和闹钟调节,可以调节年月日时分秒星期信息以及闹钟时间。
具体介绍如下。
1.做好的仿真图,如下图所示。
2.启动仿真后,先在液晶屏显示系统信息,然后在第二屏显示需要的万年历闹钟信息。
如下图所示!
3.通过单片机右侧的三个按键,即可设置闹钟。
如下图所示。
4.通过单片机左侧的四个按键,来设置年月日时分秒星期的值。
设置时,参数闪烁,同时会有按键提示音。
5.本设计默认套餐1,具体套餐详情请看下面的发货清单。
如需要其它套餐,请联系客服询问。
详情请:点击此处。
51单片机c语言编写的1602液晶显示闹钟
#include<reg52.h>#define uchar unsigned char#define uint unsigned intuchar code table[]=" 2012-08-17 MON"; //设定开始显示的时间uchar code table1[]=" 12:30:00";uchar code table2[7][3]= {{"MON"},{"TUE"},{"WED"},{"THU"},{"FRI"},{"SAT"},{"SUN"}};//定义二维字符数组sbit wr=P3^6; // 1602液晶的读/写端sbit dula=P2^6; // 数码管段选sbit wela=P2^7; // 数码管位选sbit lcden=P3^4; // 1602液晶使能端sbit lcdrs=P3^5; // 1602液晶命令/数据端sbit key1=P3^0; // 声明s4按键sbit key2=P3^1; // 声明s8按键sbit key3=P3^2; // 声明s12按键sbit key4=P3^3; // 声明s16按键sbit beep=P2^3; // 声明蜂鸣器sbit rd=P3^7; // 声明4个按键的公共端uchar num1,shi=12,fen=30,miao,yue=8,ri=17,shi1,fen1,miao1,keynum1,week; //定义时分秒变量uint nian=2012; //定义年变量void delayms(uint x){uint i,j;for(i=x;i>0;i--) //定义带参数延时函数for(j=110;j>0;j--);}void write_com(uchar com) //1602液晶写指令函数{ wr=0;lcdrs=0;P0=com;delayms(1);lcden=1;delayms(1);lcden=0;}void write_date(uchar date) //1602液晶写数据函数{ wr=0;lcdrs=1;P0=date;delayms(1);lcden=1;delayms(1);lcden=0;}void write_addate1(uchar add,uint date) //定义显示年的函数{ uint qian;uchar bai,shi,ge;qian=date/1000;bai=date%1000/100;shi=date%1000%100/10;ge=date%10;write_com(add+0x80);write_date(0x30+qian);write_date(0x30+bai);write_date(0x30+shi);write_date(0x30+ge);}void write_addate2(uchar add,uchar date) //定义显示月、日、时、分、秒函数{uchar shi,ge;shi=date/10;ge=date%10;write_com(add+0x80);write_date(0x30+shi);write_date(0x30+ge);}void write_rq(uchar i) //定义显示星期的函数{ uchar x;for(x=0;x<3;x++){ write_date(table2[i][x]);delayms(1);}}void init () //定义初始化函数{dula=0; // 关闭数码管段、位选端wela=0;TMOD=0x01; // 定时器0工作方式为16位TH0=(65536-45872)/256; // 装初值TL0=(65536-45872)%256;EA=1; // 开总中断ET0=1; // 开定时器0中断write_com(0x38); // 设置16*2显示,5*7点阵,8位数据口write_com(0x06); // 写一个字符后地址指针加1write_com(0x0c); // 设置开显示,不显示光标write_com(0x01); // 显示清0,数据清0write_com(0x80); // 使指针指向第1行第1列}void keyscan() // 定义按键函数{uchar keynum;rd=0; //4个按键公共端为低电平if(key1==0) //s4按键被按下{ delayms(3); //去抖延时if(key1==0) //确认s4按键被按下,进入调时间模式{keynum++;while(!key1); //松手检测}if(keynum==1) //s4按下一次{ TR0=0; //关闭定时器0write_com(0x81); //指针指向第1行2列write_com(0x0f); //开启光标显示,光标闪烁}if(keynum==2){write_com(0x86); //光标跳到月份}if(keynum==3){write_com(0x89); //光标跳到日}if(keynum==4){write_com(0x8c); //光标跳到星期}if(keynum==5){write_com(0xc4); //光标跳到时}if(keynum==6){write_com(0xc7); //光标跳到分}if(keynum==7){write_com(0xca); //光标跳到秒}if(keynum==8){ keynum=0; //退出调时间模式TR0=1; //开启定时器0write_com(0x0c); //关闭光标显示}}if(keynum) //当进入调时间模式时{if(key2==0) //s8按键按下{delayms(3); //去抖延时if(key2==0){if(keynum==1){nian++; //s8每按下一次年份加1if(nian==10000) // 加满清0nian=0;write_addate1(1,nian); // 显示年份write_com(0x81); //写完数据指针指向年份原来位置}if(keynum==2){yue++; //s8每按下一次月份加1if(yue==13)yue=0; //加满清0write_addate2(6,yue); //显示月份write_com(0x86); //写完数据指针指向月份原来位置}if(keynum==3){ ri++;if(yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12) //1,3,5,7,8,10,12月有31天if(ri==32)//加满还原ri=1;if(yue==4||yue==6||yue==9||yue==11) //4,6,9,11月有30天if(ri==31)ri=1;if(yue==2&&((nian%4==0&&nian%100!=0)||nian%400==0)) //闰年2月有30天if(ri==30)ri=1;if(yue==2&&(nian%4!=0)||(nian%100==0&&nian%400!=0)) //非闰年2月有31天if(ri==29)ri=1;write_addate2(9,ri); //显示日write_com(0x89); //写完数据指针指向日原来位置}if(keynum==4){week++;//s8每按下一次星期加1if(week==7)//加满还原week=0;write_rq(week); //显示星期write_com(0x8c); //写完数据指针指向星期原来位置}if(keynum==5){shi++;//s8每按下一次时加1if(shi==24)shi=0;//加满还原write_addate2(0x44,shi); //显示时write_com(0xc4); //写完数据指针指向时原来位置}if(keynum==6){fen++;//s8每按下一次分加1if(fen==60)fen=0;//加满还原write_addate2(0x47,fen); //显示分write_com(0xc7);//写完数据指针指向分原来位置}if(keynum==7){miao++;//s8每按下一次秒加1if(miao==60)miao=0;//加满还原write_addate2(0x4a,miao);//显示秒write_com(0xca);//写完数据指针指向秒原来位置}while(!key2); //松手检测}}if(key3==0){delayms(3);if(key3==0){ //s12按下时减1if(keynum==1){nian--;if(nian==-1)nian=9999;write_addate1(1,nian);write_com(0x81);}if(keynum==2){ yue--;if(yue==-1)yue=12;write_addate2(6,yue);write_com(0x86);}if(keynum==3){ri--;if(ri==0){if(yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12)ri=31;if(yue==4||yue==6||yue==9||yue==11)ri=30;if(yue==2&&((nian%4==0&&nian%100!=0)||nian%400==0))ri=29;if(yue==2&&(nian%4!=0)||(nian%100==0&&nian%400!=0))ri=28;}write_addate2(9,ri);write_com(0x89);}if(keynum==4){week--;if(week==-1)week=6;write_rq(week);write_com(0x8c);}if(keynum==5){shi--;if(shi==-1)shi=23;write_addate2(0x44,shi);write_com(0xc4);}if(keynum==6){fen--;if(fen==-1)fen=59;write_addate2(0x47,fen);write_com(0xc7);}if(keynum==7){miao--;if(miao==-1)miao=59;write_addate2(0x4a,miao);write_com(0xca);}while(!key3); //松手检测}}}if(key4==0) //s16被按下进入调闹钟模式{ delayms(3);if(key4==0){keynum1++;while(!key4);}if(keynum1==1){ write_com(0x01); //清屏,指针清0write_com(0xc6); //在时分之间显示“:”write_date(':');write_com(0xc9); //在分秒之间显示“:”write_date(':');write_com(0x0f); //开启光标write_com(0xc4); //光标指向时}if(keynum1==2){write_com(0xc7);//光标指向分}if(keynum1==3){write_com(0xca); //光标指向秒}if(keynum1==4){ keynum1=0;write_com(0x0c); //关闭光标}}if(keynum1){if(key2==0) //s8按下加1{delayms(3);if(key2==0){if(keynum1==1){shi1++;if(shi1==24)shi1=0;write_addate2(0x44,shi1);write_com(0xc4);}if(keynum1==2){fen1++;if(fen1==60)fen1=0;write_addate2(0x47,fen1);write_com(0xc7);}if(keynum1==3){miao1++;if(miao1==60)miao1=0;write_addate2(0x4a,miao1);write_com(0xca);}while(!key2);}}if(key3==0) //s12每按一次减1{delayms(3);if(key3==0){if(keynum1==1){shi1--;if(shi1==-1)shi1=23;write_addate2(0x44,shi1);write_com(0xc4);}if(keynum1==2){fen1--;if(fen1==-1)fen1=59;write_addate2(0x47,fen1);write_com(0xc7);}if(keynum1==3){miao1--;if(miao1==-1)miao1=59;write_addate2(0x4a,miao1);write_com(0xca);}while(!key3);//松手检测}}}}void main(){ uchar num;init();for(num=0;num<15;num++){ write_date(table[num]);delayms(5);} //显示初始时间write_com(0xc0);for(num=0;num<12;num++){ write_date(table1[num]);delayms(5);}TR0=1; //开启定时器0while(1){ if(shi==shi1&&fen==fen1&&miao==miao1) //闹钟到了蜂鸣器响beep=0;keyscan(); //扫描键盘}}void time() interrupt 1 //中断函数{TH0=(65536-45872)/256;TL0=(65536-45872)%256; //进入中断装初值num1++;if(num1==20) //一秒到了{ num1=0; //清0miao++;if(miao==60) //一分到了{ miao=0; fen++; }if(!keynum1) write_addate2(0x4a,miao); //当调闹钟模式按下时不显示当前时间if(fen==60){ fen=0;shi++;}if(!keynum1) write_addate2(0x47,fen); //当调闹钟模式按下时不显示当前时间if(shi==24){shi=0;ri++;week++;}if(!keynum1) write_addate2(0x44,shi); //当调闹钟模式按下时不显示当前时间if(yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12)if(ri==32){ ri=1; y ue++; }if(yue==4||yue==6||yue==9||yue==11)if(ri==31){ ri=1; yue++; }if(yue==2&&((nian%4==0&&nian%100!=0)||nian%400==0))if(ri==30){ ri=1; yue++; }if(yue==2&&(nian%4!=0)||(nian%100==0&&nian%400!=0))if(ri==29){ ri=1; yue++; }if(!keynum1) write_addate2(9,ri);//当调闹钟模式按下时不显示当前时间if(week==7)week=0;if(!keynum1)//当调闹钟模式按下时不显示当前时间{ write_com(0x8c);write_rq(week);}if(yue==13){ yue=0;nian++;}if(!keynum1)//当调闹钟模式按下时不显示当前时间{write_addate2(6,yue);write_com(0x88);write_date('-');}if(nian==10000)nian=0;if(!keynum1){ write_addate1(1,nian);//当调闹钟模式按下时不显示当前时间write_com(0x85);write_date('-');}}}。
基于c51功能最全的电子钟程序(lcd1602)
功能最全的电子钟【单片机】c51数字时钟(带年月日显示)摘要:本设计以单片机为核心,lcd1602显示。
采用独立键盘输入能任意修改当前时间日期和设定闹钟时间。
具有显示年月日(区分闰年和二月),闹钟报警和整点报时功能主程序:/********************************************************************************************************************************************************************************* ****************************************** lcd1602电子钟********************************************************************************************************************************** *************************************************************************************************** ********************/# include <reg52.h># include "lcd16024.h"sbit key1 = P2^0; //调整sbit key2 = P2^1; //加1sbit key3 = P2^2; //减1sbit speaker = P2^3; //蜂鸣器sbit key4 = P2^4; //闹钟设计bit cal_year = 1; //进入判断闰年标志位bit leap_year; //闰年标志位bit calculate = 0; //日加一标记bit run = 0; //闹钟标志bit beep = 0; //整点报时标志//uint8 num = 0; //调整是给的脉冲uint8 code str1[] = "D: ";uint8 code str2[] = "T: ";uint8 code str3[] = "Wek";uint8 daystr[]="2013-07-29 "; //年月日格式uint8 timestr[]="21:30:59 N"; //时分秒格式uint8 daystr1[]="2013-07-29 "; //闹钟年月日格式uint8 timestr1[]="21:30:59 N"; //闹钟时分秒格式uint8 numweek = 0; //星期加1标记char week = 1; //星期char sec = 53; //秒char min = 50; //分char hour = 23; //时uint8 day = 30; // 日uint8 month = 9; //月uint16 year = 2013; //年char week1 = 1; //闹钟星期char sec1 = 58; //闹钟秒char min1 = 50; //闹钟分char hour1 = 23; //闹钟时uint8 day1 = 30; //闹钟日uint8 month1 = 9; //闹钟月uint16 year1 = 2013; //闹钟年uint8 WeekData1; //闹钟星期标记uint8 number = 0; //定时uint8 WeekData; //星期标记uint8 speaker_num; //整点报时次数uint8 scan_key(void); //函数声名/****************************************************************************** ***************************** 更新LCD时间分离读取******************************************************************************************************************* *******/void TimeChange(){//时分秒timestr[7] = sec%10+'0';timestr[6] = sec/10+'0';timestr[4] = min%10+'0';timestr[3] = min/10+'0';timestr[1] = hour%10+'0';timestr[0] = hour/10+'0';//年月日daystr[9] = day%10+'0';daystr[8] = day/10+'0';daystr[6] = month%10+'0';daystr[5] = month/10+'0';daystr[3] = year%10+'0';daystr[2] = year/10%10+'0';daystr[1] = year/100%10+'0';daystr[0] = year/1000+'0';//星期WeekData = week+'0';}/****************************************************************************** ***************************** 闹钟更新LCD时间分离读取******************************************************************************************************************* *******/void TimeChange1(){//时分秒timestr1[7] = sec1%10+'0';timestr1[6] = sec1/10+'0';timestr1[4] = min1%10+'0';timestr1[3] = min1/10+'0';timestr1[1] = hour1%10+'0';timestr1[0] = hour1/10+'0';//年月日daystr1[9] = day1%10+'0';daystr1[8] = day1/10+'0';daystr1[6] = month1%10+'0';daystr1[5] = month1/10+'0';daystr1[3] = year1%10+'0';daystr1[2] = year1/10%10+'0';daystr1[1] = year1/100%10+'0';daystr1[0] = year1/1000+'0';//星期WeekData1 = week1+'0';}/****************************************************************************** ***************************** 初始化系统定时器0 ******************************************************************************************************************* *******/void systimer0_init(void){TMOD |=0x01;//设置为1时用或(|)TMOD &=0xfd;//设置为0时用与(&)TH0 = 0xDC; // 定时10msTL0 = 0x00;EA = 1;ET0=1;TR0=1;EX0 = 1;}/****************************************************************************** ***************************** 闹钟时间设置*************************************************************************************************************** *******/void naozhong(){uint8 number = 1;uint8 a = 0;uint8 b = 0;if(0 == key4){Delay1Ms(5);if(0 == key4){a = 1;LCD_write_command(0xc0+9);LCD_write_command(0x0f);}while(!key4);}while(a){if(0 == key4){Delay1Ms(5);if(0 == key4){a = 0;run = ~run;while(!key4);}}if(run){timestr[9] = 'Y';}else{timestr[9] = 'N';}if(0 == key1){Delay1Ms(5);if(0 == key1){b = 1;}while(!key1);}while(b){if(0 == key1){Delay1Ms(5);if(0 == key1){number++;if(4 == number)b = 0;}while(!key1);if(number == 1){LCD_write_command(0xc0+9);LCD_write_command(0x0f);}if(number == 2){LCD_write_command(0xc0+6);LCD_write_command(0x0f);}if(number == 3){LCD_write_command(0xc0+3);LCD_write_command(0x0f);}}}switch(number){case 1:if(0 == key2) //闹钟秒加1的设置{Delay1Ms(5);if(0 == key2){sec1++;if(60 == sec1){sec1 = 0;}while(!key2);timestr1[7] = sec1%10+'0';timestr1[6] = sec1/10+'0';LCD_write_char(8,1,timestr1[6]);LCD_write_char(9,1,timestr1[7]);LCD_write_command(0xc0+9);}}if(0 == key3) //闹钟秒减1的设置Delay1Ms(5);if(0 == key3){sec1--;if(sec1 < 0){sec1 = 59;}while(!key3);timestr1[7] = sec1%10+'0';timestr1[6] = sec1/10+'0';LCD_write_char(8,1,timestr1[6]);LCD_write_char(9,1,timestr1[7]);LCD_write_command(0xc0+9);}}break;case 2:if(0 == key2) //闹钟分加1的设置{Delay1Ms(5);if(0 == key2){min1++;if(60 == min1){min1 = 0;}while(!key2);timestr1[4] = min1%10+'0';timestr1[3] = min1/10+'0';;LCD_write_char(5,1,timestr1[3]);LCD_write_char(6,1,timestr1[4]);LCD_write_command(0xc0+6);}}if(0 == key3) //闹钟分减1的设置{Delay1Ms(5);if(0 == key3){min1--;if(min1 < 0){min1 = 59;}while(!key3);timestr1[4] = min1%10+'0';timestr1[3] = min1/10+'0';;LCD_write_char(5,1,timestr1[3]);LCD_write_char(6,1,timestr1[4]);LCD_write_command(0xc0+6);}}break;case 3:if(0 == key2) //闹钟时加1的设置{Delay1Ms(5);if(0 == key2){hour1++;if(24 == hour1){hour1 = 0;}while(!key2);timestr1[1] = hour1%10+'0';timestr1[0] = hour1/10+'0';LCD_write_char(2,1,timestr1[0]);LCD_write_char(3,1,timestr1[1]);LCD_write_command(0xc0+3);}}if(0 == key3) //闹钟时减1的设置{Delay1Ms(5);if(0 == key3){hour1--;if(hour1 < 0){hour1 = 23;}while(!key3);timestr1[1] = hour1%10+'0';timestr1[0] = hour1/10+'0';LCD_write_char(2,1,timestr1[0]);LCD_write_char(3,1,timestr1[1]);LCD_write_command(0xc0+3);}}break;case 4:b = 0;LCD_write_command(0x0c);break;}}}LCD_write_command(0x0c);while(!key4);}/****************************************************************************** ***************************** 判断按键进入时间调整*************************************************************************************************************** *******/uint8 scan_key(void){uint8 number = 1;uint8 a = 0;if(0 == key1){Delay1Ms(5);if(0 == key1){while(!key1);a = 1;LCD_write_command(0xc0+9);LCD_write_command(0x0f);}}while(a){if(0 == key1){Delay1Ms(5);if(0 == key1){number++;while(!key1);TR0 = 0;if(number == 2){LCD_write_command(0xc0+6);LCD_write_command(0x0f);}if(number == 3){LCD_write_command(0xc0+3);LCD_write_command(0x0f);}if(number == 4){LCD_write_command(0x80+11);LCD_write_command(0x0f);}if(number == 5){LCD_write_command(0x80+8);LCD_write_command(0x0f);}if(number == 6){LCD_write_command(0x80+5);LCD_write_command(0x0f);}if(number == 7){LCD_write_command(0xc0+14);LCD_write_command(0x0f);}if(8 == number){LCD_write_command(0x0c);a = 0;number = 0;}}}switch(number){case 1:if(0 == key2) //秒加1的设置{Delay1Ms(5);if(0 == key2){sec++;if(60 == sec){sec = 0;}timestr[7] = sec%10+'0';timestr[6] = sec/10+'0';LCD_write_char(8,1,timestr[6]);LCD_write_char(9,1,timestr[7]);LCD_write_command(0xc0+9);while(!key2);}}if(0 == key3) //秒减1的设置{Delay1Ms(5);if(0 == key3){sec--;if(sec < 0){sec = 59;}timestr[7] = sec%10+'0';timestr[6] = sec/10+'0';LCD_write_char(8,1,timestr[6]);LCD_write_char(9,1,timestr[7]);LCD_write_command(0xc0+9);while(!key3);}}break;case 2:if(0 == key2) //分加1的设置{Delay1Ms(5);if(0 == key2){min++;if(60 == min){min = 0;}timestr[4] = min%10+'0';timestr[3] = min/10+'0';;LCD_write_char(5,1,timestr[3]);LCD_write_char(6,1,timestr[4]);LCD_write_command(0xc0+6);while(!key2);}}if(0 == key3) //分减1的设置{Delay1Ms(5);if(0 == key3){min--;if(min < 0){min = 59;}timestr[4] = min%10+'0';timestr[3] = min/10+'0';LCD_write_char(5,1,timestr[3]);LCD_write_char(6,1,timestr[4]);LCD_write_command(0xc0+6);while(!key3);}}break;case 3:if(0 == key2) //时加1的设置{Delay1Ms(5);if(0 == key2){hour++;while(!key2);if(24 == hour){hour = 0;}timestr[1] = hour%10+'0';timestr[0] = hour/10+'0';LCD_write_char(2,1,timestr[0]);LCD_write_char(3,1,timestr[1]);LCD_write_command(0xc0+3);}}if(0 == key3) //时减1的设置{Delay1Ms(5);if(0 == key3){while(!key3);hour--;if(hour < 0){hour = 23;}timestr[1] = hour%10+'0';timestr[0] = hour/10+'0';LCD_write_char(2,1,timestr[0]);LCD_write_char(3,1,timestr[1]);LCD_write_command(0xc0+3);}}break;case 4:if(0 == key2) //日加1的设置{Delay1Ms(5);if(0 == key2){while(!key2);calculate = 1;if(calculate == 1){if(month==1|month==3|month==5|month==7|month==8|month==10|month==12){day++;if(day > 31){day=1;}}if(month==4|month==6|month==9|month==11){day++;if(day > 30){day=1;}}if(month == 2){cal_year = 1;while(cal_year == 1){leap_year = ((year % 4 == 0 && year % 100 != 0)||(year % 400 == 0));cal_year = 0;}if(leap_year==1){day++;if(day > 30){day=1;}}else{day++;if(day > 29){day=1;}}}calculate = 0;}daystr[9] = day%10+'0';daystr[8] = day/10+'0';LCD_write_char(10,0,daystr[8]);LCD_write_char(11,0,daystr[9]);LCD_write_command(0x80+11);}}if(0 == key3) //日减1的设置{Delay1Ms(5);if(0 == key3){while(!key3);calculate = 1;if(calculate == 1){if(month==1|month==3|month==5|month==7|month==8|month==10|month==12){day--;if(day == 0){day=31;}}if(month==4|month==6|month==9|month==11){day--;if(day == 0){day=30;}}if(month == 2){cal_year = 1;while(cal_year == 1){leap_year = ((year % 4 == 0 && year % 100 != 0)||(year % 400 == 0));cal_year = 0;}if(leap_year==1){day--;if(day == 0){day=30;}}else{day--;if(day == 0){day=29;}}}calculate = 0;}daystr[9] = day%10+'0';daystr[8] = day/10+'0';LCD_write_char(10,0,daystr[8]);LCD_write_char(11,0,daystr[9]);LCD_write_command(0x80+11);}}break;case 5:if(0 == key2) //月加1的设置{Delay1Ms(5);if(0 == key2){while(!key2);month++;if(13 == month){month = 1;}daystr[6] = month%10+'0';daystr[5] = month/10+'0';LCD_write_char(7,0,daystr[5]);LCD_write_char(8,0,daystr[6]);LCD_write_command(0x80+8);}}if(0 == key3) //月减1的设置{Delay1Ms(5);if(0 == key3){while(!key3);month--;if(month == 0){month = 12;}daystr[6] = month%10+'0';daystr[5] = month/10+'0';LCD_write_char(7,0,daystr[5]);LCD_write_char(8,0,daystr[6]);LCD_write_command(0x80+8);}}break;case 6:if(0 == key2) //年加1的设置{Delay1Ms(5);if(0 == key2){while(!key2);year++;}daystr[3] = year%10+'0';daystr[2] = year/10%10+'0';daystr[1] = year/100%10+'0';daystr[0] = year/1000+'0';LCD_write_char(2,0,daystr[0]);LCD_write_char(3,0,daystr[1]);LCD_write_char(4,0,daystr[2]);LCD_write_char(5,0,daystr[3]);LCD_write_command(0x80+5);}if (0 == key3) //年减1的设置{Delay1Ms(5);if(0 == key3){while(!key3);year--;if(year == 0){year = 2020;}daystr[3] = year%10+'0';daystr[2] = year/10%10+'0';daystr[1] = year/100%10+'0';daystr[0] = year/1000+'0';LCD_write_char(2,0,daystr[0]);LCD_write_char(3,0,daystr[1]);LCD_write_char(4,0,daystr[2]);LCD_write_char(5,0,daystr[3]);LCD_write_command(0x80+5);}}break;case 7:if(0 == key2) //星期加1的设置{Delay1Ms(5);if(0 == key2){while(!key2);week++;if(7 == week){week = 0;}LCD_write_char(14,1,week+'0');LCD_write_command(0xc0+14);}}if (0 == key3) //星期减1的设置{Delay1Ms(5);if(0 == key3){while(!key3);week--;if(week < 0){week = 6;}LCD_write_char(14,1,week+'0');LCD_write_command(0xc0+14);}}break;case 8:TR0 = 1;break;}}}/****************************************************************************** ***************************** 主函数******************************************************************************************************************* *******/void main(void){systimer0_init();LCD_init();LCD_write_str(0,0,str1);LCD_write_str(0,1,str2);LCD_write_str(13,0,str3);speaker = 0;while (1){TimeChange();scan_key();naozhong();LCD_write_str(2,0,daystr);LCD_write_str(2,1,timestr);LCD_write_char(14,1,WeekData);if(1 == run){if(sec==sec1 & month==month1 & hour==hour){speaker_num =30;beep = 1;}}else{speaker_num =0;beep = 0;}}}/****************************************************************************** ***************************** 定时中断0 ******************************************************************************************************************* *******/void time_0() interrupt 1{TH0 = 0xDC; // 定时10msTL0 = 0x00;number++;if(number ==100){sec++;if(beep){speaker=!speaker;speaker_num--;if(speaker_num == 0){beep=0;speaker = 0;}}if(sec == 60){sec = 0;min++;if(min == 60){min = 0;hour++; //小时加1speaker_num = hour%12; //蜂鸣器响的次数beep = 1;if(hour == 24){hour = 0;calculate = 1;if(calculate == 1) //判断这个月有多少天{if(month==1|month==3|month==5|month==7|month==8|month==10|month==12){day++;if(month==7|month==12){week++;if(7 == week){week = 0;}}else{if(day <= 31){week++;if(7 == week){week = 0;}}}if(day > 31){if(month==7|month==12){day = 1;}else{day=0;}month++;if(month > 12){month=1;year++;cal_year=1;}}}if(month==4|month==6|month==9|month==11) {day++;week++;if(7 == week){week = 0;}if(day > 30){day=1;month++;if(month > 12){month=1;year++;cal_year=1;}}}if(month == 2){while(cal_year == 1){leap_year = ((year % 4 == 0 && year % 100 != 0)||(year % 400 == 0));cal_year = 0;}if(leap_year==1){day++;if(day <= 30){week++;if(7 == week){week = 0;}}if(day > 30){day=1;month++;if(month > 12){month=1;year++;cal_year=1;}}}else{day++;week++;if(7 == week){week = 0;}if(day > 29){day=1;month++;if(month > 12){month=1;year++;cal_year=1;}}}}}calculate=0;}}}}}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Lcd1602.c子程序:////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /****************************************************************************** ***************************** lcd1602低层函数********************************************************************************************************************* *******/# include <reg52.h># include <intrins.h># include "lcd16024.h"# define LCD_DATA P0 //LCD1602的数据口定义sbit LCD_RS = P0^0; //LCD1602控制线的定义,4位控制方式sbit LCD_RW = P0^1;sbit LCD_EN = P0^2;/****************************************************************************** ***************************** 延时1MS********************************************************************************************************************* *******/void Delay1Us(uint16 n){for(;n>0;n--){_nop_();}}/****************************************************************************** ***************************** 延时1MS********************************************************************************************************************* *******/void Delay1Ms(uint16 n){while(n--){Delay1Us(1000);}}/****************************************************************************** ***************************** 延时1MS********************************************************************************************************************* *******/void LCD_en_write(void){LCD_EN=0;LCD_EN=1;Delay1Us(1);LCD_EN=0;}/****************************************************************************** ************************ LCD写一个字节命令函数************************************************************************************************************ *******/void LCD_write_command(uint8 command){Delay1Us(16);LCD_RS=0;LCD_RW=0;LCD_DATA&=0x0f;LCD_DATA|=command&0xf0;LCD_en_write();command=command<<4;LCD_DATA&=0x0f;LCD_DATA|=command&0xf0;LCD_en_write();}/****************************************************************************** ********************** LCD写一个字节数据函数*************************************************************************************************************** *******/void LCD_write_data(uint8 Data){Delay1Us(16);LCD_RS=1;LCD_RW=0;LCD_DATA&=0x0f;LCD_DATA|=Data&0xf0;LCD_en_write();Data=Data<<4;LCD_DATA&=0x0f;LCD_DATA|=Data&0xf0;LCD_en_write();}/****************************************************************************** ***************************** LCD1602光标定位函数************************************************ x--列0~15;y--行0~1********************************************************************************************************* *******/void LCD_set_xy(uint8 x,uint8 y){uint8 address;if(y==0)address=0x80+x;else address=0xc0+x;LCD_write_command(address);}/***************************************************************************************************** LCD1602 初始化函数,四位显示方式******************************************************************************************************* *******/void LCD_init(){LCD_write_command(0x28);// Delay1Us(40);LCD_write_command(0x28);LCD_write_command(0x0c);LCD_write_command(0x01);LCD_write_command(0x06);Delay1Ms(2);}/****************************************************************************** ***************************** LCD写字符串函数******************************************************* x--列0~15;y--行0~1******************************************************* s指向字符串数组**************************************************************************************************************** *******/void LCD_write_str(uint8 x,uint8 y,uint8 *s){LCD_set_xy(x,y);while(*s){LCD_write_data(*s);s++;}}/****************************************************************************** ***************************** LCD写一个字符函数******************************************************* x--列0~15;y--行0~1******************************************************* d--字符的ASCII码**************************************************************************************************************** *******/void LCD_write_char(uint8 x,uint8 y,uint8 d){LCD_set_xy(x,y);LCD_write_data(d);}/*////////////////////////////////////////////////////////////////// 等待繁忙标志/////////////////////////////////////////////////////////////////void LCD_wait(void){P0 = 0xFF;do{LCD_RS = 0;LCD_RW = 1;LCD_EN = 0;LCD_EN = 1;}while (BUSY == 1);LCD_EN = 0;}*//****************************************************************************** ***************************** LCD1602左移********************************************************************************************************************* *******void LCD_youyi(uint8 y,uint8 *s){LCD_write_str(17,y,s);for(a=0;a<16;a++){LCD_write_command(0x1c); //左移LCD_write_command(0x1c); 为右移Delay1Ms(6);}}*///LCD_write_command(0x0d);//光标闪烁//LCD_write_command(0x0e);//光标显示不闪烁//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Lcd1602.h头文件////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #ifndef _LCD16024_H_#define _LCD16024_H_typedef unsigned char uint8;typedef unsigned int uint16;typedef unsigned long uint32;void Delay1Us(uint16 n);void Delay1Ms(uint16 n);void LCD_write_data(uint8 dat);void LCD_write_command(uint8 com); //BuysC为0时忽略忙检测void LCD_set_xy(uint8 x,uint8 y);void LCD_en_write(void);void LCD_write_char(uint8 x, uint8 y, uint8 Data1);void LCD_write_str(uint8 x, uint8 y,uint8 *s);void LCD_init();//void LCD_wait(void);//void LCD_youyi(uint8 y,uint8 *s);#endif。
lcd1602液晶显示电子时钟
if(s1num==4) //如果此数为4,则执行内程序
{
write_com(0x80+14); //设置光标在周的位置
}
if(s1num==5) //如果此数为5,则执行内程序
{
write_com(0x80+9); //设置光标在日期位置
if(y==0)
}
if(s1num!=0) //如果此数不为0,则进入调整加、减键
{
if(s2==0) //确认加键是否被按下
{
delay(5); //消抖
if(s2==0) //再一次确认是否真的有键按下
write_date(0x30+ge); //个位数据
}
void keyscan() //键扫描
{
if(s1==0) //如果S1键按下
{
delay(5); //消抖
}
if(s1num==6) //如果此数为6,则执行内程序
{
write_com(0x80+6); //设置光标在月位置
}
if(s1num==7) //如果此数为7,则执行内程序
{
write_com(0x80+3); //设置光标在年位置
write_date(0x30+ge); //个位数据
}
void write_r(uchar add,uchar date)
{
uchar ge; //设定个位
ge=date;
{
RW=0;
rs=1;
lcden=0;
P0=date;
delay(5);
基于stc51单片机的LCD1602显示时间的电子万年历(显示
基于stc51单片机的LCD1602显示时间的电子万年历(显示1.1 Keil uVision4的简要介绍2020年2月公布Keil μVision4,Keil μVision4引入灵活的窗口治理系统,使开发人员能够使用多台监视器,并提供了视觉上的表面对窗口位置的完全操纵的任何地点。
新的用户界面能够更好地利用屏幕空间和更有效地组织多个窗口,提供一个整洁,高效的环境来开发应用程序。
新版本支持更多最新的ARM芯片,还添加了一些其他新功能。
2020年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中。
51单片机控制基于1602液晶显示 电子时钟【带闹铃和整点报时】
write_date(week6[num]);
delay1();
}
};
break;
}
}
void display() //显示时间子程序
{
write_week(week);
write_ymd(3,year);
write_ymd(6,months);
write_ymd(9,day);
write_sfm(0,shi);
write_sfm(3,fen);
write_sfm(6,miao);
}
void display_1() //显示闹钟子程序
{
write_week(week_1);
write_ymd(3,year1);
write_ymd(6,months1);
write_ymd(9,day1);
write_sfm(0,shi1);
write_com(0x80+add);
write_date(0x30+sh);
write_date(0x30+ge);
}
void write_week(uchar add) //周几显示
{
switch(add)
{
case 0:{
write_com(0x80+12);//设置数据起始地址
for(num=0;num<3;num++)
{
write_date(week3[num]);
delay1();
}
};
break;
case 4:{
write_com(0x80+12);//设置数据起始地址
for(num=0;num<3;num++)
LCD1602+液晶显示数字电子钟+报告书
LCD1602中文资料介绍用LCD1602 液晶显示数字电子钟,整点蜂鸣器提醒,时间可自行调整。
同时用一个功能键切换显示日期(也可更改调整)和秒表。
本设计有五个按键,第一个是功能键,切换三个功能,分别是日期、时间和秒表;第二个是调整键,按一下屏幕不会变化,只有当按调整加减键时,屏幕就会变化。
例如:一上电显示的是年月日,然后想调整,按一下调整键,屏幕无变化,按调整加减键,屏幕就会变化,date变成tzy,表示正在调整年。
年调整好后,再按一下第二个调整键,屏幕无变化,按调整加减键,屏幕就会变化,tzy变成tzm,表示正在调整月。
其他类似。
第三四个键是加减键;第五个是调整好后的确认键和秒表的确认键。
操作说明:比如要调整日期,先按一下调整p2.1键(左边数第二个键),然后按加1键p2.2或减1键p2.3,第一次是让调整年,年调整后再按调整p2.1键,这次是调整月。
调整后再按调整p2.1键,最后是调整日。
调整好后按确认键p2.4,这样年月日就设置好了。
年月日设置好后按功能切换键p2.0它会回到时间设置上,调整方法和调整年月日类似。
电路原理图:目录扉页答辩许可证毕业设计(论文)任务书中文摘要英文摘要目录文献综述一.选题的目的及意义二.研究领域概况三.文献分析四.研究思路及方案五.进度计划六.参考文献专题论文正文1.引言2.核心芯片简介2.1AT89S51的结构和特点2.1.1芯片引脚及结构特点2.1.2主要功能特性2.1.3AT89S51的新功能2.1.4单片机内部结构及说明2.2 1602液晶显示器的结构及工作原理2.2.1液晶显示器的引脚功能及内部结构图2.2.2CGROM和CGRAM中字符代码与图形对应关系2.2.3液晶模块内部控制器指令说明3.方案设计及论证4.硬件设计4.1.1芯片接口与显示设计4.2.1单片机复位电路设计4.2.2单片机晶振电路设计4.2.3单片机报时电路设计4.2.4单片机下载程序电路设计4.2.5按键功能描述及调试过程5.结论致谢参考文献实习报告外文中文论文缩写电路图§§§基于LCD1602的数字电子钟§§§购物从这里开始:/CD.asp此设计费用为:基本费用155+20(LCD1602)+1(蜂鸣器)+1(电位器)+3(6个12*12*6按键)=180元. 用LCD1602 液晶显示数字电子钟,整点蜂鸣器提醒,时间可自行调整。
可调时钟1602显示且附带智能闹钟且附带日期
typedef unsigned int u16;
sbit LCD_RS=P3^5;
sbit LCD_WR=P3^6;
sbit LCD_EN=P3^4;
sbit spk=P1^7;
sbit DRX=P3^0;
while(!adj);//直到按键抬起
}
}
}
void dis_time()
{
u8 i;
while(LCD_BUSY()); //读忙
WRITE_COM(0x80); //设置初始操作地址
while(LCD_BUSY());
{for(i=0;i<5;i++)
beep();
}
}
void adj_scan()
{
if(!adj)
{
delay(10);//消抖
if(!adj)
{
beep();
flag++;
if(flag==1)//第一次按调时
}
void alarm_scan()
{
if(!alarm)
{
delay(10);
if(!alarm)
{
alarm_flag=1;
beep();
TR0=0;
sav_hour=hour;sav_min=min;sav_sec=sec;//暂存设定闹钟前的时间
TR1=1;//用于存储设置时钟过程损耗时长的T2定时器启动
flag++;
if(flag==1)//第一次按调时
单片机LCD1602显示年月日时钟带星期和闹钟
长春工业大学测控技术与仪器专业单片机LCD1602显示年月日时钟带星期和闹钟,可识别闰年下载文档即可完全复制#include <reg52.h>#define uchar unsigned char#define uint unsigned intsbit lcdrs = P0^7; //液晶引脚定义sbit led_cs = P0^6;sbit lcden = P0^5;sbit boom = P3^6;sbit key1 = P3^5;sbit key2 = P3^4;sbit key3 = P3^3;sbit keyE = P3^2;ucharnum,key1num,key2num,count,hour,min,sec,day,mon,year,shi,f en,miao,week;char ye1,ye2;uchar code cg_1602[]={ 0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02,0x0f,0x09,0x0f,0x09,0x0f,0x09,0x11,0x00,0x0f,0x09,0x09,0x0f,0x09,0x09,0x0f,0x00,0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02,};//"年月日"/*延时函数*/void delay(uint xms){uint i,j;for(i=xms;i>0;i--)for(j=114;j>0;j--);}/*1602液晶*/void write_com(uchar com)//写命令{lcdrs=0;lcden=0;P2=com;delay(5);lcden=1;delay(5);lcden=0;}void write_data(uchar date)//写数据{lcdrs=1;lcden=0;P2=date;delay(5);lcden=1;delay(5);lcden=0;}void write_by_xy(uchar x,uchar y)//坐标定位{uchar address;if(y==0)address=0x80+x;//y=0,写第一行elseaddress=0xc0+x;//y=1,写第二行write_com(address);}/*void write_char(uchar x,uchar y,uchar date)//坐标定位显示{write_by_xy(x,y);//先定位write_data(date);//后写数}*/void write_string(uchar x,uchar y,uchar *s)//写字符串{write_by_xy(x,y);//设定显示位置while(*s)//write character{P2=*s;write_data(*s);s++;}}void write_sfm(uchar add,uchar date)//写时分秒函数{uchar hour,ge;hour=date/10;//分解一个2位数的十位和个位ge=date%10;write_com(0x80+add);//设置显示位置write_data(0x30+hour);//送去液晶显示十位write_data(0x30+ge); //送去液晶显示个位}void write_cg()//写入固定汉字和符号{write_com(0x40); //设定CGRAM地址for(num=0;num<24;num++) //将自定义字型码写入CGRAM 中{write_data(cg_1602[num]);}write_com(0xc4);//年{write_data(0);}write_com(0xc7);//月{write_data(1);}write_com(0xca);//日{write_data(2);}write_string(2,0,":");write_string(5,0,":");write_string(0x0a,0,":");write_string(0x0d,0,":");write_string(0x0c,1,"W");write_string(0x0d,1,"K");}void init_1602()//初始化{led_cs=0;hour=23;min=59;sec=55;key1num=0;count=0;day=28;mon =2;ye1=20;ye2=13;year=ye1*100+ye2;boom=0;shi=0;fen=0;m iao=0;week=7;write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x01);write_string(0,1,"2013");write_string(5,1,"02");write_string(8,1,"28");write_sfm(8,shi);write_sfm(0x0b,fen);write_sfm(0x0e,miao);write_sfm(0,hour);write_sfm(3,min);write_sfm(6,sec);write_sfm(0x48,day);write_sfm(0x45,mon);write_sfm(0x40,ye1);write_sfm(0x42,ye2);write_sfm(0x4e,week);write_cg();TMOD=0x01;//设置定时器0工作模式1 TH0=(65536-50000)/256;//定时器装初值TL0=(65536-50000)%256;EA=1; //开总中断ET0=1; //开定时器0中断TR0=1; //启动定时器0}/*键盘扫描函数*/void keyscan()//按键扫描函数{//keyE =0;if(key1==0){delay(5);if(key1==0)//确认功能键被按下{key1num++;//功能键按下次数记录while(!key1);//释放确认if(key1num==1)//第一次被按下时TR0=0; //关闭定时器write_com(0x80+7);//光标定位到秒位置write_com(0x0f); //光标开始闪烁}if(key1num==2)//第二次按下光标闪烁定位到分钟位置{write_com(0x80+4);}if(key1num==3)//第三次按下光标闪烁定位到小时位置{write_com(0x80+1);}if(key1num==4)//第四次按下光标闪烁定位到日位置{write_com(0x80+0x49);}if(key1num==5)//第五次按下光标闪烁定位到月位置{write_com(0x80+0x46);}if(key1num==6)//第六次按下光标闪烁定位到年2位置write_com(0x80+0x43);}if(key1num==7)//第七次按下光标闪烁定位到年1位置{write_com(0x80+0x41);}if(key1num==8)//第八次按下光标闪烁定位到星期位置{write_com(0x80+0x4f);}if(key1num==9)//第九次按下{key1num=0;//记录按键数清零write_com(0x0c);//取消光标闪烁TR0=1; //启动定时器使时钟开始走}}}if(key1num!=0)//只有功能键被按下后,增加和减小键才有效{if(key2==0){delay(5);if(key2==0)//增加键确认被按下{while(!key2);//按键释放if(key1num==1)//若功能键第一次按下{sec++; //则调整秒加1if(sec==60)//若满60后将清零sec=0;write_sfm(6,sec);//每调节一次送液晶显示一下write_com(0x80+7);//显示位置重新回到调节处}if(key1num==2)//若功能键第二次按下{min++;//则调整分钟加1if(min==60)//若满60后将清零min=0;write_sfm(3,min);//每调节一次送液晶显示一下write_com(0x80+4);//显示位置重新回到调节处}if(key1num==3)//若功能键第三次按下{hour++;//则调整小时加1if(hour==24)//若满24后将清零hour=0;write_sfm(0,hour);;//每调节一次送液晶显示一下write_com(0x80+1);//显示位置重新回到调节处}if(key1num==4)//若功能键第四次按下{day++;//则调整日加1if(day>31)//若大于31后将置一day=1;write_sfm(0x48,day);//每调节一次送液晶显示一下write_com(0x80+0x48);//显示位置重新回到调节处}if(key1num==5)//若功能键第五次按下{mon++;//则调整月加1if(mon>12)//若大于12后将置一mon=1;下write_com(0x80+0x45);//显示位置重新回到调节处}if(key1num==6)//若功能键第六次按下{ye2++;//则调整年加1if(ye2==0x0a)//若满99后将清零ye2=0;year=ye1*100+ye2;write_sfm(0x42,ye2);//每调节一次送液晶显示一下write_com(0x80+0x42);//显示位置重新回到调节处}if(key1num==7)//若功能键第七次按下{ye1++;//则调整年加100if(ye1==0x0a)//若满99后将清零ye1=0;year=ye1*100+ye2;下write_com(0x80+0x40);//显示位置重新回到调节处}if(key1num==8)//若功能键第八次按下{week++;//则调整周加一if(week>7)//若大于7后置一week=1;write_sfm(0x4f,week);//每调节一次送液晶显示一下write_com(0x80+0x4f);//显示位置重新回到调节处}}}if(key3==0){delay(5);if(key3==0)//确认减小键被按下{while(!key3);//按键释放if(key1num==1)//若功能键第一次按下{sec--;//则调整秒减1if(sec==-1)//若减到负数则将其重新设置为59 sec=59;write_sfm(6,sec);//每调节一次送液晶显示一下write_com(0x80+7);//显示位置重新回到调节处}if(key1num==2)//若功能键第二次按下{min--;//则调整分钟减1if(min==-1)//若减到负数则将其重新设置为59 min=59;write_sfm(3,min);//每调节一次送液晶显示一下write_com(0x80+4);//显示位置重新回到调节处}if(key1num==3)//若功能键第三次按下{hour--;//则调整小时减1if(hour==-1)//若减到负数则将其重新设置为23 hour=23;write_sfm(0,hour);//每调节一次送液晶显示一下write_com(0x80+1);//显示位置重新回到调节处}if(key1num==4)//若功能键第四次按下{day--;//则调整日减1if(day==0)//若日为零时将置一day=31;write_sfm(0x48,day);//每调节一次送液晶显示一下write_com(0x80+0x49);//显示位置重新回到调节处}if(key1num==5)//若功能键第五次按下{mon--;//则调整月减1if(mon==0)//若月为零将置一mon=12;write_sfm(0x45,mon);//每调节一次送液晶显示一下write_com(0x80+0x45);//显示位置重新回到调节处if(key1num==6)//若功能键第六次按下{ye2--;//则调整年减1if(ye2<0)//若小于零后将设置为99ye2=99;year=ye1*100+ye2;write_sfm(0x42,ye2);//每调节一次送液晶显示一下write_com(0x80+0x42);//显示位置重新回到调节处}if(key1num==7)//若功能键第七次按下{ye1--;//则调整年减100if(ye1<0)//若小于零后将设置为99ye1=99;year=ye1*100+ye2;write_sfm(0x40,ye1);//每调节一次送液晶显示一下write_com(0x80+0x40);//显示位置重新回到调节处if(key1num==8)//若功能键第八次按下{week--;//则调整周减一if(week==0)//若等于0后将置7week=7;write_sfm(0x4f,week);//每调节一次送液晶显示一下write_com(0x80+0x4f);//显示位置重新回到调节处}}}}if(keyE==0){delay(5);if(keyE==0)//确认功能键被按下{key2num++;//功能键按下次数记录while(!keyE);//释放确认if(key2num==1)//第一次被按下时{TR0=0; //关闭定时器write_com(0x80+0x0f);//光标定位到秒位置write_com(0x0f); //光标开始闪烁}if(key2num==2)//第二次按下光标闪烁定位到分钟位置{write_com(0x80+0x0c);}if(key2num==3)//第三次按下光标闪烁定位到小时位置{write_com(0x80+9);}if(key2num==4)//第八次按下{key2num=0;//记录按键数清零write_com(0x0c);//取消光标闪烁TR0=1; //启动定时器使时钟开始走}}}if(key2num!=0)//只有功能键被按下后,增加和减小键才有效{if(key2==0){delay(5);if(key2==0)//增加键确认被按下{while(!key2);//按键释放if(key2num==1)//若功能键第一次按下{miao++; //则调整秒加1if(miao==60)//若满60后将清零miao=0;write_sfm(0x0e,miao);//每调节一次送液晶显示一下write_com(0x80+0x0e);//显示位置重新回到调节处}if(key2num==2)//若功能键第二次按下{fen++;//则调整分钟加1if(fen==60)//若满60后将清零fen=0;write_sfm(0x0b,fen);//每调节一次送液晶显示一下write_com(0x80+0x0b);//显示位置重新回到调节处}if(key2num==3)//若功能键第三次按下{shi++;//则调整小时加1if(shi==24)//若满24后将清零shi=0;write_sfm(8,shi);;//每调节一次送液晶显示一下write_com(0x80+8);//显示位置重新回到调节处}}}if(key3==0){delay(5);if(key3==0)//确认减小键被按下{while(!key3);//按键释放if(key2num==1)//若功能键第一次按下{miao--;//则调整秒减1if(miao==-1)//若减到负数则将其重新设置为59miao=59;write_sfm(0x0e,miao);//每调节一次送液晶显示一下write_com(0x80+0x0e);//显示位置重新回到调节处}if(key2num==2)//若功能键第二次按下{fen--;//则调整分钟减1if(fen==-1)//若减到负数则将其重新设置为59fen=59;write_sfm(0x0b,fen);//每调节一次送液晶显示一下write_com(0x80+0x0b);//显示位置重新回到调节处}if(key2num==3)//若功能键第三次按下{shi--;//则调整小时减1if(shi==-1)//若减到负数则将其重新设置为23shi=23;write_sfm(8,shi);//每调节一次送液晶显示一下write_com(0x80+8);//显示位置重新回到调节处}}}}}/*主函数*/void main(){led_cs=0;init_1602();while(1){keyscan();}}/*中断函数*/void timer0() interrupt 1//定时器0中断服务程序{TH0=(65536-50000)/256;//再次装定时器初值TL0=(65536-50000)%256;count++; //中断次数累加if(count==20) //20次50毫秒为1秒{count=0;sec++;if(sec==60)//秒加到60则进位分钟{sec=0;//同时秒数清零min++;if(min==60)//分钟加到60则进位小时{min=0;//同时分钟数清零hour++;//boom=1;//delay(5);//boom=0;if(hour==24)//小时加到24则小时清零{hour=0;week++;if(week>7){week=1;}if(mon==1){if(day>31){day=1;mon++;}}if(mon==2){if((year%4==0 && year%100!=0)||year%4==0){if(day>29){day=1;}}else if(day>28) {day=1;mon++;}}if(mon==3) {if(day>31) {day=1;mon++;}}if(mon==4) {if(day>30) {day=1;}}if(mon==5) {if(day>31) {day=1; mon++;}}if(mon==6) {if(day>30) {day=1; mon++;}}if(mon==7) {if(day>31){day=1; mon++;}}if(mon==8) {if(day>31) {day=1; mon++;}}if(mon==9) {if(day>30) {day=1; mon++;}}if(mon==10) {if(day>31) {day=1; mon++;}}if(mon==11) {if(day>30) {day=1; mon++;}}if(mon==12) {if(day>31) {day=1; mon=1;ye2++;}}}write_sfm(0x4e,week);write_sfm(0x48,day);write_sfm(0x45,mon);write_sfm(0x40,ye1);write_sfm(0x42,ye2);}write_sfm(0,hour);//小时若变化则重新写入}write_sfm(3,min);//分钟若变化则重新写入}write_sfm(6,sec); //秒若变化则重新写入if((hour==shi && min==fen) && sec==miao) {boom=1;delay(5);boom=0;}}。
单片机实验报告 ——LCD1602显示时钟
XXXX学院实验报告Experimentation Report of Taiyuan Normal University系部计算机年级大三课程单片机原理与接口技术姓名同组者日期学号项目 LCD1602显示时钟一、实验目的1、了解单片机顺序执行的特点;2、掌握C语言的编写和keilc51的使用;3、熟悉DS1302芯片的工作过程二、实验仪器硬件资源:单片机开发板笔记本电脑 DS1302芯片;软件资源:软件 Keil uVision5;三、实验原理1、流程图2、连接图四、实验结果将LCD屏连接到单片机上,点击编译运行,LCD屏上显示时间:2013-01-01 2 12-00-38。
在DS1302.c文件里修改uchar TIME[7] = {0, 0, 0x12, 0x01, 0x01,0x02, 0x13};为uchar TIME[7] = {0x14, 0x11, 0x19, 0x28, 0x11,0x04, 0x19};点击编译运行按钮,LCD屏幕显示2019-11-28 4 19-11-14。
四、实验代码及分析//主函数void main(){Ds1302Init(); //初始化DS1302LcdInit(); //初始化LCDwhile(1){Ds1302ReadTime(); //DS1302读时间LcdDisplay(); //LCD显示时间}}//初始化DS1302void Ds1302Init(){uchar n;Ds1302Write(0x8E,0X00); //禁止写保护,就是关闭写保护功能for (n=0; n<7; n++) //写入7个字节的时钟信号:分秒时日月周年{Ds1302Write(WRITE_RTC_ADDR[n],TIME[n]);}Ds1302Write(0x8E,0x80); //打开写保护功能}//读取时钟信息void Ds1302ReadTime(){uchar n;for (n=0; n<7; n++) //读取7个字节的时钟信号:分秒时日月周年{TIME[n] = Ds1302Read(READ_RTC_ADDR[n]);}}//---DS1302写入和读取时分秒的地址命令---////---秒分时日月周年最低位读写位;-------//uchar code READ_RTC_ADDR[7] = {0x81, 0x83, 0x85, 0x87, 0x89, 0x8b, 0x8d}; uchar code WRITE_RTC_ADDR[7] = {0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c};//---DS1302时钟初始化2013年1月1日星期二12点00分00秒。
51单片机控制基于1602液晶显示 电子时钟【带闹铃和整点报时】
{
switch(be)
{//uint i;
/*用于整点响铃*/case 0:{
buzz=~buzz;
//delay1();
}break;
/*用于闹铃报时*/case 1:{
buzz=~buzz;
//delay(10);
}break;
}
}
void write_com(uchar com)//命令写入函数
{
rs=0;
delay(3);
P0=com;
delay(3);
lcden=1;
delay(3);
lcden=0;
}
void write_date(uchar date)//数据写入函数
{
rs=1;
delay(3);
P0=date;
delay(3);
write_date(0x30+ge);
}
void write_ymd(uchar add,uchar date)//年月日写入子程序
{
uchar sh,ge;
sh=date/10;
ge=date%10;
write_com(0x80+add);
write_date(0x30+sh);
write_date(0x30+ge);
sbit buzz=P1^5; //蜂鸣器控制端
uchar code week0[]="Sun";
uchar code week1[]="Mon";
uchar code week2[]="Tue";
单片机LCD1602显示年月日时钟带星期和闹钟
单片机LCD1602显示年月日时钟带星期和闹钟长春工业大学测控技术与仪器专业单片机LCD1602显示年月日时钟带星期和闹钟,可识别闰年下载文档即可完全复制#include#define uchar unsigned char#define uint unsigned intsbit lcdrs = P0^7; //液晶引脚定义sbit led_cs = P0^6;sbit lcden = P0^5;sbit boom = P3^6;sbit key1 = P3^5;sbit key2 = P3^4;sbit key3 = P3^3;sbit keyE = P3^2;ucharnum,key1num,key2num,count,hour,min,sec,day,mon,year,sh i,fen,miao,week;char ye1,ye2;uchar code cg_1602[]={ 0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02, 0x0f,0x09,0x0f,0x09,0x0f,0x09,0x11,0x00,0x0f,0x09,0x09,0x0f,0x09,0x09,0x0f,0x00,0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02,};//"年月日"/*延时函数*/void delay(uint xms){uint i,j;for(i=xms;i>0;i--)for(j=114;j>0;j--);}/*1602液晶*/void write_com(uchar com)//写命令{ lcdrs=0;lcden=0;P2=com;delay(5);lcden=1;delay(5);lcden=0;}void write_data(uchar date)//写数据{ lcdrs=1;lcden=0;P2=date;delay(5);lcden=1;delay(5);lcden=0;}void write_by_xy(uchar x,uchar y)//坐标定位{uchar address;if(y==0)address=0x80+x;//y=0,写第一行elseaddress=0xc0+x;//y=1,写第二行write_com(address);}/*void write_char(uchar x,uchar y,uchar date)//坐标定位显示{ write_by_xy(x,y);//先定位write_data(date);//后写数}*/void write_string(uchar x,uchar y,uchar *s)//写字符串{write_by_xy(x,y);//设定显示位置while(*s)//write character{P2=*s;write_data(*s);s++;}}void write_sfm(uchar add,uchar date)//写时分秒函数{uchar hour,ge;hour=date/10;//分解一个2位数的十位和个位ge=date%10;write_com(0x80+add);//设置显示位置write_data(0x30+hour);//送去液晶显示十位write_data(0x30+ge); //送去液晶显示个位}void write_cg()//写入固定汉字和符号{write_com(0x40); //设定CGRAM地址for(num=0;num<24;num++) //将自定义字型码写入CGRAM 中{write_data(cg_1602[num]);}write_com(0xc4);//年{write_data(0);}write_com(0xc7);//月{write_data(1);}write_com(0xca);//日{write_data(2);}write_string(2,0,":");write_string(5,0,":");write_string(0x0a,0,":");write_string(0x0d,0,":");write_string(0x0c,1,"W");write_string(0x0d,1,"K");}void init_1602()//初始化{led_cs=0;hour=23;min=59;sec=55;key1num=0;count=0;day=28;mon =2;ye1=20;ye2=13;year=ye1*100+ye2;boom=0;shi=0;fen=0;mi ao=0;week=7;write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x01);write_string(0,1,"2013");write_string(5,1,"02");write_string(8,1,"28");write_sfm(8,shi);write_sfm(0x0b,fen);write_sfm(0x0e,miao);write_sfm(0,hour);write_sfm(3,min);write_sfm(6,sec);write_sfm(0x48,day);write_sfm(0x45,mon);write_sfm(0x40,ye1);write_sfm(0x42,ye2);write_sfm(0x4e,week);write_cg();TMOD=0x01;//设置定时器0工作模式1 TH0=(65536-50000)/256;//定时器装初值TL0=(65536-50000)%256;EA=1; //开总中断ET0=1; //开定时器0中断TR0=1; //启动定时器0}/*键盘扫描函数*/void keyscan()//按键扫描函数{//keyE =0;if(key1==0){delay(5);if(key1==0)//确认功能键被按下{key1num++;//功能键按下次数记录while(!key1);//释放确认if(key1num==1)//第一次被按下时{TR0=0; //关闭定时器write_com(0x80+7);//光标定位到秒位置write_com(0x0f); //光标开始闪烁}if(key1num==2)//第二次按下光标闪烁定位到分钟位置{ write_com(0x80+4);}if(key1num==3)//第三次按下光标闪烁定位到小时位置{ write_com(0x80+1);}if(key1num==4)//第四次按下光标闪烁定位到日位置{ write_com(0x80+0x49);}if(key1num==5)//第五次按下光标闪烁定位到月位置{ write_com(0x80+0x46);}if(key1num==6)//第六次按下光标闪烁定位到年2位置{ write_com(0x80+0x43);}if(key1num==7)//第七次按下光标闪烁定位到年1位置{write_com(0x80+0x41);}if(key1num==8)//第八次按下光标闪烁定位到星期位置{write_com(0x80+0x4f);}if(key1num==9)//第九次按下{key1num=0;//记录按键数清零write_com(0x0c);//取消光标闪烁TR0=1; //启动定时器使时钟开始走}}}if(key1num!=0)//只有功能键被按下后,增加和减小键才有效{ if(key2==0){.delay(5);if(key2==0)//增加键确认被按下{while(!key2);//按键释放if(key1num==1)//若功能键第一次按下{sec++; //则调整秒加1if(sec==60)//若满60后将清零sec=0;write_sfm(6,sec);//每调节一次送液晶显示一下write_com(0x80+7);//显示位置重新回到调节处}if(key1num==2)//若功能键第二次按下{min++;//则调整分钟加1if(min==60)//若满60后将清零min=0;write_sfm(3,min);//每调节一次送液晶显示一下write_com(0x80+4);//显示位置重新回到调节处} if(key1num==3)//若功能键第三次按下{.hour++;//则调整小时加1if(hour==24)//若满24后将清零hour=0;write_sfm(0,hour);;//每调节一次送液晶显示一下write_com(0x80+1);//显示位置重新回到调节处} if(key1num==4)//若功能键第四次按下{day++;//则调整日加1if(day>31)//若大于31后将置一day=1;write_sfm(0x48,day);//每调节一次送液晶显示一下write_com(0x80+0x48);//显示位置重新回到调节处}if(key1num==5)//若功能键第五次按下{mon++;//则调整月加1if(mon>12)//若大于12后将置一mon=1;write_sfm(0x45,mon);//每调节一次送液晶显示一.下write_com(0x80+0x45);//显示位置重新回到调节处}if(key1num==6)//若功能键第六次按下ye2++;//则调整年加1if(ye2==0x0a)//若满99后将清零ye2=0;year=ye1*100+ye2;write_sfm(0x42,ye2);//每调节一次送液晶显示一下write_com(0x80+0x42);//显示位置重新回到调节处}if(key1num==7)//若功能键第七次按下{ye1++;//则调整年加100if(ye1==0x0a)//若满99后将清零ye1=0;year=ye1*100+ye2;write_sfm(0x40,ye1);//每调节一次送液晶显示一.下write_com(0x80+0x40);//显示位置重新回到调节处}if(key1num==8)//若功能键第八次按下{week++;//则调整周加一if(week>7)//若大于7后置一week=1;write_sfm(0x4f,week);//每调节一次送液晶显示一下write_com(0x80+0x4f);//显示位置重新回到调节处}}}if(key3==0)delay(5);if(key3==0)//确认减小键被按下{while(!key3);//按键释放.if(key1num==1)//若功能键第一次按下{sec--;//则调整秒减1if(sec==-1)//若减到负数则将其重新设置为59 sec=59;write_sfm(6,sec);//每调节一次送液晶显示一下write_com(0x80+7);//显示位置重新回到调节处}if(key1num==2)//若功能键第二次按下{min--;//则调整分钟减1if(min==-1)//若减到负数则将其重新设置为59 min=59;write_sfm(3,min);//每调节一次送液晶显示一下write_com(0x80+4);//显示位置重新回到调节处}if(key1num==3)//若功能键第三次按下{hour--;//则调整小时减1if(hour==-1)//若减到负数则将其重新设置为23 hour=23;write_sfm(0,hour);//每调节一次送液晶显示一下.write_com(0x80+1);//显示位置重新回到调节处}if(key1num==4)//若功能键第四次按下{day--;//则调整日减1if(day==0)//若日为零时将置一day=31;write_sfm(0x48,day);//每调节一次送液晶显示一下write_com(0x80+0x49);//显示位置重新回到调节处}if(key1num==5)//若功能键第五次按下{mon--;//则调整月减1if(mon==0)//若月为零将置一mon=12;write_sfm(0x45,mon);//每调节一次送液晶显示一下write_com(0x80+0x45);//显示位置重新回到调节处}{ye2--;//则调整年减1if(ye2<0)//若小于零后将设置为99ye2=99;year=ye1*100+ye2;write_sfm(0x42,ye2);//每调节一次送液晶显示一下write_com(0x80+0x42);//显示位置重新回到调节处}if(key1num==7)//若功能键第七次按下{ye1--;//则调整年减100if(ye1<0)//若小于零后将设置为99ye1=99;year=ye1*100+ye2;write_sfm(0x40,ye1);//每调节一次送液晶显示一下write_com(0x80+0x40);//显示位置重新回到调节处}{week--;//则调整周减一if(week==0)//若等于0后将置7week=7;write_sfm(0x4f,week);//每调节一次送液晶显示一下write_com(0x80+0x4f);//显示位置重新回到调节处}}}}if(keyE==0){delay(5);if(keyE==0)//确认功能键被按下{key2num++;//功能键按下次数记录while(!keyE);//释放确认if(key2num==1)//第一次被按下时{TR0=0; //关闭定时器write_com(0x80+0x0f);//光标定位到秒位置write_com(0x0f); //光标开始闪烁}if(key2num==2)//第二次按下光标闪烁定位到分钟位置{write_com(0x80+0x0c);}if(key2num==3)//第三次按下光标闪烁定位到小时位置{write_com(0x80+9);}if(key2num==4)//第八次按下{key2num=0;//记录按键数清零write_com(0x0c);//取消光标闪烁TR0=1; //启动定时器使时钟开始走}}}if(key2num!=0)//只有功能键被按下后,增加和减小键才有效{。
基于单片机的LCD1602电子时钟设计
基于单片机的LCD1602电子时钟设计近年来,随着物联网和智能设备的快速发展,电子时钟作为一种常见的智能设备,广泛应用于家庭、办公室等各种场合。
本文将基于单片机设计一款LCD1602电子时钟,实现时间显示、闹钟设置等功能。
一、硬件设计1.单片机选择在本设计中,选择常用的51系列单片机AT89C51,具有丰富的外设资源和强大的处理能力。
该单片机具有8位数据总线、16位地址总线,并且集成了定时/计数器、中断控制器和串行通信接口等外设。
2.显示模块选择3.时钟模块选择通过接入DS1302时钟模块,可以实现实时时钟的功能。
DS1302模块具有时钟计数器、电压检测电路、串行通信接口等,并且具有低功耗特点。
4.控制板设计根据LCD1602的引脚连接方式,设计一个控制板,用于将单片机、显示模块和时钟模块等连接在一起。
同时,需注意设计供电电路、外设输入输出电平等电路。
二、软件设计1.初始化设置通过单片机的GPIO口配置,将LCD1602和DS1302对应的引脚设置为输出模式,同时初始化LCD显示屏并进行清屏操作。
此外,需设置DS1302时钟模块的时钟、日期、闹钟等参数。
2.时间显示通过读取DS1302时钟模块的计数器,获得当前的小时、分钟和秒数,然后将其格式化为HH:MM:SS的形式,并通过LCD显示出来。
3.时间设置通过单片机的外部中断,当用户按下设置按钮后,进入时间设置模式。
在时间设置模式下,用户可以通过按下不同的按键来调整小时、分钟和秒数。
调整完成后,再次按下设置按钮即可保存设置。
4.闹钟设置通过单片机的定时器中断,设定一个闹钟定时器。
当闹钟定时器触发时,触发相应的中断,然后通过LCD显示闹钟提示。
此外,用户也可以通过按下按钮来设置闹钟时间,并通过单片机的外部中断进行处理。
5.闹钟响铃当闹钟时间到达时,触发相应的中断,通过LCD显示闹钟提示,并通过蜂鸣器发出响铃声。
总结通过本设计,可以实现一款功能齐全的LCD1602电子时钟。
单片机时钟芯片DS1302在LCD1602上显示年月日时分秒..
单片机设计实验内容摘要:单片机实验是通过Proteus仿真并且与Keil相结合使用控制单片机使其在仿真中完成一系列所设计的程序。
我们这个小组所做的实验是仿真一个数字时钟,通过DS130这个芯片从计算机上读取时间信息,再由51单片机对数据进行处理、分配,将其输出在LCD160上,实现简单的数字时钟的功能。
设计内容及要求:(1)根据设计课题的技术指标和给定条件,在教师指导下,能够独立而正确地进行方案论证和设计计算,要求概念清楚、方案合理、方法正确、步骤完整;(2)要求学生掌握单片机的设计内容、方法和步骤;(3)要求会查阅有关参考资料和手册等;(4)要求学会选择有关元件和参数;(5)要求学会绘制有关电路图和设计流程图;(6)要求学会编写设计说明书。
系统框图:硬件选择:1、AT89C51AT89C5是一种带 4K字节 FLASH存储器(FPEROMFIash Programmable and Erasable Read Only Memory )的低电压、高性能 CMOS位微处理器,俗称单片机。
AT89C205是一种带2K字节闪存可编程可擦除只读存储器的单片机。
单片机的可擦除只读存储器可以反复擦除1000次o该器件采用ATMEI高密度非易失存储器制造技术制造,与工业标准的MCS-5指令集和输出管脚相兼容。
由于将多功能8位 CPU和闪烁存储器组合在单个芯片中,ATMEL勺AT89C5是一种高效微控制器, AT89C205是它的一种精简版本。
AT89C5单片机为很多嵌入式控制系统提供了一种灵活性高且价廉的方案。
AT89C51 外形及引脚排列主要特性:•与MCS-51兼容•4K字节可编程FLASH存储器•寿命:1000写 /擦循环•数据保留时间:10年•全静态工作:0Hz-24MHz•三级程序存储器锁定•128X 8位内部RAM•32可编程I/O线•两个16位定时器/计数器•5个中断源•可编程串行通道•低功耗的闲置和掉电模式•片内振荡器和时钟电路特性概述:AT89C51提供以下标准功能:4k字节Flash闪速存储器,128字节内部RAM 32个I/O 口线,两个16位定时/计数器,一个5向量两级中断结构,一个全双工串行通信口,片内振荡器及时钟电路。
单片机万年历汇编闹钟时间可调程序(LCD1602,DS18B20,DS1302,MAX810L)
片机万年历汇编闹钟时间可调程序(LCD1602,DS18B20,DS1302,MAX810L)说明:0该程序全部是用汇编语言编写1.该程序附带有温度显示,并且带有闹铃功能2.正常时间和闹钟时间都可以用键盘设置3.该程序是使用LCD1602显示年月日,格式为TIME XX-XX-XX XX,由于屏幕的关系,所以就不显示周的数据,其中闹铃调整的上界面是“BELLADJUST”4.该程序的时间是由时钟芯片DS1302提供的,据说很精准,目前看起来确实是这样的,刚开始我是使用定时器计时的,但是不怎么精准,可能是我的汇编技术有限才导致,所以本人就把这个版本呈上,希望诸位多多斧正5.该程序的温度是通过DS18B20提取的,这个模块是我从别人那里COPY过来的,O(∩_∩)O~,显示是肯定没问题的6.该程序也有用MAX810l的复位功能,但是好像这一点还没被体现出来7.烧程序我使用的是MAX232外加几个极性电容,还有一个RS232,不幸的是我的PCB板的RS232的封装画错啦!!~~~~(>_<)~~~~8.该万年历是由五个按键控制的,SW5复位,SW1调时间,调年月日时分秒,除秒可以加减调节之外其余的调节都是只能加不能减(自我觉得如果增加减的功能会觉得程序复杂,所以免!), SW4 是用来调节闹钟的时分秒的,和SW1按键不同的是时分秒都能加减,当闹钟设置的时间和正常显示时间的时分秒相同时,闹铃十秒钟,期间你可以按SW4键终止响铃,SW2 和SW3 分别是用来加减时间的!9.说了这么多,最后说说自我认为的缺陷,行家应该都一眼就看出一些破绽了,那就是按键消抖的问题,这个我觉得有点麻烦所以本人就把这个问题留给阅览资料的你吧!10.废话说了这么多,最后把我的程序,ORCAD电路原理图,PADS软件的PCB图,以及一张实物图献上,希望你能喜欢,页脚有我的Email(prettyboy2009@),欢迎随时交流!程序:;*************************************************************** ;***************************************************************RS BIT P2.5RW BIT P2.6E BIT P2.7SU BIT P1.6 ;1302串行口数据端RST BIT P1.5CLK BIT P1.7ALARM BIT P2.3JIAN BIT P2.2 ;减JIA BIT P2.1 ;加MOSHI BIT P2.0 ;模式DQ BIT P1.0SOUND BIT P1.3NIAN EQU 7FHYUE EQU 7DHDAY EQU 7CHHHH EQU 7EHSHI EQU 7BHFEN EQU 7AHMIAO EQU 79HASHI EQU 78HAFEN EQU 77HAMIAO EQU 76HGEW EQU 75HA_BIT EQU 70H ;18B20B_BIT EQU 6FHFLAG EQU 6EHDS1302_ADDR EQU 6DHDS1302_DATA EQU 6CHORG 0000HLJMP STARTORG 0030H ;***************************************************************; 初始化开机时间 &&&&&&& 初始化闹铃时间;***************************************************************START:MOV DPTR,#TABMOV SHI,#16HMOV ASHI,#17MOV FEN,#58HMOV AFEN,#30MOV MIAO,#00HMOV AMIAO,#00MOV NIAN,#11HMOV YUE,#12HMOV DAY,#13HMOV HHH,#00H;***************************************************************; 初始化LCD1602 &&&&&&& 初始化DS1302 ;***************************************************************MOV P0,#01H ; 显示清屏数据指针清零所有显示清零LCALL WR_CODEMOV P0,#02H ; 显示回车数据指针清零LCALL WR_CODEMOV P0,#38H ;设置16*2显示 5*7 点阵 8位数据接口LCALL WR_CODEMOV P0,#06H ; 当写或写一个数据时地址指针自动加一光标自动加一LCALL WR_CODEMOV P0,#0cH ; 开显示不显光标 0fh开显示开光标光标闪烁LCALL WR_CODELCALL XIAN1;***************************************************************; 主函数(这个大家都懂的);*************************************************************** MAIN:lcall RD_DS1302LCALL XIANSHIlcall keyLCALL AKEYLCALL RE_TEMPLCALL CONVERLCALL DISPLAY_INTLJMP BELLRING;***************************************************************; 读1302子程序;***************************************************************RD_DS1302:MOV DS1302_ADDR,#8DH ;读DS1302中的年LCALL READ ;调用读DS1302子程序MOV NIAN, DS1302_DATA ;把读出的年数据存入年寄存器中MOV DS1302_ADDR,#89H ;读DS1302中的月LCALL READMOV YUE, DS1302_DATA ;把读出的月数据存入月寄存器中MOV DS1302_ADDR,#87H ;读DS1302中的天LCALL READMOV DAY, DS1302_DATA ;把读出的天数据存入天寄存器中MOV DS1302_ADDR,#85H ;读DS1302中的小时LCALL READMOV SHI, DS1302_DATA ;把读出的天数据存入小时寄存器中MOV FEN, DS1302_DATA ;把读出的天数据存入分钟寄存器中MOV DS1302_ADDR,#81H ;读DS1302中的秒钟LCALL READMOV MIAO, DS1302_DATA ;把读出的天数据存入秒钟寄存器中RET ;***************************************************************; 写1302子程序;***************************************************************WR_DS1302:MOV DS1302_ADDR, #8EH ;写DS1302控制指令MOV DS1302_DATA, #00H ;写数据到DS1302的8E控制寄存器中,允许对其进行写操作LCALL WRITE ;调用写DS1302子程序MOV DS1302_ADDR,#8CH ;写DS1302中的年MOV DS1302_DATA , NIAN ;把写出的年数据存入年寄存器中LCALL WRITEMOV DS1302_ADDR,#88H ;写DS1302中的月MOV DS1302_DATA ,YUE ;把写出的月数据存入月寄存器中LCALL WRITEMOV DS1302_ADDR,#86H ;写DS1302中的天MOV DS1302_DATA ,DAY ;把写出的天数据存入天寄存器中LCALL WRITEMOV DS1302_ADDR,#84H ;写DS1302中的小时MOV DS1302_DATA , SHI ;把写出的天数据存入小时寄存器中LCALL WRITEMOV DS1302_ADDR,#82H ;写DS1302中的分钟MOV DS1302_DATA , FEN ;把写出的天数据存入分钟寄存器中LCALL WRITEMOV DS1302_ADDR,#80H ;写DS1302中的秒钟MOV DS1302_DATA , MIAO ;把写出的天数据存入秒钟寄存器中LCALL WRITEMOV DS1302_ADDR, #90H ;写DS1302控制指令MOV DS1302_DATA,#0A6H ;写数据到DS1302的90控制寄存器中,对电池涓流充电,充电电流为1.1mARET;***************************************************************; 写1302程序;***************************************************************WRITE:CLR CLKNOPSETB RSTNOPMOV A,DS1302_ADDRMOV R4,#8 WRITE1:RRC A ;送地址给1302NOPNOPCLR CLKNOPNOPNOPMOV SU,CSETB CLK ;送入地址在时钟上升沿有效NOPNOPNOPNOPDJNZ R4,WRITE1CLR CLKNOPMOV A,DS1302_DATAMOV R4,#8 WRITE2:RRC ANOP ;送数据给1302,时钟上升沿,数据输入CLR CLKNOPNOPMOV SU,CNOPNOPNOPSETB CLKDJNZ R4,WRITE2CLR RSTCLR ARET ;***************************************************************; 读1302程序;***************************************************************READ:CLR CLKNOPNOPSETB RSTNOPMOV A,DS1302_ADDRMOV R4,#8 READ1:RRC ANOPMOV SU,CNOPNOPNOPSETB CLK ;送入地址在时钟上升沿有效NOPNOPNOPCLR CLKNOPNOPDJNZ R4,READ1 ;判断8位数据是否传送完?MOV R4,#8 READ2:CLR CLKNOPNOPNOPMOV C,SUNOPNOPNOPNOPNOP ;从ds1302中读取数据,时钟下降沿有效NOPNOPNOPSETB CLKNOPDJNZ R4,READ2 ;判断8位数据是否传送完?MOV DS1302_DATA,ACLR RSTRET;***************************************************************; 固定显示显示TIME ,'-',:;***************************************************************XIAN1:MOV P0,#84HLCALL WR_CODEMOV A,#'-' ;1602有字库可以直接调用不用查表LCALL WR_DATAMOV P0,#87HLCALL WR_CODEMOV A,#'-'LCALL WR_DATAMOV P0,#80HLCALL WR_CODEMOV A,#'2' ;计时100年所以20XX 20是固定的LCALL WR_DATAMOV P0,#81HLCALL WR_CODEMOV A,#'0'LCALL WR_DATAMOV P0,#0C1HLCALL WR_CODEMOV A,#'T'LCALL WR_DATAMOV P0,#0C2HLCALL WR_CODEMOV A,#'I'LCALL WR_DATAMOV P0,#0C3HLCALL WR_CODEMOV A,#'M'LCALL WR_DATAMOV P0,#0C4HLCALL WR_DATAMOV P0,#0CCHLCALL WR_CODEMOV A,#':'LCALL WR_DATAMOV P0,#0C9HLCALL WR_CODEMOV A,#':'LCALL WR_DATAMOV P0,#08EHLCALL WR_CODEMOV A,#0DFHLCALL WR_DATAMOV P0,#08FHLCALL WR_CODEMOV A,#'C'LCALL WR_DATARET;*************************************************************** ; 显示数据时分秒年月日周地址数据都在变化没用循环体;***************************************************************XIANSHI:MOV HHH,MIAOLCALL HEXMOV P0,#0CDHLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATAMOV A,BMOV P0,#0CEHLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATAMOV HHH,FENLCALL HEXMOV P0,#0CAHLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATALCALL WR_CODE MOVC A,@A+DPTR LCALL WR_DATAMOV HHH,SHI LCALL HEXMOV P0,#0C7H LCALL WR_CODE MOVC A,@A+DPTR LCALL WR_DATA MOV A,BMOV P0,#0C8H LCALL WR_CODE MOVC A,@A+DPTR LCALL WR_DATAMOV HHH,DAY LCALL HEXMOV P0,#088H LCALL WR_CODE MOVC A,@A+DPTR LCALL WR_DATA MOV A,BMOV P0,#089H LCALL WR_CODE MOVC A,@A+DPTR LCALL WR_DATAMOV HHH,YUE LCALL HEXMOV P0,#085H LCALL WR_CODE MOVC A,@A+DPTR LCALL WR_DATA MOV A,BMOV P0,#086H LCALL WR_CODE MOVC A,@A+DPTR LCALL WR_DATAMOV HHH,NIAN LCALL HEXMOV P0,#082HMOVC A,@A+DPTRLCALL WR_DATAMOV A,BMOV P0,#083HLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATARET;***************************************************************; 判键子程按一次模式键后就一直判断下一次按键是P2.1还是P2.2;判断进入下一模式还是加1(按下模式键第一次加1需要按两次);MO1加分 MO2加时 MO3加月 MO4加日 MO5加年,除秒可以加减调节外,;时间只能通过加分时日月年调节;***************************************************************KEY:JNB MOSHI,MORET MO:JNB MOSHI,$MOV P0,#0DH ; 开显示不显光标 0fh开显示开光标光标闪烁LCALL WR_CODE MO1:MOV P0,#0CBHLCALL WR_CODEJNB JIA,JIAFFJNB JIAN,JIANFFJNB MOSHI,MO11LJMP MO1 MO11:JNB MOSHI,$;MO2:MOV P0,#0C8HLCALL WR_CODEJNB JIA,JIASSJNB MOSHI,MO21LJMP MO2 MO21:JNB MOSHI,$; ;MO4:MOV P0,#089HLCALL WR_CODELJMP MO4 MO41:JNB MOSHI,$MO3:MOV P0,#086HLCALL WR_CODEJNB JIA,JIAMMJNB MOSHI,MO31LJMP MO3 MO31:JNB moshi,$;MO5:MOV P0,#083HLCALL WR_CODEJNB JIA,JIAYYJNB MOSHI,MO51LJMP MO5 MO51:JNB MOSHI,$MOV P0,#0CH ; 开显示不显光标 0fh开显示开光标光标闪烁LCALL WR_CODElcall XIAN1RET;***************************************************************; 跳转出范围中转;***************************************************************JIAFF:LJMP JIAFJIANFF:LJMP JIANFJIADD:LJMP JIADJIAMM:LJMP JIAMJIAYY:LJMP JIAYJIASS:LJMP JIAS;***************************************************************;判断加1 以及跳转到另一模式(模式是指加分还是加时加月等);***************************************************************JIAF:MOV P0,#0CBHLCALL WR_CODEJNB JIAN,JIANFJB JIA,JIAF2JNB JIA,$mov A,FENADD A , #01HDA Amov FEN,ACJNE A , #60H ,JIAF3MOV FEN ,#00H JIAF3:LCALL WR_DS1302LCALL XIANSHILJMP JIAF JIAF1:JNB MOSHI,$LJMP MO11JIANF:MOV P0,#0CBHLCALL WR_CODEJNB MOSHI,JIANF1JNB JIA,JIAFJB JIAN,JIANFJNB JIAN,$MOV A,FENCJNE A,#00,JIANF2MOV FEN,#59HLJMP JIANF3 JIANF2:CLR CSUBB A,#01DA AMOV FEN,A JIANF3:LCALL WR_DS1302LCALL XIANSHILJMP JIANF JIANF1:JNB MOSHI,$LJMP MO11JIAS:MOV P0,#0C8HJIAS2:JNB MOSHI,JIAS1JB JIA,JIAS2JNB JIA,$MOV A,SHIADD A,#01HDA AMOV SHI,ACJNE A,#24H,JIAS3MOV SHI,#00 JIAS3:LCALL WR_DS1302LCALL XIANSHILJMP JIAS JIAS1:JNB MOSHI,$LJMP MO21JIAD:MOV P0,#089HLCALL WR_CODEJIAD2:JNB MOSHI,JIAD1JB JIA,JIAD2JNB JIA,$MOV A,DAYADD A,#01HDA AMOV DAY,AMOV A,YUECJNE A,#01H,SS1LJMP JIAD4 SS1:CJNE A,#03H,SS2 LJMP JIAD4 SS2:CJNE A,#05H,SS3LJMP JIAD4 SS3:CJNE A,#07H,SS4LJMP JIAD4 SS4:SS5:CJNE A,#10H,SS6LJMP JIAD4 SS6:CJNE A,#12H,SSS JIAD4:MOV A,DAYCJNE A,#32H,JIAD3MOV DAY,#01H JIAD3:LCALL WR_DS1302LCALL XIANSHILJMP JIAD JIAD1:JNB MOSHI,$LJMP MO41 SSS:CJNE A,#02H,S30MOV A,NIANANL A,#0FHMOV GEW,AMOV A,NIANANL A,#0F0HSWAP AMOV B,#10MUL ABADD A,GEWMOV B,#04HDIV ABMOV A,BCJNE A,#00H,S29LJMP S28 S30:MOV A,DAYCJNE A,#31H,JIAD3MOV DAY,#01HLJMP JIAD3 S29:MOV A,DAYCJNE A,#29H,JIAD3MOV DAY,#01HLJMP JIAD3 S28:MOV DAY,#01HLJMP JIAD3;***************************************************************;;判断月的天数判断闰年的方法先将年的数据有十六进制BCD码转换成正常的十六进制;再除以4 判断余数是否为0 为零则为闰年不为零不是;***************************************************************JIAM:MOV P0,#086HLCALL WR_CODE JIAM2:JNB MOSHI,JIAM1JB JIA,JIAM2JNB JIA,$MOV A,YUEADD A,#01HDA AMOV YUE,ACJNE A,#13H,JIAM3MOV YUE,#01 JIAM3:LCALL WR_DS1302LCALL XIANSHI JIAM1:JNB MOSHI,$LJMP MO31 JIAY:MOV P0,#083HLCALL WR_CODE JIAY2:JNB MOSHI,JIAY1JB JIA,JIAY2JNB JIA,$MOV A,NIANADD A,#01HDA AMOV NIAN,ACJNE A,#99H,JIAY3MOV NIAN,#00 JIAY3:LCALL WR_DS1302LCALL XIANSHILJMP JIAY;***************************************************************;温度读取;***************************************************************RE_TEMP:SETB DQACALL INIT_18B20JB FLAG, STRET ST:MOV A, #0CCHACALL WRITE_18B20MOV A, #44HACALL WRITE_18B20ACALL INIT_18B20MOV A, #0CCHACALL WRITE_18B20MOV A, #0BEHACALL WRITE_18B20ACALL READ_18B20RET;***************************************************************;初始化DS18B20;***************************************************************INIT_18B20:SETB DQNOPCLR DQMOV R1, #3 DLY:MOV R0, #107DJNZ R0, $DJNZ R1, DLYSETB DQNOPNOPNOPMOV R0, #25H T2:JNB DQ, T3DJNZ R0, T2JMP T4 T3:SETB FLAGJMP T5JMP T7 T5:MOV R0, #117 T6:DJNZ R0, T6 T7:SETB DQRET ;***************************************************************;写DS18B20;***************************************************************WRITE_18B20:MOV R2, #8CLR C WR1:CLR DQMOV R3, #6DJNZ R3, $RRC AMOV DQ, CMOV R3, #23DJNZ R3, $SETB DQNOPDJNZ R2, WR1SETB DQRET;***************************************************************;读DS18B20;***************************************************************READ_18B20:MOV R4, #2MOV R1, #21H RE0:MOV R2, #8 RE1:CLR CSETB DQNOPNOPCLR DQNOPNOPMOV R3, #9 RE2:DJNZ R3, RE2MOV C, DQMOV R3, #23 RE3:DJNZ R3, RE3RRC ADJNZ R2, RE1MOV @R1, ADEC R1DJNZ R4, RE0RET;***************************************************************;温度转换;***************************************************************CONVER:MOV A, 21HMOV C, 20H.0RRC AMOV C, 20H.1RRC AMOV C, 20H.2RRC AMOV C, 20H.3RRC AMOV 21H, ARET;***************************************************************;显示温度整数部分;***************************************************************DISPLAY_INT:MOV A, 21HMOV B, #10DIV ABMOV B_BIT, AMOV A_BIT, BMOV DPTR, #TABMOV P0,#08cHLCALL WR_CODELCALL WR_DATAMOV P0,#08DHLCALL WR_CODEMOV A, A_BITMOVC A, @A+DPTRLCALL WR_DATARET;***************************************************************; 1602的写数据读指令判忙程序;***************************************************************WR_DATA:MOV P0,ASETB RS ;RS=1选择数据寄存器CLR RW ;RW=0 ;准备CLR E ;E=0 ;执行显示命令LCALL BUSY ;判断液晶模块是否忙?SETB E ;E=1 ;显示完成,程序停车RET WR_CODE:CLR RS ;写入控制命令的子程序CLR RWCLR ELCALL BUSYSETB ERET BUSY:MOV P0,#0FFH ;判断液晶显示器是否忙的子程序CLR RSSETB RWCLR ENOP ;nop一定要有SETB EJB P0.7,BUSY ;如果P0.7为高电平表示忙就循环等待RET ;***************************************************************; 判键子程按一次模式键后就一直判断下一次按键是P3.4还是P3.5 判断进入下一模式还是加1(按下模式键第一次加1需要按两次);MO1加分 MO2加时 MO3加月 MO4加日 MO5加年AKEY:JNB ALARM, XIANGUANGRET XIANGUANG:JNB ALARM,$MOV P0,#01H ; 显示清屏数据指针清零所有显示清零LCALL WR_CODEMOV P0,#02H ; 显示回车数据指针清零LCALL WR_CODEMOV P0,#038H ;设置16*2显示 5*7 点阵 8位数据接口LCALL WR_CODEMOV P0,#04H ; 当读或写一个数据时地址指针自动加一光标自动加一LCALL WR_CODEMOV P0,#0DH ; 开显示不显光标 0fh开显示开光标光标闪烁LCALL WR_CODELCALL AXIANLCALL AXIANSHIMOMIAO: MOV P0,#0CBHLCALL WR_CODEJNB JIA,INCMJNB JIAN,DECMJNB ALARM ,BACKMIAOLJMP MOMIAO BACKMIAO:JNB ALARM,$LJMP MOFENINCM:MOV P0,#0CBHLCALL WR_CODE INCM2:JNB ALARM,INCM1JNB JIAN,DECMJB JIA,INCM2JNB JIA,$INC AMIAOMOV A,AMIAOCJNE A,#60,INCM3MOV AMIAO,#00 INCM3:LCALL AXIANSHILJMP INCMINCM1:JNB ALARM ,BACKMIAODECM:MOV P0,#0CBHLCALL WR_CODEJNB ALARM,DECM1JNB JIA,INCMJB JIAN,DECMJNB JIAN,$MOV A,AMIAOCJNE A,#00,DECM2MOV AMIAO,#59LJMP DECM3 DECM2:CLR CSUBB A,#01MOV AMIAO,A DECM3:LCALL AXIANSHILJMP DECM DECM1:JNB ALARM,BACKMIAOMOFEN:MOV P0,#0C8HLCALL WR_CODEJNB JIA,INCFJNB JIAN,DECFJNB ALARM ,BACKFENLJMP MOFEN BACKFEN:JNB ALARM,$LJMP AMOSHIINCF:MOV P0,#0C8HLCALL WR_CODEINCF2:JNB ALARM,INCF1JNB JIAN,DECFJB JIA,INCF2JNB JIA,$INC AFENMOV A,AFENCJNE A,#60,INCF3MOV AFEN,#00INCF3:LCALL AXIANSHILJMP INCFINCF1:JNB ALARM ,BACKFENDECF:MOV P0,#0C8HLCALL WR_CODEJNB ALARM,DECF1JNB JIA,INCFJB JIAN,DECFJNB JIAN,$MOV A,AFENCJNE A,#00,DECF2MOV AFEN,#59LJMP DECF3DECF2:CLR C;DEC ASUBB A,#01;DA AMOV AFEN,ADECF3:LCALL AXIANSHILJMP DECFDECF1:JNB ALARM,BACKFENAMOSHI:MOV P0,#0C5HLCALL WR_CODEJNB JIA,INCSJNB JIAN,DECSJNB ALARM ,BACKSHI LJMP AMOSHIINCS:MOV P0,#0C5HLCALL WR_CODEINCS2:JNB ALARM,INCS1JNB JIAN,DECSJB JIA,INCS2JNB JIA,$INC ASHIMOV A,ASHICJNE A,#24,INCS3MOV ASHI,#00INCS3:LCALL AXIANSHILJMP INCSINCS1:JNB ALARM ,BACKSHIBACKSHI:JNB ALARM,$MOV P0,#01HLCALL WR_CODEMOV P0,#0CHLCALL WR_CODELCALL XIAN1LJMP MAINDECS:MOV P0,#0C5HLCALL WR_CODEJNB ALARM,DECS1JNB JIA,INCSJB JIAN,DECSJNB JIAN,$MOV A,ASHICJNE A,#00,DECS2MOV ASHI,#23LJMP DECS3 DECS2:CLR CSUBB A,#01MOV ASHI,ADECS3:LCALL AXIANSHILJMP DECS DECS1:JNB ALARM,BACKSHI;***************************************************************; 闹钟部分固定显示显示TIME ADJUST;***************************************************************AXIAN:MOV P0,#82HLCALL WR_CODEMOV A,#'B'LCALL WR_DATAMOV P0,#83HLCALL WR_CODEMOV A,#'E'LCALL WR_DATAMOV P0,#84HLCALL WR_CODEMOV A,#'L' ;LCALL WR_DATAMOV P0,#85HLCALL WR_CODEMOV A,#'L'LCALL WR_DATAMOV P0,#088HLCALL WR_CODEMOV A,#'A'LCALL WR_DATAMOV P0,#089HLCALL WR_CODEMOV A,#'D'LCALL WR_DATAMOV P0,#08AHLCALL WR_CODEMOV A,#'J'LCALL WR_DATAMOV P0,#08BHLCALL WR_CODEMOV A,#'U'LCALL WR_DATAMOV P0,#08CHLCALL WR_CODEMOV A,#'S'LCALL WR_DATAMOV P0,#08DHLCALL WR_CODEMOV A,#'T'LCALL WR_DATAMOV P0,#0C6HLCALL WR_CODEMOV A,#':'LCALL WR_DATAMOV P0,#0C9HLCALL WR_CODEMOV A,#':'LCALL WR_DATARET;*************************************************************** ; 显示数据时分秒年月日周地址数据都在变化没用循环体;*************************************************************** AXIANSHI:MOV HHH,AMIAOLCALL AHEXMOV P0,#0CAHLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATAMOV A,BMOV P0,#0CBHLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATAMOV HHH,AFENLCALL AHEXMOV P0,#0C7HLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATAMOV A,BMOV P0,#0C8HLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATAMOV HHH,ASHILCALL AHEXMOV P0,#0C4HLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATAMOV A,BMOV P0,#0C5HLCALL WR_CODEMOVC A,@A+DPTRLCALL WR_DATARET;***************************************************************; 分离十进制BCD码中的十位和个位;***************************************************************AHEX: MOV A,HHHMOV B,#10DIV ABRET;***************************************************************; 闹钟模块;***************************************************************;==========================条件符合响铃1分钟============================ BELLRING:MOV HHH,SHILCALL HEXMOV R2,BMOV B,#10MUL ABADD A,R2CJNE A ,ASHI, AAAMOV HHH,FENLCALL HEXMOV R2,BMOV B,#10MUL ABADD A,R2CJNE A ,AFEN,AAAMOV HHH,MIAOLCALL HEXMOV R2,BMOV B,#10MUL ABADD A,R2CJNE A ,AMIAO,AAALCALL BELLRAAA:LJMP MAIN;==========================闹钟响铃10秒钟============================BELLR:MOV COUNT,#10ZZZ:SETB SOUNDLCALL DELAY500MSCLR SOUNDLCALL DELAY500MSlcall RD_DS1302LCALL XIANSHIJNB ALARM ,BBBDJNZ COUNT ,ZZZBBB:JNB ALARM ,$SETB SOUNDRET;==========================设置闹铃延时500MS响一次=================== DELAY500MS:MOV R7,#17HDL1:MOV R6,#98HDL0:MOV R5,#46HDJNZ R5,$DJNZ R6,DL0DJNZ R7,DL1RET;*************************************************************** ; 转换成BCD码;*************************************************************** ZHUAN:MOV A,HHHADD A,#00HDA ARET;*************************************************************** ; 分离BCD码中的十位和个位;*************************************************************** HEX:MOV A,HHHMOV B,#16DIV ABRET;*************************************************************** ; 数据查表;*************************************************************** TAB: DB 30H,31H,32H,33H,34H,35H,36H,37H,38H,39HENDORCAD电路原理图PADS软件的PCB图实物图。
基于stc51单片机的LCD1602显示时间的电子万年历(显示
1 课设所需软件简介1.1 Keil uVision4的简要介绍2009年2月发布KeilμVision4,KeilμVision4引入灵活的窗口管理系统,使开发人员能够使用多台监视器,并提供了视觉上的表面对窗口位置的完全控制的任何地方。
新的用户界面可以更好地利用屏幕空间和更有效地组织多个窗口,提供一个整洁,高效的环境来开发应用程序。
新版本支持更多最新的ARM芯片,还添加了一些其他新功能。
2011年3月ARM公司发布最新集成开发环境RealViewMD K开发工具中集成了最新版本的KeiluVision4,其编译器、调试工具实现与ARM器件的最完美匹配。
KeilC51开发系统基本知识KeilC51开发系统基本知识1. 系统概述KeilC51软件提供丰富的库函数和功能强大的集成开发调试工具,全Windows界面。
另外重要的一点,只要看一下编译后生成的汇编代码,就能体会到Keil C51生成的目标代码效率非常之高,多数语句生成的汇编代码很紧凑,容易理解。
在开发大型软件时更能体现高级语言的优势。
下面详细介绍KeilC51开发系统各部分功能和使用。
2. Keil C51单片机软件开发系统的整体结构C51工具包的整体结构,uVision与Ishell分别是C51for Windo ws和forDos的集成开发环境(IDE),可以完成编辑、编译、连接、调试、仿真等整个开发流程。
开发人员可用IDE本身或其它编辑器编辑C或汇编源文件。
然后分别由C51及C51编译器编译生成目标文件(.OBJ)。
目标文件可由LIB51创建生成库文件,也可以与库文件一起经L51连接定位生成绝对目标文件(.ABS)。
ABS文件由OH51转换成标准的Hex文件,以供调试器dScope51或tScope51使用进行源代码级调试,也可由仿真器使用直接对目标板进行调试,也可以直接写入程序存贮器如EPROM中。
使用独立的Keil仿真器时,注意事项:* 仿真器标配11.0592MHz的晶振,但用户可以在仿真器上的晶振插孔中换插其他频率的晶振。
LCD1602电子时钟设计
电子时钟设计班级:电子1001姓名:***学号:**********指导老师:***一、实验目的学习利用AT89C52进行任务设计,练习使用52单片机内部的定时器进行计时。
学习ds1302时钟芯片和ds18b20温度传感器的使用。
学习用模块化编程进行较长程序的编写。
二、设计要求:(1)利用lcd1602液晶显示屏作为显示模块,用AT89C52进行控制,要求用ds18b02测量显示即时温度,温度报警,用ds1302时钟芯片为单片机提供时间数据。
具有定时功能。
(2)要求时间和定时时间可调,并且在闹铃报时的时候可以用按键进行关闭。
并且可以用按键关闭打开定时功能。
(3)利用keil uVision4编译软件进行编译。
(4)完成实验要求,写出实验报告。
三、电子元件列表四、工作现象本时钟具有显示年月日时分秒星期、温度和温度报警的功能。
实验用时钟芯片ds1302来提供秒、分、时、星期、日期、月份和年份的数据,显示部分采用液晶显示模块lcd1602,右上方显示星期,左下角显示温度,右下角显示闹铃的开关状态。
用温度传感器ds18b20来测量温度。
另外,闹铃用pxo888音乐芯片来报时,用蜂鸣器做温度报警发声器。
具体各部分功能及操作下面将做介绍:ds1302给单片机at89c52提供年、月、日、时、分、秒、星期,ds18b20采集温度的数据,经单片机的处理送到液晶显示屏lcd1602上显示,实验设置的报警温度为30*c,由于程序有点长,已达到52单片机内存的极限,所以没加调整报警温度的功能,并且在天正时间的过程中能能加,不能减。
现在开始介绍具体的操作步骤:key1为调整时间和日期的按键,按下key1键,lcd1602上的光标按时分星期日月年的顺序进行移动,光标所到处按key3键可以调整相应的数据信息。
Key2键是闹钟调整键,本实验只提供了设置时间来调整闹钟,不设计年月日和星期,按下key2键,光标在时分之间切换,光标所到处按key3调整相应数据。
1602液晶显示(年月日时分秒星期)
电子钟—1602液晶显示(年月日时分秒星期)/* 以下是电子钟的c51源程序,用1602液晶显示,虽然程序很庞大,但容易看懂。
改程序花了我两三天的时间才弄好的,现在放在此分享。
*/#include<AT89X52.H>#include<intrins.h>#define uchar unsigned char#define uint unsigned int#define T 49998#define T1 64536sbit rs=P2^0;sbit rw=P2^1;sbit en=P2^2;uchar key,n,loca=0,allow=0,cout;uchar week;uchar time[6]={0,6,15,12,30,0}; //对应、月、日、时、分、秒?uint year=2009;void delay(uint ms){uint i;for(;ms>0;ms--){for(i=246;i>0;i--);}}void timer0() interrupt 1{TH0=(65536-T)/256;TL0=(65535-T)%256;n++;}void time_addsec(){if(20<=n){n=0;time[5]++; //产生秒}}uchar key_scan(){uchar i,j,key,temp;uchar code scan[]={0xfe,0xfd,0xfb,0xf7};uchar code keyb[]={0x7e,0xbe,0xde,0xee,0x7d,0xbd,0xdd,0xed,0x7b,0xbb,0xdb,0xeb,0x77,0xb7,0xd7,0xe7};for(i=0;i<4;i++){P3=scan[i];_nop_();temp=P3;if(temp!=scan[i]){for(j=0;j<16;j++){if(keyb[j]==P3){delay(50);// while(keyb[j]==P3);//松手操作// delay(20);// while(keyb[j]==P3);key=j+1;break;}if(keyb[j] != P3){key=0;}}}}return key;}bit lcd_bz()//1602检忙{bit v;rs=0;rw=1;en=1;_nop_();v=(bit)(P0&0x80);en=0;return v;}void lcd_wcmd(uchar cmd)//1602写命令{while(lcd_bz());rs=0;rw=0;en=0;_nop_();P0=cmd;_nop_();en=1;_nop_();_nop_();en=0;_nop_();rs=0;}void lcd_wdat(uchar dat)//1602写数据{while(lcd_bz());rs=1;rw=0;en=0;_nop_();P0=dat;_nop_();en=1;_nop_();;en=0;}void lcd_wstr(uchar *str)//1602写字符串{uchar i;for(i=0;str[i]!='\0';i++){lcd_wdat(str[i]);}}void lcd_pos(uchar pos)//光标定位{while(lcd_bz());lcd_wcmd(pos|0x80);}/*void lcd_cur(){switch(loca){case 0 : lcd_pos(0x46); case 1 : lcd_pos(0x49); case 2 : lcd_pos(0x05); case 3 : lcd_pos(0x08); case 4 : lcd_pos(0x0b); }}*/void lcd_rmove()//光标右移{if(1==allow){if(loca >= 0 && loca < 5) {loca++;}}}void lcd_lmove(){if(1==allow){if(loca > 0 && loca <= 5) {loca--;}}}void lcd_addtime()//调时间加{uint dat ;if(1==allow)switch(loca){case 0 :{dat=year;dat++;year=dat;delay(100);break;}case 1 :{dat=time[1];dat++;if(dat>12)dat=1;time[1]=dat;delay(100);break; }case 2 :{dat=time[2];dat++;if(dat>30)dat=1;time[2]=dat;delay(100);break; }case 3 :{dat=time[3];dat++;if(dat>24)dat=1;time[3]=dat;delay(100);break; }case 4 :{dat=time[4];dat++;if(dat>60)dat=1;time[4]=dat;delay(100);break; }case 5 :{dat=time[5];dat++;if(dat>60)dat=1;time[5]=dat;delay(100);break; }}}void lcd_detime()//调时间减{int dat ;if(1==allow)switch(loca){case 0 :{dat=year;dat--;if(dat<0)dat=2000;year=dat;delay(100);break;}case 1 :{dat=time[1];dat--;if(dat<0)dat=12;time[1]=dat;delay(100);break; }case 2 :{dat=time[2];dat--;if(dat<0)dat=30;time[2]=dat;delay(100);break; }case 3 :{dat=time[3];dat--;if(dat<0)dat=23;time[3]=dat;delay(100);break; }case 4 :{dat=time[4];dat--;if(dat<0)dat=59;time[4]=dat;delay(100);break; }case 5 :{dat=time[5];dat--;if(dat<0)dat=59;time[5]=dat;delay(100);break;}}}void function(){uchar key=key_scan();switch(key){case 5 : lcd_lmove();break;case 6 : lcd_rmove();break;case 7 : lcd_addtime();break;case 8 : lcd_detime();break;case 9 : lcd_wcmd(0x0f);allow=1;break; //显示光标case 10 : lcd_wcmd(0x0c);allow=0;break; //关闭光标}}bit year_tell() //判断是否闰年是1 否0{if((year%4 == 0 && year%100 !=0) || year%400 == 0) return 1;else return 0;}uint count1(uint year , uchar mon , uchar day)//以下count1到count3都是为了计算对应的星期{uint m;switch(mon){case 1 : m=366-day; break;case 2 : m=335-day; break;case 3 : m=306-day; break;case 4 : m=275-day; break;case 5 : m=245-day; break;case 6 : m=214-day; break;case 7 : m=184-day; break;case 8 : m=153-day; break;case 9 : m=122-day; break;case 10 : m=92-day; break;case 11 : m=61-day; break;case 12 : m=31-day; break;default : ;}if(!(year%4 == 0 && year%100 != 0 || year%400 == 0)){if(mon<=2){m=m-1;}}return(m);}uint count2(uint year , uchar mon , uchar day){uint m;if(year%4 == 0 && year%100 != 0 || year%400 == 0){m=366-count1(year , mon , day);}else{m=365-count1(year , mon , day);}return m;}uint count3(uint year1 , uint year2){uint m=0;uchar i;uint n=year2-year1;for(i=1;i<n;i++){if((year1+i)%4 == 0 && (year1+i)%100 != 0 || (year1+i)%400 == 0) {m+=366;}else{m+=365;}}return m;}uchar week_tell()//判断对应的星期{uchar w;w=(count1(1901,1,7)+count2(year,time[1],time[2])+count3(1901,year)+1)%7; if(w!=0)return w;else return 7;}void timecount()//时间计算{if(time[5]>=60) //sec{time[5]=0;time[4]++;}if(time[4]>=60)//min{time[4]=0;time[3]++;}if(time[3]>=24)//hour{time[3]=0;time[2]++; //day}switch(time[1]) //mon{case 1 : if(time[2]>=31){time[2]=0; time[1]++;}case 2 :if(1==year_tell()){if(time[2]>29){time[2]=0; time[1]++;}}else{if(time[2]>28){time[2]=0; time[1]++;}}case 3 : if(time[2]>=31){time[2]=0; time[1]++;}case 4 : if(time[2]>=30){time[2]=0; time[1]++;}case 5 : if(time[2]>=31){time[2]=0; time[1]++;}case 6 : if(time[2]>=30){time[2]=0; time[1]++;} case 7 : if(time[2]>=31){time[2]=0; time[1]++;} case 8 : if(time[2]>=31){time[2]=0; time[1]++;} case 9 : if(time[2]>=30){time[2]=0; time[1]++;} case 10 : if(time[2]>=31){time[2]=0; time[1]++;} case 11 : if(time[2]>=30){time[2]=0; time[1]++;} case 12 : if(time[2]>=31){time[2]=0; time[1]++;} }if(time[1]>12){time[1]=0;year++;}}/*void lcd_clear(){lcd_wcmd(0x01);_nop_();}*/void lcd_display(uchar p)//液晶显示{uchar i,j;uchar str_com[14];str_com[13]=year/1000;str_com[12]=(year/100)%10;str_com[11]=(year%100)/10;str_com[10]=year%10;str_com[9]=time[1]/10;str_com[8]=time[1]%10;str_com[7]=time[2]/10;str_com[6]=time[2]%10;str_com[5]=time[3]/10;str_com[4]=time[3]%10;str_com[3]=time[4]/10;str_com[2]=time[4]%10;str_com[1]=time[5]/10;str_com[0]=time[5]%10;if(0==p)//非设定状态{lcd_pos(0x07);for(i=0,j=0;i<8;i++,j++){if(2==i || 5==i){lcd_wdat(':');j--;}elselcd_wdat(str_com[j]+48);}lcd_pos(0x49);for(i=6,j=6;i<16;i++,j++){if(8==i || 11==i){lcd_wdat('-');j--;}elselcd_wdat(str_com[j]+48);}delay(1 );lcd_wcmd(0x06);lcd_pos(0x4c);switch(week_tell()){case 1 : lcd_wstr("Mon");break;case 2 : lcd_wstr("Tue");break;case 3 : lcd_wstr("Wen");break;case 4 : lcd_wstr("Thu");break;case 5 : lcd_wstr("Fri");break;case 6 : lcd_wstr("Sat");break;case 7 : lcd_wstr("Sun");break;}delay(1 );lcd_wcmd(0x04);}else if(1==p)//时间设定状态{lcd_pos(0x07);lcd_wdat(str_com[0]+48);lcd_wdat(str_com[1]+48);switch(loca) //下面是让光标定在选择位,以便光标稳定的闪烁{case 0 : lcd_pos(0x43);break; case 1 : lcd_pos(0x46);break; case 2 : lcd_pos(0x49);break; case 3 : lcd_pos(0x01);break; case 4 : lcd_pos(0x04);break; case 5 : lcd_pos(0x07);break; }}}void lcd_init()//液晶初始化{delay(15);lcd_wcmd(0x38);delay(5);lcd_wcmd(0x38);delay(5);lcd_wcmd(0x38);while(lcd_bz());lcd_wcmd(0x0e);while(lcd_bz());lcd_wcmd(0x01);}void init(){TMOD=0x11;TH0=(65536-T)/256;TL0=(65536-T)%256;TH1=T1;TL1=T1;EA=1;TR0=1;ET0=1;TR1=0;ET1=1;}main(){init();lcd_init();while(1){// delay(3);// lcd_clear();delay(1 );lcd_wcmd(0x04);time_addsec();timecount();function();lcd_display(1);cout++;if(cout>=50){cout=0;lcd_display(0);}}}//程序到此结束,估计看了有点晕,不过没关系,程序是没有错的,定时很准,经调试在几个小时之后也达到分秒不差,晶振是12M。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
长春工业大学测控技术与仪器专业单片机LCD1602显示年月日时钟带星期和闹钟,可识别闰年下载文档即可完全复制#include <reg52.h>#define uchar unsigned char#define uint unsigned intsbit lcdrs = P0^7;//液晶引脚定义sbit led_cs = P0^6;sbit lcden = P0^5;sbit boom = P3^6;sbit key1 = P3^5;sbit key2 = P3^4;sbit key3 = P3^3;sbit keyE = P3^2;ucharnum,key1num,key2num,count,hour,min,sec,day,mon,year,shi,fen,miao ,week;char ye1,ye2;uchar code cg_1602[]={ 0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02,0x0f,0x09,0x0f,0x09,0x0f,0x09,0x11,0x00,0x0f,0x09,0x09,0x0f,0x09,0x09,0x0f,0x00,0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02,};//"年月日"/*延时函数*/void delay(uint xms){uint i,j;for(i=xms;i>0;i--)for(j=114;j>0;j--);}/*1602液晶*/void write_com(uchar com)//写命令{lcdrs=0;lcden=0;P2=com;delay(5);lcden=1;delay(5);lcden=0;}void write_data(uchar date)//写数据{lcdrs=1;lcden=0;P2=date;delay(5);lcden=1;delay(5);lcden=0;}void write_by_xy(uchar x,uchar y)//坐标定位{uchar address;if(y==0)address=0x80+x;//y=0,写第一行elseaddress=0xc0+x;//y=1,写第二行write_com(address);}/*void write_char(uchar x,uchar y,uchar date)//坐标定位显示{write_by_xy(x,y);//先定位write_data(date);//后写数}*/void write_string(uchar x,uchar y,uchar *s)//写字符串{write_by_xy(x,y);//设定显示位置while(*s)//write character{P2=*s;write_data(*s);}}void write_sfm(uchar add,uchar date)//写时分秒函数{uchar hour,ge;hour=date/10;//分解一个2位数的十位和个位ge=date%10;write_com(0x80+add);//设置显示位置write_data(0x30+hour);//送去液晶显示十位write_data(0x30+ge); //送去液晶显示个位}void write_cg()//写入固定汉字和符号{write_com(0x40); //设定CGRAM地址for(num=0;num<24;num++) //将自定义字型码写入CGRAM中{write_data(cg_1602[num]);}write_com(0xc4);//年{write_data(0);write_com(0xc7);//月{write_data(1);}write_com(0xca);//日{write_data(2);}write_string(2,0,":");write_string(5,0,":");write_string(0x0a,0,":");write_string(0x0d,0,":");write_string(0x0c,1,"W");write_string(0x0d,1,"K");}void init_1602()//初始化{led_cs=0;hour=23;min=59;sec=55;key1num=0;count=0;day=28;mon=2;ye1=2 0;ye2=13;year=ye1*100+ye2;boom=0;shi=0;fen=0;miao=0;week=7;write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x01);write_string(0,1,"2013");write_string(5,1,"02");write_string(8,1,"28");write_sfm(8,shi);write_sfm(0x0b,fen);write_sfm(0x0e,miao);write_sfm(0,hour);write_sfm(3,min);write_sfm(6,sec);write_sfm(0x48,day);write_sfm(0x45,mon);write_sfm(0x40,ye1);write_sfm(0x42,ye2);write_sfm(0x4e,week);write_cg();TMOD=0x01;//设置定时器0工作模式1 TH0=(65536-50000)/256;//定时器装初值TL0=(65536-50000)%256;EA=1; //开总中断ET0=1; //开定时器0中断TR0=1; //启动定时器0}/*键盘扫描函数*/void keyscan()//按键扫描函数{//keyE =0;if(key1==0){delay(5);if(key1==0)//确认功能键被按下{key1num++;//功能键按下次数记录while(!key1);//释放确认if(key1num==1)//第一次被按下时{TR0=0; //关闭定时器write_com(0x80+7);//光标定位到秒位置write_com(0x0f); //光标开始闪烁}if(key1num==2)//第二次按下光标闪烁定位到分钟位置{write_com(0x80+4);}if(key1num==3)//第三次按下光标闪烁定位到小时位置{write_com(0x80+1);}if(key1num==4)//第四次按下光标闪烁定位到日位置{write_com(0x80+0x49);}if(key1num==5)//第五次按下光标闪烁定位到月位置{write_com(0x80+0x46);}if(key1num==6)//第六次按下光标闪烁定位到年2位置{write_com(0x80+0x43);}if(key1num==7)//第七次按下光标闪烁定位到年1位置{write_com(0x80+0x41);}if(key1num==8)//第八次按下光标闪烁定位到星期位置{write_com(0x80+0x4f);}if(key1num==9)//第九次按下{key1num=0;//记录按键数清零write_com(0x0c);//取消光标闪烁TR0=1; //启动定时器使时钟开始走}}}if(key1num!=0)//只有功能键被按下后,增加和减小键才有效{if(key2==0){delay(5);if(key2==0)//增加键确认被按下{while(!key2);//按键释放if(key1num==1)//若功能键第一次按下{sec++; //则调整秒加1if(sec==60)//若满60后将清零sec=0;write_sfm(6,sec);//每调节一次送液晶显示一下write_com(0x80+7);//显示位置重新回到调节处}if(key1num==2)//若功能键第二次按下{min++;//则调整分钟加1if(min==60)//若满60后将清零min=0;write_sfm(3,min);//每调节一次送液晶显示一下write_com(0x80+4);//显示位置重新回到调节处}if(key1num==3)//若功能键第三次按下{hour++;//则调整小时加1if(hour==24)//若满24后将清零hour=0;write_sfm(0,hour);;//每调节一次送液晶显示一下write_com(0x80+1);//显示位置重新回到调节处}if(key1num==4)//若功能键第四次按下{day++;//则调整日加1if(day>31)//若大于31后将置一day=1;write_sfm(0x48,day);//每调节一次送液晶显示一下write_com(0x80+0x48);//显示位置重新回到调节处}if(key1num==5)//若功能键第五次按下{mon++;//则调整月加1if(mon>12)//若大于12后将置一mon=1;write_sfm(0x45,mon);//每调节一次送液晶显示一下write_com(0x80+0x45);//显示位置重新回到调节处}if(key1num==6)//若功能键第六次按下{ye2++;//则调整年加1if(ye2==0x0a)//若满99后将清零ye2=0;year=ye1*100+ye2;write_sfm(0x42,ye2);//每调节一次送液晶显示一下write_com(0x80+0x42);//显示位置重新回到调节处}if(key1num==7)//若功能键第七次按下{ye1++;//则调整年加100if(ye1==0x0a)//若满99后将清零ye1=0;year=ye1*100+ye2;write_sfm(0x40,ye1);//每调节一次送液晶显示一下write_com(0x80+0x40);//显示位置重新回到调节处}if(key1num==8)//若功能键第八次按下{week++;//则调整周加一if(week>7)//若大于7后置一week=1;write_sfm(0x4f,week);//每调节一次送液晶显示一下write_com(0x80+0x4f);//显示位置重新回到调节处}}}if(key3==0){delay(5);if(key3==0)//确认减小键被按下{while(!key3);//按键释放if(key1num==1)//若功能键第一次按下{sec--;//则调整秒减1if(sec==-1)//若减到负数则将其重新设置为59sec=59;write_sfm(6,sec);//每调节一次送液晶显示一下write_com(0x80+7);//显示位置重新回到调节处}if(key1num==2)//若功能键第二次按下{min--;//则调整分钟减1if(min==-1)//若减到负数则将其重新设置为59min=59;write_sfm(3,min);//每调节一次送液晶显示一下write_com(0x80+4);//显示位置重新回到调节处}if(key1num==3)//若功能键第三次按下{hour--;//则调整小时减1if(hour==-1)//若减到负数则将其重新设置为23 hour=23;write_sfm(0,hour);//每调节一次送液晶显示一下write_com(0x80+1);//显示位置重新回到调节处}if(key1num==4)//若功能键第四次按下{day--;//则调整日减1if(day==0)//若日为零时将置一day=31;write_sfm(0x48,day);//每调节一次送液晶显示一下write_com(0x80+0x49);//显示位置重新回到调节处}if(key1num==5)//若功能键第五次按下{mon--;//则调整月减1if(mon==0)//若月为零将置一mon=12;write_sfm(0x45,mon);//每调节一次送液晶显示一下write_com(0x80+0x45);//显示位置重新回到调节处}if(key1num==6)//若功能键第六次按下{ye2--;//则调整年减1if(ye2<0)//若小于零后将设置为99ye2=99;year=ye1*100+ye2;write_sfm(0x42,ye2);//每调节一次送液晶显示一下write_com(0x80+0x42);//显示位置重新回到调节处}if(key1num==7)//若功能键第七次按下{ye1--;//则调整年减100if(ye1<0)//若小于零后将设置为99ye1=99;year=ye1*100+ye2;write_sfm(0x40,ye1);//每调节一次送液晶显示一下write_com(0x80+0x40);//显示位置重新回到调节处}if(key1num==8)//若功能键第八次按下{week--;//则调整周减一if(week==0)//若等于0后将置7week=7;write_sfm(0x4f,week);//每调节一次送液晶显示一下write_com(0x80+0x4f);//显示位置重新回到调节处}}}}if(keyE==0){delay(5);if(keyE==0)//确认功能键被按下{key2num++;//功能键按下次数记录while(!keyE);//释放确认if(key2num==1)//第一次被按下时{TR0=0; //关闭定时器write_com(0x80+0x0f);//光标定位到秒位置write_com(0x0f); //光标开始闪烁}if(key2num==2)//第二次按下光标闪烁定位到分钟位置{write_com(0x80+0x0c);}if(key2num==3)//第三次按下光标闪烁定位到小时位置{write_com(0x80+9);}if(key2num==4)//第八次按下{key2num=0;//记录按键数清零write_com(0x0c);//取消光标闪烁TR0=1; //启动定时器使时钟开始走}}}if(key2num!=0)//只有功能键被按下后,增加和减小键才有效{if(key2==0){delay(5);if(key2==0)//增加键确认被按下{while(!key2);//按键释放if(key2num==1)//若功能键第一次按下{miao++; //则调整秒加1if(miao==60)//若满60后将清零miao=0;write_sfm(0x0e,miao);//每调节一次送液晶显示一下write_com(0x80+0x0e);//显示位置重新回到调节处}if(key2num==2)//若功能键第二次按下{fen++;//则调整分钟加1if(fen==60)//若满60后将清零fen=0;write_sfm(0x0b,fen);//每调节一次送液晶显示一下write_com(0x80+0x0b);//显示位置重新回到调节处}if(key2num==3)//若功能键第三次按下{shi++;//则调整小时加1if(shi==24)//若满24后将清零shi=0;write_sfm(8,shi);;//每调节一次送液晶显示一下write_com(0x80+8);//显示位置重新回到调节处}}}if(key3==0){delay(5);if(key3==0)//确认减小键被按下{while(!key3);//按键释放if(key2num==1)//若功能键第一次按下{miao--;//则调整秒减1if(miao==-1)//若减到负数则将其重新设置为59miao=59;write_sfm(0x0e,miao);//每调节一次送液晶显示一下write_com(0x80+0x0e);//显示位置重新回到调节处}if(key2num==2)//若功能键第二次按下{fen--;//则调整分钟减1if(fen==-1)//若减到负数则将其重新设置为59fen=59;write_sfm(0x0b,fen);//每调节一次送液晶显示一下write_com(0x80+0x0b);//显示位置重新回到调节处}if(key2num==3)//若功能键第三次按下{shi--;//则调整小时减1if(shi==-1)//若减到负数则将其重新设置为23shi=23;write_sfm(8,shi);//每调节一次送液晶显示一下write_com(0x80+8);//显示位置重新回到调节处}}}}}/*主函数*/void main(){led_cs=0;init_1602();while(1){keyscan();}}/*中断函数*/void timer0() interrupt 1//定时器0中断服务程序{TH0=(65536-50000)/256;//再次装定时器初值TL0=(65536-50000)%256;count++; //中断次数累加if(count==20) //20次50毫秒为1秒{count=0;sec++;if(sec==60)//秒加到60则进位分钟{sec=0;//同时秒数清零min++;if(min==60)//分钟加到60则进位小时{min=0;//同时分钟数清零hour++;//boom=1;//delay(5);//boom=0;if(hour==24)//小时加到24则小时清零{hour=0;day++;week++;if(week>7){week=1;}if(mon==1){if(day>31)day=1;mon++;}}if(mon==2){if((year%4==0 && year%100!=0)||year%4==0) {if(day>29){day=1;mon++;}}else if(day>28){day=1;mon++;}}if(mon==3)if(day>31) {day=1; mon++;}}if(mon==4) {if(day>30) {day=1; mon++;}}if(mon==5) {if(day>31) {day=1; mon++;}if(mon==6) {if(day>30) {day=1; mon++;}}if(mon==7) {if(day>31) {day=1; mon++;}}if(mon==8) {if(day>31) {day=1;}}if(mon==9) {if(day>30) {day=1; mon++;}}if(mon==10) {if(day>31) {day=1; mon++;}}if(mon==11) {if(day>30) {mon++;}}if(mon==12){if(day>31){day=1;mon=1;ye2++;}}}write_sfm(0x4e,week);write_sfm(0x48,day);write_sfm(0x45,mon);write_sfm(0x40,ye1);write_sfm(0x42,ye2);}write_sfm(0,hour);//小时若变化则重新写入}write_sfm(3,min);//分钟若变化则重新写入}write_sfm(6,sec); //秒若变化则重新写入if((hour==shi && min==fen) && sec==miao) {boom=1;delay(5);boom=0;}}。