DS18B20 digital thermometer

This commit is contained in:
Renaud 2020-12-19 08:39:18 +08:00
parent d2617fbb0b
commit f1f238abf8
4 changed files with 223 additions and 1 deletions

View File

@ -37,7 +37,8 @@ PROJECT = f030f4
#SRCS = startup.c uplow.2.c hello.c
#SRCS = startup.c clocks.c uptime.c
#SRCS = startup.txeie.c txeie.c uptime.c
SRCS = startup.txeie.c gpioa.c dht11main.c dht11.c
#SRCS = startup.txeie.c gpioa.c dht11main.c dht11.c
SRCS = startup.txeie.c gpioa.c ds18b20main.c ds18b20.c
OBJS = $(SRCS:.c=.o)
LIBOBJS = printf.o putchar.o puts.o
CPU = -mthumb -mcpu=cortex-m0

168
ds18b20.c Normal file
View File

@ -0,0 +1,168 @@
/* ds18b20.c -- 1-Wire digital thermometer */
/* Copyright (c) 2020 Renaud Fivet */
#include "ds18b20.h" /* implements DS18B20 API */
#include "system.h" /* gpioa_(), usleep() */
#define DIO 13
#define input() gpioa_input( DIO)
#define output() gpioa_output( DIO)
#define bread() gpioa_read( DIO)
#define MAX_RETRIES 999
#define wait_level( lvl) \
retries = MAX_RETRIES ; \
while( bread() != lvl) \
if( retries-- == 0) \
return DS18B20_FAIL_TOUT
void ds18b20_init( void) {
input() ; /* Wire floating, HIGH by pull-up */
}
static ds18b20_retv_t initialization() {
/* Reset */
output() ; /* Wire LOW */
usleep( 480) ;
input() ; /* Wire floating, HIGH by pull-up */
/* Presence */
int retries ;
wait_level( HIGH) ; /* Pull-up LOW -> HIGH, T1 */
wait_level( LOW) ; /* DS18B20 asserts line to LOW, T2, T2 - T1 = 15~60us */
wait_level( HIGH) ; /* DS18B20 releases lines, Pull-up LOW -> HIGH, T3
** T3 - T2 = 60~240us */
usleep( 405) ; /* 480 = 405 + 15 + 60 */
return DS18B20_SUCCESS ;
}
static void write( unsigned char uc) {
/* Transmit byte, least significant bit first */
for( unsigned char curbit = 1 ; curbit ; curbit <<= 1) {
/* Transmit a bit takes 60us + 1us between transmit */
/* Write 1: <15us LOW */
/* Write 0: 60us LOW */
unsigned t = uc & curbit ? 13 : 60 ;
output() ; /* Wire LOW */
usleep( t) ;
input() ; /* Wire floating, HIGH by pull-up */
usleep( 61 - t) ;
}
}
static iolvl_t poll( void) {
output() ; /* Wire LOW */
usleep( 1) ;
input() ; /* Wire floating, HIGH by pull-up */
usleep( 5) ;
iolvl_t bit = bread() ;
usleep( 55) ;
return bit ;
}
static unsigned char read( unsigned char *p, int size) {
unsigned char crc = 0 ;
while( size--) {
/* Receive byte, least significant bit first */
unsigned char uc = 0 ;
for( unsigned char curbit = 1 ; curbit ; curbit <<= 1) {
/* read bit */
int v = poll() ;
if( v)
uc |= curbit ;
/* update CRC */
v ^= crc ;
crc >>= 1 ;
if( v & 1)
crc ^= 0x119 >> 1 ; /* reverse POLY = x^8 + x^5 + x^4 + 1 */
}
/* store byte */
*p++ = uc ;
}
return crc ;
}
static ds18b20_retv_t read_scratchpad( unsigned char scratchpad[]) {
ds18b20_retv_t ret = initialization() ;
if( ret != DS18B20_SUCCESS)
return ret ;
write( 0xCC) ; /* Skip ROM */
write( 0xBE) ; /* Read Scratchpad */
return read( scratchpad, 9) ? DS18B20_FAIL_CRC : DS18B20_SUCCESS ;
}
ds18b20_retv_t ds18b20_convert( void) {
ds18b20_retv_t ret ;
ret = initialization() ;
if( ret != DS18B20_SUCCESS)
return ret ;
write( 0xCC) ; /* Skip ROM */
write( 0x44) ; /* Convert T */
return DS18B20_SUCCESS ;
}
ds18b20_retv_t ds18b20_fetch( short *deciCtemp) { /* -550~1250 = -55.0~125.0 C */
ds18b20_retv_t ret ;
unsigned char vals[ 9] ; /* scratchpad */
ret = read_scratchpad( vals) ;
if( ret != DS18B20_SUCCESS)
return ret ;
*deciCtemp = *((short *) vals) * 10 / 16 ;
return DS18B20_SUCCESS ;
}
ds18b20_retv_t ds18b20_read( short *deciCtemp) { /* -550~1250 = -55.0~125.0 C */
ds18b20_retv_t ret ;
ret = ds18b20_convert() ;
if( ret != DS18B20_SUCCESS)
return ret ;
do
usleep( 4000) ;
while( poll() == LOW) ; /* up to 93.75ms for 9 bits, 750ms for 12 bits */
return ds18b20_fetch( deciCtemp) ;
}
ds18b20_retv_t ds18b20_resolution( unsigned res) { /* 9..12 bits */
ds18b20_retv_t ret ;
unsigned char vals[ 9] ; /* scratchpad */
unsigned char curres ;
/* read scratchpad */
ret = read_scratchpad( vals) ;
if( ret != DS18B20_SUCCESS)
return ret ;
/* update resolution if current value is different than requested */
res = (res - 9) & 3 ;
curres = vals[ 4] >> 5 ;
if( curres != res) {
vals[ 4] = (vals[ 4] & 0x1F) | (res << 5) ;
ret = initialization() ;
if( ret != DS18B20_SUCCESS)
return ret ;
write( 0xCC) ; /* Skip ROM */
write( 0x4E) ; /* Write Scratchpad */
write( vals[ 2]) ;
write( vals[ 3]) ;
write( vals[ 4]) ;
}
return DS18B20_SUCCESS ;
}
/* end of ds18b20.c */

16
ds18b20.h Normal file
View File

@ -0,0 +1,16 @@
/* ds18b20.h -- 1-Wire temperature sensor */
/* Copyright (c) 2020 Renaud Fivet */
typedef enum {
DS18B20_SUCCESS,
DS18B20_FAIL_TOUT,
DS18B20_FAIL_CRC
} ds18b20_retv_t ;
void ds18b20_init( void) ;
ds18b20_retv_t ds18b20_resolution( unsigned res) ; /* 9..12 bits */
ds18b20_retv_t ds18b20_convert( void) ;
ds18b20_retv_t ds18b20_fetch( short *deciCtemp) ;/* -550~1250 = -55.0~125.0 C */
ds18b20_retv_t ds18b20_read( short *deciCtemp) ; /* -550~1250 = -55.0~125.0 C */
/* end of ds18b20.h */

37
ds18b20main.c Normal file
View File

@ -0,0 +1,37 @@
/* ds18b20main.c -- sample temperature using 1-Wire temperature sensor */
/* Copyright (c) 2020 Renaud Fivet */
#include <stdio.h>
#include "system.h" /* uptime */
#include "ds18b20.h" /* ds18b20_() */
int main( void) {
unsigned last = 0 ;
ds18b20_init() ;
ds18b20_resolution( 12) ; /* Set highest resolution: 12 bits */
ds18b20_convert() ; /* start temperature conversion */
for( ;;)
if( last == uptime)
yield() ;
else {
short val ;
last = uptime ;
switch( ds18b20_fetch( &val)) {
case DS18B20_SUCCESS:
printf( "%i.%i\n", val / 10, val % 10) ;
break ;
case DS18B20_FAIL_TOUT:
puts( "Timeout") ;
break ;
case DS18B20_FAIL_CRC:
puts( "CRC Error") ;
}
ds18b20_convert() ; /* start temperature conversion */
}
}
/* end of ds18b20main.c */