How to Read Data from I2C Device in Embedded C
To read data from an
I2C device in embedded C, you first send a start condition, then the device address with the read bit, followed by reading the data bytes and finally sending a stop condition. Use your microcontroller's I2C peripheral functions or registers to perform these steps in sequence.Syntax
The basic steps to read data from an I2C device in embedded C are:
- Start Condition: Begin communication on the I2C bus.
- Send Device Address: Send the 7-bit device address with the read bit set.
- Read Data: Read the required number of bytes from the device.
- Stop Condition: End communication on the I2C bus.
These steps are usually done by calling functions or manipulating registers provided by your microcontroller's I2C hardware.
c
i2c_start(); i2c_send_address(device_address << 1 | 0x01); // Read bit set uint8_t data = i2c_read_byte(); i2c_stop();
Example
This example shows how to read one byte from an I2C device at address 0x50 using simple functions that control the I2C bus.
c
#include <stdint.h> #include <stdio.h> // Mock functions to simulate I2C operations void i2c_start() { // Send start condition printf("Start condition sent\n"); } void i2c_stop() { // Send stop condition printf("Stop condition sent\n"); } void i2c_send_address(uint8_t address) { // Send device address with R/W bit printf("Address 0x%02X sent\n", address); } uint8_t i2c_read_byte() { // Read one byte from device uint8_t dummy_data = 0xAB; // Example data printf("Read byte: 0x%02X\n", dummy_data); return dummy_data; } int main() { uint8_t device_address = 0x50; // 7-bit address uint8_t data; i2c_start(); i2c_send_address(device_address << 1 | 0x01); // Read bit set data = i2c_read_byte(); i2c_stop(); printf("Data received from device: 0x%02X\n", data); return 0; }
Output
Start condition sent
Address 0xA1 sent
Read byte: 0xAB
Stop condition sent
Data received from device: 0xAB
Common Pitfalls
Common mistakes when reading from I2C devices include:
- Not sending the correct device address with the read bit set (least significant bit = 1).
- Forgetting to send a stop condition after reading data, which can hang the bus.
- Not acknowledging (ACK) bytes properly when reading multiple bytes.
- Ignoring bus errors or not checking status flags from the I2C peripheral.
Always consult your microcontroller's datasheet for correct register usage and timing.
c
/* Wrong: Sending write bit instead of read bit */ i2c_send_address(device_address << 1 | 0x00); // Incorrect for read /* Correct: Read bit set */ i2c_send_address(device_address << 1 | 0x01); // Correct for read
Quick Reference
| Step | Description |
|---|---|
| Start Condition | Begin I2C communication on the bus |
| Send Address + Read Bit | Send 7-bit device address with LSB=1 for read |
| Read Data Byte(s) | Read one or more bytes from the device |
| Send ACK/NACK | Acknowledge each byte except last (NACK) |
| Stop Condition | End communication to release the bus |
Key Takeaways
Always send the device address with the read bit (LSB = 1) when reading.
Start and stop conditions are essential to control the I2C bus properly.
Acknowledge bytes correctly when reading multiple bytes to avoid bus errors.
Check your microcontroller's I2C peripheral documentation for exact register usage.
Common errors include wrong address bits and missing stop conditions.