基于stc51单片机的LCD1602显示时间_的电子万年历(显示当前温度)

合集下载

基于51单片机的1602日历时钟程序

基于51单片机的1602日历时钟程序
x &= 0x0f ; //x值限定在0~15之间
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)

LCD1602_显示时间_温度

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();//显示}}完。

基于stc51单片机的LCD1602显示时间的电子万年历(显示

基于stc51单片机的LCD1602显示时间的电子万年历(显示

1 课设所需软件简介1.1 Keil uVision4的简要介绍2009年2月发布Keil μVision4,Keil μVision4引入灵活的窗口管理系统,使开发人员能够使用多台监视器,并提供了视觉上的表面对窗口位置的完全控制的任何地方。

新的用户界面可以更好地利用屏幕空间和更有效地组织多个窗口,提供一个整洁,高效的环境来开发应用程序。

新版本支持更多最新的ARM芯片,还添加了一些其他新功能。

2011年3月ARM公司发布最新集成开发环境RealView MDK开发工具中集成了最新版本的Keil uVision4,其编译器、调试工具实现与ARM器件的最完美匹配。

Keil C51开发系统基本知识Keil C51开发系统基本知识1. 系统概述Keil C51软件提供丰富的库函数和功能强大的集成开发调试工具,全Windows界面。

另外重要的一点,只要看一下编译后生成的汇编代码,就能体会到Keil C51生成的目标代码效率非常之高,多数语句生成的汇编代码很紧凑,容易理解。

在开发大型软件时更能体现高级语言的优势。

下面详细介绍Keil C51开发系统各部分功能和使用。

2. Keil C51单片机软件开发系统的整体结构C51工具包的整体结构,uVision与Ishell分别是C51 for Windows和for Dos 的集成开发环境(IDE),可以完成编辑、编译、连接、调试、仿真等整个开发流程。

开发人员可用IDE本身或其它编辑器编辑C或汇编源文件。

然后分别由C51及C51编译器编译生成目标文件(.OBJ)。

目标文件可由LIB51创建生成库文件,也可以与库文件一起经L51连接定位生成绝对目标文件(.ABS)。

ABS文件由OH51转换成标准的Hex文件,以供调试器dScope51或tScope51使用进行源代码级调试,也可由仿真器使用直接对目标板进行调试,也可以直接写入程序存贮器如EPROM中。

使用独立的Keil仿真器时,注意事项:* 仿真器标配11.0592MHz的晶振,但用户可以在仿真器上的晶振插孔中换插其他频率的晶振。

51单片机万年历1602显示时间温度按键调时(焊接前备份)

51单片机万年历1602显示时间温度按键调时(焊接前备份)
hmin_fen++;
}
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功能最全的电子钟程序(lcd1602)

基于c51功能最全的电子钟程序(lcd1602)

功能最全的电子钟【单片机】c51数字时钟(带年月日显示)摘要:本设计以单片机为核心,lcd1602显示。

采用独立键盘输入能任意修改当前时间日期和设定闹钟时间。

具有显示年月日(区分闰年和二月),闹钟报警和整点报时功能主程序:/********************************************************************************************************************************************************************************* ****************************************** lcd1602电子钟********************************************************************************************************************************** *************************************************************************************************** ********************/# include <reg52.h># include "lcd16024.h"sbit key1 = P2^0; //调整sbit key2 = P2^1; //加1sbit key3 = P2^2; //减1sbit speaker = P2^3; //蜂鸣器sbit key4 = P2^4; //闹钟设计bit cal_year = 1; //进入判断闰年标志位bit leap_year; //闰年标志位bit calculate = 0; //日加一标记bit run = 0; //闹钟标志bit beep = 0; //整点报时标志//uint8 num = 0; //调整是给的脉冲uint8 code str1[] = "D: ";uint8 code str2[] = "T: ";uint8 code str3[] = "Wek";uint8 daystr[]="2013-07-29 "; //年月日格式uint8 timestr[]="21:30:59 N"; //时分秒格式uint8 daystr1[]="2013-07-29 "; //闹钟年月日格式uint8 timestr1[]="21:30:59 N"; //闹钟时分秒格式uint8 numweek = 0; //星期加1标记char week = 1; //星期char sec = 53; //秒char min = 50; //分char hour = 23; //时uint8 day = 30; // 日uint8 month = 9; //月uint16 year = 2013; //年char week1 = 1; //闹钟星期char sec1 = 58; //闹钟秒char min1 = 50; //闹钟分char hour1 = 23; //闹钟时uint8 day1 = 30; //闹钟日uint8 month1 = 9; //闹钟月uint16 year1 = 2013; //闹钟年uint8 WeekData1; //闹钟星期标记uint8 number = 0; //定时uint8 WeekData; //星期标记uint8 speaker_num; //整点报时次数uint8 scan_key(void); //函数声名/****************************************************************************** ***************************** 更新LCD时间分离读取******************************************************************************************************************* *******/void TimeChange(){//时分秒timestr[7] = sec%10+'0';timestr[6] = sec/10+'0';timestr[4] = min%10+'0';timestr[3] = min/10+'0';timestr[1] = hour%10+'0';timestr[0] = hour/10+'0';//年月日daystr[9] = day%10+'0';daystr[8] = day/10+'0';daystr[6] = month%10+'0';daystr[5] = month/10+'0';daystr[3] = year%10+'0';daystr[2] = year/10%10+'0';daystr[1] = year/100%10+'0';daystr[0] = year/1000+'0';//星期WeekData = week+'0';}/****************************************************************************** ***************************** 闹钟更新LCD时间分离读取******************************************************************************************************************* *******/void TimeChange1(){//时分秒timestr1[7] = sec1%10+'0';timestr1[6] = sec1/10+'0';timestr1[4] = min1%10+'0';timestr1[3] = min1/10+'0';timestr1[1] = hour1%10+'0';timestr1[0] = hour1/10+'0';//年月日daystr1[9] = day1%10+'0';daystr1[8] = day1/10+'0';daystr1[6] = month1%10+'0';daystr1[5] = month1/10+'0';daystr1[3] = year1%10+'0';daystr1[2] = year1/10%10+'0';daystr1[1] = year1/100%10+'0';daystr1[0] = year1/1000+'0';//星期WeekData1 = week1+'0';}/****************************************************************************** ***************************** 初始化系统定时器0 ******************************************************************************************************************* *******/void systimer0_init(void){TMOD |=0x01;//设置为1时用或(|)TMOD &=0xfd;//设置为0时用与(&)TH0 = 0xDC; // 定时10msTL0 = 0x00;EA = 1;ET0=1;TR0=1;EX0 = 1;}/****************************************************************************** ***************************** 闹钟时间设置*************************************************************************************************************** *******/void naozhong(){uint8 number = 1;uint8 a = 0;uint8 b = 0;if(0 == key4){Delay1Ms(5);if(0 == key4){a = 1;LCD_write_command(0xc0+9);LCD_write_command(0x0f);}while(!key4);}while(a){if(0 == key4){Delay1Ms(5);if(0 == key4){a = 0;run = ~run;while(!key4);}}if(run){timestr[9] = 'Y';}else{timestr[9] = 'N';}if(0 == key1){Delay1Ms(5);if(0 == key1){b = 1;}while(!key1);}while(b){if(0 == key1){Delay1Ms(5);if(0 == key1){number++;if(4 == number)b = 0;}while(!key1);if(number == 1){LCD_write_command(0xc0+9);LCD_write_command(0x0f);}if(number == 2){LCD_write_command(0xc0+6);LCD_write_command(0x0f);}if(number == 3){LCD_write_command(0xc0+3);LCD_write_command(0x0f);}}}switch(number){case 1:if(0 == key2) //闹钟秒加1的设置{Delay1Ms(5);if(0 == key2){sec1++;if(60 == sec1){sec1 = 0;}while(!key2);timestr1[7] = sec1%10+'0';timestr1[6] = sec1/10+'0';LCD_write_char(8,1,timestr1[6]);LCD_write_char(9,1,timestr1[7]);LCD_write_command(0xc0+9);}}if(0 == key3) //闹钟秒减1的设置Delay1Ms(5);if(0 == key3){sec1--;if(sec1 < 0){sec1 = 59;}while(!key3);timestr1[7] = sec1%10+'0';timestr1[6] = sec1/10+'0';LCD_write_char(8,1,timestr1[6]);LCD_write_char(9,1,timestr1[7]);LCD_write_command(0xc0+9);}}break;case 2:if(0 == key2) //闹钟分加1的设置{Delay1Ms(5);if(0 == key2){min1++;if(60 == min1){min1 = 0;}while(!key2);timestr1[4] = min1%10+'0';timestr1[3] = min1/10+'0';;LCD_write_char(5,1,timestr1[3]);LCD_write_char(6,1,timestr1[4]);LCD_write_command(0xc0+6);}}if(0 == key3) //闹钟分减1的设置{Delay1Ms(5);if(0 == key3){min1--;if(min1 < 0){min1 = 59;}while(!key3);timestr1[4] = min1%10+'0';timestr1[3] = min1/10+'0';;LCD_write_char(5,1,timestr1[3]);LCD_write_char(6,1,timestr1[4]);LCD_write_command(0xc0+6);}}break;case 3:if(0 == key2) //闹钟时加1的设置{Delay1Ms(5);if(0 == key2){hour1++;if(24 == hour1){hour1 = 0;}while(!key2);timestr1[1] = hour1%10+'0';timestr1[0] = hour1/10+'0';LCD_write_char(2,1,timestr1[0]);LCD_write_char(3,1,timestr1[1]);LCD_write_command(0xc0+3);}}if(0 == key3) //闹钟时减1的设置{Delay1Ms(5);if(0 == key3){hour1--;if(hour1 < 0){hour1 = 23;}while(!key3);timestr1[1] = hour1%10+'0';timestr1[0] = hour1/10+'0';LCD_write_char(2,1,timestr1[0]);LCD_write_char(3,1,timestr1[1]);LCD_write_command(0xc0+3);}}break;case 4:b = 0;LCD_write_command(0x0c);break;}}}LCD_write_command(0x0c);while(!key4);}/****************************************************************************** ***************************** 判断按键进入时间调整*************************************************************************************************************** *******/uint8 scan_key(void){uint8 number = 1;uint8 a = 0;if(0 == key1){Delay1Ms(5);if(0 == key1){while(!key1);a = 1;LCD_write_command(0xc0+9);LCD_write_command(0x0f);}}while(a){if(0 == key1){Delay1Ms(5);if(0 == key1){number++;while(!key1);TR0 = 0;if(number == 2){LCD_write_command(0xc0+6);LCD_write_command(0x0f);}if(number == 3){LCD_write_command(0xc0+3);LCD_write_command(0x0f);}if(number == 4){LCD_write_command(0x80+11);LCD_write_command(0x0f);}if(number == 5){LCD_write_command(0x80+8);LCD_write_command(0x0f);}if(number == 6){LCD_write_command(0x80+5);LCD_write_command(0x0f);}if(number == 7){LCD_write_command(0xc0+14);LCD_write_command(0x0f);}if(8 == number){LCD_write_command(0x0c);a = 0;number = 0;}}}switch(number){case 1:if(0 == key2) //秒加1的设置{Delay1Ms(5);if(0 == key2){sec++;if(60 == sec){sec = 0;}timestr[7] = sec%10+'0';timestr[6] = sec/10+'0';LCD_write_char(8,1,timestr[6]);LCD_write_char(9,1,timestr[7]);LCD_write_command(0xc0+9);while(!key2);}}if(0 == key3) //秒减1的设置{Delay1Ms(5);if(0 == key3){sec--;if(sec < 0){sec = 59;}timestr[7] = sec%10+'0';timestr[6] = sec/10+'0';LCD_write_char(8,1,timestr[6]);LCD_write_char(9,1,timestr[7]);LCD_write_command(0xc0+9);while(!key3);}}break;case 2:if(0 == key2) //分加1的设置{Delay1Ms(5);if(0 == key2){min++;if(60 == min){min = 0;}timestr[4] = min%10+'0';timestr[3] = min/10+'0';;LCD_write_char(5,1,timestr[3]);LCD_write_char(6,1,timestr[4]);LCD_write_command(0xc0+6);while(!key2);}}if(0 == key3) //分减1的设置{Delay1Ms(5);if(0 == key3){min--;if(min < 0){min = 59;}timestr[4] = min%10+'0';timestr[3] = min/10+'0';LCD_write_char(5,1,timestr[3]);LCD_write_char(6,1,timestr[4]);LCD_write_command(0xc0+6);while(!key3);}}break;case 3:if(0 == key2) //时加1的设置{Delay1Ms(5);if(0 == key2){hour++;while(!key2);if(24 == hour){hour = 0;}timestr[1] = hour%10+'0';timestr[0] = hour/10+'0';LCD_write_char(2,1,timestr[0]);LCD_write_char(3,1,timestr[1]);LCD_write_command(0xc0+3);}}if(0 == key3) //时减1的设置{Delay1Ms(5);if(0 == key3){while(!key3);hour--;if(hour < 0){hour = 23;}timestr[1] = hour%10+'0';timestr[0] = hour/10+'0';LCD_write_char(2,1,timestr[0]);LCD_write_char(3,1,timestr[1]);LCD_write_command(0xc0+3);}}break;case 4:if(0 == key2) //日加1的设置{Delay1Ms(5);if(0 == key2){while(!key2);calculate = 1;if(calculate == 1){if(month==1|month==3|month==5|month==7|month==8|month==10|month==12){day++;if(day > 31){day=1;}}if(month==4|month==6|month==9|month==11){day++;if(day > 30){day=1;}}if(month == 2){cal_year = 1;while(cal_year == 1){leap_year = ((year % 4 == 0 && year % 100 != 0)||(year % 400 == 0));cal_year = 0;}if(leap_year==1){day++;if(day > 30){day=1;}}else{day++;if(day > 29){day=1;}}}calculate = 0;}daystr[9] = day%10+'0';daystr[8] = day/10+'0';LCD_write_char(10,0,daystr[8]);LCD_write_char(11,0,daystr[9]);LCD_write_command(0x80+11);}}if(0 == key3) //日减1的设置{Delay1Ms(5);if(0 == key3){while(!key3);calculate = 1;if(calculate == 1){if(month==1|month==3|month==5|month==7|month==8|month==10|month==12){day--;if(day == 0){day=31;}}if(month==4|month==6|month==9|month==11){day--;if(day == 0){day=30;}}if(month == 2){cal_year = 1;while(cal_year == 1){leap_year = ((year % 4 == 0 && year % 100 != 0)||(year % 400 == 0));cal_year = 0;}if(leap_year==1){day--;if(day == 0){day=30;}}else{day--;if(day == 0){day=29;}}}calculate = 0;}daystr[9] = day%10+'0';daystr[8] = day/10+'0';LCD_write_char(10,0,daystr[8]);LCD_write_char(11,0,daystr[9]);LCD_write_command(0x80+11);}}break;case 5:if(0 == key2) //月加1的设置{Delay1Ms(5);if(0 == key2){while(!key2);month++;if(13 == month){month = 1;}daystr[6] = month%10+'0';daystr[5] = month/10+'0';LCD_write_char(7,0,daystr[5]);LCD_write_char(8,0,daystr[6]);LCD_write_command(0x80+8);}}if(0 == key3) //月减1的设置{Delay1Ms(5);if(0 == key3){while(!key3);month--;if(month == 0){month = 12;}daystr[6] = month%10+'0';daystr[5] = month/10+'0';LCD_write_char(7,0,daystr[5]);LCD_write_char(8,0,daystr[6]);LCD_write_command(0x80+8);}}break;case 6:if(0 == key2) //年加1的设置{Delay1Ms(5);if(0 == key2){while(!key2);year++;}daystr[3] = year%10+'0';daystr[2] = year/10%10+'0';daystr[1] = year/100%10+'0';daystr[0] = year/1000+'0';LCD_write_char(2,0,daystr[0]);LCD_write_char(3,0,daystr[1]);LCD_write_char(4,0,daystr[2]);LCD_write_char(5,0,daystr[3]);LCD_write_command(0x80+5);}if (0 == key3) //年减1的设置{Delay1Ms(5);if(0 == key3){while(!key3);year--;if(year == 0){year = 2020;}daystr[3] = year%10+'0';daystr[2] = year/10%10+'0';daystr[1] = year/100%10+'0';daystr[0] = year/1000+'0';LCD_write_char(2,0,daystr[0]);LCD_write_char(3,0,daystr[1]);LCD_write_char(4,0,daystr[2]);LCD_write_char(5,0,daystr[3]);LCD_write_command(0x80+5);}}break;case 7:if(0 == key2) //星期加1的设置{Delay1Ms(5);if(0 == key2){while(!key2);week++;if(7 == week){week = 0;}LCD_write_char(14,1,week+'0');LCD_write_command(0xc0+14);}}if (0 == key3) //星期减1的设置{Delay1Ms(5);if(0 == key3){while(!key3);week--;if(week < 0){week = 6;}LCD_write_char(14,1,week+'0');LCD_write_command(0xc0+14);}}break;case 8:TR0 = 1;break;}}}/****************************************************************************** ***************************** 主函数******************************************************************************************************************* *******/void main(void){systimer0_init();LCD_init();LCD_write_str(0,0,str1);LCD_write_str(0,1,str2);LCD_write_str(13,0,str3);speaker = 0;while (1){TimeChange();scan_key();naozhong();LCD_write_str(2,0,daystr);LCD_write_str(2,1,timestr);LCD_write_char(14,1,WeekData);if(1 == run){if(sec==sec1 & month==month1 & hour==hour){speaker_num =30;beep = 1;}}else{speaker_num =0;beep = 0;}}}/****************************************************************************** ***************************** 定时中断0 ******************************************************************************************************************* *******/void time_0() interrupt 1{TH0 = 0xDC; // 定时10msTL0 = 0x00;number++;if(number ==100){sec++;if(beep){speaker=!speaker;speaker_num--;if(speaker_num == 0){beep=0;speaker = 0;}}if(sec == 60){sec = 0;min++;if(min == 60){min = 0;hour++; //小时加1speaker_num = hour%12; //蜂鸣器响的次数beep = 1;if(hour == 24){hour = 0;calculate = 1;if(calculate == 1) //判断这个月有多少天{if(month==1|month==3|month==5|month==7|month==8|month==10|month==12){day++;if(month==7|month==12){week++;if(7 == week){week = 0;}}else{if(day <= 31){week++;if(7 == week){week = 0;}}}if(day > 31){if(month==7|month==12){day = 1;}else{day=0;}month++;if(month > 12){month=1;year++;cal_year=1;}}}if(month==4|month==6|month==9|month==11) {day++;week++;if(7 == week){week = 0;}if(day > 30){day=1;month++;if(month > 12){month=1;year++;cal_year=1;}}}if(month == 2){while(cal_year == 1){leap_year = ((year % 4 == 0 && year % 100 != 0)||(year % 400 == 0));cal_year = 0;}if(leap_year==1){day++;if(day <= 30){week++;if(7 == week){week = 0;}}if(day > 30){day=1;month++;if(month > 12){month=1;year++;cal_year=1;}}}else{day++;week++;if(7 == week){week = 0;}if(day > 29){day=1;month++;if(month > 12){month=1;year++;cal_year=1;}}}}}calculate=0;}}}}}////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Lcd1602.c子程序:////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /****************************************************************************** ***************************** lcd1602低层函数********************************************************************************************************************* *******/# include <reg52.h># include <intrins.h># include "lcd16024.h"# define LCD_DATA P0 //LCD1602的数据口定义sbit LCD_RS = P0^0; //LCD1602控制线的定义,4位控制方式sbit LCD_RW = P0^1;sbit LCD_EN = P0^2;/****************************************************************************** ***************************** 延时1MS********************************************************************************************************************* *******/void Delay1Us(uint16 n){for(;n>0;n--){_nop_();}}/****************************************************************************** ***************************** 延时1MS********************************************************************************************************************* *******/void Delay1Ms(uint16 n){while(n--){Delay1Us(1000);}}/****************************************************************************** ***************************** 延时1MS********************************************************************************************************************* *******/void LCD_en_write(void){LCD_EN=0;LCD_EN=1;Delay1Us(1);LCD_EN=0;}/****************************************************************************** ************************ LCD写一个字节命令函数************************************************************************************************************ *******/void LCD_write_command(uint8 command){Delay1Us(16);LCD_RS=0;LCD_RW=0;LCD_DATA&=0x0f;LCD_DATA|=command&0xf0;LCD_en_write();command=command<<4;LCD_DATA&=0x0f;LCD_DATA|=command&0xf0;LCD_en_write();}/****************************************************************************** ********************** LCD写一个字节数据函数*************************************************************************************************************** *******/void LCD_write_data(uint8 Data){Delay1Us(16);LCD_RS=1;LCD_RW=0;LCD_DATA&=0x0f;LCD_DATA|=Data&0xf0;LCD_en_write();Data=Data<<4;LCD_DATA&=0x0f;LCD_DATA|=Data&0xf0;LCD_en_write();}/****************************************************************************** ***************************** LCD1602光标定位函数************************************************ x--列0~15;y--行0~1********************************************************************************************************* *******/void LCD_set_xy(uint8 x,uint8 y){uint8 address;if(y==0)address=0x80+x;else address=0xc0+x;LCD_write_command(address);}/***************************************************************************************************** LCD1602 初始化函数,四位显示方式******************************************************************************************************* *******/void LCD_init(){LCD_write_command(0x28);// Delay1Us(40);LCD_write_command(0x28);LCD_write_command(0x0c);LCD_write_command(0x01);LCD_write_command(0x06);Delay1Ms(2);}/****************************************************************************** ***************************** LCD写字符串函数******************************************************* x--列0~15;y--行0~1******************************************************* s指向字符串数组**************************************************************************************************************** *******/void LCD_write_str(uint8 x,uint8 y,uint8 *s){LCD_set_xy(x,y);while(*s){LCD_write_data(*s);s++;}}/****************************************************************************** ***************************** LCD写一个字符函数******************************************************* x--列0~15;y--行0~1******************************************************* d--字符的ASCII码**************************************************************************************************************** *******/void LCD_write_char(uint8 x,uint8 y,uint8 d){LCD_set_xy(x,y);LCD_write_data(d);}/*////////////////////////////////////////////////////////////////// 等待繁忙标志/////////////////////////////////////////////////////////////////void LCD_wait(void){P0 = 0xFF;do{LCD_RS = 0;LCD_RW = 1;LCD_EN = 0;LCD_EN = 1;}while (BUSY == 1);LCD_EN = 0;}*//****************************************************************************** ***************************** LCD1602左移********************************************************************************************************************* *******void LCD_youyi(uint8 y,uint8 *s){LCD_write_str(17,y,s);for(a=0;a<16;a++){LCD_write_command(0x1c); //左移LCD_write_command(0x1c); 为右移Delay1Ms(6);}}*///LCD_write_command(0x0d);//光标闪烁//LCD_write_command(0x0e);//光标显示不闪烁//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Lcd1602.h头文件////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// #ifndef _LCD16024_H_#define _LCD16024_H_typedef unsigned char uint8;typedef unsigned int uint16;typedef unsigned long uint32;void Delay1Us(uint16 n);void Delay1Ms(uint16 n);void LCD_write_data(uint8 dat);void LCD_write_command(uint8 com); //BuysC为0时忽略忙检测void LCD_set_xy(uint8 x,uint8 y);void LCD_en_write(void);void LCD_write_char(uint8 x, uint8 y, uint8 Data1);void LCD_write_str(uint8 x, uint8 y,uint8 *s);void LCD_init();//void LCD_wait(void);//void LCD_youyi(uint8 y,uint8 *s);#endif。

1602显示温度+万年历

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。

LCD1602液晶显示带汉字的万年历程序51单片机

LCD1602液晶显示带汉字的万年历程序51单片机

LCD1602液晶显示带汉字的万年历程序(51单片机)#include &quot;reg51.h&quot;#define uint unsigned int#define uchar unsigned char#define port P0uchar table[]=&quot;I love you!&quot;; uchar table1[]=&quot;Shang Hong Rui!&quot;;uchar table2[]=&quot;LI ZHEN WEI!&quot; ;uchar table3[]=&quot;>; >; >; >; >; >; >; >; &quot;; 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, //汉字&ldquo;日&rdquo;0x0F,0x09,0x0F,0x09,0x0F,0x09,0x11,0x00, //汉字&ldquo;月&rdquo;0x01,0x02,0x03,0x05,0x09,0x03,0x00,0x00, //汉字&ldquo;年&rdquo;左半部0x00,0x00,0x1e,0x08,0x08,0x1e,0x08,0x08 //汉字&ldquo;年&rdquo;右半部};/*******************************读取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(&quot; I LOVE YOU&quot;);//lcd_xy(0,1);//lcd_gets(&quot;Shang Hong Rui&quot;);lcd_xy(2,0) ;lcd_gets(&quot;2011&quot;);lcd_xy(6,0) ;lcd_writedat(2);lcd_writedat(3);lcd_xy(8,0) ;lcd_gets(&quot;03&quot;); lcd_xy(10,0);lcd_writedat(1);lcd_xy(11,0) ;lcd_gets(&quot;06&quot;); lcd_xy(13,0);lcd_writedat(0);lcd_xy(3,1) ;lcd_gets(&quot;0&quot;); lcd_xy(4,1) ;lcd_gets(&quot;0&quot;); lcd_xy(5,1) ;lcd_gets(&quot;:&quot;); lcd_xy(6,1) ;lcd_gets(&quot;0&quot;); lcd_xy(7,1) ;lcd_gets(&quot;0&quot;); lcd_xy(8,1) ;lcd_gets(&quot;:&quot;);lcd_gets(&quot;0&quot;);lcd_xy(10,1) ;lcd_gets(&quot;0&quot;);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单片机proteus的lcd1602日历键盘扫描可调整时间附c51代码及调试截图 desi

基于51单片机proteus的lcd1602日历键盘扫描可调整时间附c51代码及调试截图  desi

基于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);}}。

基于51单片机的万年历代码(1602液晶实现)

基于51单片机的万年历代码(1602液晶实现)
month++; if(month>12)month=1; playmo(month); playx(); com(0x80+8); while(!key2); } } if(key3==0) { delay(5);
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单片机定时器的1602液晶显示器时钟显示(带年月日)

基于51单片机定时器的1602液晶显示器时钟显示(带年月日)

基于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;lcdrs=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);write_data(0x30+ge);}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); //确认定义键被按下if(S1==0){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)write_com(0x80+0x40); write_sfm(0,shi);}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){}}}else if(yue<=7){if(yue%2==0&yue!=2) {if(ri==31){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++;if(yue==13)yue=1;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(); //不停的检测按键是否被按下}}。

单片机的LCM1602液晶显示温度与万年历显控制

单片机的LCM1602液晶显示温度与万年历显控制

毕业设计报告(论文)报告(论文)题目:基于单片机的LCM1602液晶控制——温度与万年历显示设计作者所在系部:电子工程系作者所在专业:作者所在班级:作者姓名:作者学号:指导教师姓名:完成时间: 2011年 6 月 9 日院教务处制电子工程系毕业设计(论文)任务书指导教师:教研室主任:系主任:摘要论文的研究工作是以液晶屏显示技术为背景展开的,并且详细介绍了通过MCS-51单片机控制LCM1602液晶的显示情况,以软件形式对系统进行控制,使得系统控制更具灵活与方便。

本文在深入分析LCD显示技术的基础上,重点解析了LCM显示的单片机控制技术,以及LCD显示在各种电子显示中的优势,同时阐述了其在日常显示系统中的应用;并且以Proteus与Keil uVision4软件为基础,编写了MCS-51单片机对LCM1602显示控制的软件,绘制其原理图,并使用Proteus软件与Keil uVision4软件建立联合仿真。

论文主要论述了原理图各个模块的作用,控制软件的各个模块的编程。

关键词液晶显示技术LCM1602 MCS-51单片机Proteus Keil uVision4目录第1章绪论 (1)1.1课题背景及主要技术国内外研究概况 (1)1.2LCM1602显示控制系统简介 (2)1.3课题的建立以及本文完成的主要工作 (3)第2章开发工具软件简介 (4)2.1K EIL U V ISION4软件简介 (4)2.2P ROTEUS软件简介 (4)2.3K EIL U V ISION4与P ROTEUS软件联合仿真 (5)2.4小结 (5)第3章 LCD显示控制技术 (6)3.1LCD显示技术的发展 (6)3.2LCM1602显示控制技术及其体系结构 (7)3.2.1 LCM1602模块简介 (8)3.2.2 LCM1602模块内部结构 (9)3.2.3 LCM1602控制指令 (10)3.3小结 (12)第4章系统硬件概况 (13)4.1系统概况 (13)4.2功能模块 (13)4.2.1 MCS-51单片机最小系统模块 (14)4.2.2 温度采集模块 (14)4.2.3 蜂鸣器报警模块 (15)4.2.4 万年历调节设置模块 (16)4.2.5 LCM1602显示模块 (16)4.2.6 电源模块 (17)3.3小结 (17)第5章软件控制系统概况 (18)5.1程序流程概况 (18)5.2万年历显示控制模块 (18)5.2.1 流程图 (18)5.2.2 源程序代码 (19)5.3温度显示控制模块 (19)5.3.1 程序流程 (19)5.3.2 源程序代码 (19)5.3.3 主程序 (19)5.4小结 (20)第6章课题特点 (21)6.1LCM模块的应用 (21)6.2程序结构化与模块化设计 (21)6.3抗干扰技术 (21)第7章结论 (23)7.1调试联合仿真 (23)7.2仿真结果 (23)7.3小结 (23)致谢 (24)参考文献 (25)附录 (26)基于单片机的LCM1602液晶控制——温度与万年历显示设计第1章绪论1.1 课题背景及主要技术国内外研究概况自20世纪80年代起,显示设备经历着传统工艺的改良、新工艺的发展、成熟的优胜劣汰。

基于51单片机的1602液晶显示温度和时间的C程序

基于51单片机的1602液晶显示温度和时间的C程序

//液晶显示温度#include "AT89X52.H"#define Ddata P0sbit RS=P2^7; //命令数据控制端sbit RW=P2^6; //读写选择端sbit LCDE=P2^5; //液晶使能端sbit DQ=P2^0; //ds18b20与单片机连接口#define uchar unsigned char#define uint unsigned intunsigned char hour=0,min=0,sec=0; //定义初值unsigned int count=0;unsigned char line1[16]={" temp: "}; //16个字符unsigned char line2[16]={" time: 00:00:00"}; //16个字符unsigned char tab[]={'0','1','2','3','4','5','6','7','8','9'}; //数组uchar data disdata[5];uint tvalue; //温度值uchar tflag; //温度正负标志void time();/*************************lcd1602程序**************************/ void delay1ms(unsigned int ms)//延时1毫秒(不够精确的){unsigned int i,j;for(i=0;i<ms;i++)for(j=0;j<110;j++);}void delay5ms()//延时5毫秒(不够精确的){unsigned int i;for (i=0;i<1000;i++);}void delay50us(){register int i;for (i=0;i<20;i++);}void delay(){unsigned char m,n;for(m=255;m>0;m--)for(n=255;n>0;n--);}void wr_com(unsigned char comm) //********写控制字符程序E=1 RS=0RW=0 **********//{LCDE=0; //使能端RS=0; //********RS寄存器选择输入端,当RS=0;当进行写模块操作,指向指令寄存器。

基于LCD1602液晶显示屏的电子万年历设计【两个C程序】

基于LCD1602液晶显示屏的电子万年历设计【两个C程序】
图2-8 ISD1420P 引脚图
二,ISD1420P与单片机的连接
ISD1420P的电路图如图 2-9所示,图中LED用做录音和放音的指示灯;R8、R10和C6起到上拉的作用;通过R14和C11的时间常数来决定自动增益控制的释放时间,470KΩ和 的标称值在绝对大多数场合下可获得满意的效果;C7为电源和地之间的去耦电容;C9和C10为话筒的耦合电容.
市场上有许多电子钟的专用芯片如:LM8363、LM8365等,但它们功能单一,电路连接复杂,不便于调试制作!但是考虑到用单片机配合时钟芯片,可制成功能任意的电子钟,而且可以做到硬件简单、成本低廉。所以本系统采用了以广泛使用的单片机AT89C51技术为核心,配合时钟芯片DS1302。软硬件结合,使硬件部分大为简化,提高了系统稳定性,并采用LED显示电路、键盘电路,使人机交互简便易行,此外结合音乐闹铃电路、看门狗和供电电路。本方案设计出的数字钟可以显示时间、设置闹铃功能之外。
本设计中我重点研究实现了单片机+时钟芯片这种模式的万年历,从原理上对单片机和时钟芯片有了深一步的认识,这些基本功能完成后,在软件基础上实现世界时,农历功能。
本设计在很多场合都能用到,可以把此万年历装在镜框中或其它工艺品中,以便更加实用。
第一章 概论 系统总体框图
本设计的核心部分为单片机控制器,系统的各项功能由其它各部分单元电路来完成,单元电路主要包括:时钟电路部分、显示部分、语音部分、人机交互控制接口部分等,单片机通过程序来控制其它各部分统一协调地来完成系统的各项功能,本设计硬件电路较简单,但软件部分较复杂,所有功能都要通过软件来实现,系统总体设计如图1-1所示。
采用AT89C55,它是美国ATMEL公司生产的低电压,高性能CMOS8位单片机,片内含20kbytes 的可反复擦写的Flash只读程序存储器(ROM)和256*8bytes的随机存取数据存储器(RAM),器件采用ATMEL公司的高密度、非易失性存储技术生产,与标准MCS-51指令系统及8052产品引脚兼容,片内置通用8 位中央处理器(CPU)和Flash存储单元,功能强大AT89C55单片机适合于许多较为复杂控制应用场合。

51单片机电子表LCD1602显示_时间可调

51单片机电子表LCD1602显示_时间可调

/*功能: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;}}}}。

基于stc51单片机的LCD1602显示时间的电子万年历(显示

基于stc51单片机的LCD1602显示时间的电子万年历(显示

1 课设所需软件简介1.1 Keil uVision4的简要介绍2009年2月发布KeilμVision4,KeilμVision4引入灵活的窗口管理系统,使开发人员能够使用多台监视器,并提供了视觉上的表面对窗口位置的完全控制的任何地方。

新的用户界面可以更好地利用屏幕空间和更有效地组织多个窗口,提供一个整洁,高效的环境来开发应用程序。

新版本支持更多最新的ARM芯片,还添加了一些其他新功能。

2011年3月ARM公司发布最新集成开发环境RealViewMD K开发工具中集成了最新版本的KeiluVision4,其编译器、调试工具实现与ARM器件的最完美匹配。

KeilC51开发系统基本知识KeilC51开发系统基本知识1. 系统概述KeilC51软件提供丰富的库函数和功能强大的集成开发调试工具,全Windows界面。

另外重要的一点,只要看一下编译后生成的汇编代码,就能体会到Keil C51生成的目标代码效率非常之高,多数语句生成的汇编代码很紧凑,容易理解。

在开发大型软件时更能体现高级语言的优势。

下面详细介绍KeilC51开发系统各部分功能和使用。

2. Keil C51单片机软件开发系统的整体结构C51工具包的整体结构,uVision与Ishell分别是C51for Windo ws和forDos的集成开发环境(IDE),可以完成编辑、编译、连接、调试、仿真等整个开发流程。

开发人员可用IDE本身或其它编辑器编辑C或汇编源文件。

然后分别由C51及C51编译器编译生成目标文件(.OBJ)。

目标文件可由LIB51创建生成库文件,也可以与库文件一起经L51连接定位生成绝对目标文件(.ABS)。

ABS文件由OH51转换成标准的Hex文件,以供调试器dScope51或tScope51使用进行源代码级调试,也可由仿真器使用直接对目标板进行调试,也可以直接写入程序存贮器如EPROM中。

使用独立的Keil仿真器时,注意事项:* 仿真器标配11.0592MHz的晶振,但用户可以在仿真器上的晶振插孔中换插其他频率的晶振。

基于51单片机的用 LCD1602 显示时钟的程序

基于51单片机的用 LCD1602 显示时钟的程序

用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 行左右。

基于51单片机和lcd1602的万年历设计

基于51单片机和lcd1602的万年历设计

基于单片机的万年历设计摘要古人依靠日冕、漏刻记录时间,而随着科技的发展,电子万年历已经成为日渐流行的日常计时工具。

本文研究的万年历系统拟用STC89C52单片机控制,以DS1302时钟芯片计时、DS18B20采集温度、1602液晶屏显示。

系统主要由温度传感器电路,单片机控制电路,显示电路以及校正电路四个模块组成。

本文阐述了系统的硬件工作原理,所应用的各个接口模块的功能以及其工作过程,论证了设计方案理论的可行性。

系统程序采用C语言编写,经Keil软件进行调试后在Proteus软件中进行仿真,可以显示年、月、日、星期、时、分、秒和温度并具有校准功能和与即时时间同步的功能。

实验结果表明此万年历实现后具有读取方便、显示直观、功能多样、电路简洁等诸多优点,符合电子仪器仪表的发展趋势,具有广阔的市场前景。

关键词:万年历单片机仿真The Calendar of Design based on Single ChipAbstractAncient rely on corona, Louke recording time. The electronic calendar has become the popular tool for the daily timing.as the development of technology.In the calendar system , the STC89C52 is used to control,with the DS1302 clock chip timing, DS18B20 collecting temperature, 1602 LCD Displaying. The system is composed of four modules:the temperature sensor circuit, the MCU control circuit, the display circuit and the correction circuit.This paper describes the hardware works, the functions of each interface module and its working process, demonstrates design theory is Feasibility.. C language is used to program, after debugging in the Keil software,then simulating in the Proteus. The electronic calendar can display year, month, day, week, hours, minutes, seconds, temperature, and has calibration features and functionality with real time synchronization.The results show that this calendar is easy to read, intuitive display, versatile, simple circuits, and many other advantages,The design meets the development trend of electronic instruments and meters, and has broad market prospects.Keywords:Calendar ; MCU ; simulation目录第一章绪论 (1)1.1课题研究的意义 (1)1.2本课题主要的研究工作 (1)1.2.1研究内容 (1)1.2.2论文章节安排 (2)1.3本章小结 (2)第二章单片机的概述 (3)2.1单片机的定义和特点 (3)2.1.1单片机的定义 (3)2.1.2单片机的特点 (3)2.2单片机的发展现状和趋势 (4)2.2.1单片机的发展现状 (4)2.2.2单片机的发展趋势 (5)2.3编程语言的选择 (5)2.4本章小结 (6)第三章设计要求和方案论证 (7)3.1设计要求 (7)3.2单片机芯片的选择方案和论证 (7)3.3显示模块选择方案和论证 (7)3.4时钟芯片的选择方案和论证 (8)3.5温度传感器的选择方案与论证 (8)3.6电路设计最终方案决定 (9)3.7本章小结 (9)第四章系统的硬件设计与实现 (10)4.1电路设计框图 (10)4.2系统硬件概述 (10)4.3主要单元电路的设计 (11)4.3.1 STC89C52单片机简介 (11)4.3.2单片机主控制模块的设计 (13)4.3.3时钟电路模块的设计 (15)4.3.4温度传感器电路设计 (16)4.3.5独立式键盘设计 (19)4.3.6显示模块的设计 (19)4.4本章小结 (21)第五章系统的软件设计 (22)5.1程序流程图 (22)5.1.1系统总流程图 (22)5.1.2温度程序流程图 (23)5.1.3时钟程序流程图 (24)5.1.4液晶显示程序流程图 (25)5.2程序的设计 (26)5.2.1 DS18B20测温程序 (26)5.2.2读写DS1302程序 (27)5.2.3液晶显示程序 (29)5.3本章小结 (29)第六章仿真与调试 (30)6.1软件简介 (30)6.1.1 Keil软件简介 (30)6.1.2 Proteus ISIS简介 (30)6.2 Keil软件调试流程 (31)6.3 Proteus软件运行流程 (33)6.4 万年历的功能仿真 (35)6.5 硬件调试结果 (35)6.6本章小结 (39)第七章总结与展望 (40)参考文献 (41)附录一:系统电路图 (42)附录二:系统PCB板 (43)附录三:系统程序 (44)致谢 (57)第一章绪论1.1课题研究的意义万年历是我国古代传说中最古老的一部太阳历。

单片机的LCM1602液晶显示温度与万年历显控制

单片机的LCM1602液晶显示温度与万年历显控制

单片机的LCM1602液晶显示温度与万年历显控制毕业设计报告(论文)报告(论文)题目:基于单片机的LCM1602液晶控制——温度与万年历显示设计作者所在系部:电子工程系作者所在专业:作者所在班级:作者姓名:作者学号:指导教师姓名:完成时间: 2011年 6 月 9 日院教务处制电子工程系毕业设计(论文)任务书指导教师:教研室主任:系主任:摘要论文的研究工作是以液晶屏显示技术为背景展开的,并且详细介绍了通过MCS-51单片机控制LCM1602液晶的显示情况,以软件形式对系统进行控制,使得系统控制更具灵活与方便。

本文在深入分析LCD显示技术的基础上,重点解析了LCM显示的单片机控制技术,以及LCD显示在各种电子显示中的优势,同时阐述了其在日常显示系统中的应用;并且以Proteus与Keil uVision4软件为基础,编写了MCS-51单片机对LCM1602显示控制的软件,绘制其原理图,并使用Proteus软件与Keil uVision4软件建立联合仿真。

论文主要论述了原理图各个模块的作用,控制软件的各个模块的编程。

关键词液晶显示技术LCM1602 MCS-51单片机Proteus Keil uVision4目录第1章绪论 (1)1.1课题背景及主要技术国内外研究概况 (1)1.2LCM1602显示控制系统简介 (2)1.3课题的建立以及本文完成的主要工作 (3)第2章开发工具软件简介 (4)2.1K EIL U V ISION4软件简介 (4)2.2P ROTEUS软件简介 (4)2.3K EIL U V ISION4与P ROTEUS软件联合仿真 (5)2.4小结 (5)第3章 LCD显示控制技术 (6)3.1LCD显示技术的发展 (6)3.2LCM1602显示控制技术及其体系结构 (7)3.2.1 LCM1602模块简介 (8)3.2.2 LCM1602模块内部结构 (9)3.2.3 LCM1602控制指令 (11)3.3小结 (13)第4章系统硬件概况 (14)4.1系统概况 (14)4.2功能模块 (14)4.2.1 MCS-51单片机最小系统模块 (15)4.2.2 温度采集模块 (15)4.2.3 蜂鸣器报警模块 (16)4.2.4 万年历调节设置模块 (17)4.2.5 LCM1602显示模块 (17)4.2.6 电源模块 (18)3.3小结 (18)第5章软件控制系统概况 (19)5.1程序流程概况 (19)5.2万年历显示控制模块 (19)5.2.1 流程图 (19)5.2.2 源程序代码 (20)5.3温度显示控制模块 (20)5.3.1 程序流程 (20)5.3.2 源程序代码 (20)5.3.3 主程序 (20)5.4小结 (21)第6章课题特点 (22)6.1LCM模块的应用 (22)6.2程序结构化与模块化设计 (22)6.3抗干扰技术 (22)第7章结论 (24)7.1调试联合仿真 (24)7.2仿真结果 (24)7.3小结 (24)致谢 (25)参考文献 (26)附录 (27)基于单片机的LCM1602液晶控制——温度与万年历显示设计第1章绪论1.1 课题背景及主要技术国内外研究概况自20世纪80年代起,显示设备经历着传统工艺的改良、新工艺的发展、成熟的优胜劣汰。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

1 课设所需软件简介1.1 Keil uVision4的简要介绍2009年2月发布Keil μVision4,Keil μVision4引入灵活的窗口管理系统,使开发人员能够使用多台监视器,并提供了视觉上的表面对窗口位置的完全控制的任何地方。

新的用户界面可以更好地利用屏幕空间和更有效地组织多个窗口,提供一个整洁,高效的环境来开发应用程序。

新版本支持更多最新的ARM芯片,还添加了一些其他新功能。

2011年3月ARM公司发布最新集成开发环境RealView MDK开发工具中集成了最新版本的Keil uVision4,其编译器、调试工具实现与ARM器件的最完美匹配。

Keil C51开发系统基本知识Keil C51开发系统基本知识1. 系统概述Keil C51软件提供丰富的库函数和功能强大的集成开发调试工具,全Windows界面。

另外重要的一点,只要看一下编译后生成的汇编代码,就能体会到Keil C51生成的目标代码效率非常之高,多数语句生成的汇编代码很紧凑,容易理解。

在开发大型软件时更能体现高级语言的优势。

下面详细介绍Keil C51开发系统各部分功能和使用。

2. Keil C51单片机软件开发系统的整体结构C51工具包的整体结构,uVision与Ishell分别是C51 for Windows和for Dos的集成开发环境(IDE),可以完成编辑、编译、连接、调试、仿真等整个开发流程。

开发人员可用IDE本身或其它编辑器编辑C或汇编源文件。

然后分别由C51及C51编译器编译生成目标文件(.OBJ)。

目标文件可由LIB51创建生成库文件,也可以与库文件一起经L51连接定位生成绝对目标文件(.ABS)。

ABS文件由OH51转换成标准的Hex文件,以供调试器dScope51或tScope51使用进行源代码级调试,也可由仿真器使用直接对目标板进行调试,也可以直接写入程序存贮器如EPROM中。

使用独立的Keil仿真器时,注意事项:* 仿真器标配11.0592MHz的晶振,但用户可以在仿真器上的晶振插孔中换插其他频率的晶振。

* 仿真器上的复位按钮只复位仿真芯片,不复位目标系统。

* 仿真芯片的31脚(/EA)已接至高电平,所以仿真时只能使用片内ROM,不能使用片外ROM;但仿真器外引插针中的31脚并不与仿真芯片的31脚相连,故该仿真器仍可插入到扩展有外部ROM(其CPU的/EA引脚接至低电平)的目标系统中使用。

优点:1.Keil C51生成的目标代码效率非常之高,多数语句生成的汇编代码很紧凑,容易理解。

在开发大型软件时更能体现高级语言的优势。

2.与汇编相比,C语言在功能上、结构性、可读性、可维护性上有明显的优势,因而易学易用。

用过汇编语言后再使用C来开发,体会更加深刻。

Keil C51软件提供丰富的库函数和功能强大的集成开发调试工具,全Windows 界面。

图1.1 KEIL操作界面1.2 STC-ISP的简要介绍STC-ISP 是一款单片机下载编程烧录软件,是针对STC系列单片机而设计的,可下载STC89系列、12C2052 系列和12C5410等系列的STC单片机,使用简便,现已被广泛使用。

操作说明如下:(1) 打开STC-ISP,如下图界面,在MCU Type栏目下选中单片机,如STC89C52RC。

图1.2 ISP操作界面(2) 根据您的9针数据线连接情况选中COM端口,波特率一般保持默认,如果遇到下载问题,可以适当下调一些。

(3) 先确认硬件连接正确,点击“打开文件”并在对话框内找到您要下载的HEX文件。

图1.3 选择HEX文件(4)选择所要下载的文件,这样可以使您在每次编译KEIL时HEX代码能自动加载到STC-ISP,点击“Download/下载”。

(5) 手动按下电源开关便即可把可执行文件HEX写入到单片机内,如图是正在写入程序截图。

(6)程序写入完毕,目标板开始运行程序结果。

图2.2 设计流程图3 单元芯片电路的设置及总体设计3.1 DS1302芯片引脚功能DS1302 是美国DALLAS公司推出的一种高性能、低功耗、带RAM的实时时钟电路,它可以对年、月、日、周日、时、分、秒进行计时,具有闰年补偿功能,工作电压为2.5V~5.5V。

采用三线接口与CPU进行同步通信,并可采用突发方式一次传送多个字节的时钟信号或RAM数据。

DS1302内部有一个31×8的用于临时性存放数据的RAM寄存器。

DS1302是DS1202的升级产品,与DS1202兼容,但增加了主电源/后备电源双电源引脚,同时提供了对后备电源进行涓细电流充电的能力。

DS1302的引脚排列,其中Vcc1为后备电源,VCC2为主电源。

在主电源关闭的情况下,也能保持时钟的连续运行。

DS1302由Vcc1或Vcc2两者中的较大者供电。

当Vcc2大于Vcc1+0.2V时,Vcc2给DS1302供电。

当Vcc2小于Vcc1时,DS1302由Vcc1供电。

X1和X2是振荡源,外接32.768kHz 晶振。

RST是复位/片选线,通过把RST输入驱动置高电平来启动所有的数据传送。

RST输入有两种功能:首先,RST接通控制逻辑,允许地址/命令序列送入移位寄存器;其次,RST提供终止单字节或多字节数据的传送手段。

当RST为高电平时,所有的数据传送被初始化,允许对DS1302进行操作。

如果在传送过程中RST置为低电平,则会终止此次数据传送,I/O引脚变为高阻态。

上电运行时,在Vcc>2.0V之前,RST必须保持低电平。

只有在SCLK 为低电平时,才能将RST置为高电平。

I/O为串行数据输入输出端(双向),后面有详细说明。

SCLK为时钟输入端。

下图为DS1302的引脚功能图:图3.1 DS1302引脚图管脚描述:X1 X2 32.768KHz 晶振管脚GND 地RST 复位脚I/O 数据输入/输出引脚SCLK 串行时钟Vcc1,Vcc2 电源供电管脚此外,拓展中用到了DS18B20温度传感器,其使用与DS1302比较类似,因此这里不再赘述。

3.2 DS1302的使用方法使用DS1302时,要对其引脚和寄存器进行特殊设置,以实现所需功能。

引脚设置后面会提及,这里不做说明,主要讲一下程序的编写。

DS1302的的工作过程中包过读写一个字节数据等过程,下面做相应的解释。

/********************************功能:往DS1302写入数据*********************************/void W1302(uchar ucAddr, uchar ucDa){T_RST = 0;T_CLK = 0;T_RST = 1;RTInputByte(ucAddr); /* 地址,命令*/RTInputByte(ucDa); /* 写1Byte数据*/T_CLK = 1;T_RST = 0;}/********************************功能:读取DS1302某地址的数据*********************************/uchar R1302(uchar ucAddr){uchar ucData;T_RST = 0;T_CLK = 0;T_RST = 1;RTInputByte(ucAddr); /* 地址,命令*/ucData = RTOutputByte(); /* 读1Byte数据*/T_CLK = 1;T_RST = 0;return(ucData);}/***********************************功能:设置初始时间************************************/void Set1302(uchar *pClock){uchar i;uchar ucAddr = 0x80;EA = 0;W1302(0x8e,0x00); /* 控制命令,WP=0,写操作?*/ for(i =7; i>0; i--){W1302(ucAddr,*pClock); /* 秒分时日月星期年*/pClock++;ucAddr +=2;}W1302(0x8e,0x80); /* 控制命令,WP=1,写保护?*/EA = 1;}/******************************功能:读取DS1302当前时间*******************************/void Get1302(uchar ucCurtime[]){uchar i;uchar ucAddr = 0x81;EA = 0;for (i=0; i<7; i++){ucCurtime[i] = R1302(ucAddr);/*格式为: 秒分时日月星期年*/ucAddr += 2;}EA = 1;}3.3 LCD1602引脚功能1602液晶也叫1602字符型液晶它是一种专门用来显示字母、数字、符号等的点阵型液晶模块它有若干个5X7或者5X11等点阵字符位组成,每个点阵字符位都可以显示一个字符。

每位之间有一个点距的间隔每行之间也有间隔起到了字符间距和行间距的作用,正因为如此所以他不能显示图形n1602LCD是指显示的内容为16X2,即可以显示两行,每行16个字符液晶模块(显示字符和数字)。

图3.2 LCD1602引脚图1602采用标准的16脚接口,其中:第1脚:VSS为电源地第2脚:VDD接5V电源正极第3脚:V0为液晶显示器对比度调整端,接正电源时对比度最弱,接地电源时对比度最高(对比度过高时会产生“鬼影”,使用时可以通过一个10K的电位器调整对比度)。

第4脚:RS为寄存器选择,高电平1时选择数据寄存器、低电平0时选择指令寄存器。

第5脚:RW为读写信号线,高电平(1)时进行读操作,低电平(0)时进行写操作。

第6脚:E(或EN)端为使能(enable)端。

第7~14脚:D0~D7为8位双向数据端。

第15~16脚:空脚或背灯电源。

15脚背光正极,16脚背光负极。

3.4 LCD1602的使用LCD1602的使用与前面的DS1302的使用有类似的地方,包括引脚的设置和对应的编程,引脚的设置后面会提及到,这里只涉及对应的编程。

/*LCD1602 延时*/void Lcd_delay(uchar ms){uchar j;while(ms--){for(j=0;j<250;j++){;}}}/*LCD1602 忙等待*/void Lcd_busy_wait(){Lcd_rs = 0;Lcd_rw = 1;Lcd_en = 1;Lcd_data = 0xff;while (Lcd_data&0x80);Lcd_en = 0;/*LCD1602 命令字写入*/}void Lcd_command_write(uchar command){Lcd_busy_wait();Lcd_rs = 0;Lcd_rw = 0;Lcd_en = 0;Lcd_data = command;Lcd_en = 1;Lcd_en = 0;}/*LCD1602 初始化*/void Init_lcd(){Lcd_delay(20);Lcd_command_write(0x38);Lcd_delay(100);Lcd_comman/*LCD1602 延时*/d_write(0x38);Lcd_delay(50);Lcd_command_write(0x38);Lcd_delay(10);Lcd_command_write(0x08);Lcd_command_write(0x01);Lcd_command_write(0x06);Lcd_command_write(0x0c);Lcd_data = 0xff; /*释放数据端口*/}void Lcd_char_write(uchar x_pos,y_pos,lcd_dat) /*LCD1602 字符写入*/ {x_pos &= 0x0f; /* X位置范围0~15 */y_pos &= 0x01; /* Y位置范围0~ 1 */if(y_pos==1) x_pos += 0x40;x_pos += 0x80;Lcd_command_write(x_pos);Lcd_busy_wait();Lcd_rs = 1;Lcd_rw = 0;Lcd_en = 0;Lcd_data = lcd_dat;Lcd_en = 1;Lcd_en = 0;Lcd_data = 0xff; /*释放数据端口*/}4 整体电路设计和程序由上面的分析可以得到实验的电路图如下:图4.1 仿真电路图设计源代码如下:/**************************************************************** 程序名称: LCD1602显示时间显示当前温度*****************************************************************//*头文件*/#include <reg52.h>#include <intrins.h>#define uint unsigned int#define uchar unsigned char#define nop() _nop_()sbit s1=P1^0;sbit s2=P1^1;sbit s3=P1^2;sbit s4=P1^3;sbit DQ =P1^3; //定义DS18B20通信端口sbit lcd_rs_port = P2^4; /*定义LCD控制端口*/sbit lcd_rw_port = P2^5;sbit lcd_en_port = P2^6;#define lcd_data_port P0sbit led_latch_port = P2^5; /*发光二极管寄存器LE引脚*/sbit sled_latch_port = P3^6; /*数码管寄存器LE引脚*/sbit T_CLK = P3^6; /*实时时钟时钟线引脚*/sbit T_IO = P3^4; /*实时时钟数据线引脚*/sbit T_RST = P3^5; /*实时时钟复位线引脚*/sbit ACC0 = ACC^0;sbit ACC7 = ACC^7;uchar code mun_to_char[] = {"0123456789ABCDEF"}; /*定义数字跟ASCII 码的关系*/uchar data time_data_buff[7]={0x50,0x59,0x23,0x31,0x12,0x04,0x12};/*格式为: 秒分时日月星期年*/uchar data lcd1602_line1[]={" 2000/00/00 000 "};uchar data lcd1602_line2[]={" 00:00:00 00.0"};uchar code Weeks[][3]={{"SUN"},{"MON"},{"TUE"},{"WED"},{"THU"},{"FRI"},{"SAT"},{"SUN"}};/**************************************************************** 函数名:RTInputByte()功能:实时时钟写入一字节说明:往DS1302写入1Byte数据(内部函数)入口参数:d 写入的数据返回值:无****************************************************************/void RTInputByte(uchar d){uchar i;ACC = d;for(i=8; i>0; i--){T_IO = ACC0; /*相当于汇编中的RRC */T_CLK = 1;T_CLK = 0;ACC = ACC >> 1;}}/**************************************************************** 函数名:RTOutputByte()功能:实时时钟读取一字节说明:从DS1302读取1Byte数据(内部函数)入口参数:无返回值:ACC****************************************************************/uchar RTOutputByte(void){uchar i;for(i=8; i>0; i--){ACC = ACC >>1; /*相当于汇编中的RRC */ACC7 = T_IO;T_CLK = 1;T_CLK = 0;}return(ACC);}/**************************************************************** 函数名:W1302()功能:往DS1302写入数据说明:先写地址,后写命令/数据(内部函数)调用:RTInputByte() , RTOutputByte()入口参数:ucAddr: DS1302地址, ucData: 要写的数据返回值:无****************************************************************/void W1302(uchar ucAddr, uchar ucDa){T_RST = 0;T_CLK = 0;T_RST = 1;RTInputByte(ucAddr); /* 地址,命令*/RTInputByte(ucDa); /* 写1Byte数据*/T_CLK = 1;T_RST = 0;}/***************************************************************函数名:R1302()功能:读取DS1302某地址的数据说明:先写地址,后读命令/数据(内部函数)调用:RTInputByte() , RTOutputByte()入口参数:ucAddr: DS1302地址返回值:ucData :读取的数据****************************************************************/uchar R1302(uchar ucAddr){uchar ucData;T_RST = 0;T_CLK = 0;T_RST = 1;RTInputByte(ucAddr); /* 地址,命令*/ucData = RTOutputByte(); /* 读1Byte数据*/T_CLK = 1;T_RST = 0;return(ucData);}/****************************************************************函数名:Set1302()功能:设置初始时间说明:先写地址,后读命令/数据(寄存器多字节方式)调用:W1302()入口参数:pClock: 设置时钟数据地址格式为: 秒分时日月星期年7Byte (BCD码)1B 1B 1B 1B 1B 1B 1B返回值:无****************************************************************/void Set1302(uchar*pClock){uchar i;uchar ucAddr = 0x80;EA = 0;W1302(0x8e,0x00); /* 控制命令,WP=0,写操作?*/for(i =7; i>0; i--){W1302(ucAddr,*pClock); /* 秒分时日月星期年*/pClock++;ucAddr +=2;}W1302(0x8e,0x80); /* 控制命令,WP=1,写保护?*/ EA = 1;}/****************************************************************函数名:Get1302()功能:读取DS1302当前时间说明:调用:R1302()入口参数:ucCurtime: 保存当前时间地址。

相关文档
最新文档