ePy-Lite人機介面實作 – 使用PCF8574實現4*4 KeyPad
電路圖
程式列表
Python – PCF8574.py
|
""" Reference: MicroPython PCF8574 8-Bit I2C I/O Expander with Interrupt https://github.com/mcauser/micropython-pcf8574 I2CKeyPad https://github.com/RobTillaart/I2CKeyPad """
from machine import I2C, Pin
I2C_KEYPAD_NOKEY = 16 I2C_KEYPAD_FAIL = 17 keyDe = ['1','2','3','A', '4','5','6','B', '7','8','9','C', '*','0','#','D', 'N','F']
keymap = [0x77,0xB7,0xD7,0xE7, 0x7B,0xBB,0xDB,0xEB, 0x7D,0xBD,0xDD,0xED, 0x7E,0xBE,0xDE,0xEE]
class PCF8574:
def __init__(self, i2c, address=0x20): self._i2c = i2c self._address = address self._port = bytearray(1) if i2c.scan().count(address) == 0: raise OSError('PCF8574 not found at I2C address {:#x}'.format(address)) self._lastKey = I2C_KEYPAD_NOKEY
# mask = 4 rows as input pull up, 4 columns as output self._port[0] = 0xF0 self._write()
def port(self, value=None): if value is None: self._read() return self._port[0] else: self._port[0] = value & 0xFF self._write()
def pin(self, pin, value=None): pin = self.validate_pin(pin) if value is None: self._read() return (self._port[0] >> pin) & 1 else: if value: self._port[0] |= (1 << (pin)) else: self._port[0] &= ~(1 << (pin)) self._write()
def toggle(self, pin): pin = self.validate_pin(pin) self._port[0] ^= (1 << (pin)) self._write()
def validate_pin(self, pin): # pin valid range 0..7 if not 0 <= pin <= 7: raise ValueError('Invalid pin {}. Use 0-7.'.format(pin)) return pin
def _read(self): self._i2c.recv(self._port,self._address)
def _write(self): self._i2c.send(self._port,self._address)
def getKey(self,key): return keyDe[key]
# to check "press any key" def isPressed(self): # mask = 4 rows as input pull up, 4 columns as output self._port[0] = 0xF0 self._write() self._read() rows = self._port[0] if (rows == 0xFF) : return False return (rows != 0xF0);
def getKey4x4(self): # key = row + 4 x col key = 0
# mask = 4 rows as input pull up, 4 columns as output self._port[0] = 0xF0 self._write() self._read() rows = self._port[0]
# check if single line has gone low. if (rows == 0xF0): return I2C_KEYPAD_NOKEY elif (rows == 0x70): key = 0 elif (rows == 0xB0): key = 1 elif (rows == 0xD0): key = 2 elif (rows == 0xE0): key = 3 else: return I2C_KEYPAD_FAIL;
# 4 columns as input pull up, 4 rows as output self._port[0] = 0x0F self._write() self._read() cols = self._port[0]
# check if single line has gone low. if (cols == 0x0F): return I2C_KEYPAD_NOKEY elif (cols == 0x07): key += 0 elif (cols == 0x0B): key += 4 elif (cols == 0x0D): key += 8 elif (cols == 0x0E): key += 12 else: return I2C_KEYPAD_FAIL
self._lastKey = key
return key # 0..15
def getKey4_4(self): key = I2C_KEYPAD_NOKEY portout = bytearray(1)
for i in range(4) : portout[0] = ~(1<<i) self._port[0] = portout[0] self._write() self._read() portin = self._port[0]
if portin != portout[0] : try: key = keymap.index(portin) except: key = I2C_KEYPAD_FAIL break
return key # 0..15 |
Python – epy-Lite_PCF8574.py
|
""" epy-Lite_PCF8574.py
ePy-Lite PCF8574 KEYPAD ---------- +--------+ +--------+ 3V3 | VCC 0|----|R | P17_SCL0 | SCL 1|----|O | P16_SDA0 | SDA 2|----|W | GND | GND 3|----|S | | | | | | INT 4|----|C | | 5|----|O | | 6|----|L | | 7|----|S | +--------+ +--------+ """
from machine import Switch #Get button KEY library from machine import I2C, Pin, LED from machine import Timer import utime import pcf8574
KEYPAD_ADDRESS = 0x20
def tick3(timer): global TimerDone TimerDone = True return TimerDone
def key_int(): global KeyADone KeyADone = True
# Start Function if __name__ == '__main__': ledY = LED('ledy') ledY.off()
KeyA = Switch('keya') #Create button A KeyA.callback(key_int) KeyADone = False
timer = Timer(3,freq=10) timer.callback(tick3) TimerDone = False
# Declaration I2C i2c_0 = I2C(0,I2C.MASTER,baudrate=100000) #Create I2C0 Master Mode, Baudrate=100kHz pcf = pcf8574.PCF8574(i2c_0, KEYPAD_ADDRESS) LastKey = pcf8574.I2C_KEYPAD_NOKEY keyChange = False
print("--- Start ---") while True: if TimerDone == True: TimerDone = False # read all pins at once as 8-bit int # print(pcf.port())
getKey=pcf.getKey4x4() # getKey=pcf.getKey4_4() # print(getKey) if (getKey < pcf8574.I2C_KEYPAD_NOKEY) : NewKey = pcf.getKey(getKey) if NewKey != LastKey : LastKey = NewKey keyChange = True print("press " + NewKey + " key") else : print("press old key") elif ((getKey == pcf8574.I2C_KEYPAD_NOKEY)and(keyChange == True)) : keyChange = False print("release")
if KeyADone == True: #Press A Key break
i2c_0.deinit() KeyA.callback(None) print("--- End ---") |
Python – epy-Lite_PCF8574_Int.py
|
""" epy-Lite_PCF8574_Int.py
ePy-Lite PCF8574 KEYPAD ---------- +--------+ +--------+ 3V3 | VCC 0|----|R | P17_SCL0 | SCL 1|----|O | P16_SDA0 | SDA 2|----|W | GND | GND 3|----|S | | | | | P18 | INT 4|----|C | | 5|----|O | | 6|----|L | | 7|----|S | +--------+ +--------+ """
from machine import Switch #Get button KEY library from machine import I2C, Pin, LED from machine import Timer import utime import pcf8574
KEYPAD_ADDRESS = 0x20
def tick3(timer): global TimerDone TimerDone = True return TimerDone
def key_int(): global KeyADone KeyADone = True
def pin_callback_fun(pin): global KeyPadIntDone ledY.toggle() KeyPadIntDone = True
# Start Function if __name__ == '__main__': ledY = LED('ledy') ledY.off()
KeyA = Switch('keya') #Create button A KeyA.callback(key_int) KeyADone = False
timer = Timer(3,freq=10) timer.callback(tick3) TimerDone = False
# Declaration I2C i2c_0 = I2C(0,I2C.MASTER,baudrate=100000) #Create I2C0 Master Mode, Baudrate=100kHz pcf = pcf8574.PCF8574(i2c_0, KEYPAD_ADDRESS) LastKey = pcf8574.I2C_KEYPAD_NOKEY keyChange = False
KeyPadInt = Pin(Pin.epy.P18,Pin.IN,Pin.PULL_UP) KeyPadInt.irq(handler=pin_callback_fun , trigger=Pin.IRQ_FALLING) KeyPadIntDone = False
print("--- Start ---") while True: if TimerDone == True: TimerDone = False
if KeyPadIntDone == True: KeyPadIntDone = False getKey=pcf.getKey4x4() # getKey=pcf.getKey4_4() if (getKey < pcf8574.I2C_KEYPAD_NOKEY) : NewKey = pcf.getKey(getKey) if NewKey != LastKey : LastKey = NewKey keyChange = True print("press " + NewKey + " key") else : print("press old key") elif ((getKey == pcf8574.I2C_KEYPAD_NOKEY)and(keyChange == True)) : keyChange = False print("release")
if KeyADone == True: #Press A Key break
i2c_0.deinit() KeyA.callback(None) print("--- End ---") |
執行結果