0
0
Embedded Cprogramming~5 mins

I2C addressing (7-bit and 10-bit) in Embedded C

Choose your learning style9 modes available
Introduction

I2C addressing lets devices on the same wire know who is talking. It uses 7-bit or 10-bit addresses to identify each device uniquely.

When connecting multiple sensors to a microcontroller using I2C.
When you need to communicate with a device that uses a 10-bit address.
When writing firmware to read or write data over I2C bus.
When debugging I2C communication to check device addresses.
Syntax
Embedded C
/* 7-bit address example */
#define DEVICE_ADDR_7BIT 0x3C

/* 10-bit address example */
#define DEVICE_ADDR_10BIT 0x1F3

/* Sending address on I2C bus */
// For 7-bit: address shifted left by 1, last bit is R/W
uint8_t address_byte = (DEVICE_ADDR_7BIT << 1) | read_write_bit;

// For 10-bit: send special header and two address bytes

7-bit addresses are most common and fit in one byte with a read/write bit.

10-bit addresses require sending extra bits and are less common.

Examples
This shows how to prepare the 7-bit address for sending with read or write bit.
Embedded C
/* 7-bit address example */
#define SENSOR_ADDR 0x50

// To send address with write bit (0)
uint8_t addr_write = (SENSOR_ADDR << 1) | 0;

// To send address with read bit (1)
uint8_t addr_read = (SENSOR_ADDR << 1) | 1;
Shows how to split a 10-bit address into two bytes for I2C communication.
Embedded C
/* 10-bit address example */
#define DEVICE_10BIT_ADDR 0x305

// First byte: 11110 + 2 MSBs of address + R/W bit
uint8_t first_byte = 0xF0 | ((DEVICE_10BIT_ADDR >> 7) & 0x06) | (read_write_bit & 0x01);

// Second byte: lower 8 bits of address
uint8_t second_byte = DEVICE_10BIT_ADDR & 0xFF;
Sample Program

This program shows how to prepare and print the I2C address bytes for both 7-bit and 10-bit addresses with read and write bits.

Embedded C
#include <stdio.h>
#include <stdint.h>

#define SENSOR_ADDR_7BIT 0x3C
#define DEVICE_ADDR_10BIT 0x1F3

void print_7bit_address(uint8_t addr, uint8_t rw) {
    uint8_t address_byte = (addr << 1) | (rw & 0x01);
    printf("7-bit address byte (with R/W=%d): 0x%02X\n", rw, address_byte);
}

void print_10bit_address(uint16_t addr, uint8_t rw) {
    uint8_t first_byte = 0xF0 | ((addr >> 7) & 0x06) | (rw & 0x01);
    uint8_t second_byte = addr & 0xFF;
    printf("10-bit address first byte (with R/W=%d): 0x%02X\n", rw, first_byte);
    printf("10-bit address second byte: 0x%02X\n", second_byte);
}

int main() {
    print_7bit_address(SENSOR_ADDR_7BIT, 0); // Write
    print_7bit_address(SENSOR_ADDR_7BIT, 1); // Read

    print_10bit_address(DEVICE_ADDR_10BIT, 0); // Write
    print_10bit_address(DEVICE_ADDR_10BIT, 1); // Read

    return 0;
}
OutputSuccess
Important Notes

Remember that the read/write bit is always the least significant bit in the address byte.

7-bit addresses are shifted left by 1 to make room for the read/write bit.

10-bit addressing is more complex and less common, so check your device datasheet carefully.

Summary

I2C uses 7-bit or 10-bit addresses to identify devices on the bus.

7-bit addresses are shifted left by 1 bit and combined with a read/write bit.

10-bit addresses require sending two bytes: a special header and the address split into two parts.