Writing data to I2C device in Embedded C - Time & Space Complexity
When writing data to an I2C device, it's important to understand how the time taken grows as the amount of data increases.
We want to know how the number of bytes affects the total time spent sending data.
Analyze the time complexity of the following code snippet.
void i2c_write_data(uint8_t device_addr, uint8_t* data, uint16_t length) {
i2c_start();
i2c_send_byte(device_addr << 1); // Send device address with write bit
for (uint16_t i = 0; i < length; i++) {
i2c_send_byte(data[i]);
}
i2c_stop();
}
This code sends a start signal, writes the device address, then sends each byte of data one by one, and finally sends a stop signal.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Sending each byte of data inside the for-loop.
- How many times: The loop runs once for every byte in the data array, so
lengthtimes.
As the number of bytes to send grows, the total time grows in a straight line with it.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 send operations |
| 100 | About 100 send operations |
| 1000 | About 1000 send operations |
Pattern observation: Doubling the data doubles the number of send operations.
Time Complexity: O(n)
This means the time to write data grows directly in proportion to the number of bytes you send.
[X] Wrong: "Sending data to an I2C device takes the same time no matter how many bytes are sent."
[OK] Correct: Each byte requires a separate send operation, so more bytes mean more time.
Understanding how data size affects communication time helps you design efficient embedded systems and answer questions about performance in real projects.
"What if we buffered multiple bytes before sending them all at once? How would the time complexity change?"
Practice
Solution
Step 1: Begin communication with the device
Writing data to an I2C device always starts with initiating the communication by sending a start condition. After starting, the device address and data can be sent, but the first step must be the start condition.Final Answer:
Start the I2C communication -> Option BQuick Check:
Start communication = first step [OK]
- Sending data before starting communication
- Stopping communication too early
- Skipping the start condition
Solution
Step 1: Understand I2C address format
The 7-bit device address is shifted left by one bit to make room for the read/write bit as the least significant bit. For writing, the least significant bit must be 0, so OR with 0 is correct.Final Answer:
device_address << 1 | 0 -> Option AQuick Check:
Write bit = 0, address shifted left = correct [OK]
- Setting LSB to 1 for write operation
- Shifting address right instead of left
- Not shifting address at all
uint8_t device_addr = 0x50; uint8_t reg_addr = 0x10; uint8_t data = 0xAB; I2C_Start(); I2C_Write(device_addr << 1 | 0); I2C_Write(reg_addr); I2C_Write(data); I2C_Stop();
Solution
Step 1: Analyze the address and data sent
The device address is correctly shifted and write bit set to 0. Then register address 0x10 and data 0xAB are sent in order. The sequence Start -> Address+Write -> Register -> Data -> Stop is correct for writing data to a register.Final Answer:
Data 0xAB is written to register 0x10 of device 0x50 -> Option DQuick Check:
Correct sequence = data written properly [OK]
- Mixing register and data order
- Not shifting device address
- Forgetting to send stop condition
uint8_t device_addr = 0x68; uint8_t reg_addr = 0x20; uint8_t data = 0x55; I2C_Start(); I2C_Write(device_addr >> 1 | 0); I2C_Write(reg_addr); I2C_Write(data); I2C_Stop();
Solution
Step 1: Check device address shifting
The device address is incorrectly shifted right instead of left, which corrupts the address sent on the bus. Register and data are sent in correct order, and stop condition is present, so no other errors.Final Answer:
Device address is shifted right instead of left -> Option AQuick Check:
Address must be shifted left for I2C write [OK]
- Shifting address right instead of left
- Sending data before register address
- Omitting stop condition
uint8_t device_addr = 0x60;
uint8_t start_reg = 0x30;
uint8_t data[] = {0x01, 0x02, 0x03};
// Which snippet is correct?Solution
Step 1: Start communication and send device address with write bit
The device address is shifted left and write bit set to 0, then start register address is sent once. After sending the start register, consecutive data bytes are sent to consecutive registers automatically by the device.Final Answer:
Start register sent once, then data bytes sent in loop -> Option CQuick Check:
Send start reg once, then data bytes [OK]
- Sending register address before each data byte
- Using read bit instead of write bit
- Not sending start register at all
Ready to prove it?
Pass the test and this pattern moves unknown
