BME280 Sensor with STM32 Blue Pill using STM32CubeIDE

In this tutorial, we will learn how to interface BME280 sensor with STM32 Blue Pill and program it in STM32CubeIDE using HAL libraries. At first, we will briefly introduce you to BME280 sensor, then interface it with our STM32 and program it for temperature, pressure, and humidity measurement using STMCube IDE. For demonstration, we will connect an SSD1306 OLED with the STM32 Blue Pill to view the sensor data on the OLED.

BME280 with STM32 Blue Pill STM32CubeIDE

We have similar guides for BME280 with other microcontrollers:

BME280 sensor Introduction

The BME280 sensor is used to measure readings regarding ambient temperature, barometric pressure, and relative humidity. It is mostly used in web and mobile applications where low power consumption is key. This sensor uses I2C or SPI to communicate data with the microcontrollers. Although there are several different versions of BME280 available in the market, the one we will be studying uses the I2C communication protocol.

I2C means Inter-Integrated Circuit and works on the principle of the synchronous, multi-master multi-slave system. With BME280, the STM32 Blue Pill acts as a master, and the BME280 sensor acts as a slave because it is an external device, that acts as a slave. The Blue Pill communicates with the BME280 sensor through the I2C protocol to get temperature, barometric pressure, relative humidity, and altitude.

The figure below shows the BME280 sensor and its pinout.

BME280 Pinout Diagram
        
  • VCC: connected with 3.3V
  • SCL: used to generate the clock signal
  • SDA: used in sending and receiving data

Interface BME280 sensor with STM32 Blue Pill and OLED

We will need the following components for this project.

  1. STM32 Blue Pill board
  2. BME280 sensor
  3. SSD1306 OLED
  4. Breadboard
  5. Connecting Wires

The connection of BME280 with the Blue Pill is very simple. We have to connect the VCC terminal with 3.3V, ground with the ground (common ground), SCL of the sensor with SCL of the module, and SDA of the sensor with the SDA pin of the board.

The OLED display has 4 terminals which we will connect with the STM Blue Pill. As the OLED display requires an operating voltage in the range of 3.3-5V hence we will connect the VCC terminal with 3.3V which will be in common with the board and the sensor. SCL of the display will be connected with the SCL pin of the module and the SDA of the display will be connected with the SDA of the module. The ground of all three devices will be held common.

As both the OLED and BME280 sensor uses I2C communication protocol to communicate with the STM32 Blue Pill, hence we will use I2C1_SCL and I2C1_SDA pins to connect with each of the SCL and SDA pins of the sensor and OLED.

The connections between the three devices which we are using can be seen below.

The connections between the OLED and Blue Pill can be seen below.

STM32 Blue PillBME280SSD1306 OLED Display
3.3VVINVCC
PB7 (I2C1_SDA)SDASDA
PB6 (I2C_SCL)SCLSCL
GNDGNDGND

Connect the BME280 sensor and OLED with STM32 Blue Pill as shown in the schematic diagram below. We are using the same connections as specified in the tables above.

STM32 Blue Pill with BME280 and OLED connection diagram

STM32 Blue Pill BME280 Code with OLED

We will use STM32Cube IDE to program our STM32 board. Open the IDE and head over to a new project.

Then for the target selection, specify the STM32 Blue Pill board number. After that click on any column as shown in the picture below. Then click the ‘Next’ button.

Blue Pill STM32 using STM32Cube creating project pic 3

Specify the name of your project then click ‘Finish’ to complete the setup of your project.

Head over to Connectivity > I2C1. Select the I2C mode as ‘I2C.’ Then go to ‘Parameter Settings’ and set the I2C speed mode as ‘Fast Mode.’ This is necessary for the SSD1306 OLED.

STM32 Blue Pill with BME280 and OLED Setup I2C

Now we will save our file. Press Ctrl + S. The following window will appear. Click ‘Yes.’ This will generate a template code for you.

Blue Pill STM32 using STM32Cube creating project pic 11

Another window will appear that will ask if you want to open the perspective. Click ‘Yes.’

Blue Pill STM32 Creating project Digital Input picture 11

STM32 BME280 Library

To acquire BME280 temperature, pressure, and humidity readings with STM32 Blue Pill using STMCube IDE, we will require some BME280 libraries. Let us show you how to include them in your project in order to access the APIs provided by bme280.h

Create a new folder called BME280 inside the Src folder. Copy and save the following files inside the BME280 folder.

STM32 SSD1306 OLED Library

As we are working with an SSD1306 OLED with our STM32 Blue Pill, we will require the ssd1306.h and fonts.h libraries. These libraries will be used to access different functions that will enable us to display texts and numbers on the OLED in various ways.

ssd1306.h

Go to Core > Inc and create a new file called ‘ssd1306.h‘ Copy the following code from this link and save it to this file.

fonts.h

Go to Core > Inc and create a new file called ‘fonts.h‘ Copy the following code from this link and save it to this file.

ssd1306.c

Similarly, head over to Core > Src and create a new file called ‘ssd1306.c‘ Copy the following code from this link and save it to this file.

fonts.c

Head over to Core > Src and create a new file called ‘fonts.c‘ Copy the following code from this link and save it to this file.

STM32 Blue Pill BME280 Sensor Code STM32CubeIDE

Now let us look at our main.c file that was generated. Inside the main.c file, make sure the following code is part of your script by including the lines of code given below. We will use bme280.h library functions to access the BME280 sensor data and display them on the OLED using the fonts.h and ssd1306.h APIs.

#include <stdio.h>
#include <string.h>
#include "./BME280/bme280.h"
#include "fonts.h"
#include "ssd1306.h"

I2C_HandleTypeDef hi2c1;

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);

float temperature;
float humidity;
float pressure;

struct bme280_dev dev;
struct bme280_data comp_data;
int8_t rslt;

char hum_string[50];
char temp_string[50];
char press_string[50];

int8_t user_i2c_read(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len)
{
  if(HAL_I2C_Master_Transmit(&hi2c1, (id << 1), &reg_addr, 1, 10) != HAL_OK) return -1;
  if(HAL_I2C_Master_Receive(&hi2c1, (id << 1) | 0x01, data, len, 10) != HAL_OK) return -1;

  return 0;
}

void user_delay_ms(uint32_t period)
{
  HAL_Delay(period);
}

int8_t user_i2c_write(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len)
{
  int8_t *buf;
  buf = malloc(len +1);
  buf[0] = reg_addr;
  memcpy(buf +1, data, len);

  if(HAL_I2C_Master_Transmit(&hi2c1, (id << 1), (uint8_t*)buf, len + 1, HAL_MAX_DELAY) != HAL_OK) return -1;

  free(buf);
  return 0;
}

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_I2C1_Init();


  /* BME280 init */
  dev.dev_id = BME280_I2C_ADDR_PRIM;
  dev.intf = BME280_I2C_INTF;
  dev.read = user_i2c_read;
  dev.write = user_i2c_write;
  dev.delay_ms = user_delay_ms;

  rslt = bme280_init(&dev);

  /* BME280 settings */
  dev.settings.osr_h = BME280_OVERSAMPLING_1X;
  dev.settings.osr_p = BME280_OVERSAMPLING_16X;
  dev.settings.osr_t = BME280_OVERSAMPLING_2X;
  dev.settings.filter = BME280_FILTER_COEFF_16;
  rslt = bme280_set_sensor_settings(BME280_OSR_PRESS_SEL | BME280_OSR_TEMP_SEL | BME280_OSR_HUM_SEL | BME280_FILTER_SEL, &dev);

  /* Initialize OLED*/
  SSD1306_Init();

  while (1)
  {
    /* Forced mode setting, switched to SLEEP mode after measurement */
    rslt = bme280_set_sensor_mode(BME280_FORCED_MODE, &dev);
    dev.delay_ms(40);
    /*Get Data */
    rslt = bme280_get_sensor_data(BME280_ALL, &comp_data, &dev);
    if(rslt == BME280_OK)
    {
      temperature = comp_data.temperature / 100.0;
      humidity = comp_data.humidity / 1024.0;
      pressure = comp_data.pressure / 10000.0;

      /*Display Data */
      memset(hum_string, 0, sizeof(hum_string));
      memset(temp_string, 0, sizeof(temp_string));
      memset(press_string, 0, sizeof(press_string));

      sprintf(hum_string, "Humidity %03.1f %% ", humidity);
      sprintf(temp_string, "Temperature %03.1f C ", temperature);
      sprintf(press_string, "Pressure %03.1f hPa ", pressure);

      SSD1306_GotoXY (0, 0);
      SSD1306_Puts (hum_string, &Font_7x10, 1);
      SSD1306_GotoXY (0, 20);
      SSD1306_Puts (temp_string, &Font_7x10, 1);
      SSD1306_GotoXY (0, 40);
      SSD1306_Puts (press_string, &Font_7x10, 1);
      SSD1306_UpdateScreen();
    }

    HAL_Delay(1000);
  }

}

How the Code Works?

We start off by including the necessary libraries for this project which include the bme280.h for the sensor and fonts.h and ssd1306.h for the OLED functionality.

#include <stdio.h>
#include <string.h>
#include "./BME280/bme280.h"
#include "fonts.h"
#include "ssd1306.h"

Create some variables that we will use later on in the sketch to store the BME280 sensor data.

float temperature;
float humidity;
float pressure;

struct bme280_dev dev;
struct bme280_data comp_data;
int8_t rslt;

char hum_string[50];
char temp_string[50];
char press_string[50];

The user_i2c_read() function calls the data transmission and reception I2C HAL APIs in blocking mode for read purpose. This function returns 0 if I2C read data transmission and reception for master occurs successfully. Otherwise, if either of them fails, -1 is returned instead.

int8_t user_i2c_read(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len)
{
  if(HAL_I2C_Master_Transmit(&hi2c1, (id << 1), &reg_addr, 1, 10) != HAL_OK) return -1;
  if(HAL_I2C_Master_Receive(&hi2c1, (id << 1) | 0x01, data, len, 10) != HAL_OK) return -1;

  return 0;
}

The user_delay_ms() function takes in a single parameter which is ‘period’ inside it. This function will be called to cause a delay according to the period set.

void user_delay_ms(uint32_t period)
{
  HAL_Delay(period);
}

The user_i2c_write() function calls the data transmission I2C HAL APIs in blocking mode for write purpose. This function returns 0 if I2C write data transmission for master occurs successfully. Otherwise, -1 is returned instead.

int8_t user_i2c_write(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len)
{
  int8_t *buf;
  buf = malloc(len +1);
  buf[0] = reg_addr;
  memcpy(buf +1, data, len);

  if(HAL_I2C_Master_Transmit(&hi2c1, (id << 1), (uint8_t*)buf, len + 1, HAL_MAX_DELAY) != HAL_OK) return -1;

  free(buf);
  return 0;
}

main()

Inside the main function, first all the peripherals are initialized, system clock is configured and all the configured peripherals are initialized.

HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_I2C1_Init();
Initialize BME280 Sensor

Specify the BME280 device structure parameters for initialization including device id, interface, read function pointer, write function pointer and delay function pointer. Initialize the BME280 sensor by calling bme280_init() which reads the chip-id and calibrates data from the sensor. This function takes in a single parameter which is the pointer to the bme280 device structure.

dev.dev_id = BME280_I2C_ADDR_PRIM;
  dev.intf = BME280_I2C_INTF;
  dev.read = user_i2c_read;
  dev.write = user_i2c_write;
  dev.delay_ms = user_delay_ms;

  rslt = bme280_init(&dev);

Next, we set the settings of the BME280 sensor which includes the humidity, pressure and temperature oversampling values. The function bme280_set_sensor_settings() is responsible for setting the oversampling, filter, and standby duration. It takes in two parameters which are the desired settings and the pointer to the bme280 device structure.

  dev.settings.osr_h = BME280_OVERSAMPLING_1X;
  dev.settings.osr_p = BME280_OVERSAMPLING_16X;
  dev.settings.osr_t = BME280_OVERSAMPLING_2X;
  dev.settings.filter = BME280_FILTER_COEFF_16;
  rslt = bme280_set_sensor_settings(BME280_OSR_PRESS_SEL | BME280_OSR_TEMP_SEL | BME280_OSR_HUM_SEL | BME280_FILTER_SEL, &dev);

Moreover, we initialize the OLED by calling SSD1306_Init() function for initialization.

SSD1306_Init();
Obtain Sensor Data

Inside the infinite while loop, we first set the BME280 sensor in forced mode setting and then switch it to sleep mode after the measurement. The mode of the sensor is configured through the function bme280_set_sensor_mode().

  rslt = bme280_set_sensor_mode(BME280_FORCED_MODE, &dev);
   dev.delay_ms(40);

After a short delay, we will start accessing the sensor data from the sensor. The bme280_get_sensor_data() will read the temperature, pressure and humidity readings from the BME280 sensor, compensate them and store them in the bme280_data structure.

  rslt = bme280_get_sensor_data(BME280_ALL, &comp_data, &dev);
Display Sensor Data

If the function returns a successful response, then we will start displaying the sensor readings on the OLED screen. The readings will update to new values after every second.

 if(rslt == BME280_OK)
    {
      temperature = comp_data.temperature / 100.0;
      humidity = comp_data.humidity / 1024.0;
      pressure = comp_data.pressure / 10000.0;

      /*Display Data */
      memset(hum_string, 0, sizeof(hum_string));
      memset(temp_string, 0, sizeof(temp_string));
      memset(press_string, 0, sizeof(press_string));

      sprintf(hum_string, "Humidity %03.1f %% ", humidity);
      sprintf(temp_string, "Temperature %03.1f C ", temperature);
      sprintf(press_string, "Pressure %03.1f hPa ", pressure);

      SSD1306_GotoXY (0, 0);
      SSD1306_Puts (hum_string, &Font_7x10, 1);
      SSD1306_GotoXY (0, 20);
      SSD1306_Puts (temp_string, &Font_7x10, 1);
      SSD1306_GotoXY (0, 40);
      SSD1306_Puts (press_string, &Font_7x10, 1);
      SSD1306_UpdateScreen();
    }

First of all, we will obtain individual compensated temperature readings in degree Celsius, compensated humidity readings in percentage and compensated pressure readings in hPa from the bme_280 structure.

   temperature = comp_data.temperature / 100.0;
      humidity = comp_data.humidity / 1024.0;
      pressure = comp_data.pressure / 10000.0;

Then we convert the float variables to strings consisting of readings and units and display them on the OLED.

To display the sensor data on the OLED, first, we will set the x and the y axis position from where the text should start. SSD1306_gotoXY() function is used to set the write pointers. We have passed (0,0) as the parameter hence the text starts from the upper left corner. We use SSD1306_Puts() function to display the humidity readings along with its unit on the screen. This function takes in three parameters which is the string to be displayed, the font name and the color of the text. Similarly, to display temperature and pressure readings, we first set the starting x-axis and y-axis at (0,20) and (0,40) respectively and then call SSD1306_Puts() to display the strings. Additionally, call SSD1306_UpdateScreen() to display the text on the screen.

      memset(hum_string, 0, sizeof(hum_string));
      memset(temp_string, 0, sizeof(temp_string));
      memset(press_string, 0, sizeof(press_string));

      sprintf(hum_string, "Humidity %03.1f %% ", humidity);
      sprintf(temp_string, "Temperature %03.1f C ", temperature);
      sprintf(press_string, "Pressure %03.1f hPa ", pressure);

      SSD1306_GotoXY (0, 0);
      SSD1306_Puts (hum_string, &Font_7x10, 1);
      SSD1306_GotoXY (0, 20);
      SSD1306_Puts (temp_string, &Font_7x10, 1);
      SSD1306_GotoXY (0, 40);
      SSD1306_Puts (press_string, &Font_7x10, 1);
      SSD1306_UpdateScreen();

main.c file

This is how a complete main.c file will be after modification.

#include <stdio.h>
#include <string.h>
#include "./BME280/bme280.h"
#include "fonts.h"
#include "ssd1306.h"

I2C_HandleTypeDef hi2c1;

void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);

float temperature;
float humidity;
float pressure;

struct bme280_dev dev;
struct bme280_data comp_data;
int8_t rslt;

char hum_string[50];
char temp_string[50];
char press_string[50];

int8_t user_i2c_read(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len)
{
  if(HAL_I2C_Master_Transmit(&hi2c1, (id << 1), &reg_addr, 1, 10) != HAL_OK) return -1;
  if(HAL_I2C_Master_Receive(&hi2c1, (id << 1) | 0x01, data, len, 10) != HAL_OK) return -1;

  return 0;
}

void user_delay_ms(uint32_t period)
{
  HAL_Delay(period);
}

int8_t user_i2c_write(uint8_t id, uint8_t reg_addr, uint8_t *data, uint16_t len)
{
  int8_t *buf;
  buf = malloc(len +1);
  buf[0] = reg_addr;
  memcpy(buf +1, data, len);

  if(HAL_I2C_Master_Transmit(&hi2c1, (id << 1), (uint8_t*)buf, len + 1, HAL_MAX_DELAY) != HAL_OK) return -1;

  free(buf);
  return 0;
}

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_I2C1_Init();


  /* BME280 init */
  dev.dev_id = BME280_I2C_ADDR_PRIM;
  dev.intf = BME280_I2C_INTF;
  dev.read = user_i2c_read;
  dev.write = user_i2c_write;
  dev.delay_ms = user_delay_ms;

  rslt = bme280_init(&dev);

  /* BME280 settings */
  dev.settings.osr_h = BME280_OVERSAMPLING_1X;
  dev.settings.osr_p = BME280_OVERSAMPLING_16X;
  dev.settings.osr_t = BME280_OVERSAMPLING_2X;
  dev.settings.filter = BME280_FILTER_COEFF_16;
  rslt = bme280_set_sensor_settings(BME280_OSR_PRESS_SEL | BME280_OSR_TEMP_SEL | BME280_OSR_HUM_SEL | BME280_FILTER_SEL, &dev);

  /* Initialize OLED*/
  SSD1306_Init();

  while (1)
  {
    /* Forced mode setting, switched to SLEEP mode after measurement */
    rslt = bme280_set_sensor_mode(BME280_FORCED_MODE, &dev);
    dev.delay_ms(40);
    /*Get Data */
    rslt = bme280_get_sensor_data(BME280_ALL, &comp_data, &dev);
    if(rslt == BME280_OK)
    {
      temperature = comp_data.temperature / 100.0;
      humidity = comp_data.humidity / 1024.0;
      pressure = comp_data.pressure / 10000.0;

      /*Display Data */
      memset(hum_string, 0, sizeof(hum_string));
      memset(temp_string, 0, sizeof(temp_string));
      memset(press_string, 0, sizeof(press_string));

      sprintf(hum_string, "Humidity %03.1f %% ", humidity);
      sprintf(temp_string, "Temperature %03.1f C ", temperature);
      sprintf(press_string, "Pressure %03.1f hPa ", pressure);

      SSD1306_GotoXY (0, 0);
      SSD1306_Puts (hum_string, &Font_7x10, 1);
      SSD1306_GotoXY (0, 20);
      SSD1306_Puts (temp_string, &Font_7x10, 1);
      SSD1306_GotoXY (0, 40);
      SSD1306_Puts (press_string, &Font_7x10, 1);
      SSD1306_UpdateScreen();
    }

    HAL_Delay(1000);
  }

}
/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  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_HSI;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

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

/**
  * @brief I2C1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_I2C1_Init(void)
{

  /* USER CODE BEGIN I2C1_Init 0 */

  /* USER CODE END I2C1_Init 0 */

  /* USER CODE BEGIN I2C1_Init 1 */

  /* USER CODE END I2C1_Init 1 */
  hi2c1.Instance = I2C1;
  hi2c1.Init.ClockSpeed = 400000;
  hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
  hi2c1.Init.OwnAddress1 = 0;
  hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
  hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
  hi2c1.Init.OwnAddress2 = 0;
  hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
  hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
  if (HAL_I2C_Init(&hi2c1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN I2C1_Init 2 */

  /* USER CODE END I2C1_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOB_CLK_ENABLE();

}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

Save the main.c file after modifying it. Now we are ready to build our project.

Building the Project

To build our project press Ctrl + B or go to Project > Build All.

Your project will start building. After a few moments, your project will be successfully built if there are no errors.

Now as we have successfully built our project let us move ahead and upload the code to our STM32 board. First, we will have to connect our Blue Pill STM32 with an ST-Link programmer. We will be using ST-Link V2.

ST-Link V2 programmer

This will provide an interface between our computer and our STM32 board. It consists of 10 pins. We will be using pin2 SWDIO, pin6 SWCLK, pin4 GND, and pin8 3.3V to connect with our STM32 board. The SWDIO is the data input/output pin and the SWCLK is the clock pin. Follow the pin configuration given on ST-LINK V2 to identify each pin.

Follow the table below to connect both devices correctly.

STM32ST-LINK V2
VCC 3.3V pinpin8 3.3V
SWDIO pinpin2 SWDIO
SWCLK pinpin6 SWCLK
GND pinpin4 GND
ST-Link V2 with STM32 connection

Additionally, move the BOOT jumper to the right to enable the microcontroller to go into programming mode.

STM32 in programming mode
  • Now connect your ST-LINK V2 with your computer via the USB port. Both devices will power ON.
  • Next press the RUN button in the IDE. The ‘Edit configuration’ window will open up. Click ‘OK’.
  • After a few moments, the code will be successfully sent to the STM32 board. Otherwise, press the RESET button on your STM32 board.
  • Now to bring the Blue pill back to normal mode make sure you bring the BOOT jumper back to its place.

Once the code is uploaded to the board, the OLED will start displaying the humidity, temperature, and pressure readings on the screen, which will update to new values after every second.

STM32 Blue Pill with BME280 and OLED

You may also like to read:

Other projects with BME280:

Leave a Comment