# I2C in a Nutshell | Interrupt

**URL:** <https://community.memfault.com/t/i2c-in-a-nutshell-interrupt/126>\
**Category:** Blog\
**Created:** [January 22, 2020, 6:09am UTC](https://community.memfault.com/t/i2c-in-a-nutshell-interrupt/126 "2020-01-22T06:09:02Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![discobot](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.memfault.com/discobot/32/1_2.png) [@discobot](https://community.memfault.com/u/discobot)\
**Post date:** [January 22, 2020, 6:09am UTC](https://community.memfault.com/t/i2c-in-a-nutshell-interrupt/126/1 "2020-01-22T06:09:02Z")

</div>

I2C is perhaps the most commonly used bus to connect ICs together. As such, firmware engineers encounter it on most project. In this post, we explain how I2C works, explore common bugs and investigate how to debug these issues.

* * *
This is a companion discussion topic for the original entry at [https://interrupt.memfault.com/blog/i2c-in-a-nutshell](https://interrupt.memfault.com/blog/i2c-in-a-nutshell)

---

<div class="post-metadata">

**Author:** ![kin.numaru](https://avatars.discourse-cdn.com/v4/letter/k/c68b51/32.png) [@kin.numaru](https://community.memfault.com/u/kin.numaru)\
**Post date:** [January 22, 2020, 7:02pm UTC](https://community.memfault.com/t/i2c-in-a-nutshell-interrupt/126/2 "2020-01-22T19:02:18Z")

</div>

I think it is worth mentioning that the I2C bus can be stuck and then require a bus reset if the master cannot finish an access. It can happen if the master soft reset during a communication and the slave does not.

The issue is described and solved in the application note: [https://www.analog.com/media/en/technical-documentation/application-notes/54305147357414AN686\_0.pdf](https://www.analog.com/media/en/technical-documentation/application-notes/54305147357414AN686_0.pdf)

Thank you for sharing all these blog posts. This is rare and good content.

---

<div class="post-metadata">

**Author:** ![francois](https://avatars.discourse-cdn.com/v4/letter/f/77aa72/32.png) [@francois](https://community.memfault.com/u/francois)\
**Post date:** [January 22, 2020, 7:25pm UTC](https://community.memfault.com/t/i2c-in-a-nutshell-interrupt/126/3 "2020-01-22T19:25:42Z")

</div>

Thanks for the note! You’re right, I should have mentioned wedged buses. I’ll update the post later today, and add a link to that app note.

Glad you enjoy the blog! We’re always looking for folks who would want to write something, so let me know if you or anyone you know would like to :-).

---

<div class="post-metadata">

**Author:** ![Yafis](https://avatars.discourse-cdn.com/v4/letter/y/aca169/32.png) [@Yafis](https://community.memfault.com/u/Yafis)\
**Post date:** [January 23, 2020, 10:18am UTC](https://community.memfault.com/t/i2c-in-a-nutshell-interrupt/126/4 "2020-01-23T10:18:47Z")

</div>

Hi…Good read to understand I2C.  
I guess it would be better if you had mentioned about Multiple Masters on the bus and topic like bus arbitration.  
Thanks.!!

---

<div class="post-metadata">

**Author:** ![Derrick](https://avatars.discourse-cdn.com/v4/letter/d/d9b06d/32.png) [@Derrick](https://community.memfault.com/u/Derrick)\
**Post date:** [January 23, 2020, 9:55pm UTC](https://community.memfault.com/t/i2c-in-a-nutshell-interrupt/126/5 "2020-01-23T21:55:32Z")

</div>

Francois,

Very good post here.

Thought it may be useful to note that the I2C bus can support speeds in excess of 3 Mbps.

In such a case, the I2C master must transmit a “master code”. The master code must be transmitted at a standard speed and is intended to allow multiple masters to arbitrate. It is up to the system integrator to ensure each I2C master on a single bus has a unique master code.

If the master code is transmitted without issue (no arbitration), the transaction will begin. Due to the high speed, the I2C master actively drives the bus–hence the need to ensure arbitration is handled at a standard speed.

---

<div class="post-metadata">

**Author:** ![xerxesb](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.memfault.com/xerxesb/32/35_2.png) [@xerxesb](https://community.memfault.com/u/xerxesb)\
**Post date:** [January 24, 2020, 5:54am UTC](https://community.memfault.com/t/i2c-in-a-nutshell-interrupt/126/6 "2020-01-24T05:54:29Z")

</div>

Hi - New to digital logic, so I might be misunderstanding something fundamental here…I have two questions…

Looking at almost all of the examples, the example says that it will transmit 0xC6, but the binary representation as 1100110 isn’t 0xC6…Why are they different?

Second question - if the I2C address size is 7-bits, how could you address 0xC6 which would require 8-bits to represent?

Other than that I thought it was a great piece.

Thanks

---

<div class="post-metadata">

**Author:** ![ftheile](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.memfault.com/ftheile/32/36_2.png) [@ftheile](https://community.memfault.com/u/ftheile)\
**Post date:** [January 24, 2020, 4:21pm UTC](https://community.memfault.com/t/i2c-in-a-nutshell-interrupt/126/7 "2020-01-24T16:21:55Z")

</div>

I also find this explanation a little bit strange.

From what I learned and what I’ve seen in data sheets: the address is always 8 bits, but an I2C slave device occupies effectively two addresses: one for read and one for write. Both addresses differ only in the LSB: ‘1’ to read, ‘0’ to write.

In the example, 0xCC would be the write address and 0xCD the read address.

Otherwise, thanks for this blog post! Nice introduction and good overview.

---

<div class="post-metadata">

**Author:** ![free\_electron](https://avatars.discourse-cdn.com/v4/letter/f/c0e974/32.png) [@free\_electron](https://community.memfault.com/u/free_electron)\
**Post date:** [January 24, 2020, 5:46pm UTC](https://community.memfault.com/t/i2c-in-a-nutshell-interrupt/126/8 "2020-01-24T17:46:59Z")

</div>

You can’t really connect 127 devices. There are a number of reserved adresses, general call addresses and backward compatibility locations for CBUS. Not only that, but the bus load for such a number of devices would be too big. You would have to use bus extenders to overcome the capacitive load ( it can be done. Many telecom and server racks use i2c for rack management such as bay temperature voltage and adressing ). You can extend a single bus beyong that number by using adressable i2c multiplexers. They basically create ‘subnets’ on the bus.  
I2C has many more modes like Fast mode and Fast mode plus that go beyond 4Mbit/s.  
There are active terminators ( active pull-ups) that contain switchable current sources. Linear technologies makes those.  
A stuck bus can be cleared by giving clockpulses until SDA goes high , then pulling SDA low , raising SCL followed by raising SDA ( effectively clocking until the data line goes high and then forcing a STOP operation. The bus arbitration mechanism of the I2C standard guarantees this behavior. Even in a multimaster system this procedure is valid.

Shameless plug: I wrote this a while ago [https://www.elektor.com/mastering-the-i2c-bus-e-book](https://www.elektor.com/mastering-the-i2c-bus-e-book) ,  
which is based on the original work i did back in the late mid 90’s by writing The I2C FAQ on sci.electronics.faq

---

<div class="post-metadata">

**Author:** ![francois](https://avatars.discourse-cdn.com/v4/letter/f/77aa72/32.png) [@francois](https://community.memfault.com/u/francois)\
**Post date:** [January 29, 2020, 5:14pm UTC](https://community.memfault.com/t/i2c-in-a-nutshell-interrupt/126/9 "2020-01-29T17:14:11Z")

</div>

Thanks for the note @ftheile and @xerxesb. You’re both correct, I used the “8-bit address” instead of the correct 7-bit address (see more on the two here: [https://www.totalphase.com/support/articles/200349176-7-bit-8-bit-and-10-bit-I2C-Slave-Addressing](https://www.totalphase.com/support/articles/200349176-7-bit-8-bit-and-10-bit-I2C-Slave-Addressing)).

I’ve fixed the post to refer to the 7-bit address: 0x66.

Thanks again!

---

<div class="post-metadata">

**Author:** ![francois](https://avatars.discourse-cdn.com/v4/letter/f/77aa72/32.png) [@francois](https://community.memfault.com/u/francois)\
**Post date:** [January 29, 2020, 5:22pm UTC](https://community.memfault.com/t/i2c-in-a-nutshell-interrupt/126/10 "2020-01-29T17:22:07Z")

</div>

Thanks for the great information!

You are right of course, there are practical limitations to adding many devices to a bus. I think the main point here though is that i2c is multi-slave.

I chose to omit high speed mode, as in my experience few devices support it. For example, popular microcontrollers like the STM32 only go up to “fast-mode-plus” (1MHz).

I’ll add a note about clearing a stuck bus, that’s definitely important and missing from this guide.

---

<div class="post-metadata">

**Author:** ![knepal](https://avatars.discourse-cdn.com/v4/letter/k/b3f665/32.png) [@knepal](https://community.memfault.com/u/knepal)\
**Post date:** [November 1, 2021, 7:01pm UTC](https://community.memfault.com/t/i2c-in-a-nutshell-interrupt/126/11 "2021-11-01T19:01:21Z")

</div>

Stumbled on this old post @ [francois](https://community.memfault.com/u/francois). Quite informative. Keep the blogs coming. WRT to this i2c debug post and flowchart, perhaps there’s one more step to be added. I’ve seen cases [in multi-slave configs, or just in general when power is cycled mid transaction, for example] where the slave holds the SDA line low. General debug technique here, and you can programmatically automate this part is where you’d send a few clocks from the master to help the slave transition out of whatever ‘corrupted’ state it may be in.

---

<div class="post-metadata">

**Author:** ![endolith](https://yyz2.discourse-cdn.com/flex030/user_avatar/community.memfault.com/endolith/32/169_2.png) [@endolith](https://community.memfault.com/u/endolith)\
**Post date:** [January 20, 2022, 5:13pm UTC](https://community.memfault.com/t/i2c-in-a-nutshell-interrupt/126/12 "2022-01-20T17:13:27Z")

</div>

> At the end of every byte, the transmitter releases the SDA line, and on the next clock cycle the receiver must pull the line low to acklowledged the byte.

Can you change this to

> At the end of every byte, the transmitter releases the SDA line, and on the next clock cycle the receiver must pull the **SDA** line low to **acknowledge** the byte.

---

<div class="post-metadata">

**Author:** ![rbsexton](https://avatars.discourse-cdn.com/v4/letter/r/8baadc/32.png) [@rbsexton](https://community.memfault.com/u/rbsexton)\
**Post date:** [February 16, 2022, 1:17am UTC](https://community.memfault.com/t/i2c-in-a-nutshell-interrupt/126/13 "2022-02-16T01:17:31Z")

</div>

This is a common misunderstanding. The spec states that Addresses are 7 bits, plus a read-write bit. When you implement the controller, its simple to treat the r/w bit as an address bit, and you’ll find older device that do it this way.

Because of this, its always better to specify which form of address you’re discussing. On schematics at work, we usually make 7-bit/8bit address tables to eliminate the ambiguity.
