|
|
View previous topic :: View next topic |
Author |
Message |
cbarberis
Joined: 01 Oct 2003 Posts: 172 Location: Punta Gorda, Florida USA
|
Problem with initialization on MCP23017 I/O expander |
Posted: Thu Nov 01, 2012 4:29 pm |
|
|
I got a question for anyone that has used the MCP23017 A few years back I had a project where I used the SPI version (MCP23S17) and successfully wrote a firmware driver for it without much pain. So after briefly looking at the data sheet for the device it appeared to me that the only differences where the method of serial communications, all registers and op-codes seem the same. So I reversed engineered my old driver so a write_spi()or read_spi() just became a write_i2c() or read_i2c() and of course got rid of chip selects. For some reason I seem to be having a lot of issues trying to get this thing to write anything to the ports, actually it appears to me that it is not being itinitialized correctly. I have also tried modifying the code that comes with the Microchip MCP23X17 demo board without much success. I think I have read the data-sheet a few times now and there is no clue as to what the set-up instructions should be
Here is all I am trying to do with it:
Only use write operations on all 16 I/O pins I do not need to do reads just writes, so just to clarify things what should be the correct initialization code? If I understand correctly the sequence of sending serial info to this device is as follows:
send I2C start
send command byte via I2C ( command byte is: 0,1,0,0,A2,A1,A0,R/W)
wait for IC2 ACK
send restart IC2
send register address byte via I2C
wait for IC2 ACK
send restart IC2
send data byte via I2C
wait for IC2 ACK
send I2C Stop
Perhaps someone can shed some light on the subject or point me in the right direction. Below is the code that I am using for the device driver. I am writing this using the CCS PCD compiler for a PIC24HJ256GP206 the I2C port is working fine (I have already monitored the data using a logic analyzer) and I am already using another I2C EEPROM on the board which is working fine, so it is not a problem directly attribuited to my I2C bus.
Code: |
#define I2CMODE 1
#define SPIMODE 0
#define WrtCmd 0
#define RdCmd 1
#defines are with IOCON.BANK = 0
**************************************************************/
#define IODIRA 0x00
#define IODIRB 0x01
#define IPOLA 0x02
#define IPOLB 0x03
#define GPINTENA 0x04
#define GPINTENB 0x05
#define DEFVALA 0x06
#define DEFVALB 0x07
#define INTCONA 0x08
#define INTCONB 0x09
#define IOCONA 0x0A
#define IOCONB 0x0B
#define GPPUA 0x0C
#define GPPUB 0x0D
#define INTFA 0x0E
#define INTFB 0x0F
#define INTCAPA 0x010
#define INTCAPB 0x011
#define GPIOA 0x012
#define GPIOB 0x013
#define OLATA 0x014
#define OLATB 0x015
#define HRDWADD 6 // device hard address
unsigned char gAddrPins = HRDWADD <<1;
unsigned char SerialMode = I2CMODE;
unsigned char gControlByte = 0x40;
void ResetMCP23X17(){
output_low(IORESET);
delay_us(100);
output_float(IORESET);
}
void InitMCP( void )
{
//Configure 23017
//Write23X17(GPPUA, 0x00); // Pullups
Write23X17(IOCONA, 0x40); //
Write23X17(IOCONB, 0x40);
Write23X17(IODIRA, 0x00); //All outs
Write23X17(IODIRB, 0x00); //All outs
}
/*************************************************************
Function Name: Write23X17
Return Value: void
Parameters: Register address, Data
Description: Writes a 23X17 register. I2C or SPI is in
global byte
**************************************************************/
void Write23X17(unsigned char reg, unsigned char data)
{
if(SerialMode == I2CMODE) //If 23017 selected
I2CWriteByte(reg, data); //
else //Else 23S17 is selected
SPIWriteByte(reg, data); //
}
//****************************************
// I2CWriteByte(unsigned char addr, unsigned char byte)
// Writes a byte to the 23017
//****************************************
void I2CWriteByte(unsigned char reg, unsigned char data)
{ unsigned char ack;
i2c_start(); //Issue Start condition on I2C
// delay_us(50);
i2c_write( gControlByte | WrtCmd | gAddrPins);
delay_us(150); ///// <<<<<<<< I should be using a wait for IC2 ACK rather than a fixed delay...was not shure
/////////////// how to implement a wait for IC2 ACK, not sure this is the problem
// i2c_stop();
i2c_start(); //same as re-start condition on I2C
//delay_us(50);
i2c_write( reg );
delay_us(150);
// i2c_stop();
// delay_us(20);
i2c_start(); // same as re-start condition on I2C
//delay_us(50);
i2c_write( data );
delay_us(150);
i2c_stop();
}
|
|
|
|
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Fri Nov 02, 2012 6:46 am |
|
|
Code: | delay_us(150); ///// <<<<<<<< I should be using a wait for IC2 ACK rather than a fixed delay...was not shure
/////////////// how to implement a wait for IC2 ACK, not sure this is the problem | From the CCS manual on i2c_write: Quote: | Returns: This function returns the ACK Bit.
0 means ACK, 1 means NO ACK, 2 means there was a collision if in
Multi_Master Mode. | The fact that i2c_write returns the ACK bit implies that i2c_write _does_ wait for the ACK bit. Nothing for you to do there, except perhaps checking the return value for an error.
Also get rid of all the I2C restarts, most likely these are your problem. I2c Restart is like an I2C Stop & Start in one command.
Try rewriting your write function as follows: Code: | //****************************************
// I2CWriteByte(unsigned char addr, unsigned char byte)
// Writes a byte to the 23017
//****************************************
void I2CWriteByte(unsigned char reg, unsigned char data)
{
i2c_start();
i2c_write( gControlByte | WrtCmd | gAddrPins );
i2c_write( reg );
i2c_write( data );
i2c_stop();
} |
|
|
|
cbarberis
Joined: 01 Oct 2003 Posts: 172 Location: Punta Gorda, Florida USA
|
|
Posted: Fri Nov 02, 2012 10:22 am |
|
|
ckielstra,
You are 100% correct! The way I was sending the data via I2C was totally incorrect, using your cleaned-up method did the trick.
Thank you so much!
I will most likely post this driver on the forum library once I fully tested and debug it, so others don't have to suffer seeking answers. |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|