当前位置:文档之家› 单片机课程设计--基于51单片机的万年历

单片机课程设计--基于51单片机的万年历

单片机课程设计报告万年历的设计基于51单片机的万年历摘要:电子万年历是一种非常广泛日常计时工具,对现代社会越来越流行。

它可以对年、月、日、周日、时、分、秒进行计时,使用寿命长,误差小。

对于数字电子万年历采用直观的数字显示,可以同时显示年、月、日、周日、时、分、秒和温度等信息,还具有时间校准等功能。

该电路采用AT89S52单片机作为核心,功耗小,能在3V的低压工作,电压可选用3~5V电压供电。

本设计是基于51系列的单片机进行的电子万年历设计,可以显示年月日时分秒及周信息,具有可调整日期和时间功能。

在设计的同时对单片机的理论基础和外围扩展知识进行了比较全面准备。

万年历的设计过程在硬件与软件方面进行同步设计。

硬件部分主要由AT89C52单片机,LCD显示电路,以及调时按键电路等组成。

在单片机的选择上本人使用了AT89C52单片机,该单片机适合于许多较为复杂控制应用场合。

显示器使用了1602液晶显示,并且使用蜂鸣器实现了整点报警的功能,温度测试的功能实现使用了DS18B20,并实现了温度过高或过低时的温度报警。

软件方面主要包括日历程序、时间调整程序,显示程序等。

程序采用C语言编写。

所有程序编写完成后,在KeilC51软件中进行调试,确定没有问题后,在Proteus软件中嵌入单片机内进行仿真,并最终实现基本要求。

综上所述此万年历具有读取方便、显示直观、功能多样、电路简洁、成本低廉等诸多优点,符合电子仪器仪表的发展趋势,具有广阔的市场前景。

一、设计要求基本要求:1,8 个数码管上显示,显示时间的格式为(假如当前时间是19:32:20)“19-32-20”;2,具有日历功能;③时间可以通过按键调整。

发挥部分:④具有闹钟功能(可以设定多个)。

二:总体设计电路设计框图系统硬件概述本电路是由AT89S52单片机为控制核心,具有在线编程功能,低功耗,能在3V超低压工作;时钟电路由单片机定时功能提供;温度的采集由DS18B20构成,它具有独特的单线接口方式,DS18B20在与微处理器连接时仅需要一条口线即可实现微处理器与DS18B20的双向通讯,使用时不需要额外的外围电路。

并且,其测温范围-55℃~+125℃,固有测温分辨率0.5℃;显示部份使用1602液晶显示,可完美地显示年、月、日、周日、时、分、秒,且在整点时刻通过蜂鸣器实现响铃。

还可以实现温度显示,且当判断得温度过高或过低时,通过液晶显示及LED发光二极管完成报警。

单片机主控制模块的设计AT89S52单片机为40引脚双列直插芯片,有四个I/O口P0,P1,P2,P3, MCS-51单片机共有4个8位的I/O口(P0、P1、P2、P3),每一条I/O线都能独立地作输出或输入。

单片机的最小系统如下图所示,18引脚和19引脚接时钟电路,XTAL1接外部晶振和微调电容的一端,在片内它是振荡器倒相放大器的输入,XTAL2接外部晶振和微调电容的另一端,在片内它是振荡器倒相放大器的输出.第9引脚为复位输入端,接上电容,电阻及开关后够上电复位电路,20引脚为接地端,40引脚为电源端.液晶显示模块的设计LCD1602有16个引脚,其中VCC、VSS分别为电源正负极;VO为液晶偏压信号输入端,图中W1可调节液晶明亮度; DB0—DB7 8位数据段;BLA、BLK背光源正负极;RS数据/命令选择端;R/W读写选择端;E使能端温度采集模块设计采用数字式温度传感器DS18B20,它是数字式温度传感器,具有测量精度高,电路连接简单特点,此类传感器仅需要一条数据线进行数据传输,使用P0.7与DS18B20的I/O口连接加一个上拉电阻,Vcc接电源,Vss接地。

PCB 图三电子时钟的软件设计系统软件按键检测流程图系统软件定时器程序流程图Y+是否按下M 是否按下Y 开始检测NN 相应项加一 —是否按下相应项减一YN子程序的设计DS18B20温度子程序void write_temp(uchar add,uchar dat)//向LCD写温度数据,并指定显示位置{uchar gw,sw,bw;if(dat>=0&&dat<=128){gw=dat%10;//取得个位数字sw=dat%100/10;//取得十位数字bw=dat/100 ;//取得百位数字}else{dat=256-dat;gw=dat%10;//取得个位数字sw=dat%100/10;//取得十位数字bw=-3; //0x30-3表示为负号}write_1602com(er+add);//er是头文件规定的值0x80+0x40write_1602dat(0x30+bw);//数字+30得到该数字的LCD1602显示码write_1602dat(0x30+sw);//数字+30得到该数字的LCD1602显示码write_1602dat(0x30+gw);//数字+30得到该数字的LCD1602显示码write_1602dat(0xdf);//显示温度的小圆圈符号,0xdf是液晶屏字符库的该符号地址码write_1602dat(0x43); //显示"C"符号,0x43是液晶屏字符库里大写C的地址码}1602子程序void write_byte(uchar dat)//写一个字节{ACC=dat;RST=1;for(a=8;a>0;a--){IO=ACC0;SCLK=0;SCLK=1;ACC=ACC>>1;}}uchar read_byte()//读一个字节RST=1;for(a=8;a>0;a--){ACC7=IO;SCLK=1;SCLK=0;ACC=ACC>>1;}return (ACC);}//----------------------------------------void write_1302(uchar add,uchar dat)//向1302芯片写函数,指定写入地址,数据{RST=0;SCLK=0;RST=1;write_byte(add);write_byte(dat);SCLK=1;RST=0;}uchar read_1302(uchar add)//从1302读数据函数,指定读取数据来源地址{uchar temp;RST=0;SCLK=0;RST=1;write_byte(add);temp=read_byte();SCLK=1;RST=0;return(temp);}uchar BCD_Decimal(uchar bcd)//BCD码转十进制函数,输入BCD,返回十进制{uchar Decimal;Decimal=bcd>>4;return(Decimal=Decimal*10+(bcd&=0x0F));}//--------------------------------------void ds1302_init() //1302芯片初始化子函数(2010-01-07,12:00:00,week4)RST=0;SCLK=0;write_1302(0x8e,0x00); //允许写,禁止写保护write_1302(0x80,0x00); //向DS1302内写秒寄存器80H写入初始秒数据00write_1302(0x82,0x00);//向DS1302内写分寄存器82H写入初始分数据00write_1302(0x84,0x12);//向DS1302内写小时寄存器84H写入初始小时数据12write_1302(0x8a,0x01);//向DS1302内写周寄存器8aH写入初始周数据4write_1302(0x86,0x08);//向DS1302内写日期寄存器86H写入初始日期数据07write_1302(0x88,0x07);//向DS1302内写月份寄存器88H写入初始月份数据01write_1302(0x8c,0x10);//向DS1302内写年份寄存器8cH写入初始年份数据10write_1302(0x8e,0x80); //打开写保护}时分秒显示子函数void write_sfm(uchar add,uchar dat)//向LCD写时分秒,有显示位置加、现示数据,两个参数{uchar gw,sw;gw=dat%10;//取得个位数字sw=dat/10;//取得十位数字write_1602com(er+add);//er是头文件规定的值0x80+0x40write_1602dat(0x30+sw);//数字+30得到该数字的LCD1602显示码write_1602dat(0x30+gw);//数字+30得到该数字的LCD1602显示码}//-------------------------------------//年月日显示子函数void write_nyr(uchar add,uchar dat)//向LCD写年月日,有显示位置加数、显示数据,两个参数{uchar gw,sw;gw=dat%10;//取得个位数字sw=dat/10;//取得十位数字write_1602com(yh+add);//设定显示位置为第一个位置+addwrite_1602dat(0x30+sw);//数字+30得到该数字的LCD1602显示码write_1602dat(0x30+gw);//数字+30得到该数字的LCD1602显示码}//-------------------------------------------void write_week(uchar week)//写星期函数{write_1602com(yh+0x0c);//星期字符的显示位置switch(week){case 1:write_1602dat('M');//星期数为1时,显示 write_1602dat('O');write_1602dat('N');break;case 2:write_1602dat('T');//星期数据为2时显示 write_1602dat('U');write_1602dat('E');break;case 3:write_1602dat('W');//星期数据为3时显示 write_1602dat('E');write_1602dat('D');break;case 4:write_1602dat('T');//星期数据为4是显示 write_1602dat('H');write_1602dat('U');break;case 5:write_1602dat('F');//星期数据为5时显示 write_1602dat('R');write_1602dat('I');break;case 6:write_1602dat('S');//星期数据为6时显示 write_1602dat('T');write_1602dat('A');break;case 7:write_1602dat('S');//星期数据为7时显示 write_1602dat('U');write_1602dat('N');break;定时器0初始化程序void init() //定时器、计数器设置函数{TMOD=0x11; //指定定时/计数器的工作方式为1TH0=0; //定时器T0的高四位=0TL0=0; //定时器T0的低四位=0EA=1; //系统允许有开放的中断ET0=1; //允许T0中断TR0=1; //开启中断,启动定时器}}//****************键盘扫描有关函数**********************void keyscan(){if(key1==0)//---------------key1为功能键(设置键)-------------------- {delay(9);//延时,用于消抖动if(key1==0)//延时后再次确认按键按下{buzzer=0;//蜂鸣器短响一次delay(20);buzzer=1;while(!key1);key1n++;if(key1n==12)key1n=1;//设置按键共有秒、分、时、星期、日、月、年、返回,8个功能循环switch(key1n){case 1: TR0=0;//关闭定时器//TR1=0;write_1602com(er+0x09);//设置按键按动一次,秒位置显示光标 write_1602com(0x0f);//设置光标为闪烁temp=(miao)/10*16+(miao)%10;//秒数据写入DS1302write_1302(0x8e,0x00);write_1302(0x80,0x80|temp);//miaowrite_1302(0x8e,0x80);break;case 2: write_1602com(er+6);//按2次fen位置显示光标//write_1602com(0x0f);break;case 3: write_1602com(er+3);//按动3次,shi//write_1602com(0x0f);break;case 4: write_1602com(yh+0x0e);//按动4次,week//write_1602com(0x0f);break;case 5: write_1602com(yh+0x0a);//按动5次,ri//write_1602com(0x0f);break;case 6: write_1602com(yh+0x07);//按动6次,yue//write_1602com(0x0f);break;case 7: write_1602com(yh+0x04);//按动7次,nian//write_1602com(0x0f);break;case 8: write_1602com(er+1);write_1602dat(0x4d);write_1602com(er+1);break;case 9: write_1602com(er+1);write_1602dat(0x46);write_1602com(er+1);break;case 10:write_1602com(er+1);write_1602dat(0x53);write_1602com(er+1);break;case 11:write_1602com(er+1);write_1602dat(0x20);write_1602com(0x0c);//按动到第8次,设置光标不闪烁TR0=1;//打开定时器temp=(miao)/10*16+(miao)%10;write_1302(0x8e,0x00);write_1302(0x80,0x00|temp);//miao数据写入DS1302write_1302(0x8e,0x80);break;}}}//------------------------------加键key2---------------------------- if(key1n!=0)//当key1按下以下。

相关主题