HW3 - ndm736/ME433_2020 GitHub Wiki
The MCP23017 is a large DIP chip that gives you 16 more general purpose IO pins. It is controlled by I2C, which uses two pins, so the overall circuit would gain 14 controllable pins. This is useful for a chip like the PIC32MX170F256B which doesn't have many pins to begin with.
The MCP23017 has 3 address pins, so you could have 8 of the chips on the same I2C bus. That would provide 128 pins, using only 2 from the PIC!
Connect the MCP23017 Vdd to 3.3V and Vss to GND. Connect the RESET pin to 3.3V. Connect the SDA to a 10k pull-up resistor, and the SCK to a 10k pull-up resistor, and connect the pins to the PIC SDA1 and SCL1. Connect the MCP23017 A0, A1, and A2 pins to GND (or whatever address you'd like to make).
Note that by connecting the RESET pin to 3.3V the only way to reset the chip is to kill power to the whole board. Resetting is sometimes necessary because if your code happens to be in the middle of communicating with the MCP23017 when the PIC is reprogrammed, the PIC code will start fresh but the MCP23017 might have been in the middle of communication and will not know that the PIC started over, so it will never respond to new communication and the PIC will get stuck in an infinite loop. Always put some kind of heart-beat in your code so you can tell that the PIC is stuck in an infinite loop and you know to do a power reset. We could manually control the RESET pin with an output pin from the PIC, but that would steal another PIC pin.
To test the chip, add an LED and a 330 ohm resistor to GND from pin GPA7, and add a button from pin GPB0 to GND with a 10k pull-up resistor.
Add the I2C sample code to your project. The goal is to read from GPB0, and if the button is pushed, turn on GPA7, else turn off GPA7. Blink the LED that is connected directly to the PIC at some frequency as a heart-beat, so that you know the PIC is running. Upload your finished code into a folder called HW3 in your repo and submit a link and a demo video on Canvas.
I2C is very tricky to debug because it is hard to tell if the chip initialization, the read function, or the write function is the problem. Break the assignment into 2 parts: chip initialization and blink the LED on GPA7, then read from GBB0 and control GPA7.
The chip must be initialized so that GPA7 is an output pin (might as well make all the A pins output, so IODIRA = 0x00) and GBB0 is input (might as well make all B pins input, so IODIRB = 0xFF). By default, IOCON.BLANK=0, so the A and B registers are interleaved. You could change that if you like.
Set the bits in OLATA to turn the A pins on or off, and read from GPIOB to know if the button is pushed or not. Note that there are no structures like LATAbits. or PORTBbits. built into the code, you'll set all the A pins and read from all the B pins each time you interact with them, so you'll probably need some bitshifting and ANDing and ORing to identify individual bits from the chars.
To write a message to the MCP23017, do a Start, send the address with the write bit (last bit is 0), send the register you want to change, send the value you want to change it to, and do a Stop.
To read a message from the MCP23017, do a Start, send the address with the write bit (last bit is 0), send the register you want to read from, do a Restart, send the address with the read bit (last bit is 1), recv from the chip, ack with a 1, and do a Stop. (If you ack with a 0, the chip expects you to immediately do another read. We'll use that feature with another chip).
I suggest writing general purpose write and read functions, like void setPin(unsigned char address, unsigned char register, unsigned char value), and unsigned char readPin(unsigned char address, unsigned char register), we'll use them or similar functions in future assignments.