I have attached a full list of the test program for your comments. The 308 line long program is a
Code: Select all
# iox01.1095 tlfong01 2018aug11hkt1626
# *** Import ***
import datetime
import time
import smbus
# *** Config ***
# *** MCP23017 Device Register Address Dictionary (iocon.bank = 0) ***
regAddrByte = \
{
'IODIRA' : 0x00,
'IODIRB' : 0x01,
'IPOLA' : 0x02,
'IPOLB' : 0x03,
'GPINTENA' : 0x04,
'GPINTENB' : 0x05,
'DEFVALA' : 0x06,
'DEFVALB' : 0x07,
'INTCONA' : 0x08,
'INTCONB' : 0x09,
'IOCON' : 0x0b,
'IOCON' : 0x0a,
'GPPUA' : 0x0c,
'GPPUB' : 0x0d,
'INTFA' : 0x0e,
'INTFB' : 0x0f,
'INTCAPA' : 0x10,
'INTCAPB' : 0x11,
'GPIOA' : 0x12,
'GPIOB' : 0x13,
'OLATA' : 0x14,
'OLATB' : 0x15,
'PortA' : \
{
'Direction' : 0x00,
'OutLatch' : 0x14,
'GpioPort' : 0x12,
},
'PortB' : \
{
'Direction' : 0x01,
'OutLatch' : 0x15,
'GpioPort' : 0x13,
'IntPinsEnable' : 0x05,
'IntPinsDefault' : 0x07,
'IntPinsCompare' : 0x09,
'InterruptFlagByte' : 0x0f,
'IntCap' : 0x11,
'PullUp' : 0x0d
},
}
# *** MCP23017 Control Byte Dictionary ***
controlByte = \
{
'WriteRegBaseByte' : 0x40,
'ReadRegBaseByte' : 0x41,
'EnableAddressPins' : 0x08,
'AllPinsOutput' : 0x00,
'AllPinsInput' : 0xff,
'LowNibblePinsOutputHighNibblePinsInput' : 0xf0,
'IntAllPinsEnable' : 0xff,
'IntPinsEnable' : 0xff,
'IntAllPinsCompareDefault' : 0xff,
'AllPinsPullUp' : 0xff,
'AllHigh' : 0xff,
'AllLow' : 0x00,
'AllPinsHigh' : 0xff,
'AllPinsLow' : 0x00,
'IntAllPinsHigh' : 0xff,
'IntAllPinsLow' : 0x00,
'IntLowNibblePinsEnable' : 0x0f,
'IntLowNibblePinsComparePrevious' : 0x00,
'0x01' : 0x01,
'0x55' : 0x55,
'0x66' : 0x66,
'0xaa' : 0xaa,
'0x0f' : 0x0f,
'0xf0' : 0xf0,
}
# *** MCP23017 Config Bit Dictionary ***
basicCnfgBits = \
{
'BaseByte' : 0x00,
'RegAddrBank0' : 0b0 << 7,
'TwoIntPinsNoMirror' : 0b0 << 6,
'TwoIntPinsMirror' : 0b1 << 6,
'AutoIncRegAddrDisable' : 0b1 << 5,
'SlewRateDiable' : 0b0 << 4,
'HardwareAddrEnable' : 0b1 << 3,
'ActiveDriver' : 0b0 << 2,
'OpenDrain' : 0b1 << 2,
'IntActiveLevelHigh' : 0b1 << 1,
'IntActiveLevelLow' : 0b0 << 1,
'Unimplemented' : 0b0 << 0,
}
# Notes:
# Byte mode = disable automatic Address Pointer incrementing.
# Sequential mode = enable automatic Address Pointer incrementing.
# Toggle register pointer mode = Byte mode with IOCON.BANK = 0
# GPIO module = 16 bit bidirectional port splie into 2 8-bit ports
# GPIO module contains
# (1) Data ports (GPIOn),
# (2) Output latches (OLATn)
# (3) Pull up resistors
# GPIO and OLAT relationship (Datasheet Section 3.4)
# Reading GPIOn register read the value on the port.
# Reading OLATn register only reads the latches, NOT the actual value on the port.
# Writing to the GPIOn register actually causes a write ot the latches (OLATn).
# Writing to the OLATn register forces the associated output drivers to drive to
# the level in OLATn.
# Pins configured as inputs turn off the associated output driver and put it in
# high impedance
# ***MCP23017 Default Config Byte ***
# Notes - V0.1.1092 tlfong01 2018aug11hkt1330
# Bank number = 0
# Interrupt flags configuration = mirror
# Hardware address select = On
# Interrupt pin configuration = Totem Pole (push/pull, not open drain)
# Interrupt trigger level = low
basicCnfgBnk0NoMrrNoAutoIncActDrvIntHghAct = \
basicCnfgBits['BaseByte'] | \
basicCnfgBits['RegAddrBank0'] | \
basicCnfgBits['TwoIntPinsMirror'] | \
basicCnfgBits['AutoIncRegAddrDisable'] | \
basicCnfgBits['SlewRateDiable'] | \
basicCnfgBits['HardwareAddrEnable'] | \
basicCnfgBits['ActiveDriver'] | \
basicCnfgBits['IntActiveLevelLow'] | \
basicCnfgBits['Unimplemented']
# *** System Time Functions ***
def getTimeNowStr():
timeNowStr = str(datetime.datetime.now())[0:16]
return timeNowStr
# *** Generic I2C Device Register Functions ***
def readDvRegOneByte(i2cCh, dvAddrByte, DvRegAddrByte):
readByte = i2cCh.read_byte_data(dvAddrByte, DvRegAddrByte)
return readByte
def writeDvRegOneByte(i2cCh, dvAddrByte, DvRegAddrByte, writeByte):
writeDvTwoBytes(i2cCh, dvAddrByte, DvRegAddrByte, writeByte)
return
def writeDvTwoBytes(i2cCh, dvAddrByte, dataByte1, dataByte2):
i2cCh.write_byte_data(dvAddrByte, dataByte1, dataByte2)
return
def printDvRegOneByte(i2cCh, dvAddrByte, dvRegAddrByte, printTitle):
readByte = readDvRegOneByte (i2cCh, dvAddrByte, dvRegAddrByte)
print(printTitle, hex(readByte))
def writeDvRegOneBlock(i2cCh, dvAddrByte, dvRegAddrByte, writeBlock):
i2cCh.write_block_data(dvAddrByte, dvRegAddrByte, writeBlock)
return
# *** Specific I2C MCP23017 Device Register Functions ***
def readRegOneByte(regName):
dvRegAddrByte = regAddrByte[regName]
readByte = readDvRegOneByte(i2cCh, dvAddrByte, dvRegAddrByte)
return readByte
def writeRegOneByte(regName, writeByte):
dvRegAddrByte = regAddrByte[regName]
writeDvRegOneByte(i2cCh, dvAddrByte, dvRegAddrByte, writeByte)
return
def writeRegOneBlock(i2cCh, dvAddrByte, regName, writeBlock):
dvRegAddrByte = regAddrByte[regName]
i2cCh.write_block_data(dvAddrByte, dvRegAddrByte, writeBlock)
return
def printRegOneByte(regName, printTitle):
readByte = readRegOneByte(regName)
print(' ', printTitle, hex(readByte))
return
# *** Test Functions ***
def testWriteReadPrintIoDirRegA(testDataByte):
printRegOneByte('IODIRA', 'Old Byte =')
writeRegOneByte('IODIRA', testDataByte)
printRegOneByte('IODIRA', 'New Byte =')
return
def testWriteReadOneByteIoDirA():
programTitle = 'testWriteReadPrintOneByteIoDirRegA'
print('*** Begin', programTitle, ' ***\n')
timeNowStr = getTimeNowStr()
print(' Time = ', timeNowStr, '***\n')
dataByte0x55 = 0x55
dataByte0xaa = 0xaa
testWriteReadPrintIoDirRegA(dataByte0x55)
testWriteReadPrintIoDirRegA(dataByte0xaa)
print('\n')
print('*** End ', programTitle, ' ***\n')
return
def testRepeatWriteOneBlock0x0f0x550xf0IoDirA():
programTitle = 'testRepeatWriteBlock0x0f0x550xf0IoDirA'
print('*** Begin', programTitle, ' ***\n')
timeNowStr = getTimeNowStr()
print(' Time = ', timeNowStr, '***\n')
writeBlock = [0x0f, 0x55, 0xf0]
print(' Writing block begin, ...')
ioDirRegAddrByteA = regAddrByte['IODIRA']
for count in range(500):
writeRegOneBlock(i2cCh, dvAddrByte, 'IODIRA', writeBlock)
time.sleep(0.01)
print(' Writing block end.')
print('\n')
print('*** End ', programTitle, ' ***\n')
return
def testRepeatWriteOneBlock0xf00x0fGpioA():
programTitle = 'testRepeatWriteBlock0xf00x0fGpioA'
print('*** Begin', programTitle, ' ***\n')
timeNowStr = getTimeNowStr()
print(' Time = ', timeNowStr, '***\n')
writeBlock = [0xf0, 0x0f]
print(' Writing block begin, ...')
ioDirRegAddrByteA = 0x00
for count in range(500):
writeRegOneBlock(i2cCh, dvAddrByte, 'IODIRA', writeBlock)
time.sleep(0.01)
print(' Writing block end.')
print('\n')
print('*** End ', programTitle, ' ***\n')
return
# *** Init ***
def configDv01():
# *** Config MCP23017 no autoincrement of register address pointer ***
configByte = basicCnfgBnk0NoMrrNoAutoIncActDrvIntHghAct
writeRegOneByte('IOCON', configByte)
# *** Config IO Direction Port A as all pint output ***
ioConfigByteName = 'AllPinsOutput'
ioConfigByte = controlByte[ioConfigByteName]
writeRegOneByte('IODIRA', ioConfigByte)
return
i2cCh = smbus.SMBus(1)
dvAddrByte = 0x22
configDv01()
# *** Test ***
def test():
print('')
testWriteReadOneByteIoDirA()
#testRepeatWriteOneBlock0x0f0x550xf0IoDirA()
testRepeatWriteOneBlock0xf00x0fGpioA()
return
# *** Main ***
test()
# *** Sample Output ***
'''
========== RESTART: /home/pi/python_programs/test1094/iox01.004.py ==========
*** Begin testWriteReadPrintOneByteIoDirRegA ***
Time = 2018-08-11 15:58 ***
Old Byte = 0x0
New Byte = 0x55
Old Byte = 0x55
New Byte = 0xaa
*** End testWriteReadPrintOneByteIoDirRegA ***
*** Begin testRepeatWriteBlock0xf00x0fGpioA ***
Time = 2018-08-11 15:58 ***
Writing block begin, ...
Writing block end.
*** End testRepeatWriteBlock0xf00x0fGpioA ***
>>>
'''
# *** End ***