课程设计报告课程名称:单片机程序设计报告题目:电子时钟学生姓名:所在学院:信息科学与工程学院专业班级:学生学号:指导教师:2013年12月25日课程设计任务书摘要单片计算机即单片微型计算机。
由RAM、ROM、CPU构成。
定时,计数和多种接口于一体的微控制器。
它体积小,成本低,功能强,广泛应用于智能产业和工业自动化上。
而51系列单片机是各单片机中最为典型和最有代表性的一种。
这次课程设计通过对它的学习,应用,从而达到学习、设计、开发软、硬的能力。
本设计主要设计了一个基于AT89C51单片机的电子时钟。
并在数码管上显示相应的时间。
并通过一个控制键用来实现时间的调节和是否进入省电模式的转换。
应用Proteus的ISIS软件实现了单片机电子时钟系统的设计与仿真。
该方法仿真效果真实、准确,节省了硬件资源。
关键词:单片机;子时钟;键控制目录一、概述 (5)1.1电子时钟简介 (5)1.2电子时钟的基本特点 (5)1.3电子时钟的原理 (5)二、方案设计选择 (5)2.1计时方案 (5)2.2显示方案 (5)三、硬件设计 (6)3.1单片机型号选择 (6)3.2数码管显示工作原理 (6)3.3键盘电路设计 (7)3.4电路原理图 (7)四、软件设计 (7)五、结论与心得 (15)六、参考文献 (16)一、概述1.1 电子时钟简介1957年,Ventura发明了世界上第一个电子表,从而奠定了电子时钟的基础,电子时钟开始迅速发展起来。
现代的电子时钟是基于单片机的一种计时工具,采用延时程序产生一定的时间中断用于一秒的定义,通过计数方式进行满六十秒分钟进一,满六十分小时进一,满二十四小时小时清零。
从而达到计时的功能,是人民日常生活补课缺少的工具。
1.2 电子时钟的基本特点现在高精度的计时工具大多数都使用了石英晶体振荡器,由于电子钟、石英钟、石英表都采用了石英技术,因此走时精度高,稳定性好,使用方便,不需要经常调试,数字式电子钟用集成电路计时时,译码代替机械式传动,用LED 显示器代替指针显示进而显示时间,减小了计时误差,这种表具有时、分、秒显示时间的功能,还可以进行时和分的校对,片选的灵活性好。
1.3 电子时钟的原理该电子时钟由89C51,BUTTON,六段数码管等构成,采用晶振电路作为驱动电路,由延时程序和循环程序产生的一秒定时,达到时分秒的计时,六十秒为一分钟,六十分钟为一小时,满二十四小时为一天。
而电路中唯一的一个控制键却拥有多种不同的功能,按下又松开,可以实现屏蔽数码管显示的功能,达到省电的目的;直接按下不松开,则可以通过按键实现分钟的累加,每按一次分钟加一;而连续两次按下按键不放松,则可实现小时的调节,同样每按一次小时加一。
二、方案设计选择2.1计时方案方案1:采用实时时钟芯片现在市场上有很多实时时钟集成电路,如DS1287、DS12887、DS1302等。
这些实时时钟芯片具备年、月、日、时、分、秒计时功能和多点定时功能,计时数据的更新每秒自动进行一次,不需要程序干预。
因此,在工业实时测控系统中多采用这一类专用芯片来实现实时时钟功能。
方案2:使用单片机内部的可编程定时器。
利用单片机内部的定时计数器进行中端定时,配合软件延时实现时、分、秒的计时。
该方案节省硬件成本,但程序设计较为复杂。
2.2显示方案对于实时时钟而言,显示显然是另一个重要的环节。
通常LED显示有两种方式:动态显示和静态显示。
静态显示的优点是程序简单、显示亮度有保证、单片机CPU的开销小,节约CPU的工作时间。
但占有I/O口线多,每一个LED都要占有一个I/O口,硬件开销大,电路复杂。
需要几个LED就必须占有几个并行口,比较适用于LED数量较少的场合。
当然当LED数量较多的时候,可以使用单片机的串行口通过移位寄存器的方式加以解决,但程序编写比较麻烦。
LED动态显示硬件连接简单,但动态扫描的显示方式需要占有CPU较多的时间,在单片机没有太多实时测控任务的情况下可以采用。
本系统需要采用6位LED数码管来分别显示时、分、秒,因数码管个数较多,故本系统选择动态显示方式。
三、硬件设计3.1单片机型号的选择通过对多种单片机性能的分析,最终认为89C51是最理想的电子时钟开发芯片。
89C51是一种带4K字节闪烁可编程可擦除只读存储器的低电压,高性能CMOS8 位微处理器,器件采用ATMEL高密度非易失存储器制造技术制造,与工业标准的MCS-51指令集和输出管脚相兼容。
由于将多功能8位CPU和闪烁存储器组合在单个芯片中,ATMEL的89C5是一种高效微控制器,而且它与MCS-51兼容,且具有4K字节可编程闪烁存储器和1000写/擦循环,数据保留时间为10年等特点,是最好的选择。
3.2数码管显示工作原理数码管是一种把多个LED显示段集成在一起的显示设备。
有两种类型,一种是共阳型,一种是共阴型。
共阳型就是把多个LED显示段的阳极接在一起,又称为公共端。
共阴型就是把多个LED显示段的阴极接在一起,即为公共商。
阳极即为二极管的正极,又称为正极,阴极即为二极管的负极,又称为负极。
通常的数码管又分为8段,即8个LED显示段,这是为工程应用方便如设计的,分别为A、B、C、D、E、F、G、DP,其中DP是小数点位段。
而多位数码管,除某一位的公共端会连接在一起,不同位的数码管的相同端也会连接在一起。
即所有的A段都会连在一起,其它的段也是如此,这是实际最常用的用法。
数码管显示方法可分为静态显示和动态显示两种。
静态显示就是数码管的8段输入及其公共端电平一直有效。
动态显示的原理是,各个数码管的相同段连接在一起,共同占用8位段引管线;每位数码管的阳极连在一起组成公共端。
利用人眼的视觉暂留性,依次给出各个数码管公共端加有效信号,在此同时给出该数码管加有效的数据信号,当全段扫描速度大于视觉暂留速度时,显示就会清晰显示出来。
3.3键盘电路设计该设计只用了一个键盘,但实现的功能却是比较完善,减少了硬件资源的损耗,该键盘可以实现小时和分钟的调节;直接按下不松开,则可以通过按键实现分钟的累加,每按一次分钟加一;而连续两次按下按键不放松,则可实现小时的调节,同样每按一次小时加一。
达到时间调节的目的。
3.4电路原理图四、软件设计#include <reg52.h>#include <intrins.h>#define uchar unsigned char#define uint unsigned int#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();} //宏定义掩延时函数sbit K1=P3^0; //位定义sbit K2=P3^1;sbit K3=P3^2;sbit K4=P3^3;sbit D34=P3^4;sbit SCL = P2^0;sbit SDA = P2^1;void diyi();void xianshi(); // 函数声明void panduan(); //函数声明void delay(uchar z); //函数声明uchar t=0,n=1,m=59,a,temp; //定义变量uchar code at[]={0xe0,0xd0,0xb0,0x70}; //定义数组uchar code as[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; uchar code b[]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};uint cnt;void delay_us(uchar tt) //短延时函数{while(tt--);}/****************************//***********初始化***********//**************************//********at24c02***********/void I2C_start()//I^2C模块{SDA = 1;_nop_();SCL = 1;somenop;SDA = 0;somenop;SCL = 0;}void I2C_stop(){SDA = 0;_nop_();SCL = 1;somenop;SDA = 1;}void I2C_ack(bit ackbit) {if(ackbit)SDA = 0;elseSDA = 1;somenop;SCL = 1;somenop;SCL = 0;SDA = 1;somenop;}bit I2C_waitack(){SDA = 1;somenop;SCL = 1;somenop;if(SDA){SCL = 0;I2C_stop();return 0;}else{SCL = 0;return 1;}}void I2C_write(uchar dat){uchar i;for(i=0;i<8;i++){if(dat&0x80)SDA = 1;elseSDA = 0;somenop;SCL = 1;dat <<= 1;somenop;SCL = 0;}}uchar I2C_read(){uchar dat;uchar i;for(i=0;i<8;i++){SCL = 1;somenop;dat <<= 1;if(SDA)dat |= 0x01;SCL = 0;somenop;}return dat;}void W_at24c02(uchar add,uchar dat){I2C_start();I2C_write(0xa0);I2C_waitack();I2C_write(add);I2C_waitack();I2C_write(dat);I2C_waitack();I2C_stop();delay_us(300);}uchar R_at24c02(uchar add) {uchar AT_temp;I2C_start();I2C_write(0xa0);I2C_waitack();I2C_write(add);I2C_waitack();I2C_start();I2C_write(0xa1);I2C_waitack();AT_temp = I2C_read();I2C_ack(0);I2C_stop();return AT_temp;}/**************************//************main**********/void main(){diyi();t= R_at24c02(24); //程序运行时,读取掉电前数据m= R_at24c02(23);n= R_at24c02(25);while(1){panduan();//判断子函数xianshi();//显示子函数}}void diyi() //定义子函数{P2=0xbf;P0=0xbf;TMOD=0x01;TH0=(65536-50000)/256;TL0=(65536-50000)%256;EA=1;ET0=1;TR0=1;}void exer1() interrupt 1 //定时器/计数器1{uchar t1;TH0=(65536-50000)/256;TL0=(65536-50000)%256;t1++;if(t1==10){P2=0x9f;P0=0x00;}if(t1==20){P2=0x9f;P0=0xff;t1=0;t++;W_at24c02(24,t ); //每隔一秒,保存当前数据delay(3);W_at24c02(23,m);delay(3);W_at24c02(25,n);if(t==60){ t=0; m++;if(m==60){ m=0; n++; }if(n==24)n=0;}}}void xianshi()//显示函数{P2 = 0xdf; P0 =b[0]; P2=0x1f; P0=0xff; P2 = 0xff; P0 =as[t%10];P2=0x1f;P0=0x00;delay(3);P2 = 0xdf; P0 =b[1]; P2=0x1f; P0=0xff; P2 = 0xff; P0 =as[(t/10)%10]; P2=0x1f;P0=0x00;delay(3);P2 = 0xdf; P0 =b[2]; P2=0x1f; P0=0xff; P2 = 0xff; P0 =0xbf;P2=0x1f;P0=0x00;delay(3);P2 = 0xdf; P0 =b[3]; P2=0x1f; P0=0xff; P2 = 0xff; P0 =as[m%10];P2=0x1f;P0=0x00;delay(3);P2 = 0xdf; P0 =b[4]; P2=0x1f; P0=0xff; P2 = 0xff; P0 =as[(m/10)%10]; P2=0x1f;P0=0x00;delay(3);P2 = 0xdf; P0 =b[5]; P2=0x1f; P0=0xff; P2 = 0xff; P0 =0xbf;P2=0x1f;P0=0x00;delay(3);P2 = 0xdf; P0 =b[6]; P2=0x1f; P0=0xff; P2 = 0xff; P0 =as[n%10];P2=0x1f;P0=0x00;delay(3);P2 = 0xdf; P0 =b[7]; P2=0x1f; P0=0xff; P2 = 0xff; P0 =as[(n/10)%10]; P2=0x1f;P0=0x00;delay(3);}void delay(uchar z)//延时函数{uchar i,j;for(i=0;i<z;i++)for(j=0;j<110;j++);}void panduan()//判断函数{P3=0xfe;delay(5);temp=P3;temp=temp&0xf0;if(temp!=0xf0){delay(5);if(temp!=0xf0){while(P3!=0xfe);if(temp==at[0]){a++;TR0=0; if(a==4) {a=0;TR0=1;}}if(temp==at[1]){if(a==1){ t++; if(t==60){ t=0;} }if(a==2){m++;if(m==60){m=0;}}if(a==3){ n++;if(n==24){n=0;}}}if(temp==at[2]){if(a==1){if(t==0){t=60;}t--;}if(a==2){if(m==0){m=60;}m--;}if(a==3){if(n==0){n=24;}n--;}}P2 = 0xc0;P0 =b[7]; P2=0x00;P0=0xff;P2 = 0xe0;P0=0xff;P2=0x00;P0=0x00;delay(3);}}}五、结论与心得在廖亦凡和曹铁军老师耐心的指导下,我顺利完成了这次单片机课程设计课题中的电子时钟设计,过这次的设计使我认识到本人对单片机方面的知识知道的太少了,对于书本上的很多知识还不能灵活运用,尤其是对程序设计语句的理解和运用,不能够充分理解每个语句的具体含义,导致编程的程序过于复杂,使得需要的存储空间增大。