基于μPD78F0485单片机实验板的实时时钟程序设计与实现讲解
- 格式:doc
- 大小:962.00 KB
- 文档页数:19
实验报告5.按下Key4 Key3执行时,该按键执行加一操作,Led灯按照5秒顺时针一个一个亮。
6.按下Key5 Key3执行时,该按键执行减一操作,Led灯按照5秒顺时针一个一个亮。
7.按下Key6 Key3执行时,该按键执行确定操作,Led灯按照5秒顺时针一个一个亮。
8.按下INT 闹钟关闭。
5、实验总结本次实验是对课本上“电子日历钟设计”的加深。
通过本次试验我对led和led显示有了更加熟悉的认识,能熟练应用它们的功能。
同时我对时钟计数器也有了一定的认识,可以使用定时中断实现实时时钟,更重要的是我的实践能力有很大的提高。
程序设计中遇到的问题(1)、问题:初始完成程序后秒针走的时间很快,不是精确的一秒走一次。
原因:单片机只能用主系统时间,修改fprs后可以真确显示。
(2)、问题:时间切换函数与显示函数和设计的不一样,如只需要显示时,却多显示分。
原因:在仔细看代码后发现每次按键中断都在调用time1()函数,而seeond++在里面,所以每次都会加快秒的运行。
把seeond++移到外面放入time()函数后这个问题就解决了。
(3)、问题:运行时发现按键中断总会加快秒的运行,不是很精确。
原因:最后设置了一个虚拟的key7,当执行完时间指向ease7,然后调用Freshddisplaybuffer函数,这样就很好的解决了这个问题。
在程序调试过程中,设置断点并且在断点处增加一个LED灯,通过判断灯是否亮可以判断程序是否执行到该位置,对程序调试有很大的帮助。
开始WhileKey? 6 1 3 2 4 结束主程序流程图附件程序流程图:Yd_c_inter() Freshddisp laybuffer(); Set_D_T(); noise(); key=7; , 5 NDownNum() ; Freshddispl aybuffer(); Set_D_T(); noise(); key=7; FreshddisplaybufferTime1();Show_Time();Show_Time(); Time1() Freshddis playbuffer ();; Display_D ate(); noise(); 初始化蜂鸣器并关闭蜂鸣器BZOE = 0;初始化 INT 按键 Init_Inter();初始化 Lcd 和 Led; Init_Lcd(),Init_Led();UpNum(); Freshddis playbuffer (); Set_D_T(); noise(); key=7; key = 0; noise(); Time1(); Freshddis playbuffer (); Set_D_T(); noise();初始化按键中断InitKey_INTKR();Time1(); noise();关中断DI ()关中断EI()开中断EI();源代码:#pragma sfr#pragma EI#pragma DI#pragma access#pragma interrupt INTTM000 Time#pragma interrupt INTKR OnKeyPress#pragma interrupt INTP5 OnKeyOver void Init_Led();void InitKey_INTKR();void Init_Lcd();void Init_Inter();void LightOneLed(unsigned char ucNum);void LightOff();int Count_Day(int month);〃定义变量i,是切换时间的标志//定义 key=0 〃用于存放当前月的天数 〃默认的秒second=0 〃默认的分minute=0 〃默认的时hour=12 〃默认的天day=1 〃默认的月month=5 〃默认的年year=2014 〃默认的闹钟时=1 〃默认的闹钟分=1 〃秒的数码显示缓存区 〃分的数码显示缓存区 〃时的数码显示缓存区 〃天的数码显示缓存区 〃月的数码显示缓存区 〃年的数码显示缓存区 〃月,天的数码显示缓存区 〃时,分的数码显示缓存区 〃分,秒的数码显示缓存区 〃闹钟时的数码显示缓存区 〃闹钟分的数码显示缓存区 //INT 中断中间变量LCD_num[10]={0X070d,0x0600,0x030e,0x070a,0x0603,0x050b,0x050f,0x0700,0x070f,0x070b);//数字0〜〜9的显示码unsigned char Scond;// ......................................................... 延时函数1 .............................................. //void Delay(int k){int i,j;for(i=0;i<k;i++){for(j=0;j<k;j++){〃使用特殊功能寄存器 〃开中断 〃关中断 〃使用绝对地址指令 〃定义时间中断函数为Time 〃定义按键中断为OnKeyPress //定义INT 中断为OnKeyOverchar i=0;int key=0;int temp=1;int temp1 = 1;int second=0;int minute=0;int hour=12;int day=1;int month=5;int year=2014;int c_hour=1;int c_minute=1;int buffs[2];int buffm[2];int buffh[2];int buffday[2];int buffmonth[2];int buffyear[4];int buffmd[4];int buffhm[4];int buffms[4];int buffch[2];int buffcm[2];unsigned char Que = 0;int// .................................................. 初始化Led函数................ //void Init_Led(){PM13=0XF0; 〃端口13的第四位为输出模式PM14=0XF0; 〃端口14的第四位为输出模式PM15=0XF0; 〃端口15的第四位为输出模式)// ............................................................. 按键中断函数............... •//void InitKey_INTKR(){PM4 = 0x3F; //P4的六个端口设置为输入模式PU4 = 0x3F; 〃接通上拉电阻KRM = 0x3F; 〃允许六个按键中断KRMK = 0;PM3.0 = 1;PU3.0 = 1;EGP.5 = 1;PMK5 = 0;PPR5 = 0;KRPR = 1;)// ............................... 初始化lcd函数............... //void Init_Lcd(){ PFALL=0x0F; 〃所有接lcd引脚指定为lcd引脚LCDC0=0x34; 〃设置原时钟和时钟频率LCDMD=0x30; //设置lcd电压为3/5电压LCDM=0xC0; //4分时1/3偏压模式)// ............................... 初始化定时器Inter函数.............. 〃void Init_Inter(){ CRC00)=0; //CR000为比较寄存器PRM00=0X04; 〃计数时钟为fprs/2A8 CR000=0X7FFF;//时间间隔为1s TMMK010=1;//TMMK010 中断屏蔽TMMK000=0; //TMMK000 中断允许TMC00=0X0C; //TM00和CR000相等时进入清零&启动模式)void Time(){ second++;)// ............................................................. 按键中断函数............... •//void OnKeyPress(){DI();switch(P4&0x3F) 〃判断哪个按键按下{case 0x3e:key=1; //按键keyl按下break;case 0x3d:key=2; //按键key2按下break;case 0x3b:key=3; //按键key3按下break;case 0x37:key=4; //按键key4按下break;case 0x2f:key=5; //按键key5按下break;case 0x1f:key=7; //按键key6按下break;default:break;)EI();)// ............................................................... I NT按键中断函数............... //void OnKeyOver(){DI();Que = 0; //判断Que是否为0BZOE = 0; 〃蜂鸣器关闭EI();)// ................................................... Led小灯函数............... //void LightOneLed(unsigned char ucNum){switch(ucNum){ 〃检测变量ucNumcase 0:case 1:case 2:case 3:P13 |= (unsigned char) 1 << (ucNum);〃如果为0到3中的一个值则让LED1到LED4中的一个亮break;case 4:case 5:case 6:case 7:P14 |= (unsigned char) 1 << (ucNum - 4);〃如果为4到7中的一个值则让LED5到LED8中的一个亮break;case 8:case 9:case 10:case 11:P15 |= (unsigned char) 1 << (ucNum - 8);〃如果为8至U 11中的一个值则让LED9至U LED12中的一个亮break;default:break;))// ................................................... Led小灯熄灭函数............... 〃void LightOff(){P13 = 0;P14 = 0;P15 = 0;)// ............................................. 时间函数.............. 〃void Time1(){if((second % 5) == 0){ 〃秒大于 5 变为0Scond = second / 5 + 1;LightOff(); 〃调用小灯亮函数LightOneLed(Scond % 12);)if(second>=60){minute++; //秒大于60时分加1second=0;if(minute>=60){minute=0;hour++; //分大于60时时加1if(hour>=24){hour=0;day++; 〃时大于24时天加1temp=Count_Day(month);if(day>=temp){day=1;month++; 〃天大于当前月份的天数时月加1if(month>=13){month=1;year++; //月大于12时年加1))))))// ...................................... 计算当前月的天数.............. •//int Count_Day(int month){int day;if((month==4)||(month==6)||(month==9)||(month==11))//4,6,9,11 月为30 天day=30;else if(month==2){if((year%4==0&&year%100==0)||(year%400==0))day=29; 〃闰年2月29天elseday=28; //平年2月28天)elseday=31; //1,3,5,7,8,10,12 月为31 天return (day);)// ................................ 倒计时函数 ...... //void Show_Time(){ pokew(0xFA40,0x00); pokew(0xFA42,0x00); pokew(0XFA48,buffs[1]); pokew(0XFA4A,buffs[0]); pokew(0XFA44,buffm[1]); pokew(0XFA46,buffm[0]); pokew(0xFA4C,0x00); pokew(0xFA4E,0x00); Delay(100);) // ..................................................................... 日期显示函数 ................. •// void Display_Date(){buffm[0]|=0x0800;pokew(0xFA40,buffyear[3]);〃显示年 pokew(0xFA42,buffyear[2]);pokew(0xFA44,buffyear[1]);pokew(0xFA46,buffyear[0]);pokew(0xFA48,buffmonth[1]);〃显示月 pokew(0xFA4A,buffmonth[0]);pokew(0xFA4C,buffday[1]);〃显示日pokew(0xFA4E,buffday[0]);temp1=0;) // .................................................................... 时间显示函数 .............. •//void Display_Time(){ pokew(0xFA40,0x00);pokew(0xFA42,0x00);pokew(0xFA44,buffh[1]);〃显示时 pokew(0xFA46,buffh[0]);pokew(0xFA48,buffm[1]);〃显示分 pokew(0xFA4A,buffm[0]);pokew(0xFA4C,buffs[1]);〃显示秒 pokew(0xFA4E,buffs[0]);)// ..................................................................... 设定时间函数 .............. •//void Set_D_T(){int lcd_addr;lcd_addr = 0xFA40;switch(i){case 1:pokew(lcd_addr,buffyear[3]);〃时间年 pokew(lcd_addr+2,buffyear[2]);pokew(lcd_addr+4,buffyear[1]);pokew(lcd_addr+6,buffyear[0]);pokew(lcd_addr+8,0x00);pokew(lcd_addr+10,0x00);pokew(lcd_addr+12,0x00);pokew(lcd_addr+14,0x00);break;case 2:pokew(lcd_addr,0x00);pokew(lcd_addr+2,0x00);pokew(lcd_addr+4,0x00);pokew(lcd_addr+6,0x00);pokew(lcd_addr+8,buffmonth[1]);〃时间月 pokew(lcd_addr+10,buffmonth[0]);pokew(lcd_addr+12,0x00);pokew(lcd_addr+14,0x00);break;case 3:pokew(lcd_addr,0x00); //在lcd 右边显示1〃在lcd 右边显示0 〃在lcd 右边显示1 〃在lcd 右边显示0pokew(lcd_addr+2,0x00);pokew(lcd_addr+4,0x00);pokew(lcd_addr+6,0x00);pokew(lcd_addr+8,0x00);pokew(lcd_addr+10,0x00);pokew(lcd_addr+12,buffday[1]); 〃时间日pokew(lcd_addr+14,buffday[0]);break;case 4:pokew(lcd_addr,0x00);pokew(lcd_addr+2,0x00);pokew(lcd_addr+4,buffh[1]); 〃时间时pokew(lcd_addr+6,buffh[0]);pokew(lcd_addr+8,0x00);pokew(lcd_addr+10,0x00);pokew(lcd_addr+12,0x00);pokew(lcd_addr+14,0x00);break;case 5:pokew(0xFA40,0x00);pokew(0xFA42,0x00);pokew(0xFA44,0x00);pokew(0xFA46,0x00);pokew(0xFA48,buffm[1]); 〃时间分pokew(0xFA4A,buffm[0]);pokew(0xFA4C,0x00);pokew(0xFA4E,0x00);break;case 6:pokew(0xFA40,0xd1);pokew(0xFA42,0xd0);pokew(0xFA44,0xd7);pokew(0xFA46,0xd1);pokew(0xFA48,0x50);pokew(0xFA4A,0x56);pokew(0xFA4C,buffch[1]); 〃闹钟时pokew(0xFA4E,buffch[0]);break;case 7:pokew(0xFA40,0xd1);pokew(0xFA42,0xd0);pokew(0xFA44,0xd7);pokew(0xFA46,0xd1);pokew(0xFA48,0x50);pokew(0xFA4A,0x00);pokew(0xFA4C,buffcm[1]); 〃闹钟分pokew(0xFA4E,buffcm[0]);break;default:break;))// ........................................................ 切换时间函数 .............. …// void d_c_inter(){DI(); 〃关中断i++;if(i>7) 〃切换标志>7, i=1,否则i++i=1;EI(); 〃开中断)// ........................................................ 调整时间加函数 .............. •// void UpNum(){ switch(i){ case 1:year++;case 2:month++;if(month > 12){month = 1;)break;case 3:temp = Count_Day(month);day++;if(temp < day)day = 1;break;case 4:hour++;if(hour > 23)hour = 1;break;case 5:minute++;if(minute > 59)minute = 0;break;case 6:c_hour++;if(c_hour > 23)c_hour = 1;break;case 7:c_minute++;if(c_minute > 59)c_minute = 0;break;default:break;))// ........................................................ 调整时间减函数.............. …// void DownNum(){switch(i){case 1:year--;case 2:month--;if(month < 1){month = 12;)break;case 3:temp = Count_Day(month);day--;if(day < 1)day = temp;break;case 4:hour--;if(hour < 1)hour = 23;break;case 5:minute--;if(minute < 0)minute = 59;break;case 6:c_hour--;if(c_hour < 1)c_hour = 23;break;case 7:c_minute--;if(c_minute < 0)c_minute = 59;break;default: break;))// .................................................. 闹铃以及小灯函数.............. •//void noise(){if(c_hour == hour && c_minute == minute && Que == 1){ 〃闹铃的时,分与系统时,分相等,并且闹钟标志开启CKS=0XE0; 〃开启蜂鸣器输出,输出频率为0.98khz的音频Time1(); 〃调用时间函数))// ........................................................ 显示缓存区刷新时间函数.............. •//void Freshddisplaybuffer(){buffs[1]=LCD_num[second/10];/期的显示码放入秒的数码显示缓存区buffs[0]=LCD_num[second%10];buffm[1]=LCD_num[minute/10];//分的显示码放入分的数码显示缓存区buffm[0]=LCD_num[minute%10];buffm[0]|=0x0800; 〃分的后面显示一个"."buffh[1]=LCD_num[hour/10]; 〃时的显示码放入时的数码显示缓存区buffh[0]=LCD_num[hour%10];buffh[0]|=0x0800; 〃时的后面显示一个"."buffday[1]=LCD_num[day/10];//天的显示码放入天的数码显示缓存区buffday[0]=LCD_num[day%10];buffmonth[1]=LCD_num[month/10];//月的显示码放入月的数码显示缓存区buffmonth[0]=LCD_num[month%10];buffmonth[0]|=0x0800; 〃月的后面显示一个"."buffyear[3]=LCD_num[year/100/10];/^的显示码放入年的数码显示缓存区buffyear[2]=LCD_num[(year/100)%10];buffyear[1]=LCD_num[(year%100)/10];buffyear[0]=LCD_num[(year%100)%10];buffyear[0]|=0x0800; 〃年的后面显示一个"."buffmd[3]=LCD_num[month/10];//月,天的显示码放入月,天的数码显示缓存区buffmd[2]=LCD_num[month%10];buffmd[2]|=0x0800; 〃月,天后显示一个"."buffmd[1]=LCD_num[day/10];buffmd[0]=LCD_num[day%10];buffhm[3]=LCD_num[hour/10];//时,分的显示码放入时,分的数码显示缓存区buffhm[2]=LCD_num[hour%10];buffhm[2]|=0x0800; 〃时,分的后显示一个"."buffhm[1]=LCD_num[minute/10];buffhm[0]=LCD_num[minute%10];buffms[3]=LCD_num[minute/10];/^,秒的显示码放入分,秒的数码显示缓存区buffms[2]=LCD_num[minute%10];buffms[2]|=0x0800; 〃分,秒的后显示一个"."buffms[1]=LCD_num[second/10];buffms[0]=LCD_num[second%10];buffch[1]=LCD_num[c_hour/10];//闹钟时的显示码放入闹钟时的数码显示缓存区buffch[0]=LCD_num[c_hour%10];buffcm[1]=LCD_num[c_minute/10];//闹钟分的显示码放入闹钟分的数码显示缓存区buffcm[0]=LCD_num[c_minute%10];)// ................................. 主函数............... 〃void main(){DI(); 〃关中断PM3.4 = 0; //P3.3,P3.4端口设置为输出模式P3.4 = 1; //led灯初始化为点亮状态PM3.3 = 0;P3.3 = 0;BZOE = 0; 〃蜂鸣器初始化为熄灭Init_Lcd(); 〃初始化lcdInit_Led(); 〃初始化ledInitKey_INTKR(); 〃初始化按键EI(); 〃开中断Init_Inter(); //初始化中断while(1){ Time1(); noise(); switch(key){ case 0: Freshddisplaybuffer(); Time1(); Show_Time();Show_Time(); break; case 1:Time1();Freshddisplaybuffer(); Display_Date(); noise();break;case 2:Time1();Freshddisplaybuffer(); Display_Time(); noise();break;case 3:d_c_inter();Freshddisplaybuffer(); Set_D_T();noise();key=7; break;case 4:UpNum();Freshddisplaybuffer(); Set_D_T();noise();key=7; break;case 5:DownNum();Freshddisplaybuffer(); Set_D_T();noise();key=7; break;case 6:key = 0;if(i > 5)Que = 1;1 = 0;noise();case 7:Time1();Freshddisplaybuffer(); Set_D_T(); 〃调用计算时间函数 〃调用闹钟函数 〃没有按键执行 〃调用刷新函数 〃计算时间 〃调用显示时间函数 //按键1执行 〃计算时间 〃调用刷新函数 〃调用显示日期函数 〃调用闹钟函数 //按键2执行 //计算时间 //调用刷新函数 //调用时间显示函数 //调用闹钟函数 //按键3执行 〃调用时间切换函数 //调用刷新函数 〃调用时间设置函数 //调用闹钟函数 //按键4执行 〃调用时间加函数 //调用刷新函数 //调用时间设置函数 //调用闹钟函数 //按键5执行〃调用时间减函数 //调用刷新函数 //调用时间设置函数//调用闹钟函数//按键6执行〃判断是否确认 //调用闹钟函数〃虚拟按键7 //调用刷新函数//调用时间设置函数〃调用闹钟函数noise();break;。
单片机闹钟设计程序报告1. 引言闹钟作为人们日常生活中的常用物品,不仅有叫醒人们起床的功能,还可以作为提醒的工具。
随着科技的进步,单片机闹钟逐渐取代了传统的机械闹钟,成为人们生活中不可或缺的一部分。
本报告旨在介绍一个基于单片机的简单闹钟设计程序。
2. 设计方案本设计方案使用了单片机和数码管作为主要硬件,通过对单片机的编程,实现了闹钟的基本功能,包括时间设置、闹钟时间设置、闹钟触发、蜂鸣器报警等。
2.1 硬件设计硬件方面,本设计基于某型号的单片机和数码管。
单片机通过相关的引脚与数码管相连,通过控制引脚的电平来显示不同的数字。
2.2 软件设计软件方面,本设计使用C语言编程实现。
主要的功能包括获取当前时间、显示时间、设置时间、设置闹钟时间、闹钟触发检测、蜂鸣器报警等。
3. 程序实现3.1 初始化设置在程序的开始部分,需要对单片机进行初始化设置。
包括设置引脚的输入输出模式、设置计时器、设置中断等。
3.2 时间显示为了实现时间显示的功能,我们需要通过单片机的计时器来不断获取当前时间,并将其转换为时、分、秒的格式。
然后通过数码管显示出来。
3.3 时间设置通过给单片机的某个引脚接入按钮,实现时间设置功能。
当按钮被按下时,单片机进入时间设置模式。
此时,用户可以通过另外的按钮来逐个调整时、分、秒的数值。
3.4 闹钟时间设置类似于时间设置,闹钟时间设置也需要通过按钮来实现。
用户可以按下对应的按钮来设置闹钟的时、分,设置完毕后,单片机会将设置的时间保存起来。
3.5 闹钟触发检测在每一次时间显示的循环中,程序都会检测当前时间是否与闹钟时间相符。
如果相符,则触发闹钟,蜂鸣器开始报警。
3.6 蜂鸣器报警通过单片机的一个输出引脚,连接到蜂鸣器,实现蜂鸣器的报警功能。
当闹钟触发时,单片机会给对应的引脚输出一个高电平,从而使蜂鸣器发声。
4. 总结通过对单片机闹钟设计程序的实现,我们成功实现了闹钟的基本功能,包括时间设置、闹钟时间设置、闹钟触发、蜂鸣器报警等。
数字钟、万年历制作(基于单片机)电路原理图:程序://********************20131206****数字钟程序#pragma SMALL#include <reg51.h>#include <absacc.h>#include <intrins.h>//********************************************************* *********编译预处理void display(unsigned char *p); //显示函数,P为显示数据首地址unsigned char keytest(); //按键检测函数unsigned char search(); //按键识别函数void alarm(); //闹钟判断启动函数void ftion0(); //始终修改函数void ftion1(); //闹钟修改函数void ftion3(); //日期修改函数void cum(); //加1修改函数void minus(); //减1修改函数void jinzhi(); //进制修改函数void riqi(); //日期void stopwatch(); //秒表函数//********************************************************* *******函数声明sbit P2_7=P2^7;//********************************************************* *******端口定义unsigned char clockbuf[3]={0,0,0};unsigned char bellbuf[3]={0,0,0};unsigned char date[3]={1,1,1}; //日期存放数组unsigned char stop[3]={0,0,0};unsigned char msec1,msec2;unsigned char timdata,rtimdata,dtimdata;unsigned char count;unsigned char *dis_p;unsigned char or; //12进制控制标志unsigned char ri; //日期显示控制标志位unsigned char mb; //秒表控制标志位bit arm,rtim,rhour,rmin,hour,min,sec,day,mon,year; //定义位变量//********************************************************* *****全局变量定义void main(){unsigned char a;or=0; //12进制修改标志清零ri=0;mb=0;P2_7=0;arm=0;msec1=0;msec2=0;timdata=0;rtimdata=0;count=0;TMOD=0x12;TL0=0x06;TH0=0x06;TH1=(65536-10000)/256;TL1=(65536-10000)%256;EA=1;ET0=1;ET1=1;TR0=1;TR1=0;dis_p=clockbuf;while(1){a=keytest();if(a==0x78) //判断是否有键按下{display(dis_p);if(arm==1) alarm();}else{display(dis_p);a=keytest();if(a!=0x78){a=search();switch(a){case 0x00:ftion0();break;case 0x01:ftion1();break;case 0x02:cum();break;case 0x06:jinzhi();break;case 0x03:riqi();break;case 0x04:ftion3();break;case 0x05:minus();break;case 0x07:stopwatch();break;case 0x09:TR1=1;break;case 0x0a:TR1=0;break;case 0x0b:stop[0]=0;stop[1]=0;stop[2]=0;break;default:break;}}}}}//********************************************主函数【完】void display(unsigned char *p){unsigned char buffer[]={0,0,0,0,0,0};unsigned char k,i,j,m,temp;unsigned char led[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};buffer[0]=p[0]/10;buffer[1]=p[0]%10;buffer[2]=p[1]/10;buffer[3]=p[1]%10;buffer[4]=p[2]/10;buffer[5]=p[2]%10;if((sec==0)&&(min==0)&&(hour==0)&&(rmin==0)&&(rhour==0)&&( day==0)&&(mon==0)&&(year==0)) //没有修改标志,正常显示{for(k=0;k<3;k++){temp=0x01;for(i=0;i<6;i++){P0=0x00; //段选端口j=buffer[i];P0=led[j];P1=~temp; //位选端口temp<<=1;for(m=0;m<200;m++);}}}else //若有修改标志,则按以下标志分别显示{if(sec==1||day==1){P1=0x1f;i=buffer[5];P0=led[i];for(m=0;m<200;m++);P1=0x2f;j=buffer[4];P0=led[j];for(m=0;m<200;m++);}if(min==1||rmin==1||mon==1){P1=0x3b;i=buffer[2];P0=led[i];for(m=0;m<200;m++);P1=0x37;j=buffer[3];P0=led[j];for(m=0;m<200;m++);}if(hour==1||rhour==1||year==1) {P1=0x3e;i=buffer[0];P0=led[i];for(m=0;m<200;m++);P1=0x3d;j=buffer[1];P0=led[j];for(m=0;m<200;m++);}}}//**********************************LED显示函数【完】unsigned char keytest(){unsigned char c;P2=0x78; //检测是否有键按下c=P2;c=c&0x78;return(c);}//******************************************键盘检测函数【完】unsigned char search(){unsigned char a,b,c,d,e;c=0x3f;a=0; //行号while(1){P2=c;d=P2;d=d&0x07;if(d==0x03){b=0;break;} //列号else if(d==0x05){b=1;break;}else if(d==0x06){b=2;break;}a++;c>>=1;if(a==5){a=0;c=0x3f;}}e=a*3+b;do{display(dis_p);}while((d=keytest())!=0x78);return(e);}//***********************************************查键值函数【完】void alarm(){if((clockbuf[0]==bellbuf[0])&&(clockbuf[1]==bellbuf[1])){P2_7=1;rtim=1;if(count==10){count=0;P2_7=0;arm=0;rtim=0;}}}//****************************************闹钟判断启动函数【完】void ftion0(){TR0=0;rhour=0;rmin=0;dis_p=clockbuf;rtimdata=0;timdata++;switch(timdata){case 0x01:sec=1;break;case 0x02:sec=0;min=1;break;case 0x03:min=0;hour=1;break;case 0x04:timdata=0;hour=0;TR0=1;break;default:break;}}//*********************************************时钟设置函数【完】void ftion1(){if(TR0==0) TR0=1;sec=0;min=0;hour=0;dis_p=bellbuf;timdata=0;rtimdata++;switch(rtimdata){case 0x01:rmin=1;break;case 0x02:rmin=0;rhour=1;break;case 0x03:rtimdata=0;rhour=0;arm=1;dis_p=clockbuf;break;default:break;}}//*********************************************闹钟设置函数【完】void ftion3(){if(TR0==0) TR0=1;day=0;mon=0;year=0;dis_p=date;timdata=0;rtimdata=0;dtimdata++;switch(dtimdata){case 0x01:day=1;break;case 0x02:day=0;mon=1;break;case 0x03:mon=0;year=1;break;case 0x04:dtimdata=0;year=0;dis_p=clockbuf;break;default:break;}}//*************************************************日期修改函数【完】void minus(){if(sec==1){if(0==clockbuf[2]) clockbuf[2]=59;else clockbuf[2]--;}else if(min==1){if(0==clockbuf[1]) clockbuf[1]=59;else clockbuf[1]--;}else if(hour==1){if(or==0) //判断进制{if(0==clockbuf[0]) clockbuf[0]=23;else clockbuf[0]--;}if(or==1){if(1==clockbuf[0]) clockbuf[0]=12;else clockbuf[0]--;}}else if(rmin==1){if(bellbuf[1]==0) bellbuf[1]=59;else bellbuf[1]--;}else if(rhour==1){if(or==0){if(bellbuf[0]==0) bellbuf[0]=23;else bellbuf[0]--;}if(or==1){if(bellbuf[0]==1) bellbuf[0]=12;else bellbuf[0]--;}}else if(day==1){if(date[2]==1) date[2]=31;else date[2]--;}else if(mon==1){if(date[1]==1) date[1]=12;else date[1]--;}else if(year==1){if(date[0]==1) date[0]=99;else date[0]--;}}//*************************************减1修改功能函数【完】void cum(){if(sec==1){if(59==clockbuf[2]) clockbuf[2]=0;else clockbuf[2]++;}else if(min==1){if(59==clockbuf[1]) clockbuf[1]=0;else clockbuf[1]++;}else if(hour==1){if(or==0) //判断进制{if(23==clockbuf[0]) clockbuf[0]=0;else clockbuf[0]++;}if(or==1){if(12==clockbuf[0]) clockbuf[0]=1;else clockbuf[0]++;}}else if(rmin==1){if(bellbuf[1]==59) bellbuf[1]=0;else bellbuf[1]++;}else if(rhour==1){if(or==0){if(bellbuf[0]==23) bellbuf[0]=0;else bellbuf[0]++;}if(or==1){if(bellbuf[0]==12) bellbuf[0]=1;else bellbuf[0]++;}}else if(day==1){if(date[2]==31) date[2]=1;else date[2]++;}else if(mon==1){if(date[1]==12) date[1]=1;else date[1]++;}else if(year==1){if(date[0]==99) date[0]=0;else date[0]++;}}//*************************************加1修改功能函数【完】void jinzhi(){if(or==0) or=1;else or=0;}//***********************************进制修改控制函数【完】void riqi(){if(ri==0){dis_p=date;}if(ri==1){dis_p=clockbuf;}ri++;if(ri==2) ri=0;}//********************************日期控显示函数【完】void stopwatch(){if(mb==0){dis_p=stop;mb=1;}else{mb=0;dis_p=clockbuf;}}//************秒表**********秒表**********秒表函数【完】void clock() interrupt 1{EA=0;if(msec1!=0x14) msec1++; //6MHz晶振定时10mselse{msec1=0;if(msec2!=100) msec2++; //定时1selse{if(rtim==1) count++; //闹钟启动标志计时10smsec2=0;if(clockbuf[2]!=59) clockbuf[2]++;else{clockbuf[2]=0;if(clockbuf[1]!=59) clockbuf[1]++;else{clockbuf[1]=0;if(or==0){if(clockbuf[0]!=23) clockbuf[0]++;else{clockbuf[0]=0;if((date[1]==1)||(date[1]==1)||(date[1]==1)||(date[1]==3)||(date[ 1]==5)||(date[1]==7)||(date[1]==8)||(date[1]==10)||(date[1]==12)){if(date[2]!=30) date[2]++;else{date[2]=1;if(date[1]!=11) date[1]++;else{date[1]=1;date[0]++;}}}if((date[1]==4)||(date[1]==6)||(date[1]==9)||(date[1]==11)){if(date[2]!=29) date[2]++;else{date[2]=1;if(date[1]!=11) date[1]++;else{date[1]=1;date[0]++;}}}if(date[1]==2){if((((date[0]%4==0)&&(date[0]%100!=0))||(date[0]%400==0))){if(date[2]!=28) date[2]++;else{date[2]=1;if(date[1]!=11) date[1]++;else{date[1]=1;date[0]++;}}}else{if(date[2]!=27) date[2]++;else{date[2]=1;if(date[1]!=11) date[1]++;else{date[1]=1;date[0]++;}}}}}}if(or==1){if(clockbuf[0]!=12) clockbuf[0]++;else{clockbuf[0]=0;if((date[1]==1)||(date[1]==1)||(date[1]==1)||(date[1]==3)||(date[ 1]==5)||(date[1]==7)||(date[1]==8)||(date[1]==10)||(date[1]==12)){if(date[2]!=30) date[2]++;else{date[2]=1;if(date[1]!=11) date[1]++;else{date[1]=1;date[0]++;}}}if((date[1]==4)||(date[1]==6)||(date[1]==9)||(date[1]==11)){if(date[2]!=29) date[2]++;else{date[2]=1;if(date[1]!=11) date[1]++;else{date[1]=1;date[0]++;}}}if(date[1]==2){if((((date[0]%4==0)&&(date[0]%100!=0))||(date[0]%400==0))){if(date[2]!=28) date[2]++;else{date[2]=1;if(date[1]!=11) date[1]++;else{date[1]=1;date[0]++;}}}else{if(date[2]!=27) date[2]++;else{date[2]=1;if(date[1]!=11) date[1]++;else{date[1]=1;date[0]++;}}}}}}}}}}EA=1;}//*******************************定时器0中断函数【完】void miaobiao() interrupt 3{TH1=(65536-10000)/256;TL1=(65536-10000)%256;if(stop[2]!=99) stop[2]++;else{stop[2]=0;if(stop[1]!=59) stop[1]++;else{stop[1]=0;if(stop[0]!=59) stop[0]++;else stop[0]=0;}}}//***********************************定时器1中断函数【完】。
目录第一章引言 (3)选题背景及其意义 (3)877A单片机的介绍 (3)设计要求及其功能 (4)本设计实现的功能 (4)第二章系统整体方案 (5)系统整体方案框图 (5)设计要求 (5)按照设计要求画出系统框图 (5)控制系统时刻分析表 (6)处置器的选择 (6)时钟芯片的选择 (7)液晶显示器的选择 (7)第三章硬件部份的设计 (7)系统部份 (7)键盘接口电路 (8)显示部份 (9)第四章控制系统软件部份 (10)软件介绍 (10)程序流程图 (11)按键的扫描子程序 (12)铃声控制程序 (12)仿真电路 (13)第五章总结 (15)参考文献 (16)致谢 (16)基于单片机的可编程作息时刻控制器的设计何欢(伊犁师范学院电子与信息工程学院电子信息科学与技术09-2班,新疆伊宁市 835000)摘要:本设计是作息时刻控制器,由单片机最小系统、按键模块、数码管显示模块、铃声模块组成。
采用PIC16F877A单片机、主频4MHZ晶振,通过按键STATE、TEN、UNIT控制时刻的校正时刻和铃声设定;数码管显示模块用来显示时刻,显示格式为“时分”,并能够按照需要显示年、月、日,由数码管小数点闪动作为秒计数;铃声模块进行到时提示并出相应动作:发光二极管闪亮,同时播放音乐。
时钟芯片采用的是DS1302,此芯片是DALLAS 公司推出的涓流充电时钟芯片,其内含有一个实不时钟/日历和31 字节静态RAM,并通过简单的串行接口与单片机进行通信。
实不时钟/日历电路提供秒、分、时、日、日期、月、年的信息,每一个月的天数和闰年的天数可自动调整,时钟操作可通过AM/PM 指示决定采用24 或12 小时格式。
DS1302 工作时功耗很低,维持数据和时钟信息时功率小于1mW。
该设计采用C语言编写程序,由于汇编语言的移植性比较差,而C语言则比较灵活,许多子函数都能够直接移植过去。
关键词:PIC16F877A单片机;晶振;液晶显示器;源程序Based on single chip microcomputer controller design ofprogrammable calendarHehuan(ili normal college of electronic and information engineering college of electronic information science and technology 09-2 class, xinjiang yining city, 835000 )Abstract:This is the time schedule controller designed by single chip microcomputer minimum system module, buttons, digital tube display module, alarm module. Using PIC16F877A MCU, 4 MHZ crystal vibration main frequency, through the button STATE, TEN, UNIT control time correction time and set ring; Digital tube display module is used to display time, display format of"time", and can according to need to display year, month, day, by the digital tube decimal counting flashing as seconds; Bell module to remind and make the corresponding action: light-emitting diodes, play music at the same time.Used clock chip DS1302, this chip is DALLAS company to launch a trickle charging the clock chip, containing a real-time clock/calendar and 31 bytes static RAM, and communicate with single chip microcomputer with simple serial interface. Real-time clock/calendar circuit provides seconds, minutes, and information day, date, month, year, number of days per month and leap year the number of days can be automatically adjusted, clock operation by an AM/PM indicator decided to adopt 12 or 24 hour format. DS1302 power consumption is low, while working to keep data and clock information when the power is less than 1 mw.This design USES the C language program, due to the portability of assembly language, but C is more flexible, Many functions can be directly transplanted in the past.Keywords: PIC16F877A MCU;crystals and liquid crystal display; the source program第一章引言选题背景和意义自从人类学会计时开始,计时方式由在木棍和骨头上刻标记,随着人类的智慧的进展,到后面利用计时工具不断的改良,由最开始的圭表、日晷、漏壶、漏箭、机械闹钟、秒表、沙漏、怀表、自摆钟、石英钟等。
基于单片机的数字钟毕业设计(附程序全) 电子时钟设计随着现代人类生活节奏的加快,人们越来越重视起了时间观念,可以说是时间和金钱划上了等号。
对于那些对时间把握非常严格和准确的人或事来说,时间的不准确会带来非常大的麻烦,所以以数码管为显示器的时钟比指针式的时钟表现出了很大的优势。
数码管显示的时间简单明了而且读数快、时间准确性更高~数字钟是采用数字电路实现对“时”、“分”、“秒”数字显示的计时装置。
数字钟的精度、稳定度远远超过老式机械钟。
在这次设计中,我们采用LED数码管显示时、分、秒,以24小时计时方式,根据数码管动态显示原理来进行显示,用12MHz的晶振产生振荡脉冲,并且由单片机的定时器计数。
在此次设计中,电路具有显示时间的其本功能,还可以实现对时间的调整。
数字钟是其小巧,价格低廉,走时精度高,使用方便,功能多,便于集成化而受广大消费的喜爱,因此得到了广泛的使用。
关键词:数字钟;单片机;数码管;时间;准确性1目录第一章绪论1. 数字电子钟的意义和应用…………………………………………………………………… 3 第二章整体设计方案2.1 单片机的选择…………………………………………………………………………… 3 2.2 单片机的基本结构……………………………………………………………………… 5 第三章数字钟的硬件设计3.1 最小系统设计…………………………………………………………………………… 9 3.2 LED显示电路…………………………………………………………………………… 12 3.3 键盘控制电路…………………………………………………………………………… 14 第四章数字钟的软件设计4.1 系统软件设计流程图…………………………………………………………………… 15 4.2 数字电子钟的原理图…………………………………………………………………… 18 4.3 主程序…………………………………………………………………………………… 19 4.4 时钟设置子程序………………………………………………………………………… 20 4.5 定时器中断子程序……………………………………………………………………… 20 4.6 LED显示子程序………………………………………………………………………… 21 4.7 按键控制子程序………………………………………………………………………… 23 第五章系统仿真5.1 PROTUES软件介绍................................................................................. 24 5.2 电子钟系统PROTUES仿真........................................................................ 24 结束语. (2)5 参考文献 (26)2第一章绪论1.数字电子钟的意义和应用数字钟是采用数字电路实现对时、分、秒数字显示的计时装置,广泛用于个人家庭、车站、码头、办公室等公共场所,成为人们日常生活中不可少的必需品,由于数字集成电路的发展和石英晶体振荡器的广泛应用,使得数字钟的精度,远远超过老式钟表, 钟表的数字化给人们生产生活带来了极大的方便,而且大大地扩展了钟表原先的报时功能。
数字时钟实验报告一、实验目的:通过实验进一步深刻理解单片机最小系统的工作原理。
着重掌握中断和定时器的使用,以及读键盘和LED显示程序的设计(具体设计在后面会涉及到)。
培养动手能力。
二、实验内容:使用单片机最小系统设计一个12小时制自动报时的数字时钟。
三、功能描述:★使用低六位数码管显示时、分、秒、使用第七位表示上午和下午。
符号A表示上午;符号P表示下午。
★通过按键分别调整小时位和分钟位。
★到达整点时以第八位数码管闪烁的方式报时,使用8作为显示内容。
★考虑整点报时功能。
四、设计整体思路以及个别重点部分的具体实现方式:下面这幅图展示主函数的流程下面描述的是调用T0中断时所进行的动作显示更新的函数具体见下面这幅图我们还一个对键盘进行扫描以获得有效键盘值,其具体的实现见下面这幅图● 要实现时钟的运行和时间的调整,我的设计思路是这样的:由于T0中断的时间间隔是4ms,那么我可以设置一个计数器i,在每次进入中断时进行加一调整,当i计满面250时就将时钟我秒的低位加一。
然后根据进位规则,对其后的各位依次进行调整。
●要实现整点报时功能,则可以根据时位是否为0判断是否要闪烁显示字符8。
至于闪烁的具体实现方式,见源程序。
至此,本实验的设计思路己基本介绍完毕。
下面就是本次实验的源程序代码。
/*********************************************************//** 数字时钟程序**//** **//*********************************************************/#include <absacc.h>#include <reg51.h>#define uchar unsigned char#define uint8 unsigned char#define uint16 unsigned int#define LED1 XBYTE [0xA000] //数码管地址#define LED2 XBYTE [0xA001]#define LED3 XBYTE [0xA002]#define LED4 XBYTE [0xA003]#define LED5 XBYTE [0xA004]#define LED6 XBYTE [0xA005]#define LED7 XBYTE [0xA006]#define LED8 XBYTE [0xA007]#define KEY XBYTE [0xA100] //键盘地址bit ap=0;//上下午int i=0;//计数器uchar data clock[7]={0,0,0,0,0,0,0};/*扫描键盘使用的变量 */sbit first_row = P1^4; //键盘第一行控制sbit second_row = P1^3; //键盘第二行控制bit first_getkey = 0,control_readkey = 0; //读键盘过程中的标志位bit getkey = 0; //获得有效键值标志位等于1时代表得到一个有效键值bit keyon = 0; //防止按键冲突标志位uchar keynum = 0; //获得的有效按键值寄存器/*数码管显示使用的变量和常量*/uchar lednum = 0; //数码管显示位控制寄存器uchar led[8] = {0,0,0,0,0,0,0,0}; //数码管显示内容寄存器uchar code segtab[18] = {0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e,0x8c,0xff}; //七段码段码表// "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D","E", "F", "P" ,"black"void leddisp(void); //数码管显示函数void readkey(void); //读键盘函数void intT0() interrupt 1 //T0 定时中断处理函数{TH0 = -2720/256; //定时器中断时间间隔 4msTL0 = -2720%256;if((clock[2]==0)&&(clock[3]==0)&&(i==125)&&(clock[5]<=5)&&(clock[4]==0))led[7]=17;if((clock[2]==0)&&(clock[3]==0)&&(i==0)&&(clock[5]<=5)&&(clock[4]==0))led[7]=8;i=i+1;if(i==250){if((clock[2]==0)&&(clock[3]==0)&&(clock[4]==0)&&(clock[5]==0)&&(clock[6]==0)){ap=!ap;if(ap==0)led[6]=10;if(ap==1)led[6]=16;}clock[5]=clock[5]+1;i=0;}if(clock[5]==10){clock[5]=0;clock[4]=clock[4]+1;}if(clock[4]==6){clock[4]=0;clock[3]=clock[3]+1;}if(clock[3]==10){clock[3]=0;clock[2]=clock[2]+1;}if(clock[2]==6){clock[2]=0;clock[6]=clock[6]+1;}if(clock[6]==12){clock[6]=0;}clock[0]=clock[6]/10;clock[1]=clock[6]%10;led[5]=clock[0];led[4]=clock[1];led[3]=clock[2];led[2]=clock[3];led[1]=clock[4];led[0]=clock[5];leddisp(); //每次定时中断显示更新一次if(control_readkey == 1) //每两次定时中断扫描一次键盘{readkey();}c ontrol_readkey = !control_readkey;}void main(void){TMOD = 0x01; //TH0 = -2720/256; //定时器中断时间间隔 4msTL0 = -2720%256;TCON = 0x10;ET0 = 1;EA = 1;while(1){if(getkey == 1) //判断是否获得有效按键{getkey = 0;switch(keynum) //判断键值,对不同键值采取相应的用户定义处理方式{case 0x01: //当按下第一行第二列键时,分加一clock[3]=clock[3]+1;break;case 0x02: ////当按下第一行的第三列键时,分减一clock[3]=clock[3]-1;break;case 0x03://当按下第一行的第四列时,时加一clock[6]=clock[6]+1;break;case 0x04:clock[6]=clock[6]-1; //当按下第一行的第五列时,时减一break;default:break;}}}}/***************************************************键盘扫描函数原型: void readkey(void);功能: 当获得有效按键时,令getkey=1,keynum为按键值****************************************************/void readkey(void){uchar M_key = 0;second_row = 0;M_key = KEY;if(M_key != 0xff) //如果有连续两次按键按下,认为有有效按键按下。
单片机时钟介绍与实例讲解在单片机系统中,时钟信号是控制系统中各个模块协调工作的基础。
单片机时钟可以提供一个固定的时钟频率,用于同步和控制各个模块的操作。
通过时钟信号的控制,可以确保单片机系统中各个模块按照一定的时间序列进行操作,从而实现各种功能。
单片机时钟通常由一组晶体振荡器和相应的电路组成。
晶体振荡器是一种根据晶体的振动来产生稳定的时钟信号的设备。
晶体振荡器通常由一个晶体和一个振荡电路组成,晶体通过振荡电路的作用来产生稳定的时钟信号。
时钟信号的频率与晶体振荡器的结构和工作原理有关,可以通过调整电路参数或更换晶体来改变时钟信号的频率。
在单片机系统中,时钟信号的频率通常以赫兹(Hz)为单位表示。
例如,一个4MHz的晶体振荡器,它会产生一个4MHz的时钟信号。
时钟信号的频率越高,单片机系统的工作速度也越快。
因此,选择合适的时钟频率对于单片机系统的性能和功能至关重要。
单片机时钟可以用于各种计时和定时任务。
例如,可以使用时钟信号来计算程序的执行时间,测量一些事件的持续时间,实现定时器和计数器等功能。
时钟信号可以通过单片机的GPIO引脚输出,以供其他模块或外部设备使用。
下面以一个简单的单片机时钟实例进行讲解。
假设我们使用一个8位的单片机,并使用一个4MHz的晶体振荡器作为时钟信号源。
我们需要设计一个定时器,每隔1秒产生一个脉冲。
首先,我们需要设置单片机的时钟频率。
由于晶体振荡器的频率是4MHz,我们可以将单片机的时钟分频为1MHz。
这样,我们可以使用一个8位的计数器,每经过1,000,000个时钟脉冲,计数器的值加1,相当于经过1秒钟。
然后,我们需要编写相应的程序来实现定时器的功能。
程序的基本思路是不断地检测计数器的值是否达到1,000,000,如果达到,则产生一个脉冲,并将计数器的值清零,重新开始计数。
下面是一个使用C语言编写的实例程序:```c#include <reg51.h>sbit pulse = P1^0; // 定义脉冲输出引脚void delalong i;void maiunsigned int count = 0;while (1)count++;pulse = 1; // 产生脉冲delay(;pulse = 0;count = 0; // 清零计数器}}```在这个程序中,我们首先定义了一个脉冲输出引脚 `pulse`,然后编写了一个延时函数 `delay`,用于生成1秒钟的延时。
单片机的实时时钟设计》引言:实时时钟是嵌入式系统中常用的功能之一,可以实现对时间的准确计时和显示功能。
本文将以数码管显示为例,介绍单片机实时时钟的设计过程。
一、硬件设计1.单片机选择实时时钟通常需要较强的计算能力和丰富的IO口,方便与其他外设进行通信。
常用的单片机有STC89C52、AT89C51等。
本设计选择STC89C52单片机。
2.数码管显示选择常用的共阴极数码管进行显示。
数码管可以通过74HC595芯片进行驱动,将单片机的IO口扩展为8位,方便控制多个数码管的显示。
3.时钟芯片本设计选择DS1302时钟芯片作为实时时钟的核心。
DS1302芯片具有低功耗、精度高、抗干扰能力强等特点。
二、软件设计1.引入头文件#include <reg52.h> // 引入单片机头文件#include "DS1302.h" // 引入DS1302头文件,包含了DS1302芯片的驱动函数2.数码管显示函数void display(unsigned char *t)unsigned char i;unsigned char code table[] = { // 0-9的显示码0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};for(i = 0; i < 6; i++) // 依次显示年、月、日、时、分、秒P0=0xFF;//所有数码管熄灭P2=0x01<<i;//选择一些数码管P0 = table[t[i]]; // 数码管显示对应的数字Delay(1); // 延时一段时间}3.主函数void mainwhile(1)Delay(100); // 延时一段时间,例如100ms}4.初始化函数void InitDS1302_Init(; // DS1302芯片初始化5.主函数调用void mainInit(; // 调用初始化函数while(1)Display(; // 显示函数Count(; // 计数函数}结论:通过以上的硬件设计和软件编写,我们可以实现单片机的实时时钟功能,并通过数码管进行显示。
摘要本设计是定时闹钟的设计,由单片机AT89C51芯片和LED数码管为核心,辅以必要的电路,构成的一个单片机电子定时闹钟。
电子钟设计可采用数字电路实现,也可以采用单片机来完成。
数字电子钟是用数字集成电路构成的,用数码管显示“时”,“分”,“秒”的现代计时装置。
若用数字电路完成,所设计的电路相当复杂,大概需要十几片数字集成块,其功能也主要依赖于数字电路的各功能模块的组合来实现,焊接的过程比较复杂,成本也非常高。
若用单片机来设计制作完成,由于其功能的实现主要通过软件编程来完成,那么就降低了硬件电路的复杂性,而且其成本也有所降低,所以在该设计中采用单片机利用AT89C51,它是低功耗、高性能的CMOS型8位单片机。
片内带有4KB的Flash存储器,且允许在系统内改写或用编程器编程。
另外, AT89C51的指令系统和引脚与8051完全兼容,片内有128B 的RAM、32条I/O口线、2个16位定时计数器、5个中断源、一个全双工串行口等。
AT89C51单片机结合七段显示器设计的简易定时闹铃时钟,可以设置现在的时间及显示闹铃设置时间,若时间到则发出一阵声响,进—步可以扩充控制电器的启停。
设计内容包括了秒信号发生器、时间显示电路、按键电路、供电电源以及闹铃指示电路等几部分的设计。
采用四个开关来控制定时闹钟的工作状态,分别为:K1、设置时间和闹钟的小时;K2、设置小时以及设置闹钟的开关;K3、设置分钟和闹钟的分钟;K4、设置完成退出。
课设准备中我根据具体的要求,查找资料,然后按要求根据已学过的时钟程序编写定时闹钟的程序,依据程序利用proteus软件进行了仿真试验,对出现的问题进行分析和反复修改源程序,最终得到正确并符合要求的结果。
设计完成的定时闹钟达到课程设计的要求,在到达定时的时间便立即发出蜂鸣声音,持续一分钟。
显示采用的六位数码管电路,如果亮度感觉不够,可以通过提升电阻来调节,控制程序中延迟时间的长短,可以获得不同的效果。
基于单片机的智能时钟设计与实现摘要电子时钟是采用数字电路实现对时,分,秒计时的装置,广泛的应用在各种工作场所。
随着科学技术的发展,多功能的电子时钟更是适应现代化个性生活的一个新需求。
本文介绍了基于单片机的智能时钟系统的设计与实现,时钟系统是以STC89C52为核心,运用数字时钟芯片DS1302,液晶显示器LCD1602,语音芯片ISD4004和按键来实现实时显示,整点报时等功能。
系统分为实时时钟,LCD显示,整点报时,按键调整四个模块。
设计的系统的可以通过按键来调节时间,通过LCD模块能够将实时时间显示出来,并且在整点的时候可以实现语音整点报时功能。
可以使人更加直观的了解到电子时钟的工作原理。
该数字时钟能长期、连续、可靠、稳定的工作;同时还具有体积小、功耗低等特点,便于携带,使用方便。
本报告对系统的工作原理,硬件电路和软件进行了详细的介绍。
[关键词]单片机数字时钟液晶显示语音报时ABSTRACTElectronic clock is a device which is used to count time, minute and second, which is widely used in the public place. With the development of science, multi-function electronic clock is a new demand to adapt to the modern personality of life. This article introducedthe multi-purpose digital clock system design. The system take STC89C52 as a core, make use of DS1302 clock chip ,use the 1602 liquid-crystal display, apply the voice chip ,coordinates the pressed keyto realize the real-time display. The system is divided into real-time clock, liquid-crystal display ,on time clock and pressed key four modules. The system is designed to change the time with pressed key, meanwhile, the liquid-crystal display the on time clock and can voice the hour on the hour .This article can enable people to directly see the operating state of digital clock. This digital clock provide the friendly user contact surface, the operation simple,this digital clock can long-term, be continual, reliably, the stablework; Simultaneously also has the volume slightly, the power loss islow and so on the characteristic, is advantageous forcarries, easy to operate.The report on the principle of the system , the hardware circuit and the software are introduced detail.[Key words]Single-chip Microcomputer Digital ComputerLCD DisplayAudio Chimer前言20世纪末,电子技术获得了飞速发展,在其推动下,现代电子产品几乎渗透了社会的各个领域,有力地推动了社会生产力的发展和社会信息化程度的提高,同时也使现代电子产品性能进一步提高,产品更新换代的节奏也越来越快。
基于μPD78F0485单片机实验板的实时时钟程序设计与实现专业:计算机科学与技术班级: 11级学号:姓名:基于μPD78F0485单片机实验板的实时时钟程序设计与实现1实验环境硬件:PC、µPD78F0485单片机。
软件:Windows7操作系统、开发环境支持软件NEC Electronics Microcomputer、Microsoft Visio绘图2功能描述a)液晶屏可切换显示日期和时间。
b)具有日期和时间校对功能。
c)用LED1~LED12模拟秒针走动。
d)有闹钟功能。
3总体设计3.1显示设计a)在LCD上显示年月日,分别用两位数表示年月日。
年的值从00~99;月的值从01~12;日的值如果是2月,闰年为01~29,平年为01~28,其他月份大月为01~31,小月为01~30。
13.12.10年月日图 3.1.1年月日的显示b)在LCD上显示星期时分,分别用两位数表示星期时分。
星期的值从00~06,其中00表示星期天,其它的则一一对应;时采用24小时制,其值从00~23;分的值从00~59。
01.12.00星期时分图 3.1.2星期时分的显示c)在LCD上显示时分秒。
时采用24小时制,其值从00~23;分的值从00~59;秒的值从00~59。
12.00.00时分秒图 3.1.3时分秒的显示3.2时间显示切换设计设置一个全局变量i,初值为0。
每按一下KEY1,i的值加一。
当i = 0,1,2,3时,LCD 显示年月日。
当i = 4,5,6时,LCD显示星期时分。
当i = 7时,LCD显示时分秒。
当i >7 时,i自动变为0。
3.3日期和时间校对设计通过前面设置的全局变量i和KEY3来实现。
当i = 1时,每按一下KEY3,年的值就加一,直到大于99时自动变为00。
当i = 2时,每按一下KEY3,月的值就加一,直到大于12时自动变为01。
当i = 3时,每按一下KEY3,日的值就加一,直到大于当月天数时自动变为01。
当i = 4时,每按一下KEY3,星期的值就加一,直到大于06 时自动变为00。
当i = 5时,每按一下KEY3,时的值就加一,直到大于23时自动变为00。
当i = 6时,每按一下KEY3,分的值就加一,直到大于59时自动变为00。
3.4闹钟显示设计当按下KEY2时,LCD显示闹钟设定的时间。
00.00时分图 3.4闹钟的显示3.5闹钟调整设计当按下KEY5时,闹钟的时就加一,到23时就归零。
当按下KEY6时,闹钟的分就加一,到59时就归零。
3.6闹钟开关设计通过KEY4控制闹钟的开关,并用LED灯的亮灭来显示。
将LED灯端口的输出信号作为闹钟是否响铃的一个判断条件。
按下KEY4,LED灯的输出信号取反,输出信号为1时灯亮并且闹钟打开,为0时灯灭并且闹钟关闭。
3.7闹钟响铃设计当闹钟设定的时分与时钟的时分相等并且闹钟处于打开状态时,蜂鸣器就会发出响声。
3.8用LED1~LED12模拟秒针走动设计将端口13、14、15设置为输出模式,设置1个全局变量s,初值为-1。
当1秒中断来到时s 的值加一模12。
根据s 的值亮相应的灯,并且灭上一个灯。
实现一秒亮一个灯。
4功能模块设计4.1主模块开始KEY = 0?初始化KEY = 1?KEY = 2?KEY = 3?闹钟函数Y调时函数闹钟显示切换时间显示函数闹钟开关显示时间KEY = 0NY N KEY = 7Y NY KEY = 4?NKEY = 0YKEY = 5?NKEY = 6?闹钟函数闹钟调时闹钟显示KEY = 7Y闹钟调分NY 闹钟显示N 图 4.1 主模块流程图当按键按下时,会改变KEY 的值。
当KEY1按下时,KEY 的值就等于1,以此类推。
主模块是一个无限循环,当KEY 改变时,它就会转到相应的分支,执行相应的的功能。
从而响应用户的操作。
如KEY2被按下,则主模块就会转到分支2,然后调用闹钟显示 函数,显示闹钟的当前设置值。
选定cpu的时钟为5.0Hz。
将所有接LCD的引脚指定为LCD引脚,确定LCD的显示频率,打开LCD显示。
将P4的六个端口设置为输出模式,接通上拉电阻,并且允许六个按键中断。
将P13、14、15的所有端口设置为输出模式。
将P3.3和P3.4端口设置为输出。
选择8MHz内部高速时钟作为主系统时钟,实时计数器时钟=fprs/28= 32.768KHz。
将周期性定时中断打开,设置为24小时制,1秒定时中断。
将年的初值设置为13,月初值为01,日初值为01,星期初值为00,时初值为12,分初值为00。
4.3实时时钟模块利用实时计数器来实现实时时钟模块。
实时计数器的秒计数寄存器、分计数寄存器、时计数寄存器、日计数寄存器、周计数寄存器、月计数寄存器、年计数寄存器在开启计数模式后会自动计数。
然后只要在一秒中断到来时,将寄存器中的值读入对应变量中,送到显示刷新模块刷新后显示就能实现实时时钟了。
4.4 闹钟设置模块开始hour1<23?hour1= hour1+1NY hour1=0结束开始minute1<59?minute1=minute1+1NYmInute1=0结束图 4.4 闹钟设置模块流程图利用变量hour1和minute1来实现闹钟功能。
当KEY5或KEY6被按下就会分别调用闹钟的调时、调分模块来设置闹钟的时间。
Hour1的值大于23时归零,minute1的值大于59时归零。
4.5 INTRTC中断处理模块在一秒中断到来时,将实时计数器的秒计数寄存器、分计数寄存器、时计数寄存器、日计数寄存器、周计数寄存器、月计数寄存器、年计数寄存器中的值从BCD码转换为十进制送入到相对应的变量中,等待显示刷新模块调用。
4.6 显示刷新模块主模块在循环中会不停的调用此模块,将实时时钟的最新值转换为LCD的显示码,并送入到显示的缓存中,等待显示模块调用。
开始i = 0?关闭计数模式i = 1?i = 2?i = 3?YMONTH=MONTH+1YEAR = YEAR+1YEAR = 0NY计算天数Y NYi = 4?Y i = 5?Ni = 6?WEEK=WEEK+1YNDAY=1NYEAR < 99?Y NMONTH< 12?NY MONTH = 1NDAY<天数?DAY = DAY+1NYWEEK< 6?WEEK=0Y HOUR<23?YHOUR=HOUR+1N HOUR=0N Y MIN< 59?YMIN=MIN+1MIN=0N开启计数模式结束图 4.7 时钟调时模块流程图此模块根据全局变量i 的值,当KEY3被按下时,分别对实时时钟的年、月、日、星期、时、分、秒进行调整,达到调时目的。
当各个寄存器的值达到所对应的最大值时, 根据各自的性质归零或归一。
根据被按下的键,将KEY 设置成对应的值。
KEY1对应的值为1,以此类推。
4.9 闹钟响铃模块开始hOur1=HOUR ?Y结束Nminute1=MIN ?NYP3.4=1?NY打开蜂鸣器图 4.9 闹钟响铃模块流程图当闹钟设置的时、分与实时时钟的时分相等并且P3.4端口的输出值为1即LED 灯亮时,打开蜂鸣器的输出。
蜂鸣器就会发出声音提醒闹钟时间到了。
4.10 显示模块开始显示地址赋初值dp <6?b[dp]=对应缓冲区[dp]dp++NYdp = 0显示结束图 4.10 显示模块流程图此模块根据全局变量i 的值,将对应的显示缓存区中的内容依次显示。
当一秒中断来到时,根据变量s的值,LED亮起对应的灯,并关闭上一个灯,s 的值加一模十二。
5 操作说明按下KEY1键,改变LCD的显示内容。
按四下KEY1键显示从年月日变为星期时分再按三下KEY1键显示又变为时分秒。
按下KEY3键,进行调时。
当按了一下KEY1键再按KEY3键时,对年进行调整;当按了两下KEY1键再按KEY3键时,对月进行调整;当按了三下KEY1键再按KEY3 键时,对日进行调整;当按了四下KEY1键再按KEY3键时,对星期进行调整;当按了五下KEY1键再按KEY3键时,对时进行调整;当按了六下KEY1键再按KEY3键时,对分进行调整。
按下KEY2键,显示闹钟的设定时间。
再按下KEY5键,对闹钟的设定时间进行时调整;再按下KEY6键,对闹钟的设定时间进行分调整。
按下KEY4键,将P3.4 LED灯打开,并开启闹钟功能。
再按一下关闭P3.4 LED灯,并关闭闹钟功能。
LED1~LED12每一秒依次亮一个灯。
6 总结经过几周的单片机课程设计,已基本完成课题要求。
功能上基本达标:时钟的显示,调时功能。
时钟显示功能,精确度完全可以满足日常生活显示时间的需要;调时功能,方便快捷。
本次设计是结合书本样例和老师给的样例,独立设计完成。
另外,在本次设计的过程中,我发现很多的问题,虽然以前没有做过这样的设计但通过这次设计我学会了很多东西,单片机课程设计重点就在于软件算法的设计,需要有很巧妙的程序算法,虽然以前写过几次程序,但我觉的写好一个程序并不是一件简单的事,比如写一个程序看其功能很少认为编写程序简单,但到编的时候才发现一些细微的知识或低级错误经常犯做不到最后常常失败,所以有些东西只有学精弄懂并且要细心才行,只学习理论有些东西是很难理解的,更谈不上掌握。
从这次的课程设计中,我真真正正的意识到,在以后的学习中,要理论联系实际,把我们所学的理论知识用到实际当中,学习单机片机更是如此,程序只有在经常的练习的过程中才能提高,我想这就是我在这次课程设计中的最大收获。
附录程序清单:#pragma sfr //使用特殊功能寄存器#pragma access //使用绝对地址指令#pragma EI //使用开中断关中断功能#pragma DI#pragma interrupt INTKR inter RB1 //定义按键中断#pragma interrupt INTRTC RTC_INTRTC //定义周期性定时中断char SEC_Num; //定义一个秒单元char MIN_Num; //定义一个分单元char HOUR_Num; //定义一个时单元char DAY_Num; //定义一个日单元char WEEK_Num; //定义一个周单元char MONTH_Num;//定义一个月单元char YEAR_Num; //定义一个年单元unsigned char hour1 = 0; //初始化闹钟时单元=0unsigned char minute1 = 0;//初始化闹钟分单元=0unsigned int numbercode[10] = {0x070d , 0x0600 , 0x030e , 0x070a , 0x0603 , 0x050b , 0x050f , 0x0700 , 0x070f , 0x070b };//数字“0”-“9”的显示码unsigned char i=0;//显示转换标志,i=0,1,2,3时显示年月日;i=4,5,6时显示星期时分;i=7时显示时分秒unsigned char KEY=0; //定义全局变量keyunsigned int s=-1; //定义全局变量sunsigned int buffy_m_d[6]; //年月日的数码显示缓存区unsigned int buffw_h_m[6]; //星期时分的数码显示缓存区unsigned int buffh_m_s[6]; //时分秒的数码显示缓存区unsigned int buffhm1[6]; //闹钟的数码显示缓存区void delay(); //延时函数unsigned int BCDtoDec( char bcd) //BCD码转换十进制函数char DectoBCD(int Dec) //十进制转换BCD码函数unsigned int m_days(unsigned int mmonth) //计算当月天数函数void inter() //按键中断处理函数void RTC_INTRTC() //INTRTC中断处理函数void noise() //闹钟响铃函数void freshdisplaybuffer() //显示缓存区刷新函数void d_c_inter() //切换时间函数void play6bit() //显示函数void set_hour() //闹钟使显示函数void set_minute() //闹钟分显示函数void set_inter() //调整时间函数void hour_inter() //闹钟调时函数void minute_inter() //闹钟调分函数//----------------------------------------------延时函数void delay(){int i;for(i=0;i<=100;i++);}//----------------------------------------------将BCD码转换成十进制的函数unsigned int BCDtoDec( char bcd){unsigned int i, tmp;tmp = ((bcd>>4)&0x0F)*10 + (bcd&0x0F);return tmp;}//----------------------------------------------将十进制转换成BCD码的函数char DectoBCD(int Dec){char Bcd;Bcd = ((Dec/10)<<4) + ((Dec%10) & 0x0F);return Bcd;}//----------------------------------------------计算当前月中天数的函数unsigned int m_days(unsigned int mmonth){unsigned int days;if((mmonth==4)||(mmonth==6)||(mmonth==9)||(mmonth==11)) days=30;else if (mmonth==2){if(BCDtoDec(YEAR)%4==0) //判断是否是闰年days=29;elsedays=28;}else days=31;return(days);}//----------------------------------------------按键中断处理函数void inter(){DI();switch(P4 & 0x3F){case 0x3e:KEY=1;break;case 0x3d:KEY=2;break;case 0x3b:KEY=3;break;case 0x37:KEY=4;break;case 0x2f:KEY=5;break;case 0x1f:KEY=6;break;default: break;}EI();}//----------------------------------------------INTRTC中断处理函数void RTC_INTRTC(){RWAIT = 1; //RWAIT标志置1,读取实时时钟数据while(RWST==0); //检测是否处于读、写模式,RWST=1表示处于读写模式SEC_Num =BCDtoDec(SEC); //将秒钟数转换为十进制读取到SEC_Num中MIN_Num =BCDtoDec(MIN); //将分钟数转换为十进制读取到MIN_Num中HOUR_Num =BCDtoDec(HOUR); //将小时数转换为十进制读取到HOUR_Num中DAY_Num =BCDtoDec(DAY); //将日计数转换为十进制读取到HOUR_Num中WEEK_Num =BCDtoDec(WEEK); //将周计数转换为十进制读取到WEEK_Num中MONTH_Num =BCDtoDec(MONTH);//将月计数转换为十进制读取到MONTH_Num中YEAR_Num =BCDtoDec(YEAR); //将年计数转换为十进制读取到YEAR_Num中RWAIT = 0;while(RWST==1); //检测是否处于计数模式,RWST=0表示处于计数模式s=(s+1)%12; //流水灯处理,每一秒换一个灯显示switch(s){case 0: P15.3=0;P13.0=1; break;case 1: P13.0=0;P13.1=1; break;case 2: P13.1=0;P13.2=1; break;case 3: P13.2=0;P13.3=1; break;case 4: P13.3=0;P14.0=1; break;case 5: P14.0=0;P14.1=1; break;case 6: P14.1=0;P14.2=1; break;case 7: P14.2=0;P14.3=1; break;case 8: P14.3=0;P15.0=1; break;case 9: P15.0=0;P15.1=1; break;case 10: P15.1=0;P15.2=1; break;case 11: P15.2=0;P15.3=1; break;default:break;}}//----------------------------------------------闹钟响铃函数void noise(){if(hour1==HOUR_Num&&minute1==MIN_Num&&P3.4==1){CKS=0X80;delay();BZOE=0;}}//----------------------------------------------显示缓存区刷新函数void freshdisplaybuffer(){buffy_m_d[5]=numbercode[YEAR_Num/10]; //年月日显示刷新buffy_m_d[4]=numbercode[YEAR_Num%10];buffy_m_d[4]|=0x0800;buffy_m_d[3]=numbercode[MONTH_Num/10];buffy_m_d[2]=numbercode[MONTH_Num%10];buffy_m_d[2]|=0x0800;buffy_m_d[1]=numbercode[DAY_Num/10];buffy_m_d[0]=numbercode[DAY_Num%10];buffw_h_m[5]=numbercode[WEEK_Num/10]; //星期时分显示刷新buffw_h_m[4]=numbercode[WEEK_Num%10];buffw_h_m[4]|=0x0800;buffw_h_m[3]=numbercode[HOUR_Num/10];buffw_h_m[2]=numbercode[HOUR_Num%10];buffw_h_m[2]|=0x0800;buffw_h_m[1]=numbercode[MIN_Num/10];buffw_h_m[0]=numbercode[MIN_Num%10];buffh_m_s[5]=numbercode[HOUR_Num/10]; //时分秒显示刷新buffh_m_s[4]=numbercode[HOUR_Num%10];buffh_m_s[4]|=0x0800;buffh_m_s[3]=numbercode[MIN_Num/10];buffh_m_s[2]=numbercode[MIN_Num%10];buffh_m_s[2]|=0x0800;buffh_m_s[1]=numbercode[SEC_Num/10];buffh_m_s[0]=numbercode[SEC_Num%10];}//----------------------------------------------切换时间函数void d_c_inter(){DI();if(i<7){i++;}else{i=0;}EI();}//----------------------------------------------显示函数void play6bit(){unsigned int dp=0;unsigned int b[6];unsigned int LCD_addr;LCD_addr=0xFA4A;while (dp<6){switch(i){case 0:case 1:case 2:case 3:b[dp] = buffy_m_d [dp];break;//i=0,1,2,3时显示年月日case 4:case 5:case 6:b[dp] = buffw_h_m [dp];break;//i=4,5,6时显示星期时分case 7:b[dp] = buffh_m_s [dp];break;//i=7使显示时分秒}pokew(LCD_addr,b[dp]);delay();pokew(LCD_addr,0x0000);LCD_addr = LCD_addr-2;dp++;}}//----------------------------------------------闹钟时显示函数void set_hour(){unsigned int dp=4;unsigned int a[6];unsigned int LCD_addr;LCD_addr=0xFA42;buffhm1[5]=numbercode[hour1/10];buffhm1[4]=numbercode[hour1%10];buffhm1[4]|=0x0800;while (dp<6){a[dp]=buffhm1[dp];pokew(LCD_addr,a[dp]);delay();pokew(LCD_addr,0x0000);LCD_addr=LCD_addr-2;dp++;}}//----------------------------------------------闹钟分显示函数void set_minute(){unsigned int dp=0;unsigned int b[6];unsigned int LCD_addr;LCD_addr=0xFA4A;buffhm1[3]=numbercode[minute1/10];buffhm1[2]=numbercode[minute1%10];buffhm1[1]=0;buffhm1[0]=0;while (dp<4){b[dp]=buffhm1[dp];pokew(LCD_addr,b[dp]);delay();pokew(LCD_addr,0x0000);LCD_addr=LCD_addr-2;dp++;}}//----------------------------------------------调整时间函数void set_inter(){DI();RTCE=0;switch(i){case 1:{if(YEAR_Num<99)YEAR = DectoBCD(YEAR_Num+1);else YEAR = 0;break;}case 2:{if(MONTH_Num<12)MONTH = DectoBCD(MONTH_Num+1);else MONTH = 1;break;}case 3:{int temp =m_days(BCDtoDec(MONTH)); //计算当月天数if(DAY_Num >= temp)DAY =1;elseDAY = DectoBCD(DAY_Num+1);break;}case 4:{ if(WEEK_Num<6)WEEK =DectoBCD(WEEK_Num+1);else WEEK = 0;break;}case 5:{if(HOUR_Num<23)HOUR = DectoBCD(HOUR_Num+1);else HOUR =0;break;}case 6:{if(MIN_Num<59)MIN = DectoBCD(MIN_Num+1);else MIN = 0;break;}default : break;}RTCE=1;EI();}//----------------------------------------------闹钟调时函数void hour_inter(){if(hour1<23)hour1++;else hour1=0;}//----------------------------------------------闹钟调分函数void minute_inter(){if(minute1<59)minute1++;else minute1=0;}//----------------------------------------------主函数void main(){PCC=0x00; //CPU的时钟选择(5.0Hz)PFALL=0x0F; //所有接LCD引脚指定为LCD引脚LCDC0=0x45; //确定LCD显示频率LCDMD=0x10; //LCD电源设置为1/5VDDLCDM=0xC0; //LCD显示开PM4=0x3F; //P4的六个端口设置为输入模式PU4=0x3F; //接通上拉电阻KRM=0x3F; //允许六个按键中断KRMK=0;P3.4=0; //LED灯初始化为熄灭状态PM3.4=0; //P3.3和P3.4端口设置为输出模式P3.3=0;PM3.3=0;PM13=0xf0; //端口13,14,15设置为输出模式PM14=0xf0;PM15=0xf0;EI();RTCCL=0X02;//8MHz内部高速时钟作为主系统时钟,实时计数器时钟=fprs/28=32.768KHz RIFG=0; //周期性定时中断打开RTCE=0; //停止计数操作RTCC0 = 0x0a; //无输出,24小时制,1秒钟定时中断MIN = 0X00; //设置分初值HOUR = 0X12; //设置时初值DAY = 0X01; //设置日初值WEEK = 0x00; //设置周初值MONTH = 0X01; //设置月初值YEAR = 0X13; //设置年(2位数)初值RTCIF = 0; //清中断固定中断标示RTCMK = 0; //固定周期中断开RTCE=1; //启动计数操作while(1){switch(KEY){case 0: //没有按键中断{noise(); //调用闹钟响铃函数freshdisplaybuffer(); //调用显示缓存区刷新函数play6bit(); //调用显示函数break;}case 1: //按键KEY1被按下{d_c_inter(); //调用切换时间函数freshdisplaybuffer(); //调用显示缓存区刷新函数play6bit(); //调用显示函数KEY=0;break;}case 2: //按键KEY2被按下{set_hour(); //调用闹钟时显示函数set_minute(); //调用闹钟分显示函数KEY=7;break;}case 3: //按键KEY3被按下{set_inter(); //调用时间调整函数freshdisplaybuffer(); //调用显示缓存区刷新函数play6bit(); //调用显示函数KEY=0;break;}case 4: //按键KEY4被按下{P3.4=~P3.4; //切换LED亮灭,调整闹钟开关KEY=0;break;}case 5: //按键KEY5被按下{hour_inter(); //调用闹钟调时函数set_hour(); //调用闹钟时显示函数KEY=7;break;}case 6: //按键KEY6被按下{minute_inter(); //调用闹钟调分函数set_minute(); //调用闹钟分显示函数KEY=7;break;}case 7:{noise(); //调用闹钟响铃函数set_hour(); //调用闹钟时显示函数set_minute(); //调用闹钟分显示函数break;}}}}。