|
#include<reg51.h>
#define uchar unsigned char
#define uint unsigned int
#define GPIO_DIG P0 //用P0口段选
sbit K1=P2^6; //按键位声明
sbit K2=P2^7;
sbit LSA=P2^2; //138译码器位声明
sbit LSB=P2^3;
sbit LSC=P2^4;
uchar code DIG_CODE[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; //0、1、2、3、4、5、6、7、8、9的显示码
void xianshi();//声明时钟函数
void DigDisplay();//声明译码器动态函数
void dinshipeizhi(); //声明定时器配置函数
void Delay10ms(uint c); //声明延时函数
uchar Key_Scan(); //声明按键检测函数
uchar DisplayData[8]; //存放要显示的8个值
uint time,ss,sg,fs,fg,ms,mg,i,j,k;
void main()
{
dinshipeizhi();//启动定时器
while(1)
{
xianshi();//时钟显示
}
}
void xianshi()
{
Key_Scan(); //检测按键是否按下
if(time==20) //定时中断一次为50ms,20次就是1s
{
++mg; //秒 个位自增一
time=0;
}
else
{
mg=mg;
}
if(mg>9) //秒 个位大于9
{
mg=0; //秒 个位归零
++ms; //秒 十位自增1
}
else
{
ms=ms;
}
if(ms==6) //秒十位等于6
{
ms=0; //秒 十位归零
++fg; //分 个位自增1
}
else
{
fg=fg+k; //按键1按下,分 个位加1
k=0;
}
if(fg>9) //分 个位大于9
{
fg=0; //分 个位归零
++fs; //分 十位自增1
}
else
{
fs=fs;
}
if(fs==6) //分 十位等于6
{
fs=0; //分 十位归零
++sg; //时 个位自增1
++i; //计数,当记到12时,时十位归零
}
else
{
sg=sg+j; //检测到按键2按下,时 个位加1
i=i+j; //时 个位加1,i也要加1
j=0;
}
if(sg>9) //时 个位大于9
{
sg=0; //时 个位归零
++ss; //时 十位自增1
}
else
{
ss=ss;
}
if(i>=12&&ss<2) //i等于12,时 十位小于2
{
ss=0; //时 十位归零
sg=1; //时 个位为一
i=0; //i归零
}
DisplayData[0] = DIG_CODE[ss]; //时
DisplayData[1] = DIG_CODE[sg];
DisplayData[2] = 0x40;
DisplayData[3] = DIG_CODE[fs]; //分
DisplayData[4] = DIG_CODE[fg];
DisplayData[5] = 0x40;
DisplayData[6] = DIG_CODE[ms]; //秒
DisplayData[7] = DIG_CODE[mg];
DigDisplay();
}
void DigDisplay()
{
uchar a;
uint b;
for(a=0;a<8;a++)
{
switch(a) //位选,选择点亮的数码管,
{
case(0):
LSA=0;LSB=0;LSC=0; break;//显示第0位
case(1):
LSA=1;LSB=0;LSC=0; break;//显示第1位
case(2):
LSA=0;LSB=1;LSC=0; break;//显示第2位
case(3):
LSA=81;LSB=1;LSC=0; break;//显示第3位
case(4):
LSA=0;LSB=0;LSC=1; break;//显示第4位
case(5):
LSA=1;LSB=0;LSC=1; break;//显示第5位
case(6):
LSA=0;LSB=1;LSC=1; break;//显示第6位
case(7):
LSA=1;LSB=1;LSC=1; break;//显示第7位
}
GPIO_DIG=DisplayData[a];//发送段码
b=50; //扫描间隔时间设定
while(b--);
GPIO_DIG=0x00;//消隐
TR0=1;
}
}
uchar Key_Scan()
{
if (K1==0) //检测按键K1是否按下
{
Delay10ms(4); //消除抖动
if (K1==0) //再次检测按键是否按下
{
j = 1;
if (K1==0) //检测按键是否松开
Delay10ms(4); //消除抖动
}
}
//--检测按键2--//
if (K2==0) //检测按键K1是否按下
{
Delay10ms(4); //消除抖动
if (K2==0) //再次检测按键是否按下
{
k = 1;
if (K2==0); //检测按键是否松开
Delay10ms(4); //消除抖动
}
}
return j,k; //将读取到键值的值返回
}
void dinshipeizhi()
{
i=0;
j=0;
k=0;
time=0;
ss=0;
sg=0;
fs=0;
fg=0;
ms=0;
mg=0;
TMOD=0x01;//选择定时器0,工作方式为1
TH0=0x3c;//高位设置初始值 50ms
TL0=0xb0;//低位设置初始值
EA=1;// 开总中断
ET0=1;//开定时器0中断
TR0=1;//启动定时器0
}
void Timer0() interrupt 1 //设置初始值为50ms,故中断执行一次就为50ms
{
TH0=0x3c;//高位设置初始值 50ms
TL0=0xb0;//低位设置初始值
time++; //执行一次中断自增1
}
void Delay10ms(uint c) //误差 0us
{
uchar a, b;
//--c已经在传递过来的时候已经赋值了,所以在for语句第一句就不用赋值了--//
for (;c>0;c--)
{
for (b=38;b>0;b--)
{
for (a=130;a>0;a--);
}
}
}
这是我自己编的时钟程序,最笨的方法,还可以用三个/10,%10,来做。
现在有一个问题,我长按键后,秒那里不动了,是什么原因?是程序死在按键检测那里了吗?如果是这样数码管不应该灭掉吗?
我知道是按键松手消抖那里的问题,但我怎么改都没用,要么就达不到按一下记一次的效果,要么就是秒不跑了,求解!!!!!! |
|