📄 keypad.c
字号:
#include <reg51.h>
#include <absacc.h>
#include <intrins.h>
#define uchar unsigned char
#define comm8255 XBYTE[0x8003]
#define pa8255 XBYTE[0X8000]
#define pb8255 XBYTE[0x8001]
#define pc8255 XBYTE[0x8002]
sbit p2_0=P3^0; //闹钟响铃用 P3.0 引脚
void init(void);
void out_time(void);
void st_outtime(void);
void key_deal();
void display();
void ring(void);
uchar code dis_7[15]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0x83,0xc6,0xf7,0xff,};
//七段段码表 0 1 2 3 4 5 - , B , C _ 不显示
uchar code scan_con[8]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; //数码管列扫描控制字
uchar dis[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //显示缓冲区
uchar ring_second=0x00,ring_minute=0x00; //响铃一分钟用变量
char keypad=0x00; //键盘程序用的键值
uchar value=0x00,key_value=0x00; //这两个键盘扫描的临时值
uchar deal=0x00; //调时位控制变量
uchar data_deal=0x00; //调日期控制变量
bit data_deal_flag=0; //日期按键是否处理控制用标志
bit sign; //区分倒计时&闹钟的标志位,用于响铃子程序
bit switchover; //24小时转12小时制度(由按键0控制)
uchar hour_12; //24小时转12小时的暂存变量
/////////////////////////////////////////
uchar st_10ms=0x00,st_s=0x00,st_minute=0x00,st_count=0x00; //秒表用变量
bit st_flag=0;
uchar st_control=0x00; //秒表开始,暂停控制变量
////////////////////////////////////////
uchar alarm_minute=0x00,alarm_second=0x00,alarm_hour=0x00; //闹钟用变量
bit alarm_flag=0; //开启闹钟用标志
bit alarm_key_flag=0; //按键处理闹钟用标志
uchar alarm_deal=0x00;
/////////////////////////////////////////////////////
uchar down_second=0x00,down_minute=0x00,down_hour=0x00; //倒计时用变量
bit down_flag=0; //开启倒计时用标志
bit down_key_flag=0; //倒计时按键处理用标志
bit down_ring=0; //倒计时响铃标志
uchar down_deal=0x00; //跳位变量
//////////
uchar count=0x00,year_higher=20,year=0x07,month=12,day=31,hour=23,minute=59,second=30;
bit flag=0; //时终一秒到用标志
bit deal_flag=0; //调时用标志
/****************************************************************************
* 名称:Ddelay()
* 功能:长软件延时
* 入口参数:t延时参数,值越大,延时越久
* 出口参数:无
****************************************************************************/
void delay(uchar t) //延时0.5ms
{
uchar i,k;
for(i=0;i<t;i++)
for(k=248;k>0;k--);
}
/*******************************************************************************
*File: Main.c
*功能: LED数码管显示0-F字符,同时控制4个LED显示对应的十六进制
*******************************************************************************/
////////////////////////////////////////////////////////键盘扫描子程序,返回键值
void keydeal(uchar *deal,uchar *hour,uchar *minute,uchar *second)
{
if ((*deal==1)&(keypad<=2)) // 时十位处理,小时十位为1或2
{
*hour=(uchar)keypad*10+*hour%10;
(*deal)++; //如果这一位输入无效,则调时控制变量不变,下
return; //一位输入还在这一位。
}
if((*deal==2)&(keypad<4)&(*hour/10==2)) //时个位处理,小时十位为2时,小时个位keypad<4
{
*hour=*hour/10*10+(uchar)keypad;
(*deal)++;
return;
}
if((*deal==2)&(*hour/10<2)) //时个位处理,小时十位为1时,小时高位随便
{
*hour=*hour/10*10+(uchar)keypad;
(*deal)++;
return;
}
if ((*deal==3)&(keypad<6)) // 分十位
{
*minute=(uchar)keypad*10+*minute%10;
(*deal)++;
return;
}
if(*deal==4) // 分个位
{
*minute=*minute/10*10+(uchar)keypad;
(*deal)++;
return;
}
if((*deal==5)&(keypad<6)) //秒十位
{
*second=(uchar)keypad*10+*second%10;
(*deal)++;
return;
}
if((*deal)==6) //秒个位处理
{
(*second)=*second/10*10+(uchar)keypad;
(*deal)++;
//deal_flag=0;
//ET0=1; TR0=1;
return;
}
}
/*******************************************************************************
*File: Main.c
*功能: LED数码管显示0-F字符,同时控制4个LED显示对应的十六进制
*******************************************************************************/
uchar line(uchar a) //行值判断子程序(也作为判断是否有按键按下判断)
{
pa8255=a; // PA送列值
a=pc8255; //读行值PC0--PC1
a=a&0x03;
return a; //屏蔽高六位 并返回低2位
}
/*******************************************************************************
*File: Main.c
*功能: LED数码管显示0-F字符,同时控制4个LED显示对应的十六进制
*******************************************************************************/
uchar keyscan()
{
value=line(0x00);
if(value==0x03)return -1; //无键按下返回—1
delay(5);
value=line(0x00);
if(value==0x03)return -1;
if(value==0x02) //键值在第一行的某一列
{
if(line(0xfe)==0x02)key_value=0x00;
if(line(0xfd)==0x02)key_value=0x01;
if(line(0xfb)==0x02)key_value=0x02;
if(line(0xf7)==0x02)key_value=0x03;
if(line(0xef)==0x02)key_value=0x04;
if(line(0xdf)==0x02)key_value=0x05;
if(line(0xbf)==0x02)key_value=0x06;
if(line(0x7f)==0x02)key_value=0x07;
while(line(0x00)==0x02); // 等待按键释放
return key_value;
}
if(value==0x01) //键值在第二行的某一列
{
if(line(0xfe)==0x01)key_value=0x08;
if(line(0xfd)==0x01)key_value=0x09;
if(line(0xfb)==0x01)key_value=0x0a;
if(line(0xf7)==0x01)key_value=0x0b;
if(line(0xef)==0x01)key_value=0x0c;
if(line(0xdf)==0x01)key_value=0x0d;
if(line(0xbf)==0x01)key_value=0x0e;
if(line(0x7f)==0x01)key_value=0x0f;
while(line(0x00)==0x01);
return key_value;
}
return -1;
}
//////////////////////////////////////////////
/*******************************************************************************
*File: Main.c
*功能: LED数码管显示0-F字符,同时控制4个LED显示对应的十六进制
*******************************************************************************/
void key_deal()
{
p2_0=0;
display();
display();
p2_0=1;
if(keypad==0x0c) //调时0x0c键有效,进入调时
{
ET0=0; TR0=0; //关定时,定时停止,进入调时
deal++;
if(deal>=7)
{
deal_flag=0;
deal=0x00; //退出调时,也要把控制变量清掉
ET0=1; TR0=1;
return;
}
if(deal_flag==0)
{
deal_flag=1;
}
return;
}
///////////////////////////////////
if((keypad==0x0e)&(data_deal_flag==0))
{
st_control++;
if(st_control==0x01)
{
ET1=0; TR1=0;
TH1=0xd8;
TL1=0xf0;
return;
}
if(st_control%2==0) //第偶数下按E键—》开始秒表
{
ET1=1; TR1=1;
return;
}
if((st_control%2==1)&(st_control!=0x01)) //第奇数次按E键暂停
{
ET1=0; TR1=0;
return;
}
}
/////////////////////////////////////////////
if((keypad==0x0d)&(st_control==0)) //日期显示以及位调控(因为跟秒表退出键复用,所以要在秒表停止下)
{
//日期调控,不用关定时
data_deal++;
if(deal>=9)
{
data_deal_flag=0;
data_deal=0x00; //退出调时,也要把控制变量清掉
return;
}
if(data_deal_flag==0)
{
data_deal_flag=1;
}
return;
}
if((keypad==0x0f)&(st_control==0)) //闹钟键
{
alarm_deal++;
if(alarm_deal>=8)
{
alarm_key_flag=0;
alarm_deal=0x00;
return;
}
if(alarm_key_flag==0)
{
alarm_key_flag=1;
}
return;
}
if(keypad==0x0b) //倒计时键控
{
down_deal++;
if(down_deal>=8)
{
down_key_flag=0;
down_deal=0x00;
return;
}
if(down_key_flag==0)
{
down_key_flag=1;
}
return;
}
if((keypad==0x0e)&(data_deal_flag==1)) //日期退出显示和键控
{
data_deal=0x00;
data_deal_flag=0;
return;
}
if((keypad==0x0a)&(alarm_key_flag==1)) //闹钟开关
{
if(alarm_flag==0)
{
alarm_flag=1;
alarm_key_flag=0;
return;
}
else
{
alarm_deal=0x00;
alarm_flag=0;
alarm_key_flag=0;
return;
}
}
if((keypad==0x0a)&(down_key_flag==1)) //倒计时开关
{
if((down_flag==0)&((down_hour>0)|(down_minute>0)|(down_second>0)))
{
down_flag=1;
down_key_flag=1; //开启并显示
return;
}
else
{
down_deal=0x00;
down_flag=0;
down_key_flag=0;
down_ring=0;
return;
}
}
if((keypad==0x0a)&(down_key_flag==0)&(alarm_key_flag==0)) //键控24小时转12小时
{
if(switchover==0)
{
switchover=1;
return;
}
else switchover=0;
return;
}
/////////////////////////////////////////////////////////////////////以下秒表处理
if((st_control%2==1)&(keypad==0x0f)) //暂停下才能清零
{
st_10ms=0x00;
st_s=0x00;
st_minute=0x00;
TH1=0x00;
TL1=0x00;
return;
}
if((st_control%2==1)&(keypad==0x0d)) //秒表退出
{
st_control=0x00;
st_10ms=0x00;
st_s=0x00;
st_minute=0x00;
TH1=0x00;
TL1=0x00;
ET1=0; TR1=0;
return;
}
///////////////////////////////////////////////
if((deal_flag==1)&(keypad<=9)) //时钟按键处理
{
keydeal(&deal,&hour,&minute,&second);
if(deal>=0x07)
{
deal=0x00;
deal_flag=0;
ET0=1; TR0=1;
}
return;
}
if((down_key_flag==1)&(keypad<=9)) //倒计时按键处理
{
keydeal(&down_deal,&down_hour,&down_minute,&down_second);
if(down_deal>=0x08)down_deal=0x00;
return;
}
if((alarm_key_flag==1)&(keypad<=9)) //闹钟按键处理
{
keydeal(&alarm_deal,&alarm_hour,&alarm_minute,&alarm_second);
if(alarm_deal>=0x08)alarm_deal=0x00;
return;
}
//////////////////////////////////////////
if((data_deal_flag==1)&(keypad<=9)) //日期按键处理(调整日期)
{
if(data_deal==1)
{
year_higher=(uchar)keypad*10+year_higher%10;
data_deal++;
return;
}
if(data_deal==2)
{
year_higher=year_higher/10*10+(uchar)keypad;
data_deal++;
return;
}
if(data_deal==3)
{
year=(uchar)keypad*10+year%10;
data_deal++;
return;
}
if(data_deal==4)
{
year=year/10*10+(uchar)keypad;
data_deal++;
return;
}
if((data_deal==5)&(keypad==1))
{
month=(uchar)keypad*10+month%10;
if(month>=13)month=12;
data_deal++;
return;
}
if ((data_deal==5)&(keypad==0))
{
month=month%10;
data_deal++;
return;
}
if((data_deal==6)&(month/10==1)&(keypad<=2))
{
month=month/10*10+(uchar)keypad;
if((day>=31)&((month==4)|(month==6)|(month==9)|(month==11)))day=30;//30号月,当调整时
data_deal++; //day=31,day要自动调整为30
return;
}
if((data_deal==6)&(month/10==0))
{
month=month/10*10+(uchar)keypad;
day=30;
if((day>=31)&((month==4)|(month==6)|(month==9)|(month==11)))day=30;
if((month==2)&(day>=29))day=28;
data_deal++;
return;
}
if((data_deal==7)&(month!=2)&(keypad<=3))
{
day=(uchar)keypad*10+day%10;
data_deal++;
return;
}
if((data_deal==7)&(month==2)&(keypad<=2))
{
day=(uchar)keypad*10+day%10;
data_deal++;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -