找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 7901|回复: 6
收起左侧

AT89C51单片机数字电子钟的设计

[复制链接]
ID:732702 发表于 2020-4-19 14:48 | 显示全部楼层 |阅读模式
一、 设计目的与要求
设计目的:通过设计,培养运用已学知识解决实际问题的能力、查阅资料的能力、自学能力和独立分析问题、解决问题的能力和能通过独立思考。
设计要求:设计一个时、分可调的数字电子钟、断电后将数据保存,开启后时间将从断电后时间继续行走。
二、 设计内容与方案制定
具有校时功能,按键控制电路其中时键、分键六个键分别控制时、分时间的调整。按下小时数实现对小时数加减,按下分钟数实现对分钟数进行加减,并设置有复位键,启始键。
以AT89C51单片机进行实现秒、分、时上的正常显示和进位,其中显示功能由单片机控制共阴极数码管来实现,数码管进行动态显示。
通过AT24C02分别写入时、分、秒数据在断电后实现保存,在下次通电后将数据读出保持为断电前数据。
三、 芯片简介1、 AT89C52
AT89C52是一个低电压,高性能CMOS8位单片机,片内含8k bytes的可反复擦写的Flash只读程序存储器和256 bytes的随机存取数据存储器(RAM),器件采用ATMEL公司的高密度、非易失性存储技术生产,兼容标准MCS-51指令系统,片内置通用8位中央处理器和Flash存储单元,AT89C52单片机在电子行业中有着广泛的应用。
AT89C52有40个引脚,32个外部双向输入/输出(I/O)端口,同时内含2个外中断口,3个16位可编程定时计数器,2个全双工串行通信口,2 个读写口线,AT89C52可以按照常规方法进行编程,也可以在线编程。其将通用的微处理器和Flash存储器结合在一起,特别是可反复擦写的 Flash存储器可有效地降低开发成本。
AT89C52为8 位通用微处理器,采用工业标准的C51内核,在内部功能及管脚排布上与通用的8xc52 相同,其主要用于会聚调整时的功能控制。功能包括对会聚主IC 内部寄存器、数据RAM及外部接口等功能部件的初始化,会聚调整控制,会聚测试图控制,红外遥控信号IR的接收解码及与主板CPU通信等。主要管脚有:XTAL1(19 脚)和XTAL2(18 脚)为振荡器输入输出端口,外接12MHz 晶振。RST/Vpd(9 脚)为复位输入端口,外接电阻电容组成的复位电路。VCC(40 脚)和VSS(20 脚)为供电端口,分别接+5V电源的正负端。P0~P3 为可编程通用I/O 脚,其功能用途由软件定义,在本设计中,P0 端口(32~39 脚)被定义为N1功能控制端口,分别与N1的相应功能管脚相连接,13 脚定义为IR输入端,10 脚和11脚定义为I2C总线控制端口,分别连接N1的SDAS(18脚)和SCLS(19脚)端口,12 脚、27 脚及28 脚定义为握手信号功能端口,连接主板CPU的相应功能端,用于当前制式的检测及会聚调整状态进入的控制功能。
2、 AT24C02
AT24C02支持I2C,总线数据传送协议I2C,总线协议规定任何将数据传送到总线的器件作为发送器。任何从总线接收数据的器件为接收器。数据传送是由产生串行时钟和所有起始停止信号的主器件控制的。主器件和从器件都可以作为发送器或接收器,但由主器件控制传送数据(发送或接收)的模式,由于A0、A1和A2可以组成000~111八种情况,即通过器件地址输入端A0、A1和A2可以实现将最多8个AT24C02器件连接到总线上,通过进行不同的配置进行选择器件。
AT24C02的存储容量为2K bit,内容分成32页,每页8Byte,共256Byte,操作时有两种寻址方式:芯片寻址和片内子地址寻址。
(1)芯片寻址:AT24C02的芯片地址为1010,其地址控制字格式为1010A2A1A0R/W。其中A2,A1,A0可编程地址选择位。A2,A1,A0引脚接高、低电平后得到确定的三位编码,与1010形成7位编码,即为该器件的地址码。R/W为芯片读写控制位,该位为0,表示芯片进行写操作。
(2)片内子地址寻址:芯片寻址可对内部256B中的任一个进行读/写操作,其寻址范围为00~FF,共256个寻址单位。

四、 设计步骤

1.2.各单元电路及工作原理
(1)按键控制电路   
键盘可实现对时间的校对,用四个按键来实现。按下小时数加实现对小时数进行加一,按下小时数减实现对小时数减一,按下分钟数加一实现对分钟数加一,按下分钟数减一实现对分钟数减一。当按下复位键时时间回到初始时间,按下启停键时时钟开始工作在次按下停止工作。
其电路连接图如下:

C7I8KUEA5T}7EYLE3N2K`88.png

LED显示器是现在最常用的显示器之一发光二极管(LED)分段式显示器由7条线段围成8字型,每一段包含一个发光二极管。外加正向电压时二极管导通,发出清晰的光。只要按规律控制各发光段亮、灭,就可以显示各种字形或符号。显示电路显示模块需要实时显示当前的时间,即时、分、秒,因此需要6个数码管,采用动态显示方式显示时间,其硬件连接方式如下图所示。
(3)AT24C02连接电路

AT24C02支持I2C,总线数据传送协议I2C,总线协议规定任何将数据传送到总线的器件作为发送器。任何从总线接收数据的器件为接收器。数据传送是由产生串行时钟和所有起始停止信号的主器件控制的。通过AT24C02分别写入时、分、秒数据在断电后实现保存,在下次通电后将数据读出保持为断电前数据。
1.3.绘制原理图
   其计时周期为24小时,显示满刻度为23时59分59秒。整个设计图由复位电路、AT89C51单片机、键盘控制电路组成。  显示电路将“时”、“分”、“秒”通过七段显示器显示出来,6个数码管的段选接到单片机的P0口,位选接到单片机的P2口。数码管按照数码管动态显示的工作原理工作。  把定时器定时时间设为50ms,则计数溢出20次即得时钟计时最小单位秒,而20次计数可用软件方法实现,每累计60秒进1分,每累计60分钟,进1小时。时采用24进制计时器,可实现对一天24小时的累计。 校时电路时用来对“时”、“分”显示数字进行校对调整,时分秒三个控制键分别接单片机的p3.2、p3.3、P3.4、P3.5进行控制。按一下分键秒单元就加1 ,按一下时键分就加1。将AT24C02接入P3.1和P3.2对断电后数据保存,通电后数据从断电前恢复运行。

1.4.元件清单列表
  
单片机
  
AT89C51
*1
数码管
7SEG-MPX8-CA-BLUE
*1
三极管
NPN
*8
按钮
BUTTON
*6
上位排阻
RESPACK-8
*1
EEPROM
AT24C02
*1


2、程序设计2.1程序流程
   数字电子钟采用内部硬件定时器来进行定时。sec等于60,应将sec清零,同时min加1。如果min等于60,应将min清零,同时h加1。如果h大于23时,应将h清零,当h小于10时十位不显示。通过分析可知,程序中可分别由
{

num2=0;

       sec++;
         if(sec==60)
       {
          sec=0;
           min++;
              if(min==60)
       {
         min=0;
          h++;
          if(h==24)
           h=0;
        }
       }
    }
这段程序负责秒、分、时的计时。
   按钮K1、K2和K3、K4为调时、调分控制按键。这两个按钮信号的输入采用外部中断方式来实现。若产生外部中断时,通过调用H或_min来实现调时或调分操作。通过displays()显示时分秒中间用“-”隔开每隔一秒实现闪烁。
       断电后数据保存,通过AT24C02芯片采用IIC串口通信解决掉电保护,具体将时、分、秒,数据每隔一秒时间将数据写入AT24C02中,在断电后数据停留在断电前,通电后数据恢复。
2.2主程序:
void main()
{
    init();
    sec=read_add(0);
    if(sec>60)
        sec=0;
    min=read_add(1);
    if(min>60)
        min=0;
    h=read_add(2);
    if(h>24)
        h=0;
      if(write==1)
      {
        write=0;
       write_add(0,sec);
       write_add(1,min);
       write_add(2,h);
       }   
      }     

}
  在主程序中先将读出保存数据分别赋给h、min、sec然后判断计时器是否到了一秒,如果到了就在24C02的地址0中写入sec在地址1中写入min在地址2中写入h。最终实现数据断电的保存。

2.2.源程序:
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
Ucharcode tab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
bit write=0;
sbit key1=P3^2;
sbit key2=P3^3;
sbit key3=P3^4;
sbit key4=P3^5;
sbit key5=P3^6;
sbit key6=P3^7;
sbit sda=P3^1;
sbit scl=P3^0;
void delayms(uint);
void display();
sbit key=P3^2;
ucharnum2,secshi,secge,minshi,minge,hshi,hge;
uchar mun=0,sec=0,min=20,h=5;
void displays();
void keyscan();
void delay()
{;;}
void start()
{
    sda=1;
    delay();
    scl=1;
    delay();
    sda=0;
    delay();
}

void stop()
{
    sda=0;
    delay();
    scl=1;
    delay();
    sda=1;
    delay();
}

void respons()
{
    uchari;
    scl=1;
    delay();
    while((sda==1)&&(i<250))
    i++;
    scl=0;
    delay();
}
void init()
{
    sda=1;
    delay();
    scl=1;
    delay();
}

void write_byte(uchar date)
{
    uchari,temp;
    temp=date;
    for(i=0;i<8;i++)
    {
       temp=temp<<1;
       scl=0;
       delay();
       sda=CY;
       delay();
       scl=1;
       delay();
    }
    scl=0;
    delay();
    sda=1;
    delay();
}

uchar read_byte()
{
    uchari,k;
    scl=0;
    delay();
    sda=1;
    delay();
    for(i=0;i<8;i++)
    {
       scl=1;
       delay();
       k=(k<<1)|sda;
       scl=0;
       delay();
    }
    returnk;
}

void write_add(ucharaddress,uchar date)
{
    start();
    write_byte(0xa0);
    respons();
    write_byte(address);
    respons();
    write_byte(date);
    respons();
    stop();

    start();
    write_byte(0xa1);
    respons();
    write_byte(address);
    respons();
    write_byte(date);
    respons();
    stop();

    start();
    write_byte(0xa2);
    respons();
    write_byte(address);
    respons();
    write_byte(date);
    respons();
    stop();
}

uchar read_add(uchar address)
{
    uchardate;
    start();
    write_byte(0xa0);
    respons();
    write_byte(address);
    respons();
    start();
    write_byte(0xa1);
    respons();
    date=read_byte();
    stop();
    start();
    write_byte(0xa2);
    respons();
    write_byte(address);
    respons();
    start();
    write_byte(0xa3);
    respons();
    write_byte(address);
    respons();
    returndate;
}

void main()
{
    init();
    sec=read_add(0);
    if(sec>60)
        sec=0;
    min=read_add(1);
    if(min>60)
        min=0;
    h=read_add(2);
    if(h>24)
        h=0;

TMOD=0x01;
EA=1;
ET0=1;
TH0=(65536-45872)/256;
TL0=(65536-45872)%256;
TR0=1;
while(1)
{

      displays();
      display();
      if(write==1)
      {
        write=0;
       write_add(0,sec);
       write_add(1,min);
       write_add(2,h);

       }

        keyscan();   
      }     

  }

void displays()
{  
if(num2==0)
{
    P2=0xdb;
    P0=0x40;
    delayms(2);
   }
}

void display( )
{
      secshi=sec/10;
      secge=sec%10;
      minshi=min/10;
      minge=min%10;
      hshi=h/10;
      hge=h%10;

      P2=0xbf;
      P0=tab[secshi];
      delayms(2);
      P2=0x7f;
      P0=tab[secge];
      delayms(2);

      P2=0xf7;
      P0=tab[minshi];
      delayms(2);
      P2=0xef;
      P0=tab[minge];

      delayms(2);
      P2=0xfe;
      P0=tab[hshi];
      delayms(2);
      P2=0xfd;
      P0=tab[hge];
      delayms(2);
}

void delayms(uint xms)
{
    uintx,y;
   for(x=xms;x>0;x--)
    for(y=110;y>0;y--);
    }

void keyscan()
{
    if(key1==0)
    {
       delayms(10);
       if(key1==0)
       {
           h++;
           if(h==24)
           {
              h=0;
           }
           while(!key1);
       }
    }

    if(key2==0)
    {
       delayms(10);
       if(key2==0)
       {
           h--;
           if(h==0)
           {
              h=24;
           }
           while(!key2);

       }
    }
    if(key3==0)
    {
       delayms(10);
       if(key3==0)
       {
           min++;
           if(min==60)
           min=0;
           while(!key3);
       }
    }

    if(key4==0)
    {
       delayms(10);
       if(key4==0)
       {
           if(min==0)
           min=60;
           min--;
           while(!key4);
       }
    }
    if(key5==0)
    {
        delayms(10);
       if(key5==0)
       {
           min=20;
           h=5;
           sec=0;
           while(!key5);
       }
    }
    if(key6==0)
    {
       delayms(10);
       if(key6==0)
       {
           while(!key6);
           TR0=~TR0;
       }
    }
}
void T0_time()interrupt 1
{
TH0=(65536-45872)/256;
TL0=(65536-45872)%256;
num2++;
if(num2==20)
{
       num2=0;
       sec++;
       write=1;
      if(sec==60)
       {
          sec=0;
           min++;
             if(min==60)
           {
             min=0;
              h++;
                 if(h==24)
                 {
                     h=0;
                  }
            }
       }

    }
}



实物图:

E8D7C52D074C60FA3A907A34D2429B2B.png

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:760481 发表于 2020-6-1 10:51 | 显示全部楼层
代码有问题
回复

使用道具 举报

ID:777643 发表于 2020-6-14 20:55 来自手机 | 显示全部楼层
这个是51的还是52的呀
回复

使用道具 举报

ID:785626 发表于 2020-6-21 14:08 | 显示全部楼层
代码错了
回复

使用道具 举报

ID:732702 发表于 2020-10-8 19:03 | 显示全部楼层

请问那一部分代码有问题?
回复

使用道具 举报

ID:732702 发表于 2020-10-8 19:04 | 显示全部楼层
1114019472 发表于 2020-6-14 20:55
这个是51的还是52的呀

AT89C52
回复

使用道具 举报

ID:732702 发表于 2020-10-8 19:05 | 显示全部楼层

请问,那一部分代码错了?
我运行时没有错误
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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