DS18B20 and STM32
I have covered few temperature sensors in the past eg- LM35, DHT11, DHT22 and also the internal temperature sensor of the STM32 itself. Today in this tutorial we will see how to interface DS18B20 temperature sensor with STM32.
The DS18B20 digital thermometer provides 9-bit to 12-bit Celsius temperature measurements and has an alarm function with non-volatile user-programmable upper and lower trigger points. Like DHT11 and DHT22, DS18B20 also communicates over a 1-Wire bus that by definition requires only one data line for communication with the micro controller. Let’s see how to program a DS18B20 temperature sensor using STM32.
HOW TO
NOTE:- This code works with STM32CUBEIDE and it uses TIMER to create delay in microsecond. If you don’t know how to do that, go to https://controllerstech.com/create-1-microsecond-delay-stm32/ .
I am going to skip the Cube mx setup process as it’s usual one only. I am using pin PA1 as the data pin for the sensor and controller is running at it’s maximum frequency.
void delay (uint32_t us)
{
__HAL_TIM_SET_COUNTER(&htim6,0);
while ((__HAL_TIM_GET_COUNTER(&htim6))<us);
}
INITIALIZE
- In order for the sensor to work, we need to initialize it every time.
- According to the datasheet, the initialization is done by pulling the data pin LOW for 480 us and than reading the pin for the presence pulse sent by sensor. Here is the function for that
uint8_t DS18B20_Start (void)
{
uint8_t Response = 0;
Set_Pin_Output(DS18B20_PORT, DS18B20_PIN); // set the pin as output
HAL_GPIO_WritePin (DS18B20_PORT, DS18B20_PIN, 0); // pull the pin low
delay (480); // delay according to datasheet
Set_Pin_Input(DS18B20_PORT, DS18B20_PIN); // set the pin as input
delay (80); // delay according to datasheet
if (!(HAL_GPIO_ReadPin (DS18B20_PORT, DS18B20_PIN))) Response = 1; // if the pin is low i.e the presence pulse is detected
else Response = -1;
delay (400); // 480 us delay totally.
return Response;
}
WRITE
- To write a BIT to the sensor, we need to perform some operation on the data line.
- To generate a Write 1, after pulling the line low, the master must release the line within 15µs.
- When the bus is released, the 5kΩ pullup resistor will pull the bus high.
- To generate a Write 0 time slot, after pulling the line low, the master must continue to hold the line low for the duration of the time slot (at least 60µs).
void DS18B20_Write (uint8_t data)
{
Set_Pin_Output(DS18B20_PORT, DS18B20_PIN); // set as output
for (int i=0; i<8; i++)
{
if ((data & (1<<i))!=0) // if the bit is high
{
// write 1
Set_Pin_Output(DS18B20_PORT, DS18B20_PIN); // set as output
HAL_GPIO_WritePin (DS18B20_PORT, DS18B20_PIN, 0); // pull the pin LOW
delay (1); // wait for 1 us
Set_Pin_Input(DS18B20_PORT, DS18B20_PIN); // set as input
delay (50); // wait for 60 us
}
else // if the bit is low
{
// write 0
Set_Pin_Output(DS18B20_PORT, DS18B20_PIN);
HAL_GPIO_WritePin (DS18B20_PORT, DS18B20_PIN, 0); // pull the pin LOW
delay (50); // wait for 60 us
Set_Pin_Input(DS18B20_PORT, DS18B20_PIN);
}
}
}
READ
- A read time slot is initiated by the master device pulling the 1-Wire bus low for a minimum of 1µs and then releasing the bus.
- After the master initiates the read time slot, the DS18B20 will begin transmitting a 1 or 0 on bus.
- It transmits a 1 by leaving the bus high and transmits a 0 by pulling the bus low.
- When transmitting a 0, the sensor will release the bus by the end of the time slot, and the bus will be pulled back to its high idle state by the pull-up resister.
uint8_t read (void)
{
uint8_t value=0;
gpio_set_input ();
for (int i=0;i<8;i++)
{
gpio_set_output (); // set as output
HAL_GPIO_WritePin (GPIOA, GPIO_PIN_1, 0); // pull the data pin LOW
delay (2); // wait for 2 us
gpio_set_input (); // set as input
if (HAL_GPIO_ReadPin (GPIOA, GPIO_PIN_1)) // if the pin is HIGH
{
value |= 1<<i; // read = 1
}
delay (60); // wait for 60 us
}
return value;
}
Main Function
The following are the STEPS, we need to follow to read the temperature from DS18B20
Presence = DS18B20_Start ();
HAL_Delay (1);
DS18B20_Write (0xCC); // skip ROM
DS18B20_Write (0x44); // convert t
HAL_Delay (800);
Presence = DS18B20_Start ();
HAL_Delay(1);
DS18B20_Write (0xCC); // skip ROM
DS18B20_Write (0xBE); // Read Scratch-pad
Temp_byte1 = DS18B20_Read();
Temp_byte2 = DS18B20_Read();