基于89c51的数码管时钟设计—两片74hc573

74HC573的八个锁存器都是透明的D型锁存器,当使能(G)为高时,Q输出将随数据(D)输入而变。当使能为低时,输出将锁存在已建立的数据电平上。输出控制不影响锁存器的内部工作,即老数据可以保持,甚至当输出被关闭时,

新的数据也可以置入。这种电路可以驱动大电容或低阻抗负载,可以直接与系统总线接口并驱动总线,而不需要外接口。特别适用于缓冲寄存器,I/O通道,双向总线驱动器和工作寄存器。

功能简介:本设计采用两片74hc573芯片,共同驱动8段数码管,89c51作为主控芯片,达到显示24小时可调节功能,小时24小时置0,分钟秒针60置0;同时设置三个按键,按键一控制时钟暂停与继续,按键二和按键三共同完成时间的调节;

主控芯片:89c51

数码管驱动:两片74hc573

仿真:Proteus 8 Professional

原理图:

源代码:

#include <reg52.h>
sbit wei=P2^0;//L2
sbit duan=P2^1;//L1
sbit SW1=P3^3;
sbit SW2=P3^4;
sbit SW3=P3^2;
int displayMode = 0; // 0 - 显示秒,1 - 显示分,2 - 显示时
int lastSW1State = 1; // 上次SW1的状态,用于检测变化
int lastSW2State = 1; // 上次SW2的状态,用于检测变化
volatile int clockPaused = 0; // 0 - 未暂停,1 - 暂停,声明为volatile是因为它在中断中会被修改
void Delay_ms(unsigned int n)

{
	unsigned int i,j;
	for(i=n;i>0;i--)
		for(j=114;j>0;j--);
}
int b=0;
void int0_handler() interrupt 0
{
    b=++b;
    while (SW3 == 0); // 简单防抖,等待按键释放
}


unsigned char tab[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
unsigned char weitab[]={0x10,0x20,0x40,0x80,0x01,0x02,0x04,0x08};
unsigned char smgtab[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x80,0xff,0x00,0x40};	  //0~9  .  全亮  全灭    -:0x40
int hour=10,min=01,sec=59,time_1s=0,inter=0;
void time0() interrupt 1
{
    TH0=(65536-2000)/256;
    TL0=(65536-2000)%256;
    inter++;   
    if(inter == 500)   //1s执行一次,且时钟未暂停
    {
        inter = 0;
        time_1s++;
        if(time_1s==2)
            time_1s=0;
        sec++;
        if(sec >= 60)
        {
            sec = 0;
            min++;
            if(min >= 60)
            {
                min = 0;
                hour++;
                if(hour >= 24)
                {
                    hour = 0;
                }
            }
        }
    }                    
}
void Init_TIME0(void)
{
    TMOD |= 0x01;
    TH0 = (65536 - 2000) / 256;
    TL0 = (65536 - 2000) % 256;
    EA = 1; // 开启总中断
    ET0 = 1; // 开启定时器0中断
    EX0 = 1; // 开启外部中断0
    IT0 = 1; // 设置INT0为下降沿触发
    
}
int a=1;
int main(void)
{
	int i=0,j=0;
	Init_TIME0(); // 初始化定时器和中断
    IT0 = 1; // 确保在启动定时器前设置中断模式
    EX0 = 1; // 确保外部中断启用
    EA = 1; // 再次确认总中断已开启

	while(1)
	{	
			TR0=a;
			if(b%2==1)
				{
					a=0;
				}
				else {a=1;}	
				
					if(SW1 != lastSW1State && SW1 == 0) // 当SW1由高变低时
        {
										a=0;
            displayMode = (displayMode + 1) % 3; // 循环切换显示模式
            Delay_ms(20); // 等待按键释放,防抖动
        }
        lastSW1State = SW1; // 更新SW1上次状态

        // 检测SW2状态变化以增加相应时间单位
        if(SW2 != lastSW2State && SW2 == 0) // 当SW2由高变低时
        {
            switch (displayMode)
            {
                case 0: // 如果显示秒
                    sec++;
										a=1;
                    if(sec > 59) sec = 0; // 秒加到59清零
                    break;
                case 1: // 如果显示分
                    min++;
										a=0;
                    if(min > 59) {min = 0; hour++;} // 分加到59清零并加时
                    if(hour > 23) hour = 0; // 时加到23清零
                    break;
                case 2: // 如果显示时
                    hour++;
										a=0;
                    if(hour > 23) hour = 0; // 时加到23清零
                    break;
            }
            Delay_ms(20); // 等待按键释放,防抖动
					
        }
        lastSW2State = SW2; // 更新SW2上次状态
   
if(displayMode == 0) // 显示秒
      {
				
				
          P1=smgtab[12]; 
					duan=1;
					duan=0;

					P1=~weitab[2]; 
					wei=1;
					wei=0;
		
					P1=smgtab[sec/10]; 
					duan=1;
					duan=0;
					Delay_ms(1);

					P1=smgtab[12]; 
					duan=1;
					duan=0;

					P1=~weitab[3]; 
					wei=1;
					wei=0;

					P1=smgtab[sec%10]; 
					duan=1;
					duan=0;
					Delay_ms(1); 
					
					
  }
else if(displayMode == 1) // 显示分
					{
            
					P1=smgtab[12]; 
					duan=1;
					duan=0;

					P1=~weitab[7]; 
					wei=1;
					wei=0;
		
					P1=smgtab[min/10]; 
					duan=1;
					duan=0;
					Delay_ms(1);
	
					P1=smgtab[12]; 
					duan=1;
					duan=0;

					P1=~weitab[0]; 
					wei=1;
					wei=0;

					P1=smgtab[min%10]; 
					duan=1;
					duan=0;
					Delay_ms(1);
				}
else if(displayMode == 2) // 显示时
     {
					P1=smgtab[12]; 
					duan=1;
					duan=0;			

					P1=~weitab[4]; 
					wei=1;
					wei=0;
		
					P1=smgtab[hour/10]; 
					duan=1;
					duan=0;
					Delay_ms(1);

				
					P0=smgtab[12]; 
					duan=1;
					duan=0;

					P1=~weitab[5]; 
					wei=1;
					wei=0;

					P1=smgtab[hour%10]; 
					duan=1;
					duan=0;
					Delay_ms(1);
      }
	{
		  {
				
				
          P1=smgtab[12]; 
					duan=1;
					duan=0;

					P1=~weitab[2]; 
					wei=1;
					wei=0;
		
					P1=smgtab[sec/10]; 
					duan=1;
					duan=0;
					Delay_ms(1);

					P1=smgtab[12]; 
					duan=1;
					duan=0;

					P1=~weitab[3]; 
					wei=1;
					wei=0;

					P1=smgtab[sec%10]; 
					duan=1;
					duan=0;
					Delay_ms(1); 
					
					
  }
		{
            
					P1=smgtab[12]; 
					duan=1;
					duan=0;

					P1=~weitab[7]; 
					wei=1;
					wei=0;
		
					P1=smgtab[min/10]; 
					duan=1;
					duan=0;
					Delay_ms(1);
	
					P1=smgtab[12]; 
					duan=1;
					duan=0;

					P1=~weitab[0]; 
					wei=1;
					wei=0;

					P1=smgtab[min%10]; 
					duan=1;
					duan=0;
					Delay_ms(1);
				}
		
		    {
					P1=smgtab[12]; 
					duan=1;
					duan=0;			

					P1=~weitab[4]; 
					wei=1;
					wei=0;
		
					P1=smgtab[hour/10]; 
					duan=1;
					duan=0;
					Delay_ms(1);

				
					P0=smgtab[12]; 
					duan=1;
					duan=0;

					P1=~weitab[5]; 
					wei=1;
					wei=0;

					P1=smgtab[hour%10]; 
					duan=1;
					duan=0;
					Delay_ms(1);
      }
			
			P1=smgtab[12]; 
		duan=1;
	   	duan=0;

		P1=~weitab[6]; 
		wei=1;
		wei=0;

	   P1=smgtab[13]; 
		duan=1;
	   	duan=0;
		Delay_ms(1);


		P1=smgtab[12]; 
		duan=1;
	   	duan=0;

		P1=~weitab[1]; 
		wei=1;
		wei=0;

	  P1=smgtab[13]; 
		duan=1;
	   	duan=0;
		Delay_ms(1);	
	}
		
    }
	
		
	}

代码存在繁琐重复,但可正常实现功能

  • 7
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值