CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to support@ccsinfo.com

trouble with mcp23016 read and write

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
sadlpx



Joined: 19 Feb 2004
Posts: 23

View user's profile Send private message

trouble with mcp23016 read and write
PostPosted: Mon Feb 07, 2005 5:31 pm     Reply with quote

Attached is a peice of code i'm using to learn the MCP23016 io expander by microchip. So far i can write the data i want to GP0 (counting 0 > ff) no problem. now i only have two problemswhich i don't understand.

#1) when i do a read on GP1 the my led's tied to GP0 go off. I'm not writing to GP0 (or am i).

#2) I cannot read anything from GP1 except all 1's back. I hav eth epins tied to vcc (10K), I can pull the pins low with a jumper wire but no change in the data input.

I'm sure i missed something in the setup, and my code looks very much like the basic stamp artical and the Hitech C compiler listing

BUT it no work any ideas.


//////////////////////////////////////////////////////////////////
//
//
////////////////////////////////////////////////////////////////////////////////
#include <16F876.h>
#fuses HS,NOWDT,NOPROTECT,PUT,BROWNOUT,NOLVP
#device ICD=true
#use delay(clock=10000000) // value based on crystal

//Uses a Scott Edwards Electronics 4x20 Serial LCD module
#use rs232(baud=9600,parity=N,xmit=PIN_c4,rcv=PIN_B0,stream=RS232,invert,bits=8)

// Define project I2C communication pins
#define SCL_PIN PIN_A4
#define SDA_PIN PIN_A5
#use i2c(master, sda=SDA_pin, scl=SCL_pin)

// #include <MCP23016_1.c>
#include <BPP_420 LCD.C>

#define MCP23016_I2C_WRITE 0x40
#define MCP23016_I2C_READ 0x41

//=============================================
// #use standard_io(C)
// #use i2c(master,sda=PIN_C4,scl=PIN_C3)

// COMMAND BYTE TO REGISTER RELATIONSHIP : Table: 1-3 of Microchip MCP23016 - DS20090A
#define GP0 0x00
#define GP1 0x01
#define OLAT0 0x02
#define OLAT1 0x03
#define IPOL0 0x04 // INPUT POLARITY PORT REGISTER 0
#define IPOL1 0x05 // INPUT POLARITY PORT REGISTER 1
#define IODIR0 0x06 // I/O DIRECTION REGISTER 0
#define IODIR1 0x07 // I/O DIRECTION REGISTER 1
#define INTCAP0 0x08 // INTERRUPT CAPTURE REGISTER 0
#define INTCAP1 0x09 // INTERRUPT CAPTURE REGISTER 1
#define IOCON0 0x0A // I/O EXPANDER CONTROL REGISTER 0
#define IOCON1 0x0B // I/O EXPANDER CONTROL REGISTER 1

// BLOCK VARIABLE REGISTER

// ----------------------------------------------------------------------------


void write2Expander(unsigned char WriteAddress, unsigned char cmdByte, unsigned char lsbData) //, unsigned char msbData)
{
short int status;

i2c_start(); // start condition
delay_us(20);
i2c_write(WriteAddress); // Send slave address and clear (R/W_)
delay_us(20);
i2c_write(cmdByte); // Command byte and register to be written.
delay_us(20);
i2c_write(lsbData); // First data byte pair as per command byte(cmd)
delay_us(20);
i2c_stop(); // stop condition
delay_us(50); // delay to allow write (12us)min.

}

// ----------------------------------------------------------------------------

int readExpander(unsigned int WriteAddress, unsigned int cmdByte)
{
int Data, lsbData, msbData;
short int status,count;

startRead:
count=0; // Initialize read attempts counter.

i2c_start(); // start condition
delay_us(20);
i2c_write(WriteAddress); // Send slave address and clear (R/W_)
delay_us(20);
i2c_write(cmdByte); // Command byte and register to be written.
delay_us(20);
i2c_start();
delay_us(20); // restart condition
i2c_write(WriteAddress+1); // Send slave address and clear (R_/W)
delay_us(20);
/***/
lsbData = i2c_read(); // Data from LSB or MSB of register
delay_us(20);
i2c_stop(); // stop condition
delay_us(50); // delay to allow read (12us)min.
return(lsbData);
}




void main(void) {
int n, nn, o;

putc(3);
putc(12); // Clear LCD
putc(1);
// LCD_goto(0); // go to position 1
printf("I/O Tester");
write2Expander(MCP23016_I2C_WRITE, IODIR0, 0x00); // Direction of all data is output.
write2Expander(MCP23016_I2C_WRITE, IODIR1, 0xFF); // Direction of all data is input.
LCD_goto (20);

while(1) {

for (n=0; n<255; ++n) {
delay_ms(500);
nn = (n ^ 0xff);
write2Expander(MCP23016_I2C_WRITE, GP0, nn);
LCD_goto (20);
printf("\%03d ", n);

o = readExpander(MCP23016_I2C_WRITE, GP1);
LCD_goto (40);
printf("\%03d ",o);
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Feb 07, 2005 8:19 pm     Reply with quote

I have three comments:

1. You have altered the code from the examples shown in the AN245.
http://ww1.microchip.com/downloads/en/AppNotes/00245.zip
The sample code always writes or reads two bytes. You've changed
it to only handle one byte. Does that work ? All the text in the data
sheet always refers to two bytes:
Quote:
1.9.2 WRITING THE REGISTERS
The I 2 C commands apply to one register pair to provide faster access.

1.9.3 READING THE REGISTERS
The data register defined by the command byte will be sent first,
followed by the other register in the register pair.


2. The sample code for AN245 follows the CCS method of indicating
a NAK with a '0' parameter in the i2c_read() statement.
Quote:
// Receive first DATA byte (LSB) and acknowledge
MCP_LSB=i2c_read(1);
// Receive second DATA byte (MSB) and don't acknowledge
MCP_MSB=i2c_read(0);

In your modified code, you have taken away the NAK on the final
i2c_read() statement. In your case, you only have one statement,
but it is therefore the "final" one, and must do the NAK. So even
if your proposed modification of only accessing one byte turns out
to work, it still is currently going to fail because you don't the '0'
parameter on the i2c_read().

3. You're correct to put the delay_us() statements in there.
The sample doesn't show them in the main source file,
but if you look in the i2cRxTx.c file, they are in there,
in the individual i2c functions.

My suggestion is to follow the sample code exactly. Access the two
bytes. Then if you get that working, try your changes later.
sadlpx



Joined: 19 Feb 2004
Posts: 23

View user's profile Send private message

MCP32016 problem solved
PostPosted: Wed Feb 09, 2005 9:33 am     Reply with quote

I found the problem and posted working code in the code forum.

I rearranged the code as suggested by PCM programmer (thanks by the way) but was still having the inputs on GP0 turn off when i would read GP1. It was tough to find because it would work fine when i stepped through the code using debug (sometimes - depending on breakpoint).

Turns out the second I2Cstart within the read_MCP routine need more time. Increased delay from 20 to 50usec and the problem went away.

Hope this helps someone else.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
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