标题:
十分好用的4*4矩阵键盘扫描程序
[打印本页]
作者:
hutians
时间:
2015-2-10 20:39
标题:
十分好用的4*4矩阵键盘扫描程序
十分好用的4*4矩阵键盘扫描程序,更重要的是程序十分的简短,几行代码就解决了4*4 扫描取键值,防抖动 ,此程序运用了一个很巧妙的算法!上程序供大家研究,此程序经过改进,可以实现长按键识别 组合按键识别。如果有哪里不够好 也请大家指出。程序算法先自己研究,初学者如果看不明白,贴子顶起来,我给大家解释!把文本格式奉上 直接复制到你的程序里。
volatile unsigned char CF[4]; //按键触发标志(表示4列,每一列同一行的
//值是一样的但列标不一样来区分不同列的键)
volatile unsigned char KeyVal;//键值
code unsigned char KeyOut[4] = {0xef,0xdf,0xbf,0x7f}; //4X4按输出端控制
#define KEY P2 //P2口作为4*4矩阵键盘输入
/*
**描述:新型4X4按键扫描程序 放在1ms-10ms中断内使用(十分稳定不需要再写消抖程序)
**备注:按键弹起时 keyVal = 0 单键按下 keyVal 有16个值,你自己程序可以针对不同值
**进行不同程序操作 keyVal单键值分别为
**0x11,0x12,0x14,0x18,
**0x21,0x22,0x24,0x28,
**0x31,0x32,0x34,0x38,
**0x41,0x42,0x44,0x48,
*/
void Key_Head()
{
unsigned char ReadData[4];
static unsigned char i;
if(++i>=4)i=0;
KEY = KeyOut[i]|0x0f; //忽略低4位
ReadData[i] = (KEY|0xf0)^0xff; //忽略高4位 取反
CF[i] = ReadData[i] & (ReadData[i] ^ Cont[i]);
Cont[i] = ReadData[i];
//输出键值
switch(CF[i])//第i列
{
case 0x08: KeyVal = (i<<4+8);break;
case 0x04: KeyVal = (i<<4+4);break;
case 0x02: KeyVal = (i<<4+2);break;
case 0x01: KeyVal = (i<<4+1);break;
default:KeyVal = 0;break;
}
}
复制代码
作者:
zlkj
时间:
2015-6-21 05:48
谢谢!希望学习完整程序。
作者:
hbljcxl
时间:
2015-6-30 21:57
楼主好,程序好精练,中间有好多地方看不懂,但是复制下来,在程序中试了你的程序,发现少定义了Cont[i]数组,加上后,程序也不成功,请教在主函数中如何调用 你的函数,多谢了!
作者:
大头5374
时间:
2016-4-26 15:05
这个程序可以直接拿来输入数值吗
作者:
瑾年Higher
时间:
2019-5-17 17:55
还烦请楼主解释一下
作者:
zhangxinwu
时间:
2020-2-20 00:54
用不了啊!咋回事啊!
作者:
xuyubin
时间:
2020-2-23 16:12
本帖最后由 xuyubin 于 2020-2-26 09:28 编辑
/*-------------------------------------------------------------------------
功能:矩阵键盘扫描程序,每经过10ms循环,进行一次4种可能的键值判断,由索引I控制,经过4轮
便可判断出所有可能的键值,(由程序执行的间隔来产生消抖作用,减少了程序执行时间)
**备注:无按键按下时 Key_Val = 0
单个键按下 Key_Val 有16个值
**0x01,0x02,0x04,0x08
**0x11,0x12,0x14,0x18,
**0x21,0x22,0x24,0x28,
**0x31,0x32,0x34,0x38,
可根据判断出的键值代表不同的按键按下
---------------------------------------------------------------------------*/
uchar Key_Judge()
{
static uchar Key_Code[4]; //每轮按键扫描后键值处理后数组
static uchar Key_Code_Store[4]; //每轮按键扫描后键值处理后储存的数组,以偏在下轮程序中对比确认键值
static uchar Key_Val; //按键扫描程序返回的键值
static uchar ReadData[4]; //按键读出后,数据处理后的暂存数组
static uchar i; //每轮按键判断处理索引
uchar key_Return=99;
if(++i>=4) i=0; //每轮判断后,索引都+1,经过4轮后又自动恢复至0;
Key_Input = KeyOut
|0x0f; //再第I轮,按设计好的数组,对高4位的进行拉低,判断16个键值,需要循环4轮
ReadData
= (Key_Input|0xf0)^0xff; //重新读取KEY_Input口,忽略高4位 异或取反后得出按键按下时后被拉低的位
Key_Code
= ReadData
& (ReadData
^ Key_Code_Store
);
//通过与上一循环周期前(4轮,40ms)前储存的按键读取值做对比,不同且为非0值,则表示按键按下持续超过40
//如相同或都是为0,则得出的值为0,表示没有按键按下,或者按键一直被按住情况
Key_Code_Store
= ReadData
;
//储存第i轮到按键读取值,以便下一循环周期(4轮,40ms)后对比用
switch(Key_Code
) //将第i轮按键读取值附上i轮索引值,以便产生16个可能的键值供判断按键用
{
case 0x08: Key_Val = (i<<4)+8;break;
case 0x04: Key_Val = (i<<4)+4;break;
case 0x02: Key_Val = (i<<4)+2;break;
case 0x01: Key_Val = (i<<4)+1;break;
default:Key_Val = 0;break;
}
作者:
wsh791
时间:
2020-2-23 21:58
学习了谢谢
作者:
wengjiamin
时间:
2021-1-9 09:07
楼主好,程序好精练,中间有好多地方看不懂,但是复制下来,在程序中试了你的程序,发现少定义了Cont[i]数组,加上后,程序也不成功,请教在主函数中如何调用 你的函数,多谢了!
在定时器1ms-10ms中断中进行调用
作者:
wengjiamin
时间:
2021-1-9 09:11
//反转法扫描4*4键盘程序
void keyscan(void) //键盘扫描函数
{ unsigned char n,m;
P1=0xf0;//全行扫描
n=P1; //读列的状态
n&=0xf0;//屏蔽掉行的状态
P1=0x0f;//全列扫描
m=P1;//读行的状态
m&=0x0f;//屏蔽掉列的状态
n=n|m;
switch(n)
{
case(0xee):display(3);break; //1110_1110
case(0xde):display(2);break; //1101_1110
case(0xbe):display(1);break; //1011_1110
case(0x7e):display(0);break; //0111_1110
case(0xed):display(7);break; //1110_1101
case(0xdd):display(6);break; //1101_1101
case(0xbd):display(5);break; //1011_1101
case(0x7d):display(4);break; //0111_1101
case(0xeb):display(11);break; //1110_1011
case(0xdb):display(10);break; //1101_1011
case(0xbb):display(9);break; //1011_1011
case(0x7b):display(8);break; //0111_1011
case(0xe7):display(15);break; //1110_0111
case(0xd7):display(14);break; //1101_0111
case(0xb7):display(13);break; //1011_0111
case(0x77):display(12);break; //0111_0111
}
}
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1