BabyStep 4. STM32F103ZET6 I2C Interface

BabyStep 4. USART with DMA [Delayed]

BabyStep 4. I2C Interface [Check]

Today I tried the I2C interface with the STM32 board (with the Gyro GY-521 sensor).

Well, the I2C from the STM32F103ZE end is working now, but still not able to communicate with the GY-521 sensor (I need to read the sensor’s document AGAIN!!)

Unfortunately, just when I was trying to use I2C, I found that the material provided by the seller doesn’t contain example project for I2C. And the I2C1 port resides in PORTB (Pin6 & 7 as SCL and SDA), which conflicts with the port used by the TFT touch screen I bought. I checked the schematic of the board, found no I2C2 interface connected. For now, no screen is not a big problem, but I’m a little bit disappointed.

[—————————————Added 19/12/2013——————————————————]

After contacting the seller and referring to the datasheet of the chip, there IS an I2C2 interface available, which means that the schematic view is wrong. I2C2 goes with PB.10 & PB.11, also I’ve add another USART interface @PA.2&PA.3 to interface with the GPS sensor I have.


At first, there’s no output from the two I2C pins, after debugging I found that the I2C peripheral is always busy. Google Search results suggested that:

1. No pull up resistor connected causing the SCL/SDA pulled down by some other devices, seen as the I2C peripheral.

2. I2C peripheral is not correctly reset.   (

I tried to change the GPIO mode, but with no luck.

Finally, I switched the I2C configuration and enable order. IT WORKS.

RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);      // Set clock for I2C1
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);   // Set clock for GPIOB
I2C_Cmd(I2C1, ENABLE); // Enable the I2C1
// RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, ENABLE);          // Assert Reset for the I2C1
// RCC_APB1PeriphResetCmd(RCC_APB1Periph_I2C1, DISABLE);        // Dessert Reset for the I2C1, not necessary as it seems now
I2C_Config(I2C1); // GY521 is connected to the I2C1 PB.6&7

void I2C_Config(I2C_TypeDef* I2Cx){
    GPIO_InitTypeDef GPIO_InitStructure;
    I2C_InitTypeDef I2C_InitStructure;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7; // PB.6 & 7
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    I2C_InitStructure.I2C_ClockSpeed = 400000; // 400kHz I2C fast mode
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; //
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2; // Tlow/Thigh = 2
    I2C_InitStructure.I2C_OwnAddress1 = 0x0000; // Use as I2C Master, Doesn't Matter
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; // Enable ACK Message
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; // 0x4000

    I2C_Init(I2Cx, &I2C_InitStructure);
    return ;

Then, I found this tutorial with example code for basic I2C read/write

After some helper function to read/write register value from/to GY521, I had the I2C communication working @400KHz.


This is the Waveform for a cycle of Register Read from STM32 Device.

This is the waveform of a Burst Read cycle from Arduino device with example project from I2CDev library. (This is my target for STM32)

PS. There’s a CPAL I2C Library from STM32 focusing on providing User Application level I2C API, but for now, it’s too complex for me, I reserve it as future investigation.
BS 5. PWM / Timer ? [____]


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s