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