C语言判断键盘按下和释放,是通过检测该键的状态来实现的。如果是单一的一个按键,那么直接检测该键是“1”还是“0”,就可以确定是按下还是释放。如果是矩阵键盘,那么需要发送扫描码,再检测输入值,来判断键盘中键的状态。以下举例说明:
bit keychk() //单一按键检测
{
if(P10==0) //如果键按下
{
delay(); //延时去抖
if(P10==0)return(1); //返回键状态
}
return(0);
}
unsigned char kbscan(void) //矩阵扫描按键检测
{
unsigned char sccode,recode;
P1=0x0f; //发0扫描,列线输入
if ((P2 & 0x0f) != 0x0f) //有键按下
{
delay(20); //延时去抖动
if ((P1&0x0f)!= 0x0f)
{
sccode = 0xef; //逐行扫描初值
while((sccode&0x01)!=0)
{
P1=sccode;
if((P1&0x0f)!=0x0f)
{
recode=(P1&0x0f)|0xf0;
while((P1&0x0f)!=0x0f);//等待键抬起
return((~sccode)+(~recode));
}
else
sccode=(sccode<<1)|0x01;
}
}
}
return 0; //无键按下,返回0
}
#include<reg52h>
#include<absacch>
#define PA XBYTE[0xF8FF]
#define PB XBYTE[0xF9FF]
#define PC XBYTE[0xFAFF]
#define COM XBYTE[0xFBFF]
#define LCD1602_RS_SET() PB|=1<<0
#define LCD1602_RS_RST() PB&=~(1<<0)
#define LCD1602_RW_RST() PB&=~(1<<1)
#define LCD1602_E_SET() PB|=1<<2
#define LCD1602_E_RST() PB&=~(1<<2)
static void Delay_ms(unsigned char time)
{
unsigned char i;
while(time--)
{
for(i=0;i<100;i++);
}
}
static void LCD1602_WriteByte(unsigned char value,bit dataTypedef)
{
if(dataTypedef)
LCD1602_RS_SET();
else
LCD1602_RS_RST();
LCD1602_RW_RST();
PA = value;
LCD1602_E_SET();
Delay_ms(2);
LCD1602_E_RST();
}
static void LCD1602_Init(void)
{
LCD1602_WriteByte(0x38,0);
Delay_ms(10);
LCD1602_WriteByte(0x01,0);
Delay_ms(10);
LCD1602_WriteByte(0x06,0);
Delay_ms(10);
LCD1602_WriteByte(0x0C,0);
Delay_ms(10);
}
static void LCD1602_ShowString(unsigned char address,unsigned char string)
{
LCD1602_WriteByte(address,0);
while(string)
{
LCD1602_WriteByte(string++,1);
}
}
static unsigned char bdata KeyStatus=0xFF;
sbit KEY1 = KeyStatus^4;
sbit KEY2 = KeyStatus^5;
sbit KEY3 = KeyStatus^6;
sbit KEY4 = KeyStatus^7;
static unsigned char KeyValue=48;
static void KEY_Testing(void)
{
PC = 0xFE;
KeyStatus = PC&0xFF;
if(KeyStatus!=0xFF)
{
if(!KEY1)KeyValue='7';
if(!KEY2)KeyValue='8';
if(!KEY3)KeyValue='9';
if(!KEY4)KeyValue='/';
}
PC = 0xFD;
KeyStatus = PC&0xFF;
if(KeyStatus!=0xFF)
{
if(!KEY1)KeyValue='4';
if(!KEY2)KeyValue='5';
if(!KEY3)KeyValue='6';
if(!KEY4)KeyValue='';
}
PC = 0xFB;
KeyStatus = PC&0xFF;
if(KeyStatus!=0xFF)
{
if(!KEY1)KeyValue='1';
if(!KEY2)KeyValue='2';
if(!KEY3)KeyValue='3';
if(!KEY4)KeyValue='-';
}
PC = 0xF7;
KeyStatus = PC&0xFF;
if(KeyStatus!=0xFF)
{
if(!KEY1)KeyValue='';
if(!KEY2)KeyValue='0';
if(!KEY3)KeyValue='=';
if(!KEY4)KeyValue='+';
}
}
void main()
{
COM = 0x88;
PA = 0xFF;
PB = 0xFF;
PC = 0xFF;
LCD1602_Init();
LCD1602_ShowString(0x82,"Hello World!");
LCD1602_ShowString(0xC0,"Key Pressed--->");
while(1)
{
KEY_Testing();
LCD1602_WriteByte(0xCF,0);
LCD1602_WriteByte(KeyValue,1);
}
}
下面是在P1口接4X3矩阵键盘的驱动程序,供你参考。上拉电阻也可以不用
code U8 kcode[]={0xb7,0xbe,0xde,0xee,0xbd,0xdd,0xed,0xbb,0xdb,0xeb,0xd7,0xe7};
//反转码对应键值 0 1 2 3 4 5 6 7 8 9 A B
U8 key(void)
{ U8 a,r = 0xff;
delay_ms(20); // 延时20毫秒,消除按键抖动
if(P1 == 0xf0) goto rn;
a = P1;
P1 = a | 0x0f;
delay_ms(20);
a = P1;
for (r = 0;r <= 11;r++)
{ if(a == kcode[r]) break;
};
rn: P1 = 0xf0;
return r;
}
if(key_l!=0xf0)
{
delay_nms(5);
key_l=P1;
……
在第4行加 while( key_l!=0xf0 );
等待按键释放,按键不放开就一直在此处等待,知道按键释放,此语句执行完。再往下执行
#define LCD1602_FLAG
#define LCD1602_PORT P0
#include<reg51h>
#include<stddefh>
#define uchar unsigned char
sbit lcd1602_rs=P2^0;
sbit lcd1602_e=P2^2;
sbit lcd1602_rw=P2^1;
sbit lcd1602_busy=P0^7;
uchar str[]="This is Key Test";
uchar keyval,keystr[16];
void delay(uchar a)
{
uchar i;
while(a--)for(i=0;i<120;i++);
}
/
函数名称:lcd1602_CheckBusy()
函数功能:状态查询
/
void lcd1602_CheckBusy()
{
do
{
lcd1602_busy=1;
lcd1602_rs=0;
lcd1602_rw=1;
lcd1602_e=0;
lcd1602_e=1;
}
while(lcd1602_busy);
}
/
函数名称: lcd1602_WriteCmd()
函数功能:写命令
入口参数:命令字
出口参数:无
/
void lcd1602_WriteCmd(const uchar cmd)
{
lcd1602_CheckBusy();
lcd1602_rs=0;
lcd1602_rw=0;
lcd1602_e=1;
LCD1602_PORT=cmd;
lcd1602_e=0;
}
/
函数名称:lcd1602_WriteData()
函数功能:写数据
入口参数:c--待写数据
出口参数:无
/
void lcd1602_WriteData(const uchar c)
{
lcd1602_CheckBusy();
lcd1602_rs=1;
lcd1602_rw=0;
lcd1602_e=1;
LCD1602_PORT=c;
lcd1602_e=0;
}
/
函数名称:lcd1602_Init()
函数功能:初始化LCD
入口参数:无
出口参数:无
/
void lcd1602_Init()
{
lcd1602_WriteCmd(0x38); //显示模式为8位2行57点阵
lcd1602_WriteCmd(0x0c); //display enable,flag enable,flash enable,
lcd1602_WriteCmd(0x06); //flag move to right,screen don't move
lcd1602_WriteCmd(0x01); //clear screen
}
/
函数名称:lcd1602_Display()
函数功能: 字符显示
入口参数:ptr--字符或字符串指针
出口参数:无
说 明:用户可通过以下方式来调用:
1)lcd1602_Display("Hello,world!");
2) INT8U 存储类型 txt[]="要显示的字符串";
或者 INT8U 存储类型 txt[]={'t','x','t',,'\0'};
INT8U ptr;
ptr=&txt;
lcd1602_Display(ptr);
或 lcd1602_Display(txt);
或 lcd1602_Display(&txt);
/
void lcd1602_Display(const uchar ptr,uchar line)
{
uchar data i=0;
uchar data q;
q=ptr;
switch(line)
{
case 0:
lcd1602_WriteCmd(0x80);
while(q!=NULL && (q!='\0') && i<16)
{
lcd1602_WriteData(q);
q++;
i++;
}
break;
case 1:
lcd1602_WriteCmd(0xc0);
while(q!=NULL && (q!='\0') && i<16)
{
lcd1602_WriteData(q);
q++;
i++;
}
break;
}
}
uchar kbscan(void)
{
unsigned char sccode,recode;
P3=0x0f; //发0扫描,列线输入
if ((P3 & 0x0f) != 0x0f) //有键按下
{
delay(20); //延时去抖动
if ((P3&0x0f)!= 0x0f)
{
sccode = 0xef; //逐行扫描初值
while((sccode&0x01)!=0)
{
P3=sccode;
if((P3&0x0f)!=0x0f)
{
recode=(P3&0x0f)|0xf0;
while((P3&0x0f)!=0x0f);//等待键抬起
return((~sccode)+(~recode));
}
else
sccode=(sccode<<1)|0x01;
}
}
}
return 0; //无键按下,返回0
}
uchar getkey(void)
{
uchar key;
key=kbscan();
if(key==0){keyval=0xff;return(0);}
switch(key)
{
case 0x11:keyval=7;break;
case 0x12:keyval=4;break;
case 0x14:keyval=1;break;
case 0x18:keyval=10;break;
case 0x21:keyval=8;break;
case 0x22:keyval=5;break;
case 0x24:keyval=2;break;
case 0x28:keyval=0;break;
case 0x41:keyval=9;break;
case 0x42:keyval=6;break;
case 0x44:keyval=3;break;
case 0x48:keyval=11;break;
case 0x81:keyval=12;break;
case 0x82:keyval=13;break;
case 0x84:keyval=14;break;
case 0x88:keyval=15;break;
default:keyval=0xff;break;
}
if(keyval!=0xff)return(1);
else return(0);
}
main()
{
uchar num;
lcd1602_Init();
lcd1602_Display(str,0);
while(1)
{
if(getkey())
{
keystr[num]=keyval+0x30;
lcd1602_Display(keystr,1);
num++;
num%=16;
}
}
}
这是一个以前写的矩阵键盘程序,显示在数码管上的。你该改就可以了
#include<reg52h>
#define uchar unsigned char
#define uint unsigned int
sbit dula=P2^6;
sbit wela=P2^7;
uchar code table[]={
0x3f,0x06,0x5b,0x4f,
0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,
0x39,0x5e,0x79,0x71,0x67};
void delay(uint m)
{ uint i,j;
for(i=m;i>0;i--)
for(j=110;j>0;j--);
}
void display(uchar num)
{ wela=1;
P0=0xc0;
wela=0;
P0=0XFF;
dula=1;
P0=table[num];
dula=0;
}
void keycans()
{ uchar a,key,c;
P3=0X0f;
if(P3!=0X0f)
{ delay(10);
if(P3!=0x0f)
{
a=P3;
P3=0Xf0;
c=P3;
a=a|c;
switch(a)
{case 0xee:key=1;break;
case 0xde:key=2;break;
case 0xbe:key=3;break;
case 0x7e:key=4;break;
case 0xed:key=5;break;
case 0xdd:key=6;break;
case 0xbd:key=7;break;
case 0x7d:key=8;break;
case 0xeb:key=9;break;
case 0xdb:key=10;break;
case 0xbb:key=11;break;
case 0x7b:key=12;break;
case 0xe7:key=13;break;
case 0xd7:key=14;break;
case 0xb7:key=15;break;
case 0x77:key=16;break;
}
while(!a);
display(key);
}
}
}
void main()
{
while(1)
keycans();
}
看程序中P10-P13是行扫描输出,P14-P17是扫描输入。所以原理是P10-P13中每次只有一个引脚输出0,其余输出1,然后读取P14-P17是否有引脚为0;如果有0说明有按键按下,如果全1说明没有按键按下。
scancode这个变量就是用于控制P10-P13(P1 = scancode;由这句输出)中每次只有一个引脚输出0的。
scancode = 0xfe;这句中bit0值为0,其余bit为1,所以开始时,P1 = scancode;由这句输出后,P10为0,其余引脚为1。
scancode = (scancode << 1) | 0x01;这句使为0的bit左移一位(依次值为0xFE, 0xFD, 0xFB, 0xF7, 0xEF)。0xFE, 0xFD, 0xFB, 0xF7都满足while ((scancode &0x10) != 0)这个条件,而0xEF则不满足了,所以说<此语句只检查第五位是否为1,如果最低列按下后不就等于零了,就跳过此函数了>,到这就所有按键都扫描过了,没有按键按下(如果有按键按下,中途就返回了)。
if ((P1 &0xf0) != 0xf0)这句中P1 &0xf0表示只判断P14-P17,只有当前按下的按键所在行扫描输出为0时,这个表达式才成立(这时(P1 &0xf0) != 0xf0);否则这个表达式肯定不成立(这时(P1 &0xf0) == 0xf0),所以说当前行。
return ((~scancode) + (~tmpcode));这句就是如果有按键按下,那么直接返回键值,并不再进行循环退出程序。
程序格式要注意,下面这样更清楚:
uchar keyscan(void){
uchar scancode, tmpcode;
P1 = 0xf0; // 发全0行扫描码
if ((P1 &0xf0) != 0xf0)
// 若有键按下
{
delay(); // 延时去抖动
if ((P1 &0xf0) != 0xf0)
// 延时后再判断一次,去除抖动影响
{
scancode = 0xfe;
while ((scancode &0x10) != 0)
// 逐行扫描<此语句只检查第五位是否为1,如果最低列按下后不就等于零了,就跳过此函数了>
{
P1 = scancode; // 输出行扫描码
if ((P1 &0xf0) != 0xf0)
// 本行有键按下<为什么是行?哪一列按下此句都成立啊>
{
tmpcode = (P1 &0xf0) | 0x0f;
/ 返回特征字节码,为1的位即对应于行和列 /
return ((~scancode) + (~tmpcode));
}
else
scancode = (scancode << 1) | 0x01;
// 行扫描码左移一位
}
}
}
return (0); // 无键按下,返回值为0
}
以上就是关于c语言怎样判断键盘按键的按下、释放全部的内容,包括:c语言怎样判断键盘按键的按下、释放、急求一个基于89C51单片机,8255A,用矩阵键盘输入数字,并在LCD1602上显示出来的C语言程序、at89s51单片机用扩展pc口接4*4矩阵键盘请问怎么用c语言编程等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)