新闻  |   论坛  |   博客  |   在线研讨会
单片机实现的数字钟(C51)
tvb2058 | 2007-09-14 14:04:38    阅读:22606   发布文章

一:电路原理和器件选择

制作电路:单片机(AT89S52)实现多功能数字钟

性能指标:该数字钟实现时钟运行,调整,倒计时,秒表功能,且精确度经调试一天的误差在2S内。

 

实现原理:利用单片机定时器及计数器产生定时效果通过编程形成数字钟效果,再利用数码管动态扫描显示单片机内部处理的数据。同时通过端口读入当前外部控制状态来改变程序的不同状态,实现不同功能。

 

电路主要模块及原理图:

1.  数码显示硬件驱动

 数码管驱动电路

 

2.单片机最小系统:

单片机最小系统

 

3.LED及单片机电源原理图

LED及单片机电源

 

4.外部控制状态输入模块原理图

外部控制状态输入模块原理图

 

 

主要元器件选择:

单片机:AT89S52采用市场上比较常用的AT89S52,这里采用AT89S52而不是AT89S51是为了最大限度减小误差,因为要实现多功能(例如秒表,时钟,倒计时)为了相互之间不干扰而要用到3个定时/计数器,而51系列只有2个,而52系列有3个,故采用52系列

三极管:用来进行数码管显示的位选,这里采用PNP

数码管:采用共阳级四位数码管

晶振:采用的是11.0592MHZ的晶振

电源部分:采用5V电压供电,采用的是L7805稳压芯片供电(加滤波)

电阻:大部分时限流电阻,阻值为4.7K10K1K

 

端口分配及连接:

P0:LED数码管显示内容通过P1口从单片机传送到数码管

P2.4-P2.7:数码管位选控制端口

P2.0-P2.3:分别连接开关K0K1K2K3通过不同的组合实现外部控制程序状态

P1.0:蜂鸣器,倒计时完毕产生鸣响

P1.2-P1.5:四个发光二极管,显示当前时钟状态

 

完整的源程序如下:

附程序源代码及注释

 

#include <reg52.h>

#include <absacc.h>

#define  uint unsigned int

#define  uchar unsigned char

 

/*定义P2口各管脚*/

sbit K0=P2^2;

sbit K1=P2^1;

sbit K2=P2^0;

sbit K3=P2^3;

 

sbit D0=P2^4;

sbit D1=P2^5;

sbit D2=P2^6;

sbit D3=P2^7;

 

/*定义P1口各管脚*/

sbit beep=P1^0;

sbit L0=P1^5;

sbit L1=P1^4;

sbit L2=P1^3;

sbit L3=P1^2;

 

uchar data BUFFER[4]={0,0,0,0};    //显示缓冲区(依次从低位到高位,共四位数码管)

uchar data CLOCK[4]={0,0,0,0};     //存放时钟时间(依次是百分秒,秒,分,时)

uchar data SECOND[3]={0,0,0};      //存放秒表时间(依次时百分秒,秒,分)

uchar data SEVER[4]={0,0,0,0};     //存放倒计时时间(依次是百分秒,秒,分,时)

 

/*定义程序运行状态*/

uchar data STATE=0;

/*STATE=0;时钟运行*/

/*STATE=1;时钟分调整*/

/*STATE=2;未定义状态,可添加*/

/*STATE=3;时钟时调整*/

/*STATE=4;倒计时分调整*/

/*STATE=5;倒计时时调整*/

/*STATE=6;秒表*/

/*STATE=7;倒计时运行*/

 

/*定义辅助计时全局变量*/

uchar m=60;

 

/*共阳数码管显示"0"-"9","-" */

uchar code TABLE[]={0xC0,0xf9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x98,0xbf};

 

/*自定义子函数*/

void display();                         //显示函数

void delay();                           //显示延时函数

void intsvr();                          //调整时间时加1子函数

void delay10ms();                       //延时函数

 

/*主函数体*/

 

void main(void)

{

    EA=1;ET0=1;                          //开总中断源,开T0中断

    TMOD=0x61;                           //T1方式2计数,T0方式1计时

    TH0=-9460/256;TL0=-9460%256;         //初始化计数器初值

    TH1=0xff;TL1=0xff;                

    T2CON=0;TH2=-9452/256;TL2=-9452%256;

 

    K0=1;K1=1;K2=1;                      //初始化控制状态位

    STATE=P2&0x07;

 

    for(;;)

    {

        switch(STATE)

           {

            case 1:                      //时钟分调整程序

            {

                TR0=0;ET0=0;EX0=0;TR2=0; //关闭定时器,时钟停止运行,同时关闭外中断IT0

                         L3=0;L1=0;L2=0;L0=1;

                intsvr();                //调用加1函数

                         BUFFER[0]=CLOCK[2]%10;   //数码管显示分钟个位

                BUFFER[1]=CLOCK[2]/10;   //数码管显示分钟十位

                BUFFER[2]=10;            //显示""

                BUFFER[3]=10;            //显示""

            }break;

 

                  case 3:                      //时钟时调整程序

                  {

                      TR0=0;ET0=0;EX0=0;TR2=0; //关闭定时器,时钟停止运行

                         L3=0;L1=0;L2=0;L0=1;

                intsvr();                //调用加1函数

                         BUFFER[0]=CLOCK[2]%10;   //数码管显示分钟个位

                BUFFER[1]=CLOCK[2]/10;   //数码管显示分钟十位

                BUFFER[2]=CLOCK[3]%10;   //数码管显示时钟个位

                BUFFER[3]=CLOCK[3]/10;   //数码管显示时钟十位

                  }break;

 

                  case 4:                      //倒计时分钟调整程序

                  {

                      TR0=1;ET0=1;EX0=0;TR2=0; //保持T0正常运行,即时钟正常运行,同时关闭外中断IT0

                         L3=0;L2=0;L1=0;   

                intsvr();                //调用加1函数               

                         BUFFER[0]=SEVER[2]%10;   //数码管显示分钟个位

                BUFFER[1]=SEVER[2]/10;   //数码管显示分钟十位

                BUFFER[2]=10;            //显示""

                BUFFER[3]=10;            //显示""

               

                         SECOND[1]=0;             //秒表初始化为0

                              SECOND[2]=0;            

                  }break;

 

                  case 5:                      //倒计时时钟调整程序

                  {

                      TR0=1;ET0=1;EX0=0;TR2=0; //保持T0正常运行,即时钟正常运行,同时关闭外中断IT0

                         L3=0;L2=0;L1=0;    

                intsvr();                //调用加1子函数

                         BUFFER[0]=SEVER[2]%10;   //数码管显示分钟个位

                BUFFER[1]=SEVER[2]/10;   //数码管显示分钟十位

                BUFFER[2]=SEVER[3]%10;   //数码管显示时钟个位

                BUFFER[3]=SEVER[3]/10;   //数码管显示时钟十位

                        

                SECOND[1]=0;             //秒表初始化为0

                              SECOND[2]=0;

                  }break;

 

                  case 6:

                  { 

                         TR0=1;ET0=1;EX0=1;ET2=1;//保持T0正常运行,即时钟正常运行,同时开外中断IT0

                        

                         BUFFER[0]=SECOND[1]%10; //数码管显示秒表秒个位

                BUFFER[1]=SECOND[1]/10; //数码管显示秒表秒十位

                BUFFER[2]=SECOND[2]%10; //数码管显示秒表分个位

                BUFFER[3]=SECOND[2]/10; //数码管显示秒表分十位

                  }break;

 

                  case 7:

                  {

                         TR0=1;ET0=1;EX0=0;ET2=1;   //倒计时运行,同时时钟也正常运行,关闭外中断T0

                         if((SEVER[2]==0)&&(SEVER[3]==0))   //当预置时间(分,时)变为0时,计时完毕

                         {

                             beep=!beep;                    //蜂鸣器响

                             BUFFER[0]=10;                  //显示""

                             BUFFER[1]=10;

                             BUFFER[2]=10;

                             BUFFER[3]=10;

                    TR2=0;                         //关闭T2

                      }

                         else

                         {

                             TR2=1;                         //开启T2 

                         }

                         SECOND[1]=0;                       //秒表时间初始化

                              SECOND[2]=0;

                  }break;

   

               default:

               {

                ET0=1;TR0=1;EX0=0;                //开启T0,时钟运行,关闭外中断

                         L1=1;L3=1;L2=1;

               

                         BUFFER[0]=CLOCK[2]%10;            //数码管显示分钟个位

                BUFFER[1]=CLOCK[2]/10;            //数码管显示分钟十位

                BUFFER[2]=CLOCK[3]%10;            //数码管显示时钟个位

                BUFFER[3]=CLOCK[3]/10;            //数码管显示时钟十位  

                  }

        }

           K0=1;K1=1;K2=1;                           //重新预置状态位

           display();                                //调用显示函数

           STATE=P2&0x07;                            //通过P2口提取当前状态

    }

}

 

/*T0中断服务*/

 

void time0(void)   interrupt 1 using 1           //T0中断函数

{

    TH0=-9460/256;                               //计时器放入预置时间,大概10毫秒

    TL0=-9460%256;

    CLOCK[0]=CLOCK[0]+1;                         //一次中断加1

    if(CLOCK[0]==50)                             //0.5秒到

    {

        L0=!L0;                                  //L0取反

    }

    if(CLOCK[0]==100)                            //1秒到

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
haili0721  2012-02-28 21:02:19 

lz,能不能把您的完整代码发给我,对我的课程设计大有帮助. 我的邮箱:djxyy@hotmail.com

新手上道  2010-07-30 23:11:03 

楼主您好!可不可以把这个时钟设计的完整代码发送到我的邮箱里544691113@qq.com 。在此表示感谢!!

zj4272  2010-04-12 18:35:15 

很强啊,很适合我这种新手参考,博主能发我个完整的源码吗?谢谢了!邮箱:zj4272@hotmail.com

andy3123  2010-02-27 23:53:19 

你好,我编译过你在另一个地方发的完整程序,但有一个错误,请问可以发正确的完整程序我吗?我的邮箱是:LZD_jerry@163.com

limzhw  2009-06-05 20:21:21 

楼主,你好啊。我在做课程设计,希望能得到你的帮忙与指导。能给我你的完整源码与编译系统吗?先谢谢你啦。我的邮箱:limzhw@foxmail.com

幽灵  2009-05-12 15:04:29 

版主 能把完整的程序源代码发给我吗??十分感谢! snliunan@163.com

nu [ 匿名]  2008-11-06 17:05:03 

很实用。用keil编译不行,后面加了一段 { CLOCK[0]=0, CLOCK[1]++; } if(CLOCK[1]==60) //1分到..... 还不行 能提供完整的源程序吗?E-mail:numamoli@tom.com

HE [ 匿名]  2008-11-03 20:42:13 

HAO 好

[ 匿名]  2008-10-10 12:06:26 

谢谢

[ 匿名]  2008-09-03 19:40:08 

我的邮箱是xxf870127@163.com 谢谢

[ 匿名]  2008-09-03 19:39:18 

有汇编的吗?

dsu5566  2007-11-05 15:27:00 

对新手很有参考价值,能把完整的源程发给我吗? E-mail:dsu5566@163.com

推荐文章
最近访客