Hi there,
well, look's like I'm not the only one you had problems in getting the I2C on the Stellaris devices up 'n running!
That's why I decided to share some of my code for I2C master communication here. It's doing I2C handling in polled fashion.
You'll find to files in the enclosed archive:
I2C_Stellaris_API.c --> the I2C driver source code
I2C_Stellaris_API.h --> the related header file with prototype definitions.
I think the source code is well documented but here are some additional information on how to use the code:
void I2CSetup(unsigned long ulI2CPeriph, unsigned long ulI2CSpeed);
Used for initializing the desired I2C peripheral. When you want to use I2C3 with 400kHz you need to call it like:
I2CSetup(I2C3_MASTER_BASE, true);
unsigned long I2CRegRead(unsigned long ulI2CBase, unsigned char ucSlaveAdress, unsigned char ucReg);
unsigned long I2CRegWrite(unsigned long ulI2CBase, unsigned char ucSlaveAdress, unsigned char ucReg, unsigned char ucValue);
These two functions can be used for reading/writing a single byte of data to/from a I2C slave register. The code snippet below shows how to use them for checking the communication with a TI TLC59116 LED driver:
// TLC59116 checking (slave address 0xD0)
//
// Read the "PWM0" Register (register address 0x02).
//
ucRegReadOrig = I2CRegRead(I2C3_MASTER_BASE, 0xD0, 0x02);
//
// Write back the inverted original value.
//
I2CRegWrite(I2C3_MASTER_BASE, 0xD0, 0x02, (~ucRegReadOrig));
//
// Read the "PWM0" Register again.
//
ucRegReadNew = I2CRegRead(I2C3_MASTER_BASE, 0xD0, 0x02);
//
// Check the values.
//
if(ucRegReadNew == (~ucRegReadOrig))
{
//
// Wait in loop for debugging.
//
while(1)
{
};
}
else
{
//
// Write back the original value.
//
I2CRegWrite(I2C3_MASTER_BASE, 0xD0, 0x02, ucRegReadOrig);
}
unsigned long I2CReadData(unsigned long ulI2CBase, unsigned char ucSlaveAdress, unsigned char ucReg, char* cReadData, unsigned int uiSize);
unsigned long I2CWriteData(unsigned long ulI2CBase, unsigned char ucSlaveAdress, unsigned char ucReg, char* cSendData, unsigned int uiSize);
These two functions can be used for bulk reading/writing of data from/to I2C slave devices.
Here is an example on how to use them (slave device is a TlC59116 again):
char readValues[16] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
..
// Read back the values (device address is 0xD0; reading starts at address 0x02 with auto-increment on brightness registers)
I2CReadData(I2C3_MASTER_BASE, 0xD0, 0xA2, readValues, 16);
// invert PWM0 register value
readValues[0] = ~readValues[0];
// Write the values (device address is 0xD0; writing starts at address 0x02 with auto-increment on brightness registers)
I2CWriteData(I2C3_MASTER_BASE, 0xD0, 0xA2, readValues, sizeof(readValues));
..
Choose the functions that suits your needs best (I'm using both sets).
PLEASE NOTICE:
This code is still lacking the timeout and error handling functionality!
Feel free to submit improvements/suggestions to the code. Please also report BUGS (if there'e any). Thank you in advance!
The code is using LM4F120H5QR ROM! If you want to use the Stellarisware software libraries just delete every 'ROM_' from the code.
EDIT 30/1212: Added a new revision, including the I2C 'address sniffer' routine (also refer to http://e2e.ti.com/support/microcontrollers/stellaris_arm_cortex-m3_microcontroller/f/471/t/235977.aspx for more info on the 'sniffer') and setup-code for the console I/O.
Kind regards
aBUGSworstnightmare