#includereg51.h#includeintrins.h#defineucharunsignedchar#defineuintunsignedintucharcount_10ms;//定义10ms计数器sbitK1=P3^2;//定义K1键sbitK2=P3^3;//定义K2键sbitK3=P3^4;//定义K3键sbitK4=P3^5;//定义K4键sbitBEEP=P3^7;//定义蜂鸣器sbitreset=P1^2;sbitsclk=P1^0;sbitio=P1^1;sbitLCD_RS=P2^0;sbitLCD_RW=P2^1;sbitLCD_EN=P2^2;bitK1_FLAG=0;//定义按键标志位,当按下K1键时,该位置1,K1键未按下时,该位为0。ucharcodeline1_data[]={---LCDClcok---};//定义第1行显示的字符ucharcodeline2_data[]={****};//定义第2行显示的字符uchardisp_buf[8]={0x00};//定义显示缓冲区uchartime_buf[7]={0,0,0x12,0,0,0,0};//DS1302时间缓冲区,存放秒、分、时、日、月、星期、年uchartemp[2]={0};//用来存放设置时的小时、分钟的中间值/********以下是函数声明********/voidDelay_ms(uintxms);bitlcd_busy();voidlcd_wcmd(ucharcmd);voidlcd_wdat(uchardat);voidlcd_clr();voidlcd_init();voidwrite_byte(ucharinbyte);//写一字节数据函数声明ucharread_byte();//读一字节数据函数声明voidwrite_ds1302(ucharcmd,ucharindata);//写DS1302函数声明ucharread_ds1302(ucharaddr);//读DS1302函数声明voidset_ds1302(ucharaddr,uchar*p,ucharn);//设置DS1302初始时间函数声明voidget_ds1302(ucharaddr,uchar*p,ucharn);//读当前时间函数声明voidinit_ds1302();//DS1302初始化函数声明/********以下是延时函数********/voidDelay_ms(uintxms){uinti,j;for(i=xms;i0;i--)//i=xms即延时约xms毫秒for(j=110;j0;j--);}/********以下是LCD忙碌检查函数********/bitlcd_busy(){bitresult;LCD_RS=0;LCD_RW=1;LCD_EN=1;_nop_();_nop_();_nop_();_nop_();result=(bit)(P0&0x80);LCD_EN=0;returnresult;}/********以下是写指令寄存器IR函数********/voidlcd_wcmd(ucharcmd){while(lcd_busy());LCD_RS=0;LCD_RW=0;LCD_EN=0;_nop_();_nop_();P0=cmd;_nop_();_nop_();_nop_();_nop_();LCD_EN=1;_nop_();_nop_();_nop_();_nop_();LCD_EN=0;}/********以下是写寄存器DR函数********/voidlcd_wdat(uchardat){while(lcd_busy());LCD_RS=1;LCD_RW=0;LCD_EN=0;P0=dat;_nop_();_nop_();_nop_();_nop_();LCD_EN=1;_nop_();_nop_();_nop_();_nop_();LCD_EN=0;}/********以下是LCD清屏函数********/voidlcd_clr(){lcd_wcmd(0x01);//清除LCD的显示内容Delay_ms(5);}/********以下是LCD初始化函数********/voidlcd_init(){Delay_ms(15);//等待LCD电源稳定lcd_wcmd(0x38);//16*2显示,5*7点阵,8位数据Delay_ms(5);lcd_wcmd(0x38);Delay_ms(5);lcd_wcmd(0x38);Delay_ms(5);lcd_wcmd(0x0c);//显示开,关光标Delay_ms(5);lcd_wcmd(0x06);//移动光标Delay_ms(5);lcd_wcmd(0x01);//清除LCD的显示内容Delay_ms(5);}/********以下是写一字节数据函数********/voidwrite_byte(ucharinbyte){uchari;for(i=0;i8;i++){sclk=0;//写时低电平改变数据if(inbyte&0x01)io=1;elseio=0;sclk=1;//高电平把数据写入DS1302_nop_();inbyte=inbyte1;}}/********以下是读一字节数据函数********/ucharread_byte(){uchari,temp=0;io=1;for(i=0;i7;i++){sclk=0;if(io==1)temp=temp|0x80;elsetemp=temp&0x7f;sclk=1;//产生下跳沿temp=temp1;}return(temp);}/********写DS1302函数,往DS1302的某个地址写入数据********/voidwrite_ds1302(ucharcmd,ucharindata){sclk=0;reset=1;write_byte(cmd);write_byte(indata);sclk=0;reset=0;}/********读DS1302函数,读DS1302某地址的的数据********/ucharread_ds1302(ucharaddr){ucharbackdata;sclk=0;reset=1;write_byte(addr);//先写地址backdata=read_byte();//然后读数据sclk=0;reset=0;return(backdata);}/********设置初始时间函数********voidset_ds1302(ucharaddr,uchar*p,ucharn){write_ds1302(0x8e,0x00);//写控制字,允许写操作for(;n0;n--){write_ds1302(addr,*p);p++;addr=addr+2;}write_ds1302(0x8e,0x80);//写保护,不允许写}********读取当前时间函数********voidget_ds1302(ucharaddr,uchar*p,ucharn){for(;n0;n--){*p=read_ds1302(addr);p++;addr=addr+2;}}********初始化DS1302函数********/voidinit_ds1302(){reset=0;sclk=0;write_ds1302(0x80,0x00);//写秒寄存器write_ds1302(0x90,0xab);//写充电器write_ds1302(0x8e,0x80);//写保护控制字,禁止写}/*********以下是蜂鸣器响一声函数********/voidbeep(){BEEP=0;//蜂鸣器响Delay_ms(100);BEEP=1;//关闭蜂鸣器Delay_ms(100);}/********以下是转换函数,负责将走时数据转换为适合LCD显示的数据********/voidLCD_conv(ucharin1,in2,in3)//形参in1、in2、in3接收实参time_buf[2]、time_buf[1]、time_buf[0]传来的小时、分钟、秒数据{disp_buf[0]=in1/10+0x30;//小时十位数据disp_buf[1]=in1%10+0x30;//小时个位数据disp_buf[2]=in2/10+0x30;//分钟十位数据disp_buf[3]=in2%10+0x30;//分钟个位数据disp_buf[4]=in3/10+0x30;//秒十位数据disp_buf[5]=in3%10+0x30;//秒个位数据}/********以下是LCD显示函数,负责将函数LCD_conv转换后的数据显示在LCD上********/voidLCD_disp(){lcd_wcmd(0x44|0x80);//从第2行第4列开始显示lcd_wdat(disp_buf[0]);//显示小时十位lcd_wdat(disp_buf[1]);//显示小时个位lcd_wdat(0x3a);//显示':'lcd_wdat(disp_buf[2]);//显示分钟十位lcd_wdat(disp_buf[3]);//显示分钟个位lcd_wdat(0x3a);//显示':'lcd_wdat(disp_buf[4]);//显示秒十位lcd_wdat(disp_buf[5]);//显示秒个位}/********以下是按键处理函数********/voidKeyProcess(){ucharmin16,hour16;//定义16进制的分钟和小时变量write_ds1302(0x8e,0x00);//DS1302写保护控制字,允许写write_ds1302(0x80,0x80);//时钟停止运行if(K2==0)//K2键用来对小时进行加1调整{Delay_ms(10);//延时去抖if(K2==0){while(!K2);//等待K2键释放beep();time_buf[2]=time_buf[2]+1;//小时加1if(time_buf[2]==24)time_buf[2]=0;//当变成24时初始化为0hour16=time_buf[2]/10*16+time_buf[2]%10;//将所得的小时数据转变成16进制数据write_ds1302(0x84,hour16);//将调整后的小时数据写入DS1302}}if(K3==0)//K3键用来对分钟进行加1调整{Delay_ms(10);//延时去抖if(K3==0){while(!K3);//等待K3键释放beep();time_buf[1]=time_buf[1]+1;//分钟加1if(time_buf[1]==60)time_buf[1]=0;//当分钟加到60时初始化为0min16=time_buf[1]/10*16+time_buf[1]%10;//将所得的分钟数据转变成16进制数据write_ds1302(0x82,min16);//将调整后的分钟数据写入DS1302}}if(K4==0)//K4键是确认键{Delay_ms(10);//延时去抖if(K4==0){while(!K4);//等待K4键释放beep();write_ds1302(0x80,0x00);//调整完毕后,启动时钟运行write_ds1302(0x8e,0x80);//写保护控制字,禁止写K1_FLAG=0;//将K1键按下标志位清0}}}/********以下是读取时间函数,负责读取当前的时间,并将读取到的时间转换为10进制数********/voidget_time(){ucharsec,min,hour;//定义秒、分和小时变量write_ds1302(0x8e,0x00);//控制命令,WP=0,允许写操作write_ds1302(0x90,0xab);//涓流充电控制sec=read_ds1302(0x81);//读取秒min