View previous topic :: View next topic |
Author |
Message |
ibg
Joined: 19 Nov 2003 Posts: 22
|
i2c_write() command |
Posted: Fri Feb 20, 2004 12:06 pm |
|
|
Hi,
I would like to know what's the meaning of the instruction "i2c_write" in the following code (code related with the master of the i2c communication). Is it to specify which device is going to read data from? What does the value '0x01' mean?
i2c_start();
i2c_write(SLAVE_ADDRESS | 0x01);
LCD_string[iLCD]=i2c_read(0);
Thanks for all,
Imanol |
|
|
Vector Research
Joined: 16 Feb 2004 Posts: 10 Location: Kelowna B.C
|
re:i2c_write() command |
Posted: Fri Feb 20, 2004 12:58 pm |
|
|
the 0x01 sets the read/write bit in the address, So in this case the master sends the slaves address with the read bit set, the slave then responds back with the data at that address. a 0x00= write to to the slave address 0x01= read from slave address
Vince |
|
|
jds-pic2 Guest
|
|
Posted: Fri Feb 20, 2004 1:06 pm |
|
|
don't forget though that the slave address is left shifted by one bit.
for example,
Code: |
#define I2CWRITE 0b00000000
#define I2CREAD 0b00000001
// this is a handy routine for taking the i2c physical address
// and shifting the bits left so that the address can simply be
// OR'd with an i2c write command...
int i2c_addr_mask(int device_addr)
{
/* xxxxxIJK --> 00000IJK, then 00000IJK --> 0000IJK0 */
return((device_addr & 0x07)<<1);
}
#define DS1624_ID 0b10010000
#define DS1624_CMD_ACCESSCONFIG 0xAC
#define DS1624_CMD_INITIATECONVERT 0xEE
#define DS1624_CMD_ACCESSTEMPERATURE 0xAA
#define DS1624_CMD_ACCESSMEMORY 0x17
#use i2c(master,sda=PIN_SCTLDAT,scl=PIN_SCTLCLK)
void i2c_ds1624_init(int device_addr)
{
int addr_mask;
addr_mask=i2c_addr_mask(device_addr);
i2c_start();
i2c_write(DS1624_ID | addr_mask | I2CWRITE); /* mode is write */
i2c_write(DS1624_CMD_ACCESSCONFIG); /* send access config command */
i2c_write(0x00); /* set up for continuous temp conversions */
i2c_stop();
delay_ms(20); /* wait for the data to be written */
i2c_start();
i2c_write(DS1624_ID | addr_mask | I2CWRITE); /* mode is write */
i2c_write(DS1624_CMD_INITIATECONVERT); /* initiate temperature conversions */
i2c_stop();
}
|
jds-pic |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Feb 20, 2004 1:30 pm |
|
|
Quote: | don't forget though that the slave address is left shifted by one bit. |
That's true, but it's so much easier to define the slave address as
an 8-bit value in your code, instead of a 7-bit value that you have
to shift left.
For example, in a 24LC256 driver, I do this:
Code: | #define EEPROM_I2C_WRITE_ADDR 0xA0
#define EEPROM_I2C_READ_ADDR 0xA1 |
Then in the code, you use it like this:
Code: | char read_eeprom_byte(long addr)
{
char data;
i2c_start();
i2c_write(EEPROM_I2C_WRITE_ADDR);
i2c_write((char)(addr >> 8));
i2c_write((char)addr);
i2c_start();
i2c_write(EEPROM_I2C_READ_ADDR);
data = i2c_read(0);
i2c_stop();
return(data);
} |
This way, you don't have to worry about shifting the slave address
and it's so much easier. |
|
|
jds-pic2 Guest
|
|
Posted: Fri Feb 20, 2004 1:56 pm |
|
|
PCM programmer wrote: |
That's true, but it's so much easier to define the slave address as
an 8-bit value in your code, instead of a 7-bit value that you have
to shift left. |
agreed. unless you have many i2c devices hanging off of the bus, which is the case in my example above.
so. for example, the function
i2c_ds1624_init(int device_addr)
is used to initialize 6 Dallas DS1624 temperature sensor devices, and it's easier to abstract them by their physical addresses (set by A0/A1/A2 pins) rather than their logical READ/WRITE addresses.
Code: |
main() {
[...]
for (i=DS1624[0].addr; i<=DS1624[5].addr; i++)
i2c_ds1624_init(DS1624[i].addr);
[...]
|
since all of the left shifting happens in the i2c abstraction layer (where it should), i only need to deal with physical addresses in my code. and when it comes to debugging the schematics at 2AM that's a benefit [to me...].
but as you noted you can go the other way as well.
jds-pic[/code] |
|
|
|