Jump to content
jrychter

I2C master using the USI module: a tiny library

Recommended Posts

I've written a tiny library that implements I2C master functionality on MSP430 devices that only have the USI module (for example, MSP430G2412 or MSP430G2452). It's small, simple, works well for me, and might help others in their projects.

 

Blog post at http://jan.rychter.com/enblog/msp430-i2c-usi-library-released

 

Github repo at https://github.com/jwr/msp430_usi_i2c

 

Have fun!

 

 

Share this post


Link to post
Share on other sites

Have you considered writing something like this for chips with USCI?  I've been having some issues getting a repeated start to work correctly with the same MMA84 accelerometer you use in the example code in this library (I posted a question on this forum about it the other day).

Share this post


Link to post
Share on other sites

I thought about it. However, there are several reasons why I don't think this will happen soon:

  • These days I mostly use the G24x2 chips, because they are tiny, cheap and low-power. For anything even slightly larger I am moving to Freescale Kinetis. I did a quick'n'rough price comparison (see http://jan.rychter.com/enblog/ti-msp430-vs-freescale-kinetis-a-price-comparison) and it turned out that you can get a 48MHz 32-bit ARM Cortex M0+ for less than the price of a G2553. This means that most of my projects will now use the Kinetis chips, unless I want a simple, small, cheap and very low-power solution (with all of these requirements simultaneously).
  • USCI makes using I2C much easier. There is also code which is I think as close to a library as TI code gets, called "TI_USCI_I2C_master", which (if you manage to find it!) gets the job done. I don't like the interface, and I don't know if it can do repeated start, but when I needed to access a light sensor, it worked for me.
  • Since the "TI_USCI_I2C_master" code solved my immediate problem, I don't have a pressing need to write something of my own :-)

Share this post


Link to post
Share on other sites

I've written a tiny library that implements I2C master functionality on MSP430 devices that only have the USI module (for example, MSP430G2412 or MSP430G2452). It's small, simple, works well for me, and might help others in their projects.

 

please enlighten me why would someone use the USI approach, when software bitbang can use any 2 IO pins and probably result is smaller code?

and as far as I've seen timing is very lax as far as the slave devices are concerned.

Share this post


Link to post
Share on other sites
Well, I don't think I can enlighten you, but I can state my reasons for using USI.

 

It is true that USI is a very primitive peripheral. However, it still gets you:

 

* a shift register,

* a "timer" that precisely times your output,

* interrupts,

* outputs that are capable of simultaneously driving the bus and reading it (read on for why this might be needed).

 

Here are my reasons for using the USI:

 

* No matter what you do, I2C needs two pins. No savings here.

 

* If I wanted to bit-bang, I would also need a timer, and there is only one on the G2412. Seems like a waste to use up such a precious peripheral.

 

* I would have to bit-bang every bit of the output/input (USI has a shift register, so it takes care of 8 bits for you in one go).

 

* The code would likely be much larger, not smaller, and more complex, too (switching pin directions, interrupts, etc). I don't see how you can simplify the I2C state machine by much (I use 6 states + idle), and my code really doesn't do much outside of the state machine.

 

* If I ever wanted arbitration loss detection, the code would become even more complex: for every bit written, you'd need to simultaneously detect that the line has been driven low by someone else.

 

Overall, bit-banging seemed to me like going out of my way so as not to use the USI at all costs. And avoiding the USI makes no sense: what else would I use it for? For projects that need both SPI and I2C, I'd much rather bit-bang SPI.

 

But, I would gladly compare notes with your library that bit-bangs I2C. Perhaps you did manage to simplify the I2C state machine. So, is the library available?

 

EDIT: oops, I missed the link to your code! Sorry. Now, having looked at your code, the tradeoff seems to be that it is significantly larger, more complex, uses busy-waiting, and the I2C clock is strictly tied to your core frequency. For some that is a reasonable tradeoff to get I2C on any GPIO pins they want, for me it wasn't. I'd rather use the USI, since it's already there.

 

BTW, another tradeoff is that your code is under GPLv3, while mine is under the MIT license.

Share this post


Link to post
Share on other sites

I keep a repository of often used libs here [1]. see serial_bitbang.

 

why I use that bitbang code:

  - the code can trivially be ported to any other (slow) uC.

  - no timers are needed. I don't have any numbers at hand, but changing the state of a pin in these slow uCs and a few nops will ensure slower then 400kHz clock speeds that all my i2c slaves support.

 

I am not sure why interrupts are considered a feature in a i2c master implementation. a missing device condition is detected after the slave address is sent out by the master.

 

[1] https://github.com/rodan/reference_libs_msp430f5x/tree/master/drivers

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×