[PIC] Problem with MCP23017 IO Expander

Status
Not open for further replies.

saikiran@ees

Member level 3
Joined
Oct 2, 2015
Messages
58
Helped
0
Reputation
0
Reaction score
0
Trophy points
6
Location
Hyderabad
Visit site
Activity points
455
Hi Friends,

I am using dsPIC30F5011 micro controller and I want to control dip switches through io expander that means on and off the switches by detecting the range.In between dip switch and io expander, I connected UNL2803 driver IC.

Basically i tested it for LED on/off but it is also not working.So give me suggestions,for led's on/off using io expander with i2c protocol.



Thanks and Regards,
M SAI KIRAN.
 

hello,


maybe this test for MCP23017 ( + DS1307) can inspire you ...

Code:
 sur le bus I2C à 100Khz
// Fosc =16Mhz

#include "p18f26k22.h"

#define OSCILLATEUR_INTERNE
// voir Help
//  Topics
//        Pic18
//            config bits settings
//                    choisir PIC18F26K22
#ifdef OSCILLATEUR_INTERNE
#pragma config FOSC = INTIO67, FCMEN = OFF, PLLCFG=OFF            // CONFIG1H
#else
#pragma config FOSC = HSMP, PLLCFG=ON, PRICLKEN=ON ,FCMEN=OFF      // quartz 10Mhz
#endif
#pragma config IESO=OFF,PWRTEN=OFF,BOREN=OFF,WDTEN=OFF,CCP2MX=PORTC1
#pragma config PBADEN=OFF,T3CMX=PORTC0,P2BMX=PORTC0,CCP3MX=PORTB5
#pragma config MCLRE=EXTMCLR,STVREN=OFF,LVP=ON,XINST=OFF,DEBUG=OFF
#pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF                    // CONFIG5Lhello
#pragma config CPB = OFF, CPD = OFF                                          // CONFIG5H
#pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF                // CONFIG6L
#pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF                            // CONFIG6H
#pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF            // CONFIG7L
#pragma config EBTRB = OFF                                                   // CONFIG7H

//#include <p18cxxx.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <i2c.h>

#include <delays.h>
#include <usart.h>

#include "../_common/Uart1.h"
#include "../_common/I2C_RTC_DS1307.h"
#include "../_common/RTC_DS1307.h"


/*
Uart1.h
void Init_UART1(void);
void Put_RS( unsigned char  untel);
void PutStr_RS( unsigned char *s);
void PutStrR_RS(const rom  char *s);
void PutR_RS( const rom  char * untel);
void CRLF(void);
void Tempo(long L);
------------
RTC_DS1307.h"
unsigned char sec, min, hr, week_day, day, mn, year;
void readDS1307(void);
void writeDS1307(void);
void Transform_Time_BCD_To_Binary(char s, char m, char hr, char wd, char d, char mo, char y);
----------------
Hardware
No Quartz ( FOSC interne 16MHz)
RC3 =SCL  avec R pull-up de 2,7K
RC4 =SDA  avec R pull-up de 2,7K
RC6 =TX   UART to Linvor BT to display result
RC7 =RX   UART to Linvor BT not used
*/


#ifndef Byte
#define Byte unsigned char
#endif 

#ifndef CLS
#define CLS 12
#define TAB 9
#endif

#define Led_Rouge LATAbits.LATA4
#define Led_Blanche LATBbits.LATB0

#pragma udata

unsigned char Texte[80];
unsigned char * txt;

unsigned char  donnee,status;	
int i,j,k;
unsigned char sec, min, hr, week_day, day, mn, year;
unsigned char date,mth;
Byte MCP23017_E;
Byte MCP23017_S;
Byte  NbMes;
Byte Allume_led;
Byte Dummy;
unsigned char  addr,donnee,status;
int  BusI2C;

//config MCP23017
// Adresse 0100 A1 A2 A3 R/W
// R/W  0 =write  1 = Read
#define MCP23017_1 0x40      // adress 1er circuit E/S
//#define MCP23017_2 0x48      // adress 2em circuit
#define config_MCP23017 0x00       // page 17 1.1.6  0b10000000
#define docu " MCP23017_DS21952B.pdf"
//--- I2C ------
void I2C_MCP23017_Init(Byte Adr);
void I2C_MCP23017_Write(unsigned char adresse, unsigned char valA);
Byte I2C_MCP23017_Read(unsigned char Adr,unsigned char val2);

//--- autres -----
void Decompile_byte(Byte un);
void Octet2Hex(char number);


void ack(void)                // attend acknowledge (I2C) de l'esclave
{
while(SSPSTATbits.R_W);       // attend fin de transmission
while (SSPCON2bits.ACKSTAT);  // attend fin ACK esclave
}



void I2C_MCP23017_Init(Byte Adresse)
{
StartI2C(); 
Tempo(100L);
WriteI2C(Adresse); 	//envoi de l'adresse
WriteI2C(0x0A); 	//@0A IOCON avec BANK=0
WriteI2C(config_MCP23017); //config_MCP23017 ); // 0x00  bank0
StopI2C();
StartI2C();
WriteI2C(Adresse);	//envoi de l'adresse
WriteI2C(0x00);	 	//@00 adresse de depart = 00
WriteI2C(0x00); 	//@00=IODIRA direction = 00 = output
WriteI2C(0xFF);	 	//@01 IODIRB direction = FF = port B en entree
WriteI2C(0x00);	 	//@02 IOPOLA polarite =FF  sortie idem que pin
WriteI2C(0xFF);   	//@02 IOPOLB polarite =FF  sortie idem que pin
StopI2C();
StartI2C();
WriteI2C(Adresse); 	//envoi de l'adresse
WriteI2C(0x0D); 	// adresse  GPPUB= 0D
WriteI2C(0xFF);  	//@16 = FF =PULL UP portB Enabled
StopI2C();
}

/*ecriture sur un MCP23017*/
void I2C_MCP23017_Write(Byte adr, Byte valA)
{
StartI2C(); 	// Issue start signal
WriteI2C(adr);
WriteI2C(0x12); //Registre du Port A
WriteI2C(valA);
StopI2C();
}

Byte I2C_MCP23017_Read(Byte Adr,Byte Registre)
{
Byte err;
Byte resu;
unsigned int k1;
StartI2C();
 Tempo(100L);
WriteI2C(Adr);
WriteI2C(Registre); //Lecture Registre du Port B
StopI2C();
StartI2C();
Tempo(100L);
WriteI2C(Adr + 1 );
k1= ReadI2C();
resu= (unsigned char)k1;
I2CACK(1); // was ack()
StopI2C();
return( resu);
}


void Decompile_byte(Byte un) {
char masque;
  masque = 128u;
  while (masque > 0u ) {
    if ((un & masque)>0)
      Put_RS(49u);  //  '1'
    else
      Put_RS(48u);  //  '0'
    masque >>= 1u;
    }
 // Usart_Write(10);
}

void Octet2Hex(char number)
{
char high,low;
  // high nibble
  high = ((number & 0xF0) >> 4) + 48; // + '0'
  if (high > '9')
    high =high + 7;
 // low nibble
  low = (number & 0x0F) + 48;          // +'0' low nibble
  if (low > '9')                       // '9'= 57u
    low += 7;                         // > '9'
  Put_RS(high);
  Put_RS(low);
  Put_RS('h');
 }




void main(void)
{
  ANSELA=0;
  TRISA=0b1101111;  // RA4 as output for led roouge
  Led_Rouge=1; // eteinte
  TRISB = 0xFF;
  PORTB = 0x00;
  ANSELC=0;       // <- pic18F26K22
  TRISC = 0b10011000;  // RC3,RC4 as Input RC7 as input  other => output
    
     #ifdef OSCILLATEUR_INTERNE  
// The internal oscillator is set to the default frequency of 1 MHz.
// The Internal Oscillator Frequency Select bits  (IRCF<2:0>)
// select the frequency output of the internal oscillator block  
   OSCCON=0b01110000;  //HFINTOSC – (16 MHz)
// OSCCONbits.IRCF2=1; //HFINTOSC – (16 MHz)
// OSCCONbits.IRCF1=1;
// OSCCONbits.IRCF0=1;
//111 = HFINTOSC –      (16 MHz)
//110 = HFINTOSC/2 –    (8 MHz)
//101 = HFINTOSC/4 –    (4 MHz)
//100 = HFINTOSC/8 –    (2 MHz)
//011 = HFINTOSC/16 –   (1 MHz)(3)
    OSCTUNE=0;
    OSCTUNEbits.PLLEN=0;  // 1= avec PLL => 64Mhz    0 =sans PLL => 16Mhz 
    #endif   
    
   
    Init_UART1();
    Put_RS(CLS);    // efface display terminal
    Tempo(200000L);
    PutR_RS( (const rom  char *)12); // CLS terminal display
    Tempo(300000L);
    PutStrR_RS((const rom unsigned char*)"\r\n Test DS1307 et MCP23017  18F26K22 16MHz 20/01/2014  Mplab C18\r\n");

   OpenI2C1(MASTER,SLEW_OFF);
   Delay10KTCYx(250);
   SSPADD = 39 ;    // at 16Mhz for I2C 100Khz;
   BusI2C=100;
   // SSPADD =9 ;     // at 16Mhz for I2C 400Khz;
   // BusI2C=400;
   // SSPADD = 49 ; // at 20MHz for I2C 100Khz;
   // SSPADD = 24 ; // at 10Mhz for I2C 100Khz;
   StartI2C();
   IdleI2C();
   Delay10KTCYx(250);
  
   k=fprintf(_H_USART,(const rom char *)"\n\r Init UART1 à 19200bds\n\r "); 
   k=fprintf(_H_USART,(const rom char *)" Freq bus I2C=%03d Khz SSPADD= %02d \r\n ",BusI2C,SSPADD);
   k=fprintf(_H_USART,(const rom char *)"Init DS1307 à :  20/01/2014 le 01 15H59M00S \n\r");
   sec=0x00;min=0x59;hr=0x15;week_day=1;
   day=0x20;mn=0x01;year=0x14;
   writeDS1307();  // init time en dur !
   
    k=fprintf(_H_USART,(const rom char *)"\r\n Init MCP23017\r\n ");  
    //On initialise le MCP23017
    I2C_MCP23017_Init(MCP23017_1);
    Tempo(1000L);
    I2C_MCP23017_Write(MCP23017_1,255);
    
   
 while(1)
 {  day=0;mn=0;hr=0; sec=0;min=0;hr=0;week_day=0;year=0;
    k=fprintf(_H_USART,(const rom char*)"Lecture DS1307 avec fonctions Hardware I2C MPLAB\r\n"); 
    //store results into sec,min,hr,week_day,day,mn,year;
    readDS1307();
    Transform_Time_BCD_To_Binary( sec, min, hr, week_day, day, mn, year);
   	k=fprintf(_H_USART,(const rom char*)" DS1307 lecture time (en decimal)%02d/%02d/20%02d le %02d %02dH %02dM %02dS \n\r",day,mn,year,week_day,hr,min,sec);  
   
   //clignotement dees leds port A 
   i=1;
    while (i<256)
   // for ( i = 0; i < 256; i++ )
    {
        Dummy=255u-(unsigned char)i;
       // Dummy=(unsigned char)i;
        I2C_MCP23017_Write(MCP23017_1,Dummy);
        if ((i%16)==0 & (i<16) & (i!=0)) CRLF();
        txt=&Texte[0];
        itoa(i,txt);
        Put_RS('i');
        Put_RS('=');
        k=PutStr_RS(txt);
        Tempo(15000L);
        Put_RS(9);// tabulation
        Led_Blanche=! Led_Blanche;
       i=i<<1;// a commenter si usage de bouce for
    }
    CRLF();
   Tempo(15000L);  
   k=fprintf(_H_USART,(const rom char*)"relecture latch Port A MCP23017_1   : ");
  MCP23017_E = I2C_MCP23017_Read(MCP23017_1,0x14);
  Allume_led=255u-MCP23017_E;
   Decompile_byte(Allume_led ); 
   CRLF();
 
   Tempo(15000L);
  // Lecture du Port B MCP23017_1
     k=fprintf(_H_USART,(const rom char*)"Lecture Entrees du portB MCP23017_1 : ");
  MCP23017_E = I2C_MCP23017_Read(MCP23017_1,0x13); // lecture portB MCP
  Allume_led=255u-MCP23017_E;
  Decompile_byte(Allume_led );
  
   CRLF();CRLF();
   Delay10KTCYx(500);
   Led_Rouge=!Led_Rouge;
 }
}
/*

Test DS1307 et MCP23017  18F26K22 16MHz 20/01/2014  Mplab C18

 Init UART1 à 19200bds
  Freq bus I2C=100 Khz SSPADD= 39 
 Init DS1307 à :  20/01/2014 le 01 15H59M00S 

 Init MCP23017
 Lecture DS1307 avec fonctions Hardware I2C MPLAB
 DS1307 lecture time (en decimal)20/01/2014 le 01 15H 59M 00S 
i=1	i=2	i=4	i=8	i=16	i=32	i=64	i=128	
relecture latch Port A MCP23017_1   : 10000000
Lecture Entrees du portB MCP23017_1 : 11110111


*/
 
Problem in protocol of MCP23017 IO Expander

Hi,

I wrote the code like this..


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
#include<reg51.h>
#include<stdio.h>
#include<intrins.h>
 
#define ACK      1
#define NO_ACK   0
 
unsigned char i;
unsigned char EData[5];
unsigned char Data;
void InitSerial(void);
void DelayMs(unsigned int);
void WriteI2C(unsigned char);
void Start(void);
void Stop(void);
void ReadBYTE(unsigned int);
void WriteBYTE(unsigned int);
unsigned char ReadI2C(bit);
 
sbit SCL = P2^0;    // connect to SCL pin (Clock)
sbit SDA = P2^1;    // connect to SDA pin (Data)
 
 
 
//---------------------------------------
// Main program
//---------------------------------------
void main(void)
{
    InitSerial();        // Initialize serial port
    putchar(0x0C);        // clear hyper terminal
     DelayMs(50);
     
     Start();
     WriteI2C(0x40);
     WriteI2C(0x00);
     WriteI2C(0xFF);
     Stop();
     DelayMs(50);
     Start();
     WriteBYTE(0x40);
     WriteI2C(0x01);
     WriteI2C(0xFF);
     Stop();
    
     DelayMs(50);
     Start();
     WriteBYTE(0x40);
     WriteI2C(0x12);
     WriteI2C(0x81);
     Stop();
     DelayMs(50);
     Start();
     WriteBYTE(0x40);
     WriteI2C(0x13);
     WriteI2C(0x83);
     Stop();
     DelayMs(50);
 
    WriteBYTE(0x0000);
    WriteI2C('A');        //Write Data's Here
    WriteI2C('B');
    WriteI2C('C');
    WriteI2C('D');  
    WriteI2C('E');
    WriteI2C('F');  
    Stop(); 
    DelayMs(10);
 
    ReadBYTE(0x0000);
    EData[0] = ReadI2C(NO_ACK);   
    EData[1] = ReadI2C(NO_ACK);   
    EData[2] = ReadI2C(NO_ACK);   
    EData[3] = ReadI2C(NO_ACK);   
    EData[4] = ReadI2C(NO_ACK);   
    EData[5] = ReadI2C(NO_ACK);
 
    for(i=0;i<6;i++)
    {
    printf("value = %c\n",EData[i]);   // display data        */
    DelayMs(100);
    }
 
    while(1);
}
 
 
 
//---------------------------------------
// Initialize serial port
//---------------------------------------
void InitSerial(void)
{
  SCON = 0x52;   // setup serial port control
  TMOD = 0x20;   // hardware (9600 BAUD @11.0592MHZ)
  TH1 = 0xFD;   // TH1
    TR1 = 1;       // Timer 1 on
}
 
 
//-------------------------------
// start I2C
//-------------------------------
void Start(void)
{
   SDA = 1;
    SCL = 1;
    _nop_();_nop_();
    SDA = 0;
    _nop_();_nop_();
    SCL = 0;
    _nop_();_nop_();
}
 
//-------------------------------
// stop I2C
//-------------------------------
void Stop(void)
{
    SDA = 0;   
    _nop_();_nop_();
    SCL = 1;
    _nop_();_nop_();
    SDA = 1;
}
 
//-------------------------------
// Write I2C
//-------------------------------
void WriteI2C(unsigned char Data)
{  
 
    for (i=0;i<8;i++)
    {
       SDA = (Data & 0x80) ? 1:0;
         SCL=1;SCL=0;
         Data<<=1;
    }
 
  SCL = 1;
    _nop_();_nop_();
    SCL = 0;
 
}
 
//-------------------------------
// Read I2C
//-------------------------------
unsigned char ReadI2C(bit ACK_Bit)
{
   
   Start();
    WriteI2C(0xA1);
  
 
   SDA = 1;
    for (i=0;i<8;i++)
    {
         SCL   = 1;      
         Data<<= 1;
         Data = (Data | SDA);    
         SCL   = 0;
         _nop_();
    }
  
   if (ACK_Bit == 1)
    SDA = 0; // Send ACK     
    else    
    SDA = 1; // Send NO ACK               
 
    _nop_();_nop_();
    SCL = 1;    
    _nop_();_nop_();
    SCL = 0;
    Stop();
    return Data;
}
 
//-------------------------------
// Read 1 byte form I2C
//-------------------------------
void ReadBYTE(unsigned int Addr)
{
    Start();
    WriteI2C(0xA0);
    WriteI2C((unsigned char)(Addr>>8)&0xFF);
    WriteI2C((unsigned char)Addr&0xFF);
}
 
//-------------------------------
// Write 1 byte to I2C
//-------------------------------
void WriteBYTE(unsigned int Addr)
{
    Start();
    WriteI2C(0xA0);
    WriteI2C((unsigned char)(Addr>>8)&0xFF);    // send address high
    WriteI2C((unsigned char)Addr&0xFF);             // send address low
}                                     
 
 
//---------------------------------------
// Delay mS function
//---------------------------------------
void DelayMs(unsigned int count)
{ // mSec Delay 11.0592 Mhz
   unsigned int i;                    // Keil v7.5a
   while(count)
    {
       i = 115;
         while(i>0) i--;
       count--;
   }
}



In above code,i used i2c for eeprom interfacing and mcp23017 io expander.EEPROM code is working correctly,but mcp23017 is not working.Problem is i wrote the protocol as per the data sheet and i connected led's to the ports.But they are not glowing.So give me suggestions for the protocol is write or not.
And my circuit is like this..
 

Re: Problem in protocol of MCP23017 IO Expander

Are you testing only in Proteus. Whether it is Proteus or real hardware you need 4.7k pull up resistors on SCL and SDA lines for 100 KHz I2C speed. In Proteus you have to set the resistors properties to digital type. Proteus has I2C Debugger to check the communication.
 

Hi Pic Programmer,

Thanks for the reply.Yes i am testing in proteus.If i connected 4.7K pull up resistors to scl and sda line,eeprom data is not displaying in terminal.So,please see my code once and tell any corrections are there in protocol or connections.


Thanks and Regards,
M SAI KIRAN.
 

You need pullup resistor in Proteus. I already told you to open the properties of the resistors and set them as DIGITAL type. Zip and post your Proteus file. I will make changes to it.
 

I have made changes to the proteus file. I have used Proteus 8.3 Sp2 to make changes. Changes made are added 4.7k pullup resistors to I2C Bus and set the resistor type to DIGITAL type. Added RST circuit for CU and connected EA pin of MCU to 5V.

If it still doesn't work then zip and post the complete Keil project files.

You can refer to this code.

http://www.libstock.com/projects/view/799/lcd-i2c-expander-mcp23017


In the first post of this thread you mentioned that you are using dsPIC but your code and proteus file are for 8051.
 

Attachments

  • I2C EEPROM and Port expander.rar
    17.7 KB · Views: 223
Last edited:
Hi Pic.programmer,
It is not working.LED's are not glowing.So i attached the keil files.

Thanks and Regards,
M SAI KIRAN.
 

Attachments

  • MCP23017.rar
    25.7 KB · Views: 188

Yeah,it working,because data writing and retrieving from eeprom through i2c is working.And data is printing on terminal.
 

In the readByte() function I don't see any I2C Read operation and also in ReadByte() and WriteByte() functions I don't see a I2C Stop operation.
 
Last edited:

In the main function,calling WriteByte(0x0000) and it contains i2c start function, device address and starting address of eeprom and after that data is sending through WriteI2c function and at final stop function is called.And same process is doing with ReadByte(0x0000) function and after reading data is printing on terminal.
 

Try the attached code. I have added MCP23017 Communication Code. next step is to add MCP23017_read() function. You try it. Add resistors in series will LEDs. 330E should be fine or use my Proteus file. it opens in Proteus 8.3 SP2.

I have tested the code in Proteus and it is working.
 

Attachments

  • MCP23017.rar
    51.3 KB · Views: 176
Hi Pic.Programmer,

I check the above code and it's working properly.And i have doubt, is the above process is same for all controllers?
I used dsPIC30F5011 controller and used the above process and scl and sda connected through pull of resistors.I want to send the data to the io expander ports for controlling switches.And in my project i2c is used for both eeprom and IO expander.EEPROM is working properly,but io expander is not working.Give me suggestions.

Thanks and Regards,
M SAI KIRAN.
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…