Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

STM32 Hardware I2C Peripheral Configuration and Usage

Tech 2

STM32 microcontrollers integrate dedicated I2C hardware peripherals that offload timing-critical tasks—including clock generation, START/STOP condition handling, ACK/NAK management, and byte-level data transfer—from the CPU. This enables reliable, low-overhead communication with I2C-compatible sensors and peripherals.

Key Capabilities

  • Dual-role operation: supports both master and slave modes
  • Address support: 7-bit and 10-bit addressing schemes
  • Configurable speed modes: standard mode (≤100 kHz) and fast mode (≤400 kHz)
  • Optional DMA integration for zero-CPU-transfer bulk operations
  • Programmable PEC (Packet Error Checking) generation or verification
  • SMBus 2.0 protocol compatibility

On the STM32F103C8T6, two independent I2C interface are available: I2C1 and I2C2.

Operational Modes

The peripheral operates in one of four mutually exclusive roles:

  • Master transmitter
  • Master receiver
  • Slave transmitter
  • Slave receiver

Note: Both SDA and SCL pins are bidirectional. In slave mode, the SCL line is driven externally by the active master; the peripheral synchronizes its internal logic to that clock.

State Machine Events (Master Transmitter)

Event flags (e.g., EV5–EV9) are asserted when corresponding conditions occur and ITEVFEN is enabled. Clearing them typically involves reading status registers or writing to data registers.

  • EV5: SB flag set → read SR1, then write target slave address to DR
  • EV6: ADDR flag set → read SR1, then read SR2
  • EV8_1: TxE set, shift register empty, DR empty → write first data byte to DR
  • EV8: TxE set, shift register busy, DR empty → write next data byte to DR
  • EV8_2: TxE and BTF both set → issue STOP via I2C_GenerateSTOP()
  • EV9: ADDR10 set (10-bit addressing) → read SR1, then write second address byte to DR

State Machine Events (Master Receiver)

  • EV5: SB set → read SR1, then write slave adress to DR
  • EV6: ADDR set → read SR1, then read SR2; for 10-bit reads, set START=1 in CR2 afterward
  • EV6_1: Implicit state after EV6 for single-byte reads → disable ACK and assert STOP before reading DR
  • EV7: RxNE set → read DR to clear
  • EV7_1: RxNE set, final byte expectde → disable ACK and request STOP before reading DR
  • EV9: ADDR10 set → read SR1, then write second address byte to DR

Initialization Example (MPU6050 Interface)

void init_i2c2_for_mpu6050(void) {
    // Enable clocks
    RCC_APB1PeriphClockCmd(RCC_APB1PERIPH_I2C2, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_GPIOB, ENABLE);

    // Configure PB10 (SCL) and PB11 (SDA) as open-drain alternate function
    GPIO_InitTypeDef gpio_cfg;
    gpio_cfg.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
    gpio_cfg.GPIO_Mode = GPIO_Mode_AF_OD;
    gpio_cfg.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &gpio_cfg);

    // Configure I2C2 peripheral
    I2C_InitTypeDef i2c_cfg;
    i2c_cfg.I2C_Mode = I2C_Mode_I2C;
    i2c_cfg.I2C_ClockSpeed = 50000;
    i2c_cfg.I2C_DutyCycle = I2C_DutyCycle_2;
    i2c_cfg.I2C_OwnAddress1 = 0x00;
    i2c_cfg.I2C_Ack = I2C_Ack_Enable;
    i2c_cfg.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_Init(I2C2, &i2c_cfg);

    // Enable peripheral
    I2C_Cmd(I2C2, ENABLE);

    // Initialize MPU6050 device registers
    i2c_write_byte(MPU6050_ADDR, MPU6050_REG_PWR_MGMT_1, 0x01);
    i2c_write_byte(MPU6050_ADDR, MPU6050_REG_PWR_MGMT_2, 0x00);
    i2c_write_byte(MPU6050_ADDR, MPU6050_REG_SMPLRT_DIV, 0x09);
    i2c_write_byte(MPU6050_ADDR, MPU6050_REG_CONFIG, 0x06);
    i2c_write_byte(MPU6050_ADDR, MPU6050_REG_GYRO_CFG, 0x18);
    i2c_write_byte(MPU6050_ADDR, MPU6050_REG_ACCEL_CFG, 0x18);
}

Write Transaction Implementation

void i2c_write_byte(uint8_t dev_addr, uint8_t reg_addr, uint8_t value) {
    I2C_GenerateSTART(I2C2, ENABLE);
    wait_i2c_event(I2C2, I2C_EVENT_MASTER_MODE_SELECT);

    I2C_Send7bitAddress(I2C2, dev_addr, I2C_Direction_Transmitter);
    wait_i2c_event(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);

    I2C_SendData(I2C2, reg_addr);
    wait_i2c_event(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTING);

    I2C_SendData(I2C2, value);
    wait_i2c_event(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED);

    I2C_GenerateSTOP(I2C2, ENABLE);
}

Read Transaction Implementation

uint8_t i2c_read_byte(uint8_t dev_addr, uint8_t reg_addr) {
    // First phase: send register address
    I2C_GenerateSTART(I2C2, ENABLE);
    wait_i2c_event(I2C2, I2C_EVENT_MASTER_MODE_SELECT);

    I2C_Send7bitAddress(I2C2, dev_addr, I2C_Direction_Transmitter);
    wait_i2c_event(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);

    I2C_SendData(I2C2, reg_addr);
    wait_i2c_event(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED);

    // Second phase: restart and read
    I2C_GenerateSTART(I2C2, ENABLE);
    wait_i2c_event(I2C2, I2C_EVENT_MASTER_MODE_SELECT);

    I2C_Send7bitAddress(I2C2, dev_addr, I2C_Direction_Receiver);
    wait_i2c_event(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED);

    // Prepare for final byte: disable ACK and request STOP
    I2C_AcknowledgeConfig(I2C2, DISABLE);
    I2C_GenerateSTOP(I2C2, ENABLE);
    wait_i2c_event(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED);

    uint8_t result = I2C_ReceiveData(I2C2);

    // Restore ACK for future multi-byte reads
    I2C_AcknowledgeConfig(I2C2, ENABLE);

    return result;
}

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.