I2C Protocol Application: Sensor Interface and Data Reading

I2C Protocol Application: Sensor Interface and Data Reading

I2C Protocol Application: Sensor Interface and Data Reading

Hello everyone, I am Daodao. Today, let’s talk about the I2C protocol, which many sensors use to communicate with microcontrollers. Although it only uses two wires, it can connect multiple devices, making it a master of saving wires. However, if not used correctly, it can easily get stuck on data reading. Today, I will explain it from a practical perspective.

What is I2C?

In simple terms, I2C is like a small alley where many “residents” (I2C devices) live. The alley has only two paths:

  • SCL: Equivalent to a traffic police officer’s gesture, controlling the communication rhythm.

  • SDA: The path for information transmission between devices.

Special Reminder: Both of these wires need pull-up resistors; otherwise, the signal will float. I have encountered many beginners who forget to add pull-ups to the signal line, leading to incorrect data readings, and it takes a long time to discover this issue.

Hardware Connection Details

         VCC

          |

         [Pull-up Resistor]

          |

MCU --- SCL ---- Sensor 1 ---- Sensor 2

         |

         [Pull-up Resistor]

          |

MCU --- SDA ---- Sensor 1 ---- Sensor 2

Several easily overlooked wiring details:

  1. Pull-up Resistor Value is generally chosen between 2.2K and 10K; too high causes slow signal rise, too low increases power consumption.

  2. Connecting too many devices on the bus increases load capacitance, affecting communication speed.

  3. Keep connection wires short; otherwise, they are prone to interference.

Code Implementation

// I2C Initialization Configuration

void I2C_Init(void)
{
    // Configure GPIO as open-drain output mode
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT_OD;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    // Idle state, both pulled high
    I2C_SCL_HIGH();
    I2C_SDA_HIGH();
}

// Send Start Signal
void I2C_Start(void)
{
    SDA_OUT();     // Set SDA as output
    I2C_SDA_HIGH();
    I2C_SCL_HIGH();
    delay_us(4);   // Suggested delay of more than 4us
    I2C_SDA_LOW(); // When SCL is high, SDA falling edge = start signal
    delay_us(4);
    I2C_SCL_LOW(); // Hold I2C bus, prepare to send data
}

// Send Stop Signal
void I2C_Stop(void)
{
    SDA_OUT();
    I2C_SCL_LOW();
    I2C_SDA_LOW();
    delay_us(4);
    I2C_SCL_HIGH();
    I2C_SDA_HIGH(); // When SCL is high, SDA rising edge = stop signal
    delay_us(4);
}

Practical Case: Reading Temperature and Humidity Sensor

Taking the SHT20 sensor as an example, its address is 0x40, and the data reading process is as follows:

uint8_t ReadTemperature(void)
{
    uint8_t temp[2];
    I2C_Start();
    I2C_Send_Byte(0x40 << 1 | 0x00);  // Write device address
    I2C_Wait_Ack();
    I2C_Send_Byte(0xF3);              // Send command to measure temperature
    I2C_Wait_Ack();
    delay_ms(85);                      // Wait for measurement to complete
    I2C_Start();
    I2C_Send_Byte(0x40 << 1 | 0x01);  // Read device address
    I2C_Wait_Ack();
    temp[0] = I2C_Read_Byte(1);       // Read high byte
    temp[1] = I2C_Read_Byte(0);       // Read low byte
    I2C_Stop();
    return Calculate_Temperature(temp); // Convert to actual temperature value
}

Pitfalls and Solutions

  1. Communication Failure
  • Symptoms: Always unable to read data or data is incorrect.

  • Solution: First, use an oscilloscope to check the waveforms of SCL and SDA; most issues can be seen in the waveforms.

  • Common Causes: Pull-up resistor not connected, timing incorrect, ground line not connected properly.

  1. Data Occasionally Incorrect
  • Possible cause: Large power ripple; add a 100nF bypass capacitor.

  • During wiring, keep signal lines away from strong electricity and switching power supplies.

  1. The Same Code Doesn’t Work with a Different Sensor
  • Each sensor may have different timing requirements.

  • Carefully check the timing diagrams in the manufacturer’s manual, especially setup time and hold time.

Recommended Debugging Tools

  1. Oscilloscope: The most intuitive way to observe waveforms.

  2. Logic Analyzer: Can analyze I2C protocol and directly see data content.

  3. I2C Debugging Tool: Can simulate master or slave, convenient for testing a specific device.

Practical Suggestions

Hardware Aspects:

  • Reserve I2C interface on the PCB for easy expansion.

  • Use twisted pair for signal lines for better interference resistance.

  • Reserve pull-up resistor positions for easy testing with different values.

Software Aspects:

  • Write a simple I2C test program to verify hardware functionality.

  • Add a timeout mechanism to prevent the program from running away.

  • Add checksums for important data.

Safety Reminder: Be cautious with power supply voltage when debugging; do not connect the power supply incorrectly to avoid damaging components.

Practical Exercises:

  1. Use an oscilloscope to observe the start and stop signal waveforms of I2C.

  2. Try reading devices with different I2C addresses.

  3. Test the impact of different pull-up resistors on communication.

Leave a Comment