找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 22163|回复: 9
收起左侧

十分好用的4*4矩阵键盘扫描程序

  [复制链接]
ID:73477 发表于 2015-2-10 20:39 | 显示全部楼层 |阅读模式
        十分好用的4*4矩阵键盘扫描程序,更重要的是程序十分的简短,几行代码就解决了4*4 扫描取键值,防抖动 ,此程序运用了一个很巧妙的算法!上程序供大家研究,此程序经过改进,可以实现长按键识别 组合按键识别。如果有哪里不够好 也请大家指出。程序算法先自己研究,初学者如果看不明白,贴子顶起来,我给大家解释!把文本格式奉上 直接复制到你的程序里。


  1. volatile unsigned char CF[4]; //按键触发标志(表示4列,每一列同一行的
  2. //值是一样的但列标不一样来区分不同列的键)
  3. volatile unsigned char KeyVal;//键值
  4. code unsigned char KeyOut[4] = {0xef,0xdf,0xbf,0x7f}; //4X4按输出端控制
  5. #define KEY P2 //P2口作为4*4矩阵键盘输入
  6. /*
  7. **描述:新型4X4按键扫描程序 放在1ms-10ms中断内使用(十分稳定不需要再写消抖程序)
  8. **备注:按键弹起时 keyVal = 0 单键按下 keyVal 有16个值,你自己程序可以针对不同值
  9. **进行不同程序操作 keyVal单键值分别为
  10. **0x11,0x12,0x14,0x18,
  11. **0x21,0x22,0x24,0x28,
  12. **0x31,0x32,0x34,0x38,
  13. **0x41,0x42,0x44,0x48,
  14. */
  15. void Key_Head()
  16. {
  17. unsigned char ReadData[4];
  18. static unsigned char i;
  19. if(++i>=4)i=0;
  20. KEY = KeyOut[i]|0x0f; //忽略低4位
  21. ReadData[i] = (KEY|0xf0)^0xff; //忽略高4位 取反
  22. CF[i] = ReadData[i] & (ReadData[i] ^ Cont[i]);
  23. Cont[i] = ReadData[i];
  24. //输出键值
  25. switch(CF[i])//第i列
  26. {
  27. case 0x08: KeyVal = (i<<4+8);break;
  28. case 0x04: KeyVal = (i<<4+4);break;
  29. case 0x02: KeyVal = (i<<4+2);break;
  30. case 0x01: KeyVal = (i<<4+1);break;
  31. default:KeyVal = 0;break;
  32. }
  33. }
复制代码



回复

使用道具 举报

ID:82098 发表于 2015-6-21 05:48 | 显示全部楼层
谢谢!希望学习完整程序。
回复

使用道具 举报

ID:47843 发表于 2015-6-30 21:57 | 显示全部楼层
楼主好,程序好精练,中间有好多地方看不懂,但是复制下来,在程序中试了你的程序,发现少定义了Cont[i]数组,加上后,程序也不成功,请教在主函数中如何调用 你的函数,多谢了!
回复

使用道具 举报

ID:116657 发表于 2016-4-26 15:05 | 显示全部楼层
这个程序可以直接拿来输入数值吗
回复

使用道具 举报

ID:434759 发表于 2019-5-17 17:55 | 显示全部楼层
还烦请楼主解释一下
回复

使用道具 举报

ID:408350 发表于 2020-2-20 00:54 | 显示全部楼层
用不了啊!咋回事啊!
回复

使用道具 举报

ID:696996 发表于 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;
}


回复

使用道具 举报

ID:686739 发表于 2020-2-23 21:58 来自手机 | 显示全部楼层
学习了谢谢
回复

使用道具 举报

ID:860602 发表于 2021-1-9 09:07 | 显示全部楼层
楼主好,程序好精练,中间有好多地方看不懂,但是复制下来,在程序中试了你的程序,发现少定义了Cont[i]数组,加上后,程序也不成功,请教在主函数中如何调用 你的函数,多谢了!


在定时器1ms-10ms中断中进行调用
回复

使用道具 举报

ID:860602 发表于 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
        }
}
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表