DS18B20 Sensor with STM32 Nucleo using STM32CubeIDE

In this tutorial, we will learn how to interface DS18B20 temperature sensor with STM32 Nucleo and program it in STM32CubeIDE using HAL libraries. Firstly, we will briefly introduce you to DS18B20 sensor, then interface it with STM32 and program it for temperature measurement using STMCube IDE. For demonstration, we will connect an SSD1306 OLED with the STM32 Nucleo to display the sensor data on the OLED.

DS18B20 Sensor with STM32 Nucleo OLED

DS18B20 Introduction

DS18B20 is a temperature sensor that is single-wire programmable in nature. It is widely used to measure the temperature of chemical solutions and substances which are present in a hard environment. One of the advantages of using this sensor is that we only require a single pin of our microcontrollers to transfer data. Thus, it is extremely convenient to use this sensor with a microcontroller as we can measure multiple temperatures by using the least number of pins of our development board.

The table below shows some key characteristics of the ds18b120 sensor.

FeatureValue
Operating Voltage3-5V
Temperature Range-55°C to +125°C
Accuracy±0.5°C
Output Resolution9-12 bit
Key Characteristics of DS18B20

Pinout Diagram

A waterproof version of this sensor is also available in the market. The following figures show the pinout of the DS18B20 sensors.

ds18b20 waterproof pinout diagram
Pinout of waterproof DS18B20

The following diagram shows the pinout of the normal DS18B20 temperature sensor.

ds18b20 pinout diagram
DS18B20 pinout

The table below lists the pin configurations:

PinDescription
VCCThis is the pin that powers up the sensor. It is 3.3V or 5V for STM32 Nucleo boards.
DataThis pin gives the temperature reading.
GroundThis pin is connected with the ground
Pin Configuration details DS18B20

This temperature sensor also comes in a single package module which contains a sensor and a pull-up resistor. If you are using a module, you do not need to connect an external 4.7K ohm resistor. This is because the module already has an onboard pull-up resistor.

ds18b20 module
DS18B20 Module

Required Components:

QuantityComponentAmazon.com
1STM32 Nucleo Development Board with STM32F446RE MCU NUCLEO-F446REBuy here
1Breadboard Jumper Wires KitBuy Here
1DS18B20 SensorBuy here
1OLEDBuy here

Interface DS18B20 sensor with STM32 Nucleo and OLED

DS18B20 Sensor with STM32 Nucleo OLED

We will need the following components for this project.

  1. STM32 Nucleo board
  2. DS18B20 Sensor
  3. 4.7k ohm resistor
  4. SSD1306 OLED
  5. Breadboard
  6. Connecting Wires

The connections between DS18B20 and Nucleo can be seen below.

DS18B20 Sensor PinSTM32 Nucleo Pin
GNDGND
DataThe data out pin will be connected with a GPIO output pin with a 4.7k ohm pull-up resistor. We will use PA1 to connect with the data pin.
VCC5V

The connections between the OLED and Nucleo can be seen below.

STM32 NucleoSSD1306 OLED Display
3.3VVCC
PB7 (I2C1_SDA)SDA
PB6 (I2C1_SCL)SCL
GNDGND

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

You can read this in-depth guide on OLED with STM32:

STM32 Nucleo DS18B20 with OLED using STMCube IDE

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 Nucleo board number. After that click on any column as shown in the picture below. Then click the ‘Next’ button.

select STM32 Nucleo from board selector

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

Go to System Core > RCC then select ‘Crystal/Ceramic Resonator’ in from the High Speed Clock feature.

Enable external crystal resonator

Now we have enabled the RCC external clock source.

Now head over to Timers > TIM1 and select the Clock Source as ‘Internal Clock.’ Then click the Parameter Settings and set the Prescaler as 63 and set the trigger event selection as Reset.

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.

Setup PA1 as GPIO_Output pin and label it as DS18B20_Pin.

Clock Configuration

Next, go to the Clock Configuration found at the top. This will open the following window. Here we will select the clock frequency.

STM32 Blue Pill UART Interrupt Clock

Set the system clock as 48 MHz. These are the configurations we have set:

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 DS18B20 Library

To acquire DS18B20 temperature readings with STM32 Nucleo using STMCube IDE, we will require ds18b20 and onewire libraries. Let us show you how to include them in your project in order to access the APIs provided by each of them.

ds18b20.h

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

/*
 * ds18b20.h
 *
 *	The MIT License.
 *  Created on: 20.09.2018
 *      Author: Mateusz Salamon
 *      www.msalamon.pl
 *      mateusz@msalamon.pl
 *
 */
#ifndef	_DS18B20_H
#define	_DS18B20_H

#include "onewire.h"
#include "main.h"
//
//	CONFIGURATION
//
extern TIM_HandleTypeDef htim1;
//	Remember to configure a timer on CubeMX 1us per tick
//	example 72 MHz cpu - Prescaler=(72-1), Counter period=65000
#define _DS18B20_MAX_SENSORS		    4
#define	_DS18B20_GPIO					DS18B20_Pin_GPIO_Port
#define	_DS18B20_PIN					DS18B20_Pin

#define	_DS18B20_TIMER					htim1

//#define _DS18B20_USE_CRC

//
//	Sensor structure
//
typedef struct
{
	uint8_t 	Address[8];
	float 		Temperature;
	uint8_t		ValidDataFlag;
} Ds18b20Sensor_t;

//
//	DEFINES
//
#define DS18B20_FAMILY_CODE				0x28

#define DS18B20_CMD_ALARMSEARCH			0xEC
#define DS18B20_CMD_CONVERTTEMP			0x44

#define DS18B20_STEP_12BIT		0.0625
#define DS18B20_STEP_11BIT		0.125
#define DS18B20_STEP_10BIT		0.25
#define DS18B20_STEP_9BIT		0.5

#define DS18B20_RESOLUTION_R1	6 // Resolution bit R1
#define DS18B20_RESOLUTION_R0	5 // Resolution bit R0

#ifdef _DS18B20_USE_CRC
#define DS18B20_DATA_LEN	9
#else
#define DS18B20_DATA_LEN	5
#endif

typedef enum {
	DS18B20_Resolution_9bits = 9,
	DS18B20_Resolution_10bits = 10,
	DS18B20_Resolution_11bits = 11,
	DS18B20_Resolution_12bits = 12
} DS18B20_Resolution_t;

//
//	FUNCTIONS
//

// 	Init
void		DS18B20_Init(DS18B20_Resolution_t resolution);
//	Settings
uint8_t 	DS18B20_GetResolution(uint8_t number); // Get the sensor resolution
uint8_t 	DS18B20_SetResolution(uint8_t number, DS18B20_Resolution_t resolution);	// Set the sensor resolution
// Control
uint8_t 	DS18B20_Start(uint8_t number); // Start conversion of one sensor
void 		DS18B20_StartAll(void);	// Start conversion for all sensors
uint8_t		DS18B20_Read(uint8_t number, float* destination); // Read one sensor
void 		DS18B20_ReadAll(void);	// Read all connected sensors
uint8_t 	DS18B20_Is(uint8_t* ROM); // Check if ROM address is DS18B20 family
uint8_t 	DS18B20_AllDone(void);	// Check if all sensor's conversion is done
//	ROMs
void		DS18B20_GetROM(uint8_t number, uint8_t* ROM); // Get sensor's ROM from 'number' position
void		DS18B20_WriteROM(uint8_t number, uint8_t* ROM); // Write a ROM to 'number' position in sensors table
// Return functions
uint8_t 	DS18B20_Quantity(void);	// Returns quantity of connected sensors
uint8_t		DS18B20_GetTemperature(uint8_t number, float* destination); // Returns 0 if read data is invalid
#endif

onewire.h

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

/*
 * onewire.h
 *
 *	The MIT License.
 *  Created on: 20.09.2018
 *      Author: Mateusz Salamon
 *      www.msalamon.pl
 *      mateusz@msalamon.pl
 *
 */
#ifndef ONEWIRE_H
#define ONEWIRE_H

#ifdef __cplusplus
extern C {
#endif
#include "stm32f1xx_hal.h"
//
//	1-Wire bus structure
//
typedef struct {
	GPIO_TypeDef* GPIOx;           // Bus GPIO Port
	uint16_t GPIO_Pin;             // Bus GPIO Pin
	uint8_t LastDiscrepancy;       // For searching purpose
	uint8_t LastFamilyDiscrepancy; // For searching purpose
	uint8_t LastDeviceFlag;        // For searching purpose
	uint8_t ROM_NO[8];             // 8-byte ROM addres last found device
} OneWire_t;

//
//	COMMANDS
//
#define ONEWIRE_CMD_RSCRATCHPAD			0xBE
#define ONEWIRE_CMD_WSCRATCHPAD			0x4E
#define ONEWIRE_CMD_CPYSCRATCHPAD		0x48
#define ONEWIRE_CMD_RECEEPROM			0xB8
#define ONEWIRE_CMD_RPWRSUPPLY			0xB4
#define ONEWIRE_CMD_SEARCHROM			0xF0
#define ONEWIRE_CMD_READROM				0x33
#define ONEWIRE_CMD_MATCHROM			0x55
#define ONEWIRE_CMD_SKIPROM				0xCC

//
//	FUNCTIONS
//

//
// Initialisation
//
void OneWire_Init(OneWire_t* OneWireStruct, GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

//
// Reset bus
//
uint8_t OneWire_Reset(OneWire_t* OneWireStruct);

//
// Searching
//
void OneWire_ResetSearch(OneWire_t* OneWireStruct);
uint8_t OneWire_First(OneWire_t* OneWireStruct);
uint8_t OneWire_Next(OneWire_t* OneWireStruct);
uint8_t OneWire_Search(OneWire_t* OneWireStruct, uint8_t command);

//
// Writing/Reading
//
void OneWire_WriteBit(OneWire_t* OneWireStruct, uint8_t bit);
uint8_t OneWire_ReadBit(OneWire_t* OneWireStruct);
void OneWire_WriteByte(OneWire_t* OneWireStruct, uint8_t byte);
uint8_t OneWire_ReadByte(OneWire_t* OneWireStruct);

//
// ROM operations
//
void OneWire_GetFullROM(OneWire_t* OneWireStruct, uint8_t *firstIndex);
void OneWire_Select(OneWire_t* OneWireStruct, uint8_t* addr);
void OneWire_SelectWithPointer(OneWire_t* OneWireStruct, uint8_t* ROM);

//
//	CRC calculating
//
uint8_t OneWire_CRC8(uint8_t* addr, uint8_t len);
#ifdef __cplusplus
}
#endif
#endif

ds18b20.c

Go to Core > Inc and create a new file called ‘ds18b20.c‘. Copy the following code and save it to this file. 

/*
 * ds18b20.c
 *
 *	The MIT License.
 *  Created on: 20.09.2018
 *      Author: Mateusz Salamon
 *      www.msalamon.pl
 *      mateusz@msalamon.pl
 *
 */
#include "ds18b20.h"

//
//	VARIABLES
//
Ds18b20Sensor_t	ds18b20[_DS18B20_MAX_SENSORS];

OneWire_t OneWire;
uint8_t	OneWireDevices;
uint8_t TempSensorCount=0;

//
//	FUNCTIONS
//

//
//	Start conversion of @number sensor
//
uint8_t DS18B20_Start(uint8_t number)
{
	if( number >= TempSensorCount) // If read sensor is not availible
		return 0;

	if (!DS18B20_Is((uint8_t*)&ds18b20[number].Address)) // Check if sensor is DS18B20 family
		return 0;

	OneWire_Reset(&OneWire); // Reset the bus
	OneWire_SelectWithPointer(&OneWire, (uint8_t*)ds18b20[number].Address); // Select the sensor by ROM
	OneWire_WriteByte(&OneWire, DS18B20_CMD_CONVERTTEMP); // Convert command

	return 1;
}

//
//	Start conversion on all sensors
//
void DS18B20_StartAll()
{
	OneWire_Reset(&OneWire); // Reset the bus
	OneWire_WriteByte(&OneWire, ONEWIRE_CMD_SKIPROM); // Skip ROM command
	OneWire_WriteByte(&OneWire, DS18B20_CMD_CONVERTTEMP); // Start conversion on all sensors
}

//
//	Read one sensor
//
uint8_t DS18B20_Read(uint8_t number, float *destination)
{
	if( number >= TempSensorCount) // If read sensor is not availible
		return 0;

	uint16_t temperature;
	uint8_t resolution;
	float result;
	uint8_t i = 0;
	uint8_t data[DS18B20_DATA_LEN];
#ifdef _DS18B20_USE_CRC
	uint8_t crc;

#endif


	if (!DS18B20_Is((uint8_t*)&ds18b20[number].Address)) // Check if sensor is DS18B20 family
		return 0;

	if (!OneWire_ReadBit(&OneWire)) // Check if the bus is released
		return 0; // Busy bus - conversion is not finished

	OneWire_Reset(&OneWire); // Reset the bus
	OneWire_SelectWithPointer(&OneWire, (uint8_t*)&ds18b20[number].Address); // Select the sensor by ROM
	OneWire_WriteByte(&OneWire, ONEWIRE_CMD_RSCRATCHPAD); // Read scratchpad command

	for (i = 0; i < DS18B20_DATA_LEN; i++) // Read scratchpad
		data[i] = OneWire_ReadByte(&OneWire);

#ifdef _DS18B20_USE_CRC
	crc = OneWire_CRC8(data, 8); // CRC calculation

	if (crc != data[8])
		return 0; // CRC invalid
#endif
	temperature = data[0] | (data[1] << 8); // Temperature is 16-bit length

	OneWire_Reset(&OneWire); // Reset the bus

	resolution = ((data[4] & 0x60) >> 5) + 9; // Sensor's resolution from scratchpad's byte 4

	switch (resolution) // Chceck the correct value dur to resolution
	{
		case DS18B20_Resolution_9bits:
			result = temperature*(float)DS18B20_STEP_9BIT;
		break;
		case DS18B20_Resolution_10bits:
			result = temperature*(float)DS18B20_STEP_10BIT;
		 break;
		case DS18B20_Resolution_11bits:
			result = temperature*(float)DS18B20_STEP_11BIT;
		break;
		case DS18B20_Resolution_12bits:
			result = temperature*(float)DS18B20_STEP_12BIT;
		 break;
		default:
			result = 0xFF;
	}

	*destination = result;

	return 1; //temperature valid
}

uint8_t DS18B20_GetResolution(uint8_t number)
{
	if( number >= TempSensorCount)
		return 0;

	uint8_t conf;

	if (!DS18B20_Is((uint8_t*)&ds18b20[number].Address))
		return 0;

	OneWire_Reset(&OneWire); // Reset the bus
	OneWire_SelectWithPointer(&OneWire, (uint8_t*)&ds18b20[number].Address); // Select the sensor by ROM
	OneWire_WriteByte(&OneWire, ONEWIRE_CMD_RSCRATCHPAD); // Read scratchpad command

	OneWire_ReadByte(&OneWire);
	OneWire_ReadByte(&OneWire);
	OneWire_ReadByte(&OneWire);
	OneWire_ReadByte(&OneWire);

	conf = OneWire_ReadByte(&OneWire); // Register 5 is the configuration register with resolution
	conf &= 0x60; // Mask two resolution bits
	conf >>= 5; // Shift to left
	conf += 9; // Get the result in number of resolution bits

	return conf;
}

uint8_t DS18B20_SetResolution(uint8_t number, DS18B20_Resolution_t resolution)
{
	if( number >= TempSensorCount)
		return 0;

	uint8_t th, tl, conf;
	if (!DS18B20_Is((uint8_t*)&ds18b20[number].Address))
		return 0;

	OneWire_Reset(&OneWire); // Reset the bus
	OneWire_SelectWithPointer(&OneWire, (uint8_t*)&ds18b20[number].Address); // Select the sensor by ROM
	OneWire_WriteByte(&OneWire, ONEWIRE_CMD_RSCRATCHPAD); // Read scratchpad command

	OneWire_ReadByte(&OneWire);
	OneWire_ReadByte(&OneWire);

	th = OneWire_ReadByte(&OneWire); 	// Writing to scratchpad begins from the temperature alarms bytes
	tl = OneWire_ReadByte(&OneWire); 	// 	so i have to store them.
	conf = OneWire_ReadByte(&OneWire);	// Config byte

	if (resolution == DS18B20_Resolution_9bits) // Bits setting
	{
		conf &= ~(1 << DS18B20_RESOLUTION_R1);
		conf &= ~(1 << DS18B20_RESOLUTION_R0);
	}
	else if (resolution == DS18B20_Resolution_10bits)
	{
		conf &= ~(1 << DS18B20_RESOLUTION_R1);
		conf |= 1 << DS18B20_RESOLUTION_R0;
	}
	else if (resolution == DS18B20_Resolution_11bits)
	{
		conf |= 1 << DS18B20_RESOLUTION_R1;
		conf &= ~(1 << DS18B20_RESOLUTION_R0);
	}
	else if (resolution == DS18B20_Resolution_12bits)
	{
		conf |= 1 << DS18B20_RESOLUTION_R1;
		conf |= 1 << DS18B20_RESOLUTION_R0;
	}

	OneWire_Reset(&OneWire); // Reset the bus
	OneWire_SelectWithPointer(&OneWire, (uint8_t*)&ds18b20[number].Address); // Select the sensor by ROM
	OneWire_WriteByte(&OneWire, ONEWIRE_CMD_WSCRATCHPAD); // Write scratchpad command

	OneWire_WriteByte(&OneWire, th); // Write 3 bytes to scratchpad
	OneWire_WriteByte(&OneWire, tl);
	OneWire_WriteByte(&OneWire, conf);

	OneWire_Reset(&OneWire); // Reset the bus
	OneWire_SelectWithPointer(&OneWire, (uint8_t*)&ds18b20[number].Address); // Select the sensor by ROM
	OneWire_WriteByte(&OneWire, ONEWIRE_CMD_CPYSCRATCHPAD); // Copy scratchpad to EEPROM

	return 1;
}

uint8_t DS18B20_Is(uint8_t* ROM)
{
	if (*ROM == DS18B20_FAMILY_CODE) // Check family code
		return 1;
	return 0;
}

uint8_t DS18B20_AllDone(void)
{
	return OneWire_ReadBit(&OneWire); // Bus is down - busy
}

void DS18B20_ReadAll(void)
{
	uint8_t i;

	if (DS18B20_AllDone())
	{
		for(i = 0; i < TempSensorCount; i++) // All detected sensors loop
		{
			ds18b20[i].ValidDataFlag = 0;

			if (DS18B20_Is((uint8_t*)&ds18b20[i].Address))
			{
				ds18b20[i].ValidDataFlag = DS18B20_Read(i, &ds18b20[i].Temperature); // Read single sensor
			}
		}
	}
}

void DS18B20_GetROM(uint8_t number, uint8_t* ROM)
{
	if( number >= TempSensorCount)
		number = TempSensorCount;

	uint8_t i;

	for(i = 0; i < 8; i++)
		ROM[i] = ds18b20[number].Address[i];
}

void DS18B20_WriteROM(uint8_t number, uint8_t* ROM)
{
	if( number >= TempSensorCount)
		return;

	uint8_t i;

	for(i = 0; i < 8; i++)
		ds18b20[number].Address[i] = ROM[i]; // Write ROM into sensor's structure
}

uint8_t DS18B20_Quantity(void)
{
	return TempSensorCount;
}

uint8_t DS18B20_GetTemperature(uint8_t number, float* destination)
{
	if(!ds18b20[number].ValidDataFlag)
		return 0;

	*destination = ds18b20[number].Temperature;
	return 1;

}

void DS18B20_Init(DS18B20_Resolution_t resolution)
{
	uint8_t next = 0, i = 0, j;
	OneWire_Init(&OneWire, DS18B20_Pin_GPIO_Port, DS18B20_Pin_Pin); // Init OneWire bus

	next = OneWire_First(&OneWire); // Search first OneWire device
	while(next)
	{
		TempSensorCount++;
		OneWire_GetFullROM(&OneWire, (uint8_t*)&ds18b20[i++].Address); // Get the ROM of next sensor
		next = OneWire_Next(&OneWire);
		if(TempSensorCount >= _DS18B20_MAX_SENSORS) // More sensors than set maximum is not allowed
			break;
	}

	for(j = 0; j < i; j++)
	{
		DS18B20_SetResolution(j, resolution); // Set the initial resolution to sensor

		DS18B20_StartAll(); // Start conversion on all sensors
	}
}

onewire.c

Go to Core > Inc and create a new file called ‘onewire.c‘ Copy the following code and save it to this file. 

/*
 * onewire.c
 *
 *	The MIT License.
 *  Created on: 20.09.2018
 *      Author: Mateusz Salamon
 *      www.msalamon.pl
 *      mateusz@msalamon.pl
 *
 */
#include "onewire.h"
#include "ds18b20.h"

//
//	Delay function for constant 1-Wire timings
//
void OneWire_Delay(uint16_t us)
{
	_DS18B20_TIMER.Instance->CNT = 0;
	while(_DS18B20_TIMER.Instance->CNT <= us);
}

//
//	Bus direction control
//
void OneWire_BusInputDirection(OneWire_t *onewire)
{
	GPIO_InitTypeDef	GPIO_InitStruct;
	GPIO_InitStruct.Mode = GPIO_MODE_INPUT; // Set as input
	GPIO_InitStruct.Pull = GPIO_NOPULL; // No pullup - the pullup resistor is external
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; // Medium GPIO frequency
	GPIO_InitStruct.Pin = onewire->GPIO_Pin; // Pin for 1-Wire bus
	HAL_GPIO_Init(onewire->GPIOx, &GPIO_InitStruct); // Reinitialize
}

void OneWire_BusOutputDirection(OneWire_t *onewire)
{
	GPIO_InitTypeDef	GPIO_InitStruct;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD; // Set as open-drain output
	GPIO_InitStruct.Pull = GPIO_NOPULL; // No pullup - the pullup resistor is external
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM; // Medium GPIO frequency
	GPIO_InitStruct.Pin = onewire->GPIO_Pin; // Pin for 1-Wire bus
	HAL_GPIO_Init(onewire->GPIOx, &GPIO_InitStruct); // Reinitialize
}

//
//	Bus pin output state control
//
void OneWire_OutputLow(OneWire_t *onewire)
{
	onewire->GPIOx->BSRR = onewire->GPIO_Pin<<16; // Reset the 1-Wire pin
}

void OneWire_OutputHigh(OneWire_t *onewire)
{
	onewire->GPIOx->BSRR = onewire->GPIO_Pin; // Set the 1-Wire pin
}

//
//	1-Wire bus reset signal
//
//	Returns:
//	0 - Reset ok
//	1 - Error
//
uint8_t OneWire_Reset(OneWire_t* onewire)
{
	uint8_t i;

	OneWire_OutputLow(onewire);  // Write bus output low
	OneWire_BusOutputDirection(onewire);
	OneWire_Delay(480); // Wait 480 us for reset

	OneWire_BusInputDirection(onewire); // Release the bus by switching to input
	OneWire_Delay(70);

	i = HAL_GPIO_ReadPin(onewire->GPIOx, onewire->GPIO_Pin); // Check if bus is low
															 // if it's high - no device is presence on the bus
	OneWire_Delay(410);

	return i;
}

//
//	Writing/Reading operations
//
void OneWire_WriteBit(OneWire_t* onewire, uint8_t bit)
{
	if (bit) // Send '1',
	{
		OneWire_OutputLow(onewire);	// Set the bus low
		OneWire_BusOutputDirection(onewire);
		OneWire_Delay(6);

		OneWire_BusInputDirection(onewire); // Release bus - bit high by pullup
		OneWire_Delay(64);
	}
	else // Send '0'
	{
		OneWire_OutputLow(onewire); // Set the bus low
		OneWire_BusOutputDirection(onewire);
		OneWire_Delay(60);

		OneWire_BusInputDirection(onewire); // Release bus - bit high by pullup
		OneWire_Delay(10);
	}
}

uint8_t OneWire_ReadBit(OneWire_t* onewire)
{
	uint8_t bit = 0; // Default read bit state is low

	OneWire_OutputLow(onewire); // Set low to initiate reading
	OneWire_BusOutputDirection(onewire);
	OneWire_Delay(2);

	OneWire_BusInputDirection(onewire); // Release bus for Slave response
	OneWire_Delay(10);

	if (HAL_GPIO_ReadPin(onewire->GPIOx, onewire->GPIO_Pin)) // Read the bus state
		bit = 1;

	OneWire_Delay(50); // Wait for end of read cycle

	return bit;
}

void OneWire_WriteByte(OneWire_t* onewire, uint8_t byte)
{
	uint8_t i = 8;

	do
	{
		OneWire_WriteBit(onewire, byte & 1); // LSB first
		byte >>= 1;
	} while(--i);
}

uint8_t OneWire_ReadByte(OneWire_t* onewire)
{
	uint8_t i = 8, byte = 0;

	do{
		byte >>= 1;
		byte |= (OneWire_ReadBit(onewire) << 7); // LSB first
	} while(--i);

	return byte;
}

//
// 1-Wire search operations
//
void OneWire_ResetSearch(OneWire_t* onewire)
{
	// Clear the search results
	onewire->LastDiscrepancy = 0;
	onewire->LastDeviceFlag = 0;
	onewire->LastFamilyDiscrepancy = 0;
}

uint8_t OneWire_Search(OneWire_t* onewire, uint8_t command)
{
	uint8_t id_bit_number;
	uint8_t last_zero, rom_byte_number, search_result;
	uint8_t id_bit, cmp_id_bit;
	uint8_t rom_byte_mask, search_direction;

	id_bit_number = 1;
	last_zero = 0;
	rom_byte_number = 0;
	rom_byte_mask = 1;
	search_result = 0;

	if (!onewire->LastDeviceFlag) // If last device flag is not set
	{
		if (OneWire_Reset(onewire)) // Reset bus
		{
			// If error while reset - reset search results
			onewire->LastDiscrepancy = 0;
			onewire->LastDeviceFlag = 0;
			onewire->LastFamilyDiscrepancy = 0;
			return 0;
		}

		OneWire_WriteByte(onewire, command); // Send searching command

		// Searching loop, Maxim APPLICATION NOTE 187
		do
		{
			id_bit = OneWire_ReadBit(onewire); // Read a bit 1
			cmp_id_bit = OneWire_ReadBit(onewire); // Read the complement of bit 1

			if ((id_bit == 1) && (cmp_id_bit == 1)) // 11 - data error
			{
				break;
			}
			else
			{
				if (id_bit != cmp_id_bit)
				{
					search_direction = id_bit;  // Bit write value for search
				}
				else // 00 - 2 devices
				{
					// Table 3. Search Path Direction
					if (id_bit_number < onewire->LastDiscrepancy)
					{
						search_direction = ((onewire->ROM_NO[rom_byte_number] & rom_byte_mask) > 0);
					}
					else
					{
						// If bit is equal to last - pick 1
						// If not - then pick 0
						search_direction = (id_bit_number == onewire->LastDiscrepancy);
					}

					if (search_direction == 0) // If 0 was picked, write it to LastZero
					{
						last_zero = id_bit_number;

						if (last_zero < 9) // Check for last discrepancy in family
						{
							onewire->LastFamilyDiscrepancy = last_zero;
						}
					}
				}

				if (search_direction == 1)
				{
					onewire->ROM_NO[rom_byte_number] |= rom_byte_mask; // Set the bit in the ROM byte rom_byte_number
				}
				else
				{
					onewire->ROM_NO[rom_byte_number] &= ~rom_byte_mask; // Clear the bit in the ROM byte rom_byte_number
				}

				OneWire_WriteBit(onewire, search_direction); // Search direction write bit

				id_bit_number++; // Next bit search - increase the id
				rom_byte_mask <<= 1; // Shoft the mask for next bit

				if (rom_byte_mask == 0) // If the mask is 0, it says the whole byte is read
				{
					rom_byte_number++; // Next byte number
					rom_byte_mask = 1; // Reset the mask - first bit
				}
			}
		} while(rom_byte_number < 8);  // Read 8 bytes

		if (!(id_bit_number < 65)) // If all read bits number is below 65 (8 bytes)
		{
			onewire->LastDiscrepancy = last_zero;

			if (onewire->LastDiscrepancy == 0) // If last discrepancy is 0 - last device found
			{
				onewire->LastDeviceFlag = 1; // Set the flag
			}

			search_result = 1; // Searching successful
		}
	}

	// If no device is found - reset search data and return 0
	if (!search_result || !onewire->ROM_NO[0])
	{
		onewire->LastDiscrepancy = 0;
		onewire->LastDeviceFlag = 0;
		onewire->LastFamilyDiscrepancy = 0;
		search_result = 0;
	}

	return search_result;
}

//
//	Return first device on 1-Wire bus
//
uint8_t OneWire_First(OneWire_t* onewire)
{
	OneWire_ResetSearch(onewire);

	return OneWire_Search(onewire, ONEWIRE_CMD_SEARCHROM);
}

//
//	Return next device on 1-Wire bus
//
uint8_t OneWire_Next(OneWire_t* onewire)
{
   /* Leave the search state alone */
   return OneWire_Search(onewire, ONEWIRE_CMD_SEARCHROM);
}

//
//	Select a device on bus by address
//
void OneWire_Select(OneWire_t* onewire, uint8_t* addr)
{
	uint8_t i;
	OneWire_WriteByte(onewire, ONEWIRE_CMD_MATCHROM); // Match ROM command

	for (i = 0; i < 8; i++)
	{
		OneWire_WriteByte(onewire, *(addr + i));
	}
}

//
//	Select a device on bus by pointer to ROM address
//
void OneWire_SelectWithPointer(OneWire_t* onewire, uint8_t *ROM)
{
	uint8_t i;
	OneWire_WriteByte(onewire, ONEWIRE_CMD_MATCHROM); // Match ROM command

	for (i = 0; i < 8; i++)
	{
		OneWire_WriteByte(onewire, *(ROM + i));
	}
}

//
//	Get the ROM of found device
//
void OneWire_GetFullROM(OneWire_t* onewire, uint8_t *firstIndex)
{
	uint8_t i;
	for (i = 0; i < 8; i++) {
		*(firstIndex + i) = onewire->ROM_NO[i];
	}
}

//
//	Calculate CRC
//
uint8_t OneWire_CRC8(uint8_t *addr, uint8_t len) {
	uint8_t crc = 0, inbyte, i, mix;

	while (len--)
	{
		inbyte = *addr++;
		for (i = 8; i; i--)
		{
			mix = (crc ^ inbyte) & 0x01;
			crc >>= 1;
			if (mix)
			{
				crc ^= 0x8C;
			}
			inbyte >>= 1;
		}
	}

	return crc;
}

//
//	1-Wire initialization
//
void OneWire_Init(OneWire_t* onewire, GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
	HAL_TIM_Base_Start(&_DS18B20_TIMER); // Start the delay timer

	onewire->GPIOx = GPIOx; // Save 1-wire bus pin
	onewire->GPIO_Pin = GPIO_Pin;

	// 1-Wire bit bang initialization
	OneWire_BusOutputDirection(onewire);
	OneWire_OutputHigh(onewire);
	HAL_Delay(100);
	OneWire_OutputLow(onewire);
	HAL_Delay(100);
	OneWire_OutputHigh(onewire);
	HAL_Delay(200);
}

STM32 OLED Library

As we are working with an SSD1306 OLED with our STM32 Nucleo, 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.hCopy the following code from this link and save it to this file.

In ssd1306.h file, remove #include “i2c.h” (line 49) and add extern I2C_HandleTypeDef hi2c1;

fonts.h

Go to Core > Inc and create a new file called ‘fonts.hCopy 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.cCopy 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.cCopy the following code from this link and save it to this file.

STM32 Nucleo DS18B20 Sensor with OLED Code

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 HAL library functions and DS18B20 libraries to access the sensor data and display them on the OLED using the fonts.h and ssd1306.h APIs.

#include "main.h"
#include "onewire.h"
#include "ds18b20.h"
#include "string.h"
#include <stdio.h>
#include "fonts.h"
#include "ssd1306.h"

I2C_HandleTypeDef hi2c1;

TIM_HandleTypeDef htim1;

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

float temperature;
char string[64];

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

  SSD1306_Init();

  DS18B20_Init(DS18B20_Resolution_12bits);
 
  while (1)
  {
	  DS18B20_ReadAll();
          DS18B20_StartAll();
		uint8_t ROM_tmp[8];
		uint8_t i;

	for(i = 0; i < DS18B20_Quantity(); i++)
		{
			if(DS18B20_GetTemperature(i, &temperature))
			{
				DS18B20_GetROM(i, ROM_tmp);
				memset(string, 0, sizeof(string));
				sprintf(string, "%.2f C", temperature);
				SSD1306_GotoXY (20, 0);
				SSD1306_Puts ("Temperature", &Font_7x10, 1);
				SSD1306_GotoXY (25, 30);
				SSD1306_Puts (string, &Font_11x18, 1);
				SSD1306_UpdateScreen();
			}
		}
		HAL_Delay(1000);
  }
}

How does the Code Works?

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

#include "main.h"
#include "onewire.h"
#include "ds18b20.h"
#include "string.h"
#include <stdio.h>
#include "fonts.h"
#include "ssd1306.h"

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_TIM1_Init();
  MX_I2C1_Init();

Next, we initialize the OLED. We use the SSD1306_Init() function for initialization.

SSD1306_Init();

Initialize the DS18B20 sensor with 12 bits resolution by calling DS18B20_Init() and specifiying the sensor resolution as a parameter inside this function.

  DS18B20_Init(DS18B20_Resolution_12bits);

Read and Display Sensor Data

Inside the infinite while loop, we start accessing the temperature readings from the DS18B20 sensor and display them on the OLED screen.

  while (1)
  {
	  DS18B20_ReadAll();
      DS18B20_StartAll();
		uint8_t ROM_tmp[8];
		uint8_t i;

	for(i = 0; i < DS18B20_Quantity(); i++)
		{
			if(DS18B20_GetTemperature(i, &temperature))
			{
				DS18B20_GetROM(i, ROM_tmp);
				memset(string, 0, sizeof(string));
				sprintf(string, "%.2f C", temperature);
				SSD1306_GotoXY (20, 0);
				SSD1306_Puts ("Temperature", &Font_7x10, 1);
				SSD1306_GotoXY (25, 30);
				SSD1306_Puts (string, &Font_11x18, 1);
				SSD1306_UpdateScreen();
			}
		}
		HAL_Delay(1000);
  }

To start reading the DS18B20 sensor, we first call the function DS18B20_ReadAll(). This reads the temperatures of all the connected sensors in a loop. Then we call DS18B20_Start(). The DS18B20_Start() function resets the onewire bus, skips the ROM command and starts the conversion on all the sensors.

DS18B20_ReadAll();
DS18B20_StartAll();

After that we run a for loop to obtain the temperature readings using DS18B20_GetTemperature() and display them on the OLED. In our case, the loop runs once as we are using a single DS18B20 sensor.

If the DS18B20_GetTemperature() Then we convert the float temperature variable to string consisting of reading and its unit 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 (20,0) as the parameter to display the text ‘Temperature’. We use SSD1306_Puts() function to display the temperature readings along with its unit on the screen at starting x-axis and y-axis at (25,30). This function takes in three parameters which is the string to be displayed, the font name and the color of the text. Additionally, call SSD1306_UpdateScreen() to display the text on the screen. The readings will update on the screen after every second.


	for(i = 0; i < DS18B20_Quantity(); i++)
		{
			if(DS18B20_GetTemperature(i, &temperature))
			{
				DS18B20_GetROM(i, ROM_tmp);
				memset(string, 0, sizeof(string));
				sprintf(string, "%.2f C", temperature);
				SSD1306_GotoXY (20, 0);
				SSD1306_Puts ("Temperature", &Font_7x10, 1);
				SSD1306_GotoXY (25, 30);
				SSD1306_Puts (string, &Font_11x18, 1);
				SSD1306_UpdateScreen();
			}
		}
		HAL_Delay(1000);
  }

main.c file

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

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
extern I2C_HandleTypeDef hi2c1;
TIM_HandleTypeDef htim1;
#include "fonts.h"
#include "ssd1306.h"
#include <stdio.h>
#include "onewire.h"
#include "ds18b20.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */


/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
I2C_HandleTypeDef hi2c1;

TIM_HandleTypeDef htim1;

/* USER CODE BEGIN PV */
float temperature;
char string[64];

/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_I2C1_Init(void);
static void MX_TIM1_Init(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_I2C1_Init();
  MX_TIM1_Init();
  /* USER CODE BEGIN 2 */
  HAL_TIM_Base_Start(&htim1);
  DS18B20_Init(DS18B20_Resolution_12bits);
  uint8_t res = SSD1306_Init();

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  DS18B20_ReadAll();

	        DS18B20_StartAll();

	  		uint8_t ROM_tmp[8];
	  		uint8_t i;

	  	for(i = 0; i < DS18B20_Quantity(); i++)
	  		{
	  			if(DS18B20_GetTemperature(i, &temperature))
	  			{
	  				DS18B20_GetROM(i, ROM_tmp);
	  				memset(string, 0, sizeof(string));
	  				sprintf(string, "%.2f C", temperature);
	  				SSD1306_GotoXY (20, 0);
	  				SSD1306_Puts ("Temperature", &Font_7x10, 1);
	  				SSD1306_GotoXY (25, 30);
	  				SSD1306_Puts (string, &Font_11x18, 1);
	  				SSD1306_UpdateScreen();
	  			}
	  		}
	  		HAL_Delay(1000);


    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @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_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  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_2) != 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 TIM1 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM1_Init(void)
{

  /* USER CODE BEGIN TIM1_Init 0 */

  /* USER CODE END TIM1_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  /* USER CODE BEGIN TIM1_Init 1 */

  /* USER CODE END TIM1_Init 1 */
  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 63;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 65535;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM1_Init 2 */

  /* USER CODE END TIM1_Init 2 */

}

/**
  * @brief GPIO Initialization Function
  * @param None
  * @retval None
  */
static void MX_GPIO_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct = {0};
/* USER CODE BEGIN MX_GPIO_Init_1 */
/* USER CODE END MX_GPIO_Init_1 */

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

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(DS18B20_Pin_GPIO_Port, DS18B20_Pin_Pin, GPIO_PIN_RESET);

  /*Configure GPIO pin : DS18B20_Pin_Pin */
  GPIO_InitStruct.Pin = DS18B20_Pin_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(DS18B20_Pin_GPIO_Port, &GPIO_InitStruct);

/* USER CODE BEGIN MX_GPIO_Init_2 */
/* USER CODE END MX_GPIO_Init_2 */
}

/* 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.

Demonstration

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.

STM32 Serial Data Print Run Project 2

Otherwise, press the RESET button on your STM32

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

DS18B20 Sensor with STM32 Nucleo using STM32CubeIDE

Watch the video below:

You may also like to read:

Leave a Comment