首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

矩阵按键扫描解决方法

2012-08-02 
矩阵按键扫描求高手指点个矩阵按键的扫描程序。不用延时,或者有写好的原意给我参考下的感激不尽。下面这个是

矩阵按键扫描
求高手指点个矩阵按键的扫描程序。不用延时,或者有写好的原意给我参考下的感激不尽。下面这个是我自己写的,但是老是不能得到正确的结果。非常着急。求高手指点!!
#include <HB_KEY_LJSV02.h>
 unsigned char key_l=0; //记录行
 unsigned char key_r=0; //记录列
 unsigned char key_val=0; //返回值
 unsigned char count_key=0; //防抖动
 unsigned char cot=0; //用于选择扫描行或列
  void key_scan(unsigned char s_val,unsigned char s_r)
  {
  KEY_PORT=s_val; //KEY_PORT为矩阵按键接口
if((KEY_PORT&s_val)!=s_val)
{
s_r=(KEY_PORT^s_val);
count_key++;
}
  }
  unsigned char key_return()
  {
if(30==count_key)
{
key_l=0;
key_r=0;
count_key=0;
}
key_scan(0xf0,key_l);
if(1==count_key)
{
  key_scan(0x0f,key_r);
}
if((count_key<30)&(2==count_key))
{
count_key++;
}
key_val=(key_r|key_l);
return key_r;
  }

[解决办法]
#ifndef _KEYBOARD_H_ 
#define _KEYBOARD_H_ 
#include <iom16v.h> 
#include "define.h" 

#define KEYSUM 9 ///按键数量 
#define HANGSUM 3 ///按键行数 
#define LIESUM 3 ///按键列数 
#define HANGSTART 0 ///按键行起始端口号 
#define LIEEND 6 ///按键列末位端口号 
#define KEYOUT PORTB ///按键扫描高电平输出端口 
#define KEYIN PINB ///按键扫描输入端口 


struct key 

 uchar keynum; ///按键编号 
 uchar keyconter; ///按键灵敏度 
 uchar keyburstmode; ///按键触发方式0为延时电平触发1为按下触发2为抬起触发 
}; ///按键键值缓冲区 


extern volatile uchar nowkeynum; ///当前按键编号 无按键按下时为0 

/*! 
 * \brief 按键扫描程序 
 * 
 *读入按键键值并写入全局变量nowkeynum 
 * 
 * \return 按键键值 
 */ 
uchar keyscan(void); 

#endif 

********************************************************************** 
文件keyboard.c: 
#include "keyboard.h" 
/*按键记录电平计数缓冲区 
每次扫描有按键按下记录缓冲区加1,直到超过按键灵敏度值。如无按键按下则清零。 
 */ 
uchar keytmp[KEYSUM + 1] = 

0, 0, 0, 0, 0, 0, 0, 0, 0, 0 
}; 

/*按键记录缓冲区 
当使用沿触发方式时记录按键状态 
 */ 
uchar keytmpnow[KEYSUM + 1] = 

0, 0, 0, 0, 0, 0, 0, 0, 0, 0 
}; 

/*按键记录历史缓冲区 
当使用沿触发方式时记录上一次按键状态 
 */ 
uchar keytmpold[KEYSUM + 1] = 

0, 0, 0, 0, 0, 0, 0, 0, 0, 0 
}; 

/*按键声明区 
定义各个按键属性 
 */ 
const struct key keyunit[KEYSUM + 1] = 

0, 1, 0, /// 
1, 2, 1, /// 
2, 5, 0, /// 
3, 5, 0, /// 
4, 5, 0, /// 
5, 5, 0, /// 
6, 5, 0, /// 
7, 5, 0, /// 
8, 5, 0, /// 
9, 5, 0, /// 
}; 

uchar keyscan(void) 

uchar loop1 = 0; ///行扫描循环控制 
uchar loop2 = 0; ///列扫描循环控制 
uchar keynumtmp = 0; ///按键编号缓存 
uchar keyloopmasklie = 0; ///列扫描掩码 
///列扫描掩码设定 
keyloopmasklie |= (1 << LIEEND); 
KEYOUT = 0x00; 
for (loop1 = 0; loop1 < HANGSUM; loop1++) 

///置行线 
KEYOUT |= (1 << (loop1 + HANGSTART)); 

for (loop2 = 0; loop2 < LIESUM; loop2++) 

keynumtmp = loop1 * LIESUM + loop2 + 1; ///计算出当前正在处理的按键编号 

///判断按键的触发方式然后执行相应的判断程序 
switch (keyunit[keynumtmp].keyburstmode) 



///电平触发 
case 0: 

///如果有键按下相应键值计数器加1 
if ((KEYIN &keyloopmasklie) != 0) 

keytmp[keynumtmp]++; 
///如果计数器计数超出灵敏度设定值有效按键键值赋值 
if (keytmp[keynumtmp] >= keyunit[keynumtmp].keyconter) 

nowkeynum = keynumtmp; 
///计数器计数保持最大值 
keytmp[keynumtmp] = keyunit[keynumtmp].keyconter; 
return nowkeynum; 


///没有按键按下相应按键计数寄存器清零 
else 

keytmp[keynumtmp] = 0; 


break; 
///按下触发 
case 1: 
///抬起触发 
case 2: 

///如果有键按下相应键值计数器加1 
if ((KEYIN &keyloopmasklie) != 0) 

keytmp[keynumtmp]++; 

///没有按键按下相应按键计数寄存器清零 
else 

keytmp[keynumtmp] = 0; 


///如果计数器计数超出灵敏度设定值按键键值赋高 
if (keytmp[keynumtmp] >= keyunit[keynumtmp].keyconter) 

///置当前按键电平状态为高 
keytmpnow[keynumtmp] = HIGH; 
///计数器计数保持最大值 
keytmp[keynumtmp] = keyunit[keynumtmp].keyconter; 
///按下触发 
if (keyunit[keynumtmp].keyburstmode == 1) 

///上升沿 
if (keytmpold[keynumtmp] == LOW && keytmpnow[keynumtmp] == HIGH) 

nowkeynum = keynumtmp; 
keytmpold[keynumtmp] = keytmpnow[keynumtmp]; 
return nowkeynum; 



else 

///置当前按键电平状态为低 
keytmpnow[keynumtmp] = LOW; 
///抬起触发 
if (keyunit[keynumtmp].keyburstmode == 2) 

///下降沿 
if (keytmpold[keynumtmp] == HIGH && keytmpnow[keynumtmp] == LOW) 

nowkeynum = keynumtmp; 
keytmpold[keynumtmp] = keytmpnow[keynumtmp]; 
return nowkeynum; 



///按键记录推移 
keytmpold[keynumtmp] = keytmpnow[keynumtmp]; 

break; 

keyloopmasklie >>= 1; 


///列扫描掩码设定 
keyloopmasklie = 0; 
keyloopmasklie |= (1 << LIEEND); 

///复位行线到KL1 
KEYOUT = 0x00; 

nowkeynum = 0; 
return nowkeynum; 

热点排行