STM32F411 based custom PCB I2C debugging

Hi everyone: i received in these days a custom PCB i designed based on the STM32F411 microcontroller:

I wanted to experiment with such MCUs and make a custom board with them for the first time; i was also interested in making it compatible with the arduino framework through PlatformIO as i already have some working pieces of code for arduino that i don’t want to lose.

I started running some tests and it turned out that i was able to program it and to use the serial monitor just fine; however the problems started when i tryed to use I2C sensors like this BME280 Breackout board i got from Amazon: i started simple by connecting it up to 3V3, same GND as the STM32 board, and SDA and SCL according to the attached PCB schematic.
I used this code as a firts test I2C address scanner in the main.c file:

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

int nDevices = 0;

void setup() {
  delay(1000);
  
  Wire.begin();

  Serial.begin(115200);
  while(!Serial){
    delay(10);
  }

  pinMode(PC13, OUTPUT);

  Serial.println("I2C pronto!");

  // Scan I2C
  byte error, address;
  for (address = 1; address < 127; address++) {
    Wire.beginTransmission(address);
    error = Wire.endTransmission();
    Serial.println(error);
    if (error == 0) {
      Serial.print("device found at 0x");
      Serial.println(address, HEX);
      nDevices++;
    }
    delay(5);  // Add small delay between attempts
  }
}

void loop() {
  if(nDevices != 0){
    digitalWrite(PC13, !digitalRead(PC13));
    delay(250);
  } else {
    Serial.println("no device found");
    delay(500);
  }
}

I also put this in the platformio.ini file (as u can see i was initially using the “genericSTM32F411CE” board on platformio):

[env:genericSTM32F411CE] 
platform = ststm32 
board = genericSTM32F411CE
framework = arduino 
upload_protocol = dfu 
build_flags = 
    -D PIO_FRAMEWORK_ARDUINO_ENABLE_CDC 
    -D USBCON 
    -D HSE_VALUE=8000000 
    -D ARDUINO_PIN_SDA=PB7 
    -D ARDUINO_PIN_SCL=PB6

With this setup it wasn’t finding any I2C device but at least it was printing such error message on the serial monitor as the code sayed.
Later i tryed swapping both “board” and “env” in the platformio.ini file with “blackpill_f411ce” and this time something weird happened: soon after startup the board started flashing its LED as it found a device but on the PC (in the device manager tab) it couldn’t recognise the STM32 board and thus not open the serial monitor on Platformio.

I assume it’s something more software related but i wouldn’t exlucde completely some hardware errors due to my inexperience working with STM32. Also i wanna poit out that the sensor breackout board works just fine as i tested it with a separate Arduino nano that powered the sensor with the same 3.3V as my custom PCB; i also verified that the power supply of my pcb that regualtes the 5V of the USB-C down to 3.3V was working and capable of powering both the STM32 and the sensor breackout.

Any help will be apreciated

This is not overriding the right pin macros at all. There are zero results when looking for a code reference to it.

Since you are using board = genericSTM32F411CE we have the used Arduino variant as

and that variant_generic.h file has

Which is in turn used to create

which is in turn what the Wire (I2C) library uses to construct its Wire object on by default

So your platformio.ini should be

[env:genericSTM32F411CE] 
platform = ststm32 
board = genericSTM32F411CE
framework = arduino 
upload_protocol = dfu 
build_flags = 
    -D PIO_FRAMEWORK_ARDUINO_ENABLE_CDC 
    -D USBCON 
    -D HSE_VALUE=8000000 
    -D PIN_WIRE_SDA=PB7 
    -D PIN_WIRE_SCL=PB6

Equally, you can construct a different or more Wire object or redefine pins on the fly, as is documented in

1 Like

Thanks a lot, now it works perfectly.

Also, you shouldn’t forget to setup your clock source properly. Your schematic has a 8 MHz crystal, but it is totally unused by the code. Since the generic board = genericSTM32F411CE uses the generic_clock.c clock initialization code,

It will cause only the high-speed internal 16 MHz (HSI) clock to be used, through the PLL to achieve a system clock of 96 MHz. But the USB subsystem needs a very accurate clock

And the HSI drifts around with temperature, very unstable. It’s sort of a miracle to me that you have a USB connection. With HSE = 8 MHz, the clocking for a stable 48MHz USB clock and 96 MHz system clock should look like this

Since the SystemClock_Config() function is marked as _WEAK (source), you can override it by providing a regular (strong) definition in code.

For example, in your main.cpp code, you can add

extern "C" void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 4;
  RCC_OscInitStruct.PLL.PLLN = 96;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
    Error_Handler();
  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
                                | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_3) != HAL_OK) {
    Error_Handler();
  }
}

The STM32F411 is also explicitly marked as being not crystal-less for USB: https://www.st.com/resource/en/application_note/an4879-introduction-to-usb-hardware-and-pcb-guidelines-using-stm32-mcus-stmicroelectronics.pdf

1 Like