Skip to content

Instantly share code, notes, and snippets.

@HTD
Last active May 17, 2022 20:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save HTD/07f8ecd36f533382cddf814d2b44b219 to your computer and use it in GitHub Desktop.
Save HTD/07f8ecd36f533382cddf814d2b44b219 to your computer and use it in GitHub Desktop.
DS18B20 driver for STM32
/**
* DS18B20 driver.
*/
#include <string.h>
#include "ds18b20.h"
/**
* Reads the address of the only DS18B20 connected to the configured USART.
* @param rom_code A pointer to the 8-byte array containing the address.
* @retval HAL status.
*/
HAL_StatusTypeDef ds18b20_read_address(uint8_t* rom_code)
{
uint8_t crc;
HAL_StatusTypeDef status;
status = wire_reset();
if (status != HAL_OK) return status;
wire_write(DS18B20_READ_ROM);
for (int i = 0; i < DS18B20_ROM_CODE_SIZE; i++) rom_code[i] = wire_read();
crc = wire_crc(rom_code, DS18B20_ROM_CODE_SIZE - 1);
return rom_code[DS18B20_ROM_CODE_SIZE - 1] == crc ? HAL_OK : HAL_ERROR;
}
/**
* Sends a command to the DS18B20 connected to the configured USART.
* @param rom_code A pointer to the 8-byte array containing the address.
* @param cmd The command to send.
* @retval HAL status.
*/
static HAL_StatusTypeDef send_cmd(const uint8_t* rom_code, uint8_t cmd)
{
if (wire_reset() != HAL_OK) return HAL_ERROR;
if (!rom_code)
wire_write(DS18B20_SKIP_ROM);
else
{
wire_write(DS18B20_MATCH_ROM);
for (int i = 0; i < DS18B20_ROM_CODE_SIZE; i++) wire_write(rom_code[i]);
}
wire_write(cmd);
return HAL_OK;
}
/**
* Starts the measurement.
* @param rom_code A pointer to the 8-byte array containing the address.
* @retval HAL status.
*/
HAL_StatusTypeDef ds18b20_start_measure(const uint8_t* rom_code)
{
return send_cmd(rom_code, DS18B20_CONVERT_T);
}
/**
* Reads the DS18B20 scratchpad content.
* @param rom_code A pointer to the 8-byte array containing the address.
* @param scratchpad A pointer to the 9-byte scratchpad array.
* @retval HAL status.
*/
static HAL_StatusTypeDef ds18b20_read_scratchpad(const uint8_t* rom_code, uint8_t* scratchpad)
{
uint8_t crc;
if (send_cmd(rom_code, DS18B20_READ_SCRATCHPAD) != HAL_OK) return HAL_ERROR;
for (int i = 0; i < DS18B20_SCRATCHPAD_SIZE; i++) scratchpad[i] = wire_read();
crc = wire_crc(scratchpad, DS18B20_SCRATCHPAD_SIZE - 1);
return scratchpad[DS18B20_SCRATCHPAD_SIZE - 1] == crc ? HAL_OK : HAL_ERROR;
}
/**
* Gets the measured temperature from the DS18B20 scratchpad.
* @param rom_code A pointer to the 8-byte array containing the address.
* @retval Temperature in °C. -273 for invalid reading. 85 is initial scratchpad value before the first measurement.
*/
float ds18b20_get_temp(const uint8_t* rom_code)
{
uint8_t scratchpad[DS18B20_SCRATCHPAD_SIZE];
int16_t temp;
if (ds18b20_read_scratchpad(rom_code, scratchpad) != HAL_OK) return -273.0f;
memcpy(&temp, &scratchpad[0], sizeof(temp));
return temp / 16.0f;
}
/**
* DS18B20 driver - header.
*/
#pragma once
#include "wire.h"
#define DS18B20_ROM_CODE_SIZE 8
#define DS18B20_SCRATCHPAD_SIZE 9
#define DS18B20_READ_ROM 0x33
#define DS18B20_MATCH_ROM 0x55
#define DS18B20_SKIP_ROM 0xCC
#define DS18B20_CONVERT_T 0x44
#define DS18B20_READ_SCRATCHPAD 0xBE
HAL_StatusTypeDef ds18b20_read_address(uint8_t* rom_code);
HAL_StatusTypeDef ds18b20_start_measure(const uint8_t* rom_code);
float ds18b20_get_temp(const uint8_t* rom_code);
/**
* HAL USART helper.
*/
#include "usart.h"
/**
* Sets the USART baud rate.
* @param baudrate Baud rate value in bits per seconds.
* @retval HAL status.
*/
HAL_StatusTypeDef usart_set_baudrate(uint32_t baudrate)
{
USART.Init.BaudRate = baudrate;
return HAL_HalfDuplex_Init(&USART);
}
/**
* Transmits data over the USART.
* @param pData A pointer to the data.
* @param size Data size in bytes.
* @retval HAL status.
*/
HAL_StatusTypeDef usart_tx(void* pData, uint16_t size)
{
return HAL_UART_Transmit(&USART, pData, size, USART_TIMEOUT);
}
/**
* Receives data over the USART.
* @param pData A pointer to the data.
* @param size Data size in bytes.
* @retval HAL status.
*/
HAL_StatusTypeDef usart_rx(void* pData, uint16_t size)
{
return HAL_UART_Receive(&USART, pData, size, USART_TIMEOUT);
}
/**
* HAL USART helper - header.
*/
#pragma once
#include <stdint.h>
#include "stm32l4xx_hal.h" // insert your specific include from main.h.
#define USART huart3 // DEFAULT USART HANDLE
extern UART_HandleTypeDef USART;
#define USART_TIMEOUT 2000
HAL_StatusTypeDef usart_set_baudrate(uint32_t baudrate);
HAL_StatusTypeDef usart_tx(void* pData, uint16_t size);
HAL_StatusTypeDef usart_rx(void* pData, uint16_t size);
/**
* One wire protocol handler.
*/
#include "wire.h"
/**
* Resets the wire for the pin specified.
*/
HAL_StatusTypeDef wire_reset()
{
uint8_t data_out = 0xf0;
uint8_t data_in = 0x00;
HAL_StatusTypeDef status;
status = usart_set_baudrate(WIRE_SLOW);
if (status != HAL_OK) return status;
status = usart_tx(&data_out, 1);
if (status != HAL_OK) return status;
status = usart_rx(&data_in, 1);
if (status != HAL_OK) return status;
status = usart_set_baudrate(WIRE_FAST);
if (status != HAL_OK) return status;
return data_in != 0x00 ? HAL_OK : HAL_ERROR;
}
/**
* Reads one bit from the wire.
* @retval The bit read from the wire.
*/
static int read_bit()
{
uint8_t data_out = 0xff;
uint8_t data_in = 0x00;
usart_tx(&data_out, 1);
usart_rx(&data_in, 1);
return data_in & 1;
}
/**
* Reads one byte from the wire.
* @retval The byte read from the wire.
*/
uint8_t wire_read()
{
uint8_t value = 0;
for (int i = 0; i < 8; i++)
{
value >>= 1;
if (read_bit()) value |= 0x80;
}
return value;
}
/**
* Writes one bit to the wire.
* @param value A bit to write to the wire.
*/
static void write_bit(int value)
{
uint8_t data_out = value ? 0xff : 0x00;
usart_tx(&data_out, 1);
}
/**
* Writes one byte to the wire.
* @param byte A byte to write to the wire.
*/
void wire_write(uint8_t byte)
{
for (int i = 0; i < 8; i++) {
write_bit(byte & 0x01);
byte >>= 1;
}
}
/**
* Calculates CRC for 1 byte.
* @param crc Current value.
* @param byte Byte to add.
* @retval Calculated CRC.
*/
static uint8_t byte_crc(uint8_t crc, uint8_t byte)
{
for (int i = 0; i < 8; i++) {
uint8_t b = crc ^ byte;
crc >>= 1;
if (b & 0x01) crc ^= 0x8c;
byte >>= 1;
}
return crc;
}
/**
* Calculates CRC byte for some data.
* @param pData Address.
* @param size Length.
* @retval Calculated CRC.
*/
uint8_t wire_crc(const void* pData, int size)
{
int i;
uint8_t crc = 0;
for (i = 0; i < size; i++) crc = byte_crc(crc, ((uint8_t*)pData)[i]);
return crc;
}
/**
* One wire protocol handler - header.
*/
#pragma once
#include <stdint.h>
#include "stm32h7xx_hal.h"
#include "usart.h"
#define WIRE_SLOW 9600
#define WIRE_FAST 115200
HAL_StatusTypeDef wire_reset();
uint8_t wire_read();
void wire_write(uint8_t byte);
uint8_t wire_crc(const void* data, int len);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment