给你一个电路和程序,完全满足你的要求,共阳数码管,实际电路Q2、Q3要用PNP管才合理,位选a、b对调。图中用NPN管只是为了仿真。#include <reg51.h>
#define uint unsigned int
#define uchar unsigned char
#define key_S 300 //宏定义短按(约20ms)
#define key_L 6000 //宏定义长按(约2/3s)
#define key_M 3000 //宏定义长按(约1/3s)
sbit K1 = P1^1; //定时设置端口
sbit OUT= P1^0; //输出端口
sbit b=P3^1; //位选b端口
sbit a=P3^0; //位选a端口
uchar code table[]={ //共阳数码管段码0~f
0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,
0x80,0x90,0x88,0x83,
0xc6,0xa1,0x86,0x8e};
uint Cnt2ms=0; //定义2ms秒变量
uchar hour=8,min=59,sec=59; //定义时、分、秒变量
bit Twinkle; //闪烁标志
bit flag=0; //2ms数码管动态显示标志
bit Back=1; //倒计时标志
/***************************************
定时器T0/T1初始化程序 @11.0592MHz
***************************************/
void Timer_Init()
{
TMOD = 0x01; //设置T0模式1,T1模式2
TL0 = 0xCD; //设置定时初值2ms
TH0 = 0xF8; //设置定时初值2ms
TR0 = 1; //定时器0开始计时
EA=1; //开总中断
ET0=1; //开定时器1中断
}
/*************************
按键扫描程序
*************************/
void key_scan()
{
static uint count;//消抖计数变量
if(!K1)
{
count++;
if(count>=key_L) //长按快调
{
hour++;
if(hour>=25)
hour=0;
count=key_M;
}
}
else //按键抬起
{
if(count>key_S && count<key_L)//短按
{
hour++;
if(hour>=25)
hour=0;
}
count=0; //count清0
}
}
/********************************
数码管显示程序
********************************/
void display()
{
static uchar num=0; //分时显示变量
if(flag==1)
{
flag=0;
switch(num)
{
case 0:
P2=0xff; //消隐
a=1;b=0; //时十位位码
if(Back==0) P2=0xbf; //显示"-"
else P2=table[hour/10]; //时十位段码
num++;
break;
case 1:
P2=0xff; //消隐
a=0;b=1; //时个位位码
if(Back==0) P2=0xbf; //显示"-"
else
{
if(Twinkle==1) //时点闪烁
P2=table[hour%10]+0x80;//时个位段码+点
else
P2=table[hour%10];
}
num=0;
break;
}
}
}
/********************************
主程序
********************************/
void main(void)
{
Timer_Init(); //初始化定时器
OUT=1; //加电输出
while(1)
{
key_scan(); //按键扫描
display(); //显示
if(hour==0)
{
OUT=0; //停止输出
Back=0; //倒计时标志清0
}
else
{
OUT=1; //输出
Back=1; //倒计时标志置1
}
}
}
/*-----------------------------
定时器0中断服务程序 2m秒
------------------------------*/
void timer0() interrupt 1
{
TL0 = 0xCD; //设置定时初值2ms
TH0 = 0xF8; //设置定时初值2ms
flag=1;
if(Back==1)
{
Cnt2ms++; //时间变量Cnt2ms自+1
if(Cnt2ms<125) //闪烁频率1Hz
Twinkle=1; //闪烁标志
else Twinkle=0;
if(Cnt2ms>=500) //在此可以调整精度
{
Cnt2ms=0; //变量Cnt2ms清0
sec--; //秒自-1
if(sec>=60) //如果秒>=60
{
sec=59; //秒清0
min--; //分自-1
if(min>=60) //分>=60
{
min=59; //分清0
hour--; //小时自-1
if(hour>=25) //小时>=25
hour=24; //小时清0
}
}
}
}
}
|