当前位置:文档之家› 单片机课程设计电子时钟实验可定时调闹钟用LCD显示

单片机课程设计电子时钟实验可定时调闹钟用LCD显示

姓名学号时间 2013.1.9实验题目电子数字钟一、实验目的与要求1.电子数字钟必须具有显示年、月、日和显示时、分、秒的功能。

(用LCD显示)。

2.具有按键时间校正功能。

3.具备设定闹钟和定时闹钟功能。

二、实验环境(硬件环境、软件环境)1.硬件环境:单片机开发板一个,计算机一台,单片机主机电源线及与计算机的连接线各一条。

2.软件环境:软件Keil C51和软件Flash Magic。

三、实验电路(P2口输入、P1口输出实验原理图)本次实验主要使用了开发板的4个板块,分别是单片机STC89C52(如图2所示)、矩阵键盘(如图2所示)、1206LCD显示器和蜂鸣器(如图3所示)。

其中单片机芯片通过P0口把总线和矩阵键盘连接;通过P2.2和蜂鸣器间接相连,因为蜂鸣器所在的电路已经连芯片ULN2003,因此用一根杜邦线把P2.2和芯片ULN2003的第一个输入口IN1连起来。

而键盘显示这一块,由于内部已经把键盘显示的电路和单片机芯片连接起来了,所以不需要借助杜邦线了。

图1为实物连线图。

图1 实物连线图图2 单片机机座和矩阵键盘图3 蜂鸣器和1602液晶显示器四、程序流程图主要算法:主函数中先定时中断初始化,利用定时器中断实现走时,调用LCD显示程序和按键处理子函数,再调用显示时间函数显示初始时间值。

同时,在主函数中判断当前的小时和分钟值是否等于闹钟设定的时间,若等于则让蜂鸣器响。

主函数算法的框图如图4所示。

按键处理函数算法:通过键盘扫描函数得到确定哪个键盘按下,得到键盘值,如果键0按下则暂停时钟走时;键1按下则在当前的光标所在的时间单元加1;键2按下则开闹钟;键3按下则实现当前的时间单元左移一位的功能;键4按下则在当前的光标所在的时间单元减1。

时间的年月日算法:通过定时器实现时钟的走时,秒满60,分钟加1;分满60,小时加1;小时满24,日加1;至于每个月的天数根据闰年和非闰年的表格确定当月天数。

图4 主函数算法框图五、程序测试报告:(调试输入数据、结果数据或状态。

)1.输入:源代码1输出结果:(1)电子数字钟必须具有显示年、月、日和显示时、分、秒的功能。

(用LCD显示)(2)具有按键时间校正功能。

(3)具备设定闹钟和定时闹钟功能。

六、体会:(碰到的问题、如何解决、有何体会。

)1.深入了解如何运用高级语言,此次实验运用C语言进行编程,使单片机开发板实现电子时钟的功能,对汇编语言和高级语言在实现单片机功能的特点也加深了认识。

体会到C语言在编程时的灵活性和不用过多考虑硬件的方便。

2.该实验中主要用到几个板块,单片机控制,键盘运用,LCD显示,蜂鸣器。

掌握了键盘的工作方式和扫描的特点,懂得运用C语言进行编程键盘扫描的程序;掌握LCD显示的几种功能指令,尽管LCD显示的程序较多,但是工作原理弄清楚后就清晰很多;掌握如何把硬件和软件联系起来,特别是控制定时闹钟蜂鸣器的程序,由于该片单片机开发板的蜂鸣器是和步进电机等电路连在一起的,所以需要把控制蜂鸣器的连接端口找到,并用指令“sbit BEEP=P2^2”进行定义;对单片机的应用有了更深入的认识和了解。

3.蒋老师在实验过程中一直强调程序的排版格式,让我从细节上更注意排版,收获了一个美观处理文档的习惯。

在实验过程中遇到了调试失败的各种问题,除了得到老师的指导,自己也主动上网搜索发生错误的各种原因,培养了解决问题的能力。

七、源程序代码#include<reg52.h>#include<intrins.h>sbit BEEP=P2^2; //喇叭端口sbit RS = P2^4; //定义端口sbit RW = P2^5;sbit EN = P2^6;bit Al; //闹钟标志位#define DataPort P0#define KeyPort P1#define uint unsigned int#define uchar unsigned charuchar code table[]="0123456789";//转换成液晶显示的字符uchar table1[]={31,31,29,31,30,31,30,31,31,30,31,30,31}; //闰年uchar table2[]={31,31,28,31,30,31,30,31,31,30,31,30,31}; //非闰年uint i,j,k;uint n_hour,n_minu; //闹钟时,分uint sec,minu,hour,day,mon; //秒,分,时,日,星期uint count,key;unsigned long int year; //年uchar hs,hg,mis,mig,ss,sg;uchar nhs,nhg,nms,nmg;uchar ms,mg,ds,dg;uchar yq,yb,ys,yg;uchar i_,j_,k_;/*------------------------------------------------mS延时函数,这里使用单片机的晶振为12MHz------------------------------------------------*/void DelayMs(uchar i_){for(j_=i_;j_>0;j_--)for(k_=500;k_>0;k_--)}/*------------------------------------------------判忙函数-----------------------------------------*/bit LCD_Check_Busy(void){DataPort= 0xFF;RS=0;RW=1;EN=0;_nop_();EN=1;return (bit)(DataPort & 0x80);}/*------------------------------------------------写入命令函数------------------------------------------------*/ void LCD_Write_Com(uchar com){RS=0;RW=0;DataPort=com;DelayMs(5);EN=1;DelayMs(5);EN=0;}/*------------------------------------------------写入数据函数------------------------------------------------*/ void LCD_Write_Data(uchar Data){//while(LCD_Check_Busy()); //忙则等待DelayMs(5);RS=1;RW=0;EN=1;DataPort= Data;DelayMs(5);EN=0;}/*------------------------------------------------清屏函数------------------------------------------------*/ void LCD_Clear(void){LCD_Write_Com(0x01);DelayMs(5);}/*------------------------------------------------写入字符串函数------------------------------------------------*/ void LCD_Write_String(uchar x,uchar y,uchar *s){if (y == 0){ LCD_Write_Com(0x80 + x); }else{ LCD_Write_Com(0xC0 + x); }while (*s){ LCD_Write_Data( *s); s ++; }}/*------------------------------------------------写入字符函数------------------------------------------------*/void LCD_Write_Char(uchar x,uchar y,uchar Data){if (y == 0){ LCD_Write_Com(0x80 + x); }else{ LCD_Write_Com(0xC0 + x); }LCD_Write_Data( Data);}/*------------------------------------------------初始化函数------------------------------------------------*/void LCD_Init(void){LCD_Write_Com(0x38); /*显示模式设置*/LCD_Write_Com(0x08); /*显示关闭*/LCD_Write_Com(0x01); /*显示清屏*/LCD_Write_Com(0x06); /*显示光标移动设置*/DelayMs(5);LCD_Write_Com(0x0C); /*显示开及光标设置*/}/*------------------------------------------------按键扫描函数,返回扫描键值------------------------------------------------*/ unsigned char KeyScan(void) //键盘扫描函数,使用行列反转扫描法{unsigned char cord_h,cord_l;//行列值中间变量KeyPort=0x0f; //行线输出全为0cord_h=KeyPort&0x0f; //读入列线值if(cord_h!=0x0f) //先检测有无按键按下{DelayMs(10); //去抖if((KeyPort&0x0f)!=0x0f){cord_h=KeyPort&0x0f; //读入列线值KeyPort=cord_h|0xf0; //输出当前列线值cord_l=KeyPort&0xf0; //读入行线值while((KeyPort&0xf0)!=0xf0);//等待松开并输出return(cord_h+cord_l);//键盘最后组合码值}}return(0xff); //返回该值}/*------------------------------------------------ 按键值处理函数,返回扫键值------------------------------------------------*/ unsigned char KeyPro(void){switch(KeyScan()){case 0x7e:return 0;break;//0 暂停键case 0x7d:return 1;break;//1 加case 0x7b:return 2;break;//2 闹钟case 0x77:return 3;break;//3 左移case 0xbe:return 4;break;//4 减case 0xbd:return 5;break;//5case 0xbb:return 6;break;//6case 0xb7:return 7;break;//7case 0xde:return 8;break;//8case 0xdd:return 9;break;//9case 0xdb:return 10;break;//acase 0xd7:return 11;break;//bcase 0xee:return 12;break;//ccase 0xed:return 13;break;//dcase 0xeb:return 14;break;//ecase 0xe7:return 15;break;//fdefault:return 0xff;break;}}/*------------------------------------------------键盘控制时间函数(0键-暂停键,1键-加1键,2键-开闹钟,3键-左移键,4键-减1键)------------------------------------------------*/void jianpan(){key=KeyPro();if(key!=0xff){if(key==0) //关中断,暂停时钟{EA=~EA;}if((EA==0)&&(Al==0)) //若闹钟关且时间暂停,则可以改动时间{if(key==3) // 左移,i为改动标志位,按顺序改动秒分时日月年{if(i<6){i++;}else{i=0;}}else if((key==1)) //加1,根据i增加对应的数值{switch(i){case 0:if(sec<59){sec++;}else{sec=0;};break;case 1:if(minu<59){minu++;}else{minu=0;};break;case 2:if(hour<23){hour++;}else{hour=0;};break;case 3:if(day<31){day++;}else{day=0;};break;case 4:if(mon<12){mon++;}else{mon=0;};break;case 5:year++;break;}}else if((key==4)) //减1,根据i减少对应的数值{switch(i){case 0:if(sec>0){sec--;}else{sec=60;};break;case 1:if(minu>0){minu--;}else{minu=60;};break;case 2:if(hour>0){hour--;}else{hour=23;};break;case 3:if(day>1){day--;}else{day=31;};break;case 4:if(mon>1){mon--;}else{mon=12;};break;case 5:if(year>0)year--;break;}}}if(key==2) //闹钟开关{Al=~Al;}if(Al==1) //闹钟开,显示闹钟,允许设定闹钟if(key==3) //左移,设定标志位{if(j<1){j++;}else{j=0;}}else if(key==1) //加1,根据l增减设定{switch(j){case 0:if(n_hour<24)n_hour++;break;case 1:if(n_minu<60)n_minu++;break;}} else if(key==4)//减1{switch(j){case 0:if(n_hour>0)n_hour--;break;case 1:if(n_minu>0)n_minu--;break;}}}else if(Al==0){LCD_Write_Char(15,0,' ');LCD_Write_String(10,1," ");}}/*------------------------------------------------时间的年月日算法(考虑闰年和非闰年)------------------------------------------------*/ void time() //计时函数{if(sec==60){sec=0;minu++;if(minu==60){minu=0;hour++;if(hour==24){ hour=0;day++;if(year%4==0&&year%100!=0||year%400==0) //闰年{if(day==table1[mon]+1){day=0;mon++;if(mon==13){mon=0;year++;}}}else //非闰年{if(day==table2[mon]+1){day=0;mon++;if(mon==13){mon=0;year++;}}}}}}}/*------------------------------------------------ 定时器中断控制时钟走动------------------------------------------------*/ void time0_to()interrupt 1{TH0=(65536-49872)/256;TL0=(65536-49872)%256;count++;if(count==20) //中断20次为一秒{count=0;sec++;time();}}/*------------------------------------------------时间显示函数------------------------------------------------*/void DISPLAY(){uchar KeyPro();yq=year/1000;yb=(year/100)%10;ys=(year/10)%10;yg=year%10;hs=hour/10; //时分秒HH.MM.SShg=hour%10;mis=minu/10;mig=minu%10;ss=sec/10;sg=sec%10;ms=mon/10; //月日-星期MM.DD.-W mg=mon%10;ds=day/10;dg=day%10;nhs=n_hour/10; //闹钟定时HH.MM.SS nhg=n_hour%10;nms=n_minu/10;nmg=n_minu%10;//年显示LCD_Write_Char(0,0,table[yq]); LCD_Write_Char(1,0,table[yb]); LCD_Write_Char(2,0,table[ys]);LCD_Write_Char(3,0,table[yg]); LCD_Write_Char(4,0,'-');//月显示LCD_Write_Char(5,0,table[ms]); LCD_Write_Char(6,0,table[mg]); LCD_Write_Char(7,0,'-');//日显示LCD_Write_Char(8,0,table[ds]);LCD_Write_Char(9,0,table[dg]);//时显示LCD_Write_Char(1,1,table[hs]);LCD_Write_Char(2,1,table[hg]);LCD_Write_Char(3,1,':');//分显示LCD_Write_Char(4,1,table[mis]);LCD_Write_Char(5,1,table[mig]);LCD_Write_Char(6,1,':');//秒显示LCD_Write_Char(7,1,table[ss]);LCD_Write_Char(8,1,table[sg]);if(Al==1) //闹钟开,显示闹钟,允许设定闹钟{LCD_Write_Char(15,0,'*');LCD_Write_Char(10,1,table[nhs]);LCD_Write_Char(11,1,table[nhg]);LCD_Write_Char(12,1,':');LCD_Write_Char(13,1,table[nms]);LCD_Write_Char(14,1,table[nmg]);}}/*------------------------------------------------主函数------------------------------------------------*/ void main(void){EA=1; //开中断ET0=1;TR0=1;TMOD=0x01;TH0=(65536-45872)/256;TL0=(65536-45872)%256; //定时器赋初值hour=23;minu=59;sec=49; //赋初值:11点59分49秒n_hour=18;n_minu=10; //闹钟赋初值18点10分year=2014;mon=1;day=1; //年月日赋初值LCD_Init();LCD_Write_Com(0x0F); //光标开,光标闪烁开DelayMs(750); //延时0.75秒LCD_Clear();while(1){jianpan(); //扫描键盘DISPLAY(); //显示时间if((Al==1)&&(n_hour==hour)&&(n_minu==minu)){DelayMs(1);BEEP=!BEEP;}//闹钟响}}。

相关主题