基于-51单片机闹钟设计_第1页
基于-51单片机闹钟设计_第2页
基于-51单片机闹钟设计_第3页
基于-51单片机闹钟设计_第4页
基于-51单片机闹钟设计_第5页
已阅读5页,还剩23页未读 继续免费阅读

下载本文档

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

文档简介

-.z电子课程设计实习报告元件购置及焊接元件购置:地点:广埠屯,华中电子市场二楼时间:2021年4月7日过程:大早到华中电子市场后,当时还没开门,等到九点才开门,据人介绍上了二楼,卖各种电子元件的店面很多,但都不大。选了一家比拟小的店面,把教师给的清单给店主看后,店主很热情,但是说有两样元件没有,但承诺叫我们等等,到仓库去找一下。我们委婉拒绝了,想先看看,第一次来毕竟的货比三家嘛。又挨个找了几家店,比照价格和元件齐全程度后,我们选了一家比拟大元件齐全而且价格合理的店面。由于主要的元件,包括板子和各种芯片教师都发了,我们主要买一些小型元件。主要是电阻电容,由于元件小,不是单个卖的,都是十个十个的卖。至于电阻电容的区分,以前参加电子协会也接触过,关键是一些不熟悉的元件,如串口下载线之类的,我们虽然在课堂听教师讲过区分公母,但对于是否买对了,还是有疑问,得到店主承诺买错了,可以包换后,才放心结账。对着清单上一一看好后,除了电阻点容多买了几个外,其他的东西都还齐全。最后叫店主结账,并依照教师要求开发票。原清单:〔局部元件由于分批购置或者网上购置,未能列入清单〕焊接心得:焊接时间:2021年4月9日〔星期六上午〕地点:信息楼405焊接元件电路图:过程及心得:有了大二焊接收音机的一些焊接功底后,对于焊接还是有些经历的,先将小的元件焊接好,比方说电容电感,防止大的高的元件焊好后留下的可操作空间太少,给小的元件焊接带来不便。而不耐高温的元件,如三极管等,可以留在最后焊接,以免引脚触到烙铁损坏元件。当然有些元件的引脚虽然是对称分布,但是是是有区别的,如电解电容,二极管,三极管等。特别应该注意的是排阻,普通电阻部没有负极,但是排阻比拟特别,两端是不同的。由于排阻焊反了,导致与P0口相连的矩阵键盘无论如何都没常使用,后来发现后,拔了好久才拔下来,手还在此过程中,还跟烙铁来了个亲密接触,手指被烫的留下了一道白印记。拔下来时候,板子已经伤痕累累了,幸好买了新的排阻焊上去之后,键盘能够正常工作了,真可谓教训沉痛。焊接过程中,由于烙铁使用的还是比拟少,开场时手拿着总觉得很别扭,点锡丝的时候甚至有点抖,不过焊完一两个元件后就适应了很多,后来越来越上手,速度也快了很多。我们特地几个人约好一起焊接,并比照,有疑问先讨论,再动手焊接。但是还是有些问题没得到解决,由于没接触过1602,对于排针和排插的位置还是焊反了,但是问题不大,后来的实习过程中证明液晶一直工作正常,不过以后还是得按常规出牌,以免遇到大麻烦。其间也遇到了复位开关的摆放问题,我一直觉得是只要能插进去就正确的,但有人觉得有正反问题,后来证明我的想法是正确。焊完后,分模块对整个硬件电路进展调试检测,看有没有漏焊,虚焊的地方。之后,插上芯片试电,一切正常后,用安装好的编译和STC串口下载软件给单片机下载程序,红色的二极管一闪一闪的,等二极管不闪后,第一个数码管被点亮了,当时很兴奋。至此焊接告一段落。在此过程中,我总结出焊接前需熟悉电路,了解各元件,因为真正的焊接过程实际上是很短的,而准备工作没做好,只会给后面的焊接带来意想不到的麻烦,甚至导致板子被毁。焊接过程中,要注意力集中,逐渐积累经历,怎样操作适应,怎样防止虚焊和短路,以提高效率。总的来说是一个熟练掌握焊枪和熟悉锡丝特性的过程。焊接后先不要急于上电,也不要想板子一定焊好了,或者不正常之后惶恐是不是焊废了。毕竟这也是一个小的系统,我们第一次接触,第一次上电就能一切运行成功不现实,出现情况不要急,可能只是一些小问题,如没插上芯片或跳线帽之类的。总之作为学电子电气的,我们毕竟还会接触硬件的焊接和调试,这只是一个开端,相信有了这次的经历后,以后的会对这一过程了解的更深入。基于数码管及矩阵键盘实现的移位等假设干功能一、材料及硬件分析数码管的接法:由于数码管的借口很多,如果一个个接在单片机IO口上,将会很占用硬件资源,同时编程时候要兼顾段选和位选,会给编程带来很大不便。使用74LS138和CD4511译码器后,两个问题迎刃而解,如下为数码管的接法原理图:由图可知,138控制位选占用3个IO口,CD4511控制段选占用4个IO口,加上控制小数点的引脚总共占用8个IO口。给P1口赋值的时候,高3位控制的是位选,即第几个数码管亮,低4位控制的为段选,直接显示0-9,无需代码。而第4位则控制的是小数点的亮暗。动态显示的时候,只需要在*一位IO口后面的小数点点亮即可。矩阵键盘线反法:矩阵键盘部是4*4的8根线组成的16键的键盘,每个限于线穿插点,表示为一个键。总共需要8个IO口,当两个线没有穿插的时候,接通的两条线都变味低电平。首先可将高八位置为高电平第八位置为低电平,记下变为低电平的一条线路。然后将上下电平交换,再记下一条线路,即可确定按下的键的位置。具体程序如下:voidpress(){unsignedcharkeybuf1,keybuf2;P0=0*f0;keybuf1=P0;if(P0!=0*f0) {if(P0!=0*f0)//按键 {P0=0*0f;keybuf2=P0;KeyV=keybuf1+keybuf2;}}经过屡次试验后得出的各键的代码为:0*ee0*de0*be0*7e0*ed0*dd0*bd0*7d0*eb0*db0*bb0*7b0*e70*d70*b70*77,当然将键盘反接之后键就值完全变了。软件消抖:当有键按下的时候,瞬间单片机的电平会不稳定,即出现电平抖动,为了消除抖动,可采用软件法:unsignedcharup(){unsignedcharP0Buf;P0=0*f0;//松键P0Buf=P0;return(P0Buf-0*f0);}在有键按下之后执行while(up());即停在该处,只给Keyv赋值一次。二、程序功能1、密码锁:其他所有功能都在此程序运行成功的根底才能执行。上电之后,输入密码,并按c键验证正确之后会显示全8,否则显示全0。验证成功后按下A可以自行下面程序2、自动拉幕式移屏:1键左移,2键右移,其他键停顿,全屏显示为12345678。3、定时器时钟:BCD分别可调时分秒,A键实现下一功能4、秒表:1、2、3分别可以实现暂停,继续,清零功能,可准确到百分之一秒5、手动式移位并删除:输入数字的将第一个数字删除,并将所有数字前移一位。C键可实现删除,将最后一位数字删除,并在第一位补零。6、加法器:输入两个数字可实现相加,并可清屏和连加,但不能实现小数相加。二、源程序*include"reg52.h"unsignedcharPin[8]={8,5,8,5,8,5,8,5};unsignedcharLock[8]={11,11,11,11,11,11,11,11};unsignedcharL1[8]={0,0,0,0,0,0,0,0};unsignedcharL[8]={0,0,0,0,0,0,0,0};unsignedcharLed1[8]={0,0,0,0,0,0,0,0};unsignedcharLed[16]={11,11,11,11,11,11,11,11,0,1,2,3,4,5,6,7};unsignedcharKeyV=0;unsignedcharTotal=0;unsignedchardisp[]={0*00,0*01,0*02,0*03,0*04,0*05,0*06,0*07,0*08,0*09};unsignedcharsecond1=0;unsignedcharsecond2=0;unsignedcharminute1=0;unsignedcharminute2=0;unsignedcharhour1=0;unsignedcharday=0;unsignedcharmonth=0;unsignedcharCon=60;unsignedcharcodeKey[]={0*d7,0*ee,0*de,0*be,0*ed,0*dd,0*bd,0*eb,0*db,0*bb,0*7e};unsignedcharT=0;unsignedcharV=0;voiddelay(intn){while(n--);}voiddly(){unsignedintq;q=2000;while(q--);}/*change(){if(Con==60)Con=1;if(Con==1)Con=60;}*/unsignedcharup(){unsignedcharP0Buf;P0=0*f0;//松键P0Buf=P0;return(P0Buf-0*f0);}voidpress(){unsignedcharkeybuf1,keybuf2;P0=0*f0;keybuf1=P0;if(P0!=0*f0) {if(P0!=0*f0)//按键 {P0=0*0f;keybuf2=P0;KeyV=keybuf1+keybuf2;}while(up());}}display(){unsignedchari,P1Buf;for(i=0;i<=7;i++){P1Buf=i*2;P1Buf=P1Buf<<4;P1Buf=P1Buf+Led[i];//显示P1=P1Buf;//delay();}}voidlscan(){unsignedchari;for(i=0;i<=10;i++){if(KeyV==Key[i]){KeyV=i;//换数值break;}}for(i=7;i>0;i--){Lock[i]=Lock[i-1];}Lock[0]=KeyV;}ldisplay(){unsignedchari,P1Buf;for(i=0;i<=7;i++){P1Buf=i*2;P1Buf=P1Buf<<4;P1Buf=P1Buf+Lock[i];//显示P1=P1Buf;//delay();}}display1(){unsignedchari,P1Buf;for(i=0;i<=7;i++){P1Buf=i*2;P1Buf=P1Buf<<4;P1Buf=P1Buf+L[i];//显示P1=P1Buf;//delay();}}voidscan1(){unsignedcharkeybuf1,keybuf2;P0=0*f0;keybuf1=P0;if(P0!=0*f0) { P0=0*0f;keybuf2=P0;KeyV=keybuf1+keybuf2;if(KeyV==0*ee){minute1++;if(minute1==10)minute1=0;}//调时间if(KeyV==0*de){minute2++;if(minute2==6)minute2=0;}if(KeyV==0*be){hour1++;if(hour1==13)hour1=1;}delay(15000);}}voidTimer0()interrupt1{TH0=(65536-16666)/256;TL0=(65536-16666)%256;T++;if(T==Con){T=0;second1++;if(second1>=10){second1=0;second2++;if(second2>=6){//中断0minute1++;second2=0;if(minute1>=10){minute1=0;minute2++;if(minute2>=6){hour1++;minute2=0; if(hour1>=13) { hour1=1; }}}}}}}rotatel(){unsignedchart,i;{t=Led[15];{for(i=15;i>0;i--){Led[i]=Led[i-1];}//左移Led[0]=t;}}}rotater(){unsignedchart,i;{t=Led[0];{for(i=1;i<=15;i++)//右移{Led[i-1]=Led[i];}Led[15]=t;}}}back(){unsignedchari;for(i=1;i<=7;i++)//右移{L[i-1]=L[i];}L[7]=0;}voidTimer1()interrupt3{TH1=(65536-40000)/256;TL1=(65536-40000)%256;T++;if(T==200)switch(KeyV){case0*ee:rotatel();break;case0*de:rotater();break;default:break;}}voidscan(){unsignedchari;for(i=0;i<=10;i++){if(KeyV==Key[i]){KeyV=i;//换数值break;}}for(i=7;i>0;i--){L[i]=L[i-1];}L[0]=KeyV;}voidadscan(){unsignedchari;for(i=0;i<=10;i++){if(KeyV==Key[i]){KeyV=i;//换数值break;}}for(i=7;i>0;i--){Led1[i]=Led1[i-1];}Led1[0]=KeyV;}voidclr(){if(KeyV==0*be){second1=0;second2=0;//清零3minute1=0;minute2=0;hour1=0;EA=0;Con=1;}}add0(){unsignedchari;for(i=0;i<=7;i++)L1[i]=Led1[i];for(i=0;i<=7;i++)Led1[i]=0;}eql(){unsignedchart,i,b;t=0;b=0;for(i=0;i<=7;i++){/*Led1[i]=(Led1[i]+L1[i]+t)%10;if(Led1[i]>9)t=1;*/t=Led1[i]+L1[i]+b;if(t<=9){Led1[i]=t;b=0;}if(t>9){Led1[i]=t-10;b=1;}}}adcl(){unsignedchari;if(KeyV==0*77)for(i=0;i<=7;i++){Led1[i]=0;L1[i]=0;}}voidsec2(){if(KeyV==0*de){EA=0;}//暂停2}voidsec1(){if(KeyV==0*ed)//切换4{EA=1;Con=60;}}voidsec(){if(KeyV==0*ee)//开场1{EA=1;}}addisp(){unsignedchari,P1Buf;for(i=0;i<=7;i++){P1Buf=i*2;P1Buf=P1Buf<<4;P1Buf=P1Buf+Led1[i];P1=P1Buf;}}add(){while(1){KeyV=0;press();adcl();if(KeyV==0*7e){screen();}if(KeyV==0*e7){add0();}if(KeyV==0*b7){eql();}if(KeyV!=0*b7&&KeyV!=0*e7&&KeyV!=0&&KeyV!=0*77&&KeyV!=0*7e)adscan();addisp();}}rotate(){KeyV=0;while(1){KeyV=11;press();if(KeyV==0*7e){add();}if(KeyV==0*77)back();if(KeyV!=0*7e&&KeyV!=11&&KeyV!=0*77)scan();display1();//移位}}second(){KeyV=0;second1=0;second2=0;minute1=0;minute2=0;hour1=0;TMOD=0*01;TH0=(65536-16666)/256;TL0=(65536-16666)%256;TR0=1;ET0=1;//秒表EA=1;Con=1; while(1) { P1=0*50+disp[minute1]; P1=0*60+disp[minute2]; P1=0*00+disp[second1]; P1=0*20+disp[second2]; P1=0*90+disp[(hour1%10)]; P1=0*a0+disp[(hour1/10)];press();sec();sec1();sec2();clr();if(KeyV==0*7e){rotate();} }}clock(){KeyV=0;TMOD=0*01;TH0=(65536-16666)/256;TL0=(65536-16666)%256;TR0=1;TR1=0;ET0=1;//时钟EA=1;Con=63; while(1) { P1=0*50+disp[minute1]; P1=0*60+disp[minute2]; P1=0*00+disp[second1]; P1=0*20+disp[second2]; P1=0*90+disp[(hour1%10)]; P1=0*a0+disp[(hour1/10)];scan1();press();if(KeyV==0*7e){second();} }}screen(){KeyV=0;TMOD=0*01;TH1=(65536-40000)/256;TL1=(65536-40000)%256;TR1=1;TR0=0;ET1=1;//时钟EA=1;//dly();while(1){press();display();if(KeyV==0*7e){clock();}}}Klock(){unsignedchari,t;V=0;while(1){KeyV=11;V=0;press();ldisplay();if(KeyV!=11&&KeyV!=0*7b&&KeyV!=0*7e)lscan();if(KeyV==0*7b){for(i=0;i<=7;i++){if(Pin[i]==Lock[i])V++;}if(V!=8){for(i=0;i<=7;i++)Lock[i]=0;}if(V==8){for(i=0;i<=7;i++)Lock[i]=8;t=V;}//等于8证明八个数都相等开锁}if(t==8&&KeyV==0*7e)break;}}voidmain(){dly();while(1){Klock();screen();}}暑期实习课题一:基于51单片机的闹钟设计材料材料:STC89C52单片机开发板一块,1602液晶一片,12c887时钟芯片,ps2键盘,下载线,个人计算机编译软件:wave及keil下载程序软件:STC专用下载串口软件芯片及硬件资料一、芯片DS12c8871、DS12C887能够自动产生世纪、年、月、日、时、分、秒等时间信息,其部又增加了世纪存放器,从而利用硬件电路解决子"千年〞问题;DS12C887中自带有锂电池,外部掉电时,其部时间信息还能够保持10年之久;对于一天的时间记录,有12小时制和24小时制两种模式。在12小时制模式中,用AM和PM区分上午和下午;、引脚功能:DS12C887的引脚排列如图1所示,各管脚的功能说明如下:GND、VCC:直流电源,其中VCC接+5V输入,GND接地,当VCC输入为+5V时,用户可以DS12C887RAM中的数据,并可对其进展读、写操作;当VCC的输入小于+4.25V时,制止用户对部RAM进展读、写操作,此时用户不能正确获取芯片的时间信息;当VCC的输入小于+3V时,DS12C887会自动将电源发换到部自带的锂电池上,以保证部的电路能够正常工作。图1图2是用8031单片机和DS12C887构成的时间获取电路图即对应的管脚为如下:---------------------------------------------------|DS12887-----51|DS12887-----51|DS12887------51|--------------------------------------------------||AD0-------P0.0|AD4-------P0.4|AS-----------ALE||AD1-------P0.1|AD5-------P0.5|DS-----------P3.7||AD2-------P0.2|AD6-------P1.6|RW-----------P3.6||AD3-------P0.3|AD7-------P0.7|IRQ----------P3.5|---------------------------------------------------图2下列图为DS12C887地址分布图,则结合上图及其管脚知其基地址为:0*0fe0图3、相应的程序采用C51语言编写,由于Mot接地则以Intel工作模式。即可以将各个引脚宏定义如下,并放入头文件中:*defineDS12887_Sec*BYTE[0*0fe00]//秒*defineDS12887_Min*BYTE[0*0fe02]//分*defineDS12887_Hour*BYTE[0*0fe04]//时*defineDS12887_Week*BYTE[0*0fe06]//星期*defineDS12887_Day*BYTE[0*0fe07]//日*defineDS12887_Mon*BYTE[0*0fe08]//月*defineDS12887_Year*BYTE[0*0fe09]//年*defineDS12887_A*BYTE[0*0fe0a]//存放器A*defineDS12887_B*BYTE[0*0fe0b]//存放器B*defineDS12887_C*BYTE[0*0fe0c]//存放器C*defineDS12887_D*BYTE[0*0fe0d]//存放器D*defineDS12887_AlarmSec*BYTE[0*0fe01]//秒闹钟*defineDS12887_AlarmMin*BYTE[0*0fe03]//分钟闹钟*defineDS12887_AlarmHour*BYTE[0*0fe05]//小时闹思路分析时间及日期显示:要有闹钟功能,及先应该有时钟显示,可先将*一时间初值赋值给各个AD管脚,然后又以扫描方式将时间调出来,并用Lcd显示,并在第二次下载程序之前,将原有时间屏蔽,即可实现。时间及日期修改:如果时间不准,可以通过软件重设时间,但是现实时钟不允许软件改时间,为了与现实闹钟功能一致,必须实现用硬件修改时间,及必先有输入设备。用ps2键盘,结合头文件可编程实现该功能。闹钟设置:用一个数组记录三个数据,分别定义为闹钟时分秒,并通过扫描与当前时间比照,如果一一对应,则开场闹钟。闹钟过程可将开发板上的Led点亮,然后按*件实现关闭。可另行增加自己的想法功能,如懒猪功能延时,自行延时等。闹钟屏蔽:如果设置了闹钟,在主界面上可以通过*个符号显示,如果没有则通过另一个符号显示。如果显示没有闹钟,则可屏蔽闹钟,即使设置了也不能到点闹。该功能可通过按下*键改变*变量实现。功能及实现时间日期星期显示:从头文件中调用函数SetTime(unsignedcharhour,unsignedcharmin,unsignedcharsec)和SetDate(unsignedcharyear,unsignedcharmon,unsignedcharday)将时间日期分别赋值给对应变量。并将各个值分别赋值给数组:Date_Time[6]=DS12887_Sec;//秒Date_Time[5]=DS12887_Min;//分Date_Time[4]=DS12887_Hour;//时Date_Time[3]=DS12887_Week;//星期Date_Time[2]=DS12887_Day;//日Date_Time[1]=DS12887_Mon;//月Date_Time[0]=DS12887_Year;在主函数中用while〔1〕循环扫描记录各值。将时分秒及月日用如下方式别离成十位和个位:Date_Time[i]/10)+48);(Date_Time[i]%10)+48)注意要显示字符,必须加上48,因为Lcd只能显示字符为char型。定义displaytime〔〕函数,用DispOneChar(*,y,(Date_Time[i]/10)+48);语句将别离后的时分秒及日月显示在液晶适当的位置。由于星期只能用字符串显示,只能另外编写函数,因为Date_Time[3]为记录星期的数组元素,其值从1到7,分别对应星期日到星期一。可编写星期函数如下:voidweek(){if(Date_Time[3]==6)Display(5,0,"Fri");...}整个时间显示构造如下:mian〔〕{SetTime();SetDate();While(1){Date_Time[i]=DS12887_...;week();displaytime〔〕;}}2、时间星期日期的调整:日期及星期的调整可在主界面上进展,调用Ps2头文件,在while循环中用if判断如果有键按下则星期加减同时日期同步加减,if(KeyChar=='w'){DS12887_Day+=1;DS12887_Week+=1;if(DS12887_Week>7)DS12887_Week=1;KeyChar=0;}//设置新日期if(KeyChar=='j'){DS12887_Day-=1;DS12887_Week-=1;if(DS12887_Week<1)DS12887_Week=7;KeyChar=0;}注意星期只能从1到7变化。月份的调整要简单些if(KeyChar=='m'){DS12887_Mon+=1;KeyChar=0;}//设置新月份if(KeyChar=='_'){DS12887_Mon-=1;KeyChar=0;}时分秒的调整由于变量太多,可设置跳入另一界面实现,如果有‘s’键按下,则进入另一界面设置时间,在Newtime()中调整时间,以‘b’跳回主函数,函数从新设置的时间开场执行。闹钟的实现如果没有设置闹钟,在主界面上将显示"$*〞。在主函数循环中,如果按下回车键,进入闹钟设置界面,用一个全局变量数组Almtime[]记录所设置的闹钟时分秒,回车键后返回主界面,在原来显示"$*〞的地方显示"$〞及脑中翻开。并开启Led〔〕和autdly()函数开场始扫描比照Almtime[]和当前时间。如果到了设置时间,则开场闹钟,D2=0;即亮灯,并显示"LazypigGetup〞。并进入自动延时状态,如果有‘t’键按下,关闭闹钟,否则自动延时10秒后开场灭灯返回主界面,一分钟后继续开场闹钟。懒猪功能:对于赖床的人,转么设置的一个功能,如果到点了,可以按下'y'键延时三分钟。具体实现如下:while(Date_Time[5]%10==Almtime[7]-48&&D2==0){D2=0;Display(0,0,"Lazypig");Display(4,1,"Getup!");Date_Time[6]=DS12887_Sec;if(KeyChar=='t'){D2=1;Flag=1;KeyChar=0;WrtLcdCmd(Clear);break;}//关闭闹钟if(KeyChar=='y'){Almtime[7]+=3;if(Almtime[7]>'9'){Almtime[7]=Almtime[7]-10;Almtime[8]=Almtime[8]+1;}D2=1;KeyChar=0;WrtLcdCmd(Clear);break;}//懒猪功能if(Date_Time[6]/10==(Almtime[9]-47)){D2=1;WrtLcdCmd(Clear);break;}}以上为第一次开场闹钟,一分钟后通过语句while(Date_Time[5]%10==(Almtime[7]-47)),再次进入闹钟实现如上一样功能。4、闹钟的屏蔽样如果想屏蔽闹钟功能,按下'p'键,将闹钟屏蔽,屏蔽后,不扫描Led〔〕及其autdly〔〕函数,同时显示"$*〞。在主函数循环中可定义如下语句:if(KeyChar=='p'){flg=1;KeyChar=0;}其中,如果flg为1则不扫描Led〔〕及autdly〔〕;五、整体构造整个程序简化后如下:时分秒调整〔〕;时间显示〔〕;闹钟设置〔〕;亮灯〔〕;mian〔〕{Lcd初始化;开ps2中断;While〔1〕{时间数组=DS12887_;时间显示〔〕;日期及星期调整;时分秒调整〔〕;闹钟设置〔〕;亮灯〔〕;开关闹钟屏蔽;}}源程序*include<reg52.h>//包含单片机存放器的头文件*include<stdlib.h>//包含随机函数rand()的定义文件*include"absacc.h"*include<intrins.h>//包含_nop_()函数定义的头文件*include<12887.h>*include<1602.h>*include<ps2.h>sbitD2=P3^1;unsignedcharAlmtime[15]={'','','','_','_',':','_','_',':','_','_'};unsignedcharDate_Time[7];unsignedcharflg=1;//闹钟屏蔽标志unsignedcharFlag=1;//延时扫描标志voiddelay(){unsignedchari,j=200;for(i=0;i<200;i++)while(j){j--;}}voiddely(){unsignedchari;for(i=0;i<200;i++)delay();}voidDisplayTime()//别离并显示时间{//取余运算,求得各位数字DispOneChar(12,0,(Date_Time[2]/10)+48);DispOneChar(13,0,(Date_Time[2]%10)+48);//日期DispOneChar(9,0,(Date_Time[1]/10)+48);DispOneChar(10,0,(Date_Time[1]%10)+48);//月份DispOneChar(3,1,(Date_Time[4]/10)+48);//小时DispOneChar(4,1,(Date_Time[4]%10)+48);DispOneChar(6,1,(Date_Time[5]/10)+48);DispOneChar(7,1,(Date_Time[5]%10)+48);//分钟DispOneChar(9,1,(Date_Time[6]/10)+48);DispOneChar(10,1,(Date_Time[6]%10)+48);//秒钟}voidweek()//星期函数{if(Date_Time[3]==6)Display(5,0,"Fri");if(Date_Time[3]==5)Display(5,0,"Thu");if(Date_Time[3]==4)Display(5,0,"Wed");if(Date_Time[3]==3)Display(5,0,"Tue");if(Date_Time[3]==2)Display(5,0,"Mon");if(Date_Time[3]==1)Display(5,0,"Sun");if(Date_Time[3]==7)Display(5,0,"Sat");}voidNewtime() //新事件设置{unsignedchar*,y;//显示坐标unsignedchartmp[12];//用于暂存WrtLcdCmd(Clear);//清显示();WrtLcdCmd(AllOn);*=3;y=1;while(1){SetCursor(*,y);while(KeyPress==0);KeyPress=0;//按键标识清零DispOneChar(5,1,':');DispOneChar(8,1,':');Display(0,0,"Timeset:");if(KeyChar!='b'&&KeyChar!='s'){tmp[*]=KeyChar;DispOneChar(*,y,KeyChar);*++;if(*==11){*=3;//掉头}if(*==5)*=6;if(*==8)*=9;}if(KeyChar=='b')//Enter键保存参数{DS12887_Hour=(tmp[3]-48)*10+tmp[4]-48;DS12887_Min=(tmp[6]-48)*10+tmp[7]-48;DS12887_Sec=(tmp[9]-48)*10+tmp[10]-48;LcdInit();WrtLcdCmd(Clear);KeyChar=0;break;}}}voidautdly()//自动延时{//unsignedchardly1,dly2;//dly1=Almtime[9]-47;dly2=Almtime[7]-47;while(Date_Time[5]%10==Almtime[7]-48&&D2==0){D2=0;Display(0,0,"Lazypig");Display(4,1,"Getup!");Date_Time[6]=DS12887_Sec;if(KeyChar=='t'){D2=1;Flag=1;KeyChar=0;WrtLcdCmd(Clear);break;}//关闭闹钟if(KeyChar=='y'){Almtime[7]+=3;if(Almtime[7]>'9'){Almtime[7]=Almtime[7]-10;Almtime[8]=Almtime[8]+1;}D2=1;KeyChar=0;WrtLcdCmd(Clear);break;}//懒猪功能if(Date_Time[6]/10==(Almtime[9]-47)){D2=1;WrtLcdCmd(Clear);break;}}while(Date_Time[5]%10==(Almtime[7]-47))//如果没有关,一分钟后再闹{D2=0;Display(0,0,"Lazypig");Display(4,1,"Getup!");Date_Time[6]=DS12887_Sec;if(KeyChar=='t'){D2=1;Flag=1;KeyChar=0;WrtLcdCmd(Clear);break;}//关闭闹钟if(KeyChar=='y'){Almtime[7]+=3;if(Almtime[7]>'9'){Almtime[7]=Almtime[7]-10;Almtime[8]=Almtime[8]+1;}D2=1;KeyChar=0;WrtLcdCmd(Clear);break;}//懒猪功能if(Date_Time[6]/10==(Almtime[9]-47)){D2=1;Flag=1;WrtLcdCmd(Clear);break;}//10秒后关}}voidLed()//亮灯{if((Almtime[10]-48)==Date_Time[6]%10&&(Almtime[9]-48)==Date_Time[6]/10)if((Almtime[7]-48)==Date_Time[5]%10&&(Almtime[6]-48)==Date_Time[5]/10)if((Almtime[4]-48)==Date_Time[4]%10&&(Almtime[3]-48)==Date_Time[4]/10)D2=0;}voiddisalm()//闹钟界面显示{DispOneChar(3,1,Almtime[3]);DispOneChar(4,1,Almtime[4]);DispOneChar(6,1,Almtime[6]);DispOneChar(7,1,Almtime[7]);DispOneChar(9,1,Almtime[9]);DispOneChar(10,1,Almtime[10]);}Alrm(){unsignedchar*,y;//显示坐标//dely();KeyChar='-';KeyPress=0;WrtLcdCmd(Clear);//清显示WrtLcdCmd(AllOn);*=3;y=0;while(1){ Display(0,0,"Alarmset:"); DispOneChar(5,1,':'); DispOneChar(8,1,':'); WrtLcdCmd(0*0E);while(KeyPress==0)disalm();//等待有键按下KeyPress=0;//按键标识清零if(KeyChar==''){*++;SetCursor(*,1);WrtLcdCmd(0*0F);} if(KeyChar=='-'){*--;SetCursor(*,1);} if(*>10||*<4){*=3;SetCursor(*,1);}if(KeyChar==0*0EF){KeyChar='-';flg=0;Flag=0;LcdInit();break;}else{DispOneChar(*,1,KeyChar);Almtime[*]=KeyChar;}}}main(){dely();LcdInit(); Init12887();IT0=0;//设外部中断0为低电平触发E*0=1;//开中断0EA=1;//SetTime(9,15,34);//SetDate(2021,8,26);//DS12887_Week=6;while(1){week();Date_Time[6]=DS12887_Sec;//秒Date_Time[5]=DS12887_Min;//分Date_Time[4]=DS12887_Hour;//时Date_Time[3]=DS12887_Week;//星期Date_Time[2]=DS12887_Day;//日Date_Time[1]=DS12887_Mon;//月Date_Time[0]=DS12887_Year;//定义时间数组并设定初始值if(flg==1)Display(0,0,"$*");//屏蔽状态if(flg==0)Display(0,0,"$");//开启状态DispOneChar(11,0,'-');DispOneChar(5,1,':');DispOneChar(8,1,':');if(KeyChar=='s')Newtime();//设置新时间if(KeyChar=='w'){DS12887_Day+=1;DS12887_Week+=1;if(DS12887_Week>7)DS12887_Week=1;KeyChar=0;}//设置新日期if(KeyChar=='j'){DS12887_Day-=1;DS12887_Week-=1;if(DS12887_Week<1)DS12887_Week=7;KeyChar=0;}if(KeyChar=='m'){DS12887_Mon+=1;KeyChar=0;}//设置新月份if(KeyChar=='_'){DS12887_Mon-=1;KeyChar=0;}if(KeyChar==0*ef){Alrm();WrtLcdCmd(Clear);}//设置闹钟if(Flag==0){autdly();}//关闭后不延时if(KeyChar=='p'){flg=1;KeyChar=0;}//屏蔽闹钟if(flg==0)Led();//flg=0时扫描闹钟时间DisplayTime();}}七、心得体会从了解硬件到熟悉硬件及芯片功能,再到编程实现功能用时四天,真正的的编程时间实为两天。印象很深的是,头两天很不熟悉硬件开发板,忘了给下面的板子上电,时钟芯片的时间不能调出来给单片机,导致不管怎样改编程序,都显示同一个时间,而且是一些看不懂得乱码。后来发现问题后,才真正开场编程,这让我认识到硬件不熟悉,编程能力再好,往往也无从下手的。至于乱码问题,也想了很久,定义的时间的数组中,开场赋值的都是一些数值,而实际上调用函数Display〔〕和DispOneChar〔〕都必须是char字符型。开场的时候无论怎么改变数组里面元素值,都是显示一些看不懂得字符,后来我试探性的将每个元素都加上一个单引号,才在液晶上正常显示了定义的数字,原来显示的都是数值对应的ASC码。别离后我想到数字跟ASC码相隔48,所以在别离的时候特意用了Date_Time[i]/10)+48(Date_Time[i]%10)+48;到达正常显示数字对应的ASC码的目的。时间显示只是第一步,但也算是一个关键,没有时间就没有闹钟。本来先调用头文件中的SetAlarm〔〕函数实现闹钟功能,后来发现到时间后引发的中断在P3.5脚,不好当成闹钟使用。就只好加重单片机负担不用硬件实现,用软件自己定义了一个闹钟函数,用if语句扫描判断,到点后P3.1脚的二极管开场亮灯,后来也加上了自己的一点小创意,在液晶上显示LazyPigGetup。之后定义的Flg和flg两个全局变量帮我很好的实现了自动延时和闹钟屏蔽等功能,觉得自己的想法都得到了实现,小有成就感。后来和其他同学比照,我的闹钟还是有优势的,但是他们还能设置时间,又定义了一项设置时间日期的功能。总之从1602液晶到ps2键盘再到12C887都是第一次接触,能在几天用软件程序把它们结合起来,实现一个多功能闹钟,自己觉得还是收获不小的。当然其间不得不成认百度功能很强大,也请教了他很多不懂的地方,比方说编译过程中的语法和其他错误问题。由于时间有限,还要编一个计算器,设想好的实现多个闹钟的功能未能实现,有点小遗憾,不过有时间,还是会想一想的。课题二:基于51单片机的计算器设计材料材料:STC89C52单片机开发板一块,1602液晶一片,ps2键盘,下载线,个人计算机编译软件:wave及keil下载程序软件:STC专用下载串口软件二、思路分析1、硬件:计算器的加减乘除对单片机来说本来不难,但是要结合硬件,实现显示和输入,必先熟悉PS2键盘和液晶的使用。2、算法问题:考虑到计算器有小数运算问题,数据类型可以选用float浮点型。要想实现显示和数据存储,就必须用到数组,而头文件stdio.h中的sscanf〔〕和sprintf〔〕函数接近完美的实现了数组和数据类型的转换。要实现都功能,就得有单值函数的计算,如三角函数,log、ln等等,而调用math.h就使得这些算法变得很简单。三、功能实现1、数据输入和记录:要实现显示,可先将数据先输入并记录到*一个数组tmp[]中,在液晶上显示,等有符号和算法键按下后,记录第一个数据,并清空tmp[],开场记录第二个数据。具体实现如下if(firstflag==0)//如果是输入的第一个数据,赋值给a,并把标志位置1,到下一个数据输入时可以跳转赋值给b { sscanf(temp,"%f",&a);firstflag=1; } else sscanf(temp,"%f",&b); for(s=0;s<16;s++)//赋值完成后把缓冲区清零,防止下次输入影响结果temp[s]=0;其中firstflag起到标志第几个数据的作用,如果firstflag等于0,就用while(KeyPress==0);等待记录第二个数据,如果是等于1则记录下第二个数据。按下‘=’开场计算。、双值函数计算:在记录第一个数据的同时记下按下的符号键,按下等于号后根据记录下的符号键使用switch〔〕语句开场计算:if(('c'==num)||(i==16)||('+'==num)||('-'==num)||('*'==num)||('/'==num)||('l'==num)||('t'==num)||('s'==num)||('g'==num)||('p'==num)||('='==num)) if(num!='=')//判断当前符号位并做相应处理 sign=num;//如果不是等号记下标志位 else { firstflag=0;//检测到输入=号,判断上次读入的符合switch(sign){casesign:a〔sign〕b;break;}单值函数计算:在输入第一个数据后,可以进一步判断,如果输入的为单值函数符号,如sin,tan,log等的时候,不须等待第二个数据的输入,直接按'='计算出来。即:switch(sign){casesign:sign〔a〕;break;}小数和头数字点处理:在输入的过程中,必须判断小数点的位置,特别是第一位的时候,如果是0,则需判断第二位是否是小数点。if((1==i)&&(temp[0]=='0'))//如果第一个字符是0,判读第二个字符 { if(num=='.')//如果是小数点则正常输入,光标位置加1 { temp[1]='.'; DispOneChar(1,0,num);//输出数据 i++;}//这里没有判断连续按小数点,如 else { temp[0]=num;//如果是1-9数字,说明0没有用,则直接替换第一位0 DispOneChar(0,0,num);//输出数据 } } else {temp[i]=num;DispOneChar(i,0,num);//输出数据 i++;//输入数值累加 }整体构造程序构造如下:voidfun〔〕{while〔1〕{记录数据a;记录数据b;单值符号判断;双值判断;运算;小数点判断;}}main〔〕{Lcd初始化;开ps2中断;While〔1〕{fun〔〕;}}源程序*include<reg52.h>*include<math.h>//调用单值函数*include<intrins.h>*i

温馨提示

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

评论

0/150

提交评论