#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 voidcrc8(uint8_t b){for (uint8_t i = 0; i < 8; ++i) {if ((crc_value ^ b) & 0x80) {crc_value <<= 1;crc_value ^= 0x31;} elsecrc_value <<= 1;b <<= 1;}}/////////////////////////////////////////////////////////////////////////////static uint8_tsend(uint16_t b){crc8(b);// datafor (uint8_t i = 0; i < 8; ++i) {if (b & 0x80)sda_hi();elsesda_lo();b <<= 1;delay();scl_pulse();}// acknowledgesda_hi();delay();uint8_t ack = sda_val();scl_pulse();return ack;}static uint8_trecv_data(void){// datauint8_t b = 0;for (uint8_t i = 0; i < 8; ++i) {// data is transmitted MSB firstb <<= 1;if (sda_val())b |= 1;scl_pulse();delay();}// lo acknowledgesda_lo();delay();scl_pulse();sda_hi();delay();crc8(b);return b;}static uint8_trecv_crc(void){// datauint8_t b = 0;for (uint8_t i = 0; i < 8; ++i) {// CRC is transmitted LSB firstb >>= 1;if (sda_val())b |= 0x80;scl_pulse();delay();}// hi acknowledgesda_hi();delay();scl_pulse();delay();return b;}static voidstart(void){clrBits(PORT(SHT11_PORT), SHT11_SCL | SHT11_SDA); // SCK output low, SDA input/highsetBits(DDR(SHT11_PORT), SHT11_SCL);clrBits(DDR(SHT11_PORT), SHT11_SDA);delay();// reset communicationfor (uint8_t i = 0; i < 10; ++i) {scl_pulse();delay();}// "start" sequencescl_hi(); delay();sda_lo(); delay();scl_lo(); delay();scl_hi(); delay();sda_hi(); delay();scl_lo(); delay();}/////////////////////////////////////////////////////////////////////////////// Measurement sequence.uint8_tsht11_start_temp(void){crc_value = SHT11_LOWRES << 7; // bit-reversedstart();return send(SHT11_CMD_TEMP) == 0;}uint8_tsht11_start_humid(void){crc_value = SHT11_LOWRES << 7; // bit-reversedstart();return send(SHT11_CMD_HUMID) == 0;}uint8_tsht11_ready(void){return sda_val() == 0;}static int16_tresult(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_tsht11_result_temp(void){int16_t v = result();if (sht11_valid(v)) {#if SHT11_LOWRESv = v * 4 - 4000;#elsev -= 4000;#endif}return v;}int16_tsht11_result_humid(void){int16_t v = result();if (sht11_valid(v)) {#if SHT11_LOWRES// inspired by Werner Hoch, modified for low resolution modeconst 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 Hochconst 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.voidsht11_init(void){start();send(SHT11_CMD_RESET);_delay_ms(11);start();send(SHT11_CMD_WSTAT);send(SHT11_LOWRES);}