石家庄铁道大学课程设计模拟电子时钟单位电气与电子工程学院分院(系)专业电气学号学生姓名指导教师完成日期 2011 年5 月29日摘要电子时钟是一种用电脑实现时、分、秒计时的装置,与机械时钟相比具有更高的准确性和直观性,且无机械装置,具有更长的使用寿命。
电子钟已成为人们日常生活中必不可少的必需品,广泛用于个人家庭以及车站、码头、剧院、办公室等公共场所,给人们的生活、学习、工作、娱乐带来极大地方便。
C语言功能丰富、表达能力强、使用方便、应用面广、目标程序效率高,因此特别适合模拟电子时钟的开发关键词:模拟电子时钟,程序设计。
目录第1章选题的意义 (4)1.1 (4)1.2 (4)第2章系统功能需求分析 (5)2.1系统的基本要求 (5)2.2 (5)第3章系统设计 (6)第4章系统实现 (7)第5章总结………………………………………………………………………19第1章选题的意义1.1 选题的意义随着社会的发展,电子钟逐渐成为人们生活中不可缺少的一部分。
人们对时钟精度的要求越来越高,这就要求我们动用电子模拟技术对时钟的精度进行保证,同时模拟电子时钟还可以设计出美观的画面,具有现实中时钟不可相比的优点。
此程序所模拟出来的电子时钟具有操作简单,灵活,实用的优点,可以为我们提供方便。
同时通过对生活中普遍存在实物的设计,可以加深我们对c语言的深入理解掌握开发电子钟的基本原理,为进一步开发高质量程序打下基础。
1.2 硬件环境完整的电脑,包括键盘、鼠标、以及足够大的内存空间。
屏幕尺寸推荐使用640*380.1.3软件环境开发过程采用win-tc环境,运行环境是采用windows xp操作系统。
第2章系统功能需求分析2.1系统的基本要求实现时钟显示功能,具有动画模拟时钟和数字时钟,可以修改时间,界面友好,运行稳定2.2系统的功能首先画出时钟的界面,包括表盘,表针,以及数字时钟界面。
同时还在屏幕上打印出帮助信息,使使用者轻松方便的使用该时钟。
预期设想实现时钟的调时功能,按下一个键,进入时钟时间重设功能。
本电子时钟有四个模块构成,电子时钟界面显示,电子时钟按键控制,电子时钟动画处理,数字时钟模拟;具备修改时间功能,模拟出动态画面,界面友好,显示准确。
可以模拟出动画状态。
运行稳定,时间准确,精度较高,界面给人以美感,舒适。
第3章系统设计设计主体为首先画图,然后调用时钟处理函数,其次再调用一个循环,使之进入主体时钟处理函数。
时钟处理函数中含有划线函数,先取得电脑中的时间,调用画图函数画出当前所对应的模拟时钟图像,同时把时间赋给数字时钟3.1流程图3.2电子时钟界面显示本程序定义了huatu()函数,程序首先进入主函数后,就开始调用huatu()函数。
Huatu()函数中首先调用initgraph()函数,使系统进入图形模式,调用setlinestyle(x,y,z)函数来设定线粗。
Z代表线的粗细,分为1,2,3三个等级的线型;调用setbkcolor(x)函数设置当前的背景颜色,颜色分为1-15个等级,0为白色;然后调用setcolor(x)函数确定当前画线的颜色,同样也有1-15个等级;调用line(x,y,a,b)函数开始画线,(x,y)代表起点坐标(a,b)代表终点坐标;然后调用outtextxy(x,y,””)函数在坐标点为(x,y)的位置输出分号中的内容;其中还调用了circle(i,j,x)函数画出了以x为半径(x,y)为圆心的圆作为表示小时或者分钟的圆点;调用完以上函数就完成了界面主体的绘制。
3.3按键控制模块在本模块中,使用bioskey()函数读取用户的键值进行判断,执行相应操作。
具体如下:用户按下TAB或者Esc键,系统调按键判断函数,跳出时钟处理函数1,进入输入界面,调用scanf()函数对结构体变量中的元素&t[0].ti_min,&t[0].ti_hour,&t[0].ti_sec重新赋值后,再调用settime(t)函数,使之把数值赋给系统时间,通过改变系统时间达到修改时间的功能。
3.4时钟动画处理时钟动画处理是本程序的核心,巧妙模拟出动态效果。
其中的关键在于对时针、分针、秒针的绘制以及计算。
具体设计如下:(1)坐标点的计算,表盘中的时分秒有一个共同的圆心,但是各在不同的圆弧上移动,规律是:秒针转动60次,分针转动1次;分针转动60次,时针转动1次;秒针每一次所经过的角度是60度,并且可以通过与圆心的关系计算出来。
具体计算如下:圆心坐标为(x,y),半径为r借助三角函数可以求得k点的坐标值(x+a sinθ,y-a cosθ),同样可以用相同的方法求得,分、秒的坐标值。
本程序中a,b,c分别取50,80,98,单位为像素。
可以模拟出不同的长度,作为时、分、秒指针示意图如下:(2)动画处理流程初运行阶段首先取得系统时间并保存在t结构体变量内,同时在数字时钟中显示出当前系统时间。
然后开始进入for循环,直到用户按ESC或者Tab键跳出循环。
同时打开扬声器,发出滴答声,并利用while循环延迟一秒从而模拟出机械钟的滴答声。
延迟一秒后清除原来的秒针,绘制新的秒针,同时更新数字时钟的数字。
用一个if语句判断如果分钟有变化,清除分针,重绘分针;如果时针有变化,清除时针,重绘时针。
最后通过对键值的判断,若为Esc或者Tab则跳出循环。
3.5数字时钟处理模块在本模块中,每隔一秒会调用gettime(t)函数来得到系统时间,并把它赋给digitclock()函数,并在显示相应的数字时钟位置,同时还有一个判断语句,如果秒数等于60,那么秒数就会重新变为0,从而形成一个循环。
修改时间是通过的改变系统时间来实现的,调用scanf()函数把t结构体变量重新赋值,再调用settime()函数就把系统时间修改成功了。
第4章系统实现/*电子时钟源代码*/#include<graphics.h>#include<stdio.h>#include<math.h>#include<dos.h>#define PI 3.1415926 /*定义常量*/#define ESC 0x11b /*ESC键:退出系统*/#define TAB 0xf09 /*TAB键:移动光标*//*函数声明*/int keyhandle(int); /*键盘按键判断,并调用相关函数处理*/int digithour(double); /*将double型的小时数转换成int型*/int digitmin(double); /*将double型的分钟数转换成int型*/int digitsec(double); /*将double型的秒钟数转换成int型*/void digitclock(int,int,int ); /*在指定位置显示时钟或分钟或秒钟数*/ void drawcursor(int); /*绘制一个光标*/void clearcursor(int);/*消除前一个光标*/void clockhandle(); /*时钟处理*/double h,m,s; /*全局变量:小时,分,秒*/double ho,mi;double x,x1,x2,y,y1,y2; /*全局变量:坐标值*/struct time t[1];/*定义一个time结构类型的数组*/main(){huatu();clockhandle1();/*开始调用时钟处理程序*/tab1:closegraph();printf("setuptime,now!\n please (min,hour,sec)\n");scanf("%d,%d,%d",&t[0].ti_min,&t[0].ti_hour,&t[0].ti_sec);huatu();settime(t);clockhandle2();goto tab1;closegraph(); /*关闭图形系统*/return 0; /*表示程序正常结束,向操作系统返回一个0值*/}clockhandle1(){int k=0,count;setcolor(15);gettime(t);/*取得系统时间,保存在time结构类型的数组变量中*/h=t[0].ti_hour;m=t[0].ti_min;x=50*sin((h*60+m)/360*PI)+320; /*时针的x坐标值*/y=180-50*cos((h*60+m)/360*PI); /*时针的y坐标值*/line(320,180,x,y);/*在电子表中绘制时针*/x1=80*sin(m/30*PI)+320; /*分针的x坐标值*/y1=180-80*cos(m/30*PI); /*分针的y坐标值*/line(320,180,x1,y1); /*在电子表中绘制分针*/digitclock(260,333,digithour(h)); /*在数字时钟中,显示当前的小时值*/ digitclock(305,333,digitmin(m)); /*在数字时钟中,显示当前的分钟值*/ setwritemode(1);/*规定画线的方式,如果mode=1,则表示画线时用现在特性的线与所画之处原有的线进行异或(XOR)操作,实际上画出的线是原有线与现在规定的线进行异或后的结果。
因此, 当线的特性不变, 进行两次画线操作相当于没有画线,即在当前位置处清除了原来的画线*/for(count=2;k!=ESC&&k!=TAB;){ /*开始循环,直至用户按下ESC键结束循环*/ setcolor(12);/*淡红色*/sound(500);/*以指定频率打开PC扬声器,这里频率为500Hz*/delay(700);/*发一个频率为500Hz的音调,维持700毫秒*/sound(200);/*以指定频率打开PC扬声器,这里频率为200Hz*/delay(300);/*以上两种不同频率的音调,可仿真钟表转动时的嘀哒声*/nosound(); /*关闭PC扬声器*/s=t[0].ti_sec;m=t[0].ti_min;h=t[0].ti_hour;x2=98*sin(s/30*PI)+320; /*秒针的x坐标值*/y2=180-98*cos(s/30*PI); /*秒针的y坐标值*/setlinestyle(0,0,1);line(320,180,x2,y2);/*绘制秒针*//*利用此循环,延时一秒*/while(t[0].ti_sec==s&&t[0].ti_min==m&&t[0].ti_hour==h){ gettime(t);/*取得系统时间*/if(bioskey(1)!=0){k=bioskey(0);count=keyhandle(k);}}setcolor(15);digitclock(353,333,digitsec(s)+1);/*数字时钟增加1秒*/setcolor(12); /*淡红色*/x2=98*sin(s/30*PI)+320;y2=180-98*cos(s/30*PI);line(320,180,x2,y2);/*用原来的颜色在原来位置处再绘制秒针,以达到清除当前秒针的目的*//*分钟处理*/if(t[0].ti_min!=m){ /*若分钟有变化*//*消除当前分针*/setcolor(15); /*白色*/x1=80*sin(m/30*PI)+320;y1=180-80*cos(m/30*PI);line(320,180,x1,y1);/*绘制新的分针*/m=t[0].ti_min;digitclock(305,333,digitmin(m)); /*在数字时钟中显示新的分钟值*/x1=80*sin(m/30*PI)+320;y1=180-80*cos(m/30*PI);line(320,180,x1,y1);}/*小时处理*/if((t[0].ti_hour*60+t[0].ti_min)!=(h*60+m)){ /*若小时数有变化*//*消除当前时针*/setcolor(15); /*白色*/x=50*sin((h*60+m)/360*PI)+320;/*50:时钟的长度(单位:像素),320:圆心的x 坐标值*/y=180-50*cos((h*60+m)/360*PI);line(320,180,x,y);/*绘制新的时针*/h=t[0].ti_hour;digitclock(260,333,digithour(h));x=50*sin((h*60+m)/360*PI)+320;y=180-50*cos((h*60+m)/360*PI);line(320,180,x,y);}}}int keyhandle(int key) /*键盘控制*/case TAB:;}int digithour(double h)/*将double型的小时数转换成int型*/{int i;for(i=0;i<=23;i++){if(h==i) return i;}}int digitmin(double m)/*将double型的分钟数转换成int型*/{int i;for(i=0;i<=59;i++){if(m==i) return i;}}int digitsec(double s) /*将double型的秒钟数转换成int型*/{int i;for(i=0;i<=59;i++){if(s==i) return i;}}void digitclock(int x,int y,int clock)/*在指定位置显示数字时钟:时\分\秒*/ {char buffer1[10];setfillstyle(0,2);bar(x,y,x+20,348);if(clock==60) clock=0;sprintf(buffer1,"%d",clock);outtextxy(x,y,buffer1);}void drawcursor(int count) /*根据count的值,画一个光标*/ {switch(count){case 1:line(424,315,424,325);break;case 2:line(465,315,465,325);break;case 3:line(505,315,505,325);break;}}void clearcursor(int count) /*根据count的值,清除前一个光标*/{case 1:line(424,315,424,325);break;case 2:line(465,315,465,325);break;case 3:line(505,315,505,325);break;}}huatu(){int driver, mode=0,i,j;driver=DETECT; /*自动检测显示设备*/initgraph(&driver, &mode, "");/*初始化图形系统*/setlinestyle(0,0,3); /*设置当前画线宽度和类型:设置三点宽实线*/ setbkcolor(0);/*用调色板设置当前背景颜色*/setcolor(9); /*设置当前画线颜色*/line(5,5,635,5);line(5,5,5,475);line(635,5,635,475);line(5,475,635,475);line(5,235,320,5);line(320,5,635,235);line(635,235,320,400);line(320,400,5,235); /*画主体框架的边直线*//*arc(int x, int y, int stangle, int endangle, int radius)*/setcolor(15);outtextxy(305,50,"CLOCK"); /*显示标题*/setcolor(7);line(250,320,390,320);line(390,320,390,350);line(390,350,250,350);line(250,350,250,320);setcolor(5);for(i=290;i<=336;i+=46)for(j=333;j<=340;j+=7){setlinestyle(0,0,3);circle(i,j,1); /*以(i, y)为圆心,1为半径画圆*/}/*绘制表示小时的圆点*/setcolor(15);for(i=0,mi=0,ho=0;i<=11;i++,ho++){x=100*sin((ho*60+mi)/360*PI)+320;y=180-100*cos((ho*60+mi)/360*PI);setlinestyle(0,0,3);}/*绘制表示分钟或秒钟的圆点*/setcolor(11);for(i=0,mi=0;i<=59;mi++,i++){x=100*sin(mi/30*PI)+320;y=180-100*cos(mi/30*PI);setlinestyle(0,0,1);circle(x,y,1);}/*在电子表的左边打印帮助提示信息*/setcolor(12);outtextxy(250,420,"Do not waste time!"); outtextxy(20,35,"print TAB or ESC to setup time!"); outtextxy(385,35,"May you be happy forever"); setcolor(10);outtextxy(400,55,"version 1.0");outtextxy(20,55,"jinhengli c language program"); outtextxy(313,65,"12");outtextxy(363,80,"1");outtextxy(413,120,"2");outtextxy(426,175,"3");outtextxy(413,225,"4");outtextxy(370,273,"5");outtextxy(316,286,"6");outtextxy(263,275,"7");outtextxy(219,233,"8");outtextxy(205,177,"9");outtextxy(214,120,"10");outtextxy(263,80,"11");setcolor(10);circle(150,240,50);circle(150,240,45);circle(150,240,40);circle(150,240,35);circle(150,240,30);circle(150,240,25);circle(150,240,20);circle(150,240,15);circle(150,240,10);circle(150,240,05);circle(150,240,1);circle(490,240,50);circle(490,240,45);circle(490,240,35);circle(490,240,30);circle(490,240,25);circle(490,240,20);circle(490,240,15);circle(490,240,10);circle(490,240,05);circle(490,240,1);}clockhandle2(){int k=0,count;setcolor(15);gettime(t);/*取得系统时间,保存在time结构类型的数组变量中*/h=t[0].ti_hour;m=t[0].ti_min;x=50*sin((h*60+m)/360*PI)+320; /*时针的x坐标值*/y=180-50*cos((h*60+m)/360*PI); /*时针的y坐标值*/line(320,180,x,y);/*在电子表中绘制时针*/x1=80*sin(m/30*PI)+320; /*分针的x坐标值*/y1=180-80*cos(m/30*PI); /*分针的y坐标值*/line(320,180,x1,y1); /*在电子表中绘制分针*/digitclock(260,333,digithour(h)); /*在数字时钟中,显示当前的小时值*/ digitclock(305,333,digitmin(m)); /*在数字时钟中,显示当前的分钟值*/ setwritemode(1);/*规定画线的方式,如果mode=1,则表示画线时用现在特性的线与所画之处原有的线进行异或(XOR)操作,实际上画出的线是原有线与现在规定的线进行异或后的结果。