找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 9517|回复: 10
打印 上一主题 下一主题
收起左侧

单片机实现的数字钟(C51)

  [复制链接]
跳转到指定楼层
楼主
ID:76190 发表于 2015-4-5 16:05 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
一:电路原理和器件选择
制作电路:单片机(AT89S52)实现多功能数字钟
性能指标:该数字钟实现时钟运行,调整,倒计时,秒表功能,且精确度经调试一天的误差在2S内。

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

电路主要模块及原理图:
1.数码显示硬件驱动

数码管驱动电路

2.单片机最小系统:

单片机最小系统

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

LED及单片机电源

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

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


主要元器件选择:
单片机:AT89S52采用市场上比较常用的AT89S52,这里采用AT89S52而不是AT89S51是为了最大限度减小误差,因为要实现多功能(例如秒表,时钟,倒计时)为了相互之间不干扰而要用到3个定时/计数器,而51系列只有2个,而52系列有3个,故采用52系列
三极管:用来进行数码管显示的位选,这里采用PNP管
数码管:采用共阳级四位数码管
晶振:采用的是11.0592MHZ的晶振
电源部分:采用5V电压供电,采用的是L7805稳压芯片供电(加滤波)
电阻:大部分时限流电阻,阻值为4.7K或10K,1K

端口分配及连接:
P0:LED数码管显示内容通过P1口从单片机传送到数码管
P2.4-P2.7:数码管位选控制端口
P2.0-P2.3:分别连接开关K0,K1,K2,K3通过不同的组合实现外部控制程序状态
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秒到
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏5 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:43559 发表于 2015-4-7 19:29 | 只看该作者
不错。感谢分享。
回复

使用道具 举报

板凳
ID:79866 发表于 2015-5-13 16:08 | 只看该作者
大神,能搞一个89C51的出来么?
回复

使用道具 举报

地板
ID:79866 发表于 2015-6-2 19:49 | 只看该作者
程序好像不全啊!!!!可惜可惜!!!!
回复

使用道具 举报

5#
ID:69319 发表于 2015-7-4 14:55 | 只看该作者
程序不全啊
回复

使用道具 举报

6#
ID:86421 发表于 2015-10-12 21:21 | 只看该作者
安装上不好用呀
回复

使用道具 举报

7#
ID:94340 发表于 2015-11-1 19:43 | 只看该作者
再加点功能就好了
回复

使用道具 举报

8#
ID:27825 发表于 2015-11-7 10:44 | 只看该作者

大神,能搞一个89C51的出来么?
回复

使用道具 举报

9#
ID:44267 发表于 2015-11-17 08:17 | 只看该作者
非常受欢迎的东西
回复

使用道具 举报

10#
ID:434615 发表于 2018-11-27 22:47 | 只看该作者
您好,您的那个单片机数字钟程序不全呀,能不能发下完整的
回复

使用道具 举报

11#
ID:434615 发表于 2018-11-27 22:48 | 只看该作者
您好,您的那个单片机数字钟程序不全呀,能不能发下完整的
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表