This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
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
Just wanted to say thanks. Simple and easy to use. Confirmed working on BMP085.
Hi Greg,
glad you like it!
Have a look at this post here: http://e2e.ti.com/support/microcontrollers/stellaris_arm_cortex-m3_microcontroller/f/471/p/234042/829926.aspx#829926
I've used my I2C driver API to build some code to write to a SSD1308 based 128x64 pixels I2C OLED module. The code will be available in the Stellaris Sharing Forum once I've finisched touch-up and testing of the 'image-printing' routine.
aBUGSworstnightmare
I'd appreciate your help with a clarification.
Your I2CRegRead() operation is defined as:
unsigned long I2CRegRead(unsigned long ulI2CBase, unsigned char ucSlaveAdress, unsigned char ucReg)
with the following comment regarding returned value:
"return Register value in an unsigned long format. Note that 0 will be returned if there is ever an error, 1 if there was not."
I'm sure I'm missing something here but....
Q1: why is the returned value when 4 bytes when I'm reading 1 byte values from slave device?
Q2: how can the return value serve both as "register value" (I assume 1-byte register is LS Byte of 4-byte result) and indicate 1 or 0 for "not an error" or "is...an error", respectively? The register may have returned 1 or 0 content.
Thanks
Hi Tim,
there's no real error handling in place with the current API revision. Nevertheless some 'markers' were there. Pls note that some routines will return in case an error is detected (but the error condition is not handled).
Some timeout and other error handling needs to be implemented --> if you need it yo can add it by your own.
Tim Coddington said:Q1: why is the returned value when 4 bytes when I'm reading 1 byte values from slave device?
Hi, I don't understand this question! When you read one byte of data from a slave you will get one byte of data.
Yes, your right! You will get one byte of data (char), but the routines comsumes 4bytes (unsigned long) for the return value. I agree: that's a total waste of resources! But, feel free to improve the API. I just needed to get some working code and didn't care abut the resources used when coding it. The API will see some improvements during 'field use' but I think it's good to get started with.
Rgds
aBUGSworstnightmare
I am not questioning your hard work. Your api has been very useful so far. I'm in a learning mode and focus on those things that don't meet my expectations or understanding. These questions came to mind when I looked through the code. Thanks
aBUGSworstnightmare,
Initially, I had hoped to drop your I2C_Stellaris_API into my port of one of the MPU6050 based APIs (from Arduino camp) that I found. However, during the process I had to make a few tweaks to make it "integrate" better--read "I hacked it a little to get it to fit my needs". i will try to summarize some of the changes I made to suit my needs below, but eventually I will try to provide an object oriented redesign that includes a fix I had to make. The "fix" I made has been the cause of my problem, which I was finally able to debug after cb1 helped do some pull-ups for my health (sorry, I've been up for 24hrs+ trying to make progress and I'm punchy).
I cannot explain the subtitles of why but the the difference in the I2CMasterControl() commands issued in the I2C_Stellaris_API API and other Stellaris I2C APIs results in different behavior for me.
While other i2c API's coded for the Stellaris Launchpad LM4F have i2c read/write operations that have caller pre-pend the device register address to the data and then call the respective operation with only device address, data address, and byte count, the I2C_Stellaris_API provided operations all require device register address in the call parameters. This in and of itself is not a problem, but the I2CMasterControl() call sequence differences prevented writing any data to the MPU-9150 slave.
Here's where I found another Stellaris Launchpad API: http://scriptogr.am/syntaxerror/post/porting-freeimu-code-to-stellaris-launchpad, in particular it2utils.c/h.
Here's a couple of the changes I made, in case you are curious....
o When I2CSetup() is called I save the peripheral base to a static variable so I can implement read/write operations that did not require it passed as a parameters. This simplified my integration of the API into some of the MPU6050 packages.
o Since I'm not sure how to fix the problem with the I2CReadData() and I2CWriteData(), I reused routines from it2utils in freeIMU.
Now that I'm over the hump I need to get further along before I can come back and clean things up. Thanks for your API and support.
It actually doesn't waste anything for a function to return a 32 bit value over an 8 bit value on the Cortex-M, since the return from the function in both cases is going to be in a register, and therefore will "consume" 32 bits of CPU resource regardless. It's how you use the return value that will ultimately determine the cost to your code.
Generally in C, an int is supposed to be numeric size that's handled best by the underlying processor architecture. This isn't always the case, it's very inconvenient for the programmer to be restricted to 8 bit int on an 8 bit processor, so int (and short int) is usually 16 bits there. When unspecified, C function arguments are assumed to be int and the returns are also assumed to be int.
slandrum said:It actually doesn't waste anything for a function to return a 32 bit value over an 8 bit value on the Cortex-M, since the return from the function in both cases is going to be in a register, and therefore will "consume" 32 bits of CPU resource regardless.
You're absolutely right!
slandrum said:It's how you use the return value that will ultimately determine the cost to your code.
That's why I've added my local variable declaration to the last code snippet here: http://e2e.ti.com/support/microcontrollers/stellaris_arm/f/901/p/249546/874047.aspx#874047
aBUGSworstnightmare
Hello Everyone,
I saw the post is quite old now, but I have a question. Is it necessary to have output pulling resistors on both clk and data lines or is this done internally in the controller?
I use the launchpad LM4F board
Thank you in advance
Hi Costin,
you need to have external pull-ups on both lines (SCL, SDA) for proper operation (http://www.nxp.com/documents/other/39340011.pdf).
Rgds
aBUGSworstnightmare
Hi,
forgot to mention that there's an interrupt based I2C driver included in the Tiva software for the Launchpad http://www.ti.com/tool/sw-ek-tm4c123gxl
Rgds
aBUGSworstnightmare
aBUGSworstnightmare said:there's an interrupt based I2C driver included...
And - outer deck chairs were included on HMS Titanic...
Surely our esteemed Bug always seeks to be helpful. That said - our group (and many clients) most always find I2C to be complex enough by itself... (7 bit Slave Adr w/in 8 bit field - w/varying representations by different vendors...)
And - thread started by our Bug with, "look's like I'm not the only one who had problems in getting the I2C on the Stellaris - up & running!"
Thus, encouraging yet more "technical hoops" (i.e. interrupts) may not be the, "safest/fastest/surest" means to gain I2C mastery.
KISS suggests that "plain vanilla" I2C operation (zero interrupts) should first be implemented - and proven robust. Only at that stage - should the addition of interrupts be attempted...
Troubleshooting/debugging a program with too many demands & restrictions - often causes delay, frustration & confusion. When the objective can be better isolated and confined - better, faster & eased solutions most always result... Baby steps first - long-jump/hurdles - bit downstream... (helps bugs avoid even minor nightmare...)
Thanks for your work, but I can't download the file (403 Forbidden), could you please upload it to external services like Dropbox?
Hi Walter,
find the I2C driver API and the OLED driver enclosed.
aBUGSworstnightmare
I'm getting a 403 Forbidden: Access Denied error whenever I try to download your code. Could you verify that it is still there and the download is working?
Hi Will,
the link from my last post here is working. Here it is again: 5684.I2C Stellaris API.zip
Rgds
aBUGSworstnightmare
P.s. checked it myself before posting it again!
aBUGSworstnightmare said:Hi Will,
the link from my last post here is working. Here it is again: 5684.I2C Stellaris API.zip
Rgds
aBUGSworstnightmareP.s. checked it myself before posting it again!
If I use your library (which is great!!) and try to make a Scan with I2CBusScan, the my output is:
Address found: 0x 0 - 0 Address found: 0x 1 - 1 Address found: 0x 2 - 2 Address found: 0x 3 - 3 Address found: 0x 4 - 4 Address found: 0x 5 - 5 Address found: 0x 6 - 6 Address found: 0x 7 - 7 Address found: 0x 8 - 8 Address found: 0x 9 - 9 Address found: 0x a - 10 Address found: 0x b - 11 Address found: 0x c - 12 Address found: 0x d - 13 Address found: 0x e - 14 Address found: 0x f - 15 Address found: 0x10 - 16 Address found: 0x11 - 17 Address found: 0x12 - 18 Address found: 0x13 - 19 Address found: 0x14 - 20 Address found: 0x15 - 21 Address found: 0x16 - 22 Address found: 0x17 - 23 Address found: 0x18 - 24 Address found: 0x19 - 25 Address found: 0x1a - 26 Address found: 0x1b - 27 Address found: 0x1c - 28 Address found: 0x1d - 29 Address found: 0x1e - 30 Address found: 0x1f - 31 Address found: 0x20 - 32 Address found: 0x21 - 33 Address found: 0x22 - 34 Address found: 0x23 - 35 Address found: 0x24 - 36 Address found: 0x25 - 37 Address found: 0x26 - 38 Address found: 0x27 - 39 Address found: 0x28 - 40 Address found: 0x29 - 41 Address found: 0x2a - 42 Address found: 0x2b - 43 Address found: 0x2c - 44 Address found: 0x2d - 45 Address found: 0x2e - 46 Address found: 0x2f - 47 Address found: 0x30 - 48 Address found: 0x31 - 49 Address found: 0x32 - 50 Address found: 0x33 - 51 Address found: 0x34 - 52 Address found: 0x35 - 53 Address found: 0x36 - 54 Address found: 0x37 - 55 Address found: 0x38 - 56 Address found: 0x39 - 57 Address found: 0x3a - 58 Address found: 0x3b - 59 Address found: 0x3c - 60 Address found: 0x3d - 61 Address found: 0x3e - 62 Address found: 0x3f - 63 Address found: 0x40 - 64 Address found: 0x41 - 65 Address found: 0x42 - 66 Address found: 0x43 - 67 Address found: 0x44 - 68 Address found: 0x45 - 69 Address found: 0x46 - 70 Address found: 0x47 - 71 Address found: 0x48 - 72 Address found: 0x49 - 73 Address found: 0x4a - 74 Address found: 0x4b - 75 Address found: 0x4c - 76 Address found: 0x4d - 77 Address found: 0x4e - 78 Address found: 0x4f - 79 Address found: 0x50 - 80 Address found: 0x51 - 81 Address found: 0x52 - 82 Address found: 0x53 - 83 Address found: 0x54 - 84 Address found: 0x55 - 85 Address found: 0x56 - 86 Address found: 0x57 - 87 Address found: 0x58 - 88 Address found: 0x59 - 89 Address found: 0x5a - 90 Address found: 0x5b - 91 Address found: 0x5c - 92 Address found: 0x5d - 93 Address found: 0x5e - 94 Address found: 0x5f - 95 Address found: 0x60 - 96 Address found: 0x61 - 97 Address found: 0x62 - 98 Address found: 0x63 - 99 Address found: 0x64 - 100 Address found: 0x65 - 101 Address found: 0x66 - 102 Address found: 0x67 - 103 Address found: 0x68 - 104 Address found: 0x69 - 105 Address found: 0x6a - 106 Address found: 0x6b - 107 Address found: 0x6c - 108 Address found: 0x6d - 109 Address found: 0x6e - 110 Address found: 0x6f - 111 Address found: 0x70 - 112 Address found: 0x71 - 113 Address found: 0x72 - 114 Address found: 0x73 - 115 Address found: 0x74 - 116 Address found: 0x75 - 117 Address found: 0x76 - 118 Address found: 0x77 - 119 Address found: 0x78 - 120 Address found: 0x79 - 121 Address found: 0x7a - 122 Address found: 0x7b - 123 Address found: 0x7c - 124 Address found: 0x7d - 125 Address found: 0x7e - 126 I2C Bus-Scan done...
It happens both with the SENSOR HUB BOOSTERPACK connected and without it (just the stellaris launchpad alone).
I am using it under Tivaware 1.1, to adapt the code I replaced the "I2C3_MASTER_BASE" calls with "I2C3_BASE" and added the following includes to your file:
#include <stdint.h> #include <stdbool.h> #include "driverlib/sysctl.h"
Where is the error hiding?
Thanks.
Happens as well with the old Stellarisware for LM4F devices and in all my boards.
In the I2CBusScan function, the ROM_I2CMasterErr call always returns 0. I have tried to debug it by changing it to I2CMasterErr and returns no error.
Hi PAk SY,
the routine worked well with Stellarisware. If tested it on the LM4F120H5QR Launchpad and with an LM4F232 Eval Board.
Have you tested with 100kHz or 400kHz? Do the test with 100kHz! Be shure that your I2C bus is working proppely (check the pull-up resistor values).
Please be aware that this routine is a quick&dirty hack since it only checks if the device is acknowledging an address or not.
I need to say that I've abandoned the SW I2C routines for a while and I've never tested it with TIVAware.
Kind regards
aBUGSwortstnightmare
aBUGSworstnightmare said:Hi PAk SY,
the routine worked well with Stellarisware. If tested it on the LM4F120H5QR Launchpad and with an LM4F232 Eval Board.
Have you tested with 100kHz or 400kHz? Do the test with 100kHz! Be shure that your I2C bus is working proppely (check the pull-up resistor values).
Please be aware that this routine is a quick&dirty hack since it only checks if the device is acknowledging an address or not.
I need to say that I've abandoned the SW I2C routines for a while and I've never tested it with TIVAware.
Kind regards
aBUGSwortstnightmare
I tested it as well under stellarisware.
I have tried with both 100kHz and 400kHz. I am using it with the sensorhub board which includes the pullup resistors.
I have tried to use it without the I2CBUSscan call, and every time I use a function I get stuck in the while (ROM_I2CMasterBusy(ulI2CBase)) loop. (even in I2CRegWrite).
With the scope I can spot some frames after the reset, and then nothing.
This is my I2C main function calls:
ROM_SysCtlClockSet(SYSCTL_SYSDIV_2_5 | SYSCTL_USE_PLL | SYSCTL_XTAL_16MHZ | SYSCTL_OSC_MAIN);
I2CSetup(I2C3_MASTER_BASE, false);
I2CBusScan(I2C3_MASTER_BASE);
Is it required anything else?
Thank you.
Ok, Big News!!
I was able to make it work (partly). However I do not understand the behaviour completely.
I am connecting the SENSOR HUB connected to a TIVA / Stellaris board.
Routes I2C from PD0 to J2.07 for MSP430-Tiva C Series LaunchPad compatibility. If using PD0 or PB6, the unused GPIO must be configured as an input or R9 removed.
etc
Hi PAk SY,
the BOOSTXL.SENSHUB can be used with MSP430 and TIVA Launchpad. That's why PD0/PD1 were bridged to PB6/PB7 via 0 OHM resistors (R9 and R10).
So, when using the boosterpack and if your application is using PB6 and PB7 you'll have to remove R9 and R10 to use I2C3 ! This is not related to the software library, it's a hardware issue with the Launchpad!
So, your use-case 1/3/4 should work, case 2 will not work.
The I2C bus operation relies on the pull-up resistors! Refer to http://www.nxp.com/documents/user_manual/UM10204.pdf for details on the I2C bus.
aBUGSworstnightmare
aBUGSworstnightmare said:Hi PAk SY,
the BOOSTXL.SENSHUB can be used with MSP430 and TIVA Launchpad. That's why PD0/PD1 were bridged to PB6/PB7 via 0 OHM resistors (R9 and R10).
So, when using the boosterpack and if your application is using PB6 and PB7 you'll have to remove R9 and R10 to use I2C3 ! This is not related to the software library, it's a hardware issue with the Launchpad!
So, your use-case 1/3/4 should work, case 2 will not work.
The I2C bus operation relies on the pull-up resistors! Refer to http://www.nxp.com/documents/user_manual/UM10204.pdf for details on the I2C bus.
aBUGSworstnightmare
Watch out!! As I explained in the previous post, the Boosterpacks I2C pins are actually connected to the PB6 and PB7 pins, so you need those R9 and R10 to make it work on the Tiva/Stellaris Launchpads!!!
Thats why only point 1 works
My question is if there is a way for the library to detect nothing is connected, to avoid false found addresses .
PAk SY said:Watch out!! As I explained in the previous post, the Boosterpacks I2C pins are actually connected to the PB6 and PB7 pins, so you need those R9 and R10 to make it work on the Tiva/Stellaris Launchpads!!!
As I said: it's related to the hardware, not the software lib!
And, you're right: R9 and R10 were needed when using the launchpad with the BOOSTXL-SENSHUB since I2C3SDA = PD1 = J3.04 and I2C3SCL = PD0 = J3.03.
--> MSP430 Launchpad compatibility is paid with loosing 2 more I/Os!
aBUGSworstnightmare
Dear aBUGSworstnightmare
Can I get your attached file, 8311.I2C_Stellaris_API_r02.zip ?
Hi avraka,
you're welcome! Here they are:
I2C Stellaris API r02: 3666.I2C_Stellaris_API_r02.zip
I2C Stellaris OLED 128x64 r03 driver: 0385.I2C OLED 128x64 - API_r03.zip (find details here http://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/p/238721/928701.aspx)
TI changes something on the E2E forum which lead to some details get lost (mostly all pictures).
Kind regards
aBUGSworstnightmare
P.S. WoW! Impressive! More than 8.300 views of this thread! Thanks!
aBUGSworstnightmare said:P.S. WoW! Impressive! More than 8.300 views of this thread! Thanks!
And beyond 17K today - quite a nice job by you, mein Bug...
(yet we doubt that this post will register the hit number of your past (restricted?) "Free MCU Board" posting... Confess that some-way/how - our group acquired several...)
Hi cb1,
mir geht es gut, danke (I'm fine, thanks)! And you? Hope you (and your group) is fine too!
You've visited Germany? I hope you didn't had a breakdown on the autobahn (like I had a few weeks ago when heading down to Stuttgart, 'flying-low' at 220km/h on the far left lane :-( Bad luck that day!)).
Well, I've made some posts on the E2E forum --> I don't really know if I've posted some design files too. But, if you can find the post on the forum (I didn't managed to find it) I would be glad if you could send me the link.
By the way - while searching the forum for this thread I hit my 'Is there a request for CCS on MAC OS X' post. Too bad that TI still doesn't support CCS on MAC; 47506 views of this post (making it no.17 when sorting for #ofviews) should make them think about it.
Rgds
aBUGSworstnightmare
Dear aBUGSworstnightmare :
Great thanks for your support.
In fact, my customer want to use TLC59116 in her new project which is operated on LINUX base. So, I am looking for a Linux driver for PWM LED Driver IC (TLC59116). But I cannot find it anywhere. So I hope to get all materials related to TLC59116 including header file which define registers.
Do you know of such a driver in the open source for the TLC59116 ?
Any materials are helpful to me. Plz help....
Thanks.
Hi,
a header file is no problem, here you go: 0564.TLC59116.h
Using this device is easy, so it shouldn't be a big deal to get it up'nrunning under Linux. Here is a sample shot what can be done with the TLC59116 : http://www.youtube.com/watch?v=roAdWY0ph84
Rgds
aBUGSworstnightmare
Hello Sir,
I tried to get this library and i got 403 - Forbidden: Access is denied.Is there any way to download it... ?
Hi,
working links to the sources were in my post dated Nov 22 2013 on page 2 of this thread: http://e2e.ti.com/support/microcontrollers/tiva_arm/f/908/p/235926/1062071.aspx#1062071
Kind regards
aBUGSworstnightmare
Hi,
you should be able to download them from here TLV62569: TLV62569 Application Consult - Power management forum - Power management - TI E2E support ...
If not, find all related stuff attached.
aBUGSworstnightmare
Hi Georg,
be sure to download from 2 post above yours: AM2431: There is something unclear about TRM "1.5.4.8.1.3.3.2 Transmit (TX)" - Arm-based microcontrollers...
All files are there in one .zip file
aBUGSworstnightmare
Thank you. I'm very sorry....
Tried to download from a public network.. :-(
Shame on me.
aBUGSworstnightmare said:Try this one e2e.ti.com/.../TI-I2C_5F00_OLED.zip
Hello, Joerg Quinten , I wonder if you did extend the library to support TM4C129X devices?
Thanks in advance
I will answer myself....there is a problem with I2CMasterErr function, so it is better to use:
Thanks to the decision of TI of not supporting this device and my effort + time....I decided to not provide that information in this forum.
Sorry about any inconvenience.