树莓派是一个让不是纯玩硬件的工程师在想玩硬件的时候,能够提供一个比较舒适的工具。但是,我和好几个也有玩树莓派的同学交流过,发现大家都是玩的纯软件,也就是都只是用树莓派玩 Linux。而我认为树莓派强大的地方在于它提供的各种扩展接口,例如 USB/GPIO口等,纯玩 Linux 能力还是差了些,比较难玩出一些花样来。这篇文章就介绍一下我是如何使用 GPIO 口来使用 4×4 的键盘的。

在介绍功能之前,肯定是要先看下原材料的,这里就直接给出一个列表好了:

这里的 4×4 矩阵键盘我用的是比较 low 的那种,也许你印象中的可能是这样的:

图 1:键盘示意图

但是,事实上,我用的是这样的:

图 2:键盘实体图

哈哈,虽然外貌不一样,但是,对于使用是不影响的,因为内部的工作原理是一致的,所以没关系。然后需要说一下的就是它们的工作原理,这里给出一个内部示意图:

4_m_4_matrix_keyboard_inner.jpg
图 3:内部示意图

这是一份电路示意图,示意得比较简单,可以看到有 8 个针口,分别是 1-8 口,然后分别对应于 4 行 4 列,可能这里你会有点疑惑,按照二进制来说,16个按钮,应该是 2 的 4 次方就够了,为什么要8个口。这里给你解释一下工作原理你就知道了.

这款键盘是非自带电源的,也就是无源的。那么我们怎么知道按下了那个键盘呢?工作原理是这样的:

我们可以在示意图中看到,其实行和列在按键未按下之前是不相通的,但是,一旦将键按下,那么行和列就通了,这样我们就可以从行的接收结果中知道按下了哪一列,然后在列的接收结果中知道按下了哪一行。

因此,按照这些规则,我们就可以连接键盘和 GPIO 口:

图 4:GPIO 接口

  1. 1 - GPIO 4
  2. 2 - GPIO 17
  3. 3 - GPIO 21
  4. 4 - GPIO 22

  1. 5 - GPIO 25
  2. 6 - GPIO 24
  3. 7 - GPIO 23
  4. 8 - GPIO 18

然后我就是使用 python 的 GPIO模块进行编写代码了:

  1. import RPi.GPIO as GPIO
  2. class keypad():
  3. # CONSTANTS
  4. KEYPAD = [
  5. [1, 2, 3, "A"],
  6. [4, 5, 6, "B"],
  7. [7, 8, 9, "C"],
  8. ["*", 0, "#", "D"]
  9. ]
  10. COLUMN = [25, 24, 23, 18]
  11. ROW = [22, 21, 17, 4]
  12. def __init__(self):
  13. GPIO.setmode(GPIO.BCM)
  14. def getKey(self):
  15. # Set all columns as output low
  16. for j in range(len(self.COLUMN)):
  17. GPIO.setup(self.COLUMN[j], GPIO.OUT)
  18. GPIO.output(self.COLUMN[j], GPIO.LOW)
  19. # Set all rows as input
  20. for i in range(len(self.ROW)):
  21. GPIO.setup(self.ROW[i], GPIO.IN, pull_up_down=GPIO.PUD_UP)
  22. # Scan rows for pushed key/button
  23. # A valid key press should set "rowVal" between 0 and 3.
  24. rowVal = -1
  25. for i in range(len(self.ROW)):
  26. tmpRead = GPIO.input(self.ROW[i])
  27. if tmpRead == 0:
  28. rowVal = i
  29. # if rowVal is not 0 thru 3 then no button was pressed and we can exit
  30. if rowVal <0 or rowVal >3:
  31. self.exit()
  32. return
  33. # Convert columns to input
  34. for j in range(len(self.COLUMN)):
  35. GPIO.setup(self.COLUMN[j], GPIO.IN, pull_up_down=GPIO.PUD_DOWN)
  36. # Switch the i-th row found from scan to output
  37. GPIO.setup(self.ROW[rowVal], GPIO.OUT)
  38. GPIO.output(self.ROW[rowVal], GPIO.HIGH)
  39. # Scan columns for still-pushed key/button
  40. # A valid key press should set "colVal" between 0 and 3.
  41. colVal = -1
  42. for j in range(len(self.COLUMN)):
  43. tmpRead = GPIO.input(self.COLUMN[j])
  44. if tmpRead == 1:
  45. colVal=j
  46. # if colVal is not 0 thru 3 then no button was pressed and we can exit
  47. if colVal < 0 or colVal > 3:
  48. self.exit()
  49. return
  50. # Return the value of the key pressed
  51. self.exit()
  52. return self.KEYPAD[rowVal][colVal]
  53. def exit(self):
  54. # Reinitialize all rows and columns as input at exit
  55. for i in range(len(self.ROW)):
  56. GPIO.setup(self.ROW[i], GPIO.IN, pull_up_down=GPIO.PUD_UP)
  57. for j in range(len(self.COLUMN)):
  58. GPIO.setup(self.COLUMN[j], GPIO.IN, pull_up_down=GPIO.PUD_UP)
  59. if __name__ == '__main__':
  60. # Initialize the keypad class
  61. kp = keypad()
  62. # Loop while waiting for a keypress
  63. digit = None
  64. while digit == None:
  65. digit = kp.getKey()
  66. # Print the result
  67. print digit

将这段代码保存为 keyboard4_4.py,然后执行它

  1. python keyboard4_4.py

你随便按下一个键,就会发现屏幕中打印出你按下的那个键了。