Struggling with I2C on nucleo stm32f103rb using arduino

I am struggling to get I2C working on a vanilla stm32f10310rb development board. I am using the Arduino Wire library. Here is my platformio.ini.

platform = ststm32
board = nucleo_f103rb
framework = arduino
monitor_port = /dev/ttyACM0

The nucleo has default solder bridges, this means the PB8 on the MCU should be routed to pin 10 on the arduino 10 pin connector (SCL) and PB9 to pin 9 (SDA). But putting the scope on both of these pins shows no signals.

So wherever the wire library sends its signals to on the MCU they are not going to PB8/9!

Here is my test code.

#include <Arduino.h>
#include <Wire.h>

void setup() {
    // Set the SDA/SCL

    // Initialise

    // Setup monitor
    Serial.println("\nI2C Scanner");

void loop() {
    byte error, address;
    int nDevices;


    nDevices = 0;
    for(address = 1; address < 127; address++ )
        // The i2c_scanner uses the return value of
        // the Write.endTransmisstion to see if
        // a device did acknowledge to the address.
        error = Wire.endTransmission();

        if (error == 0)
            Serial.print("I2C device found at address 0x");
            if (address<16)
            Serial.println(" !");

        else if (error==4)
            Serial.print("Unknow error at address 0x");
            if (address<16)
    if (nDevices == 0)
        Serial.println("No I2C devices found\n");

    delay(5000); // wait 5 seconds for next scan

So it looks like a pin mapping problem. Does the Wire library need to have its default pin names overriden? Am I picking up the correct PinMapping variant from the many ones in the framework-arduinoststm32?

Any help gratefully received.

PB8 and PB9 should be correct. Maybe the board has an entirely different problem, like a clock startup problem? Do you see the serial output in the serial monitor?

I happen to have this exact Nucleo board and according to NUCLEO-F103RB | Mbed you are correct in the pinout. On my board, with the USB socket the the top, the top right Arduino connector, CN5, is marked SCL/D15 and SDA/D14 for the two top pins – so it “should” work.

I created a project with your code, exactly as above, and with nothing plugged in, the Serial output told me so. I then connected up an RTC module that I have, and two devices were detected:

I2C device found at address 0x57 !
I2C device found at address 0x68 !

So, it appears that the pinout is correct and I2C is indeed on PB8 and PB9.

This is a silly question, but you are connecting to the inner Arduino style “female” connector and not to the double row of “male” pins to the outer edge of the board?


Norm .

Thanks guys.

The Serial monitor is running via the probe as expected.

I have stepped through the i2c setup and pinmap resolution with the debug probe and it all checks out (PB8 and PB9). I am now suspecting that the OLED display device I was using to test it is kaput.

I cannot understand why I am not seeing not seeing anything on the pins. Surely there should be some visible activity. I have tried it with the display module removed but leaving the pullups on, still nothing.

I put my cheap and nasty logic analyser – Seleae clone – on the pins and that detected activity on SCL/SDA. I didn’t try with my scope – a dinky little Espotek Labrador – as the logic anslyzer has an I2C decoder built in which is extremely handy and shows the start, stop, ack, nack, read and write addresses rather nicely.

The output is brief to say the least, then there’s the 5 second pause before there is any more activity.


Just enjoying a large slice of humble pie!

Thanks Norman. I had a closer look at my USB scope settings. Doh! Like an idiot I had got the timebase wrong, set far to low to see anything, and not triggering properly.

Reconnected the SSD1306 OLED. Now that is being found correctly! I had my head stuck too far down the Rabbit Hole to see properly! Arrrrgggghh.

1 Like

No need. We all make mistakes. (Said the hedgehog climbing off the toilet brush!! :laughing: )

I spent a large part of yesterday looking for a bug in some AVR assembly where the code was accepting some data over USART and then printing it out to the USART to display on the device monitor. It was printing the very first character only, but repeatedly “forever”.

Turned out I’d been using LDD r16,Z+ instead of LD r16,Z+ so I never advanced the Z pointer as LDD in this format, is invalid on ATmega328, so instead of an error message from the assembler, I simply get a NOP. Duh! Z never incremented so I never moved from the first character and never hit the terminating zero byte to stop output.

That was my afternoon yesterday!

Anyway, I’m glad you got it sorted in the end.