sadlpx
Joined: 19 Feb 2004 Posts: 23
|
MCP23016 |
Posted: Wed Feb 09, 2005 9:22 am |
|
|
Finally got the MCP working after lots of time.
Short background GP0 is all outputs.
GP1 is all inputs.
Kept having inputs go off on the I2cread. Tough to debug problem would go away when i stepped through code. Problem appears to be that more time is required before each I2cstart. Changed delay from 20 to 50usec just before the second i2cstart in the read _MCP and problem went away.
Hope this is useful
Code: |
///////////////////////////////////////////////////////////////////////////////
//
//
////////////////////////////////////////////////////////////////////////////////
#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)
unsigned int MCP_D1, MCP_d2;
// 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 <BPP_420 LCD.C>
#define MCP23016_I2C_WRITE 0x40
#define MCP23016_I2C_READ 0x41
// 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
unsigned char MCP23016_Device_Address; // MCP23016 Assigned Device Address.
int GPIO_port; // MCP23016 Data Port Register.
// MCP23016 - I2C constants for selecting type of data transfer.
#define I2C_MCP23016_GP0_READ 0x41 // 1001 1111
#define I2C_MCP23016_GP0_WRITE 0x40 // 1001 1110
#define I2C_MCP23016_GP1_READ 0x41 // 1001 1111
#define I2C_MCP23016_GP1_WRITE 0x40 // 1001 1110
// ----------------------------------------------------------------------------
void write_to_MCP(unsigned char WriteAddress, unsigned char cmdByte,
unsigned char lsbData, unsigned char msbData) //, 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_write(msbData); // Second data byte pair as per command byte(cmd)
delay_us(20);
i2c_stop(); // stop condition
delay_us(50); // delay to allow write (12us)min.
}
// ----------------------------------------------------------------------------
Long int read_MCP(unsigned int WriteAddress, unsigned int cmdByte, unsigned int ReadAddress)
{
int Data, lsbData, msbData;
long int ldata;
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(50);
i2c_start();
delay_us(20); // restart condition
i2c_write(ReadAddress); // Send slave address and clear (R_/W)
delay_us(20);
lsbData = i2c_read(1); // Data from LSB or MSB of register
delay_us(20);
msbData = i2c_read(0); // Data from LSB or MSB of register
delay_us(20);
i2c_stop(); // stop condition
delay_us(50); // delay to allow read (12us)min.
MCP_D1 = lsbdata;
MCP_d2 = msbdata;
ldata = (msbdata<<8);
ldata = ldata + lsbdata;
return(ldata);
}
// ----------------------------------------------------------------------------
/*
void init_mcp23016(unsigned char MCP23016_Device_Address)
{
// Wait for MCP23016 Expander Device to power-up.
delay_ms(250);
delay_ms(250);
delay_ms(250);
// Set-up selected I/O expander unit
//write2Expander(MCP23016_Device_Address, IPOL0, 0xFF, 0xFF); // Invert all input polarities if active low.
//write2Expander(MCP23016_Device_Address, IPOL1, 0xFF, 0xFF); // Invert all input polarities if active low.
write2Expander(MCP23016_Device_Address, IPOL0, 0x00, 0x00); // NonInvert all input polarities if active low.
write2Expander(MCP23016_Device_Address, IPOL1, 0x00, 0x00); // NonInvert all input polarities if active low.
write2Expander(MCP23016_Device_Address, IOCON0, 0x01, 0x01); // IARES(1) to max. activity detection time.
write2Expander(MCP23016_Device_Address, IOCON0, 0x01, 0x01); // IARES(1) to max. activity detection time.
write2Expander(MCP23016_Device_Address, IODIR0, 0x00, 0x00); // Direction of all data is output.
write2Expander(MCP23016_Device_Address, IODIR1, 0x00, 0x00); // Direction of all data is output.
write2Expander(MCP23016_Device_Address, OLAT0, 0xFF, 0xFF); // Update o/p latch that controls the output.
write2Expander(MCP23016_Device_Address, OLAT1, 0xFF, 0xFF); // Update o/p latch that controls the output.
//write2Expander(MCP23016_Device_Address, IODIR0, 0x00, 0x00); // Direction of all data is output.
//write2Expander(MCP23016_Device_Address, IODIR1, 0x00, 0x00); // Direction of all data is output.
}
*/
//=============================================
void main(void) {
int n, nn, o;
long int oo;
putc(3);
putc(12); // Clear LCD
putc(1);
printf("I/O Tester");
write_to_MCP(MCP23016_I2C_WRITE, IODIR0, 0x00, 0xff); // GP0= outputs GP1=inputs
LCD_goto (20);
while(1) {
for (n=0; n<255; ++n) {
delay_ms(500);
nn = (n ^ 0xff);
write_to_MCP(MCP23016_I2C_WRITE, OLAT0, nn, 0);
LCD_goto (20);
printf("\%03d ", n);
oo = read_MCP(MCP23016_I2C_WRITE, GP0, MCP23016_I2C_READ);
LCD_goto (40);
oo = (oo ^ 0xff00);
oo = (oo & 0xff00);
printf("\%04lx ", oo);
}
}
} |
|
|