0
0
Embedded Cprogramming~20 mins

Reading data from I2C device in Embedded C - Practice Problems & Coding Challenges

Choose your learning style9 modes available
Challenge - 5 Problems
🎖️
I2C Reading Master
Get all challenges correct to earn this badge!
Test your skills under time pressure!
Predict Output
intermediate
2:00remaining
What is the output of this I2C read function?

Consider this embedded C function that reads a byte from an I2C device register. What value does data hold after calling read_i2c_register(0x50, 0x10) if the device returns 0xAB at register 0x10?

Embedded C
uint8_t read_i2c_register(uint8_t device_addr, uint8_t reg_addr) {
    uint8_t data = 0;
    i2c_start();
    i2c_write(device_addr << 1); // Write mode
    i2c_write(reg_addr);
    i2c_start();
    i2c_write((device_addr << 1) | 1); // Read mode
    data = i2c_read_nack();
    i2c_stop();
    return data;
}

uint8_t data = read_i2c_register(0x50, 0x10);
A0x10
B0x00
C0xAB
D0x50
Attempts:
2 left
💡 Hint

Remember that the function reads the byte from the device register after sending the register address.

🧠 Conceptual
intermediate
1:30remaining
Which step is missing in this I2C read sequence?

This code snippet tries to read a byte from an I2C device but misses a critical step. Which step is missing?

Embedded C
i2c_start();
i2c_write(device_addr << 1); // Write mode
// Missing step here
i2c_start();
i2c_write((device_addr << 1) | 1); // Read mode
uint8_t data = i2c_read_nack();
i2c_stop();
ASending a stop condition before restart
BWriting the register address to read from
CReading with ACK instead of NACK
DDelaying between start and write
Attempts:
2 left
💡 Hint

Think about how the device knows which register you want to read.

🔧 Debug
advanced
2:30remaining
Why does this I2C read code cause a bus hang?

This code snippet causes the I2C bus to hang during reading. Identify the cause.

Embedded C
i2c_start();
i2c_write(device_addr << 1); // Write mode
i2c_write(reg_addr);
i2c_start();
i2c_write((device_addr << 1) | 1); // Read mode
uint8_t data = i2c_read_ack();
i2c_stop();
ANot shifting device address by 1 bit
BMissing <code>i2c_stop()</code> after first write
CNot sending register address before restart
DUsing <code>i2c_read_ack()</code> instead of <code>i2c_read_nack()</code> for the last byte
Attempts:
2 left
💡 Hint

Think about how the master signals the end of reading bytes.

📝 Syntax
advanced
1:30remaining
Which option fixes the syntax error in this I2C read code?

Identify the option that fixes the syntax error in this code snippet.

Embedded C
uint8_t read_byte(uint8_t device_addr, uint8_t reg_addr) {
    uint8_t data;
    i2c_start();
    i2c_write(device_addr << 1);
    i2c_write(reg_addr);
    i2c_start();
    i2c_write((device_addr << 1) | 1);
    data = i2c_read_nack();
    i2c_stop();
    return data;
}
AAdd semicolon after <code>i2c_start()</code> on line 3
BChange <code>i2c_write(device_addr << 1)</code> to <code>i2c_write(device_addr >> 1)</code>
CDeclare <code>data</code> as <code>int</code> instead of <code>uint8_t</code>
DRemove <code>return data;</code> line
Attempts:
2 left
💡 Hint

Look carefully at the line endings for missing punctuation.

🚀 Application
expert
3:00remaining
How many bytes are read by this I2C multi-byte read function?

This function reads multiple bytes from an I2C device starting at a register. How many bytes does it read?

Embedded C
void read_i2c_bytes(uint8_t device_addr, uint8_t start_reg, uint8_t *buffer, uint8_t length) {
    i2c_start();
    i2c_write(device_addr << 1); // Write mode
    i2c_write(start_reg);
    i2c_start();
    i2c_write((device_addr << 1) | 1); // Read mode
    for (uint8_t i = 0; i < length; i++) {
        if (i < length - 1) {
            buffer[i] = i2c_read_ack();
        } else {
            buffer[i] = i2c_read_nack();
        }
    }
    i2c_stop();
}

uint8_t data_buffer[5];
read_i2c_bytes(0x50, 0x20, data_buffer, 5);
A5 bytes
B4 bytes
C6 bytes
D1 byte
Attempts:
2 left
💡 Hint

Check the loop and the length parameter passed.