51单片机程序 1602显示日期时间可调汉字
基于51单片机的1602日历时钟程序
![基于51单片机的1602日历时钟程序](https://img.taocdn.com/s3/m/08666e1c6bd97f192279e972.png)
if(y == 0)
x |= 0x40 ; //如果显示是在第二行,则x的值加0x40
x |= 0x80 ; //获得x的值
LCD1602_write_cmd(x) ;//写入坐标值到LCD
}
}
/************************************************************
case 3 : sele_count = 3 ; break ;
default : break ;
}
return(self_cou***************************************************
蜂鸣器
************************************************************/
void delay_ms(uint16 count) // 延时时间count*1ms
{ uint16 i;
for(;count>0;count--)
LCD1602_DATA = dat ;
LCD1602_EN = 1 ;
LCD1602_EN = 0 ;
}
/***********************************************************
1602初始化
************************************************************/
uint8 LCD1602_display_self(uint8 count)
51单片机,DS1302时钟,1602显示,可调时钟剖析
![51单片机,DS1302时钟,1602显示,可调时钟剖析](https://img.taocdn.com/s3/m/8d1013517fd5360cba1adbd7.png)
基于proteus的51单片机仿真实例八十一、实时时钟芯片DS1302应用实例1、DS1302引脚排列:如下图引脚说明:1)Vcc1:后备电源,VCC2:主电源。
在主电源关闭的情况下,也能保持时钟的连续运行。
DS1302由Vcc1或Vcc2两者中的较大者供电。
当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。
当Vcc2小于Vcc1时,DS1302由Vcc1供电。
2)X1、X2:振荡源,外接32.768kHz 晶振。
3)RST:复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。
RST输入有两种功能:首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据的传送手段。
当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。
如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。
上电运行时,在Vcc>2.0V之前,RST必须保持低电平。
只有在SCLK为低电平时,才能将RST置为高电平。
4)I/O为串行数据输入输出端(双向)。
5)SCLK为时钟输入端。
2、DS1302的控制字节DS1302 的控制字如下图所示。
控制字节的最高有效位(位7)必须是逻辑1,如果它为0,则不能把数据写入DS1302中,位6如果为0,则表示存取日历时钟数据,为1表示存取RAM数据;位5至位1指示操作单元的地址;最低有效位(位0)如为0表示要进行写操作,为1表示进行读操作,控制字节总是从最低位开始输出。
3、数据输入输出(I/O)在控制指令字输入后的下一个SCLK时钟的上升沿时,数据被写入DS1302,数据输入从低位即位0开始。
同样,在紧跟8位的控制指令字后的下一个SCLK脉冲的下降沿读出DS1302的数据,读出数据时从低位0位到高位7。
DS1302的寄存器DS1302有12个寄存器,其中有7个寄存器与日历、时钟相关,存放的数据位为BCD码形式,其日历、时间寄存器及其控制字见数据手册。
51单片机万年历1602显示时间温度按键调时(焊接前备份)
![51单片机万年历1602显示时间温度按键调时(焊接前备份)](https://img.taocdn.com/s3/m/604ba47b8e9951e79b892740.png)
}
if(hmin_fen==6)
{
hmin_fen=0;
//nmin_shi++;
}
ZuiZhong[13]=l_tmpdate[1]%16+0x30;
ZuiZhong[14]=':';
ZuiZhong[15]=l_tmpdate[0]/16+0x30;
ZuiZhong[16]=l_tmpdate[0]%16+0x30;
ZuiZhong[17]=' ';
/* ZuiZhong[18]=Temperature%1000/100+0x30;
ZuiZhong[19]=Temperature%100/10+0x30;
ZuiZhong[20]=Temperature%10+0x30;
ZuiZhong[21]=0xdf;
ZuiZhong[22]='C'; */
write_lcd1602(0x80+0x43,0); // 20
for(i=23;i<=24;i++)
write_lcd1602( ZuiZhong[i], 1 );
if(K1==0)
#include <reg52.h>
#include<intrins.h>
#define uchar unsigned char
#define uint unsigned int
sbit rs=P2^6; // 【1602显示引脚定义】
sbit rw=P2^5; //【【【【【7-6-5顺序
单片机用C51实现时间、星期、年月、温度在DS1602上显示的多功能数字钟
![单片机用C51实现时间、星期、年月、温度在DS1602上显示的多功能数字钟](https://img.taocdn.com/s3/m/245abe160b4e767f5acfce1d.png)
//***************************************************************************** //******用DS1602实现可调日期,时间,星期及温度实时监测的实用数字钟功能******* //*****************创建日期:2010-1-7***********************//功能介绍:用3*3按键在DS1602上显示第一排显示"2010-01-05 MON"第二排显示"23:59:00"//*******************功能介绍**************************************//********* K6:adjtime K3:hour K2:minute K1:OK*******************//********* K3:adjalarm K3:hh K1:OK**********************//********* K2:lookalarm K1:OK **********************//********* K1:alarm ON/OFF ***********************//********* K5:adjdate (K9:month)K8:day (K7:week)K4:OK*********//***********************************************************************#include "main.h"void lcd_data(unsigned char dat);//DS1602数据写入unsigned char kbscan();//按键扫描void ds1602();//DS1602初始化void lcd_com(unsigned char com);//DS1602命令写入void timer0();//用于延时的定时中断初始2mSvoid disp();//主程序的显示调用void display();//正常的显示void display_alarm();//查看闹铃void alarm();//闹铃void process();//按键的处理unsigned char hands();//与18B20通信握手void write_temp_date(unsigned char dat);//写温度数据18B20unsigned char read_temp_date();//读温度数据18B20void tmpdelay(unsigned char tmp);//ds18b20对时序要求严格unsigned char result();//计算月份的天数//*******************************//DS1602命令的写入//*******************************void lcd_com(unsigned char com){rs=0;rw=0;P0=com;dema=1;while(dema!=0);en=1;dema=1;while(dema!=0);en=0;}//*********************//DS1602数据的写入//*********************void lcd_data(unsigned char dat){rs=1;rw=0;P0=dat;dema=1;while(dema!=0);en=1;dema=1;while(dema!=0);en=0;}//***************************//3*3按键的扫描//***************************unsigned char kbscan(){unsigned char sccode,recode,tenp;P1=0XF8;tenp=P1;if(tenp!=0xf8){demb=3;while(demb!=0);if(tenp==P1){sccode=0xfe;while((sccode&0xf7)!=0){P1=sccode;if((P1&0xf8)!=0xf8){recode=P1&0Xf8;sccode=sccode&0xc7;return(recode|sccode);}elsesccode=sccode<<1|0x01;}}}return(0);}//**************************//*********每月的天数计算***//**************************unsigned char result(){switch(month){case 1:return 31;break;case 3:return 31;break;case 5:return 31;break;case 7:return 31;break;case 8:return 31;break;case 10:return 31;break;case 12:return 31;break;case 4:return 30;break;case 6:return 30;break;case 9:return 30;break;case 11:return 30;break;case 2:if(year%4==0){return 29;//闰年29天}else{return 28;//平年28天}}}//**************************//*********DS1602的初始化***//**************************void ds1602(){lcd_com(0x38);//16*2显示5*7矩阵dema=1;while(dema!=0);lcd_com(0x0c);//显示开,无光标无闪烁dema=1;while(dema!=0);lcd_com(0x06);//指针+1,整屏不动dema=1;while(dema!=0);lcd_com(0x01);//清屏}//*******************************//定时中断延时的初始化以及中断***//*******************************void timer0(){TMOD=0X01;TH0=0Xf8;TL0=0X30; //2mS初值12M晶振TR0=1;ET0=1;EA=1;}TIME0() interrupt 1{TR0=0;TH0=0Xf8;TL0=0X30; //2mS初值TR0=1;count++;if(count>=500)//1s{count=0;second++;if(second>=60)//1m{second=0;minute++;if(minute>=60)//1h{minute=0;hour++;if(hour>=24)//1day{hour=0;flag_week++;//星期调整if(flag_week>8){flag_week=1;}day++;if(day>(days=result()))//1month{day=1;month++;if(month>12)//1year{month=1;year++;if(year>100){year=0;}}}}}}}if(dema)dema--;//写命令的延时if(demb)demb--;//按键的延时//************闹铃**********if(demc){demc--;}if(demd){demd--;}flag++;if(flag>=200){flag=0;temp=1;deme++;if(deme>=2){demc=0;temp=0;}}}//**************************//正常日期时间显示//**************************void display(){a=hour/10;b=hour%10;c=minute/10;d=minute%10;e=second/10;f=second%10;m3=year/10;m4=year%10;m6=month/10;m7=month%10;m9=day/10;m10=day%10;//*****第一排显示**********lcd_com(0x81);//第一排从第2个位置开始显示lcd_data(0x32);lcd_com(0x82);lcd_data(0x30);lcd_com(0x83);lcd_data(0x30+m3);lcd_com(0x84);lcd_data(0x30+m4);lcd_com(0x85);lcd_data(0x2d);//"-"lcd_com(0x86);lcd_data(0x30+m6);lcd_com(0x87);lcd_data(0x30+m7);lcd_com(0x88);lcd_data(0x2d);//"-"lcd_com(0x89);lcd_data(0x30+m9);lcd_com(0x8a);lcd_data(0x30+m10);if(flag_week==1)//周1{lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week1[n]);}}else if(flag_week==2)//周2 {lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week2[n]);}}else if(flag_week==3)//周3 {lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week3[n]);}}else if(flag_week==4)//周4 {lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week4[n]);}}else if(flag_week==5)//周5 {lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week5[n]);}}else if(flag_week==6)//周6 {lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week6[n]);}}else if(flag_week==7)//周7{lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week7[n]);}}//*****第二排显示***********lcd_com(0xc1);//第二排从第3个位置开始显示lcd_data(0x30+a);lcd_com(0xc2);lcd_data(0x30+b);lcd_com(0xc3);lcd_data(0x3a);//":"lcd_com(0xc4);lcd_data(0x30+c);lcd_com(0xc5);lcd_data(0x30+d);lcd_com(0xc6);lcd_data(0x3a);//":"lcd_com(0xc7);lcd_data(0x30+e);lcd_com(0xc8);lcd_data(0x30+f);lcd_com(0xca);lcd_data(0x47);//"G"lcd_com(0xcb);lcd_data(0x47);//"G"lcd_com(0xcd);all_date=all_date%100;lcd_data(match[all_date/10]);//十位lcd_com(0xce);lcd_data(match[all_date%10]);//个位lcd_com(0xcf);lcd_data('C');//"temperapure" "C"}//********************************************** //*************************看闹钟*************** void display_alarm(){a=hh/10;b=hh%10;c=min/10;d=min%10;e=sec/10;f=sec%10;m3=year/10;m4=year%10;m6=month/10;m7=month%10;m9=day/10;m10=day%10;//*****第一排显示**********lcd_com(0x81);//第一排从第2个位置开始显示lcd_data(0x32);lcd_com(0x82);lcd_data(0x30);lcd_com(0x83);lcd_data(0x30+m3);lcd_com(0x84);lcd_data(0x30+m4);lcd_com(0x85);lcd_data(0x2d);//"-"lcd_com(0x86);lcd_data(0x30+m6);lcd_com(0x87);lcd_data(0x30+m7);lcd_com(0x88);lcd_data(0x2d);//"-"lcd_com(0x89);lcd_data(0x30+m9);lcd_com(0x8a);lcd_data(0x30+m10);if(flag_week==1)//周1{lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week1[n]);}}else if(flag_week==2)//周2{lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week2[n]);}}else if(flag_week==3)//周3 {lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week3[n]);}}else if(flag_week==4)//周4 {lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week4[n]);}}else if(flag_week==5)//周5 {lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week5[n]);}}else if(flag_week==6)//周6 {lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week6[n]);}}else if(flag_week==7)//周7 {lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week7[n]);}}//****第二排**************lcd_com(0xc1);//第二排从第3个位置开始显示lcd_data(0x30+a);lcd_com(0xc2);lcd_data(0x30+b);lcd_com(0xc3);lcd_data(0x3a);//":"lcd_com(0xc4);lcd_data(0x30+c);lcd_com(0xc5);lcd_data(0x30+d);lcd_com(0xc6);lcd_data(0x3a);//":"lcd_com(0xc7);lcd_data(0x30+e);lcd_com(0xc8);lcd_data(0x30+f);lcd_com(0xcd);all_date=all_date%100;lcd_data(match[all_date/10]);//十位lcd_com(0xce);lcd_data(match[all_date%10]);//个位lcd_com(0xcf);lcd_data('C');//"temperapure" "C"}//**********************//闹钟开的显示**********//**********************void display_onalarm(){a=hour/10;b=hour%10;c=minute/10;d=minute%10;e=second/10;f=second%10;m3=year/10;m4=year%10;m6=month/10;m7=month%10;m9=day/10;m10=day%10;//*****第一排显示**********lcd_com(0x81);//第一排从第2个位置开始显示lcd_data(0x32);lcd_com(0x82);lcd_data(0x30);lcd_com(0x83);lcd_data(0x30+m3);lcd_com(0x84);lcd_data(0x30+m4);lcd_com(0x85);lcd_data(0x2d);//"-"lcd_com(0x86);lcd_data(0x30+m6);lcd_com(0x87);lcd_data(0x30+m7);lcd_com(0x88);lcd_data(0x2d);//"-"lcd_com(0x89);lcd_data(0x30+m9);lcd_com(0x8a);lcd_data(0x30+m10);if(flag_week==1)//周1{lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week1[n]);}}else if(flag_week==2)//周2{lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week2[n]);}}else if(flag_week==3)//周3{lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week3[n]);}}else if(flag_week==4)//周4{lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week4[n]);}}else if(flag_week==5)//周5{lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week5[n]);}}else if(flag_week==6)//周6{lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week6[n]);}}else if(flag_week==7)//周7{lcd_com(0x8c);for(n=0;n<3;n++){lcd_data(week7[n]);}}//****第二排**************lcd_com(0xc1);//第二排从第3个位置开始显示lcd_data(0x30+a);lcd_com(0xc2);lcd_data(0x30+b);lcd_com(0xc3);lcd_data(0x3a);//":"lcd_com(0xc4);lcd_data(0x30+c);lcd_com(0xc5);lcd_data(0x30+d);lcd_com(0xc6);lcd_data(0x3a);//":"lcd_com(0xc7);lcd_data(0x30+e);lcd_com(0xc8);lcd_data(0x30+f);lcd_com(0xca);lcd_data(0x4B);//"K"lcd_com(0xcb);lcd_data(0x4B);//"K"lcd_com(0xcd);all_date=all_date%100;lcd_data(match[all_date/10]);//十位lcd_com(0xce);lcd_data(match[all_date%10]);//个位lcd_com(0xcf);lcd_data('C');//"temperapure" "C" }//*****************************//*******按键的处理************//***************************** void process(){if(key!=0){if(key==K6){display();while((key=kbscan())!=K1){display();if((key=kbscan())==K3){hour++;if(hour>=24){hour=0;}}if((key=kbscan())==K2){minute++;if(minute>=60){minute=0;}}}}else if(key==K2)//看闹铃{while(((key=kbscan())!=K1)){display_alarm();}}else if(key==K3)//调闹铃{display_alarm();while((key=kbscan())!=K1){display_alarm();if((key=kbscan())==K3){hh++;if(hh>=24){hh=0;}}if((key=kbscan())==K2){min++;if(min>=60){min=0;}}}}else if(key==K1)//开/关闹钟{flag_alarm=~flag_alarm; }else if(key==K5)//调日期星期{display();while((key=kbscan())!=K4)//ok{display();// if((key=kbscan())==K9)//month // {// month++;// if(month>12)// {// month=1;// }// }if((key=kbscan())==K8)//day{day++;flag_week++;if(flag_week>7){flag_week=1;}if(day>(days=result())){day=1;month++;if(month>12){month=1;year++;if(year>100){year=0;}}}// if((key=kbscan())==K7)//week // {// flag_week++;// if(flag_week>8)// {// flag_week=1;// }// }}}}}}//*************************************//*****************闹铃****************//*************************************void alarm(){if(flag_offalarm==1){if(flag_alarm==1){if(temp){TR0=0;TH0=0Xf8;TL0=0X30;TR0=1; //重装初值2mSdemd=2;while(demd!=0);//P37=~P37;}else{TR0=0;TH0=0XF8;TL0=0X30;TR0=1; //重装初值demc=1;while(demc!=0);//P37=~P37;}}else{P37=1;flag_offalarm=0;}}elseif((flag_alarm==1)&&(minute==min)&&(hour==hh)) {flag_offalarm=1;if(temp){TR0=0;TH0=0Xf8;TL0=0X30;TR0=1; //重装初值2mSdemd=2;while(demd!=0);//P37=~P37;}else{TR0=0;TH0=0XF8;TL0=0X30;TR0=1; //重装初值demc=1;while(demc!=0);//P37=~P37;}}}//**********************************//***********DS18B20时序控制*********** //**********************************void tmpdelay(unsigned char tmp)//注意!!{while(tmp>0){tmp--;}}//*tmdelay(1) ;//16.28us//增加一个就加6.5us // tmdelay(2) ;//22.78us// tmdelay(3) ;//29.30us// tmdelay(4) ;//35.81us// tmdelay(70) ;//465.49// tmdelay(74) ;//491.54// tmdelay(80) ;//530.60// tmdelay(115) ;//150us *//*例如16.28+(?*6.5)=490*///********************************//**************************************//**********DS18B20读取温度***********//*************************************unsigned char read_temp_date()//读温度数据18B20{unsigned char i;unsigned int y=0;value=0;for(i=8;i>0;i--){value>>=1;DQ=0;// tmpdelay(1);//>15usy++;y++;y++;y++;//1-15usDQ=1;// tmpdelay(1);//读温度对时序要求严格不能用tmpdelay(1)代替y++;if(DQ==1){value=value|0x80;}else{}tmpdelay(16);//120US}return (value);}//**************************************//**********DS18B20写指令温度***********//*************************************void write_temp_date(unsigned char dat)//写温度指令18B20{unsigned char i;for(i=8;i>0;i--){DQ=0;tmpdelay(1);//>15usif((dat&0x01)==1){DQ=1;tmpdelay(16);//120us}else{DQ=0;tmpdelay(16);//120usDQ=1;tmpdelay(1);//>15us}dat=dat>>1;}DQ=1;tmpdelay(1);//>15us}//**************************************//**********DS18B20复位*****************//*************************************unsigned char hands()//握手复位{temp=0;// noanswer:do{DQ=0;tmpdelay(72);//490uSDQ=1;tmpdelay(11);/*>60uS 注意:此处把函数名改为hans()后,这里两处的tmpdelay()括号内最好改成74和12*/}while(DQ!=0);temp=1;tmpdelay(35);//>240usDQ=1;return(temp);//此处可以采用两种方式表达,1用直到...才;2用goto转向// if(DQ==1)// {// goto noanswer;// }// else if(DQ==0)// {// temp=1;// tmpdelay(40);//>250uS// DQ=1;// }// return(temp);}void disp(){if(flag_alarm){display_onalarm();}else{display();}}//***********************//*******主程序**********//***********************main(void){timer0();//中断延时初始化ds1602();//初始化while(1){key=kbscan();//调用按键process();//按键处理alarm();//闹零if(hands()==1){write_temp_date(0xcc);//跳过write_temp_date(0x44);//温度转换tmpdelay(75);//500us// dema=250;// while(dema!=0);//500ms}if(hands()==1){write_temp_date(0xcc);//跳过write_temp_date(0xbe);//读取温度数据tmpdelay(75);//500us// dema=250;// while(dema!=0);//500ms}date_l=read_temp_date();//读取低位温度date_h=read_temp_date();//读取高位温度all_date=((date_h<<4)|(date_l>>4));// 整数位// dot_date=date_l&0x0f;// dot_date=dot_date*625;//小数位// all_date=all_date+dot_date/10000;disp();//显示}}。
TX-1C1602液晶显示时间年月日可调
![TX-1C1602液晶显示时间年月日可调](https://img.taocdn.com/s3/m/fcb77b6f9b6648d7c1c74677.png)
#include<reg52.h>#define uchar unsigned char#define uint unsigned intsbit dula=P2^6;sbit wela=P2^7;sbit rs=P3^5;sbit lcden=P3^4;sbit s1=P3^0;sbit s2=P3^1;sbit s3=P3^2;sbit rd=P3^7;uchar s1num;uint count;char miao,shi,fen,tian,yue,xqi,x,nian; uchar code table[]=" 2013-01-01 1 "; uchar code table1[]=" 12:00:00"; void delay(uchar z){uchar x,j;for(x=z;x>0;x--)for(j=110;j>0;j--);}void write_com(uchar com)//写指令{rs=0;lcden=0;P0=com;delay(5);lcden=1;delay(5);lcden=0;}void write_date(uchar date)//写数据{rs=1;lcden=0;P0=date;delay(5);lcden=1;delay(5);lcden=0;}void init() // 初始化{uchar num;dula=0;wela=0;lcden=0;write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x01);write_com(0x80);for(num=0;num<17;num++){write_date(table[num]);delay(10);}write_com(0x80+0x40);for(num=0;num<10;num++)write_date(table1[num]);delay(10);TMOD=0X02; //设定时器0为工作方式2 TH0=0x06; //初值为12Mhe0.25msTL0=0x06;EA=1;ET0=1;TR0=1;nian=13;yue=1;tian=1;xqi=1;shi=12;}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_sfm1(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 write_sfm2(uchar add,uchar xqi) //定位显示星期{write_com(0x80+add);write_date(0x30+xqi); //0x30的意思是数据从码表中0开始}void keyscan() //键盘扫描{rd=0;if(s1==0){delay(5);if(s1==0);{s1num++;while(!s1);if(s1num==1){TR0=0;write_com(0x80+0x40+11);write_com(0x0f);}if(s1num==2){write_com(0x80+0x40+8);}if(s1num==3){write_com(0x80+0x40+5);}if(s1num==4){write_com(0x80+12);}if(s1num==5){write_com(0x80+9);}if(s1num==6){write_com(0x80+6);}if(s1num==7){write_com(0x80+14);}if(s1num==8){s1num=0;write_com(0x0c);TR0=1;}}}if(s1num!=0){if(s2==0){delay(5);if(s2==0){while(!s2);if(s1num==1){miao++;if(miao==60)miao=0;write_sfm(10,miao);write_com(0x80+0x40+11);}if(s1num==2){fen++;if(fen==60)fen=0;write_sfm(7,fen);write_com(0x80+0x40+8);}if(s1num==3){shi++;if(shi==24)shi=0;write_sfm(4,shi);write_com(0x80+0x40+5);}if(s1num==4){tian++;if(tian==31)tian=1;write_sfm1(11,tian);write_com(0x80+12);}if(s1num==5){yue++;if(yue>=13)yue=1;write_sfm1(8,yue);write_com(0x80+9);}if(s1num==6){nian++;if(nian>=99)nian=1;write_sfm1(5,nian);write_com(0x80+6);}if(s1num==7){xqi++;if(xqi>=8)xqi=1;write_sfm2(14,xqi);write_com(0x80+14);}}}if(s3==0){delay(5);if(s3==0){while(!s3);if(s1num==1){miao--;if(miao==-1)miao=59;write_com(0x80+0x40+10);write_sfm(10,miao);}if(s1num==2){fen--;if(fen==-1)fen=59;write_sfm(7,fen);write_com(0x80+0x40+8);}if(s1num==3){shi--;if(shi==-1)shi=23;write_sfm(4,shi);write_com(0x80+0x40+4);}if(s1num==4){tian--;if(tian==-1)tian=31;write_sfm1(11,tian);write_com(0x80+11);}if(s1num==5){yue--;if(yue==0)yue=12;write_sfm1(8,yue);write_com(0x80+9);}if(s1num==6){nian--;if(nian==0)nian=99;write_sfm1(5,nian);write_com(0x80+6);}}}}}char tianshu() //以月份来判断天数{switch (yue){case 1:x=32;break;case 2:if( ((0 == nian%4)&&(0 != nian%10)) ||(0 == nian %40) )//判断平年或闰年x=30;else x=29;break;case 3:x=32;break;case 4:x=31;break;case 5:x=32;break;case 6:x=31;break;case 7:x=32;break;case 8:x=31;break;case 9:x=31;break;case 10:x=32;break;case 11:x=31;break;case 12:x=32;break;}return x;}void main() //主函数{init();while(1){keyscan();}}void t0()interrupt 1 //to定时器{count++;if(count==4000){count=0;miao++;if(miao>=60){miao=0;fen++;if(fen>=60){fen=0;shi++;if(shi==24){shi=0;tian++;if(tian>=(tianshu())){ tian=1;yue++;if(yue>=13){yue=1;nian++;write_sfm1(5,nian);}write_sfm1(8,yue);}xqi++;if(xqi>=8)xqi=1;write_sfm2(14,xqi);write_sfm1(11,tian);}write_sfm(4,shi) ;}write_sfm(7,fen) ;}write_sfm(10,miao) ;}}。
LCD1602液晶显示带汉字的万年历程序51单片机
![LCD1602液晶显示带汉字的万年历程序51单片机](https://img.taocdn.com/s3/m/49035f320740be1e650e9a37.png)
LCD1602液晶显示带汉字的万年历程序(51单片机)#include "reg51.h"#define uint unsigned int#define uchar unsigned char#define port P0uchar table[]="I love you!"; uchar table1[]="Shang Hong Rui!";uchar table2[]="LI ZHEN WEI!" ;uchar table3[]=">; >; >; >; >; >; >; >; "; uchar num;sbit rs=P2^0;sbit rw=P2^1;sbit e=P2^2;/********************************************1ms 为基本单位的延时函数********************************************/ void delay(uint z){uint x,y;for(x=z;x>;0;x--)for(y=110;y>;0;y--);}/******************************************** 读取lcd1602状态********************************************/ read(){uchar temp ;port=0xff;rs=0;rw=1;e=1;temp=port;e=0;return temp;}/******************************************** 检测lcd是否忙碌小卒整天没事********************************************/ void busy(){uchar temp;do{temp=read();}while((temp&0x80)==0x80);}/********************************************向 lcd 里写命令********************************************/ void write_com(uchar com){busy();//delay(2);port=com;//busy();rs=0;rw=0;e=1;e=0;}/******************************************** 向 lcd 里写数据********************************************/ void write_data(uchar dat){busy();//delay(2);port=dat;//busy();rs=1;rw=0;e=1;e=0;}/******************************************** 初始化lcd********************************************/ void init(){write_com(0x06) ;//显示地址递增,即写一个数据后,显示位置右移一位write_com(0x0e) ;//开显示,有光标,光标不闪write_com(0x38) ;//8位数据,双列,5*7字形write_com(0x01) ;//清屏}/********************************************** 主程序实现显示***********************************************/ main(){init();write_com(0x80+0x02);for(num=0;num; 0xff*****0** /5*80x40*****0**0x40 ---->; I*****0**0x40 ---->;*****0**0x40*****0**0x40***000000x1f添加自己的自定义字符***********************************/code uchar ziku[]={0x0f,0x09,0x09,0x0f,0x09,0x09,0x0f,0x00, //汉字“日”0x0F,0x09,0x0F,0x09,0x0F,0x09,0x11,0x00, //汉字“月”0x01,0x02,0x03,0x05,0x09,0x03,0x00,0x00, //汉字“年”左半部0x00,0x00,0x1e,0x08,0x08,0x1e,0x08,0x08 //汉字“年”右半部};/*******************************读取lcd1602状态*******************************/uchar lcd_readcom(){uchar temp;e=0;port=0xff;rs=0;rw=1;e=1;temp=port;e=0;return temp;}/***************************************检测 lcd 是否忙碌小卒整天没事***************************************/ check_busy(){uchar temp;do{temp=lcd_readcom();}while((temp&0x80)==0x80);}/*****************************************向lcd里写命令*****************************************/ void lcd_writecom(uchar dat){check_busy();e=0;port=dat;rs=0;rw=0;e=1;e=0;}/*************************************** 读取lcd对应地址数据*****************************************/ uchar lcd_readdat(){uchar temp;check_busy();e=0;port=0xff;rs=1;rw=1;e=1;temp=port;e=0;return temp;}/**************************************** 向lcd里写数据****************************************/ void lcd_writedat(uchar dat){check_busy();e=0;port=dat;rs=1;rw=0;e=1;e=0;}/****************************************向lcd写字符串*****************************************/ void lcd_gets(char *dat){while(*dat!=0){lcd_writedat(*dat);dat++;}}/*****************************************确定要写的位子即x y 坐标******************************************/void lcd_xy(uchar x,uchar y){switch(y){case 0:lcd_writecom(0x80+x);break;//第一行第X个位置case1:lcd_writecom(0xc0+x);break;//0xc0==0x80+0x50 第二行第X个位置case 2:lcd_writecom(0x94+x);break;//case 3:lcd_writecom(0xd4+x);break;//4*20}}/************************************************ ****单行显示才有5*10 其他5*8 MODE=1 5*8 MODE=0 5*10 ****************************************************/add_custom_word(uchar *dat,uchar len,uchar mode) {uchar n,m;for(n=0;n;0;x--)for(y=110;y>;0;y--)for(a=1;a>;0;a--) ;}/********************************************** 主程序实现显示***********************************************/ main(){lcd_init();//lcd_xy(0,0);//lcd_gets(" I LOVE YOU");//lcd_xy(0,1);//lcd_gets("Shang Hong Rui");lcd_xy(2,0) ;lcd_gets("2011");lcd_xy(6,0) ;lcd_writedat(2);lcd_writedat(3);lcd_xy(8,0) ;lcd_gets("03"); lcd_xy(10,0);lcd_writedat(1);lcd_xy(11,0) ;lcd_gets("06"); lcd_xy(13,0);lcd_writedat(0);lcd_xy(3,1) ;lcd_gets("0"); lcd_xy(4,1) ;lcd_gets("0"); lcd_xy(5,1) ;lcd_gets(":"); lcd_xy(6,1) ;lcd_gets("0"); lcd_xy(7,1) ;lcd_gets("0"); lcd_xy(8,1) ;lcd_gets(":");lcd_gets("0");lcd_xy(10,1) ;lcd_gets("0");while(1){//for(m=0;m<10;m++)lcd_xy(10,1);lcd_writedat(table[miaog]);//秒个位delay(1000);miaog++;if(miaog==10){miaog=0;lcd_xy(9,1);lcd_writedat(table[miaos]); //秒十位miaos++;if(miaos==6){miaos=0;lcd_xy(7,1);lcd_writedat(table[feng]); //分个位 feng++;if(feng==10){feng=0;lcd_xy(6,1);lcd_writedat(table[fens]); //分十位 fens++;if(fens==6){fens=0;lcd_xy(4,1);lcd_writedat(table[shig]); //时个位 shig++;if(shig==10){shig=0;lcd_xy(3,1);lcd_writedat(table[shis]);//时十位shis++;if(shis==6){shis=0;}}}}}}}//lcd_xy(0,0);//lcd_writedat(0);//自定义字符使用,0表示第一个字,1表示第二个字,依此类推//lcd_xy(15,0);//lcd_writedat(3); //自定义字符使用}第二段程序为借用别人的,呵呵。
基于51单片机的1602液晶时钟设计的C程序(闰年补偿,月份调整)
![基于51单片机的1602液晶时钟设计的C程序(闰年补偿,月份调整)](https://img.taocdn.com/s3/m/d0755936e518964bce847c17.png)
#include<reg52.h>#define uchar unsigned char#define uint unsigned intuchar code table[]=" 2012-02-29 MON";uchar code table1[]=" 23:59:55";uchar num,count,shi,fen,miao,nian,yue,ri,xingqi,s1num,flag; sbit lcden=P2^5;sbit lcdrs=P1^0;sbit lcdrw=P1^1;sbit s1=P3^0;sbit s2=P3^1;sbit s3=P3^2;sbit s4=P3^3;sbit feng=P2^3;/***************延迟函数***************/void delay(uint z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}/**********写命令***************/void write_com(uchar com){lcdrs=0;lcdrw=0;P0=com;lcden=1;delay(5);lcden=0;}/**************写数据****************/void write_data(uchar date){lcdrs=1;lcdrw=0;P0=date;lcden=1;delay(5);lcden=0;}/*************时分秒调节函数********************/void write_sfm(uchar add,uchar date){uchar shi,ge;shi=date/10;ge=date%10;write_com(0x80+0x40+add);write_data(0x30+shi);write_data(0x30+ge);}/****************年月日调节函数***************/void write_nyr(uchar ad,uchar dat){uchar shi,ge;shi=dat/10;ge=dat%10;write_com(0x80+0x00+ad);write_data(0x30+shi);write_data(0x30+ge);}/**************************星期显示函数*****************/void display_week(){switch (xingqi){case 1: write_data('M');write_data('O');write_data('N');write_com(0x80+0x00+14);break;case 2: write_data('T');write_data('U');write_data('E');write_com(0x80+0x00+14);break;case 3: write_data('W');write_data('E');write_data('D');write_com(0x80+0x00+14);break;case 4: write_data('T');write_data('H');write_data('U');write_com(0x80+0x00+14);break;case 5: write_data('F');write_data('R');write_data('I');write_com(0x80+0x00+14);break;case 6: write_data('S');write_data('A');write_data('T');write_com(0x80+0x00+14);break;case 7: write_data('S');write_data('U');write_data('N');write_com(0x80+0x00+14);break;}}void keycan(){/****************光标左移***************/if(s1==0){delay(5);if(s1==0){s1num++;while(!s1);if(s1num==1){TR0=0;write_com(0x80+0x40+11);write_data('<');write_com(0x80+0x40+10);//光标重新回到闪烁点,写光标地址同样加一write_com(0x0f); //光标闪烁}if(s1num==2){write_com(0x80+0x40+11);write_data(' ');write_com(0x80+0x40+8);write_data('<');write_com(0x80+0x40+7);}if(s1num==3){write_com(0x80+0x40+8);write_data(':');write_com(0x80+0x40+5);write_data('<');write_com(0x80+0x40+4);}if(s1num==4){write_com(0x80+0x40+5);write_data(':');write_com(0x80+15);write_data('<');write_com(0x80+14);}if(s1num==5){write_com(0x80+15);write_data(' ');write_com(0x80+11);write_data('<');write_com(0x80+10);}if(s1num==6){write_com(0x80+11);write_data(' ');write_com(0x80+8);write_data('<');write_com(0x80+7); }if(s1num==7){write_com(0x80+8);write_data('-');write_com(0x80+5);write_data('<');write_com(0x80+4); }if(s1num==8){s1num=0;write_com(0x80+5);write_data('-');write_com(0x0c);TR0=1;}}}/**************光标右移***************//* if(s2==0){delay(5);if(s2==0){s1num--;while(!s2);if(s1num==1){TR0=0;write_com(0x80+0x40+11);write_data('<');write_com(0x80+0x40+11);//光标重新回到闪烁点,写光标地址同样加一write_com(0x0f); //光标闪烁}if(s1num==2){write_com(0x80+0x40+11);write_data(' ');write_com(0x80+0x40+8);write_data('<');write_com(0x80+0x40+8);}if(s1num==3){write_com(0x80+0x40+8);write_data(':');write_com(0x80+0x40+5);write_data('<');write_com(0x80+0x40+5);}if(s1num==4){write_com(0x80+0x40+5);write_data(':');write_com(0x80+15);write_data('<');write_com(0x80+15);}if(s1num==5){write_com(0x80+15);write_data(' ');write_com(0x80+11);write_data('<');write_com(0x80+11);}if(s1num==6){write_com(0x80+11);write_data(' ');write_com(0x80+8);write_data('<');write_com(0x80+8);}if(s1num==7){write_com(0x80+8);write_data('-');write_com(0x80+5);write_data('<');write_com(0x80+5);}if(s1num==8){s1num=0;write_com(0x80+5);write_data('-');write_com(0x0c);TR0=1;}}} *//***************************按键加*******************************/if(s1num!=0){if(s3==0){delay(5);if(s3==0){while(!s3);if(s1num==1){miao++;if(miao==60)miao=0;write_sfm(9,miao);write_com(0x80+0x40+10);}if(s1num==2){fen++;if(fen==60)fen=0;write_sfm(6,fen);write_com(0x80+0x40+7);}if(s1num==3){shi++;if(shi==24)shi=0;write_sfm(3,shi);write_com(0x80+0x40+4);}if(s1num==4){xingqi++;if(xingqi==8)xingqi=1;write_com(0x80+0x00+12);display_week();}if(s1num==5){ri++;if(ri==32&&(yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12)){ri=1;yue++;if(yue==13){yue=1;nian++;write_nyr(3,nian);}write_nyr(6,yue);}if(ri==31&&(yue==4||yue==6||yue==9||yue==11)){ri=1;yue++;write_nyr(6,yue);}if(flag==1){if(ri==30&&yue==2){ri=1;yue++;write_nyr(6,yue);}}if(flag==0){if(ri==29&&yue==2){ri=1;yue++;write_nyr(6,yue);}}write_nyr(9,ri);write_com(0x80+0x00+10);}if(s1num==6){yue++;if(yue==2&&ri>29&&flag==1) //当为闰年时,如果ri=30,但是月份已经加到2,这种情况ri必须等于29{ri=29;write_nyr(9,ri);}if(yue==2&&ri>28&&flag==0) //当为平年时,如果ri=30,但是月份已经加到2,这种情况ri必须等于28{ri=28;write_nyr(9,ri);}if((yue==4||yue==6||yue==9||yue==11)&&(ri==31||ri==29||ri==28)){ri=1;write_nyr(9,ri);}if(yue==13){yue=1;nian++;if(nian%4>0){write_nyr(9,28);}write_nyr(3,nian);}write_nyr(6,yue);write_com(0x80+0x00+7);}if(s1num==7){nian++;if(nian==100)nian=0;flag=0;if(nian%4==0)flag=1;write_nyr(3,nian);write_com(0x80+0x00+4);}}}}/***************************按键减*********************/if(s4==0){delay(5);if(s4==0){while(!s4);if(s1num==1){miao--;if(miao==-1)miao=59;write_sfm(9,miao);write_com(0x80+0x40+10);}if(s1num==2){fen--;if(fen==-1)fen=59;write_sfm(6,fen);write_com(0x80+0x40+7);}if(s1num==3){shi--;if(shi==-1)shi=23;write_sfm(3,shi);write_com(0x80+0x40+4);}if(s1num==4){xingqi--;if(xingqi==0)xingqi=7;write_com(0x80+0x00+12);display_week();}if(s1num==5){ri--;if(ri==0&&(yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12)){ri=30; //防止当yue=12时,当yue减到11时,ri任然等于31时这种不允许情况出现yue--;if(yue==2){if(flag==1)ri=29;elseri=28;}write_nyr(6,yue);if(yue==0){yue=12;ri=31;write_nyr(9,ri);write_nyr(6,yue);}}if(ri==0&&(yue==4||yue==6||yue==9||yue==11)){ri=31;//按下减小按钮,yue 减到3或5或8或10,为大月yue--;write_nyr(6,yue);}if(flag==1) //闰年标志位{if(ri==0&&yue==2){ri=29;yue--;write_nyr(6,yue);}}if(flag==0) //平年标志位{if(ri==0&&yue==2){ri=28;yue--;write_nyr(6,yue);}}write_nyr(9,ri);write_com(0x80+0x00+10);}if(s1num==6){yue--;if(yue==2&&ri>29&&flag==1){ri=29;write_nyr(9,ri);}if(yue==2&&ri>28&&flag==0){ri=28;write_nyr(9,ri);}if(yue==0){yue=12;nian--;write_nyr(3,nian);}write_nyr(6,yue);if((yue==4||yue==6||yue==9||yue==11)&&(ri==31||ri==29||ri==28)){ri=1;write_nyr(9,ri);}write_com(0x80+0x00+7);}if(s1num==7){nian--;if(nian==-1)nian=99;flag=0; //清除标志位if(nian%4==0)flag=1;write_nyr(3,nian);write_com(0x80+0x00+4);}}}}/************初始化**************/void init(){write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x01);write_com(0x80+0x00);for(num=0;num<15;num++){write_data(table[num]);delay(5);}write_com(0x80+0x40);for(num=0;num<11;num++){write_data(table1[num]);delay(5);}shi=23;fen=59;miao=55;xingqi=1;ri=29;yue=2;nian=12;if(nian%4==0)flag=1;TMOD=0x01;TH0=(65536-50000)/256;TL0=(65536-50000)%256;EA=1;ET0=1;TR0=1;}/***********主函数*************/ void main(){init(); //初始化while(1){keycan();}}/******启动定时器*************/void timer() interrupt 1{TH0=(65536-50000)/256;TL0=(65536-50000)%256;count++;if(count==18){count=0;miao++;if(miao==60){miao=0;fen++;if(fen==60){fen=0;feng=0;delay(500);feng=1;shi++;if(shi==24){shi=0;ri++;xingqi++;if(xingqi==8)xingqi=1;write_com(0x80+0x00+12);display_week();if(ri==32&&(yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12)){ri=1;yue++;if(yue==13){yue=1;nian++;if(nian==99)nian=0;if(nian%4==0)flag=1;flag=0;write_nyr(3,nian);}write_nyr(6,yue);}if(ri==31&&(yue==4||yue==6||yue==9||yue==11)){ri=1;yue++;write_nyr(6,yue);}if(flag==1){if(ri==30&&yue==2){ri=1;yue++;write_nyr(6,yue);}}if(flag==0){if(ri==29&&yue==2).专业整理..学习帮手.{ri=1;yue++;write_nyr(6,yue);}}write_nyr(9,ri);}write_sfm(3,shi);}write_sfm(6,fen);}write_sfm(9,miao);}}。
基于51单片机proteus的lcd1602日历键盘扫描可调整时间附c51代码及调试截图 desi
![基于51单片机proteus的lcd1602日历键盘扫描可调整时间附c51代码及调试截图 desi](https://img.taocdn.com/s3/m/72b87817227916888486d76a.png)
基于51单片机proteus的lcd1602日历键盘扫描可调整时间附c51代码及调试截图designed by qin(2014.10.3)第一张是时间正在跑的截图,第二张是调整时间的截图,图中s1是用来选择调整年月日时分秒的(星期几系统会自动根据年月日求出),s2,s3分别是用来调大调小数字的。
有一点得说明一下,当按动s1到“日”的那个位置时,系统会自动把日设定为20日,因为日得由年和月来限制范围,笔者是出于程序简洁的目的才这样设定。
附:c51代码这里还要说明一下,读者若要自己动手仿真本实验的话,请用这款编译软件:,不要用这款:,本人亲测发现keil uVsion4编译c51代码时会有很多bug,很烦人。
#include<reg52.h>#include<math.h>#define uchar unsigned char#define uint unsigned intsbit rs=P2^0;sbit rw=P2^1;sbit en=P2^2;sbit s1=P2^4;sbit s2=P2^5;sbit s3=P2^6;sbit s4=P2^7;sbit beep=P1^0;sbit p2=P2;uchar code zhou[28]="Mon TuesWed ThurFri Sat Sun "; uchar yue,ri,shi,fen,miao,xingqi;long nian;void delay(uchar n);void lcd_init();void write_com(uchar n);void write_data(uchar n);void calculate_week(uint y,uchar m,uchar d);void write_week(uchar hang,uchar lie,uchar n);void key_scan();void tiao_nian();void timer_0_init();void timer_0();void write_erweishu(uchar hang,uchar lie,uchar num);void write_nian(uchar hang,uchar lie,uint n);void delay(uchar n){uchar i,j;for(i=0;i<n;i++)for(j=0;j<110;j++);}void write_com(uchar n){rs=0;rw=0;en=0;P0=n;delay(5);en=1;delay(5);en=0;}void write_data(uchar n){rs=1;rw=0;en=1;P0=n;delay(5);en=0;delay(5);}void write_erweishu(uchar hang,uchar lie,uchar num) {uchar i,shiwei,gewei;shiwei=num/10;gewei=num%10;if(hang==1)i=0;if(hang==2)i=0x40;write_com(0x80+i+lie-1);write_data(0x30+shiwei);write_data(0x30+gewei);}void write_nian(uchar hang,uchar lie, long n) {uchar i,ge,shi,bai,qian;if(hang==1)i=0;if(hang==2)i=0x40;write_com(0x80+i+lie-1);qian=n/1000;bai=(n/100)%10;shi=(n/10)%10;ge=n%10;write_data(0x30+n/1000);write_data(0x30+(n/100)%10);write_data(0x30+(n/10)%10);write_data(0x30+n%10);}void calculate_week(uint y,uchar m,uchar d){if(m==1||m==2){m+=12;y--;}xingqi=(d+1+2*m+3*(m+1)/5+y+y/4-y/100+y/400)%7;}void write_week(uchar hang,uchar lie,uchar n){uchar k,i;if(hang==1)i=0;if(hang==2)i=0x40;write_com(0x80+i+lie-1);if(n!=0) //xingqi=1~6的时候是和周几对应的{for(k=4*n-4;k<4*n;k++)write_data(zhou[k]);}else //xingqi=0的时候是周日{for(k=24;k<28;k++)write_data(zhou[k]);}}void lcd_init(){en=0;write_com(0x38); //设置16x2 显示5x7 点阵,8 位数据接口write_com(0x0c); //设置开始显示不显示光标write_com(0x06); //写一个字符后地址指针加1write_com(0x01); //lcd1602清屏write_com(0x80); //设置起始位置}void timer_0_init(){TMOD=0x01;EA=1;ET0=1;TR0=1;}void key_scan(){uchar i=0,s1_num,s2_num,s3_num,s4_num,run;while(1){if(s1==0) //s1键用来移动光标,配合s2(调大时间),s3(调小时间)调整时间{delay(5); //按键去抖if(s1==0){TR0=0;s1_num++;while(s1==0); //这个while是用来防止s1长时间按下而导致的按键执行程序不断循环的现象switch(s1_num){case 1: write_com(0x80+3);write_com(0x0f);break;//调整年case 2: write_com(0x80+6);break;//调整月case 3: ri=28;write_erweishu(1,9,ri);write_com(0x80+9);break; //调整日case 4: write_com(0x80+0x40+5);break;//调整时case 5: write_com(0x80+0x40+8);break;//调整分case 6: write_com(0x80+0x40+11);break;//调整秒case 7:TR0=1;write_com(0x38);write_com(0x0c);write_com(0x06);s1_nu m=0;calculate_week(nian,yue,ri);write_week(1,13,xingqi);break; //定时启动}}}if(s2==0){delay(5);if(s2==0){while(s2==0);if(s1_num==1) //调大年{write_nian(1,1,++nian);write_com(0x80+3);}if(s1_num==2) //调大月{if(yue++==12)yue=1;write_erweishu(1,6,yue);write_com(0x80+6);}if(s1_num==3) //调大日{if(nian%400==0||(nian%100!=0&&nian%4==0))run=1; //判断是否为闰年if(yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12){if(ri++==31)ri=1;write_erweishu(1,9,ri);write_com(0x80+9);}if(yue==4||yue==6||yue==9||yue==11) {if(ri++==30)ri=1;write_erweishu(1,9,ri);write_com(0x80+9);}if(yue==2){if(run==1){run=0;if(ri++==29)ri=1;write_erweishu(1,9,ri);write_com(0x80+9);}else{if(ri++==28)ri=1;write_erweishu(1,9,ri);write_com(0x80+9);}}}if(s1_num==4) //调大时{if(shi++==23)shi=0;{write_erweishu(2,5,shi);write_com(0x80+0x40+5);}}if(s1_num==5) //调大分{if(fen++==59)fen=0;{write_erweishu(2,8,fen);write_com(0x80+0x40+8);}}if(s1_num==6) //调大秒{if(miao++==59)miao=0;{write_erweishu(2,11,miao);write_com(0x80+0x40+11);}}}}if(s3==0){delay(5);if(s3==0){while(s3==0);if(s1_num==1) //调小年{write_nian(1,1,--nian);write_com(0x80+3);}if(s1_num==2) //调小月{if(yue--==1)yue=12;write_erweishu(1,6,yue);write_com(0x80+6);}if(s1_num==3) //调小日{if(nian%400==0||(nian%100!=0&&nian%4==0))run=1; //判断是否为闰年if(yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12){if(ri--==1)ri=31;write_erweishu(1,9,ri);write_com(0x80+9);}if(yue==4||yue==6||yue==9||yue==11) {if(ri--==1)ri=30;write_erweishu(1,9,ri);write_com(0x80+9);}if(yue==2){if(run==1){run=0;if(ri--==1)ri=29;write_erweishu(1,9,ri);write_com(0x80+9);}else{if(ri--==1)ri=28;write_erweishu(1,9,ri);write_com(0x80+9);}}}if(s1_num==4) //调小时{if(shi--==0)shi=23;{write_erweishu(2,5,shi);write_com(0x80+0x40+5);}}if(s1_num==5) //调小分{if(fen--==0)fen=59;{write_erweishu(2,8,fen);write_com(0x80+0x40+8);}}if(s1_num==6) //调小秒{if(miao--==0)miao=59;{write_erweishu(2,11,miao);write_com(0x80+0x40+11);}}}}}}void main(){nian=2014;yue=12;ri=31;shi=23;fen=59;miao=45;lcd_init();timer_0_init();write_nian(1,1,nian);write_data('-'); //keil uVsion4(uVsion3没有)在这里似乎有一个bug,如果直接用write_nian(1,1,nian)显示2014的话,它只会显示0000;write_erweishu(1,6,yue);write_data('-');write_erweishu(1,9,ri);calculate_week(nian,yue,ri); write_week(1,13,xingqi); //写星期几write_erweishu(2,5,shi); write_data(':');write_erweishu(2,8,fen); write_data(':');write_erweishu(2,11,miao);key_scan();}void timer_0()interrupt 1 using 1{uchar i,run;TH0=(65536-55536)/256;TL0=(65536-55536)%256;if(i++==4){i=0;if(miao++==59){miao=0;if(fen++==59){fen=0;if(shi++==23){shi=0;if(nian%400==0||(nian%100!=0&&nian%4==0))run=1; //判断是否为闰年if(yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12) {if(ri++==31){ri=1;if(yue++==12){nian++;yue=1;write_nian(1,1,nian);write_data(' -');}}}write_erweishu(1,6,yue);write_data('-');write_erweishu(1,9,r i);if(yue==4||yue==6||yue==9||yue==11){if(ri++==30){ri=1;if(yue++==12){nian++;yue=1;write_nian(1,1,nian);write_data('-');}}}write_erweishu(1,6,yue);write_data('-');write_erweishu(1,9,r i);if(yue==2){if(run==1){run=0;if(ri++==29){ri=1;if(yue++==12){nian++;yue=1;write_nian(1,1,nian);write_data('-');}}write_erweishu(1,6,yue);write_data('-');write_erw eishu(1,9,ri);}else{if(ri++==28){ri=1;if(yue++==12){nian++;yue=1;write_nian(1,1,nian);write_data('-');}}write_erweishu(1,6,yue);write_data('-');write_erw eishu(1,9,ri);}}}write_erweishu(2,5,shi);calculate_week(nian,yue,ri);write_wee k(1,13,xingqi); //写星期几//这里keil有个bug,原本只需ri就行,但这里必须是ri+=2才行}write_erweishu(2,8,fen);}write_erweishu(2,11,miao);}}。
可调时钟1602显示且附带智能闹钟且附带日期
![可调时钟1602显示且附带智能闹钟且附带日期](https://img.taocdn.com/s3/m/3681363287c24028915fc308.png)
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)//第一次按调时
基于51单片机的万年历代码(1602液晶实现)
![基于51单片机的万年历代码(1602液晶实现)](https://img.taocdn.com/s3/m/96d029976bec0975f465e290.png)
if(key3==0) {
month‐‐; if(month==0||month>12)month=12; playx(); playmo(month); com(0x80+8); while(!key3); } } } if(key4==0) { delay(5); if(key4==0) { keynum=0; com(0x0c); TR0=1; while(!key4); } }
hmiao=0; miao++; if(miao==60) {
miao=0; fen++; if(fen==60) {
fen=0; shi++; if(shi==24) {
shi=0; day++; playx(); if((Yeepyear(year))&&day==ryue[month]) 是否为闰年
} void plays(uchar s)
{ shi1=s/10; shi2=s%10; com(0x80+0x44); date(0x30+shi1); date(0x30+shi2); } void playf(uchar f) { fen1=f/10; fen2=f%10; com(0x80+0x47); date(0x30+fen1); date(0x30+fen2); } void playmi(uchar m) { miao1=m/10; miao2=m%10; com(0x80+0x40+10); date(0x30+miao1); date(0x30+miao2);
51单片机电子表LCD1602显示_时间可调
![51单片机电子表LCD1602显示_时间可调](https://img.taocdn.com/s3/m/8ae133c408a1284ac850433f.png)
/*功能:52单片机定时器0电子表LCD1602显示可对时间进行调节作者:燕山大学里仁学院09应电四班杨立业欢迎您的建议、指点和更多交流QQ:1024549573晶振:12M*/#include<reg52.h>#define uint unsigned intsbit lcden=P3^4; //液晶的使能端sbit rs=P3^5; //液晶的数据指令控制端sbit wr=P3^6; //液晶的读写端sbit rd=P3^7; //按键的一个线选使按键共阴极sbit fc=P3^0; //功能键确定时间调整的位置sbit jia=P3^1; //加1sbit jian=P3^2;//减1unsigned char code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f};unsigned char code table1[]=" 00:00:00 ";uint num,num1,i,shi,ge,shu;long int hour,fen,miao;void write_com(uint com);void write_date(uint date);void init1602();void init() ;void write_sf(uint add,uint sf);void delay(uint x);void keyscan();void main(){ init();init1602();write_com(0x80+0x40+3);for(num1=1;num1<8;num1++){ write_date(table1[num1]);delay(5);}while(1){ keyscan();}}void write_com(uint com)//1602 写指令{ rs=0;P0=com;lcden=0;delay(10);lcden=1;delay(10);lcden=0;}void write_date(uint date)//1602写数据{ rs=1;P0=date;lcden=0;delay(10);lcden=1;delay(10);lcden=0;}void init() //定时器初始化{ rd=0;TMOD=0X01;TH0=(65536-50000)/256;TL0=(65536-50000)%256;EA=1;ET0=1;TR0=1;}void init1602()//1602初始化{ dula=0;wela=0;wr=0;lcden=0;write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x01);}void write_sf(uint add,uint sf)//显示时间{ uint shi,ge;shi=sf/10;ge=sf%10;write_com(0x80+0x40+add);write_date(0x30+shi);write_date(0x30+ge);}void time0() interrupt 1 //定时器0中断{ TH0=(65536-50000)/256;TL0=(65536-50000)%256;num++;if(num==20){num=0;miao++;if(miao==60){ miao=0;fen++;if(fen==60){ fen=0;hour++;if(hour==24)hour=0;write_sf(4,hour);}write_sf(7,fen);}write_sf(10,miao);}}void delay(uint x)//ms级延时{ uint i,j;for(i=x;i>0;i--)for(j=110;j>0;j--);}void keyscan()//按键扫描{ if(fc==0) //功能键选择时间调节加减的位置{ delay(5);if(fc==0){ while(!fc);shu++;if(shu==4)shu=0;switch(shu){ case 0:TR0=1;write_com(0x0c);break;case 1:TR0=0;write_com(0x80+0x40+11);write_com(0x0f);break;case 2:write_com(0x80+0x40+8);write_com(0x0f);break;case 3:write_com(0x80+0x40+5);write_com(0x0f);break;}}}if(jia==0) //时或分或秒的加一{ delay(5);if(jia==0){ while(!jia);switch(shu){ case 1: miao++;if(miao==60)miao=0;write_sf(10,miao);write_com(0x80+0x40+11);break;case 2: fen++;if(fen==60)fen=0;write_sf(7,fen);write_com(0x80+0x40+8);break;case 3: hour++;if(hour==24)hour=0;write_sf(4,hour);write_com(0x80+0x40+5);break;}}}if(jian==0) //时或分或秒的减一{ delay(8);if(jian==0){ while(!jian);switch(shu){ case 1: --miao;if(miao==-1)miao=59;write_sf(10,miao);write_com(0x80+0x40+11);break;case 2: fen--;if(fen==-1)fen=59;write_sf(7,fen);write_com(0x80+0x40+8);break;case 3: hour--;if(hour==-1)hour=23;write_sf(4,hour);write_com(0x80+0x40+5);break;}}}}。
基于51单片机定时器的1602液晶显示器时钟显示(带年月日)
![基于51单片机定时器的1602液晶显示器时钟显示(带年月日)](https://img.taocdn.com/s3/m/8821af0aa200a6c30c22590102020740be1ecd31.png)
基于51单⽚机定时器的1602液晶显⽰器时钟显⽰(带年⽉⽇)#include#define uchar unsigned char#define uint unsigned intuchar a,count,S1num,xqnum;char yue,ri,shi,fen,miao;int nian;sbit lcdrs=P2^5;sbit lcdrw=P2^4;sbit lcden=P2^3;sbit S1=P3^0; //定义键——进⼊设置sbit S2=P3^1; //定义键——增⼤sbit S3=P3^2; //定义键——减⼩sbit S4=P3^3; //定义键——退出设置uchar code table0[]="2014-08-13 WED";uchar code table1[]="00:00:00";uchar code xingqi[][3]={"MON","TUE","WED","THU","FRI","SAT","SUN"};void delay(uint z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}/**************************************************1602液晶显⽰器模块sbit lcdrs=P2^5;sbit lcdrw=P2^4;sbit lcden=P2^3;*************************************************/void write_com(uchar com) //液晶写指令{lcdrw=0;P0=com;delay(5);lcden=1;delay(5);lcden=0;}void write_data(uchar dat) //液晶写数据{lcdrw=0;lcdrs=1;P0=dat;delay(5);lcden=1;delay(5);lcden=0;}/********************************************年⽉⽇写⼊1602函数********************************************/void write_sfm(uchar add,uchar dat) //写时分秒函数{ uchar shi,ge;shi=dat/10;ge=dat%10;write_com(0x80+0x40+add);write_data(0x30+shi);write_data(0x30+ge);}void write_yr(uchar add,uchar dat) //写⽉⽇函数{uchar shi,ge;shi=dat/10;ge=dat%10;write_com(0x80+add);write_data(0x30+shi);}void write_nian(uchar add,uint dat) //写年函数{uint qian,bai,shi,ge;qian=dat/1000;bai=dat%1000/100;shi=dat%100/10;ge=dat%10;write_com(0x80+add);write_data(0x30+qian);write_data(0x30+bai);write_data(0x30+shi);write_data(0x30+ge);/***************************************************初始化***************************************************/void init_lcd() //液晶初始化{lcden=0;nian=2014;yue=8;ri=13;shi=0; //初始shi、fen、miaofen=0;miao=0;write_com(0x38); //设置16x2显⽰,5x7点阵,8位数据⼝write_com(0x0c); //设置开显⽰,不显⽰光标write_com(0x06); //写⼀个字符后地址指针加1write_com(0x01); //显⽰清0,数据指针清0}void init() //初始化函数{init_lcd(); //液晶初始化write_com(0x80); //设置显⽰初始坐标for(a=0;a<14;a++) //显⽰年⽉⽇初始值write_data(table0[a]);delay(5);}write_com(0x80+0x40); //设置显⽰初始坐标for(a=0;a<8;a++) //显⽰时分秒初始值{write_data(table1[a]);delay(5);}write_nian(0,nian);write_sfm(6,miao); //分别将shi、fen、miao送去液晶显⽰write_sfm(3,fen);write_sfm(0,shi);count=0;xqnum=0;S1num=0; //初始化全局变量countTMOD=0x01; //设置定时器0⼯作模式1 TH0=(65535-50000)/256; //定时器装初始值TL0=(65535-50000)%256;EA=1; //开总中断ET0=1; //开定时器0中断TR0=1; //启动定时器0}/**************************************************独⽴键盘sbit S1=P3^0; //定义键——进⼊设置sbit S2=P3^1; //定义键——增⼤sbit S3=P3^2; //定义键——减⼩sbit S4=P3^3; //定义键——退出设置独⽴键盘已接地*************************************************/void keyscan(){if(S1==0){delay(5); //确认定义键被按下{S1num++; //定义键S1按下次数记录while(!S1); //释放按键确认if(S1num==1) //S1按下⼀次时{TR0=0; //关闭定时器write_com(0xc0+7); //光标定位到秒位置write_com(0x0f); //光标闪烁}if(S1num==2) //S1按下两次时{write_com(0xc0+4); //光标定位到分位置}if(S1num==3) //S1按下三次时{write_com(0xc0+1); //光标定位到时位置}if(S1num==4) //S1按下四次时{write_com(0x80+13); //光标定位到星期位置}if(S1num==5) //S1按下五次时{write_com(0x80+9); //光标定位到⽇位置}if(S1num==6) //S1按下六次时{write_com(0x80+6); //光标定位到⽉位置}if(S1num==7) //S1按下七次时{write_com(0x80+3); //光标定位到年位置}if(S1num==8) //S1按下⼋次时S1num=0; //S1记录按键次数清零TR0=1; //开启定时器write_com(0x0c); //取消光标闪烁}}}if(S1num!=0) //只有定义键按下后S2、S3、S4才有效{ if(S2==0){delay(5); //防抖if(S2==0) //确认按键被按下{while(!S2); //释放按键确认if(S1num==1) //S1按下⼀次时{miao++; //调整秒加1if(miao==60) //满60清零miao=0;write_sfm(6,miao); //每调节⼀次送液晶显⽰⼀次write_com(0x80+0x40+6); //显⽰位置重新回到调节处} if(S1num==2) //S1按下两次时{fen++; //调整分加1if(fen==60)fen=0;write_sfm(3,fen);write_com(0x80+0x40+3);}if(S1num==3) //S1按下三次时{shi++; //调整时加1if(shi==24)shi=0;write_com(0x80+0x40);}if(S1num==4) //星期加调整{ xqnum++;if(xqnum==7)xqnum=0;write_com(0x80+0x0b);for(a=0;a<3;a++){write_data(xingqi[xqnum][a]); delay(5);}}if(S1num==5) //⽇加调整{ri++;if(yue==2){if(nian%400==0){if(ri==30){ri=1;}}if(nian%400!=0){if(ri==29){ri=1;}}}else if(yue<=7){if(yue%2==0&yue!=2){ri=1;}}else if(yue%2!=0&yue!=2) {if(ri==32){ri=1;}}}else if(yue>=8){if(yue%2==0){if(ri==32){ri=1;}}else if(yue%2!=0){if(ri==31){ri=1;}}}write_yr(8,ri);}if(S1num==6) //⽉加调整{ yue++;write_yr(5,yue);}if(S1num==7) //年加调整{nian++;if(nian==2019)nian=2014;write_nian(0,nian);}}}if(S3==0){delay(5);if(S3==0) //确认按键被按下{while(!S3);if(S1num==1){miao--; //调整秒减1if(miao==-1) //减到00后再减重新设置为59 miao=59;write_sfm(6,miao);write_com(0x80+0x40+6);}if(S1num==2){fen--; //调整分减1if(fen==-1)fen=59;write_sfm(3,fen);write_com(0x80+0x40+3);}if(S1num==3)shi--; //调整时减1if(shi==-1)shi=23;write_sfm(0,shi);write_com(0x80+0x40);}if(S1num==4){xqnum--; //调整星期减⼀if(xqnum==-1)xqnum=6;write_com(0x80+0x0b);for(a=0;a<3;a++){write_data(xingqi[xqnum][a]); delay(5);}}if(S1num==5) //调整⽇{ri--;if(yue==2){if(nian%400==0){if(ri==0){ri=29;}}if(nian%400!=0){if(ri==0){ri=28;}else if(yue<=7){if(yue%2==0&yue!=2){if(ri==0){ri=30;}}else if(yue%2!=0&yue!=2) {if(ri==0){ri=31;}}}else if(yue>=8){if(yue%2==0){if(ri==0){ri=31;}}else if(yue%2!=0){if(ri==0){ri=30;}}write_yr(8,ri);}if(S1num==6) //调整⽉{yue--;if(yue==0)yue=12;write_yr(5,yue);}if(S1num==7) //调整年{nian--;if(nian==2013)nian=2018;write_nian(0,nian);}}}if(S4==0) //退出设置、开启中断{delay(5);if(S4==0){S1num=0;TR0=1;write_com(0x0c);}}}}/**************************************************定时器0*************************************************/ void timer0() interrupt 1 //定时器0中断服务程序TH0=(65535-50000)/256; //重装定时器初始值TL0=(65535-50000)%256; count++; //中断次数累加if(count==20) //20次50毫秒即⼀秒{count=0;miao++;if(miao==60) //秒加到60时分进位{miao=0;fen++;if(fen==60) //分加到60时时进位{fen=0;shi++;if(shi==24) //时加到24时清0{shi=0;xqnum++;ri++;if(yue==2) //如果是⼆⽉{if(nian%400==0) //闰年判断{if(ri==30){ri=1;yue++;write_yr(5,yue);}}if(nian%400!=0) //平年判断{if(ri==29){ri=1;yue++;write_yr(5,yue);}}}else if(yue<=7&yue!=2) //⼀⽉到七⽉{if(yue%2==0) //偶数⽉(除⼆⽉){if(ri==31){ri=1;yue++;}}else if(yue%2!=0) //奇数⽉{if(ri==32){ri=1;yue++;}}write_yr(5,yue);}else if(yue>=8) //⼋⽉到12⽉{if(yue%2==0) //偶数⽉(除⼆⽉){if(ri==32){ri=1;yue++;if(yue==13) //如果判断⽉份为12⽉,则加⼀后重新定义⽉份为1{yue=1;nian++;write_nian(0,nian);}write_yr(5,yue);}}else if(yue%2!=0) //奇数⽉{if(ri==31){ri=1;yue++;write_yr(5,yue);}}}write_yr(8,ri);if(xqnum==7) //星期写⼊xqnum=0;write_com(0x80+0x0b);for(a=0;a<3;a++){write_data(xingqi[xqnum][a]); delay(5);}}write_sfm(0,shi); //重新写⼊数据}write_sfm(3,fen); //重新写⼊数据}write_sfm(6,miao); //重新写⼊数据}}/*************************************************主函数*************************************************/ void main(){init();while(1){keyscan(); //不停的检测按键是否被按下} }。
1602液晶显示汉字程序
![1602液晶显示汉字程序](https://img.taocdn.com/s3/m/6ea543f2482fb4daa48d4bd4.png)
1602 液晶显示汉字程序利用1602 显示汉字也不是新鲜的内容,今天不想颓废了。
只是需要自己事先定义一下汉字的字模,就是显示出来的汉子字体结构。
要定义字模就需要知道1602 的CG RAM 地址和显示字符的地址DD RAM图1: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 第一行第一个字符的地址是( 0x80) ,后面的字符地址以此类推第二行第一个字符的地址为( 0x80 + 0x40) ,需要在第一行的基地址后面加上一个偏移量0x40 ,后面的地址在此基址上再依次加一。
void delay(unsigned int time_i){ int i;for (;tim>0;tim--){for (i=0;i<10;i++); } }void command_out (char out_data) {RW=0;RS=0;EN=1;DB=out_data;EN=0;delay(10);}void OUTD(char out_data){RS=1;RW=0;EN=1;DB= out_data;EN=0;delay(10);}OUTI() 是写入指令的函数,OUTD() 是写入数据的函数。
如:左上角第一个5*7 的显示数据为:0x00,0x01,0x81,0x12,0x24,0x41,0x81,0x10蓝色区域的相应位为1这样就可以写出全部 4 个 5*7 点阵的显示数据了,把它封装在一个数组中,如数组, hanzi[]={OxOO,OxO1,Ox81,Ox12,Ox24,Ox41,Ox81,Ox1O,} 之后利用命令:OUTI(0X40); for (i=0;i<64;i++){ OUTD(neu[i]);} 将这个数组中的数据赋值到 1602 内部 CGRAM 中。
一个1602显示汉字程序
![一个1602显示汉字程序](https://img.taocdn.com/s3/m/eea6fecea1c7aa00b52acbde.png)
一个1602显示汉字程序//************************************* //lcd头文件//*************************************#include<reg52.h>#include<string.h>#include <absacc.h>#define lcd_data P0 //定义端口#define uchar unsigned char#define uint unsigned intsbit RS=P2^1;sbit RW=P2^2;sbit E=P2^3;sbit BF=P0^7;//*************************************** //延时函数//*************************************** void delay(uint i){while(i--);}//***************************************//写控制字//*************************************** void write_struct(uchar temp){E=0;delay(100);//while(BF==1);RW=0;RS=0;lcd_data=temp;delay(3);E=1;delay(3);E=0;}//**************************************//写数据//**************************************void write_data(uchar temp){delay(100);//while(BF==1);E=0;RS=1;RW=0;lcd_data=temp;E=1;delay(3);E=0;}//***************************************//获得显示地址//x表示是第几行显示(0-1)//y表示某行的第几个字符(0-15)//***************************************uchar getchar_adress(uchar x,uchar y){ uchar address;if(x==0) address=0x80+y; //第一行else address=0xc0+y; //第二行return address;}//***************************************//lcd初始化//***************************************void lcd_init(){write_struct(0x38); //设置接口DB宽度(8位)和LCM显示行数(2行) write_struct(0x08); //write_struct(0x0c); //设置光标为移位模式write_struct(0x01); //执行清屏操作write_struct(0x06); //设置光标为加1模式}//***************************************//向CGRAM写入数据//***************************************void write_cgram(unsigned char adress,unsigned char *p){char i;for(i=0;i<8;i++){ write_struct(adress+i);write_data(p[i]);}}//***************************************//显示CGRAM数据//x表示是第几行显示(0-1)//y表示某行的第几个字符(0-15)//***************************************void display_cgram(unsigned char x,uchar y,uchar *CgramData) {uchar address,cgram_address,p;address=getchar_adress(x,y); //获得CGRAM字符显示位置cgram_address=0x40+(address&0x07)*8; //CGR AM初始地址 p=address&0x07;write_cgram(cgram_address,CgramData);write_struct(address); //设置DDRAM地址write_data(p);}//显示字符//***************************************void display(char temp0,char *p){write_struct(temp0);delay(3);write_data(*p);}//****************************************//显示字符串//****************************************void display_str(uchar x,uchar y,char *p){char i,temp0;temp0=getchar_adress(x,y);write_struct(temp0);for(i=0;i<16;i++){if(*p=='\0')break;write_data(*p);p++;}}//****************************************//清屏//****************************************void lcd_clr(){write_struct(0x01);}//*****************************************************end。
基于51单片机的用 LCD1602 显示时钟的程序
![基于51单片机的用 LCD1602 显示时钟的程序](https://img.taocdn.com/s3/m/4f39eb3010661ed9ad51f31b.png)
用LCD1602 显示的时钟2012-04-30 15:04有这样一个题目:求一个为51 单片机编写的LCD 电子时钟的设计,简单就好!希望说一下怎么设计这个时钟,都需要些什么东西,最重要的——把这个设计需要的程序写出来。
设计的任务:以单片机控制的时钟,在LCD 显示器上显示当前的时间。
设计的基本要求:1.使用文字型LCD 显示器显示当前时间。
2.显示格式为“时时:分分:秒秒”。
3.用4个功能键操作来设置当前时间。
各个功能键的功能如下:K1:进入设置现在的时间。
K2:设置小时。
K3:设置分钟。
K4:确认完成设置。
4. 程序执行后工作指示灯LED 闪烁,表示程序开始执行,LCD 显示“00:00:00”,然后开始计时。
题目链接:/question/416705477.html//==================================================提到设计时钟,很多人都想到了时钟芯片DS1302,都说它简单、准确。
其实,这是个误区。
仅仅使用一般的单片机,简单的编程,达到相同DS1302 的准确度,并不是难事。
如果不要求计算平闰年、不要求分清大小月、不要求计算星期几,只是要求一个简单的时钟(及日历),用DS1302,就是自寻烦恼。
大家可以打开题目链接,看看其中的一些答案,就可以看出使用DS1302 是多么的繁琐了,简直就是一场噩梦。
做而论道以前就使用普通的单片机和LCD1602 设计过《时钟与日历》,程序设计的非常合理,时间精度就完全取决于晶振的精度。
设计出来的时钟,几个月都差不上一秒。
针对这个题目,做而论道翻出了以前的设计,删节了一些不需要的功能,设计出了符合题目要求的时钟,用PROTEUS 仿真截图如下:程序用C 语言编写,全部代码如下://---------------------------------------------------#include<reg52.h>#define uchar unsigned char#define uint unsigned int#define KEY_IO P3#define LCD_IO P0sbit LCD_RS = P2^0;sbit LCD_RW = P2^1;sbit LCD_EN = P2^2;sbit SPK = P1^2;sbit LED = P2^4;bit new_s, modify = 0;char t0, sec = 50, min = 59, hour = 23;char code LCD_line1[] = "Designed by ZELD"; char code LCD_line2[] = "Timer: 00:00:00 "; char Timer_buf[] = "23:59:50";//---------------------------------------------------void delay(uint z){uint x, y;for(x = z; x > 0; x--) for(y = 100; y > 0; y--);//---------------------------------------------------void W_LCD_Com(uchar com) //写指令{LCD_RS = 0; LCD_IO = com; // LCD_RS和R/W都为低电平时,写入指令LCD_EN = 1; delay(5); LCD_EN = 0; //用EN输入一个高脉冲}//---------------------------------------------------void W_LCD_Dat(uchar dat) //写数据{LCD_RS = 1; LCD_IO = dat; // LCD_RS为高、R/W为低时,写入数据LCD_EN = 1; delay(5); LCD_EN = 0; //用EN输入一个高脉冲}//---------------------------------------------------void W_LCD_STR(uchar *s) //写字符串{while(*s) W_LCD_Dat(*s++);}//---------------------------------------------------void W_BUFF(void) //填写显示缓冲区{Timer_buf[7] = sec % 10 + 48; Timer_buf[6] = sec / 10 + 48;Timer_buf[4] = min % 10 + 48; Timer_buf[3] = min / 10 + 48;Timer_buf[1] = hour % 10 + 48;Timer_buf[0] = hour / 10 + 48;W_LCD_Com(0xc0 + 7); W_LCD_STR(Timer_buf);}//---------------------------------------------------uchar read_key(void){uchar x1, x2;KEY_IO = 255;x1 = KEY_IO;if (x1 != 255) {delay(100);x2 = KEY_IO;if (x1 != x2) return 255;while(x2 != 255) x2 = KEY_IO;if (x1 == 0x7f) return 0;else if (x1 == 0xbf) return 1;else if (x1 == 0xdf) return 2;else if (x1 == 0xef) return 3;else if (x1 == 0xf7) return 4;}return 255;//---------------------------------------------------void Init(){LCD_RW = 0;W_LCD_Com(0x38); delay(50);W_LCD_Com(0x0c);W_LCD_Com(0x06);W_LCD_Com(0x01);W_LCD_Com(0x80); W_LCD_STR(LCD_line1);W_LCD_Com(0xC0); W_LCD_STR(LCD_line2);TMOD = 0x01; //T0定时方式1TH0 = 0x4c;TR0 = 1; //启动T0PT0 = 1; //高优先级, 以保证定时精度ET0 = 1;EA = 1;}//---------------------------------------------------void main(){uint i, j;uchar Key;Init();while(1) {//-------------------------------if (new_s) { //如果出现了新的一秒, 修改时间new_s = 0; sec++; sec %= 60;if(!sec) { min++; min %= 60;if(!min) { hour++; hour %= 24;}}W_BUFF(); //写显示//-------------------------------if (!sec && !min) { //整点报时for (i = 0; i < 200; i++) {SPK = 0; for (j = 0; j < 100; j++);SPK = 1; for (j = 0; j < 100; j++);} }}//-------------------------------Key = read_key(); //读出按键switch(Key) { //分别处理四个按键case 0: modify = 1; break;case 1: if(modify) {min++; min %= 60; W_BUFF(); break;}case 2: if(modify) {hour++; hour %= 24; W_BUFF(); break;}case 3: modify = 0; break;} }}//---------------------------------------------------void timer0(void) interrupt 1 //T0中断函数, 50ms执行一次{TH0 = 0x4c;t0++; t0 %= 20; //20, 一秒钟if(t0 == 0) {new_s = 1; LED = ~LED;}if(modify) LED = 0;}//===================================================呵呵,全部程序,也不过120 行左右。
1602液晶显示(年月日时分秒星期)
![1602液晶显示(年月日时分秒星期)](https://img.taocdn.com/s3/m/1f89386ba36925c52cc58bd63186bceb19e8ed1c.png)
电子钟—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)。
if(sec==60)//秒加到60则进位分钟
{
sec=0;//同时秒数清零
min++;
if(min==60)//分钟加到60则进位小时
{
min=0;//同时分钟数清零
hour++;
if(hour==24)//小时加到24则小时清零
}*/
void write_string(uchar x,uchar y,uchar *s)//写字符串(这个指针还不大懂啊)
{
write_by_xy(x,y);//设定显示位置
while(*s)//write character
{
P2=*s;
write_data(*s);
write_com(0x80+0x40+7);//显示位置重新回到调节处
}
if(key1num==2)//若功能键第二次按下
{
min++;//则调整分钟加1
if(min==60)//若满60后将清零
min=0;
write_sfm(3,min);//每调节一次送液晶显示一下
{
sec--;//则调整秒减1
if(sec==-1)//若减到负数则将其重新设置为59
sec=59;
write_sfm(6,sec);//每调节一次送液晶显示一下
write_com(0x80+0x40+7);//显示位置重新回到调节处
{
write_data(cg_1602[num]);
}
write_com(0x84);//年
{
write_data(0);
}
write_com(0x87);//月
{
write_data(1);
}
write_com(0x8a);//日
void timer0() interrupt 1//定时器0中断服务程序
{
TH0=(65536-50000)/256;//再次装定时器初值
TL0=(65536-50000)%256;
count++; //中断次数累加
if(count==20) //20次50毫秒为1秒
{
count=0;
write_com(0x80+0x40+4);//显示位置重新回到调节处
}
if(key1num==3)//若功能键第三次按下
{
hour++;//则调整小时加1
if(hour==24)//若满24后将清零
hour=0;
write_sfm(0,hour);;//每调节一次送液晶显示一下
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit lcdrs = P0^7; //液晶引脚定义
sbit led_cs = P0^6;
sbit lcden = P0^5;
sbit key1 = P3^5;
write_com(0x80+0x40+1);//显示位置重新回到调节处
}
}
}
if(key3==0)
{
delay(5);
if(key3==0)//确认减小键被按下
{
while(!key3);//按键释放
if(key1num==1)//若功能键第一次按下
TR0=1; //启动定时器0
}
/*键盘扫描函数*/
void keyscan()//按键扫描函数
{
keyE =0;
if(key1==0)
{
delay(5);
if(key1==0)//确认功能键被按下
{
key1num++;//功能键按下次数记录
while(!key1);//释放确认
{
while(!key2);//按键释放
if(key1num==1)//若功能键第一次按下
{
sec++; //则调整秒加1
if(sec==60)//若满60后将清零
sec=0;
write_sfm(6,sec);//每调节一次送液晶显示一下
write_data(0x30+hour);//送去液晶显示十位
write_data(0x30+ge); //送去液晶显示个位
}
void write_cg()//写入固定汉字和符号
{
write_com(0x40); //设定CGRAM地址
for(num=0;num<24;num++) //将自定义字型码写入CGRAM中
write_com(0x0c);//取消光标闪烁
TR0=1; //启动定时器使时钟开始走
}
}
}
if(key1num!=0)//只有功能键被按下后,增加和减小键才有效
{
if(key2==0)
{
delay(5);
if(key2==0)//增加键确认被按下
else
address=0xc0+x;//y=1,写第二行
write_com(address);
}
/*void write_char(ucha示
{
write_by_xy(x,y);//先定位
write_data(date);//后写数
write_com(0x38);
write_com(0x0c);
write_com(0x06);
write_com(0x01);
write_string(0,0,"2014");
write_string(5,0,"07");
write_string(8,0,"12");
write_sfm(0,hour);
if(key1num==1)//第一次被按下时
{
TR0=0; //关闭定时器
write_com(0x80+0x40+7);//光标定位到秒位置
write_com(0x0f); //光标开始闪烁
}
if(key1num==2)//第二次按下光标闪烁定位到分钟位置
write_sfm(3,min);
write_sfm(6,sec);
write_cg();
TMOD=0x01;//设置定时器0工作模式1
TH0=(65536-50000)/256;//定时器装初值
TL0=(65536-50000)%256;
EA=1; //开总中断
ET0=1; //开定时器0中断
}
if(key1num==2)//若功能键第二次按下
{
min--;//则调整分钟减1
if(min==-1)//若减到负数则将其重新设置为59
min=59;
write_sfm(3,min);//每调节一次送液晶显示一下
write_com(0x80+0x40+4);//显示位置重新回到调节处
sbit key2 = P3^4;
sbit key3 = P3^3;
sbit keyE = P3^2;
uchar num,key1num,count,hour,min,sec;
uchar code cg_1602[]={ 0x08,0x0f,0x12,0x0f,0x0a,0x1f,0x02,0x02,
write_com(0x80+0x40+1);//显示位置重新回到调节处
}
}
}
}
}
/*主函数*/
void main()
{
led_cs=0;
init_1602();
while(1)
{
keyscan();
}
}
/*中断函数*/
{
write_com(0x80+0x40+4);
}
if(key1num==3)//第三次按下光标闪烁定位到小时位置
{
write_com(0x80+0x40+1);
}
if(key1num==4)//第四次按下
{
key1num=0;//记录按键数清零
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,写第一行