在单片机技术日趋成熟的今天,其灵活的硬件电路和软件电路的设计,让单片机得到广泛的应用,几乎是从小的电子产品,到大的工业控制,单片机都起到了举足轻重的作用。单片机小的系统结构几乎是所有具有可编程硬件的一个缩影,可谓是"麻雀虽小,肝胆俱全",单片机的学习和研究是对微机系统学习和研究的简捷途径。基于单片机的定时和控制装置在许多行业有着广泛的应用,而电子时钟是其中最基本的,也是最具有代表性的一个例子[1] ,用数字电路实现对时、分、秒数字显示的计时装置。因为机具有体积小、功耗低、功能强、性价比高、易于推广应用的优点,在自动化装置、智能仪器表、过程控制、通信、家用电器等许多领域得到日益广泛的应用[2],因此具有很大的研究价值。
2 单片机介绍
单片机是一种集成在电路芯片,是采用超大规模集成电路技术把具有数据处理能力的中央处理器CPU、随机存储器RAM、只读存储器ROM、多种I/O口和中断系统、定时器/计时器等功能(可能还包括显示驱动电路、脉宽调制电路、模拟多路转换器、A/D转换器等电路)集成到一块硅片上构成的一个小而完善的计算机系统[3]。由于单片机的这种结构形式及它所采取的半导体工艺[4],使其具有很多显著的特点,因而在各个领域都得到了迅猛的发展。单片机主要有如下特点[5]:(1)性价比高;(2)集成度高、体积小、可靠性强。机把各功能部件集成在一块芯片上,内部采用总线结构,减少了各芯片之间的连线,大大提高了单片机的可靠性与抗干扰能力。另外,其体积小,对于强磁场环境易于采取屏蔽措施,适合在恶劣环境下工作;(3)控制功能强;(4)功耗小、电压低、便于生产的携式产品。;(5)外部总线采用串行总线连接,以此缩小了体积;(6)单片机的系统扩展和系统配置典型、规范,容易构成各种规模的应用系统。
3 电子时钟硬件设计 3.1 系统方案的确定
硬件电路是一个系统的重要部分,在本次设计中主要是以AT89C51为核心控制器,外加一些控制电路来实现电子时钟的基本功能。单片机芯片作为控制系统的核心部件,它除了具备微机CPU的数值计算功能外,还具有灵活强大的控制功能,以便实时检测系统的输入量、控制系统的输出量,实现自动控制[6],外围控制电路主要包括晶振电路模块、复位电路模块、按键电路模块以及数码管显示电路模块,通过这些控制电路的连接构成完整的电路,其结构框图如图1所示。
图1 电子时钟系统结构图
3.2功能分析
1.准确计时,以数字形式显示时、分、秒的时间;2. 小时的计时为24小时制,分和秒的计时要求为60进位;3. 八位数码管 显示HH-MM-SS(时分秒),按键"模式键"依次选择调整"时","分","秒", 按键"加键"依次加1,按键"减键"依次减1 ;4.晶振电路起到减小误差,提高精确度的作用;5.复位电路是对单片机的初始化操作。
3.3电子时钟设计原理
电子时钟的实现一般有两种方法:其一是直接用单片机的定时计数器产生固定时间,这种方法的优点是可以省去一些外围的芯片,其缺点是只能适用于一些要求不是十分精确、不作长期保留的场合;而对于要求较高的场合,则必须选用专用的芯片[7],本设计采用的是第一种方法。
直接用单片机的定时计数器产生固定时间,这种方法的工作原理是利用单片机芯片的定时器产生固定时间,模拟时钟的时、分、秒。基于这一原理构成的电子时钟系统主要由以下几部分组成:89C51单片机控制器电路,按键开关电路,8位数码管显示电路,复位电路,晶振电路五部分构成。其工作原理电路图如图2所示。
图2 电子时钟设计原理图
3.3.1键盘控制电路
电子时钟最基本的功能除了能正常显示时间外,还需要对时间进行设置和调整,所以要配以相应的键盘控制电路。该设计的键盘控制电路主要包括8个按键: P1.0控制系统时间暂停,P1.4控制系统时间继续;P1.1、P1.2、P1.3作为增加时分秒调整时按键,P1.5、P1.6、P1.7作为增加时分秒调整时按键。键盘控制电路的硬件连接图如图3所示。
图3 键盘控制电路
3.3.2晶振电路
晶振的全称叫晶体振荡器,它在单片机系统里作用非常大,主要作用是产生单片机所需的时钟频率,单片机执行程序所需的时间完全取决于单片机晶振所提供的时钟频率,时钟频率越高,那么单片机运行速度就越快[8]。在通常工作条件下,普通的晶振频率绝对精度可达百万分之五十。高级的精度更高。有些晶振还可以由外加电压在一定范围内调整频率,称为压控振荡器(VCO)。晶振用一种能把电能和机械能相互转化的晶体在共振的状态下工作,以提供稳定,精确的单频振荡。晶振电路如图4所示。
图4 晶振电路
3.3.3复位电路
复位是单片机的初始化操作。单片机启动运行时,都需要先复位,其作用是使CPU和系统中其他部件处于一个确定的初始状态,并从这个状态开始工作。因而,复位是一个很重要的操作方式。 当MCS-5l系列单片机的复位引脚RST(全称RESET)出现2个机器周期以上的高电平时,单片机就执行复位操作:07H写入堆栈指针SP,P0口---P3口均置1,程序计数器PC和其他特殊功能寄存器SFR全部清零。只要RST持续为高电平,单片机就处于循环复位状态[9]。
单片机的复位方式有上电自动复位和手工复位两种,本设计采用的是手动复位方式,其电路图如图5所示。
图5 复位电路
3.3.4数码显示电路
发光二极管显示器驱动(点亮)的方法有两种。一种是静态驱动法,即给欲点亮的LED通以恒定的定流。这种驱动方法要有寄存器,译码器,驱动电路等逻辑部件。当需要显示的位数增加时,所需的逻辑部件及连线也相应增加,成本也增加。另一种是动态驱动方法,这种方法是给欲点亮的LED通过通以电流,此时LED的亮度是通断的平均亮度。为保证亮度,通过LED的脉冲电流应数倍于其额定电流值。利用动态驱动法可以减少需要的逻辑部件和连线,单片机应用系统中常采用动态驱动法[10]。数码管有两种接法即共阳极接法和共阴极接法。所谓共阳共阴,是针对数码管的公共脚而言的。一个1位典型的数码管,一般有10个脚,8个段码(7段加1个小数点),剩下两个脚接在一起。共阳指的是公共脚是正极(阳极),所有的段码实际上是负极,当某一个或某几个段码位接低电平,公共脚接高电平时,对应的段码位就能点亮,进而组合形成我们看到的数字或字母。共阴刚好相反,也就是公共脚是负极(阴极),段码位是阳极,当公共脚接地,段码位接高电平时,对应段码位点亮,本次设计选择共阴极数码管,其中有6位显示"时","分","秒",剩下两位显示"---"数码管A~DP接单片机P0端口用于段选,1~9接单片机P2端口用于位选。各个段码实际上是一个发光二极管,既然是发光二极管,就有正负极,为了防止驱动数码管电流过大而损坏,各端口接1K电阻。8位共阴极LED数码显示电路如图6所示。
图6 八位8段共阴极LED数码显示
4.电子时钟的软件设计 4.1程序设计内容
单片机软件设计主要包括执行软件(完成各种实质性功能)的设计和监控软件的设计。设计步骤如下所示。
- 采用模块化程序结构设计软件,首先将整个软件分成若干功能模块;
- 根据流程图,编写源程序;
- 上机调试各模块程序;
- 与硬件一起联调,最后完成全部调试工作。
4.2源程序
- #include<reg52.h>
- /*共阴数码管编码*/
- unsigned char code tab1[]={
- 0x3f,0x06,0x5b,0x4f,0x66,
- 0x6d,0x7d,0x07,0x7f,0x6f};
- /*共阳数码管编码
- unsigned char code tab1[]={
- 0xc0,0xf9,0xa4,0xb0,
- 0x99,0x92,0x82,0xf8,
- 0x80,0x90,0x88,0x83,
- 0xc6,0xa1,0x86,0x8e};
- */
- /*位选编码*/
- unsigned char code tab2[]={
- 0xfe,0xfd,0xfb,0xf7,
- 0xef,0xdf,0xbf,0x7f};
- sbit duanxuan=P1^0;
- /*按键位定义*/
- sbit key0=P1^0;
- sbit key1=P1^1;
- sbit key2=P1^2;
- sbit key3=P1^3;
- sbit key4=P1^4;
- sbit key5=P1^5;
- sbit key6=P1^6;
- sbit key7=P1^7;
- /*秒、分、时的初始化*/
- unsigned char tt=0;
- unsigned char miao=0;
- unsigned char fen=0;
- unsigned char shi=0;
- /*延时函数*/
- void delay(unsigned char t)
- {
- unsigned i;
- while(t--)
- for(i=0;i<75;i++);
- }
- /*定时器0初始化函数*/
- void chushihua()
- {
- TMOD=0x01;
- EA=1;
- ET0=1;
- TH0=(65535-50000)/256;
- TL0=(65535-50000)%256;
- TR0=1;
- }
- /*时分秒处理函数*/
- void timedeal()
- {
- if(miao==60)
- {
- miao=0;
- fen++;
- if(fen==60)
- {
- fen=0;
- shi++;
- if(shi==24)
- {
- shi=0;
- }
- }
- }
- }
- /*显示函数*/
- void display()
- {
- P2=tab2[0];
- P0=tab1[miao%10];
- delay(1);
- P0=0x00;//消影
- P2=tab2[1];
- P0=tab1[miao/10];
- delay(1);
- P0=0x00;//消影
- P2=tab2[2];
- P0=0x40;
- delay(1);
- P0=0x00;//消影
- P2=tab2[3];
- P0=tab1[fen%10];
- delay(1);
- P0=0x00;//消影
- P2=tab2[4];
- P0=tab1[fen/10];
- delay(1);
- P0=0x00;//消影
- P2=tab2[5];
- P0=0x40;
- delay(1);
- P0=0x00;//消影
- P2=tab2[6];
- P0=tab1[shi%10];
- delay(1);
- P0=0x00;//消影
- P2=tab2[7];
- P0=tab1[shi/10];
- delay(1);
- P0=0x00;//消影
- }
- /*按键设定函数*/
- void sheding()
- {
- if(key0==0)
- {
- delay(10);
- if(key0==0)
- {
- EA=0;
- }
- }
- if(key1==0)
- {
- delay(10);
- if(key1==0)
- {
- miao++;
- if(miao==60)
- miao=0;
- while(!key1);
- }
- }
- if(key2==0)
- {
- delay(10);
- if(key2==0)
- {
- fen++;
- if(fen==60)
- fen=0;
- while(!key2);
- }
- }
- if(key3==0)
- {
- delay(10);
- if(key3==0)
- {
- shi++;
- if(shi==24)
- shi=0;
- while(!key3);
- }
- }
- if(key5==0)
- {
- delay(10);
- if(key5==0)
- {
- miao--;
- if(miao==0)
- miao=59;
- while(!key5);
- }
- }
- if(key6==0)
- {
- delay(10);
- if(key6==0)
- {
- fen--;
- if(fen==0)
- fen=59;
- while(!key6);
- }
- }
- if(key7==0)
- {
- delay(10);
- if(key7==0)
- {
- shi--;
- if(shi==0)
- shi=23;
- while(!key7);
- }
- }
- if(key4==0)
- {
- delay(10);
- if(key4==0)
- {
- EA=1;
- }
- }
- }
- /*主函数*/
- void main()
- {
- chushihua();
- while(1)
- {
- sheding();
- timedeal();
- display();
- }
- }
- /*定时器0中断函数*/
- void time0() interrupt 1
- {
- TH0=(65535-50000)/256;
- TL0=(65535-50000)%256;
- tt++;
- if(tt==20)
- {
- tt=0;
- miao++;
- }
- }