Imagine you want to connect several sensors to a microcontroller using a communication protocol. Why is I2C often chosen for this task?
Think about how many wires are needed to connect many devices and how I2C handles addressing.
I2C uses just two wires (SDA and SCL) to connect multiple devices by assigning each a unique address. This reduces wiring complexity and saves microcontroller pins.
Both I2C and SPI are common communication protocols. What is a main advantage of I2C compared to SPI?
Consider how many wires each protocol uses and how devices are selected.
I2C uses only two wires and supports multiple devices with unique addresses, while SPI needs separate chip select lines for each device, increasing wiring complexity.
Consider this embedded C code snippet that scans for I2C devices on the bus and prints their addresses:
for (uint8_t addr = 1; addr < 128; addr++) { if (i2c_start(addr << 1 | I2C_WRITE)) { printf("Device found at 0x%02X\n", addr); i2c_stop(); } }
Look at how the address is shifted and printed.
The code shifts the 7-bit address left by 1 and adds the write bit, then tries to start communication. If successful, it prints the address in hex.
Analyze this embedded C code snippet for I2C initialization:
void i2c_init() {
TWBR = 0x48; // Set bit rate
TWSR = 0x02; // Set prescaler bits
TWCR = (1 << TWEN); // Enable TWI
TWDR = 0xFF; // Load data register
}Consider the purpose of TWDR during initialization.
TWDR is the data register used during data transmission, not during initialization. Setting it here is a logical mistake but not a syntax error.
In I2C communication, the data (SDA) and clock (SCL) lines are open-drain or open-collector. Why is this design used?
Think about how multiple devices communicate on the same wire safely.
Open-drain/open-collector lines allow devices to pull the line low but never drive it high directly. A pull-up resistor brings the line high when no device pulls it low. This prevents conflicts and damage when multiple devices share the bus.