I2C addressing (7-bit and 10-bit) in Embedded C - Time & Space Complexity
When working with I2C communication, it's important to understand how addressing affects the time it takes to send data.
We want to see how the number of bits in the address changes the work the microcontroller does.
Analyze the time complexity of the following code snippet.
// Send I2C address (7-bit or 10-bit)
void i2c_send_address(uint16_t address, bool is_10bit) {
if (is_10bit) {
// Send 10-bit prefix + high bits (11110 A9 A8 0)
i2c_write(((address >> 7) & 0x06) | 0xF0);
// Send last 8 bits
i2c_write(address & 0xFF);
} else {
// Send 7-bit address
i2c_write(address << 1);
}
}
This code sends either a 7-bit or 10-bit I2C address by writing bytes to the bus.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Calls to
i2c_write()to send address bytes. - How many times: For 7-bit address, 1 call; for 10-bit address, 2 calls.
As the address size grows from 7 to 10 bits, the number of write operations increases slightly.
| Address Size (bits) | Write Calls |
|---|---|
| 7 | 1 |
| 10 | 2 |
| 14 (hypothetical) | 3 |
Pattern observation: Each additional 7 bits roughly adds one more write operation.
Time Complexity: O(1)
This means the time to send the address does not grow with input size in a way that depends on variable data; it stays constant.
[X] Wrong: "Sending a 10-bit address takes twice as long as a 7-bit address because it has more bits."
[OK] Correct: The code sends a fixed small number of bytes regardless of address size, so the time difference is small and constant, not proportional to the number of bits.
Understanding how fixed-size operations affect timing helps you explain device communication clearly and confidently.
"What if the I2C address size increased to 15 bits? How would the time complexity change?"
Practice
What is the size of the standard I2C address used to identify devices?
Solution
Step 1: Understand I2C addressing basics
I2C commonly uses 7-bit addresses to identify devices on the bus.Step 2: Recall standard address size
The standard I2C address size is 7 bits, while 10-bit is an extended mode.Final Answer:
7 bits -> Option AQuick Check:
Standard I2C address = 7 bits [OK]
- Confusing 7-bit with 8-bit addresses
- Thinking 10-bit is the default
- Assuming 16-bit addresses exist in I2C
Which of the following is the correct way to prepare a 7-bit I2C address for a write operation in embedded C?
uint8_t address = 0x3C; // 7-bit address
uint8_t write_address = ?;Solution
Step 1: Shift 7-bit address left by 1
The 7-bit address must be shifted left by 1 to make room for the read/write bit.Step 2: Set read/write bit for write operation
For write, the least significant bit is 0, so OR with 0.Final Answer:
write_address = (address << 1) | 0; -> Option DQuick Check:
Shift left 1 + write bit 0 = correct address [OK]
- Shifting right instead of left
- Setting read/write bit incorrectly
- Using wrong bitwise OR values
Given the following code snippet, what is the value of header for a 10-bit I2C address 0x305?
uint16_t addr = 0x305;
uint8_t header = 0xF0 | ((addr >> 7) & 0x06) | 0x00; // write operationSolution
Step 1: Analyze addr = 0x305
Binary 0b1100000101 (bits 9-0: bit9=1, bit8=1, bit7=0). Shift right 7: 0b110 (6).Step 2: Mask and compute header
(6 & 0x06) = 0x06. Then 0xF0 | 0x06 | 0x00 = 0xF6.Final Answer:
0xF6 -> Option AQuick Check:
0xF0 | ((0x305 >> 7) & 0x06) = 0xF6 [OK]
- Not shifting address before masking
- Incorrect mask value
- Confusing read/write bit in header
Identify the error in this code snippet for sending a 10-bit I2C address:
uint16_t addr = 0x3FF;
uint8_t header = 0xF0 | ((addr >> 7) & 0x06) | 0x01; // read operation
uint8_t low_addr = addr & 0xFF;
// send header and low_addr over I2CSolution
Step 1: Check read/write bit in header
For read operation, the last bit is set to 1, which matches the code.Step 2: Verify mask and low address
Mask 0x06 correctly extracts bits 7 and 8; low_addr is the lower 8 bits, no shift needed.Final Answer:
The header calculation is correct; no error -> Option CQuick Check:
Header and low_addr correct for 10-bit read [OK]
- Confusing read/write bit value
- Incorrect mask for bits 7 and 8
- Shifting low address unnecessarily
You need to write a function in embedded C that takes a 10-bit I2C address and returns the two bytes to send: the header byte and the low address byte for a write operation. Which of the following implementations is correct?
void get_i2c_10bit_bytes(uint16_t addr, uint8_t *header, uint8_t *low_addr) {
// ?
}Solution
Step 1: Use pointers to assign output values
The function parameters header and low_addr are pointers, so use * to assign values.Step 2: Calculate header and low_addr correctly
Header is 0xF0 ORed with bits 7 and 8 of addr shifted right 7, and OR 0 for write; low_addr is lower 8 bits.Final Answer:
*header = 0xF0 | ((addr >> 7) & 0x06) | 0x00; *low_addr = addr & 0xFF; -> Option BQuick Check:
Pointer dereference + correct bit ops = correct function [OK]
- Not using * to assign pointer values
- Shifting bits incorrectly
- Setting read/write bit wrong
Ready to prove it?
Pass the test and this pattern moves unknown
