1. Detailed Explanation of I2C Communication Principles
1. Hardware Structure and Physical Layer
Bus Topology:
The I2C bus is a multi-master/slave structure that supports multiple master and slave devices sharing the bus.
SCL (Clock Line) and SDA (Data Line) are both open-drain outputs and require external pull-up resistors (typical value: 4.7kΩ, specific values should be adjusted based on bus capacitance).
When the bus is idle, SCL and SDA are both at a high level.
Levels and Speeds:
Standard Mode (Standard Mode):100kHz, maximum bus capacitance 400pF.
Fast Mode (Fast Mode):400kHz, maximum bus capacitance 200pF.
High-Speed Mode (High-Speed Mode):3.4MHz (both master and slave devices must support this).
Signal Integrity:
For long-distance communication, signal reflection and interference must be considered. The pull-up resistor value can be reduced, or an I2C buffer (such as PCA9615) can be used.
2. Protocol Timing Details
Start Condition (START):
When SCL is high, SDA transitions from high to low.
(https://img-blog.csdnimg.cn/20210519150818168.png)
Stop Condition (STOP):
When SCL is high, SDA transitions from low to high.
(https://img-blog.csdnimg.cn/20210519150834724.png)
Data Transmission Rules:
Data Validity: SDA must remain stable during the high level of SCL and can only change when SCL is low.
ACK/NACK Mechanism: After transmitting 8 bits of data, the receiver pulls down SDA on the 9th clock cycle (ACK) or keeps it high (NACK).
If the master device does not receive an ACK, it must trigger a retransmission or terminate communication.
7-bit Address Format:
Slave Address (7 bits) + Read/Write Bit (0: Master writes, 1: Master reads).
Example:SHT30 default address is 0x44, write operation address is `0x44 << 1 | 0 = 0x88`, read operation is `0x44 << 1 | 1 = 0x89`.
2. Deep Configuration of SHT30 Sensor
1. Pin Definitions for Sensor and Hardware Connections:
| Pin | Function | Connection Description |
| VDD | Power | 3.3V (range 2.4V-5.5V) |
| GND | Ground | Connect to Ground |
| SDA | Data Line | Connect to MCU SDA, pull up to VDD |
| SCL | Clock Line | Connect to MCU SCL, pull up to VDD |
| ADDR | Address Selection | Connect to Ground (0x44) or connect to VDD (0x45). |
Hardware Design Considerations:
Power supply should include a 0.1μF ceramic capacitor for filtering to reduce noise.
Avoid long traces for SDA/SCL to reduce electromagnetic interference (EMI).
2. Common Commands in Sensor Command Set:
| Command | Command Code (MSB, LSB) | Function |
| Trigger Measurement (High Precision) | 0x2C, 0x06 | Start a single measurement, enable clock stretching |
| Soft Reset | 0x30, 0xA2 | Reset the sensor |
| Read Status Register | 0xF3, 0x2D | Get sensor status information |
Clock Stretching:
The SHT30 may pull down SCL during measurement, and the master device must detect and wait for its release.
3. Data Format and CRC Check for Raw Data Parsing:
Measurement data consists of 6 bytes: `[Temp_H, Temp_L, Temp_CRC, Humi_H, Humi_L, Humi_CRC]`.
Temperature and humidity are both 16-bit unsigned integers (big-endian format).
CRC8 Check Algorithm:
Polynomial: `x^8 + x^5 + x^4 + 1` (0x31).
Initial Value: 0xFF.
Example Code:
uint8_t crc8(uint8_t *data, uint8_t len) {
uint8_t crc = 0xFF;
for (uint8_t i = 0; i < len; i++) {
crc ^= data[i];
for (uint8_t bit = 0; bit < 8; bit++) {
if (crc & 0x80) {
crc = (crc << 1) ^ 0x31;
} else {
crc <<= 1;
}
}
return crc;
}
3. STM32 Programming Implementation (Deep Optimization of HAL Library)
1. I2C Initialization (Key Parameters in CubeMX Configuration):
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 100000; // 100kHz
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; // Tlow/Thigh = 2 (Standard Mode)
hi2c1.Init.OwnAddress1 = 0; // Master device does not need an address
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; // Allow clock stretching
HAL_I2C_Init(&hi2c1);
2. Complete Communication Process (Including Timeout and Error Handling) Trigger Measurement:
uint8_t cmd[2] = {0x2C, 0x06}; // High Precision Measurement Command
HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(&hi2c1, 0x88, cmd, 2, 100);
if (status != HAL_OK) {
// Error Handling: Retry or Report Error
Error_Handler();
}
Wait for Measurement Completion:
Method 1 (Blocking Wait): Delay 6ms (SHT30 typical measurement time).
Method 2 (Clock Stretching Detection): MCU must support clock stretching, HAL library handles it automatically.
Read Data:
uint8_t data[6];
status = HAL_I2C_Master_Receive(&hi2c1, 0x89, data, 6, 100);
if (status != HAL_OK) {
// Error Handling
}
Data Verification and Conversion:
// Verify Temperature Data CRC
if (crc8(data, 2) != data[2]) {
// CRC Error Handling
}
// Temperature Conversion
uint16_t raw_temp = (data[0] << 8) | data[1];
float temperature =45.0f + 175.0f * (raw_temp / 65535.0f);
// Humidity Conversion (similarly)
3. Interrupt and DMA Optimization in Interrupt Mode:
// Start Non-blocking Transmission
HAL_I2C_Master_Transmit_IT(&hi2c1, 0x88, cmd, 2);
// Handle Completion Event in Callback Function
void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *hi2c) {
// Trigger Data Read
}
DMA Mode:
// Configure DMA Channel (enable I2C TX/RX DMA in CubeMX)
HAL_I2C_Master_Transmit_DMA(&hi2c1, 0x88, cmd, 2);
// Handle Subsequent Logic in DMA Completion Interrupt
4. Debugging and Troubleshooting
1. Hardware Debugging Tools Logic Analyzer (Saleae/PulseView):
Capture I2C waveforms, verify start/stop conditions, addresses, data, and ACK.
Check if the SCL frequency meets expectations (e.g., 100kHz).
Oscilloscope:
Observe SDA/SCL signal quality, ensuring no overshoot or ringing.
2. Common Issues and Solutions
| Problem Phenomenon | Possible Cause | Solution |
| Sensor Not Responding | Incorrect Address/Power Not Connected | Check I2C address, measure VDD voltage |
| DataCRC Check Failed | Bus Interference/Timing Instability | Reduce Communication Speed, Shorten Traces |
| Communication Timeout | Slave Device Did Not ReleaseSCL (Clock Stretching) | Enable `NoStretchMode` or Increase Timeout |
| Temperature/Humidity Values Abnormal | Data Processing Formula Error | Check Raw Data Conversion Formula |
3. Code Debugging Tips Add Debug Prints:
printf(“Raw Temp: 0x%04X, Calc: %.2f°C\n”, raw_temp, temperature);
HAL Library Error Code Analysis:
if (status == HAL_ERROR) {
uint32_t error = HAL_I2C_GetError(&hi2c1);
if (error & HAL_I2C_ERROR_AF) {
// ACK Failure
}
}
5. Extended Applications Multi-Sensor Shared Bus:
Assign a unique address for each sensor (e.g., SHT30 can set the ADDR pin to switch between 0x44/0x45).
Use an I2C multiplexer (such as TCA9548A) to extend the bus.
Low Power Design:
Turn off the sensor power during non-measurement periods (controlled by a MOS transistor for VDD).
Use I2C wake-up commands (such as SHT30‘s 0x2C06 supports low power mode).
Summary: By refining the I2C protocol details, sensor configuration, code optimization, and debugging techniques, the stability and accuracy of temperature and humidity data collection can be significantly improved. In practical development, it is necessary to combine hardware design with software fault tolerance mechanisms to ensure reliability in complex environments.