前言
大二下的时候,刚学32没两个星期就热血膨胀去做项目,做的是一个简易的函数信号发生器(过段时间整理下也放到博客上来),里头要用到矩阵键盘,就上淘宝买了个来摸索,半天愣是没整明白,就找师兄要了份代码,那时候我的C语言水平就只是在scanf,printf阶段,死活没看懂,死活不理解,然后也就那么套上去用了;后来慢慢学习磨练,代码敲得多一些,回过头去看,才把这个东西给领悟了,下面我就来讲一讲4*4矩阵键盘的扫描原理,给有需要的人看看,自己也算是一个巩固。
4*4矩阵键盘的扫描原理
先上一副4*4矩阵键盘的原理图
首先要说明的一点,矩阵键盘的动态扫描略显复杂,不可能就是读一个端口数据,然后马上就出来结果。这需要对依次每一行(或每一列)的按键进行扫描、判断,然后得出结果。
从原理图我们可以看出,4行每行串联接分别接到PA4-PA7,4列每列串联分别接到PA0-PA3;设置PA0-PA3为输入模式,设置PA4-PA7为输出模式;
如上图所示,先扫描第一行,也就是S1,S2,S3,S4四个按键的状态,我们在PA口输入0xEF(二进制1110 1111),假设这个时候S1被按下了,会出现什么情况?因为PA4是低电平,S1被按下之后S1导通,导致PA0的电平从1降到0,于是PA端口的数据就变成了1110 1110,换算成16进制就是0XEE。于是我们知道S1被按下了。同理,S2,S3,S4被按下也有对应的16进制值,就这样循环每一行扫描,就可以知道16个按键哪个被按下。
下面附上一段STM32的源代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66//按键初始化函数
void KEY_Init(void) //IO初始化
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能PORTA时钟
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化输入
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //输出
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化
}
u8 num = 16; //num用来存放当前按下的按键,当前赋值一个与处理无关的数,不让函数误操作
u32 a = 0; //a用来存放按下后处理的数据a = a*10+num;
//扫描按键程序
u8 getkey(void)
{
u8 keycode;
u8 scancode;
u8 i=0;
scancode = 0x10; //行扫描
for(i=0; i<4; i++)
{
GPIO_Write(GPIOA, ~scancode);
if((GPIO_ReadInputData(GPIOA)&0x0f) != 0x0f)
{
keycode = GPIO_ReadInputData(GPIOA); //读出的列值
while((GPIO_ReadInputData(GPIOA)&0x0f) != 0x0f) //等待按键松开
{
;
}
}
scancode <<= 1; //循环扫描
keycode &= 0x0f; //有按键按下为0,0x0f,只考虑低四位的处理,低四位为输入
switch(keycode)
{
case 0x0e:
num = 4 * i + 1;
break;
case 0x0d:
num = 4 * i + 2;
break;
case 0x0b:
num = 4 * i + 3;
break;
case 0x07:
num = 4 * i + 4;
break;
default:
keycode = 0xff;
break;
}
}
return num;
}
完结!