总体设计方案及组成原理

总体设计方案及组成原理
总体设计方案及组成原理

设计题目:电子时钟

专业班级:光电14101班学生学号:201411030114 学生姓名:贺舒怡

设计时间:2016.12.23

一、总体设计方案及组成原理

电子时钟主要实现的功能为:1、自动计时功能

2、能够显示时间

3、有校时功能,能对时间进行校准

针对上述功能我们在设计电子时钟时就主要需讨论计时、显示、调时三个功能的实现。

1、计时方案

我们可以利用单片机内部的两个定时/计数器T0和T1进行定时。它们的基本工作原理为:它们的本质就是一个二进制加1寄存器,当启动后就开始从所设定的计数初始值开始加1计数,寄存器计满回零时能自动产生溢出中断请求。

关于电子时钟实现定时功能的原理:当选择定时器工作方式时,对片内振荡器的12分频信号进行计数,实现定时;定时器的定时时间与系统的振荡频率有关,因为1个机器周期等于12个振荡周期,我们选择频率为12MHZ的晶振,其计数周期为1us。M1、M0两位构成工作方式控制位,它们不同的取值组合决定了工作方式的不同。C/T是是工作模式选择位,当取高电平为计数模式,取低电平时为定时模式。不同的工作方式决定了定时范围的不同,现假设最大计数值为M,那么各方式下的M值如下:方式0:M=8192;方式1:M=65536;方式2:M=256; 方式3:定时器0分为两个8位计数器,所以两个M均为256,因为定时/计数器是做“加1”计数,并在计满溢出时产生中断,因此初值X可以这样计算:

X=M-计数值。

2、显示方案

可以用比较常用的LED进行显示。

LED的显示方式分为静态显示和动态显示:

(1)静态显示方式

LED静态显示时,其公共端直接接地(共阴极)或接电源(共阳极),各段选线分别与I/O接口线相连。要显示字符,直接在I/O线发送相应的字断码,如下图所示:

两位数码管的静态显示

两个数码管的共阴极直接接地,如果要在第一个数码管上显示数字 1 ,只需在I/O(1)发送1的共阴极字码段;如果要在第二数码管上显示2,只需在I/O(2)发送2的字码段。

静态显示结构简单,显示方便,要显示某个字符,直接在I/O接口线上发送相应的字段码,但一个数码管需要8根I/O接口线,如果数码管个数少,用起来方便,但如果数码管数目较多时,往往采用动态显示方式。

(2)动态显示方式

LED动态显示是将所有的数码管的段选线并连在一起,用一个I/O接口控制,公共端不是直接接地(共阴极)或接电源电源(共阳极),而是通过相应的I/O接口线控制,如图2所示。图2是4位LED数码管动态显示连接图,4个数码管的段选线并接在一起,通过I/O(1)控制,它们的公共端不直接接地(共阴极)或电源(共阳极),每个数码管的公共端与一根I/O接口线相连,通过I/O(2)控制。设数码管为共阳极,它的工作过程为:第一步使右边第一个数码管的公共端D0为1,其余的数码管的公共端为0,同时在I/O(1)上发送第一个数码管的字段码,这时,只有右边第一个数码管显示,其余不显示;第二步使右边第二个数码管的公共端D1为1,其余的数码管的公共端为0,同时在I/O(1)上发送右边第二个数码管的字段码,这时,只有右边第二个数码管显示,其余不显示,依此类推,直到最后一个,这样4个数码管轮流显示相应的信息,一遍显示完毕,隔一段时间,又这样循环显示。从计算机的角度看,每个数码管隔一段时间才显示一次,但由于人的视觉暂留效应,只要时间足够短,循环的周期够快,每次达到24次以上,看起来数码管就一直稳定显示了,这就是动态显示的原理。而这个周期对于计算机来说很容易实现,所以在单片机中经常用到动态显示。

对于动态显示,计算机通常把显示一遍的处理过程编成子程序,每隔一段时间调

用一次。可以在主程序的循环中调用,每一次循环调用一次;也可以放在定时器中断服务程序中,定时计数器每隔一段时间中断一次,执行一次中断服务程序,相应地执行一次显示子程序。

3、调时方案

设定三个按键。一个按键充当控制键,控制是调时钟,还是调分钟,另外两个键充当加减键,对时分进行加减。调时方案可以在软件编程中实现。

二、系统设计

硬件电路设计

1、

软件计时LED数码管显示时钟在PROTEUS中的电路如下图所示:

其中单片机采用应用广泛的AT89C51,系统时钟采用12MHZ的晶振,8个数码管显示,小时与分钟与秒钟之间用短横线间隔,采用8个动态显示方式共阳极七段式数码管(7-SEG-MPX80-CA-BLUE),由于并口上没有连接其他的硬件电路,所以P0口直接作段选码输出端,P2口作为选码输出端。

采用简化按键方式,只设定3个开关K0、K1、和K2,通过P1口低3位相连。其中K0键为调时模式选择键,K1为加1键,K2为减1键。

2、软件计时数码管显示时钟的软件程序

软件系统程序由主程序和子程序组成,主程序包含初始化参数设置、按键处理、数码管显示模块等,在设计时,各个模块都采用子程序结构设计,在主程序中调用。时钟由定时/计数器0产生,采用中断方式工作,因此还要编写定时/计数器0中断服务子程序,在定时器/计数器0中断服务程序中形成时钟关系。

(1)主程序

主程序的执行流程如图A所示,主程序先对显示单元和定时器/计数器初始化,然后重复调用数码管显示模块和按键处理模块,当有键按下时,则转入相应的功能程序。

(2)数码管显示模块

本系统共用9个数码管,从左到右依次显示时十位、时个位、横线、分十位、分个位、横线、秒十位、秒个位。数码管显示的信息用8个内存单元存放,这8个内存单元称为数据缓冲区,其中秒个位

秒十位、分十位、分个位和分十位i、时个位和时十位分别由秒数据、分数据和小时数据分拆得到。

在本系统中,数码显示采用软件译码动态显示。在存储器中首先建立一张显示信息的字段码表,显示时,先在P2口送出位选码,选中显示的数码管,然后从显示缓冲区中取出当前显示的信息,在字码表中查出所显示的信息得字断码,从P0口输出,就能在相应的的数码管上显示出缓冲区的内容了。

定时/计数器T0中断服务程序

计时选择定时/计数器T0。具体处理如下:定时/计数器T0选择方式1,重复定时,定时时间设定为50MS,定时时间到则中断,在中断服务程序中用一个计数器对50MS计数,计20次则对秒单元加1,秒单元加到60则对分单元加1,同时秒单元清零;分单元加到60则对时单元加1,同时分单元清0;时单元加到24则对时单元清零,标志一天时间计满,这样就形成了时钟关系。在对各单元计数的同时,把它们的值存放到存储单元的指定位置。定时./计数器T0中断服务流程如图B.

按键处理模块

按键处理设置为:如没有按键,则时钟正常走时。当按K0键一次,时钟暂停走动,进入调小时状态,再按K0键一次,进入调分状态,再按K0键一次,回到正常走时;对于K1和K2按键,如果是正常走时,按K1和K2键不起作用,如果进入调时或调分状态,按K1键可对时或分进行加1操作,小时加到24则回到0,分加到60则回到0;按K2可对时或分进行减1操作,小时减到负则回到23,分减到负则回到59.按键处理模块的流程如图C

图A主程序流程

图B定时/计数器T0中断服务程序流程

图C按键处理模块流程

程序:

#include

#define char unsigned char

char code dis_7[12]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0xb2,0xf8,0x80,0x90,0xff,0xbf}; //共阳极LED数码管“0~9”、“灭”和“—”字段

char code scan_con[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};

//位选择码

char data dis[8]={0x00,0x00,0x0b,0x00,0x00,0x0b,0x00,0x00};

//显示缓冲区,时、分、秒初始为0,0Xb0为“—”的编码

char data timedata[3]={0x00,0x00,0x00};

//分别为秒、分和小时的值

char data ms50=0x00,con=0x00,con1=0x00,con2=0x00;

sbit key0 = p1^0;

sbit key1 = p1^1;

sbit key2 = p2^2;

delay1ms(int t)

{

int i,j;

for(i=0;i

for(j=0;j<120;j++);

}

//按键处理函数

keyscan()

{

EA=0;

if(key0==0)

{

delay1ms(10)

while(key0==0);

con++;TR0=0;ET=0;

if(con>=3)

{con=0;TR0=1;ET0=1;}

}

if(con!=0)

{

if(key1==0)

{

delay1ms(10);

while(key1==0);

timedata[con]++;

if(con==2)con1=24;else con1=60;

if(timedata[con]>=con1)

{ timedata[con]=0;}

}

}

if(con!=0)

{

if(key2==0)

{

delay1ms(10);

while(key2==0);

timedata[con]--;

if(con==2) con2=23;else con2=59;

if(timedata[con]<=0)

{timedata[con]=con2;}

}

}

EA=1;

}

//数码管显示函数

scan()

{

char k;

dis[0]=timedata[0]%10;dis[1]=timedata[0]/10;

dis[3]=timedata[1]%10;dis[4]=timedata[1]/10;

dis[6]=timedata[2]%10;dis[7]=timedata[2]/10;

for(k=0;k<8;k++)

{

p0=dis_7[dis[k]];p2=scan_con[k];delay1ms(1);p2=0xff; }

}

//主函数

main()

{

TH0=0x3c;TL0=0xb0;

TMOD=0x01;ET0=1;TR0=1;EA=1;

while(1)

{

scan();

keyscan();

}

}

//定时器/计数器T0中断服务函数

void time_intt0(void) interrupt 1

{

ET0=0;TR0=0;TH0=0x3c;TL0=0xb0;TR0=1;

ms50++;

if(ms50==20)

{

ms50=0x00;timedata[0]++;

if(timedata[0]==60)

{

timedata[0]=0;timedata[1]++;

if(timedata[1]==60)

{

timedata[1]=0;timedata[2]++;

if( timedata[2]==24)

{

timedata[2]=0;

}

}

}

}

ET0=1;

}

三、设计总结

这次设计,我通过查阅资料,自学知识,培养到了自己的自学能力,另外在设计程序的过程中,锻炼了自己的思维能力。设计出的时钟电路也实现了一定的的功能。但还是存在不足,比如时钟电路的功能太过简单,如果再让我改进,我会给它增加整点报时功能或者增加闹铃的功能。

相关主题
相关文档
最新文档