#ifndef _SHT1X_H
#define _SHT1X_H
#include "stdbool.h"
#include "stdio.h"
#include "math.h"
#include "mgos_gpio.h"
#include "mgos_timers.h"
#include "mgos_hal.h"
#define port_data 13
#define port_sck 15
#define DATA_L mgos_gpio_write(port_data, false)
#define DATA_H mgos_gpio_write(port_data, true)
#define DATA_R mgos_gpio_read(port_data)
#define DATA_I mgos_gpio_set_mode(port_data, MGOS_GPIO_MODE_INPUT);\
mgos_gpio_set_pull(port_data, MGOS_GPIO_PULL_NONE);
#define DATA_Q mgos_gpio_set_mode(port_data, MGOS_GPIO_MODE_OUTPUT)
#define SCK_L mgos_gpio_write(port_sck, false)
#define SCK_H mgos_gpio_write(port_sck, true)
#define SCK_Q mgos_gpio_set_mode(port_sck, MGOS_GPIO_MODE_OUTPUT)
#define noACK 0
#define ACK 1
//adr command r/w
#define STATUS_REG_W 0x06 //000 0011 0
#define STATUS_REG_R 0x07 //000 0011 1
#define MEASURE_TEMP 0x03 //000 0001 1
#define MEASURE_HUM 0x05 //000 0010 1
#define RESET 0x1e //000 1111 0
typedef struct
{
float t;
float h;
float t_true;
float h_true;
unsigned char mode;
unsigned char error;
unsigned char checksum;
} SHT1x_V3;
void connectionreset(void);
char softreset(void);
void measure(SHT1x_V3 *sht1x, unsigned char mode);
void calc_sth11(SHT1x_V3 *sht1x);
#endif // _SHT1X_H
#include "sht1x_v3.h"
//----------------------------------------------------------------------------------
char read_byte(unsigned char ack)
//----------------------------------------------------------------------------------
// reads a byte form the Sensibus and gives an acknowledge in case of "ack=1"
{
unsigned char i, val = 0;
DATA_Q; // ->>
DATA_H; //release DATA-line
DATA_I; // <<-
SCK_Q; // ->>
for (i = 0x80; i > 0; i /= 2) //shift bit for masking
{
SCK_H; //clk for SENSI-BUS
if (DATA_R)
val = (val | i); //read bit
SCK_L;
}
//in case of "ack==1" pull down DATA-Line
DATA_Q; // ->>
if (ack == 1) // 拉低响应
{
DATA_L;
}
SCK_H; //clk #9 for ack
mgos_usleep(3);
SCK_L;
mgos_usleep(1);
DATA_H; //release DATA-line
return val;
}
char write_byte(unsigned char value)
//----------------------------------------------------------------------------------
// writes a byte on the Sensibus and checks the acknowledge
{
unsigned char i, error = 0;
SCK_Q; // -->
DATA_Q; // -->
for (i = 0x80; i > 0; i /= 2)
{ //shift bit for masking
if (i & value)
DATA_H; //masking value with i , write to SENSI-BUS
else
DATA_L;
mgos_usleep(1);
SCK_H; //clk for SENSI-BUS
mgos_usleep(3);
SCK_L;
mgos_usleep(1);
}
DATA_H; //release DATA-line
mgos_usleep(1);
SCK_H; //clk #9 for ack
DATA_I; // <<-
error = DATA_R; //check ack (DATA will be pulled down by SHT11)
SCK_L;
if (error >= 1)
printf("write byte error\n");
return error; //error=1 in case of no acknowledge
}
//----------------------------------------------------------------------------------
void transstart(void)
//----------------------------------------------------------------------------------
// generates a transmission start
// _____ ________
// DATA: |_______|
// ___ ___
// SCK : ___| |___| |______
{
SCK_Q; // ->>
DATA_Q; // ->>
SCK_L;
DATA_H;//Initial state
mgos_usleep(1);
SCK_H;
mgos_usleep(1);
DATA_L;
mgos_usleep(1);
SCK_L;
mgos_usleep(1);
SCK_H;
mgos_usleep(1);
DATA_H;
mgos_usleep(1);
SCK_L;
}
//----------------------------------------------------------------------------------
void connectionreset(void)
//----------------------------------------------------------------------------------
// communication reset: DATA-line=1 and at least 9 SCK cycles followed by transstart
// _____________________________________________________ ________
// DATA: |_______|
// _ _ _ _ _ _ _ _ _ ___ ___
// SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______| |___| |______
{
unsigned char i;
SCK_Q;
DATA_Q;
SCK_L;
DATA_H;//Initial state
for (i = 0; i < 9; i++) //9 SCK cycles
{
SCK_H;
SCK_L;
}
transstart(); //transmission start
}
//----------------------------------------------------------------------------------
char softreset(void)
//----------------------------------------------------------------------------------
// resets the sensor by a softreset
{
unsigned char error = 0;
connectionreset(); //reset communication
error += write_byte(RESET); //send RESET-command to sensor
return error; //error=1 in case of no response form the sensor
}
//----------------------------------------------------------------------------------
char read_statusreg(unsigned char *p_value, unsigned char *p_checksum)
//----------------------------------------------------------------------------------
// reads the status register with checksum (8-bit)
{
unsigned char error = 0;
transstart(); //transmission start
error = write_byte(STATUS_REG_R); //send command to sensor
*p_value = read_byte(ACK); //read status register (8-bit)
*p_checksum = read_byte(noACK); //read checksum (8-bit)
return error; //error=1 in case of no response form the sensor
}
//----------------------------------------------------------------------------------
char write_statusreg(unsigned char *p_value)
//----------------------------------------------------------------------------------
// writes the status register with checksum (8-bit)
{
unsigned char error = 0;
transstart(); //transmission start
error += write_byte(STATUS_REG_W); //send command to sensor
error += write_byte(*p_value); //send value of status register
return error; //error>=1 in case of no response form the sensor
}
// 回调:等待DATA
static void cb_wait_data(void *arg)
{
DATA_I; // <<-
if (!DATA_R)
{
SHT1x_V3 *sht1x = (SHT1x_V3 *)arg;
char msb = read_byte(ACK); //read the first byte (MSB)
char lsb = read_byte(ACK); //read the second byte (LSB)
float value = (float)(msb * 256 + lsb);
if (sht1x->mode == MEASURE_TEMP)
{
sht1x->t = value;
}
else if (sht1x->mode == MEASURE_HUM)
{
sht1x->h = value;
}
calc_sth11(sht1x);
printf("value is :%f\n", value);
sht1x->checksum = read_byte(noACK); //read checksum
//arg = sht1x;
}
}
//----------------------------------------------------------------------------------
void measure(SHT1x_V3 *sht1x, unsigned char mode)
//----------------------------------------------------------------------------------
// makes a measurement (humidity/temperature) with checksum
{
int wait = 320;
sht1x->error = 0;
sht1x->mode = mode;
transstart(); //transmission start
switch (mode)
{ //send command to sensor
case MEASURE_TEMP:
sht1x->error += write_byte(MEASURE_TEMP);
break;
wait = 320;
case MEASURE_HUM:
sht1x->error += write_byte(MEASURE_HUM);
break;
wait = 80;
default:
break;
}
// 等待:测温等待320ms,测湿度等待80ms
// for (i=0;i<65535;i++) if(DATA==0) break;
mgos_set_timer(wait, false, cb_wait_data, sht1x);
}
//----------------------------------------------------------------------------------------
void calc_sth11(SHT1x_V3 *sht1x)
//----------------------------------------------------------------------------------------
// calculates temperature [℃] and humidity [%RH]
// input : hum [Ticks] (12 bit)
// temp [Ticks] (14 bit)
// output: hum
// temp
{
const float C1 = -2.0468; // for 12 Bit RH
const float C2 = +0.0367; // for 12 Bit RH
const float C3 = -0.0000015955; // for 12 Bit RH
const float T1 = +0.01; // for 12 Bit RH
const float T2 = +0.00008; // for 12 Bit RH
float h = sht1x->h; // h: Humidity [Ticks] 12 Bit
float t = sht1x->t; // t: Temperature [Ticks] 14 Bit
float h_lin; // h_lin: Humidity linear
float h_true; // h_true: Temperature compensated humidity
float t_C; // t_C : Temperature [℃]
t_C = t * 0.01 - 40.1; //calc. temperature [℃] from 14 bit temp. ticks @ 5V
h_lin = C3 * h * h + C2 * h + C1; //calc. humidity from ticks to [%RH]
h_true = (t_C - 25) * (T1 + T2 * h) + h_lin; //calc. temperature compensated humidity [%RH]
if (h_true > 100)
h_true = 100; //cut if the value is outside of
if (h_true < 0.1)
h_true = 0.1; //the physical possible range
sht1x->t_true = t_C; //return temperature [℃]
sht1x->h_true = h_true; //return humidity[%RH]
printf("t:%2.1f,h:%2.1f\n", t_C, h_true);
}
//--------------------------------------------------------------------
float calc_dewpoint(float h, float t)
//--------------------------------------------------------------------
// calculates dew point
// input: humidity [%RH], temperature [℃]
// output: dew point [℃]
{
float k, dew_point;
k = (log10(h) - 2) / 0.4343 + (17.62 * t) / (243.12 + t);
dew_point = 243.12 * k / (17.62 - k);
return dew_point;
}
SCK是滴答,在不同的滴答DATA应该怎样高、低, 这样来理解时序应该是一种方式。