I2C in a Nutshell - JohnHau/mis GitHub Wiki
https://interrupt.memfault.com/blog/i2c-in-a-nutshell
I2C is perhaps the most commonly used bus to connect ICs together. As such, firmware engineers encounter it on most projects. In this post, we explain how I2C works, explore common bugs and investigate how to debug these issues. Like Interrupt? Subscribe to get our latest posts straight to your mailbox.
Table of Contents Why use I2C Anatomy of an I2C transaction Ones and Zeroes Start and Stop Addresses Reading and Writing Ack/Nack Clock Stretching Debugging I2C Incompatible Devices Misconfigured Peripherals I2C Address Issues Slave device disabled or not working Line Pull-Up Flowchart Closing Why use I2C I2C has many advantages:
It is cheaper to implement than comparable low-power buses, with fewer pins than SPI1, and a simpler physical layer than CAN2 (no differential signalling). It supports up to 127 devices on a bus with only two pins. It has transfer rates up to 400Kbps, which is fast enough for many human interfaces as well as fan control, temperature sensing and other low-speed contol loops. Historically, it has been less onerous for manufacturers to include than competing protocols like Maxim’s 1-wire protocol3. Many of the sensors and actuators in devices all around us use I2C: temperature sensors, accelerometers, gyroscopes, fans, video bridging chips, GPIO expanders, EEPROMs, …etc.
I2C is not appropriate for all applications however:
When higher bandwidth is required, SPI may be the right choice and can be found in many NOR-flash chips. MIPI can go even faster, and is often used in displays and cameras. If reliability is a must, CAN is the bus of choice. It is found in cars and other vehicles. When a single device is on the bus, UART may work just as well. Anatomy of an I2C transaction I2C is made up of two signals: a clock (SCL), and a data line (SDA). By default, the lines are pulled high by resistors. To communicate, a device pulls lines low and releases them to let them rise back to high.
I2C buses accumulate capacitances when traces are long and devices are added to the bus. You may need stronger pull-ups to overcome it. Counter intuitively, a stronger pull-up is a weaker resistor. In doubt, go to 2K resistors. You will waste a bit of power, but your I2C signal will look great.
Flowchart To make the process easier, we’ve put together a flowchart summarizing the I2C debugging process. You can find it below, or download it here.
Closing I hope this post gave you a useful overview of I2C, and how to debug misbehaving buses and devices.
Did I miss any obscure part of the standard, or forget to mention a debugging technique you find particularly useful? Let us know in the discussion area below!
See anything you'd like to change? Submit a pull request or open an issue at GitHub
Like Interrupt? Subscribe to get our latest posts straight to your mailbox.
Reference Wikipedia: SPI ↩
Wikipedia: CAN ↩
Wikipedia: 1-Wire ↩
TotalPhase: 10-bit vs 7-bit I2C ↩
Salae: How to Analyze I2C ↩
StackExchange: What happens if I omit the pullup resitors? ↩
François Baldassari has worked on the embedded software teams at Sun, Pebble, and Oculus. He is currently the CEO of Memfault.