Revision | Description | Date |
---|---|---|
1.0 | I2C Description | 10/27/14 |
The I2C topics seem to be a bit confusing.
I am creating this Blog to address these concerns.
I will post a video shortly that will thru a Code Walk Thru.
NOTE:
There is a known issue with i2cm_* functions.
You must use cfa_* functions instead.
i2cm_* can only be used when patch enable_spiff1_i2c_interop.a is used *and* NV is serial flash on SPI1
Here are miscellaneous notes that have collected regarding the I2C Issues:
Both SCL and SDA should be high before I2C communication begins.
SPIFFY1 is shared with I2C, which is already being used to talk to the EEPROM on the module.
SPI-flash and I2C interfaces concurrent:
We don’t have the drive strength once to drive the I2C line hard enough with a total of 4 slaves on the bus.
How the SDA pin is sampled during boot by the firmware and how the I2C pins behave:
How to decrease the clock speed during programming (and for subsequent accesses to the EEPROM), because the faster clock speed seems to be causing another i2c device to lock up:
See i2cm.h, i2cm_setSpeed(). Use I2CM_SPEED_* from this header.
If you use cfa_* API that is used by the i2c_temperature_sensor sample, you cannot change the I2C bus speed (defaults to 400KHz). You can use the corresponding API in i2cm.h to read/write the same data and also change speed if required
I2C and P_UART Dependency:
To use it, you just have to include the patch and use the API in i2cm.h:
# Add to application’s makefile.mk:
APP_PATCHES_AND_LIBS += enable_spiffy1_i2c_interop.a
The in application, #include “i2cm.h” and use the I2C API in this header to access the I2C slaves. No changes to the way you access NV (using bleprofile_*)
The cfa.h interface is where most people failed in their code
Example Code:
// Reads 16 bits from the given register address in LM73.
// \param register_address The address to the register to read.
// \param data INOUT Pointer to a INT16 into which the data is to be read, valid only if return value is 1.
// \return 1 if successful, 0 on failure.
UINT8 temperature_sensor_read_16_bit_register(UINT8 register_address, INT16* data)
{
UINT8 read_status;
UINT8 return_value = 0;
UINT8 reg_read_bytes_to_write[1];
UINT8 reg_bytes_to_read[2];
reg_read_bytes_to_write[0] = register_address;
// Do a combo write then read operation
read_status = i2cm_comboRead(reg_bytes_to_read, sizeof(reg_bytes_to_read), reg_read_bytes_to_write,
sizeof(reg_read_bytes_to_write), LM73_SLAVE_ADDR);
switch(read_status)
{
case I2CM_BUSY:
// Transaction did not go through. ERROR. Handle this case.
// There is already a pending transaction.
break;
case I2CM_SUCCESS:
// The read was successful.
*data = (INT16)(reg_bytes_to_read[1] | reg_bytes_to_read[0] << 8);
return_value = 1;
break;
case I2CM_OP_FAILED:
// No slave device with this address exists on the I2C bus. ERROR. Handle this.
default:
break;
}
return return_value;
}
// Writes the given value ino the given 16 bit register.
// \param register_address The address of the register to write to.
// \param data The data to write.
// \return 1 on success; else 0.
UINT8 temperature_sensor_write_16_bit_register(UINT8 register_address, INT16 data)
{
UINT8 read_status;
UINT8 return_value = 0;
UINT8 reg_bytes_to_write[3];
reg_bytes_to_write[0] = register_address;
reg_bytes_to_write[1] = (data >> 😎 & 0xFF;
reg_bytes_to_write[2] = data & 0xFF;
read_status = i2cm_write(reg_bytes_to_write, sizeof(reg_bytes_to_write), LM73_SLAVE_ADDR);
switch(read_status)
{
case I2CM_BUSY:
// Transaction did not go through. ERROR. Handle this case.
// There is already a pending transaction.
break;
case I2CM_SUCCESS:
// The read was successful.
return_value = 1;
break;
case I2CM_OP_FAILED:
// No slave device with this address exists on the I2C bus. ERROR. Handle this.
default:
break;
}
return return_value;
}
// Reads given register by first writing the pointer register
// then reading the register value. Leaves the pointer register as is when leaving
// \param register_address The register to read from
// \param data INOUT Pointer to a buffer into which to read. Valid only if the return value is 1
// \return 1 on success; else 0.
UINT8 temperature_sensor_read_8_bit_register(UINT8 register_address, UINT8* data)
{
UINT8 read_status;
UINT8 return_value = 0;
UINT8 reg_bytes_to_read[1];
// Do a combo write then read operation
read_status = i2cm_comboRead(reg_bytes_to_read, sizeof(reg_bytes_to_read), ®ister_address,
sizeof(register_address), LM73_SLAVE_ADDR);
switch(read_status)
{
case I2CM_BUSY:
// Transaction did not go through. ERROR. Handle this case.
break;
case I2CM_SUCCESS:
// The read was successful.
*data = reg_bytes_to_read[0];
return_value = 1;
break;
case I2CM_OP_FAILED:
// No slave device with this address exists on the I2C bus. ERROR. Handle this.
default:
break;
}
return return_value;
}
// Writes the given value to the given register by first writing the pointer register
// then writing the value. Leaves the pointer register as is when leaving.
// \param register_address The address of the register to write to.
// \param data The data to write to the register.
// \return 1 on success; else 0.
UINT8 temperature_sensor_write_8_bit_register(UINT8 register_address, UINT8 data)
{
UINT8 read_status;
UINT8 return_value = 0;
UINT8 reg_data_bytes[2];
reg_data_bytes[0]= register_address;
reg_data_bytes[1] = data;
read_status = i2cm_write(reg_data_bytes, sizeof(reg_data_bytes), LM73_SLAVE_ADDR);
switch(read_status)
{
case I2CM_BUSY:
// Transaction did not go through. ERROR. Handle this case.
break;
case I2CM_SUCCESS:
// The read was successful.
return_value = 1;
break;
case I2CM_OP_FAILED:
// No slave device with this address exists on the I2C bus. ERROR. Handle this.
default:
break;
}
return return_value;
}
Show Less
Product Selection | Product Evaluation | WICED Sense | Product Development | Manufacturing / Production |