早在我將舊型電話按鍵盤改做數字鍵盤之前,就覺得直接驅動 3x4 數字鍵盤至少需要用到 7 條 GPIO 接線,這樣太過佔用 GPIO 腳位了,便有了該將之改造成 I²C (Inter-Integrated Circuit) 介面的想法。

尋找到的 MCP23008 是一個具有將串列介面擴充成 8 位元輸入/輸出的 IC,查看了它的 data sheet,直覺應該可以達成目的,便先買了兩顆來試試。
在 Raspberry Pi 的測試
若不能確認 Raspbian 是否已啟用 I²C,可參考 Using the I2C Interface 的說明,該文也列出了稍後即將使用到的 SMBus Functions。
再來要在麵包板上接線-將 Raspberry Pi 與 MCP23008 的 I²C 信號腳位連接,MCP23008 的 GPIO 與數字鍵盤的接腳連接,如以下所示。
RPi MCP23008 3x4 Keypad --- -------- ---------- SCL <---> SCL SDA <---> SDA 3V3 <---> VDD GND <---> VSS GP0 ----> C1 GP1 ----> C2 GP2 ----> C3 GP3 <---- R1 GP4 <---- R2 GP5 <---- R3 GP6 <---- R4
MCP23008 有三個接腳 (A0, A1, A2) 是用來設定從屬裝置在 I²C bus 上的位址 (address),將其皆接在 GND 可得位址為 0x20,事後可用 i2cdetect 指令確認位址是否如預期。另外還有 i2cget 與 i2cset 兩個指令可用來對從屬裝置做讀取與寫入。
1 2 3 4 5 6 7 8 9 10 | pi@raspberrypi ~ $ sudo i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: 20 -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- |
MCP23008 內部有 11 個暫存器做設定與控制用的,以下稱 CCR (Configuration and Control Registers),程式將對這些 CCR 進行讀取或寫入以達成與所連接的裝置通信或控制的目的。
我將這些基本功能編寫成一個 MCP23008 類別以方便讀取或寫入 CCR,基於此再編寫了一個 MyNumPad 類別,使應用程式輕易讀取數字鍵盤的輸入。程式範例如下:
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 | #!/usr/bin/python from mcp23008 import MCP23008 import time class MyNumPad: keys = [[ '1' , '2' , '3' ],[ '4' , '5' , '6' ],[ '7' , '8' , '9' ],[ '*' , '0' , '#' ]] def __init__( self , address): self .mcp = MCP23008(address) def read( self ): self .mcp.writeByte( 'IODIR' , 0b11111000 ) self .mcp.writeByte( 'GPIO' , 0 ) self .mcp.writeByte( 'GPPU' , 0b11111111 ) for i in range ( 3 ): self .mcp.writeByte( 'GPIO' , ( 1 << i) ^ 0b11111111 ) time.sleep( 0.05 ) v = ( self .mcp.readByte( 'GPIO' ) | 0b00000111 ) ^ 0b11111111 for j in range ( 4 ): if (v & ( 0b00001000 << j)) ! = 0 : time.sleep( 0.1 ) return self .keys[j][i] return 0 # test read input from MyNumPad try : npad = MyNumPad( 0x20 ) while True : ch = npad.read() if ch ! = 0 : print ch except KeyboardInterrupt: pass |
使用 MCP23008 的小提示
各 GPIO 接腳僅可做內部 PULL-UP 的控制,不像直接使用 Raspberry Pi 的 GPIO 可以控制做 PULL-UP 或 PULL-DOWN,所以程式在掃瞄鍵盤按下時是要判斷電位為 LOW。
另外,RESET 與三個位址接腳不要空接,否則 MC23008 可能會處在不穩定的狀態。
下次,來試試接 16x2 LCD 顯示器模組。
沒有留言:
張貼留言