Thursday, September 10, 2020

ATMega32 TWI interfaces to MCP23017 I2C I/O expanding

Overview

MCP23017 is a 16-bit microprocessor digital I/O expander, built up with two 8-bit GPIO ports. The inputs/outputs are bi-directional. I/O direction is controlled by its data direction control register that's similar to one's in its PICMicro device.

This device is required in any applications that the MCU has used up its digital I/O. For example, a master MCU need to toggle 16 output relays. The manufacturer has released an example of using this device to create a matrix keypad.

I/O Pins

The I/O expander also support interrupt whenever the logic inputs changed.

ATMega32 TWI interfaces to MCP23016 I2C I/O expander
MCP23017-E/SP I use for my prototyping
MCP23017 Pin Diagram

I make a summary of this 28-pin device:

  • 1 to 8 : 8-bit GPIOB port, ranges from GPB0 to GPB7.
  • 9 : VDD - positive supply voltage (2.0 to 5.5 V)
  • 10 : VSS - Supply ground
  • 11 : NC - Not Connected
  • 12 : SCK - Serial Clock
  • 13 : SDA - Serial Data
  • 14 : NC - Not Connected
  • 15 16 17 : A0 A1 A2 - I2C optional address select pins (must be properly wired between GND and VDD)
  • 18 : RESET - Active low reset pin
  • 19 20 : INTB INTA - Digital input change interrupt trigger pin.
  • 21 to 28 : 8-bit GPIOA port, ranges from GPB0 to GPB7.

Two-wire Serial Communication (TWI)

Using I2C (or TWI), this device could clock up to 1700 kHz. It's supplied from 2.0 to 5.5 V, but for most of electronics hobbyist a 5.0 V supply voltage is a preference. 

Just like other TWI devices, MCP23017 read and write operations are similar. This device contain I/O port register, output register, interrupt control registers etc.

MCP23017 Register Addresses

These registers could locate at both banks - bank 0 and bank 1 with different location. By default, without any control register setting, it locate at bank 0.

TWI Writting 

The writing address of MCP23017 is 01000000 in binary. To write to this device,
  1. initiate a start condition
  2. write 01000000 for MCP23017 slave writing
  3. write the address of a specific register we want to send data to
  4. write any data to that register
  5. send a stop condition
The register we select has its own address list in the table above. For example we want to enable the interrupt on the input port.

TWI Reading

The reading address of MCP23017 is 01000001 in binary. To read to this device,
  1. initiate a start condition
  2. write 01000001 for MCP23017 slave reading
  3. write the address of a specific register we want to read from
  4. Read the TWI TWDR register
  5. send a stop condition

Interfacing and Programming In Atmel Studio 7

A communication interface from a master MCU to MCP23017 uses only two wires - SCL and SDA. Most of TWI slave device left these two pins in open-drain, requires two external pull up resistor with a resistance between 4.7 kOhm to 10 kOhm.

However, ATMega32 pins can be pulled high via software. Hence, it eliminates the requirement of adding two external resistors for TWI communication.

In this example, I only make a basic digital I/O reading and writing without using any interrupt features.

ATMega32 TWI interfaces to MCP23017 I2C I/O expander
A running program

GPIOx configured as input while GPIOx configured as output. There direction control registers are IODIRA and IODIRB respectively. Both GPIOx ports have their own internal weak pull up resistors name as GPPUA and GPPUB for both ports. 

Reading from GPIOx to get its inputs status. Writing to OLATx register to send digital data to GPIO output registers.

The sample program as shown above, GPIOA configured as digital inputs. I turn on its internal weak pull up resistor. GPIOB configured as digital output port. The main program just reads digital input from GPIOA, and send the result to GPIOB.

Source Code

/*
 * i2c_mcp23017.c
 *
 * Created: 9/9/2020 6:47:16 PM
 * Author : aki-technical
 */ 

#include <avr/io.h>

#define F_CPU 16000000UL
#include <util/delay.h>

#define mcp23017Read 0b01000001
#define mcp23017Write 0b01000000

void i2cInit(void){
TWSR=0x03; //Bit Rate Pre-scaler Is 1:64
TWBR=0x0F;
TWCR=(1<<TWEN); //Enable The TWI Module
PORTC|=(1<<0);
PORTC|=(1<<1);
}

void i2cStart(void){
TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
while((TWCR&(1<<TWINT))==0);
}

void i2cWrite(unsigned char data){
TWDR=data;
TWCR=(1<<TWINT)|(1<<TWEN);
while((TWCR&(1<<TWINT))==0);
}

unsigned char i2cRead(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 i2cStop(){
TWCR=(1<<TWINT)|(1<<TWEN)|(1<<TWSTO);
}

/*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;

/*MCP23017 Configuration Setting*/
void mcp23017Config(char address,char config){
i2cStart();
/*Select the write address*/
i2cWrite(mcp23017Write);
/*Select a register address*/
i2cWrite(address);
/*Send configuration data*/
i2cWrite(config);
i2cStop();
}

/*Read Data From MCP23017*/
unsigned char mcp23017Return(char address){
/*Select a specific address*/
i2cStart();
i2cWrite(mcp23017Write);
i2cWrite(address);
i2cStop();
/*Read data from the given address*/
i2cStart();
i2cWrite(mcp23017Read);
unsigned char i2cData=i2cRead(1);
i2cStop();
return i2cData;
}
int main(void)
{
unsigned char i2cData;
i2cInit();
/*Pull SCL and SDA high*/
PORTC=0x03;
/*Set GPIOA To Input*/
mcp23017Config(IODIRA,0xFF);
/*Set GPIOB To Output*/
mcp23017Config(IODIRB,0x00);
/*Turn On Pull Up Resistors On GPIOB*/
mcp23017Config(GPPUA,0xFF);

_delay_ms(10);
while (1)
{
/*Read digital input from GPIOA*/
i2cData=mcp23017Return(GPIOA);
/*Send it back to GPIOB*/
mcp23017Config(OLATB,i2cData);
_delay_ms(10);
}
}

Schematic Diagram

ATMega32 TWI interfaces to MCP23017 I2C I/O expander
Schematic Diagram - The master TWI doesn't use any other digital I/O rather than its TWI pins.

Click here to download the zip file of this example project.


If you want a standard PCB for ATMega32 micro-controller, you can order my AVR Microcontroller project from PCBWay with a reasonable price. Click here to get a free $5 credit for new account.

Interfacing ATMega32 to 74HC595 shift register
ATMega16 ATMega32 Experiment Board PCB from PCBWay

10 comments:

  1. If you had financial problems, then it is time for you to smile. You only need to contact Mr. Benjamin  with the amount you wish to borrow at the low rate of 2% ROI and the payment period that suits you and you will have your loan  within three working days. I just benefited for the sixth time a loan of 700 thousand dollars for a period of 180 months with the possibility of paying before the expiration date. Mr Benjamin has been helping me with the loan.Make contact with him and you will see that he is a very honest man with a good heart.His email is  247officedept@gmail.com   and his WhatApp phone number is + 1-989-394-3740 .

    ReplyDelete
  2. Hi there, I found your blog via Google while searching for such kinda informative post and your post looks very interesting for me. IRF740 alternative

    ReplyDelete
  3. I am truly pleased to discover this website as well as do appreciate reading through helpful content articles submitted right here. The actual suggestions from the writer had been amazing, many thanks for that reveal Dofollw Backlinks

    ReplyDelete
  4. Wow, What a Excellent post. I really found this to much informatics. It is what i was searching for.I would like to suggest you that please keep sharing such type of info.Thanks Unique Dofollow Backlinks

    ReplyDelete
  5. Admiring the time and effort you put into your website and in depth information you present. It’s good to come across a blog every once in a while that isn’t the same old rehashed information. Wonderful read! I’ve bookmarked your site and I’m adding your RSS feeds to my Google account. vape attic olathe

    ReplyDelete

Search This Blog

Labels

25AA010A (1) 8051 (7) 93AA46B (1) ADC (30) Analog Comparator (1) Arduino (15) ARM (6) AT89C52 (7) ATMega32 (54) 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 (46) Master/Slave (1) MAX7221 (1) MCP23017 (5) MCP23S17 (4) Meter (3) MikroC (2) Motor (15) MPLABX (66) 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 (2) SPI (24) STM32 (6) STM32 Blue Pill (6) STM32CubeIDE (6) STM32F103C8T6 (6) SysTick (3) temperature sensor (11) Thermometer (21) Timer/Counter (30) TM1637 (2) UART (7) Ultrasonic (4) Voltmeter (7) WDT (1) XC16 (2) XC8 (94)