Updated and tidied up file, also can now have multiple sensors (but each on an individual bus)

This commit is contained in:
2025-04-19 16:13:47 +00:00
parent 620c7d29e1
commit c94933e264

144
ds18b20.c
View File

@ -1,20 +1,19 @@
// Lots of the info came from: https://teslabs.com/openplayer/docs/docs/other/ds18b20_pre1.pdf and https://www.circuitbread.com/tutorials/embedded-c-programming-with-the-pic18f14k50-12-digital-thermometer
// Also needed to use a scope to check the timings were reasonably accurate
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/rcc.h>
#include <libopencm3/cm3/systick.h>
#include <stdint.h>
#include <string.h>
#include "ds18b20.h"
//#include "delay.h"
#include "misc.h"
// Define GPIO port and pin for the DS18B20
#define DS18B20_PORT GPIOB
#define DS18B20_PIN GPIO1
// Delay function
void ds18b20_delay_us(uint32_t us) {
for (uint32_t i = 0; i < (us * 3); i++) {
__asm__("nop");
}
for (uint32_t i = 0; i < (us * 3); i++) {
__asm__("nop");
}
}
void ds18b20_delay_us_nop() {
@ -23,95 +22,75 @@ void ds18b20_delay_us_nop() {
}
// OneWire low-level functions
static void ds18b20_pin_mode_output(void) {
gpio_mode_setup(DS18B20_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, DS18B20_PIN);
static void ds18b20_pin_mode_output(uint32_t ds18b20_port, uint32_t ds18b20_pin) {
gpio_mode_setup(ds18b20_port, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, ds18b20_pin);
}
static void ds18b20_pin_mode_input(void) {
gpio_mode_setup(DS18B20_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, DS18B20_PIN);
static void ds18b20_pin_mode_input(uint32_t ds18b20_port, uint32_t ds18b20_pin) {
gpio_mode_setup(ds18b20_port, GPIO_MODE_INPUT, GPIO_PUPD_NONE, ds18b20_pin);
}
static void ds18b20_write_bit(uint8_t bit) {
ds18b20_pin_mode_output();
gpio_clear(DS18B20_PORT, DS18B20_PIN);
static void ds18b20_write_bit(uint32_t ds18b20_port, uint32_t ds18b20_pin, uint8_t bit) {
ds18b20_pin_mode_output(ds18b20_port, ds18b20_pin);
gpio_clear(ds18b20_port, ds18b20_pin);
if (bit) {
delay_us(1); // Short low pulse for '1'
gpio_set(DS18B20_PORT, DS18B20_PIN);
ds18b20_pin_mode_input();
gpio_set(ds18b20_port, ds18b20_pin);
ds18b20_pin_mode_input(ds18b20_port, ds18b20_pin);
}
delay_us(60);
ds18b20_pin_mode_input();
ds18b20_pin_mode_input(ds18b20_port, ds18b20_pin);
delay_us(10);
}
static uint8_t ds18b20_read_bit(void) {
static uint8_t ds18b20_read_bit(uint32_t ds18b20_port, uint32_t ds18b20_pin) {
uint8_t bit;
ds18b20_pin_mode_output();
gpio_clear(DS18B20_PORT, DS18B20_PIN);
ds18b20_pin_mode_output(ds18b20_port, ds18b20_pin);
gpio_clear(ds18b20_port, ds18b20_pin);
// ds18b20_delay_us(1);
// gpio_set(DS18B20_PORT, DS18B20_PIN);
// gpio_set(ds18b20_port, ds18b20_pin);
ds18b20_pin_mode_input();
ds18b20_pin_mode_input(ds18b20_port, ds18b20_pin);
ds18b20_delay_us(10);
bit = gpio_get(DS18B20_PORT, DS18B20_PIN);
bit = gpio_get(ds18b20_port, ds18b20_pin);
ds18b20_delay_us(50);
return bit;
}
uint8_t ds18b20_reset(void) {
uint8_t ds18b20_reset(uint32_t ds18b20_port, uint32_t ds18b20_pin) {
uint8_t presence;
ds18b20_pin_mode_output();
gpio_clear(DS18B20_PORT, DS18B20_PIN);
ds18b20_pin_mode_output(ds18b20_port, ds18b20_pin);
gpio_clear(ds18b20_port, ds18b20_pin);
ds18b20_delay_us(960);
ds18b20_pin_mode_input();
ds18b20_pin_mode_input(ds18b20_port, ds18b20_pin);
ds18b20_delay_us(120);
presence = gpio_get(DS18B20_PORT, DS18B20_PIN);
presence = gpio_get(ds18b20_port, ds18b20_pin);
ds18b20_delay_us(840);
return presence == 0; // If presence is detected, return 1
}
void ds18b20_write_byte(uint8_t byte) {
void ds18b20_write_byte(uint32_t ds18b20_port, uint32_t ds18b20_pin, uint8_t byte) {
for (uint8_t i = 0; i < 8; i++) {
ds18b20_write_bit(byte & 0x01);
ds18b20_write_bit(ds18b20_port, ds18b20_pin, byte & 0x01);
byte >>= 1;
}
ds18b20_pin_mode_input();
ds18b20_pin_mode_input(ds18b20_port, ds18b20_pin);
}
/*
uint8_t ds18b20_read_byte(void) {
uint8_t byte = 0;
for (uint8_t i = 0; i < 8; i++) {
byte |= (ds18b20_read_bit() << i);
}
return byte;
}
*/
/*
uint8_t ds18b20_read_byte(void) {
uint8_t i=8, n=0;
while(i--){
n>>=1;
n |= (ds18b20_read_bit()<<7);
}
return n;
}
*/
uint8_t ds18b20_read_byte(void)
uint8_t ds18b20_read_byte(uint32_t ds18b20_port, uint32_t ds18b20_pin)
{
uint8_t byte = 0; //Value to be returned
for (uint8_t i = 0; i< 8; i++)//Loop to read the whole byte
{
byte >>= 1; //Shift the byte at one bit to the right
if (ds18b20_read_bit()) //If 1 has been read
if (ds18b20_read_bit(ds18b20_port, ds18b20_pin)) //If 1 has been read
byte |= 0x80; //Then add it to the byte
}
return (byte);
@ -119,49 +98,36 @@ uint8_t ds18b20_read_byte(void)
// DS18B20 high-level functions
void ds18b20_start_conversion(void) {
ds18b20_reset();
void ds18b20_start_conversion(uint32_t ds18b20_port, uint32_t ds18b20_pin) {
ds18b20_reset(ds18b20_port, ds18b20_pin);
delay_ms(1);
ds18b20_write_byte(0xCC); // Skip ROM
ds18b20_write_byte(ds18b20_port, ds18b20_pin, 0xCC); // Skip ROM
delay_ms(1);
ds18b20_write_byte(0x44); // Start conversion
ds18b20_write_byte(ds18b20_port, ds18b20_pin, 0x44); // Start conversion
delay_ms(1);
}
int16_t ds18b20_read_temperature(void) {
uint8_t temp_lsb, temp_msb;
uint8_t temperature[2];
int8_t digit;
uint16_t decimal;
int16_t ds18b20_read_raw_temperature(uint32_t ds18b20_port, uint32_t ds18b20_pin) {
uint8_t scratchpad[10];
int16_t temp;
ds18b20_reset();
ds18b20_write_byte(0xCC); // Skip ROM
ds18b20_write_byte(0xBE); // Read scratchpad
temp = ds18b20_read_byte();
temp |= (uint16_t)(ds18b20_read_byte() << 8);
int16_t temp_raw;
ds18b20_reset(ds18b20_port, ds18b20_pin);
delay_ms(1);
ds18b20_write_byte(ds18b20_port, ds18b20_pin, 0xCC); // Skip ROM
delay_ms(1);
ds18b20_write_byte(ds18b20_port, ds18b20_pin, 0xBE); // Read Scratchpad
delay_ms(1);
// temperature[0] = ds18b20_read_byte();
// temperature[1] = ds18b20_read_byte();
ds18b20_reset();
// temp = (temp_msb << 8) | temp_lsb;
// Read all 9 bytes of the scratchpad
for (int i = 0; i <= 9; i++) {
scratchpad[i] = ds18b20_read_byte(ds18b20_port, ds18b20_pin);
}
// digit=temperature[0]>>4;
// digit|=(temperature[1]&0x7)<<4;
//Store decimal digits
// decimal=temperature[0]&0xf;
// decimal*=625;
// Raw temperature is stored in the first two bytes
uint8_t temp_lsb = scratchpad[0];
uint8_t temp_msb = scratchpad[1];
temp_raw = (temp_msb << 8) | temp_lsb;
// temp = (digit * 1000) + decimal;
//return temp * 0.0625; // Convert to Celsius
// return temp; // Convert to Celsius
// return digit;
if (temp & 0x8000) { // Check if the sign bit (MSB) is set
temp = -(int16_t)((~temp + 1) & 0xFFFF); // Two's complement unary conversion
}
return (temp * 625) / 10;
return (temp_raw * 625) / 10; // Scale to Celsius * 1000
}