mercredi 3 juillet 2013

Interfacing an MCP23017 a GPIO expander with a PIC16F877

Hello,
When we dealing with microcontrollers, the number of GPIO (General Purpose Input Output) pins is always limited and sometimes it is impossible to interface some components that desires many outputs from a microcontroller due to the unavailability of pins in the microcontroller and this may lead to change the used microcontroller to another one.
In some other cases, the microcontroller controls a very distant equipment that requires many pins to work, this will lead us to make one wear for each pin and so there is a big chance of loosing data plus there is the high price of the wires.

For this problems there are a simple solution that consists on a GPIO expander. The role of a GPIO expander is to add more GPIO pins to the microcontroller, the microcontroller then is interfacing with the expander using a serial protocols that requires few wires.

In this tutorial I used the MCP23017 which is a GPIO expander by MICROCHIP that talks with a PIC16F877 using I2C protocol.
I used mplab-x and hi tech C for code creation,and proteus ISIS for simulation:

If you want to know more about I2C visit this link.

The schematics:

The code:
I2C.C
#include "Includes.h"

void I2CInit(void){
        TRISC3 = 1;      /* SDA and SCL as input pin */
        TRISC4 = 1;      /* these pins can be configured either i/p or o/p */
        SSPSTAT |= 0x80; /* Slew rate disabled */
        SSPCON = 0x28;   /* SSPEN = 1, I2C Master mode, clock = FOSC/(4 * (SSPADD + 1)) */
        SSPADD = 0x28;    /* 100Khz @ 4Mhz Fosc */
}

/*
Function: I2CStart
Return:
Arguments:
Description: Send a start condition on I2C Bus
*/
void I2CStart(){
        SEN = 1;         /* Start condition enabled */
        while(SEN);      /* automatically cleared by hardware */
                     /* wait for start condition to finish */
}

/*
Function: I2CStop
Return:
Arguments:
Description: Send a stop condition on I2C Bus
*/
void I2CStop(){
        PEN = 1;         /* Stop condition enabled */
        while(PEN);      /* Wait for stop condition to finish */
                     /* PEN automatically cleared by hardware */
}

/*
Function: I2CRestart
Return:
Arguments:
Description: Sends a repeated start condition on I2C Bus
*/
void I2CRestart(){
        RSEN = 1;        /* Repeated start enabled */
        while(RSEN);     /* wait for condition to finish */
}

/*
Function: I2CAck
Return:
Arguments:
Description: Generates acknowledge for a transfer
*/
void I2CAck(){
        ACKDT = 0;       /* Acknowledge data bit, 0 = ACK */
        ACKEN = 1;       /* Ack data enabled */
        while(ACKEN);    /* wait for ack data to send on bus */
}

/*
Function: I2CNck
Return:
Arguments:
Description: Generates Not-acknowledge for a transfer
*/
void I2CNak(){
        ACKDT = 1;       /* Acknowledge data bit, 1 = NAK */
        ACKEN = 1;       /* Ack data enabled */
        while(ACKEN);    /* wait for ack data to send on bus */
}

/*
Function: I2CWait
Return:
Arguments:
Description: wait for transfer to finish
*/
void I2C_Wait(){
        while ( ( SSPCON2 & 0x1F ) || ( SSPSTAT & 0x04 ) );
    /* wait for any pending transfer */
}

/*
Function: I2CSend
Return:
Arguments: dat - 8-bit data to be sent on bus
           data can be either address/data byte
Description: Send 8-bit data on I2C bus
*/
void I2CSend(unsigned char dat){
        SSPBUF = dat;    /* Move data to SSPBUF */
        while(BF);       /* wait till complete data is sent from buffer */
        I2C_Wait();       /* wait for any pending transfer */
}

/*
Function: I2CRead
Return:    8-bit data read from I2C bus
Arguments:
Description: read 8-bit data from I2C bus
*/
unsigned char I2CRead(void){
        unsigned char temp;
/* Reception works if transfer is initiated in read mode */
        RCEN = 1;        /* Enable data reception */
        while(!BF);      /* wait for buffer full */
        temp = SSPBUF;   /* Read serial buffer and store in temp register */
        I2C_Wait();       /* wait to check any pending transfer */
        return temp;     /* Return the read data from bus */
}


MCP23017.C
#include "MCP23017.h"
#include "I2C.h"

void MCP23017_write(unsigned char reg, unsigned char data){
    I2CInit();
    I2CStart();
    I2CSend(DE_ADD_WRITE);
    I2CSend(reg);
    I2CSend(data);
    I2CStop();
}

unsigned char MCP23017_read(unsigned char reg){
    unsigned char Rxbyte;
    I2CStart();
    I2CSend(DE_ADD_WRITE);
    I2CSend(GP_PINS_A);
    I2CRestart();
    I2CSend(DE_ADD_READ);
    Rxbyte= I2CRead();
    I2CStop();
}

void MCP23017_IO(unsigned char PortA_IO, unsigned char PortB_IO){
    MCP23017_write(GPB_A,PortA_IO);
    MCP23017_write(GPB_B,PortB_IO);
}





Aucun commentaire:

Enregistrer un commentaire