Ekspander 2x8bit I2C MCP23017

Moderator: bbiernat

Post Reply
User avatar
pancio
Administrator
Posts: 67
Joined: 18 September 2013, 23:02 - Wed
Location: SILESIA

Ekspander 2x8bit I2C MCP23017

Post by pancio »

Tym razem zajmiemy się dość popularnym ekspanderem 16 bitowym (2x8bit) MCP23017, który to ze względu na swoje możliwości znacznie przewyższa omawiany już wcześniej PCF8574. Mimo iż MCP23017 posiada w swojej strukturze aż 21 rejestrów, jego sterowanie wcale nie jest skomplikowane a w przypadku prostych adaptacji wręcz sprowadza się do kilku linijek kodu. Niestety nie posiadam gotowego modułu, postanowiłem zatem zmontować coś na szybko:
mcp23017_application.png
Jest to typowa najprostsza aplikacja, Ze schematu można wyczytać, że układ będzie znajdował się pod adresem bazowym 0x20 (A0 = A1 = A2 = GND). Należy też pamiętać o podciągnięciu pinu RESET (rezystor 1k) oraz ograniczeniu prądu diod LED (300 ohm). Oczywiście, w naszych dalszych projektach można użyć drugiego portu (np jako wejściowego) oraz sygnałów przerwań (by np. nasz CT zareagował na zmiany na porcie). Na potrzeby naszego tutoriala wystarczy nam informacja, że układ MCP23017 będzie pracował w trybie domyślnym (IOCON.BANK = 0), czyli rejestry od obu portów poukładane są zamiennie jeden po drugim... po szczegóły odsyłam do serwisówki (str. 17). A oto masz krótki program:

Code: Select all

import smbus
import time

'''
CONTROL REGISTER SUMMARY (IOCON.BANK = 0)	
Register	Address	7bit	6bit	5bit	4bit	3bit	2bit	1bit 	0bit	POR/RST 
---------------------------------------------------------------------------------------------										
IODIRA		0x00	IO7		IO6		IO5		IO4		IO3		IO2		IO1		IO0		1111 1111
IODIRB		0x01	IO7		IO6		IO5		IO4		IO3		IO2		IO1		IO0		1111 1111
IPOLA		0x02	IP7		IP6		IP5		IP4		IP3		IP2		IP1		IP0		0000 0000
IPOLB		0x03	IP7		IP6		IP5		IP4		IP3		IP2		IP1		IP0		0000 0000
GPINTENA	0x04	GPINT7	GPINT6	GPINT5	GPINT4	GPINT3	GPINT2	GPINT1	GPINT0	0000 0000
GPINTENB	0x05	GPINT7	GPINT6	GPINT5	GPINT4	GPINT3	GPINT2	GPINT1	GPINT0	0000 0000
DEFVALA		0x06	DEF7	DEF6	DEF5	DEF4	DEF3	DEF2	DEF1	DEF0	0000 0000
DEFVALB		0x07	DEF7	DEF6	DEF5	DEF4	DEF3	DEF2	DEF1	DEF0	0000 0000
INTCONA		0x08	IOC7	IOC6	IOC5	IOC4	IOC3	IOC2	IOC1	IOC0	0000 0000
INTCONB		0x09	IOC7	IOC6	IOC5	IOC4	IOC3	IOC2	IOC1	IOC0	0000 0000
IOCON		0x0A	BANK	MIRROR	SEQOP	DISSLW	HAEN	ODR		INTPOL	-		0000 0000
IOCON		0x0B	BANK	MIRROR	SEQOP	DISSLW	HAEN	ODR		INTPOL	-		0000 0000
GPPUA		0x0C	PU7		PU6		PU5		PU4		PU3		PU2		PU1		PU0		0000 0000
GPPUB		0x0D	PU7		PU6		PU5		PU4		PU3		PU2		PU1		PU0		0000 0000
INTFA		0x0E	INT7	INT6	INT5	INT4	INT3	INT2	INT1	INTO	0000 0000
INTFB		0x0F	INT7	INT6	INT5	INT4	INT3	INT2	INT1	INTO	0000 0000
INTCAPA		0x10	ICP7	ICP6	ICP5	ICP4	ICP3	ICP2	ICP1	ICP0	0000 0000
INTCAPB		0x11	ICP7	ICP6	ICP5	ICP4	ICP3	ICP2	ICP1	ICP0	0000 0000
GPIOA		0x12	GP7		GP6		GP5		GP4		GP3		GP2		GP1		GP0		0000 0000
GPIOB		0x13	GP7		GP6		GP5		GP4		GP3		GP2		GP1		GP0		0000 0000
OLATA		0x14	OL7		OL6		OL5		OL4		OL3		OL2		OL1		OL0		0000 0000
OLATB		0x15	OL7		OL6		OL5		OL4		OL3		OL2		OL1		OL0		0000 0000									
---------------------------------------------------------------------------------------------
CONTROL REGISTER SUMMARY (IOCON.BANK = 1)	
Register	Address	7bit	6bit	5bit	4bit	3bit	2bit	1bit 	0bit	POR/RST 
---------------------------------------------------------------------------------------------										
IODIRA		0x00	IO7		IO6		IO5		IO4		IO3		IO2		IO1		IO0		1111 1111
IPOLA		0x01	IP7		IP6		IP5		IP4		IP3		IP2		IP1		IP0		0000 0000
GPINTENA	0x02	GPINT7	GPINT6	GPINT5	GPINT4	GPINT3	GPINT2	GPINT1	GPINT0	0000 0000
DEFVALA		0x03	DEF7	DEF6	DEF5	DEF4	DEF3	DEF2	DEF1	DEF0	0000 0000
INTCONA		0x04	IOC7	IOC6	IOC5	IOC4	IOC3	IOC2	IOC1	IOC0	0000 0000
IOCON		0x05	BANK	MIRROR	SEQOP	DISSLW	HAEN	ODR		INTPOL	-		0000 0000
GPPUA		0x06	PU7		PU6		PU5		PU4		PU3		PU2		PU1		PU0		0000 0000
INTFA		0x07	INT7	INT6	INT5	INT4	INT3	INT2	INT1	INTO	0000 0000
INTCAPA		0x08	ICP7	ICP6	ICP5	ICP4	ICP3	ICP2	ICP1	ICP0	0000 0000
GPIOA		0x09	GP7		GP6		GP5		GP4		GP3		GP2		GP1		GP0		0000 0000
OLATA		0x0A	OL7		OL6		OL5		OL4		OL3		OL2		OL1		OL0		0000 0000

IODIRB		0x10	IO7		IO6		IO5		IO4		IO3		IO2		IO1		IO0		1111 1111
IPOLB		0x11	IP7		IP6		IP5		IP4		IP3		IP2		IP1		IP0		0000 0000
GPINTENB	0x12	GPINT7	GPINT6	GPINT5	GPINT4	GPINT3	GPINT2	GPINT1	GPINT0	0000 0000
DEFVALB		0x13	DEF7	DEF6	DEF5	DEF4	DEF3	DEF2	DEF1	DEF0	0000 0000
INTCONB		0x14	IOC7	IOC6	IOC5	IOC4	IOC3	IOC2	IOC1	IOC0	0000 0000
IOCON		0x15	BANK	MIRROR	SEQOP	DISSLW	HAEN	ODR		INTPOL	-		0000 0000
GPPUB		0x16	PU7		PU6		PU5		PU4		PU3		PU2		PU1		PU0		0000 0000
INTFB		0x17	INT7	INT6	INT5	INT4	INT3	INT2	INT1	INTO	0000 0000
INTCAPB		0x18	ICP7	ICP6	ICP5	ICP4	ICP3	ICP2	ICP1	ICP0	0000 0000
GPIOB		0x19	GP7		GP6		GP5		GP4		GP3		GP2		GP1		GP0		0000 0000
OLATB		0x1A	OL7		OL6		OL5		OL4		OL3		OL2		OL1		OL0		0000 0000
'''

bus = smbus.SMBus(1)
ADDRESS	=	0x20
 
IODIRA = 0x00 # IO Direction PortA
OLATA  = 0x14 # Output Latch PortA
GPIOA  = 0x12 # Output Latch PortA
 
# Set all GPA pins as outputs by setting
# all bits of IODIRA register to 0
bus.write_byte_data(ADDRESS,IODIRA,0x00)
 
# Set output all 7 output bits to 0
bus.write_byte_data(ADDRESS,OLATA,0)
 
for x in range(1,256):
  bus.write_byte_data(ADDRESS,OLATA,x)
  print "POTRA:",x
  time.sleep(.1)
 
# After while - switch off PORTA
bus.write_byte_data(ADDRESS,OLATA,0)
print "POTRA: 0"

Program zwyczajnie zapisuje (po wcześniejszym ustawieniu w trym wyjściowy) kolejne wartości binarne do rejestru OLATA (Output Latch PortA) co skutkuje zapalaniem się i gaszeniem poszczególnych diod LED:
20161026_200133.jpg
Obsługa wejścia i wyjścia jednocześnie
Rozbudujmy nasz układ o włącznik astabilny (mikroswitch), który pozwoli nam kontrolować przebieg programu. Do ostatniej linii GPIO portu B dołączmy nasz mikroswitch a jego drugą końcówkę dołączmy do masy układu. Warto zadbać o podciągnięcie (pullup) GPB8 do zasilania przez rezystor ograniczający (1k). Można użyć wewnętrznego rejestru GPPULB i użyć do tego celu rezystorów zawartych w układzie. Ja zdecydowałem się na użycie rezystora zewnętrznego.
mcp23017-application_sw.png
mcp23017-application_sw.png (14.76 KiB) Viewed 32448 times

Code: Select all

import smbus
import time

'''
CONTROL REGISTER SUMMARY (IOCON.BANK = 0)	
Register	Address	7bit	6bit	5bit	4bit	3bit	2bit	1bit 	0bit	POR/RST 
---------------------------------------------------------------------------------------------										
IODIRA		0x00	IO7		IO6		IO5		IO4		IO3		IO2		IO1		IO0		1111 1111
IODIRB		0x01	IO7		IO6		IO5		IO4		IO3		IO2		IO1		IO0		1111 1111
IPOLA		0x02	IP7		IP6		IP5		IP4		IP3		IP2		IP1		IP0		0000 0000
IPOLB		0x03	IP7		IP6		IP5		IP4		IP3		IP2		IP1		IP0		0000 0000
GPINTENA	0x04	GPINT7	GPINT6	GPINT5	GPINT4	GPINT3	GPINT2	GPINT1	GPINT0	0000 0000
GPINTENB	0x05	GPINT7	GPINT6	GPINT5	GPINT4	GPINT3	GPINT2	GPINT1	GPINT0	0000 0000
DEFVALA		0x06	DEF7	DEF6	DEF5	DEF4	DEF3	DEF2	DEF1	DEF0	0000 0000
DEFVALB		0x07	DEF7	DEF6	DEF5	DEF4	DEF3	DEF2	DEF1	DEF0	0000 0000
INTCONA		0x08	IOC7	IOC6	IOC5	IOC4	IOC3	IOC2	IOC1	IOC0	0000 0000
INTCONB		0x09	IOC7	IOC6	IOC5	IOC4	IOC3	IOC2	IOC1	IOC0	0000 0000
IOCON		0x0A	BANK	MIRROR	SEQOP	DISSLW	HAEN	ODR		INTPOL	-		0000 0000
IOCON		0x0B	BANK	MIRROR	SEQOP	DISSLW	HAEN	ODR		INTPOL	-		0000 0000
GPPUA		0x0C	PU7		PU6		PU5		PU4		PU3		PU2		PU1		PU0		0000 0000
GPPUB		0x0D	PU7		PU6		PU5		PU4		PU3		PU2		PU1		PU0		0000 0000
INTFA		0x0E	INT7	INT6	INT5	INT4	INT3	INT2	INT1	INTO	0000 0000
INTFB		0x0F	INT7	INT6	INT5	INT4	INT3	INT2	INT1	INTO	0000 0000
INTCAPA		0x10	ICP7	ICP6	ICP5	ICP4	ICP3	ICP2	ICP1	ICP0	0000 0000
INTCAPB		0x11	ICP7	ICP6	ICP5	ICP4	ICP3	ICP2	ICP1	ICP0	0000 0000
GPIOA		0x12	GP7		GP6		GP5		GP4		GP3		GP2		GP1		GP0		0000 0000
GPIOB		0x13	GP7		GP6		GP5		GP4		GP3		GP2		GP1		GP0		0000 0000
OLATA		0x14	OL7		OL6		OL5		OL4		OL3		OL2		OL1		OL0		0000 0000
OLATB		0x15	OL7		OL6		OL5		OL4		OL3		OL2		OL1		OL0		0000 0000									
---------------------------------------------------------------------------------------------
CONTROL REGISTER SUMMARY (IOCON.BANK = 1)	
Register	Address	7bit	6bit	5bit	4bit	3bit	2bit	1bit 	0bit	POR/RST 
---------------------------------------------------------------------------------------------										
IODIRA		0x00	IO7		IO6		IO5		IO4		IO3		IO2		IO1		IO0		1111 1111
IPOLA		0x01	IP7		IP6		IP5		IP4		IP3		IP2		IP1		IP0		0000 0000
GPINTENA	0x02	GPINT7	GPINT6	GPINT5	GPINT4	GPINT3	GPINT2	GPINT1	GPINT0	0000 0000
DEFVALA		0x03	DEF7	DEF6	DEF5	DEF4	DEF3	DEF2	DEF1	DEF0	0000 0000
INTCONA		0x04	IOC7	IOC6	IOC5	IOC4	IOC3	IOC2	IOC1	IOC0	0000 0000
IOCON		0x05	BANK	MIRROR	SEQOP	DISSLW	HAEN	ODR		INTPOL	-		0000 0000
GPPUA		0x06	PU7		PU6		PU5		PU4		PU3		PU2		PU1		PU0		0000 0000
INTFA		0x07	INT7	INT6	INT5	INT4	INT3	INT2	INT1	INTO	0000 0000
INTCAPA		0x08	ICP7	ICP6	ICP5	ICP4	ICP3	ICP2	ICP1	ICP0	0000 0000
GPIOA		0x09	GP7		GP6		GP5		GP4		GP3		GP2		GP1		GP0		0000 0000
OLATA		0x0A	OL7		OL6		OL5		OL4		OL3		OL2		OL1		OL0		0000 0000

IODIRB		0x10	IO7		IO6		IO5		IO4		IO3		IO2		IO1		IO0		1111 1111
IPOLB		0x11	IP7		IP6		IP5		IP4		IP3		IP2		IP1		IP0		0000 0000
GPINTENB	0x12	GPINT7	GPINT6	GPINT5	GPINT4	GPINT3	GPINT2	GPINT1	GPINT0	0000 0000
DEFVALB		0x13	DEF7	DEF6	DEF5	DEF4	DEF3	DEF2	DEF1	DEF0	0000 0000
INTCONB		0x14	IOC7	IOC6	IOC5	IOC4	IOC3	IOC2	IOC1	IOC0	0000 0000
IOCON		0x15	BANK	MIRROR	SEQOP	DISSLW	HAEN	ODR		INTPOL	-		0000 0000
GPPUB		0x16	PU7		PU6		PU5		PU4		PU3		PU2		PU1		PU0		0000 0000
INTFB		0x17	INT7	INT6	INT5	INT4	INT3	INT2	INT1	INTO	0000 0000
INTCAPB		0x18	ICP7	ICP6	ICP5	ICP4	ICP3	ICP2	ICP1	ICP0	0000 0000
GPIOB		0x19	GP7		GP6		GP5		GP4		GP3		GP2		GP1		GP0		0000 0000
OLATB		0x1A	OL7		OL6		OL5		OL4		OL3		OL2		OL1		OL0		0000 0000
'''

bus = smbus.SMBus(1)

ADDRESS	=	0x20

# Settings for IOCON.BANK = 0 
IODIRA = 0x00 # IO Direction PortA
OLATA  = 0x14 # Output Latch PortA
IODIRB = 0x01 # IO Direction PortB
OLATB  = 0x15 # Output Latch PortB
GPIOA  = 0x12 # General Purpose Input/Output PortA
GPIOB  = 0x13 # General Purpose Input/Output Portb

# Set all GPIOA pins as outputs by setting
# all bits of IODIRA register to 0
bus.write_byte_data(ADDRESS,IODIRA,0x00)
 
# Set output all 8 output bits to 0
bus.write_byte_data(ADDRESS,OLATA,0x00)

# Set all GPIOB pins as input.
bus.write_byte_data(ADDRESS,IODIRB,0xff)

while True: 
	for x in range(1,256):
	  bus.write_byte_data(ADDRESS,OLATA,x)
	  Switch = bus.read_byte_data(ADDRESS,GPIOB)
	  if Switch & 0b10000000 == 0b10000000:
		  print "POTRA:",x, "Switch is OFF"
	  else:
		  print "POTRA:",x, "Switch is ON"
		
	  time.sleep(.1)
Mało kto wie, ale jest możliwość jednoczesego używania GPIO jako wejścia i wyjścia.. ale o tym następnym razem...
Attachments
mcp23017_kicad.zip
Plik projektu w KiCAD wraz z biblioteką dla MCP23017
(653.46 KiB) Downloaded 1967 times
mcp23017_application.pdf
(31.4 KiB) Downloaded 1972 times
MCP23017.pdf
(915.92 KiB) Downloaded 1949 times

Post Reply