c语言怎样判断键盘按键的按下、释放

c语言怎样判断键盘按键的按下、释放,第1张

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语言编程等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zz/9495447.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-28
下一篇 2023-04-28

发表评论

登录后才能评论

评论列表(0条)

保存