|
|
View previous topic :: View next topic |
Author |
Message |
Markdem
Joined: 24 Jun 2005 Posts: 206
|
Sending on\off command to one port on MCP23016 |
Posted: Fri Jan 27, 2006 7:37 pm |
|
|
Hi All, quick question, how do i send a on or a off command to just one on the outputs on a MCP23016 (eg. GP0.4), without changing any of the other outputs??
Dont know if it is going to help, but here is my code anyway
Driver file
Code: |
#define MCP23016_I2C_WRITE 0x40
#define MCP23016_I2C_READ 0x40
unsigned int MCP_D1, MCP_D2;
// 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.
void write_to_MCP(unsigned char WriteAddress, unsigned char cmdByte,
unsigned char Data) //, 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(Data); // First data byte pair as per command byte(cmd)
delay_us(20);
i2c_stop(); // stop condition
delay_us(50); // delay to allow write (50us)min.
}
// ----------------------------------------------------------------------------
Long int read_MCP(unsigned int WriteAddress, unsigned int cmdByte, unsigned int ReadAddress)
{
int lsbData, msbData;
//int data;
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)
{
// Set-up selected I/O expander unit
write_to_MCP(MCP23016_Device_Address, IPOL0, 0x00); // NonInvert all input polarities if active low.
write_to_MCP(MCP23016_Device_Address, IPOL1, 0x00); // NonInvert all input polarities if active low.
write_to_MCP(MCP23016_Device_Address, OLAT0, 0x00); // Update o/p latch that controls the output.
write_to_MCP(MCP23016_Device_Address, OLAT1, 0x00); // Update o/p latch that controls the output.
write_to_MCP(MCP23016_Device_Address, IODIR0, 0x00); // Direction of all data is output.
write_to_MCP(MCP23016_Device_Address, IODIR1, 0x00); // Direction of all data is output.
}
|
Main Code
Code: |
~
init_mcp23016(MCP23016_I2C_WRITE);
write_to_MCP(MCP23016_I2C_WRITE, OLAT0, 0x00);
delay_ms(1000);
write_to_MCP(MCP23016_I2C_WRITE, OLAT0, 0xff);
delay_ms(1000);
|
the above code will toggle all the outputs on port 0 OK, but i need to change just one of them.
Thank you
Mark |
|
|
ak6dn
Joined: 08 Jan 2006 Posts: 23 Location: Saratoga, CA USA
|
Re: Sending on\off command to one port on MCP23016 |
Posted: Fri Jan 27, 2006 7:53 pm |
|
|
[quote="Markdem"]Hi All, quick question, how do i send a on or a off command to just one on the outputs on a MCP23016 (eg. GP0.4), without changing any of the other outputs??
[/quote
You can't access individual bits of these devices directly as you can a PIC internal register, so you'll have to read in the whole register you want to change, update the bits you want to alter, and write out the entire updated register contents. |
|
|
Markdem
Joined: 24 Jun 2005 Posts: 206
|
|
Posted: Fri Jan 27, 2006 9:39 pm |
|
|
Thanks ak6dn, that is a pitty. It would of been nice and easy to sent to each pin. How do i update just one bit in a byte wihout changing any of the other bits?? |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1907
|
|
Posted: Fri Jan 27, 2006 10:44 pm |
|
|
To change one bit in a byte without affecting the other bits:
Set a bit:
OR the byte with a mask. The bit(s) you want to set are 1's in the mask, the other bits are all 0's.
Clear a bit:
AND the byte with a mask. The bit(s) you want to clear are 0's in the mask, the other bits are all 1's. |
|
|
Markdem
Joined: 24 Jun 2005 Posts: 206
|
|
Posted: Fri Jan 27, 2006 11:09 pm |
|
|
Thanks newguy, do you mean like this??
void device_on(device)
{
latch0 = latch0 | device;
write_to_MCP(MCP23016_I2C_WRITE, OLAT0, latch0);
}
void device_off(device)
{
device = ~ device;
latch0 = latch0 & device;
write_to_MCP(MCP23016_I2C_WRITE, OLAT0, latch0);
} |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1907
|
|
Posted: Sat Jan 28, 2006 1:43 am |
|
|
Yup, what you have would do it. |
|
|
|
|
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
|