Overview
The MCP23017 is an I2C interface 16-bit (two 8-bit GPIO Ports) I/O expansion chip. Its variance MCP23S17 is an SPI interface I/O expansion chip that functions almost identical. Any micro-controller that has a limit I/O port can easily add this chip to expand its I/O pins using its dedicated hardware communication module, or even by software bit-banging.
| ATMega644P Experiment Board |
The MCP23017 uses the TWI communication interface that implement only two wires, Serial Clock(SCL) and Serial Data(SDA). It supports up to 1.7MHz serial clock rate.
| MCP23017 Chip and Module |
This chip a DIP and an SMD package. There are a lot of module that use the SMD chip that is very friendly to use for hobbyist prototyping.
| Package Types |
This chip contains some main blocks, TWI Interface, 3-bit Address Select, Reset, Interrupt Request and GPIO ports.
| Functional Block Diagram |
The MCP23017 is a slave I2C interface device that supports 7-bit slave addressing, with the read/write bit filling out the control byte. The slave address contains four fixed bits and three user-defined hardware address bits (pins A2, A1 and A0).
| I2C ADDRESSING REGISTERS |
Its I/O pins work in a similar way with the I/O port model of PIC micro-controllers. The I/O ports operation are controlled by its internal registers.
There are two port registers GPA and GPB. The data input for GPA is GPIOA while its output register is OLATA. IODIRA is its data direction control register. For example setting IODIRA to 0xFF make GPA to input port. It also has interrupt input and interrupt flag pin that's control via other registers listed in its data sheet. GPB operation works very similar to GPA.
Each port has its pull resistors that's enabled by setting the GPPUx registers.
By default we don't set bit 7 (BANK) of IOCON register its control register are arranged below.
For more detail please check this device's datasheet.
ATMega644P TWI and MCP23017 Programming Example
For a simple programming the ATMega644P send data to GPA of the MCP23017. So in software the GPA register must set to 0x00 to make it as input port.
Source Code "main.c" :
- /*
- * 10-i2c_mcp23017_output_a.c
- *
- * Created: 2/4/2026 7:40:16 PM
- * Author : Admin
- */
- #include <avr/io.h>
- #include <util/delay.h>
- #define F_CPU 16000000UL
- #include "twi.c"
- //MCP23017 TWI Slave Address
- const char MCP23017_W=0x40;
- const char MCP23017_R=0x41;
- /*GPIO A and B Direction Control Register*/
- const char IODIRA = 0x00;
- const char IODIRB = 0x01;
- /*GPIOA PULL UP REGISTER CONTROL*/
- const char GPPUA = 0x0C;
- /*GPIOA I/O PORT register*/
- const char GPIOA = 0x12;
- /*GPIOB Output Register*/
- const char OLATA = 0x14;
- /*GPIOB Output Register*/
- const char OLATB = 0x15;
- void mcp23017_write(char address,char data){
- twi_start();
- /*Select the write address*/
- twi_write(MCP23017_W);
- /*Select a register address*/
- twi_write(address);
- /*Send configuration data*/
- twi_write(data);
- twi_stop();
- }
- unsigned char mcp23017_read(char address){
- /*Select a specific address*/
- twi_start();
- twi_write(MCP23017_W);
- twi_write(address);
- twi_stop();
- /*Read data from the given address*/
- twi_start();
- twi_write(MCP23017_R);
- unsigned char i2cData=twi_read(1);
- twi_stop();
- return i2cData;
- }
- int main(void)
- {
- /* Replace with your application code */
- _delay_ms(1000);
- char data;
- twi_init();
- /*Set GPIOA To Output*/
- mcp23017_write(IODIRA,0x00);
- while (1)
- {
- /*Send Data to OLATA*/
- mcp23017_write(OLATA,data);
- data++;
- _delay_ms(100);
- }
- }
Source Code "twi.c" :
- /*
- * twi.c
- *
- * Created: 2/4/2026 10:22:02 AM
- * Author: Admin
- */
- #include <avr/io.h>
- #include <util/delay.h>
- #define F_CPU 16000000UL
- const write_address=0xA0;
- const read_address=0xA1;
- void twi_init(void){
- TWSR|=0x00; //Prescaler Selection Bit
- TWBR=0x0F; //Baud Rate Generator
- TWCR=(1<<TWEN); //Enable The TWI Module
- PORTC|=(1<<0);
- PORTC|=(1<<1);
- }
- void twi_start(void){
- TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
- while((TWCR&(1<<TWINT))==0);
- }
- void twi_write(unsigned char data){
- TWDR=data;
- TWCR=(1<<TWINT)|(1<<TWEN);
- while((TWCR&(1<<TWINT))==0);
- }
- unsigned char twi_read(char ACK){
- if(ACK==0)
- TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWEA);
- else
- TWCR=(1<<TWINT)|(1<<TWEN);
- while((TWCR&(1<<TWINT))==0);
- return TWDR;
- }
- void twi_stop(){
- TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
- _delay_us(10);
- }
Schematic:
| Schematic and Simulation |
ATMega644P Prototype Board:
| ATMega644P Prototype Board |
For more example the ATMega644P will read data from GPAand then send it to GPB.
Source Code:
- /*
- * 10-i2c_mcp23017_io.c
- *
- * Created: 2/4/2026 9:59:26 AM
- * Author : Admin
- */
- #include <avr/io.h>
- #include <util/delay.h>
- #define F_CPU 16000000UL
- //MCP23017 TWI Slave Address
- const char MCP23017_W=0x40;
- const char MCP23017_R=0x41;
- /*GPIO A and B Direction Control Register*/
- const char IODIRA = 0x00;
- const char IODIRB = 0x01;
- /*GPIOA PULL UP REGISTER CONTROL*/
- const char GPPUA = 0x0C;
- /*GPIOA I/O PORT register*/
- const char GPIOA = 0x12;
- /*GPIOB Output Register*/
- const char OLATB = 0x15;
- void mcp23017_write(char address,char data){
- twi_start();
- /*Select the write address*/
- twi_write(MCP23017_W);
- /*Select a register address*/
- twi_write(address);
- /*Send configuration data*/
- twi_write(data);
- twi_stop();
- }
- unsigned char mcp23017_read(char address){
- /*Select a specific address*/
- twi_start();
- twi_write(MCP23017_W);
- twi_write(address);
- twi_stop();
- /*Read data from the given address*/
- twi_start();
- twi_write(MCP23017_R);
- unsigned char i2cData=twi_read(1);
- twi_stop();
- return i2cData;
- }
- int main(void)
- {
- /* Replace with your application code */
- _delay_ms(1000);
- char data;
- twi_init();
- /*Set GPIOA To Input*/
- mcp23017_write(IODIRA,0xFF);
- /*Set GPIOB To Output*/
- mcp23017_write(IODIRB,0x00);
- /*Turn On Pull Up Resistors On GPIOA*/
- mcp23017_write(GPPUA,0xFF);
- while (1)
- {
- /*Read digital input from GPIOA*/
- data=mcp23017_read(GPIOA);
- /*Send it back to GPIOB*/
- mcp23017_write(OLATB,data);
- }
- }
The "twi.c" must be add to project folder the IDE.
Schematic:
| Schematic |
ATMega644P Prototype Board:
This PCB was offered by PCBWay (pcbway.com).
I have been using PCBWay for many years now. PCBWay fabricate PCBs at low cost, fast processing time for only 24 hours, and fast delivery time using any carrier options. This double side 10cmx10cm can be fabricate at only 5USD for 5 to 10pcs by PCBWay. It's a standard PCB with silk screen and solder mask.
![]() |
| 10 PCBs for only 5USD |
For different size of PCB we can instantly quote on PCBWay website using a zip PCB Gerber file without account.
![]() |
| PCBWay Instant Quote |





No comments:
Post a Comment