Mastering Embedded Core: MCU I2C Bus Protocol and Sensor Integration Guide

The I2C bus is one of the most commonly used communication protocols in embedded systems, serving as a “dedicated highway” between microcontrollers and various sensors and memory devices. Today, let’s discuss how this protocol works and how to use it to read data from temperature and humidity sensors.

I2C Protocol Basics

The I2C protocol uses two wires: SDA (data line) and SCL (clock line). You can think of it as a two-way road where SDA is used for data transmission and SCL controls the traffic lights.

Main features:

  • Master-slave communication: one master device (usually a microcontroller) and multiple slave devices (sensors, etc.)
  • Addressing: each slave device has a unique address
  • Bidirectional transmission: data can be read and written
  • Clock synchronization: all devices follow the rhythm of SCL

Hardware Connection

This is a typical I2C connection diagram:

   VCC
    |
    |
 ---|---
 |  |  |
 |  R  R   (Pull-up resistors, usually 4.7k)
 |  |  |
 |  |  |
SCL--|--|-- SCL (each device)
SDA--|--|-- SDA (each device)
    |  |
  Master Device  Slave Device 1, Slave Device 2...

Note: The I2C bus requires pull-up resistors! The first time I connected an I2C device, I forgot this detail, and as a result, communication failed. After struggling for a long time, I discovered this was the reason.

Software Implementation

Taking STM32 as an example, here is a simple program to read data from the SHT20 temperature and humidity sensor:

#include "stm32f10x.h"
#include "i2c.h"

#define SHT20_ADDR 0x40  // I2C address of SHT20
#define TEMP_CMD 0xF3    // Command to measure temperature
#define HUMI_CMD 0xF5    // Command to measure humidity

float readTemperature(void) {
    uint8_t data[2];
    uint16_t temp;
    float temperature;
    
    I2C_Start();
    I2C_Send7bitAddress(SHT20_ADDR, I2C_Direction_Transmitter);
    I2C_SendData(TEMP_CMD);
    I2C_Stop();
    
    delay_ms(100);  // Wait for measurement to complete
    
    I2C_Start();
    I2C_Send7bitAddress(SHT20_ADDR, I2C_Direction_Receiver);
    data[0] = I2C_ReceiveData(1);  // Receive high 8 bits
    data[1] = I2C_ReceiveData(0);  // Receive low 8 bits
    I2C_Stop();
    
    temp = (data[0] << 8) | data[1];
    temperature = -46.85 + 175.72 * (temp / 65536.0);
    
    return temperature;
}

This code does the following:

  1. Sends the command to measure temperature
  2. Waits for the sensor to complete the measurement
  3. Reads the measurement result
  4. Converts the raw data into the actual temperature value

Practical Application Case

In a smart home project, I used the SHT20 sensor to monitor indoor temperature and humidity, and controlled the air conditioning and humidifier based on the data. The code is roughly as follows:

void smartHomeControl(void) {
    float temp = readTemperature();
    float humi = readHumidity();
    
    if(temp > 28.0) {
        turnOnAC();
    } else if(temp < 22.0) {
        turnOffAC();
    }
    
    if(humi < 40.0) {
        turnOnHumidifier();
    } else if(humi > 60.0) {
        turnOffHumidifier();
    }
    
    // Check every 5 minutes
    delay_ms(300000);
}

Common Issues and Solutions

  1. Communication Failure

  • Check the wiring, especially the pull-up resistors
  • Confirm the slave device address is correct
  • Observe SCL and SDA signals with an oscilloscope
  • Abnormal Data

    • Check if the conversion formula is correct
    • Consider environmental factors, such as whether the sensor is affected by heat sources
  • Unstable Communication

    • It could be power noise; add a decoupling capacitor
    • Is the line too long? I2C is not suitable for long-distance transmission; consider using RS-485

    Once in a project, the sensor readings fluctuated wildly, and after much troubleshooting, I found it was installed near the air conditioning outlet. This reminds us that in practical applications, we must pay attention not only to the code and circuitry but also to the sensor’s installation position.

    Practical Recommendations

    Start by reading a single sensor, then try reading multiple I2C devices simultaneously. You can set up a simple weather station to monitor temperature, humidity, and pressure parameters. In practice, pay special attention to the timing requirements of I2C; using a logic analyzer to observe the communication process can be very helpful in understanding the protocol.

    While I2C is simple, it also has its limitations. In high-speed, long-distance, or complex environments, you may need to consider alternative communication methods.

    Leave a Comment