新手用AT89S52、按键、数码管做的可调时钟,请朋友们多指点
本帖最后由 husange 于 2013-5-5 23:58 编辑功能:系统有四个按键k5,k6,k7,k8,功能分别是 调整,加,减,确定。在按下k5时候,显示 时 的两位数码管以一定频率闪烁。如果再次按下k5,则 分 开始闪烁,时恢复正常显示,依次循环,直到按下确定键k8,恢复正常的显示。在数码管闪烁的时候,按下k6或者k7可以调整相应的显示内容。按键支持短按,和长按,即短按时,修改的内容每次增加一或者减小一,长按时候以一定速率连续增加或者减少。8位数码管显示格式如下:时-分-秒(XX-XX-XX)。P2控制位选,P0是段码。12MHZ晶振。
我是新手,写的代码功能虽然实现了,但是冗长混乱,请大家帮忙指点。
timer.c
#include<reg52.h>
bit TIME2MS_1=0; //2ms时标,用于按键扫描
bit TIME2MS_2=0; //2ms时标,用于数码管扫描
void timer0_init()
{
TMOD=0x01;
TH0=(65536-2000)/256;
TL0=(65536-2000)%256;
TR0=1;
ET0=1;
}
void timer0_interrupt() interrupt 1
{
TH0=(65536-2000)/256;
TL0=(65536-2000)%256;
TIME2MS_1=1;
TIME2MS_2=1;
}
anjian.c
#include<reg52.h>
#include"timer.h"
typedef unsigned char uchar;
typedef unsigned intuint;
sbit k5=P1^4;
sbit k6=P1^5;
sbit k7=P1^6;
sbit k8=P1^7;
#define KEY_INIT 0
#define KEY_PRESS 1 //k5摁下
#define KEY_RELEASE 2 //k5释放
#define KEY_PROCESS 3
#define KEY_CERTAIN 4 //k8摁下
#define KEY6_LONG 5 // k6长摁
#define KEY6_SHORT 6
#define KEY7_LONG 7 // k7长摁
#define KEY7_SHORT 8
uchar t[]={2,3,10,5,9,10,4,1}; //数码管显示缓存
uchar adjust=0; //调整标志位
void key_init()
{
k5=1;
k6=1;
k7=1;
k8=1;
}
void key_process() //状态转移处理
{
static uchar key_state=KEY_INIT;
static uchar j=0,n=0; //定义变量,用于判断长、短摁
switch(key_state)
{
case KEY_INIT:
{
if(k5==0)
{
key_state=KEY_PRESS;
}
}
break;
case KEY_PRESS:
{
if(k5==0)
{
adjust=1; //k5摁下,把调整标志位置1
key_state=KEY_RELEASE;
}
else
{
key_state=KEY_INIT;
}
}
break;
case KEY_RELEASE: //k5释放
{
if(k5==1)
{
key_state=KEY_PROCESS;
}
}
break;
case KEY_PROCESS:
{
if(k5==0)
{
adjust++; //k5摁下,即调整标志位
if(adjust>3)
{
adjust=1;
}
key_state=KEY_RELEASE;
}
if(k6==0)
{
j++;
if(j>=3) //长按
{
j=0;
key_state=KEY6_LONG;
}
if(j==1) //短按
{
key_state=KEY6_SHORT;
}
}
else
{
j=0;
}
if(k7==0)
{
n++;
if(n>=3) //长按
{
n=0;
key_state=KEY7_LONG;
}
if(n==1) //短按
{
key_state=KEY7_SHORT;
}
}
else
{
n=0;
}
if(k8==0)
{
key_state=KEY_CERTAIN;
}
}
break;
case KEY6_SHORT: //短摁,加1
{
switch(adjust)
{
case 1: //时+1
{
t++;
if(t>9)
{
t=0;
t++;
}
if(t==2 && t>3)
{
t=0;
t=0;
}
}
break;
case 2: //分+1
{
t++;
if(t>9)
{
t=0;
t++;
if(t>5)
{
t=0;
t=0;
}
}
}
break;
case 3: //秒+1
{
t++;
if(t>9)
{
t=0;
t++;
if(t>5)
{
t=0;
t=0;
}
}
}
break;
default: break;
}
key_state=KEY_PROCESS;
}
break;
case KEY6_LONG: //长摁,每100ms加1
{
if(k6==0)
{
switch(adjust)
{
case 1:
{
t++;
if(t>9)
{
t=0;
t++;
}
if(t==2 && t>3)
{
t=0;
t=0;
}
}
break;
case 2:
{
t++;
if(t>9)
{
t=0;
t++;
if(t>5)
{
t=0;
t=0;
}
}
}
break;
case 3:
{
t++;
if(t>9)
{
t=0;
t++;
if(t>5)
{
t=0;
t=0;
}
}
}
break;
default: break;
}
}
else
{
key_state=KEY_PROCESS;
}
}
break;
case KEY7_SHORT:
{
switch(adjust)
{
case 1:
{
t--;
if(t>9)
{
t=9;
t--;
if(t>2)
{
t=2;
t=3;
}
}
}
break;
case 2:
{
t--;
if(t>9)
{
t=9;
t--;
if(t>5)
{
t=5;
t=9;
}
}
}
break;
case 3:
{
t--;
if(t>9)
{
t=9;
t--;
if(t>5)
{
t=5;
t=9;
}
}
}
break;
default: break;
}
key_state=KEY_PROCESS;
}
break;
case KEY7_LONG:
{
if(k7==0)
{
switch(adjust)
{
case 1:
{
t--;
if(t>9)
{
t=9;
t--;
if(t>2)
{
t=2;
t=3;
}
}
}
break;
case 2:
{
t--;
if(t>9)
{
t=9;
t--;
if(t>5)
{
t=5;
t=9;
}
}
}
break;
case 3:
{
t--;
if(t>9)
{
t=9;
t--;
if(t>5)
{
t=5;
t=9;
}
}
}
break;
default: break;
}
}
else
{
key_state=KEY_PROCESS;
}
}
break;
case KEY_CERTAIN: //k8摁下,将调整标志位清0,结束调整
{
adjust=0;
key_state=KEY_INIT;
}
break;
default :break;
}
}
void key_loop() //键盘扫描周期为100ms
{
static uchar i=0;
if(TIME2MS_1)
{
TIME2MS_1=0;
i++;
if(i>=50) //每100ms扫描一次
{
i=0;
key_process();
}
}
}
shumaguan.c
#include<reg52.h>
#include<intrins.h>
#include"timer.h"
#include"anjian.h"
uchar code s[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf}; //段码表
uchar wei=0xfe; //数码管位选
void desplay() //每2ms扫描一位数码管,每16ms全部扫描一次,频率为60HZ多,不会闪烁的
{
static uchar i=0;
static uintj=0;
static uintk=0;
if(TIME2MS_2)
{
TIME2MS_2=0;
if(adjust==0) //没有调整时间时的显示
{
j++;
if(j>=500) //1秒钟时间到,秒+1,调整时间
{
j=0;
t++;
if(t>=10)
{
t=0;
t++;
if(t>=6)
{
t=0;
t++;
if(t>=10)
{
t=0;
t++;
if(t>=6)
{
t=0;
t++;
if(t>=10)
{
t=0;
t++;
}
if(t==2 && t>=4)
{
t=0;
t=0;
}
}
}
}
}
}
P0=s]; //显示时间
P2=wei;
i++;
if(i>7)
i=0;
wei=_crol_(wei,1);
}
else //调整时间时的显示
{
j=0; //调整时间时,把j=0,保证调整结束后j从0开始加
k++;
switch(adjust)
{
case 1:
{
if(k<=50) //调整 时,显示 时 的数码管闪烁,频率为5HZ
{ //亮100ms
P0=s];
P2=wei;
i++;
if(i>7)
i=0;
wei=_crol_(wei,1);
}
if(k>50) //灭100ms
{
if(i==0)
{
i=2; //跳过 时 的扫描
}
if(wei==0xfe)
{
wei=0xfb; //跳过 时 的扫描
}
P0=s];
P2=wei;
i++;
if(i>7)
i=0;
wei=_crol_(wei,1);
}
if(k>100)
{
k=0;
}
}
break;
case 2: //调整 分,显示 分 的数码管闪烁,频率为5HZ
{
if(k<=50)
{
P0=s];
P2=wei;
i++;
if(i>7)
i=0;
wei=_crol_(wei,1);
}
if(k>50)
{
if(i==3)
{
i=5;
}
if(wei==0xf7)
{
wei=0xdf;
}
P0=s];
P2=wei;
i++;
if(i>7)
i=0;
wei=_crol_(wei,1);
}
if(k>100)
{
k=0;
}
}
break;
case 3: //调整 秒,显示 秒 的数码管闪烁,频率为5HZ
{
if(k<=50)
{
P0=s];
P2=wei;
i++;
if(i>7)
i=0;
wei=_crol_(wei,1);
}
if(k>50)
{
if(i==6)
{
i=0;
}
if(wei==0xbf)
{
wei=0xfe;
}
P0=s];
P2=wei;
i++;
if(i>7)
i=0;
wei=_crol_(wei,1);
}
if(k>100)
{
k=0;
}
}
break;
default : break;
}
}
}
}
main.c
#include<reg52.h>
#include"timer.h"
#include"anjian.h"
#include"shumaguan.h"
void main()
{
timer0_init(); //每2ms中断一次
EA=1;
key_init();
while(1)
{
key_loop(); //每100ms执行一次
desplay(); //每2ms执行一次
}
}
自己调应该能搞定的 不错我也学习一下 求指点,求批评,求板砖,感谢各位朋友指出问题互相交流帮忙进步。 我也学习一下 感觉和我以前写的差不多。。。问下楼主,多少级的菜单? jssd 发表于 2013-5-8 15:02 static/image/common/back.gif
感觉和我以前写的差不多。。。问下楼主,多少级的菜单?
“多少级的菜单?”是什么意思啊,不好意思,我是新手
页:
[1]