OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 7090|回复: 7

8*8矩阵键盘多键同时识别问题

[复制链接]

2

主题

5

帖子

0

精华

新手上路

积分
31
金钱
31
注册时间
2017-8-11
在线时间
6 小时
发表于 2017-9-9 07:59:51 | 显示全部楼层 |阅读模式
1金钱
初学STM32,做个8*8矩阵键盘试验,编了个小程序,已经能识别同时按下或松开的任意单个键,
用GPIOF高8位为行,GPIOF低8位为列,对GPIOF的总键值进行异或,取得活动键值,并判断是按下还是松开;
64KEY.jpg
[url=]20 秒后保存[/url] [url=]保存数据[/url] | [url=]恢复数据[/url]    [url=]字数检查[/url] | [url=]清除内容[/url]    [url=]加大编辑框[/url] | [url=]缩小编辑框[/url]



附加选项



本版积分规则发布悬赏(求助)  保存草稿








HL.jpg


源程序如下:


问题来了:
Action_key为本次活动按键的键值,如果每次取键值时,活动按键只有1个,那么最终的Action_key中高8位只有1个1,低8位也只有1个,很容易得出键值;
但是,如果同时按下2个键,如下图的A、B两键,最终得到Action_key的键值,与同时按下C、D两键,最终得到Action_key的键值完全相同,有什么办法能够正确识别真正按下的A、B两个按键呢








正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

2

主题

5

帖子

0

精华

新手上路

积分
31
金钱
31
注册时间
2017-8-11
在线时间
6 小时
 楼主| 发表于 2017-9-9 08:00:31 | 显示全部楼层
源码如下:

#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "key.h"
#include "stm32f4xx_gpio.h"


//ALIENTEK 探索者STM32F407开发板 实验3
//按键输入实验-库函数版本
//技术支持:www.openedv.com
//淘宝店铺:http://eboard.taobao.com
//广州市星翼电子科技有限公司   
//作者:正点原子 @alientek

//8*8矩阵按键输入识别,GPIOF高8位为行,GPIOF低8位为列


void Input_KEY_Init(void)
{
        GPIO_InitTypeDef  GPIO_InitStructure;
        RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能GPIOF时钟
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|

GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|

GPIO_Pin_11|GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15; //KEY对应引脚
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//普通输入模式
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100M
        GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;//下拉模式
        GPIO_Init(GPIOF, &GPIO_InitStructure);//初始化GPIOF
}

int Count1(unsigned char n)
{
    int sum=0;
    while(n)
    {
        n&=(n-1);
        sum++;
    }
    return sum;
}


int main(void)
{
       
        u16

Last_key=0,Current_key=0,key_bit=0,key_H8=0xff00,key_L8=0x00ff,Action_key=0;        
        int i,j;
       
       
       
        uart_init(115200);

        Input_KEY_Init();        //GPIOF的16位IO初始化,下拉输入
        delay_init(100);          //初始化延时函数
        while(1)
        {

                delay_ms(200);
                Current_key=GPIO_ReadInputData(GPIOF);                //得到当前总键值
           if(Current_key!=Last_key)
             {       
                        printf("\n位键值bit= ");
                        for(i=0x8000;i>=0x0001;i=i>>1)        //显示GPIOF的16位IO的各位数值
                        {
                                key_bit=GPIO_ReadInputDataBit(GPIOF,i);
                                printf("%d ",key_bit);
                        }
                        printf("\n\n当前总键值Current_key=%x \n",Current_key);
               
                        key_H8=0xff00&Last_key;                //取得上次总键值的高8位;
                        key_L8=0x00ff&Last_key;                //取得上次总键值的低8位;
                        printf("\n Last_key高8位=%x \n",key_H8);
                        printf("\n Last_key低8位=%x \n",key_L8);
                       
                        Action_key=Current_key^Last_key;
                        printf("\n Current_key^Last_key=%x \n",Action_key);
               
                        if(        0==(0xff00&Action_key))        //判断是否同行
                        {       
                        Action_key=Action_key|key_H8;                //取回原行值
                        }
                        if(        0==(0x00ff&Action_key))        //判断是否同列
                        {       
                        Action_key=Action_key|key_L8;                //取回原列值
                        }       
                       
                i=Count1(Last_key);
                j=Count1(Current_key);
                if(j>i) //有键按下;
                {printf("\n 按下按键=%x \n",Action_key);        }
                if(j<i) //有键松开;
                {printf("\n 松开按键=%x \n",Action_key);        }

                Last_key=Current_key;
             }       
                       
        }

}






回复

使用道具 举报

2

主题

5

帖子

0

精华

新手上路

积分
31
金钱
31
注册时间
2017-8-11
在线时间
6 小时
 楼主| 发表于 2017-9-9 08:03:35 | 显示全部楼层
程序在开发板调试运行通过
回复

使用道具 举报

50

主题

1805

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6662
金钱
6662
注册时间
2016-5-29
在线时间
910 小时
发表于 2017-9-9 09:23:34 | 显示全部楼层
应该是同时按下ADC,或者得到同时按下ABCD的结果吧.这个叫幻影键.又称鬼键..这个没有办法.硬件上决定了一定会有.
回复

使用道具 举报

2

主题

5

帖子

0

精华

新手上路

积分
31
金钱
31
注册时间
2017-8-11
在线时间
6 小时
 楼主| 发表于 2017-9-9 09:59:47 | 显示全部楼层
操作系统 发表于 2017-9-9 09:23
应该是同时按下ADC,或者得到同时按下ABCD的结果吧.这个叫幻影键.又称鬼键..这个没有办法.硬件上决定了一定 ...

请教,我有个想法,有7个延迟芯片,把9到15行的输入分别延迟不同的时间,延迟时间大于防抖扫描周期,强制控制每次扫描只能得到同一行上的键,你看这样可以吗?
回复

使用道具 举报

50

主题

1805

帖子

0

精华

论坛元老

Rank: 8Rank: 8

积分
6662
金钱
6662
注册时间
2016-5-29
在线时间
910 小时
发表于 2017-9-9 10:53:58 | 显示全部楼层
随便怎么处理,都行不能.这是硬件决定的.软件没有办法
回复

使用道具 举报

29

主题

338

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1181
金钱
1181
注册时间
2018-4-13
在线时间
170 小时
发表于 2018-11-9 09:26:22 | 显示全部楼层
操作系统 发表于 2017-9-9 10:53
随便怎么处理,都行不能.这是硬件决定的.软件没有办法

能不能详细些,到底硬件怎么不行导致的?
回复

使用道具 举报

0

主题

1

帖子

0

精华

新手上路

积分
20
金钱
20
注册时间
2020-5-13
在线时间
8 小时
发表于 2020-5-20 10:35:18 | 显示全部楼层
鬼键原理.jpg

回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-8 09:03

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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