Sunday, January 21, 2024

PIC16F887 MCP23017 I2C GPIO Example using XC8

Overview

The MCP23017 is a 16-bit I2C I/O expander chip. It could be used for digital input reading/writing, relay driving, multiplexing display driving, keypad scanning, LCD controlling, etc. It uses a Two-Wire serial interface or I2C with two communication line, serial data (SDA) and serial clock (SCL).

PIC16F887 MCP23017 I2C GPIO Example using XC8
Simulating Program for I/O Reading and Writing

This chip has more functionalities compare to the older PCF8574 I/O expander. It has data direction control, pull-up resistor control, input output register, output latch register, interrupt control and status registers, etc. For an introductory example, you can see this post that I use the ATMega32 micro-controller.

PIC16F887 MCP23017 I2C GPIO Example using XC8
The MCP23017 DIP-28 I Posses

This chip comes with various packages. A DIP-28 is preferred for most of electronics hobby projects.

PIC16F887 MCP23017 I2C GPIO Example using XC8
MCP23017 Package Types
The MCP23S17 implements the Serial Peripheral Interface (SPI) communication interface. The MCP23017 has,

  • I2C communication interface 
  • reset (active high)
  • additional address setting
  • interrupts output
  • two 8-bit bi-directional GPIO, GPA and GPB.
PIC16F887 MCP23017 I2C GPIO Example using XC8
Functional Block Diagram


This chip able to operate at high speed up to 1.7MHz. Its operating voltage ranges from 1.8V to 5.5V. For electronics hobbyist prototyping a 5V stable supply voltage is common.

PIC16F887 MCP23017 I2C GPIO Example using XC8
Register Addresses
All registers listed above are configuration registers, status registers, and data registers. It has two memory banks, bank0 and bank1. By default we work with bank0. For example,

  • IODIRA - I/O Direction Register A (0 for output and 1 for input)
  • IODIRB - I/O Direction Register B (0 for output and 1 for input)
  • GPPUA - GPIO Pull-Up Resistor Register A (1 for enable and 0 for disable)
  • GPPUB - GPIO Pull-Up Resistor Register B (1 for enable and 0 for disable)
  • GPIOA - General Purpose I/O Port Register A ( this register is for reading data from PORTA)
  • GPIOB - General Purpose I/O Port Register B ( this register is for reading data from PORTB)
  • OLATA - Output Latch Register A ( this register is for writing data to output PORTA) 
  • OLATB - Output Latch Register B ( this register is for writing data to output PORTB)

For more detail you can see its datasheet

To write to this chip the controller needs to write its slave address of 0x40 (A2...A0 are logic 0) followed by its register address and data. It also have sequential addressing mode but I don't mention it here.

To read from this chip the controller needs to write its slave address 0x40 (A2...A0 are logic 0) followed by its register address. Then start a new write session of the device slave address of 0x41 followed the I2C read mode to get the data.

MPLABX IDE and XC8 Programming 

This introductory example, the master micro-processor just send a LED shifting data to the I2C slave MCP23017 chip. I use the I2C communication module of PIC16F887. Its serial clock frequency is 400kHz.

  1. /*
  2.  * File: main.c
  3.  * Author: Admin
  4.  *
  5.  * Created on January 21, 2024, 3:07 PM
  6.  */
  7.  
  8. #include <xc.h>
  9. #include "config.h"
  10. #include "i2c.h"
  11.  
  12. #define _XTAL_FREQ 8000000UL
  13.  
  14. #define MCP23017_W 0x40
  15. #define MCP23017_R 0x41
  16.  
  17. void mcp23017_write(uint8_t address, uint8_t data){
  18. i2c_start();
  19. i2c_write(MCP23017_W);
  20. i2c_write(address);
  21. i2c_write(data);
  22. i2c_stop();
  23. }
  24.  
  25. void main(void) {
  26. OSCCONbits.IRCF=7;
  27. i2c_init(400000);
  28. mcp23017_write(0,0);
  29. while(1){
  30. uint8_t i=0;
  31. while(i<8){
  32. mcp23017_write(0x14,1<<i);
  33. i++;
  34. __delay_ms(100);
  35. }
  36. }
  37. return;
  38. }
  39.  

I use only GPA for LED output. The LED shifts for every 100 Milli seconds.

PIC16F887 MCP23017 I2C GPIO Example using XC8
Proteus Simulation
I simulate this program using Proteus VSM 8. Click here to download this example.

The following example, the MCP23017 is used for reading data from GPB and writing data back to GPA.

  1. /*
  2.  * File: main.c
  3.  * Author: Admin
  4.  *
  5.  * Created on January 21, 2024, 4:16 PM
  6.  */
  7.  
  8. #include <xc.h>
  9. #include "config.h"
  10. #include "i2c.h"
  11.  
  12. #define _XTAL_FREQ 8000000UL
  13.  
  14. #define MCP23017_W 0x40
  15. #define MCP23017_R 0x41
  16.  
  17. #define IODIRA 0x00
  18. #define IODIRB 0x01
  19. #define GPPUB 0x0D
  20. #define GPIOB 0x13
  21. #define OLATA 0x14
  22.  
  23. void mcp23017_write(uint8_t address, uint8_t data){
  24. i2c_start();
  25. i2c_write(MCP23017_W);
  26. i2c_write(address);
  27. i2c_write(data);
  28. i2c_stop();
  29. }
  30.  
  31. uint8_t mcp23017_read(uint8_t address){
  32. uint8_t data;
  33. i2c_start();
  34. i2c_write(MCP23017_W);
  35. i2c_write(address);
  36. i2c_stop();
  37.  
  38. i2c_start();
  39. i2c_write(MCP23017_R);
  40. data=i2c_read(0);
  41. i2c_stop();
  42. return data;
  43. }
  44.  
  45. void main(void) {
  46. OSCCONbits.IRCF=7;
  47. i2c_init(400000);
  48. mcp23017_write(IODIRA,0); //GPA AS OUTPUT
  49. mcp23017_write(IODIRB,0xFF); //GPB AS INPUT
  50. mcp23017_write(GPPUB,0xFF); //GPB PULL-UP ENABLE
  51. while(1){
  52. //READ GPB INPUT DATA
  53. uint8_t temp=mcp23017_read(GPIOB);
  54. __delay_ms(10);
  55. //WRITE GPA OUTPUT DATA
  56. mcp23017_write(OLATA,temp);
  57. __delay_ms(50);
  58. }
  59. return;
  60. }
  61.  

I enable its pull-up resistor at GPB without adding additional resistor the the circuit.

PIC16F887 MCP23017 I2C GPIO Example using XC8
Schematic Diagram

Simulating program in Proteus work very well. Click here to download this example.
 




No comments:

Post a Comment

Search This Blog

Labels

25AA010A (1) 8051 (7) 93AA46B (1) ADC (30) Analog Comparator (1) Arduino (15) ARM (6) AT89C52 (7) ATMega32 (56) AVR (57) CCS PICC (28) DAC (1) DHT11 (2) Display (105) Distance Sensor (3) DS18B20 (3) dsPIC (2) dsPIC30F1010 (2) EEPROM (5) Environment Sensor (4) esp8266 (1) I2C (29) Input/Output (67) Interrupt (19) Keil (5) Keypad (10) LCD (47) Master/Slave (1) MAX7221 (1) MCP23017 (5) MCP23S17 (4) Meter (3) MikroC (2) Motor (15) MPLABX (71) Nokia 5110 LCD (3) OLED (2) One-Wire (6) Oscillator (8) PCB (6) PCD8544 (3) PCF8574 (5) PIC (107) PIC12F (2) PIC16F628A (2) PIC16F630 (1) PIC16F716 (3) PIC16F818 (10) PIC16F818/819 (2) PIC16F84A (15) PIC16F876A (1) PIC16F877A (9) PIC16F88 (1) PIC16F887 (60) PIC18 (19) PIC18F1220 (4) PIC18F2550 (3) PIC18F4550 (12) PWM (11) RTC (8) Sensor (10) SH1106 (1) Shift Register (11) Shift Registers (3) SPI (24) STM32 (6) STM32 Blue Pill (6) STM32CubeIDE (6) STM32F103C8T6 (6) SysTick (3) temperature sensor (11) Thermometer (21) Timer/Counter (31) TM1637 (2) UART (7) Ultrasonic (4) Voltmeter (7) WDT (1) XC16 (2) XC8 (94)