This article provides guidance on troubleshooting common I2C issues.
Issue #1: No START Condition Generated
The PIC® microcontroller operating as an I2C master generates a start condition to begin an I2C data transfer. If no start condition is generated then there is something wrong with the setup.
- Check that the I2C pins (SDA and SCL) are set as digital inputs. By default, the pins might have an analog function and need to be configured for digital mode. The pins might also have been mistakingly configured as outputs in the source code. For more information on configuring pins refer to this article: http://microchipdeveloper.com/8bit:emr-digital-io
- The I2C bus must be in an idle state for the I2C peripheral to be able to generate a start condition. This means both the SDA and SCL lines must be in the high state. View the pin signals on an oscilloscope to verify they are in this state when the PIC attempts to generate the start condition. If the I2C lines are not in the idle high state, it could be that something on the bus is pulling the pin(s) low, or the required pull-up resistors are missing.
- The I2C peripheral must be in master mode to generate a start condition. Check the I2C Special Function Registers (SFR) to make sure the peripheral is set for I2C master mode.
Note: If the PIC microcontroller attempts to generate a start condition while the I2C bus is not ready, or the pins not configured correctly, this will cause a bus collision and the BCL or BCLIF bit will be set to '1' in the I2C related SFRs. Not all PIC microcontrollers have this bit, it depends on the device used.
Issue #2: No ACK Given For an I2C Address
An I2C slave will generate an Acknowledge (ACK) when it receives a valid I2C address byte from the master, otherwise, it will generate a Not Acknowledge (NACK).
- View the I2C signals on an oscilloscope to verify what address the master is sending. The datasheet of the I2C slave device will generally have an example waveform showing the I2C address, which can be compared to what is seen on the oscilloscope.
- If the PIC is the I2C slave which is not generating the ACK, run the code with a debugger and check the address register (typically labeled SSPADD or I2CADD), to see what value is present there. Since the address byte also contains the R/W bit at position 0, the address value may need to be shifted to account for that. Also, verify in the SFRs that the I2C peripheral is set for slave mode.
Issue #3: A Read or Write Operation is Not Working as Expected
In some situations an I2C master read or write operation might not be working, even though activity can be seen on the I2C bus and the I2C code is not blocking.
This type of scenario can happen when the program does not wait for an I2C operation to complete before executing the next operation. I2C operations (START, STOP, byte write etc.) are not queued. The program must be sure that the current operation completes before beginning the next operation otherwise, part of the I2C transaction can be missed. One way to do this is to check the I2C interrupt flag, which is set to '1' at the completion of each operation. By checking this flag the program can be sure the current I2C operation is complete.
Here are some suggestions on how to identify the problem.
- View the I2C signals on an oscilloscope to see what is happening on the bus. It may be that not all bytes are being sent on the bus or some part of the transaction is missing. An example of this is shown in Figures 1 and 2. Figure 1 shows bytes 0xA0, 0x12, 0x34, 0x56 on the bus. Figure 2 shows that byte 0x12 is missing. If some part of the I2C transaction is missing, then the full transfer will not succeed.
- Check the I2C error flags in the SFRs. Using a debugger such as MPLAB® ICD3, the SFR values can be checked in MPLAB X IDE. When something goes wrong in the I2C peripheral, there are some error flags to indicate where the problem occurred.
WCOL: Write Collision Detect bit
A write to the SSPBUF register was attempted while the I2C conditions were not valid for a transmission to be started.
SSPOV: Receive Overflow Indicator bit
A byte is received while the SSPBUF register is still holding the previous byte.
BCLIF: MSSP Bus Collision Interrupt Flag bit
A Bus Collision was detected.
- Use a spare I/O pin to indicate when events are happening in the program. Toggle the pin when the event occurs, and view this pin on the oscilloscope alongside the I2C signals. This will help to verify that the program is initiating I2C operations when it should.
Summary
- View the I2C pins on an oscilloscope to see what is happening.
- Check the I2C register (SFR) values to see if any error flags are set.
- Use a spare I/O pin to see when I2C events are happening.