矩阵按键实现,欢迎来分享更好的矩阵按键实现方案!

2019-07-20 23:22发布


注意:IO口都要上拉。


一、IO口设置为开漏输出:
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA, ENABLE); 
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_InitStructure.GPIO_Mode =  GPIO_Mode_Out_OD;   
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 
GPIO_Init(GPIOA, &GPIO_InitStructure);

二、扫描程序:
uint8_t KeyScan(void)
{
int tmp;
    static int KeyConter = 0;
 int keyval;
 keyval = 0xFF;
    if (KeyConter < 1)
    {//去抖
                KeyConter++;
    }
else 
{
keyval = 0xFF;
GPIO_Write(GPIOA, 0x0F);          //GPIOA低四位置1,既行选全置1
tmp = (GPIO_ReadInputData(GPIOA) | 0xF0);//读取此时的列选的值
keyval &= tmp;
GPIO_Write(GPIOA, 0xF0);//列选全置1
tmp = (GPIO_ReadInputData(GPIOA) | 0x0F);//读取此时的行选的值
keyval &= tmp; //两次的结果相与得到是一个唯一值,既一个按键按下只有一个keyval与之对应
switch (keyval)
                {                                                  
                case 0xee:    return 1; 
                case 0xde:    return 2;
                case 0xbe:    return 3;
                case 0x7e:    return 4;              
                case 0xed:    return 5;
                case 0xdd:    return 6;
                case 0xbd:    return 7;
                case 0x7d:    return 8;
                case 0xeb:    return 9;
                case 0xdb:    return 10; //*
                case 0xbb:    return 11;
                case 0x7b:    return 12;  //#
case 0x77:    return 13; //下一位
                default:      return 0;
                }               

KeyConter=0;
}  
}

友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
18条回答
kxing91
1楼-- · 2019-07-21 21:45
回复【7楼】oceanzi:
------------------------
你的IO口多的用不掉的话可以。。
伟好好学习
2楼-- · 2019-07-22 01:20
 精彩回答 2  元偷偷看……
bruellyyang
3楼-- · 2019-07-22 05:39
楼主您好,看到程序还有些不懂的地方想请教下,望解答,谢谢。
首先是GPIO_Write(GPIOA, 0x0F);          //GPIOA低四位置1,既行选全置1
tmp = (GPIO_ReadInputData(GPIOA) | 0xF0);//读取此时的列选的值
上面的语句如果只读列的话,为什么不用&而是|。还有一个问题是当开关按下的时候,两端是低电平的时候导通,为什么不是高电平,开关两端的上拉对这个电平没有影响吗
150315175
4楼-- · 2019-07-22 07:23
本帖最后由 150315175 于 2016-6-29 16:07 编辑

请教一下,单片机引脚应该是读取电阻右边的电平吧?
GPIO_Write(GPIOA, 0x0F);          //GPIOA低四位置1,既行选全置1
tmp = (GPIO_ReadInputData(GPIOA) | 0xF0);//读取此时的列选的值
PA0~PA3置1,假设S1按下,那么PA4读取的状态是跟PA0相同是1吧?PA5~PA7(S2~S4)右侧没信号,但是左侧上拉应该读取都是1吧。
不是很明白,求解惑
bruellyyang
5楼-- · 2019-07-22 12:40
150315175 发表于 2016-6-29 16:06
请教一下,单片机引脚应该是读取电阻右边的电平吧?
GPIO_Write(GPIOA, 0x0F);          //GPIOA低四位置1 ...

我自己的理解是这样的,当拉高后是高电平,两边都是1;但是在按键按下的时候由于两边电平一样就会变成0,所以在开关按下的时候应该是低电平。还有tmp = (GPIO_ReadInputData(GPIOA) | 0xF0);//读取此时的列选的值;这句我感觉是不是应该读取行的值
bruellyyang
6楼-- · 2019-07-22 13:18
 精彩回答 2  元偷偷看……

一周热门 更多>