What if you could talk to many devices on one wire without ever mixing up who's listening?
Why I2C addressing (7-bit and 10-bit) in Embedded C? - Purpose & Use Cases
Imagine you have many devices connected on a single wire bus, and you need to talk to each one separately. Without a clear way to identify each device, you might try to send commands blindly or one by one, hoping the right device listens.
Manually managing device communication without proper addressing is slow and confusing. You risk sending data to the wrong device or missing devices entirely. It's like shouting in a crowded room without knowing who should answer--lots of noise, no clear response.
I2C addressing gives each device a unique ID using 7-bit or 10-bit addresses. This way, the master device can call out to exactly one device at a time, making communication clear and organized on the shared bus.
send_data_to_all_devices(); // no addressing, guess who listens
send_data_to_device(address, data); // clear 7-bit or 10-bit address
It allows precise, reliable communication with multiple devices on the same bus without confusion or errors.
Think of a smart home system where sensors and lights share one wire. Using I2C addressing, the controller can turn on just the kitchen light or read temperature from the living room sensor without mixing commands.
I2C addressing uniquely identifies devices on a shared bus.
7-bit and 10-bit addresses let you connect many devices without confusion.
This makes communication faster, clearer, and less error-prone.
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
