65.9K
CodeProject 正在变化。 阅读更多。
Home

在 Arduino 中使用矩阵键盘

starIconstarIconstarIconstarIconstarIcon

5.00/5 (2投票s)

2014年1月14日

CPOL

6分钟阅读

viewsIcon

56311

downloadIcon

704

另一个 Arduino.Keypad 库

引言

如果您对 Arduino 感兴趣,您可能听说过矩阵键盘。它们广泛用于 Arduino 项目中输入数字数据。矩阵键盘的例子(我有一个)可以在 这里 找到,官方的 Arduino 矩阵键盘库可以在 这里 找到。
 

背景

我不喜欢 Arduino 提供的库,因为它不必要地复杂。矩阵键盘实际上非常简单。举个例子,假设您有一个“4 行 X 3 列”的键盘。它有 12 个按键和 7 个引脚。这些引脚对应于行和列。

您可以在 这里 找到我的键盘的数据手册。我的键盘的按键及其对应的 <行引脚, 列引脚> 对如下:

按键:行引脚 + 列引脚
1: 2 + 3
2: 2 + 1
3: 2 + 5
4: 7 + 3
5: 7 + 1
6: 7 + 5
7: 6 + 3
8: 6 + 1
9: 6 + 5
*: 4 + 3
0: 4 + 1
#: 4 + 5

当您按下按键时,比如“1”,其对应的引脚会被短接。这意味着,当您给按键的行引脚发送信号时,您会从该按键的列引脚读到相同的值,反之亦然。如果您按下键盘上的“1”,您会看到引脚 2 和 3 被短接了。

正如您所注意到的,按键 [1..3] 共享同一个行引脚,即 pin2,而按键 [1,4,7,*] 共享同一个列引脚,即 pin3。

您的键盘在按键数量、引脚和它们与按键的映射方面可能有所不同。因此,如果您有一个键盘但没有任何文档,您应该首先使用万用表找出按键与引脚之间的关系。

硬件设置

在本节中,我将尝试以我的键盘为例,解释如何将矩阵键盘连接到 Arduino 板。您的键盘结构可能与我的不同,但同样的规则适用。

我的键盘有 7 个引脚,因此我为我的 Arduino 板分配了 7 个数字引脚,从 2 到 8。

首先,将键盘的行引脚连接到 Arduino。但要注意引脚的顺序。键盘的 Row1 引脚(即 pin 2)将连接到 Arduino 的数字引脚 2,依此类推。我键盘的所有连接如下:

键盘引脚 => Arduino 数字引脚
2 (row1) => 2
7 (row2) => 3
6 (row3) => 4
4 (row4) => 5
3 (col1) => 6
1 (col2) => 7
5 (col3) => 8

现在,您已准备好测试该库。请记住,该库的默认配置是根据我上面解释的我的键盘配置的。如果您的键盘与我的不同,您的硬件设置和软件配置必须进行调整。下面将说明如何进行新的软件配置。

 

使用代码

您期望从矩阵键盘中得到什么?很简单。哪个按键被按下,哪个按键被释放?
让我们开始吧。

当您将库放入 Arduino IDE 的库文件夹中时,您就可以使用它了。

首先,包含该库并创建一个实例。

#include <Keypad2.h>
Keypad2 kp(1); // create default keypad.  

在 setup 函数中,指定您的按键按下和释放事件的回调函数。

void setup() {
  Serial.begin(9600); // initialize Serial
  kp.setPressCallback(kpPressCallback); // set keypad callback function
}

以及回调函数的实现

void kpPressCallback(char c, uint8_t state) {
 Serial.print(c);
 Serial.print(" ");
 Serial.print(state == KP2_KEYUP ? "up":"down");
 Serial.println();
}   

别忘了在主循环中监控您的键盘。

void loop() {
  kp.update();
} 

您的键盘的布局(按键数量、引脚、按键与引脚的关系)可能与默认的布局不同,当然。在这种情况下,您必须通过调用 setLayout 函数来提供新的配置。其在头文件中的原型如下:

 // initialize hardware layout, both keypad & arduino
 // if not called, default layout should be used in constructor
 // parameters:
 // 1- row count
 // 2- column count
 // 3- keypad layout
 // 4- key states (2 bits for each key)
 // 5- row pins
 // 6- column pins
 // 7- internal pullup usage (0 for external pullups)
 void setLayout(int rowc, int colc, char **layout, uint8_t *keyState, \
     int *rowp, int *colp, uint8_t useInternalPullup);

以及库的默认配置(描述了我的键盘)

// default layout
const char kp2DefaultLayout[4][3] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
};
// 2 bits for each key to store its state
// 12*2/8 = 3 bytes for default layout
const uint8_t kp2DefaultStateHolder[3] = {0, 0, 0};
const int kp2RowPins[4] = {2,3,4,5}; // connect to keypad pins 2,7,6,4 respectively
const int kp2ColPins[3] = {6,7,8};   // connect to keypad pins 3,1,5 respectively
// end of default layout  

当您像本节开头那样,使用 1(true)作为参数调用构造函数时,幕后所做的事情是使用默认参数调用 setLayout 函数,如下所示:

if(useDefaultLayout) {
  this->setLayout(4, 3, (char **)kp2DefaultLayout, (uint8_t *)kp2DefaultStateHolder, \
   (int *)kp2RowPins, (int *)kp2ColPins, 1);
} 

如果您的配置与默认配置不同,您必须使用适当的参数调用 setLayout 函数。在这种情况下,我会这样做:

- 从头文件中复制默认值并粘贴到我的代码中 :)
- 根据新的键盘编辑默认值
- 重命名参数

让我们通过一个例子来学习。假设我们的键盘是一个带有十六进制值的矩阵键盘。4x4 十六进制矩阵键盘可能看起来像这样:

1 | 2 | 3 | 4
5 | 6 | 7 | 8
9 | 0 | A | B
C | D | E | F

因此,对于 4 行和 4 列,必须有 8 个引脚。假设引脚与行和列的关系如下:
引脚 | 行/列
1 | row1
2 | row3
3 | row2
4 | row4
5 | col2
6 | col4
7 | col1
8 | col3

我们必须在 Arduino 板上分配 8 个数字引脚。假设分配了引脚 [2..9]。我们的参数应该是:

// hex keypad layout
const char layout[4][4] = {
  {'1','2','3','4'},
  {'5','6','7','8'},
  {'9','0','A','B'},
  {'C','D','E','F'}
};
// 2 bits for each key to store its state
// 16*2/8 = 4 bytes for states
const uint8_t stateHolder[4] = {0, 0, 0, 0};
const int rowPins[4] = {2,3,4,5}; // connect to keypad pins 1,3,2,4 respectively
const int colPins[4] = {6,7,8,9};   // connect to keypad pins 7,5,8,6 respectively
// end of hex keypad layout  

我们已经准备好了硬件,进行了连接,准备了布局配置,并且我们已经准备好创建一个实例。

#include <Keypad2.h>
Keypad2 kp(0); // will be configured as hex keypad  

在 setup 函数中,调用 setLayout。

this->setLayout(4, 4, (char **)layout, (uint8_t *)stateHolder, \
   (int *)rowPins, (int *)colPins, 1);

就是这样。您就可以使用您的十六进制键盘了。需要注意的是,stateHolder 是供内部使用的。您只需为库提供一些内存来跟踪按键。

关注点

我见过很多关于上拉电阻以及将它们放置在矩阵键盘电路上的讨论。实际上,您不需要它们,只需使用内置的上拉电阻即可!

按键检测算法是“扫描行和列”。正如我在介绍部分所说,按下按键时,行和列引脚会被短接。通过将行引脚设置为 INPUT,将列引脚设置为 OUTPUT,可以尝试对每个列发送信号并从每个行读取。如果您从行中读到相同的值,这意味着它们对应的按键被按下,否则就是释放。

事实上,我可以使用动态内存分配来存储状态,以减少传递给 setLayout 函数的参数数量。但是,如果我不需要,我不会使用这种技术。它非常容易出错,并且如果您犯了错误,很难发现。

我讨厌矩阵键盘的一点是,它是 Arduino 板引脚的敌人。您需要分配太多数字引脚才能使用它。如果有一个串行版本,可以在按键按下时通知我的 Arduino,那就太好了。您知道这样的东西吗?
 

© . All rights reserved.