stm32bringup/dht11.c

94 lines
2.8 KiB
C

/* dht11.c -- DHT11 humidity and temperature sensor reading */
/* Copyright (c) 2020-2021 Renaud Fivet */
#include "dht11.h" /* implements DHT11 API */
#include "system.h" /* usleep(), gpioa_*() */
#define DIO 13
#define dht11_input() gpioa_input( DIO)
#define dht11_output() gpioa_output( DIO)
#define dht11_bread() gpioa_read( DIO)
#define MAX_RETRIES 200 /* at 48 MHz, 160 retries for 80 us HIGH */
#define is_not_LOW( a) a != LOW
#define is_not_HIGH( a) a == LOW
#define wait_level( lvl) \
retries = MAX_RETRIES ; \
while( is_not_##lvl( dht11_bread())) \
if( retries-- == 0) \
return DHT11_FAIL_TOUT
/* 5 .. 95 %RH, -20 .. 60 C */
unsigned char dht11_humid ; /* 5 .. 95 %RH */
signed char dht11_tempc ; /* -20 .. 60 C */
unsigned char dht11_tempf ; /* .0 .. .9 C */
void dht11_init( void) {
/* At startup A13 is ALT DIO with Pull Up enabled */
dht11_input() ;
}
dht11_retv_t dht11_read( void) {
unsigned char values[ 5] ;
/* Host START: pulls line down for > 18ms then release line, pull-up raises to HIGH */
dht11_output() ;
usleep( 18000) ;
dht11_input() ;
/* DHT START: takes line, 80us low then 80us high */
int retries ; /* retry counter */
wait_level( LOW) ; /* HIGH -> LOW, starts 80us low */
wait_level( HIGH) ; /* LOW -> HIGH, ends 80us low, starts 80us high */
/* DHT transmits 40 bits, high bit first
* 0 coded as 50us low then 26~28us high
* 1 coded as 50us low then 70us high
*/
wait_level( LOW) ; /* HIGH -> LOW, ends 80us high, starts 50us low */
int threshold = (MAX_RETRIES + retries) / 2 ;
unsigned char sum = 0 ;
unsigned char v = 0 ;
for( int idx = 0 ; idx <= 4 ; idx += 1) {
sum += v ;
v = 0 ;
for( unsigned char curbit = 128 ; curbit ; curbit >>= 1) {
/* Measure duration of HIGH level */
wait_level( HIGH) ; /* LOW -> HIGH, ends 50us low, starts timed high */
wait_level( LOW) ; /* HIGH -> LOW, timed high ends, starts 50us low */
/* Set bit based on measured HIGH duration */
if( retries < threshold) /* 0 == 26~28us, 1 == 70us */
v |= curbit ;
}
values[ idx] = v ;
}
/* DHT STOP: releases line after 50us, pull-up raises to HIGH */
wait_level( HIGH) ; /* LOW -> HIGH, ends 50us low, DHT has released the line */
if( sum != values[ 4])
return DHT11_FAIL_CKSUM ;
dht11_humid = values[ 0] ;
dht11_tempc = values[ 2] ;
dht11_tempf = values[ 3] ;
if( dht11_tempf & 0x80) {
dht11_tempc *= -1 ;
dht11_tempf = 10 - ( dht11_tempf & 0x7F) ;
if( dht11_tempf == 10) {
dht11_tempc -= 1 ;
dht11_tempf = 0 ;
}
}
return DHT11_SUCCESS ;
}
/* end of file dht11.c */