I²C Hardware Debugging
I²C is used as a serial interface between chips. It is so commonplace that it is used in so many systems that no problems arise.
However, sometimes even small things can get you hooked.
Here we will introduce some common I²C problems and some easy debugging methods.
0. Table of Contents
table of contents
Anyway it doesn't work! (--;
The target doesn't respond (꒪⌓꒪)
Repeat start was necessary/unavailable
Controllers that do not support clock stretching
Multi-Controller
The clock frequency is lowered
Long distance routing. Noise and crosstalk can cause communication problems.
Measuring Bus Capacitance
SDA Line Stuck and Bus Clear
Who is giving the signal?
Reference materials
1. It just doesn't work! (--;
I forgot to put on the pull-up orz
This is a common problem when using an I²C device for the first time. When you obtain a sample chip and try it out on a breadboard or universal board, you connect it to a microcontroller while checking the I²C signal names. At this point, it's easy to forget to attach a pull-up resistor .
I²C signals have an output called " open drain ." A high-level voltage cannot be obtained unless an external pull-up resistor is attached. When trying to easily check operation using a breadboard, it is easy to forget about this resistor.
Don't forget to use pull-up resistors on the SDA and SCL signals!
How do you determine the pull-up resistor value?
How is the value of a pull-up resistor determined? Generally, values such as 2.2 kΩ or 4.7 kΩ are used. I think many people use these values without much consideration. But what happens if a smaller or larger value is used ?
A pull-up with a small resistance value can cause the problem of "not being able to pull the signal low enough." When a device outputs a low signal, current flows through the pull-up resistor. If the resistance is small, the current flowing here will be large, and this current will flow into the device that is outputting a low signal. The transistor that pulls the signal low inside the device has a resistance component, and this resistance and current create a voltage. For this reason, if the current becomes large, a higher-than-expected voltage will be generated, and a sufficiently low low-level voltage will not be obtained.
Conversely, pull-up resistors with large resistance values can cause problems such as insufficient communication speeds. When a signal transitions from LOW to HIGH, the capacitance of the signal line is charged via the pull-up resistor, causing the voltage to rise. If a large resistance value is used for the pull-up, the current at this time becomes smaller, and it takes longer for the signal to rise (voltage to rise).
There is a method for calculating the value of the pull-up resistor. Details are provided in Section 7 of the I²C Specification [English version (rev7)] [Japanese version (rev5)] . Generally, when using I²C fast mode (400kHz) with a pull-up voltage of 3.3V, a pull-up resistance of around 1kΩ to 8kΩ can be used without any problems [Figure 1].
Figure 1: Pull-up resistor values for I²C signal lines
2. The target doesn't respond (꒪⌓꒪)
No ACK returned!😭
I connected the microcontroller to the target, added a pull-up resistor, and checked the signal's HIGH level with an oscilloscope, but the target still did not respond .
"Target not responding" means that no ACK is returned after the target address is sent.
This is common in the early stages of evaluation. Many targets allow you to change the target address depending on their settings (for example, by connecting the address setting pin to power or GND), so you need to double-check which address is set.
Also, even if you think you've set the address correctly, you need to check whether the address written in hexadecimal on the datasheet is a 7-bit representation (right-justified) or an 8-bit representation (left-justified). Furthermore, the microcontroller development tool (SDK) you're using may specify hexadecimal addresses in 7-bit representation (such as MicroPython) or 8-bit representation (such as Arm Mbed).💦
The I²C specification does not use either representation, and addresses are standardized to binary representation, so there is no such misunderstanding, but you should be careful when specifying them in hexadecimal.
How to check
How can you specify the target address? Check this in the device specifications and development tools. Then double-check that the device address is set as intended.
When checking on an actual device, for example in MicroPython the I2C class has a scan() method which displays a list of devices connected to the bus that are returning ACKs. One technique is to use this kind of function to quickly see what the settings are [Figure 2]. If the SDK you are using does not have a function like I2C::scan(), try sending addresses in order and checking for ACK/NACK.
Figure 2: Testing I2C.scan()
3. Repeat starts were necessary/unavailable
Even if I communicate according to the target device specifications, I can't read the data?
The I²C specification defines the signal levels and protocols in detail. Writes and reads can be performed in a defined manner on any target device. However , the method for accessing the registers and data buffers within that target is determined by the specifications of each device. For target devices with multiple internal registers, it is generally possible to specify and read/write registers using communications such as those shown in Figure 3. However, even if communications are performed in this manner, there are cases where the expected data is not read.
Repeat Start Condition
When executing a write transaction to specify a register address and a read transaction to read the register consecutively, a repeated start condition is often used to start the second transaction.
The repeated start condition is used to avoid the bus-free state that occurs after a stop condition before generating the next start condition. From the target device's perspective, using a repeated start condition is usually equivalent to using a stop and start condition.
However, there are devices that do not do this, and for such devices you must use one of the two methods to read the registers.
Some microcontroller SDKs provide an API for reading registers on I²C targets, which automatically handles access with a repeated start condition, but some microcontrollers do not support inserting a stop condition. In such cases, the API cannot be used as is, and it becomes necessary to handle the protocol at a lower level.
It is important to be careful as devices and microcontroller SDKs can have "specification pitfalls" like this that you only notice later.
Figure 3: Typical register access
4. Controllers that do not support clock stretching
The behavior is strange!
I²C has an optional function called " clock stretching ." Even nowadays, there are rare devices that have this function. The general I²C controllers installed in many microcontrollers support this clock stretching function, so you don't have to worry about it too much, but if you are implementing your own controller, you need to be aware of this optional function.
What is clock stretching?
I²C transmits and receives data according to the timing of the clock output by the controller. However, clock stretching is an option that allows the target side to make the controller wait [Figure 4]. The controller also outputs the clock via open drain. The controller monitors its own clock output and checks whether the signal is HIGH when it outputs HIGH. If the target side wants to make the controller wait, it holds this clock signal LOW. The controller knows it is being made to wait when the clock, which should be HIGH, turns LOW.
If the controller ignores this target behavior, it may cause communication problems such as fewer clocks being output.
Figure 4: Clock stretching
5. Multi-Controller
Also for debugging a running target device
Multi-controller is also an optional feature of I²C. Multiple controllers can control communication on the same bus without affecting each other's communication.
There aren't many applications that use it
There are not many cases where multiple controllers are used, except for a few applications. However, the I²C controllers built into many microcontrollers have this function.
Using this function, for example, if there is a problem with a running system, you can connect another microcontroller to the I²C bus and read or overwrite the contents of each target's register settings to verify them [Figure 5]. Normal debugging involves checking the code you have written, so you probably won't have an opportunity to do this, but it may be useful when verifying an unknown system for which the source code is unavailable.
Figure 5: Multi-master debugging
6. Clock frequency is lower
I thought I had set it to a 100kHz clock.
There aren't many cases where the I²C bandwidth is used to its full potential. However, what if you find that communication is occurring at a clock frequency that is significantly different from the speed you intended? Clock stretching, which was introduced in the previous section, is related to frequency reduction .
Below is an example at 100kHz, but the higher the frequency used, the greater this effect (rate of frequency reduction).
Check the waveform and adjust the frequency
Clock stretching is a function that makes the controller wait. However, it does not only affect the target. As the signal line length increases and the number of connected devices increases, the capacitance of the bus increases. In this case, if a large resistor is used for pull-up, the rise of the signal will be slowed down.
A slow signal rise time increases the time it takes for the clock to go high. After the clock goes high, the controller operates to ensure the set high hold time, resulting in a longer low-to-high transition time, which extends the low period. This causes a drop in the clock frequency [Figure 6].
Depending on the controller, you may be able to set the clock frequency in detail, or the LOW and HIGH periods of the clock. If you are concerned about the frequency, check the waveform and adjust the clock settings.
7. Long-distance routing. Noise and crosstalk can cause communication problems.
Data errors caused by waveform distortion
I²C is an easy-to-use two-wire serial bus. Because it is a slow signal, it will operate stably even if the signal line is extended to a distance of a few tens of centimeters (although this depends on the environment). However, if you are not careful and consider the characteristics of I²C, you may experience unexpected behavior.
High impedance, two wires
Because I²C is an open-drain signal, when a HIGH level is output, the impedance of the signal line is high. With a push-pull signal, if the device outputting the signal is LOW it is close to short-circuiting to GND, and if it is HIGH it is close to short-circuiting to the power supply, but with I²C it is connected to the power supply via a pull-up resistor. If noise is picked up on the signal line here, the noise current will escape to the power supply via the resistor. In addition, the currents of each I²C signal line also affect each other, which causes crosstalk.
To reduce noise and crosstalk, careful wiring is required. For example, GND or power supply wiring should be placed between the data and clock signals [Figure 7].
Alternatively, using a bus buffer is effective when transmitting over long distances via cable. However, because I²C is a bidirectional open-drain signal, standard logic buffers cannot be used as is. Various buffers are available for I²C, including those with signal voltage conversion functions and those that convert single-ended I²C to differential signals. By combining these, it is possible to create a stable and reliable system even when signal lines are run long distances.
Figure 7: Crosstalk and noise
8. Measuring Bus Capacitance
Bus capacity limit... But how do you measure it?
Up to 400kHz, I²C can communicate with a bus capacitance of up to 400pF. For 1MHz, I²C can communicate with a bus capacitance of up to 550pF. But how can we know this bus capacitance?
Calculate backward from the signal waveform
This blog post introduces several topics related to bus capacitance, all of which point out that the rise time of signals increases. Bus capacitance can be determined from this rise time.
[Figure 8] shows an example waveform. For an I²C signal pulled up to a 5V power supply with 2.2kΩ, the rise time (T) from the LOW reference voltage V OL = 1.5V to the HIGH reference voltage V OH = 3.5V is 154ns.
The formula in section 7.1 of the I²C specification [English version (rev7)] [Japanese version (rev5)] is "T = 0.8473 x RC," so if we apply "C = T / (0.8473 x R)," we get approximately 82pF. Subtracting the capacitance of the probe used for measurement (15pF), we get approximately 67pF.
Figure 8: Calculating bus capacitance
9. SDA Line Stuck and Bus Clear
SDA stuck at LOW and stopped working
The controller and target communicate with each other based on a clock. If the number of clocks becomes inconsistent due to noise or other reasons, not only will the communication be bit-shifted, but the situation will become known as "bus stuck." Figure 9-a shows an example in which the controller thinks it has sent nine clock pulses and finished communication, but the target is still returning an ACK as the last bit.
Getting out of a stuck bus situation
There are two ways to get out of this state. One is to reset the target. The other is to clear the bus. Bus clearing is described in the I²C specification [English version (rev7)] [Japanese version (rev5)] (Section 3.1.16).
If SDA is stuck LOW, you can return the target state to normal by generating nine clock pulses. [Figure 9-b] shows an example where an ACK was issued at the end of a read transfer due to a programming error on the microcontroller side. The MSB of the next data to be read happened to be 0, so SDA was fixed LOW.
To get out of this situation, we issue a clock nine times and clear the bus, after which we can see that the target has returned to normal.
In addition, the System Management Bus (SMBus), which uses I²C as its specification, has a timeout function on top of the normal I²C specification, and is specified to automatically return to normal operation after a maximum of 35 ms has elapsed on the target device.
The I²C specification does not have such a timeout provision, so once a stuck state occurs, it cannot be recovered from without resetting or clearing the bus.
Figure 9-a: Example of a bus stuck
Figure 9-b: Bus Clear
10. Who is sending the signal? Series resistor
Who is keeping the signal low?
When looking at the bus status of the bus stack mentioned above or a multi-controller system, you may want to know which device is sending the signal. The voltage when a LOW signal is output varies depending on the drive capacity of each device, and this can tell you which device is sending the signal.
Add a series resistor and check the voltage
[Figure 10] is an example of a multi-controller waveform. This waveform shows two controllers attempting to start communication at the same time, with clock synchronization and arbitration taking place. One controller (microcontroller 1) is attempting to start communication at 400 kHz, and the other controller (microcontroller 0) is attempting to start communication at 100 kHz, each driving the SCL signal.
Looking at the clock waveform, we can see that the terminal of the 100kHz controller is connected to the bus via a 100Ω resistor, so when microcontroller 0 outputs a LOW, this series resistor limits its ability to draw current, causing the LOW voltage to rise slightly. By using this mechanism, we can determine which device output a LOW.
Figure 10: Who is signaling?
11. Reference materials
I2C Bus Specification and User Manual (Rev5.0 Japanese version)
I2C Bus Specification and User Manual (Rev7.0 English version)
Interface March 2024 issue (CQ Publishing) : Special feature "Serial communication from scratch [UART/I2C/SPI with Pico]"
Transistor Technology Special No.161 "Measure, Measure, Measure Circuit & Technique Collection" Appendix: "Detailed Explanation of 2-wire Serial Interface I²C" - The above magazine article is an excerpt from this article.
NXP Community Blog: An Overview of the I²C Bus
[Originally published in Interface, March 2024 issue (CQ Publishing), " UART, I²C, SPI, CAN... Problems that can occur with various standards " pp. 101-115. The I²C-related section has been excerpted and revised for this blog post .]
Change history: 2025-02-04: First Edition 2025-08-14: Corrected a typographical error in the section "3. Repeat Start was necessary/unavailable." Added a line break to the text of the section "7. Long-distance routing. Communication becomes erratic due to noise and crosstalk." 2026-01-02: Added an introductory section before the table of contents / Added a YouTube video link to the section about MicroPython. 2026-04-14: Fixed broken links. Improved readability.
=========================
We are currently unable to respond to comments in the "Comment" section of this post. We apologize for the inconvenience, but when making inquiries, please refer to `` Technical Questions to NXP - How to Contact Us( Japanese Blog) ''. (If you are already an NXP distributor or have a relationship with NXP, you may ask the person in charge directly.)
I²C is used as a serial interface between chips. It is so commonplace that it is used in so many systems that no problems arise.
However, sometimes even small things can get you hooked.
Here we will introduce some common I²C problems and some easy debugging methods. Interface Japanese blog
查看全文