0,0 → 1,224 |
#include "config.h" |
#include "sht11.h" |
|
#define SHT11_CMD_TEMP 0x03 |
#define SHT11_CMD_HUMID 0x05 |
#define SHT11_CMD_WSTAT 0x06 |
#define SHT11_CMD_RSTAT 0x07 |
#define SHT11_CMD_RESET 0x1E |
|
///////////////////////////////////////////////////////////////////////////// |
// This version needs external pullups on SDA! |
///////////////////////////////////////////////////////////////////////////// |
|
static void delay(void) { _delay_us(2); } |
|
static void scl_hi(void) { setBits(PORT(SHT11_PORT), SHT11_SCL); } |
static void scl_lo(void) { clrBits(PORT(SHT11_PORT), SHT11_SCL); } |
static void sda_hi(void) { clrBits(DDR(SHT11_PORT), SHT11_SDA); } |
static void sda_lo(void) { setBits(DDR(SHT11_PORT), SHT11_SDA); } |
static void scl_pulse(void) { scl_hi(); delay(); scl_lo(); } |
static uint8_t sda_val(void) { return (PIN(SHT11_PORT) & SHT11_SDA) != 0; } |
|
///////////////////////////////////////////////////////////////////////////// |
|
static uint8_t crc_value; |
|
static void |
crc8(uint8_t b) |
{ |
for (uint8_t i = 0; i < 8; ++i) { |
if ((crc_value ^ b) & 0x80) { |
crc_value <<= 1; |
crc_value ^= 0x31; |
} else |
crc_value <<= 1; |
b <<= 1; |
} |
} |
|
///////////////////////////////////////////////////////////////////////////// |
|
static uint8_t |
send(uint16_t b) |
{ |
crc8(b); |
|
// data |
for (uint8_t i = 0; i < 8; ++i) { |
if (b & 0x80) |
sda_hi(); |
else |
sda_lo(); |
b <<= 1; |
delay(); |
scl_pulse(); |
} |
|
// acknowledge |
sda_hi(); |
delay(); |
uint8_t ack = sda_val(); |
scl_pulse(); |
return ack; |
} |
|
static uint8_t |
recv_data(void) |
{ |
// data |
uint8_t b = 0; |
for (uint8_t i = 0; i < 8; ++i) { |
// data is transmitted MSB first |
b <<= 1; |
if (sda_val()) |
b |= 1; |
scl_pulse(); |
delay(); |
} |
|
// lo acknowledge |
sda_lo(); |
delay(); |
scl_pulse(); |
sda_hi(); |
delay(); |
|
crc8(b); |
return b; |
} |
|
static uint8_t |
recv_crc(void) |
{ |
// data |
uint8_t b = 0; |
for (uint8_t i = 0; i < 8; ++i) { |
// CRC is transmitted LSB first |
b >>= 1; |
if (sda_val()) |
b |= 0x80; |
scl_pulse(); |
delay(); |
} |
|
// hi acknowledge |
sda_hi(); |
delay(); |
scl_pulse(); |
delay(); |
|
return b; |
} |
|
static void |
start(void) |
{ |
clrBits(PORT(SHT11_PORT), SHT11_SCL | SHT11_SDA); // SCK output low, SDA input/high |
setBits(DDR(SHT11_PORT), SHT11_SCL); |
clrBits(DDR(SHT11_PORT), SHT11_SDA); |
delay(); |
|
// reset communication |
for (uint8_t i = 0; i < 10; ++i) { |
scl_pulse(); |
delay(); |
} |
|
// "start" sequence |
scl_hi(); delay(); |
sda_lo(); delay(); |
scl_lo(); delay(); |
scl_hi(); delay(); |
sda_hi(); delay(); |
scl_lo(); delay(); |
} |
|
///////////////////////////////////////////////////////////////////////////// |
// Measurement sequence. |
|
uint8_t |
sht11_start_temp(void) |
{ |
crc_value = SHT11_LOWRES << 7; // bit-reversed |
start(); |
return send(SHT11_CMD_TEMP) == 0; |
} |
|
uint8_t |
sht11_start_humid(void) |
{ |
crc_value = SHT11_LOWRES << 7; // bit-reversed |
start(); |
return send(SHT11_CMD_HUMID) == 0; |
} |
|
uint8_t |
sht11_ready(void) |
{ |
return sda_val() == 0; |
} |
|
static int16_t |
result(void) |
{ |
if (!sht11_ready()) |
return SHT11_UNAVAIL; |
int16_t v = recv_data() << 8; v |= recv_data(); |
uint8_t crc = recv_crc(); |
if (crc != crc_value) |
return SHT11_CRC_FAIL; |
return v; |
} |
|
int16_t |
sht11_result_temp(void) |
{ |
int16_t v = result(); |
if (sht11_valid(v)) { |
#if SHT11_LOWRES |
v = v * 4 - 4000; |
#else |
v -= 4000; |
#endif |
} |
return v; |
} |
|
int16_t |
sht11_result_humid(void) |
{ |
int16_t v = result(); |
if (sht11_valid(v)) { |
#if SHT11_LOWRES |
// inspired by Werner Hoch, modified for low resolution mode |
const int32_t C1 = (int32_t)(-4.0 * 100); |
const int32_t C2 = (int32_t)(0.648 * 100 * (1L<<24)); |
const int32_t C3 = (int32_t)(-7.2e-4 * 100 * (1L<<24)); |
v = (int16_t)((((C3 * v + C2) >> 7) * v + (1L<<16)) >> 17) + C1; |
#else |
// inspired by Werner Hoch |
const int32_t C1 = (int32_t)(-4.0 * 100); |
const int32_t C2 = (int32_t)(0.0405 * 100 * (1L<<28)); |
const int32_t C3 = (int32_t)(-2.8e-6 * 100 * (1L<<30)); |
v = (int16_t)((((((C3 * v) >> 2) + C2) >> 11) * v + (1L<<16)) >> 17) + C1; |
#endif |
} |
return v; |
} |
|
///////////////////////////////////////////////////////////////////////////// |
// Initialize. |
|
void |
sht11_init(void) |
{ |
start(); |
send(SHT11_CMD_RESET); |
_delay_ms(11); |
|
start(); |
send(SHT11_CMD_WSTAT); |
send(SHT11_LOWRES); |
} |
|
Property changes: |
Added: svn:executable |
+* |
\ No newline at end of property |