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);
}
}
}
代码存在繁琐重复,但可正常实现功能