DS1802HE LCD1602实现万年历和温度显示(不用时间芯片)
C语言Lcd1602万年历闹钟Proteus仿真单片机毕业课程电子设计

C语言Lcd1602万年历闹钟Proteus仿真单片机毕业课程电子设计
C语言Lcd1602万年历闹钟Proteus仿真单片机设计
AT89C51+Lcd1602+DS1302+独立按键+蜂鸣器
Lcd1602万年历闹钟。
时间信息来自DS1302,显示采用
Lcd1602,蜂鸣器提供闹音和按键提示音。
液晶上面显示年月日时分秒星期以及闹钟时间。
有时间调节和闹钟调节,可以调节年月日时分秒星期信息以及闹钟时间。
具体介绍如下。
1.做好的仿真图,如下图所示。
2.启动仿真后,先在液晶屏显示系统信息,然后在第二屏显示需要的万年历闹钟信息。
如下图所示!
3.通过单片机右侧的三个按键,即可设置闹钟。
如下图所示。
4.通过单片机左侧的四个按键,来设置年月日时分秒星期的值。
设置时,参数闪烁,同时会有按键提示音。
5.本设计默认套餐1,具体套餐详情请看下面的发货清单。
如需要其它套餐,请联系客服询问。
详情请:点击此处。
LCD1602_显示时间_温度

#include<reg52.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned int#define LCDIO P2sbit DQ=P1^3;//ds18b20与单片机连接口sbit rs=P1^0;sbit rd=P1^1;sbit lcden=P1^2;sbit acc0=ACC^0; //移位时的第0位sbit acc7=ACC^7; //移位时用的第7位uchar second,minute,hour,day,month,year,week,count=0; uchar ReadValue,num,time;uint tvalue;//温度值uchar tflag;uchar code table[]={" 2010-11-29 MON"};uchar code table1[]={" 15:45:00 000.0C"};uchar code table2[]= "THUFRISATSUNMONTUEWES";uchar data disdata[5];sbit DATA=P0^1; //时钟数据接口sbit RST=P0^2;sbit SCLK=P0^0;sbit menu=P3^5; //菜单sbit add=P3^6; //加一sbit dec=P3^7; //减一void delay(uint z){uint x,y;for(x=z;x>0;x--)for(y=110;y>0;y--); }void delay1(uint z){for(;z>0;z--);}void write_com(uchar com) {rs=0;rd=0;lcden=0;P2=com;delay(5);lcden=1;delay(5);lcden=0;}void write_date(uchar date) {rs=1;lcden=0;P2=date;delay(5);lcden=1;delay(5);lcden=0;}void init(){uchar num;lcden=0;write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x01);write_com(0x80);delay(5);write_com(0x80);for(num=0;num<15;num++){write_date(table[num]);delay(5);write_com(0x80+0x40);for(num=0;num<15;num++){write_date(table1[num]);delay(5);}}void Write1302(uchar dat){uchar i;SCLK=0; //拉低SCLK,为脉冲上升沿写入数据做好准备delay1(2); //稍微等待,使硬件做好准备for(i=0;i<8;i++) //连续写8个二进制位数据{DATA=dat&0x01; //取出dat的第0位数据写入1302delay(2); //稍微等待,使硬件做好准备SCLK=1; //上升沿写入数据delay1(2); //稍微等待,使硬件做好准备SCLK=0; //重新拉低SCLK,形成脉冲dat>>=1; //将dat的各数据位右移1位,准备写入下一个数据位 }}void WriteSet1302(uchar Cmd,uchar dat){RST=0; //禁止数据传递SCLK=0; //确保写数居前SCLK被拉低RST=1; //启动数据传输delay1(2); //稍微等待,使硬件做好准备Write1302(Cmd); //写入命令字Write1302(dat); //写数据SCLK=1; //将时钟电平置于已知状态RST=0; //禁止数据传递}uchar Read1302(void){uchar i,dat;delay(2); //稍微等待,使硬件做好准备for(i=0;i<8;i++) //连续读8个二进制位数据{dat>>=1; //将dat的各数据位右移1位,因为先读出的是字节的最低位 if(DATA==1) //如果读出的数据是1dat|=0x80; //将1取出,写在dat的最高位SCLK=1; //将SCLK置于高电平,为下降沿读出delay1(2); //稍微等待SCLK=0; //拉低SCLK,形成脉冲下降沿delay1(2); //稍微等待}return dat; //将读出的数据返回}uchar ReadSet1302(uchar Cmd){uchar dat;RST=0; //拉低RSTSCLK=0; //确保写数居前SCLK被拉低RST=1; //启动数据传输Write1302(Cmd); //写入命令字dat=Read1302(); //读出数据SCLK=1; //将时钟电平置于已知状态RST=0; //禁止数据传递return dat; //将读出的数据返回}void Init_DS1302(void){WriteSet1302(0x8E,0x00); //根据写状态寄存器命令字,写入不保护指令WriteSet1302(0x80,((0/10)<<4|(0%10))); //根据写秒寄存器命令字,写入秒的初始值 WriteSet1302(0x82,((45/10)<<4|(45%10))); //根据写分寄存器命令字,写入分的初始值WriteSet1302(0x84,((15/10)<<4|(15%10))); //根据写小时寄存器命令字,写入小时的初始值WriteSet1302(0x86,((29/10)<<4|(29%10))); //根据写日寄存器命令字,写入日的初始值 WriteSet1302(0x88,((11/10)<<4|(11%10))); //根据写月寄存器命令字,写入月的初始值 WriteSet1302(0x8c,((10/10)<<4|(10%10))); //nianWriteSet1302(0x8a,((4/10)<<4|(4%10)));}void DisplaySecond(uchar x){uchar i,j;i=x/10;j=x%10;write_com(0xc7);write_date(0x30+i);write_date(0x30+j);}void DisplayMinute(uchar x){uchar i,j;i=x/10;j=x%10;write_com(0xc4);write_date(0x30+i);write_date(0x30+j);}void DisplayHour(uchar x) {uchar i,j;i=x/10;j=x%10;write_com(0xc1);write_date(0x30+i);write_date(0x30+j); }void DisplayDay(uchar x) {uchar i,j;i=x/10;j=x%10;write_com(0x89);write_date(0x30+i);write_date(0x30+j); }void DisplayMonth(uchar x) {uchar i,j;i=x/10;j=x%10;write_com(0x86);write_date(0x30+i);write_date(0x30+j); }void DisplayYear(uchar x) {uchar i,j;i=x/10;j=x%10;write_com(0x83);write_date(0x30+i);write_date(0x30+j); }void DisplayWeek(uchar x) { uchar i;x=x*3;write_com(0x8c);for(i=0;i<3;i++){write_date(table2[x]);x++;}}void read_date(void){ReadValue = ReadSet1302(0x81);second=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = ReadSet1302(0x83);minute=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = ReadSet1302(0x85);hour=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = ReadSet1302(0x87);day=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = ReadSet1302(0x89);month=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue = ReadSet1302(0x8d);year=((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F);ReadValue=ReadSet1302(0x8b); //读星期 week=ReadValue&0x07;DisplaySecond(second);DisplayMinute(minute);DisplayHour(hour);DisplayDay(day);DisplayMonth(month);DisplayYear(year);DisplayWeek(week);}void turn_val(char newval,uchar flag,uchar newaddr,uchar s1num){newval=ReadSet1302(newaddr); //读取当前时间newval=((newval&0x70)>>4)*10+(newval&0x0f); //将bcd码转换成十进制if(flag) //判断是加一还是减一{newval++;switch(s1num){ case 1: if(newval>99) newval=0;DisplayYear(newval);break;case 2: if(newval>12) newval=1;DisplayMonth(newval);break;case 3: if(newval>31) newval=1;DisplayDay(newval);break;case 4: if(newval>6) newval=0;DisplayWeek(newval);break;case 5: if(newval>23) newval=0;DisplayHour(newval);case 6: if(newval>59) newval=0;DisplayMinute(newval);break;case 7: if(newval>59) newval=0;DisplaySecond(newval);break;default:break;}}else{newval--;switch(s1num){ case 1: if(newval==0) newval=99;DisplayYear(newval);break;case 2: if(newval==0) newval=12;DisplayMonth(newval);break;case 3: if(newval==0) newval=31;DisplayDay(newval);break;case 4: if(newval<0) newval=6;DisplayWeek(newval);case 5: if(newval<0) newval=23;DisplayHour(newval);break;case 6: if(newval<0) newval=59;DisplayMinute(newval);break;case 7: if(newval<0) newval=59;DisplaySecond(newval);break;default:break;}}WriteSet1302((newaddr-1),((newval/10)<<4)|(newval%10)); //将新数据写入寄存器}//键盘扫描程序//*******************************************void key_scan(void){ uchar miao,s1num=0;if(menu==0){delay(5);if(menu==0){while(!menu);s1num++;while(1){if(menu==0){delay(5);if(menu==0){while(!menu);s1num++;}}rd=0;miao=ReadSet1302(0x81);second=miao;WriteSet1302(0x80,miao|0x80);write_com(0x0f);//光标闪射if(s1num==1){ year=ReadSet1302(0x8d);write_com(0x80+4); //年光标if(add==0){delay(3);if(add==0){ while(!add);turn_val(year,1,0x8d,1);}}if(dec==0){delay(3);if(dec==0){ while(!dec);turn_val(year,0,0x8d,1);}}}if(s1num==2){month=ReadSet1302(0x89);write_com(0x80+7); //月光标if(add==0){delay(3);if(add==0){ while(!add);turn_val(month,1,0x89,2); }}if(dec==0){delay(3);if(dec==0){ while(!dec);turn_val(month,0,0x89,2); }}}if(s1num==3){ day=ReadSet1302(0x87);write_com(0x80+10);//日光标if(add==0){delay(3);if(add==0){ while(!add);turn_val(day,1,0x87,3);}}if(dec==0){delay(3);if(dec==0){ while(!dec);turn_val(day,0,0x87,3); //写入日寄存器 }}}if(s1num==4){ week=ReadSet1302(0x8b);write_com(0x80+14); //星期光标if(add==0){delay(3);if(add==0){ while(!add);turn_val(week,1,0x8b,4);}}if(dec==0){delay(3);if(dec==0){ while(!dec);turn_val(week,0,0x8b,4);}}}if(s1num==5){ hour=ReadSet1302(0x85);write_com(0x80+0x40+2); //时光标if(add==0){delay(3);if(add==0){ while(!add);turn_val(hour,1,0x85,5);}}if(dec==0){delay(3);if(dec==0){ while(!dec);turn_val(hour,0,0x85,5);}}}if(s1num==6)//调时间分{ minute=ReadSet1302(0x83);write_com(0x80+0x40+5);if(add==0){delay(5);if(add==0){ while(!add);turn_val(minute,1,0x83,6); //写入分寄存器 }}if(dec==0){delay(3);if(dec==0){ while(!dec);turn_val(minute,0,0x83,6); //写入分寄存器 }}}if(s1num==7)//调时间秒{ second=ReadSet1302(0x81);write_com(0x80+0x40+8);//秒光标if(add==0){delay(3);if(add==0){ while(!add);if(second==0x60)second=0x00;turn_val(second,1,0x81,7);}}if(dec==0){delay(3);if(dec==0){ while(!dec);turn_val(second,0,0x81,7);}}}if(s1num==8){ miao=ReadSet1302(0x81);second=miao;WriteSet1302(0x80,second&0x7f);s1num=0;//s1num清零//write_com(0x0c);//光标不闪烁//break;}}}}}void delay_18B20(unsigned int i)//延时1微秒{while(i--);}void ds1820rst()/*ds1820复位*/{ unsigned char x=0;DQ = 1; //DQ复位delay_18B20(4); //延时DQ = 0; //DQ拉低delay_18B20(100); //精确延时大于480usDQ = 1; //拉高delay_18B20(40);}uchar ds1820rd()/*读数据*/{ unsigned char i=0;unsigned char dat = 0;for (i=8;i>0;i--){ DQ = 0; //给脉冲信号dat>>=1;DQ = 1; //给脉冲信号if(DQ)dat|=0x80;delay_18B20(10);}return(dat);}void ds1820wr(uchar wdata)/*写数据*/ {unsigned char i=0;for (i=8; i>0; i--){ DQ = 0;DQ = wdata&0x01;delay_18B20(10);DQ = 1;wdata>>=1;}}read_temp()/*读取温度值并转换*/{uchar a,b;ds1820rst();ds1820wr(0xcc);//*跳过读序列号*/ds1820wr(0x44);//*启动温度转换*/ds1820rst();ds1820wr(0xcc);//*跳过读序列号*/ds1820wr(0xbe);//*读取温度*/a=ds1820rd();b=ds1820rd();tvalue=b;tvalue<<=8;tvalue=tvalue|a;if(tvalue<0x0fff)tflag=0;else{tvalue=~tvalue+1;tflag=1;}tvalue=tvalue*(0.425);//温度值扩大10倍,精确到1位小数return(tvalue);}void ds1820disp()//温度值显示{ uchar flagdat;disdata[0]=tvalue/1000+0x30;//百位数disdata[1]=tvalue%1000/100+0x30;//十位数disdata[2]=tvalue%100/10+0x30;//个位数disdata[3]=tvalue%10+0x30;//小数位if(tflag==0)flagdat=0x20;//正温度不显示符号elseflagdat=0x2d;//负温度显示负号:-if(disdata[0]==0x30){disdata[0]=0x20;//如果百位为0,不显示if(disdata[1]==0x30){disdata[1]=0x20;//如果百位为0,十位为0也不显示}}write_com(0xc9);write_date(flagdat);//显示符号位write_com(0xca);write_date(disdata[0]);//显示百位write_com(0xcb);write_date(disdata[1]);//显示十位write_com(0xcc);write_date(disdata[2]);//显示个位write_com(0xcd);write_date(0x2e);//显示小数点write_com(0xce);write_date(disdata[3]);//显示小数位write_com(0xcf);write_date('C');}void main(){init();Init_DS1302(); //将1302初始化read_temp();//读取温度ds1820disp();//显示while(1){read_date();key_scan();read_temp();//读取温度ds1820disp();//显示}}完。
液晶万年历的显示

毕业设计(论文)设计(论文)题目:液晶万年历的显示指导教师:学生专业:班级:学生姓教研室主任:信息工程学院二〇一〇年 11 月 10 日摘要随着电子技术的迅速发展,特别是大规模集成电路的出现,人类生活发生了根本性的变化。
以单片机技术为核心的产品已走进了千家万户,数字万年历的出现更是给人们的生活带来诸多方便,本文就实现了基于AT89C52单片机的多功能数字万年历的设计。
本设计以AT89C52单片机技术为核心,以各种硬件电路为基础,软件采用C语言进行编写,为了便于扩展和更改,采用模块化的程序设计方法,使程序设计的逻辑关系更加简洁明了,系统升级更加简单方便。
系统以LCD1602液晶模块为载体显示数据,所以具有人性化的操作界面和美观的页面效果;可以显示公历日期、时间、农历日期、星期、温度。
用户可以通过按键调节系统时间、设定时间。
左后完成了组装与调试。
关键词:AT89C52 LCD1602AbstractWith the rapid development of electronic technology, especially the emergence of large-scale integrated circuits, human life there has been a fundamental change. The products have entered tens of thousands of household whose core is single-chip technology, the emergence of digital calendar is to bring a lot of people’s lives easy, This article worked out a design of multi-functional digital calendar based on the single chip AT89S52.The design of single-chip AT89S52 technology as the core, based on a variety of hardware circuitry and used assembly language for the preparation of software, In order to facilitate the expansion and changes to the design ,procedures for the used of modular design method so that the logic of the relationship between program design more concise, the system more simple and convenient to upgrade. System use dot-matrix LCD Module 1602 font display as the data ,time ,Chinese data, week ,temperature, and has alarm functions. User can adjust the system time or set the alarm time through the button . I completed the assembly and commissioning finally.Keywords:AT89C51chip LCD1602目录第一章绪论 (1)1.1单片机的发展 (1)1.2设计任务 (1)1.3设计意义 (1)1.4设计方案思路: (2)1.5系统原理 (2)第二章硬件电路设计 (3)2.1芯片DS1302: (3)2.1.1、D S1302简介: (3)2.1.2、D S1302工作原理: (4)2.2温度传感器: (4)2.2.1、温度传感器(DS18B20芯片)简介: (4)2.2.2、DS18B20的主要特征: (5)2.2.3、引脚定义: (5)2.2.4、DS18B20工作原理及应用: (6)2.3液晶显示器 (6)2.3.1引脚说明: (6)2.3.2液晶显示器的工作原理: (8)2.4AT89C52主控模块: (8)2.4.1㈠引脚功能特性: (9)2.4.2AT89S52的总线结构 (10)2.4.3AT89C51的功能描述 (11)2.5硬件原理框图 (11)2.5.1系统硬件概述 (12)2.5.2主要单元电路 (12)第三章系统软件设计 (14)3.1软件开发流程 (14)3.1.1系统的程序流程图 (14)3.1.2时钟设定模块设计流程图 (15)3.1.3温度设定模块设计流程图: (22)第四章设计调试 (27)4.1开发环境介绍: (27)4.2 PROTEUS调试与仿真 (27)致谢 (30)附录: (31)液晶显示部分子程序: (31)按键部分子程序: (34)第一章绪论1.1单片机的发展单片机是单片微型计算机的简称,也就是把微处理器(CPU)、一定容量的程序存储器(ROM)和数据存储器(RAM)、输入/输出接口(I/O)、时钟及其他一些计算机外围电路,通过总线连接在一起并集成在一个芯片上构成的微型计算机系统。
1602显示温度+万年历

程序功能:1602显示温度、时间(简称万年历)废话不多说,先上图希望大家多多捧场#include<reg51.h>#include<lcd1602.h>//#include<keyscan.h>#include<ds1302.h>#define uchar unsigned char#define uint unsigned intuchar init_time[]={21,50,30,11,12,31,6}; //23:59:30 11-12-31 6 uchar current_time[]={0,0,0,0,0,0,0};uchar num=0;sbit up=P1^1;sbit donw=P1^2;sbit set=P1^3;void read_current_time() //读取当前时间{current_time[2]=read_1302(0x81);current_time[1]=read_1302(0x83);current_time[0]=read_1302(0x85);current_time[3]=read_1302(0x8d);current_time[4]=read_1302(0x89);current_time[5]=read_1302(0x87);}void write_hour_min_sec(uchar add,uchar date) //时分秒{uchar s,g;s=date/16;g=date%16;lcd_wcom(0x80+0x40+add);lcd_wdat(0x30+s);lcd_wdat(0x30+g);}void write_yea_mon_dat(uchar add,uchar date) //年月日{uchar s,g;s=date/16;g=date%16;lcd_wcom(0x80+add);lcd_wdat(0x30+s);lcd_wdat(0x30+g);}void dis_dat_1602() //显示{lcd_wcom(0x80);lcd_wdat('2');lcd_wdat('0');write_yea_mon_dat(2,current_time[3]);lcd_wdat('-');write_yea_mon_dat(5,current_time[4]);lcd_wdat('-');write_yea_mon_dat(8,current_time[5]);lcd_wcom(0x80+11);lcd_wdat('W');lcd_wdat('e');lcd_wdat('e');lcd_wdat('k');write_hour_min_sec(0,current_time[0]);lcd_wdat(':');write_hour_min_sec(3,current_time[1]);lcd_wdat(':');write_hour_min_sec(6,current_time[2]);}void delay(uint z) //延时函数{uint x,y;for(x = z;x>0;x--)for(y = 124;y>0;y--);}void keyscan(){if(set==0) //判断按键是否按下{delay(5); //消除抖动if(set==0){num++;if(num==7){num=0;current_time[2]=0;write_1302(0x8e,0x00);write_1302(0x80,current_time[2]);write_1302(0x8e,0x80);}}if(up==0){delay(5);if(up==0){while(!up); //一直检测,直到up=1if(num==1){// lcd_wcom(0x80+0x44);// lcd_wcom(0x0e); //光标闪烁// lcd_wdat(current_time[1]);current_time[1]=read_1302(0x83);current_time[1]++;if(current_time[1]&0x0f>9)current_time[1]=current_time[1]+6;if(current_time[1]>=60)current_time[1]=0x00;write_1302(0x8e,0x80);write_1302(0x82,current_time[1]);write_1302(0x8e,0x80);}}}}}void main(){uchar i,d;TMOD=0x01;TH0=0xfc;TL0=0x18;EA=1;ET0=1;TR0=1;for(i=0;i<7;i++) //十进制转BCD码{d=init_time[i]/10;init_time[i]=init_time[i]%10;init_time[i]=init_time[i]+d*16;}write_1302(0x8e,0x00);write_1302(0x80,init_time[2]);write_1302(0x82,init_time[1]);write_1302(0x84,init_time[0]);write_1302(0x86,init_time[5]);write_1302(0x88,init_time[4]);write_1302(0x8a,init_time[6]);write_1302(0x8c,init_time[3]);write_1302(0x8e,0x80);lcd_init();while(1){dis_dat_1602();read_current_time();}}void timer0() interrupt 1{TH0=0xfc;TL0=0x18;keyscan();}#ifndef __lcd1602_H__#define __lcd1602_H__#include<reg51.h>#include<intrins.h>#define uchar unsigned char#define uint unsigned intsbit rs=P2^6;sbit rw=P2^5;sbit en=P2^7;void delayled(int n){int x,y;for(x=n;x>0;x--){for(y=110;y>0;y--);}}void lcd_wcom(uchar com){rs=0;rw=0;P0=com;delayled(5);en=1;en=0;}void lcd_wdat(uchar dat){rs=1;rw=0;P0=dat;delayled(5);en=1;en=0;}void lcd_init(){lcd_wcom(0x38);lcd_wcom(0x0c);lcd_wcom(0x06);lcd_wcom(0x01);}#endif#ifndef __ds1302_H__#define __ds1302_H__#include<reg51.h>#define uchar unsigned char#define uint unsigned intsbit rst=P3^5;sbit sclk=P3^6;sbit io=P3^4;//写入一个字节到DS1302void write_byte_1302(uchar temp){uchar i;for(i=0;i<8;i++){sclk=0;io=temp&0x01;temp>>=1;sclk=1;}}//写入到DS1302void write_1302(uchar address,uchar dat) {rst=0;sclk=0;rst=1;write_byte_1302(address);write_byte_1302(dat);rst=0;sclk=0;sclk=1;io=1;}//读出ds1302数据uchar read_1302(uchar address){uchar i,temp;rst=0;sclk=0;rst=1;write_byte_1302(address);for(i=0;i<8;i++){sclk=0;temp>>=1;if(io==1)temp|=0x80;sclk=1;}rst=0;sclk=0;sclk=1;io=0;io=1;return temp;}#endif#ifndef __keyscan_H__#define __keyscan_H__#include<reg51.h>#include<ds1302.h>#include<lcd1602.h>#define uchar unsigned char#define uint unsigned intuchar current_time[]={0,0,0,0,0,0,0};void delay(uint z) //延时函数{uint x,y;for(x = z;x>0;x--)for(y = 124;y>0;y--);}void keyscan(){uchar num;if(set==0) //判断按键是否按下{delay(5); //消除抖动if(set==0){num++;if(num==7){num==0;current_time[2]=0;write_1302(0x8e,0x00);write_1302(0x80,current_time[2]);write_1302(0x8e,0x80);}}if(up==0){delay(5);if(up==0){while(!up); //一直检测,直到up=1if(num==1){lcd_wcom(0x80+0x44);lcd_wcom(0x0e); //光标闪烁lcd_wdat(current_time[1]);current_time[1]=read_1302(0x83);current_time[1]++;if(current_time[1]&0x0f>9)current_time[1]=current_time[1]+6;if(current_time[1]>=60)current_time[1]=0x00;write_1302(0x8e,0x80);write_1302(0x82,current_time[1]);write_1302(0x8e,0x80);}}}}}#endif。
简析基于DS1302和LCD1602的万年历系统设计论文

简析基于DS1302和LCD1602的万年历系统设计论文简析基于DS1302和LCD1602的万年历系统设计论文0引言在日常生活中,无论哪一行业,哪一领域,时间授时都是不可或缺的。
从古老的钟表到现代的电子设备都提供时间授时的功能。
因此,对于单片机学习者来说,设计并实现一款低成本的,有操作性的,提供年,月,日,小时,分,秒,星期等基本计时功能的万年历系统,显得特别实用,特别有意义。
1总体设计及原理图万年历的基本功能一是要提供年月日等基本时间项的授时;二是可以修改时间项。
基于以上两个功能,我们万年历总体设计方案。
万年历有时钟计时模块,显示模块,调整时钟模块和控制器4部分组成。
接下来的任务就是对以上模块进行选型。
低成本,可操作是选型的标准。
对于控制器,选择最常用的C51系列单片机STC89C52。
STC89C52是由宏品科技生产的是一种低功耗8位基于经典C51内核的微处理器,具有8 KhyteFLASH存储器,512 byte RAM , 4 KByte EEPROM , 32位通用IO接口,可以直接用串口下载程序。
时钟模块选择由dallas公司生产的时钟芯片DS1302,DS1302是一款支持年月日,小时分秒,星期,闰年补偿的实时时钟芯片;其简单三线结构可以很方便地与单片机通用IO相连,进行串行总线读写传输。
显示模块选择16x2的字符点阵模块LCD 16020LC D 1602的控制器以Hitachi公司生产的HD44780芯片最为常见。
LC D 1602引脚主要包括3类,第1类是电源。
第2类是8位数据I/0通道,用于读写LC D 1602。
第3类是3根控制线,RS,R/W和E,其中,RS和R/W是用于实现LCD不同操作的。
E是作为读写的启动信号,有点类似一个时钟信号,数据要写人LC D 1602或从LCD 1602读出数据均需要首先置E信号为高至少1 s,然后置低。
调整时钟模块设计了4个轻触开关,用于设定和修改时间项。
DSHELCD实现万年历和温度显示(不用时间芯片)

#include<reg52.h>#include<intrins.h>#include <math.h>#define uchar unsigned char#define uint unsigned intuchar code table[]="--Figo"。
//uchar code table1[]=""。
sbit lcden=P3^4。
sbit lcdrs=P3^5。
sbit dula=P2^6。
sbit wela=P2^7。
sbit ds=P1^7。
sbit key1=P1^0。
sbit key2=P1^1。
sbit key3=P1^2。
sbit key4=P1^3。
int tempValue。
int s_1=1000。
unsigned char FunKeyFlag=6,keypress。
#define key_vaule1 0x01#define key_vaule2 0x02#define key_vaule3 0x03#define key_vaule4 0x04uchar num。
int ms_10=10。
int flag=0。
int s_1_1=1000。
uint sec=55。
uint min=9。
uint hour=22。
uint nian=2014。
uint yue=8。
uint ri=20。
uint xingqi=3。
//延时函数, 对于11.0592MHz时钟, 例i=10,则大概延时10ms. void delay_wendu(unsigned int i){unsigned int j。
while(i--){for(j = 0。
j < 125。
j++)。
}}//初始化DS18B20//让DS18B20一段相对长时间低电平, 然后一段相对非常短时间高电平, 即可启动void dsInit(){//对于11.0592MHz时钟, unsigned int型的i, 作一个i++操作的时间大于?usunsigned int i。
LCD1602液晶显示带汉字的万年历程序51单片机

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); //自定义字符使用}第二段程序为借用别人的,呵呵。
DS18B20温度计 c程序 lcd1602显示

2007-12-14 19:05温度值精确到0.1度,lcd1602显示仿真电路图如下c程序如下:#include<reg51.h>#define uchar unsigned char#define uint unsigned intsbit DQ=P3^7;//ds18b20与单片机连接口sbit RS=P3^0;sbit RW=P3^1;sbit EN=P3^2;unsigned char code str1[]={"temperature: "};unsigned char code str2[]={" "};uchar data disdata[5];uint tvalue;//温度值uchar tflag;//温度正负标志/*************************lcd1602程序**************************/ void delay1ms(unsigned int ms)//延时1毫秒(不够精确的){unsigned int i,j;for(i=0;i<ms;i++)for(j=0;j<100;j++);}void wr_com(unsigned char com)//写指令//{ delay1ms(1);RS=0;RW=0;EN=0;P2=com;delay1ms(1);EN=1;delay1ms(1);EN=0;}void wr_dat(unsigned char dat)//写数据//{ delay1ms(1);;RS=1;RW=0;EN=0;P2=dat;delay1ms(1);EN=1;delay1ms(1);EN=0;}void lcd_init()//初始化设置//{delay1ms(15);wr_com(0x38);delay1ms(5);wr_com(0x08);delay1ms(5);wr_com(0x01);delay1ms(5);wr_com(0x06);delay1ms(5);wr_com(0x0c);delay1ms(5);}void display(unsigned char *p)//显示//{while(*p!='\0'){wr_dat(*p);p++;delay1ms(1);}}init_play()//初始化显示{ lcd_init();wr_com(0x80);display(str1);wr_com(0xc0);display(str2);}/******************************ds1820程序***************************************/ void delay_18B20(unsigned int i)//延时1微秒{while(i--);}void ds1820rst()/*ds1820复位*/{ unsigned char x=0;DQ = 1; //DQ复位delay_18B20(4); //延时DQ = 0; //DQ拉低delay_18B20(100); //精确延时大于480usDQ = 1; //拉高delay_18B20(40);}uchar ds1820rd()/*读数据*/{ unsigned char i=0;unsigned char dat = 0;for (i=8;i>0;i--){ DQ = 0; //给脉冲信号dat>>=1;DQ = 1; //给脉冲信号if(DQ)dat|=0x80;delay_18B20(10);}return(dat);}void ds1820wr(uchar wdata)/*写数据*/{unsigned char i=0;for (i=8; i>0; i--){ DQ = 0;DQ = wdata&0x01;delay_18B20(10);DQ = 1;wdata>>=1;}}read_temp()/*读取温度值并转换*/{uchar a,b;ds1820rst();ds1820wr(0xcc);//*跳过读序列号*/ds1820wr(0x44);//*启动温度转换*/ds1820rst();ds1820wr(0xcc);//*跳过读序列号*/ds1820wr(0xbe);//*读取温度*/a=ds1820rd();b=ds1820rd();tvalue=b;tvalue<<=8;tvalue=tvalue|a;if(tvalue<0x0fff)tflag=0;else{tvalue=~tvalue+1;tflag=1;}tvalue=tvalue*(0.625);//温度值扩大10倍,精确到1位小数return(tvalue);}/*******************************************************************/ void ds1820disp()//温度值显示{ uchar flagdat;disdata[0]=tvalue/1000+0x30;//百位数disdata[1]=tvalue%1000/100+0x30;//十位数disdata[2]=tvalue%100/10+0x30;//个位数disdata[3]=tvalue%10+0x30;//小数位if(tflag==0)flagdat=0x20;//正温度不显示符号elseflagdat=0x2d;//负温度显示负号:-if(disdata[0]==0x30){disdata[0]=0x20;//如果百位为0,不显示if(disdata[1]==0x30){disdata[1]=0x20;//如果百位为0,十位为0也不显示}}wr_com(0xc0);wr_dat(flagdat);//显示符号位wr_com(0xc1);wr_dat(disdata[0]);//显示百位wr_com(0xc2);wr_dat(disdata[1]);//显示十位wr_com(0xc3);wr_dat(disdata[2]);//显示个位wr_com(0xc4);wr_dat(0x2e);//显示小数点wr_com(0xc5);wr_dat(disdata[3]);//显示小数位}/********************主程序***********************************/void main(){ init_play();//初始化显示while(1){read_temp();//读取温度ds1820disp();//显示}}。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include<reg52.h>#include<intrins.h>#include <math.h>#define uchar unsigned char#define uint unsigned intuchar code table[]="--Figo";//uchar code table1[]="";sbit lcden=P3^4;sbit lcdrs=P3^5;sbit dula=P2^6;sbit wela=P2^7;sbit ds=P1^7;sbit key1=P1^0;sbit key2=P1^1;sbit key3=P1^2;sbit key4=P1^3;int tempValue;int s_1=1000;unsigned char FunKeyFlag=6,keypress;#define key_vaule1 0x01#define key_vaule2 0x02#define key_vaule3 0x03#define key_vaule4 0x04uchar num;int ms_10=10;int flag=0;int s_1_1=1000;uint sec=55;uint min=9;uint hour=22;uint nian=2014;uint yue=8;uint ri=20;uint xingqi=3;//延时函数, 对于11.0592MHz时钟, 例i=10,则大概延时10ms. void delay_wendu(unsigned int i){unsigned int j;while(i--){for(j = 0; j < 125; j++);}}//初始化DS18B20//让DS18B20一段相对长时间低电平, 然后一段相对非常短时间高电平, 即可启动void dsInit(){//对于11.0592MHz时钟, unsigned int型的i, 作一个i++操作的时间大于?us unsigned int i;ds = 0;i = 100; //拉低约800us, 符合协议要求的480us以上while(i>0) i--;ds = 1; //产生一个上升沿, 进入等待应答状态i = 4;while(i>0) i--;}void dsWait(){unsigned int i;while(ds);while(~ds);//检测到应答脉冲i = 4;while(i > 0) i--;}//向DS18B20读取一位数据//读一位, 让DS18B20一小周期低电平, 然后两小周期高电平,//之后DS18B20则会输出持续一段时间的一位数据bit readBit(){unsigned int i;bit b;ds = 0;i++;//延时约8us, 符合协议要求至少保持1usds = 1;i++; i++;//延时约16us, 符合协议要求的至少延时15us以上b = ds;i = 8;while(i>0) i--; //延时约64us, 符合读时隙不低于60us要求return b;}//读取一字节数据, 通过调用readBit()来实现unsigned char readByte()unsigned int i;unsigned char j, dat;dat = 0;for(i=0; i<8; i++){j = readBit();//最先读出的是最低位数据dat = (j << 7) | (dat >> 1);}return dat;}//向DS18B20写入一字节数据void writeByte(unsigned char dat){unsigned int i;unsigned char j;bit b;for(j = 0; j < 8; j++){b = dat & 0x01;dat >>= 1;//写"1", 将DQ拉低15us后, 在15us~60us内将DQ拉高, 即完成写1if(b){ds = 0;i++;i++; //拉低约16us, 符号要求15~60us内ds = 1;i = 8;while(i>0)i--; //延时约64us, 符合写时隙不低于60us要求}else //写"0", 将DQ拉低60us~120usds = 0;i = 8; while(i>0) i--;//拉低约64us, 符号要求ds = 1;i++;i++;//整个写0时隙过程已经超过60us, 这里就不用像写1那样, 再延时64us了}}//向DS18B20发送温度转换命令void sendChangeCmd()dsInit(); //初始化DS18B20, 无论什么命令, 首先都要发起初始化dsWait(); //等待DS18B20应答delay_wendu(1); //延时1ms, 因为DS18B20会拉低DQ 60~240us作为应答信号writeByte(0xcc); //写入跳过序列号命令字Skip RomwriteByte(0x44); //写入温度转换命令字Convert T}//向DS18B20发送读取数据命令void sendReadCmd(){dsInit();dsWait();delay_wendu(1);writeByte(0xcc); //写入跳过序列号命令字Skip RomwriteByte(0xbe); //写入读取数据令字Read Scratchpad}//获取当前温度值int getTmpValue(){unsigned int tmpvalue;int value; //存放温度数值float t;unsigned char low, high;sendReadCmd();//连续读取两个字节数据low = readByte();high = readByte();//将高低两个字节合成一个整形变量//计算机中对于负数是利用补码来表示的//若是负值, 读取出来的数值是用补码表示的, 可直接赋值给int型的valuetmpvalue = high;tmpvalue <<= 8;tmpvalue |= low;value = tmpvalue;//使用DS18B20的默认分辨率12位, 精确度为0.0625度, 即读回数据的最低位代表0.0625度t = value * 0.0625;//将它放大100倍, 使显示时可显示小数点后两位, 并对小数点后第三进行4舍5入//如t=11.0625, 进行计数后, 得到value = 1106, 即11.06 度//如t=-11.0625, 进行计数后, 得到value = -1106, 即-11.06 度value = t * 100 + (value > 0 ? 0.5 : -0.5); //大于0加0.5, 小于0减0.5return value;}void HandleKeyPress() ;void KeyScan() //按键扫描{static unsigned char state=0;unsigned char temp;if (key1==0) temp=key_vaule1;else if (key2==0) temp=key_vaule2;else if (key3==0) temp=key_vaule3;else if (key4==0) temp=key_vaule4;else temp=0;switch (state){case 0: if(temp!=0) state=1;break;case 1: state=2; break;case 2: if(temp!=0) {state=3;keypress=temp;} else state=0; break;case 3: if(temp==0) {HandleKeyPress();state=0;} break;}}void HandleKeyPress() //按键功能的设置{ if (keypress==key_vaule1) //功能键的设置{FunKeyFlag=(FunKeyFlag+1)%7;}else if (keypress==key_vaule2) //第二个按键的设置{switch (FunKeyFlag){case 0:hour++;if(hour>23)hour=0;break;case 1:min++;if(min>59)min=0;break;case 2:sec++;if(sec>59)min=0;break;case 3:ri++;xingqi++;if(ri>30)ri=1;if(xingqi>7)xingqi=1;break;case 4:yue++;if(yue>12)yue=1;break;case 5:nian++;break;}}else if (keypress==key_vaule3) //第三个按键的设置{switch (FunKeyFlag){case 0:hour--;if(hour<0)hour=23;break;case 1:min--;if(min<0)min=59;break;case 2:sec--;if(sec<0)sec=59;break;case 3:ri--;xingqi--;if(ri<1)ri=31;if(xingqi<1)xingqi=1;break;case 4:yue--;if(yue<1)yue=12;break;case 5:nian--;break;}}else if (keypress==key_vaule4) //第四个按键的设置{switch (FunKeyFlag){case 0:hour=0;break;case 1:min=0;break;case 2:sec=0;break;case 3:ri=1;xingqi=1;break;case 4:yue=1;break;case 5:nian=2000;break;}}}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;P0=com;delay(5);lcden=1;delay(5);lcden=0;}void write_data(uchar date){lcdrs=1;P0=date;flag=1;delay(5);lcden=1;delay(5);lcden=0;}shijian_show(uchar wei,shijian ){uchar shi,ge;shi=shijian/10;ge=shijian%10;write_com(0x80+0x40+wei);write_data(0x30+shi);write_data(0x30+ge);}rili_show(uchar wei,rili ){uchar shi,ge;shi=rili/10;ge=rili%10;write_com(0x80+wei);write_data(0x30+shi);write_data(0x30+ge);}nian_show(uchar wei,shijian ){uchar shi,ge,qian,bai;qian=shijian/1000;bai=shijian%1000/100;shi=shijian%100/10;ge=shijian%10;write_com(0x80+wei);write_data(0x30+qian);write_data(0x30+bai);write_data(0x30+shi);write_data(0x30+ge);}wendu_show(uchar wei,int wendu ) {uchar shi,ge,qian,bai,xiao;qian=wendu/10000;bai=wendu%10000/1000;shi=wendu%1000/100;ge=wendu%100/10;xiao=wendu%10;write_com(0x80+0x40+wei);write_data(0x30+qian);write_data(0x30+bai);write_data(0x30+shi);// write_com(0x80+0x40+wei+1);write_data(0xdf);write_data(0x30+ge);write_data(0x30+xiao);}void init(){P0=0;dula=0;wela=0;lcden=0;write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x01);}void week_show() //星期的显示{write_com(0x80+12);switch (xingqi){case 1:{write_data('M');write_data('o');write_data('n');}break;case 2:{write_data('T');write_data('u');write_data('e');}break;case 3:{write_data('W');write_data('e');write_data('d');}break;case 4:{write_data('T');write_data('h');write_data('u');}break;case 5:{write_data('F');write_data('r');write_data('i');}break;case 6:{write_data('S');write_data('a');write_data('t');}break;case 7:{write_data('S');write_data('u');write_data('n');}break;}}void main(){TMOD = 0x01;TH0 = (65536-1000)/256;TL0 = (65536-1000)%256;EA = 1;ET0 = 1;TR0 = 1;init();while(1){nian_show(1,nian);rili_show(6,yue);rili_show(9,ri);shijian_show(0,hour);shijian_show(3,min);shijian_show(6,sec);write_com(0x80+5);write_data(0x2d);write_com(0x80+8);write_data(0x2d);write_com(0x80+0x40+2);write_data(0x3A);write_com(0x80+0x40+5);write_data(0x3A);week_show();wendu_show(10,tempValue);}}void time() interrupt 1{TH0 = (65536-1000)/256;TL0 = (65536-1000)%256;ms_10--;s_1_1--;if(s_1_1<=0){s_1_1=1000; sendChangeCmd();//显示5次tempValue = getTmpValue(); //计算温度}if(ms_10<=0) //按键扫描{ms_10=10;KeyScan();}s_1--;if(s_1<=0){s_1=1000;sec++;if(sec>59){sec=0;min++;if(min>59){min=0;hour++;if(hour>23){hour=0;ri++;xingqi++;if(xingqi>7){xingqi=1;}if((yue==1||yue==3||yue==5||yue==7||yue==8||yue==10||yue==12)&&ri>31){ri=1;yue++;}else if(yue==2){if(nian%100!=0){if(nian%4==0){if(ri>29){ri=1;yue++;}}else if(nian%4!=0){if(ri>28){ri=1;yue++;}}}else if(nian%100==0){if(nian%400==0){if(ri>29){ri=1;yue++;}}else if(nian%400!=0){if(ri>28){ri=1;yue++;}}}}else if((yue==4||yue==6||yue==9||yue==11)&&ri>30){ri=1;yue++;}if(yue>12){nian++;yue=1;}}}}}}。