728x90

728x90

Wednesday, February 4, 2026

ATMega644P TWI MCP23017 GPIO Example

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 TWI MCP23017 GPIO Example
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. 

ATMega644P TWI MCP23017 GPIO Example
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. 

ATMega644P TWI MCP23017 GPIO Example
Package Types

This chip contains some main blocks, TWI Interface, 3-bit Address Select, Reset, Interrupt Request and GPIO ports.

ATMega644P TWI MCP23017 GPIO Example
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).

ATMega644P TWI MCP23017 GPIO Example
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.

ATMega644P TWI MCP23017 GPIO Example 

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" :

  1. /*
  2. * 10-i2c_mcp23017_output_a.c
  3. *
  4. * Created: 2/4/2026 7:40:16 PM
  5. * Author : Admin
  6. */

  7. #include <avr/io.h>
  8. #include <util/delay.h>
  9. #define F_CPU 16000000UL

  10. #include "twi.c"

  11. //MCP23017 TWI Slave Address
  12. const char MCP23017_W=0x40;
  13. const char MCP23017_R=0x41;

  14. /*GPIO A and B Direction Control Register*/
  15. const char IODIRA = 0x00;
  16. const char IODIRB = 0x01;
  17. /*GPIOA PULL UP REGISTER CONTROL*/
  18. const char GPPUA = 0x0C;
  19. /*GPIOA I/O PORT register*/
  20. const char GPIOA = 0x12;
  21. /*GPIOB Output Register*/
  22. const char OLATA = 0x14;
  23. /*GPIOB Output Register*/
  24. const char OLATB = 0x15;



  25. void mcp23017_write(char address,char data){
  26. twi_start();
  27. /*Select the write address*/
  28. twi_write(MCP23017_W);
  29. /*Select a register address*/
  30. twi_write(address);
  31. /*Send configuration data*/
  32. twi_write(data);
  33. twi_stop();
  34. }

  35. unsigned char mcp23017_read(char address){
  36. /*Select a specific address*/
  37. twi_start();
  38. twi_write(MCP23017_W);
  39. twi_write(address);
  40. twi_stop();
  41. /*Read data from the given address*/
  42. twi_start();
  43. twi_write(MCP23017_R);
  44. unsigned char i2cData=twi_read(1);
  45. twi_stop();
  46. return i2cData;
  47. }

  48. int main(void)
  49. {
  50. /* Replace with your application code */
  51. _delay_ms(1000);
  52. char data;
  53. twi_init();
  54. /*Set GPIOA To Output*/
  55. mcp23017_write(IODIRA,0x00);
  56. while (1)
  57. {
  58. /*Send Data to OLATA*/
  59. mcp23017_write(OLATA,data);
  60. data++;
  61. _delay_ms(100);
  62. }
  63. }



Source Code "twi.c" :

  1. /*
  2. * twi.c
  3. *
  4. * Created: 2/4/2026 10:22:02 AM
  5. * Author: Admin
  6. */

  7. #include <avr/io.h>
  8. #include <util/delay.h>
  9. #define F_CPU 16000000UL

  10. const write_address=0xA0;
  11. const read_address=0xA1;


  12. void twi_init(void){
  13. TWSR|=0x00; //Prescaler Selection Bit
  14. TWBR=0x0F; //Baud Rate Generator
  15. TWCR=(1<<TWEN); //Enable The TWI Module
  16. PORTC|=(1<<0);
  17. PORTC|=(1<<1);
  18. }

  19. void twi_start(void){
  20. TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
  21. while((TWCR&(1<<TWINT))==0);
  22. }

  23. void twi_write(unsigned char data){
  24. TWDR=data;
  25. TWCR=(1<<TWINT)|(1<<TWEN);
  26. while((TWCR&(1<<TWINT))==0);
  27. }

  28. unsigned char twi_read(char ACK){
  29. if(ACK==0)
  30. TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWEA);
  31. else
  32. TWCR=(1<<TWINT)|(1<<TWEN);
  33. while((TWCR&(1<<TWINT))==0);
  34. return TWDR;
  35. }

  36. void twi_stop(){
  37. TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
  38. _delay_us(10);
  39. }

Schematic:

ATMega644P TWI MCP23017 GPIO Example
Schematic and Simulation

ATMega644P Prototype Board:

ATMega644P TWI MCP23017 GPIO Example
ATMega644P Prototype Board

 For more example the ATMega644P will read data from GPAand then send it to GPB.

Source Code:

  1. /*
  2. * 10-i2c_mcp23017_io.c
  3. *
  4. * Created: 2/4/2026 9:59:26 AM
  5. * Author : Admin
  6. */
  7. #include <avr/io.h>
  8. #include <util/delay.h>
  9. #define F_CPU 16000000UL

  10. //MCP23017 TWI Slave Address
  11. const char MCP23017_W=0x40;
  12. const char MCP23017_R=0x41;

  13. /*GPIO A and B Direction Control Register*/
  14. const char IODIRA = 0x00;
  15. const char IODIRB = 0x01;
  16. /*GPIOA PULL UP REGISTER CONTROL*/
  17. const char GPPUA = 0x0C;
  18. /*GPIOA I/O PORT register*/
  19. const char GPIOA = 0x12;
  20. /*GPIOB Output Register*/
  21. const char OLATB = 0x15;



  22. void mcp23017_write(char address,char data){
  23. twi_start();
  24. /*Select the write address*/
  25. twi_write(MCP23017_W);
  26. /*Select a register address*/
  27. twi_write(address);
  28. /*Send configuration data*/
  29. twi_write(data);
  30. twi_stop();
  31. }

  32. unsigned char mcp23017_read(char address){
  33. /*Select a specific address*/
  34. twi_start();
  35. twi_write(MCP23017_W);
  36. twi_write(address);
  37. twi_stop();
  38. /*Read data from the given address*/
  39. twi_start();
  40. twi_write(MCP23017_R);
  41. unsigned char i2cData=twi_read(1);
  42. twi_stop();
  43. return i2cData;
  44. }

  45. int main(void)
  46. {
  47. /* Replace with your application code */
  48. _delay_ms(1000);
  49. char data;
  50. twi_init();
  51. /*Set GPIOA To Input*/
  52. mcp23017_write(IODIRA,0xFF);
  53. /*Set GPIOB To Output*/
  54. mcp23017_write(IODIRB,0x00);
  55. /*Turn On Pull Up Resistors On GPIOA*/
  56. mcp23017_write(GPPUA,0xFF);
  57. while (1)
  58. {
  59. /*Read digital input from GPIOA*/
  60. data=mcp23017_read(GPIOA);
  61. /*Send it back to GPIOB*/
  62. mcp23017_write(OLATB,data);
  63. }
  64. }


The "twi.c" must be add to project folder the IDE.

Schematic:

ATMega644P TWI MCP23017 GPIO Example
Schematic

ATMega644P Prototype Board:

ATMega644P TWI MCP23017 GPIO Example

ATMega644P TWI MCP23017 GPIO Example

ATMega644P TWI MCP23017 GPIO Example

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.

A DIY dsPIC30F2010 and dsPIC30F1010 Prototype Board with Programmer
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.

A DIY dsPIC30F2010 and dsPIC30F1010 Prototype Board with Programmer
PCBWay Instant Quote


No comments:

Post a Comment

320x50

Search This Blog

tyro-728x90