矩阵按键扫描

求高手指点个矩阵按键的扫描程序。不用延时,或者有写好的原意给我参考下的感激不尽。下面这个是我自己写的,但是老是不能得到正确的结果。非常着急。求高手指点!!
#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;
  }

作者: liu_jiansheng   发布时间: 2011-06-15

#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; 

作者: aa1013911535   发布时间: 2011-06-16