通信电子专业毕业设计基于单片机的多功能万年历的设计与实现_第1页
通信电子专业毕业设计基于单片机的多功能万年历的设计与实现_第2页
通信电子专业毕业设计基于单片机的多功能万年历的设计与实现_第3页
通信电子专业毕业设计基于单片机的多功能万年历的设计与实现_第4页
通信电子专业毕业设计基于单片机的多功能万年历的设计与实现_第5页
已阅读5页,还剩19页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

毕业设计基于单片机的多功能万年历的设计与实现选题的背景及意义二十一世纪是数字化技术高速发展的时代,而单片机在数字化高速发展的时代扮演着极为重要的角色。电子万年历的开发与研究在信息化时代的今天亦是当务之急,因为它应用在学校、机关、企业、部队等单位礼堂、训练场地、教学室、公共场地等场合,可以说遍及人们生活的每一个角落。所以说电子万年历的开发是国家之所需,社会之所需,人民之所需。由于社会对信息交换不断提高的要求及高新技术的逐步发展,促使电子万年历发展并且投入市场得到广泛应用。设计任务及要求(1)用4个按键实现所有功能,计时准确。(2)可以设定闹钟功能。(3)有阴历功能,平年闰年准确无误。(4)数码管能显示年、月、日、星期、时、分、秒、温度。三、项目分析与方案论证1.过程分析分析要设计的多功能万年历该有的系统的控制要求。1)控制多功能万年历计时的功能2)具有温度显示功能3)具有整点报时功能4)具有设置闹钟功能5)能够显示年月日功能6)具有智能模式2.方案论证选择方案1:单片机是一种集成电路芯片,单片机又称单片微控制器,它不是完成某一个逻辑功能的芯片,而是把一个计算机系统集成到一个芯片上,它的体积小、质量轻、价格便宜、为学习、应用和开发提供了便利条件,在工业控制领域广泛应用。方案2:可编程序控制器(PLC)是综合了计算机技术、自动控制技术和通讯技术而发展起来的一种新型的工业控制装置,它具有可靠性高、编程简单、维护方便等优点,已在工业控制领域得到广泛地应用。若利用PLC来控制多功能万年历,成本较高,而且设备庞大,占用空间较多。因此,我们选择方案1单片机来实现的多功能万年历系统的设计。四、项目设计本设计由数据显示模块、温度采集模块、时间处理模块和调整设置模块四个模块组成。系统以STC89C52单片机为控制器,以串行时钟日历芯片DS1302记录日历和时间,它可以对年、月、日、时、分、秒进行计时,还具有闰年补偿等多种功能。温度采集选用DS18B20芯片,万年历采用直观的数字显示,数据显示采用数码管显示模块,可以在LCD上同时显示年、月、日、星期、时、分、秒,还具有时间校准等功能。此万年历具有读取方便、显示直观、功能多样、电路简洁、成本低廉等诸多优点,具有广阔的市场前景。如图1所示图1五、项目实施过程1.成员任务安排从接受任务后具体成员的任务安排及时间安排如表1所示:表1任务实施计划实施计划时间主要任务负责人阶段成果2022.9-2022.10方案设计与电路设计陈嘉宇、蒋敏初步方向确立2022.10-202.12Proteus仿真,焊接电路顾嘉诚、高煜琪电路板完成2023.3-2023.4系统整体调试以及相关实验资料整理蒋敏、顾嘉诚顾嘉诚,王鑫实体完成2023.4-2023.5项目所有资料的完善陈嘉宇、王鑫总体完成2.原理图绘制利用proteus软件对项目进行原理图的绘制,如图2所示:图23.硬件焊接根据原理图焊接元器件,形成的硬件电路板如图3所示:图34.pcbpcb图如图4所示图4流程图5.多功能万年历的调试(1)调试步骤1)按照原理图连接。2)编程:编写多功能万年历的程序。3)将程序下载到51单片机,电路上电运行。。4)观察并记录能否实现程序的功能,如有错误,检查硬件接线是否错误,如果连接正确,再检查程序,直到调试成功为止。(2)调试要点1)如果在硬件调试时,某些元器件没起到作用,应该用万用表测量元器件的好坏,还有可能是电阻阻值选用不合理等问题。2)将设计好的程序下载到51单片机中,首先要做的就是仔细检查程序,是否出现语法错误,延时时间是否算对,主程序是否成功调用子程序。程序一般先在仿真软件上调试,然后再在焊接成功的电路板上调试。六、总结与体会本次学期从选题到设计,原理图的绘制到PCB图的设计,程序的设计以及软硬件的调试等工作,历时一个学期之久。设计项目最终实现了预定的功能,外观也是比较漂亮和时尚的,应该说取得了一定的成果。这次学期项目感受最深的是团队合作,毕竟个人能力有限,掌握的知识不够全面。所以在项目执行过程中,团队分工合作,在每个时间节点积极完成所需要完成的工作。另外,在这里要感谢苏老师的认真指导,经常与我们小组交流设计理念,并且在一定程度上帮助了我们大多数难题,包括程序上的、硬件上的一些问题。程序:#include<reg52.h> //调用单片机头文件#defineucharunsignedchar//无符号字符型宏定义 变量范围0~255#defineuintunsignedint //无符号整型宏定义 变量范围0~65535//数码管段选定义012345 6 7 8 9 ucharcodesmg_du[]={0xa0,0xbb,0x62,0x2a,0x39,0x2c,0x24,0xBa,0x20,0x28, 0x30,0x25,0xe4,0x23,0x64,0x74,0xff}; //断码//数码管位选定义ucharcodesmg_we[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//数码管位选定义uchardis_smg[8]={0}; bitflag_200ms;bitflag_100ms;sbitbeep=P3^7; //蜂鸣器定义bitflag_beep_en;uintclock_value;//用作闹钟用的ucharflag_s=0x03;//控制数码管闪烁的变量sbitdq=P3^1; //18b20IO口的定义uinttemperature;//温度变量sbitclk=P1^3; //ds1302时钟线定义sbitio=P1^4; //数据线sbitrst=P1^5; //复位线 //秒分时日月年星期 ucharcodewrite_add[]={0x80,0x82,0x84,0x86,0x88,0x8c,0x8a};//写地址ucharcoderead_add[]={0x81,0x83,0x85,0x87,0x89,0x8d,0x8b};//读地址ucharmiao,fen,shi,ri,yue,week,nian;uchari;ucharfen1=3,shi1=8; //闹钟变量的定义ucharopen1;ucharmenu_1,menu_2;sbitkey1=P3^6; //按键IO口定义sbitkey2=P3^5; //按键IO口定义sbitkey3=P3^4; //按键IO口定义sbitkey4=P3^3; //按键IO口定义/*************写一个数据到对应的地址里***************/voidwrite_ds1302(ucharadd,uchardat){ rst=1; //把复位线拿高 for(i=0;i<8;i++) { //低位在前 clk=0; //时钟线拿低开始写数据 io=add&0x01; add>>=1; //把地址右移一位 clk=1; //时钟线拿高 } for(i=0;i<8;i++) { clk=0; //时钟线拿低开始写数据 io=dat&0x01; dat>>=1; //把数据右移一位 clk=1; //时钟线拿高 } rst=0; //复位线合低}/*************从对应的地址读一个数据出来***************/ucharread_ds1302(ucharadd){ ucharvalue,i; rst=1; //把复位线拿高 for(i=0;i<8;i++) { //低位在前 clk=0; //时钟线拿低开始写数据 io=add&0x01; add>>=1; //把地址右移一位 clk=1; //时钟线拿高 } for(i=0;i<8;i++) { clk=0; //时钟线拿低开始读数据 value>>=1; if(io==1) value|=0x80; clk=1; //时钟线拿高 } rst=0; //复位线合低 returnvalue; //返回读出来的数据}/*************把要的时间年月日都读出来***************/voidread_time(){ miao=read_ds1302(read_add[0]); //读秒 fen=read_ds1302(read_add[1]); //读分 shi=read_ds1302(read_add[2]); //读时 ri=read_ds1302(read_add[3]); //读日 yue=read_ds1302(read_add[4]); //读月 nian=read_ds1302(read_add[5]); //读年 week=read_ds1302(read_add[6]); //读星期}/*************把要写的时间年月日都写入ds1302里***************/voidwrite_time() //把时间写进去{ write_ds1302(0x8e,0x00); //打开写保护 write_ds1302(write_add[0],miao); //写秒 write_ds1302(write_add[1],fen); //写分 write_ds1302(write_add[2],shi); //写时 write_ds1302(write_add[3],ri); //写日 write_ds1302(write_add[4],yue); //写月 write_ds1302(write_add[5],nian); //写星期 write_ds1302(write_add[6],week); //写年 write_ds1302(0x8e,0x80); //关闭写保护}/***********************延时函数************************/voiddelay_uint(uintq){ while(q--);}/***********************1ms延时函数*****************************/voiddelay_1ms(uintq){ uinti,j; for(i=0;i<q;i++) for(j=0;j<120;j++);}/********************独立按键程序*****************/ucharkey_can; //按键值voidkey() //独立按键程序{ ucharkey_new;//key_new这个变量的功能是做按键松手检测的 key_can=0;//按键值还原成0 if(key1==0||key2==0||key3==0||key4==0) //有按键按下 { delay_1ms(1); //按键延时消抖动 if(key_new==1) { key_new=0; //key_new=0说明按键已按下 if(key1==0) //确认是按键按下 key_can=1; //得到按键值 if(key2==0) //确认是按键按下 key_can=2; //得到按键值 if(key3==0) //确认是按键按下 key_can=3; //得到按键值 if(key4==0) //确认是按键按下 key_can=4; //得到按键值 } } else key_new=1; //key_new=1说明按键已经松开了 }/**********************设置函数************************/voidkey_with(){ if(key_can==1) //设置键 { menu_1++; menu_2=1; if(menu_1==1) //设置时间 flag_s=0x03; if(menu_1==2) //设置年月日 flag_s=0x03; if(menu_1==3) //设置星期闹钟的开和关 flag_s=0x03; if(menu_1==4) ////设置闹钟 flag_s=0x0c; if(menu_1>4)//回到正常显示 { menu_1=0; } } if(key_can==2) //选择键 { flag_200ms=1; if((menu_1==1)||(menu_1==2)) //设置时间 { menu_2++; if(menu_2>3) menu_2=1; if(menu_2==1) flag_s=0x03; if(menu_2==2) flag_s=0x18; if(menu_2==3) flag_s=0xc0; } if(menu_1==3) //设置星期闹钟的开和关 { menu_2++; if(menu_2>2) menu_2=1; if(menu_2==1) flag_s=0x03; if(menu_2==2) flag_s=0xf8; } if(menu_1==4) //设置闹钟 { menu_2++; if(menu_2>2) menu_2=1; if(menu_2==1) flag_s=0x0c; if(menu_2==2) flag_s=0x60; } } if(menu_1==1) // { if(menu_2==1) //设置秒 { if(key_can==3) //加键 { miao+=0x01; //设置秒钟加1 if((miao&0x0f)>=0x0a) miao=(miao&0xf0)+0x10; if(miao>=0x60) miao=0; } if(key_can==4) //减键 { if(miao==0x00) miao=0x5a; if((miao&0x0f)==0x00) miao=(miao|0x0a)-0x10; miao--; //设置秒减1 } } if(menu_2==2) //设置分 { if(key_can==3) //加键 { fen+=0x01; //设置分钟加1 if((fen&0x0f)>=0x0a) fen=(fen&0xf0)+0x10; if(fen>=0x60) fen=0; } if(key_can==4) //减键 { if(fen==0x00) fen=0x5a; if((fen&0x0f)==0x00) fen=(fen|0x0a)-0x10; fen--; //设置分钟减1 } } if(menu_2==3) //设置时 { if(key_can==3) //加键 { shi+=0x01; //设置时钟加1 if((shi&0x0f)>=0x0a) shi=(shi&0xf0)+0x10; if(shi>=0x24) shi=0; } if(key_can==4) //减键 { if(shi==0x00) shi=0x24; if((shi&0x0f)==0x00) shi=(shi|0x0a)-0x10; shi--; //设置时钟减1 } } write_time(); //把时间写进去 } if(menu_1==2) //设置年月日 { if(menu_2==1) //设置日 { if(key_can==3) //加键 { ri+=0x01; //设置日加1 if((ri&0x0f)>=0x0a) ri=(ri&0xf0)+0x10; if(ri>=0x32) ri=0; } if(key_can==4) //减键 { if(ri==0x01) ri=0x32; if((ri&0x0f)==0x00) ri=(ri|0x0a)-0x10; ri--; //设置日减1 } } if(menu_2==2) //设置月 { if(key_can==3) //加键 { yue+=0x01; //设置月加1 if((yue&0x0f)>=0x0a) yue=(yue&0xf0)+0x10; if(yue>=0x13) yue=1; } if(key_can==4) //减键 { if(yue==0x01) yue=0x13; if((yue&0x0f)==0x00) yue=(yue|0x0a)-0x10; yue--; //设置月减1 } } if(menu_2==3) //设置年 { if(key_can==3) //加键 { nian+=0x01; //设置年加1 if((nian&0x0f)>=0x0a) nian=(nian&0xf0)+0x10; if(nian>=0x9a) nian=1; } if(key_can==4) //减键 { if(nian==0x01) nian=0x9a; if((nian&0x0f)==0x00) nian=(nian|0x0a)-0x10; nian--; //设置年减1 } } write_time(); //把时间写进去 } if(menu_1==3) //设置星期闹钟的开和关 { if(menu_2==1) //设置星期 { if(key_can==3) //加键 { week+=0x01; //设置星期加1 if((week&0x0f)>=0x0a) week=(week&0xf0)+0x10; if(week>=0x08) week=1; } if(key_can==4) //减键 { if(week==0x01) week=0x08; if((week&0x0f)==0x00) week=(week|0x0a)-0x10; week--; //设置星期减1 } } if(menu_2==2) //设置闹钟的开和关 { if((key_can==4)||(key_can==3)) //加 open1++; if(open1>=2) open1=0; } write_time(); //把时间写进去 } if(menu_1==4) //设置闹钟 { if(menu_2==1) //设置分 { if(key_can==3) //加键 { fen1+=0x01; //设置闹钟分加1 if((fen1&0x0f)>=0x0a) fen1=(fen1&0xf0)+0x10; if(fen1>=0x60) fen1=0; } if(key_can==4) //减键 { if(fen1==0x00) fen1=0x5a; if((fen1&0x0f)==0x00) fen1=(fen1|0x0a)-0x10; fen1--; //设置闹钟分减1 } } if(menu_2==2) //设置时 { if(key_can==3) //加键 { shi1+=0x01; //设置闹钟时加1 if((shi1&0x0f)>=0x0a) shi1=(shi1&0xf0)+0x10; if(shi1>=0x24) shi1=0; } if(key_can==4) //减键 { if(shi1==0x00) shi1=0x5a; if((shi1&0x0f)==0x00) shi1=(shi1|0x0a)-0x10; shi1--; //设置闹钟时减1 } } write_time(); //把时间写进去 }}/************菜单处理函数****************/voidmenu_dis(){ if((menu_1==1)) //选设置时分秒 { dis_smg[0]=smg_du[miao%16];//显示秒 dis_smg[1]=smg_du[miao/16];// dis_smg[2]=0x7f; dis_smg[3]=smg_du[fen%16];//显示分 dis_smg[4]=smg_du[fen/16];// dis_smg[5]=0x7f; dis_smg[6]=smg_du[shi%16];//显示秒 dis_smg[7]=smg_du[shi/16];// } if((menu_1==2)) //选设置年月日 { dis_smg[0]=smg_du[ri%16];//显示日 dis_smg[1]=smg_du[ri/16];// dis_smg[2]=0xfe; dis_smg[3]=smg_du[yue%16];//显示月 dis_smg[4]=smg_du[yue/16];// dis_smg[5]=0xfe; dis_smg[6]=smg_du[nian%16];//显示年 dis_smg[7]=smg_du[nian/16];// } if((menu_1==3)) //设置星期和闹钟的开和关 { dis_smg[0]=smg_du[week%16];//显示星期 dis_smg[1]=smg_du[week/16];// dis_smg[2]=0x7f; if(open1==1) //开闹钟 { dis_smg[3]=0xb0; //OPEN dis_smg[4]=0x64; dis_smg[5]=0x70; dis_smg[6]=0xa0; }else { dis_smg[3]=0x74; //OFF dis_smg[4]=0x74; dis_smg[5]=0xa0; dis_smg[6]=0xFF; } } if(menu_1==4) //选设置时分秒 { dis_smg[0]=0xff;// dis_smg[1]=0xff;// dis_smg[2]=smg_du[fen1%16];//显示分 dis_smg[3]=smg_du[fen1/16];// dis_smg[4]=0x7f; dis_smg[5]=smg_du[shi1%16];//显示秒 dis_smg[6]=smg_du[shi1/16];// dis_smg[7]=0xff; }}/*************闹钟报警函数***************/voidclock_dis(){ if(flag_100ms==1) //100ms执行一次 { flag_100ms=0; if(open1==1) //如果闹钟打开 { if((miao==0)&&(fen==fen1)&&(shi==shi1)) { flag_beep_en=1; //有报警打开蜂鸣器响的标志位 } if(flag_beep_en==1) //闹钟以被打开 { beep=~beep; //蜂鸣器叫3秒 } if((miao==0)&&(fen==fen1+1)&&(shi==shi1)) { flag_beep_en=0; //1分钟后关闭闹钟 } } }}/*************定时器0初始化程序***************/voidtime_init() { EA=1; //开总中断 TMOD=0X01; //定时器0、工作方式1 ET0=1; //开定时器0中断 TR0=1; //允许定时器0定时}/***********************18b20初始化函数*****************************/voidinit_18b20(){ bitq; dq=1; //把总线拿高 delay_uint(8); dq=0; //给复位脉冲再将数据线从高拉低,要求保持480~960us delay_uint(80); dq=1; //把总线拿高等待 delay_uint(8); q=dq; //读取18b20初始化信号 delay_uint(4); dq=1; //把总线拿高释放总线}/*************写18b20内的数据***************/voidwrite_18b20(uchardat){ uchari; for(i=0;i<8;i++) //单总线写8位的数据需要循环8次才能写完 { //写数据是低位开始 dq=0; //把总线拿低写时间隙开始 dq=dat&0x01;//向18b20总线写一位数 delay_uint(4); dq=1; //释放总线 dat>>=1; //将dat中的各二进制位数据右移1位 } delay_uint(4); //稍作延时,给硬件一点反应时间}/*************读取18b20内的数据***************/ucharread_18b20(){ uchari,value; for(i=0;i<8;i++) { dq=0; //把总线拿低读时间隙开始 value>>=1; //读数据是低位开始 dq=1; //释放总线 if(dq==1) //开始读写数据 value|=0x80; delay_uint(4); } returnvalue; //返回数据}/*************读取温度的值读出来的是小数***************/uintread_temp(){ uintvalue; ucharlow; //在读取温度的时候如果中断的太频繁了,就应该把中断给关了,否则会影响到18b20的时序 init_18b20(); //初始化18b20 write_18b20(0xcc); //跳过64位ROM write_18b20(0x44); //启动一次温度转换命令 delay_uint(50); //转换一次温度需要时间延时一下 init_18b20(); //初始化18b20 write_18b20(0xcc); //跳过64位ROM write_18b20(0xbe); //发出读取暂存器命令 low=read_18b20(); //读温度低字节 value=read_18b20();//读温度高字节 value<<=8; //把温度的高位左移8位 value|=low; //把读出的温度低位放到value的低八位中 value*=0.625; //转换到温度值小数 returnvalue; //返回读出的温度带小数}/*************时钟显示***************/voidxianshi_ds1302(){ ucharvalue; value++; if(value<=5*2)//2秒 { dis_smg[0]=smg_du[miao%16];//显示秒 dis_smg[1]=smg_du[miao/16];// dis_smg[2]=0x7f; dis_smg[3]=smg_du[fen%16];//显示分 dis_smg[4]=smg_du[fen/16];// dis_smg[5]=0x7f; dis_smg[6]=smg_du[shi%16];//显示秒 dis_smg[7]=smg_du[shi/16];// } elseif(value<=5*4)//2秒 { dis_smg[0]=smg_du[ri%16];//

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论