SHT10温湿度传感器

1、SHT1x (包括 SHT10, SHT11 和 SHT15) 属于Sensirion温湿度传感器家族中的贴片封装系列。传感器将传感元件和信号处理电路集成在一块微型电路板上,输出完全标定的数字信号。传感器具有体积小、响应速度快、接口简单、性价比高等特点。

传感器接口定义如下:

SHT10温湿度传感器_第1张图片

SHT10的供电电压范围为2.4v-5.5v,建议供电电压为3.3v。SHT1x的串行接口,在传感器信号的读取及电源损耗方面,都做了优化处理;传感器不能按照I2C协议编址,但是如果I2C总线上没有挂接别的元件,传感器可以连接到I2C总线上,但单片机必须按照传感器的协议工作。

串行时钟输入(SCK): SCK 用于单片机与SHT10之间的通讯同步。

串行数据(DATA):DATA引脚为三态结构,用于读取传感器数据。当向传感器发送命令时, DATA在SCK上升沿有效且在SCK高电平时必须保持稳定,DATA在SCK下降沿之后改变。

传感器的通讯如下:

  1. 启动传感器:首先,选择供电电压后将传感器通电,上电速率不能低于1V/ms。通电后传感器需要11ms 进入休眠状态,在此之前不允许对传感器发送任何命令。
  2. 发送命令:用一组“启动传输”时序,来完成数据传输的初始化。它包括当SCK 时钟高电平时DATA 翻转为低电平,紧接着SCK变为低电平,随后是在SCK时钟高电平时DATA 翻转为高电平。启动时序如下图:

SHT10温湿度传感器_第2张图片

后续命令包含三个地址位(目前只支持“000”),和五个命令位。SHT1x会以下述方式表示已正确地接收到指令:在第8个SCK时钟的下降沿之后,将DATA下拉为低电平(ACK 位)。在第9个SCK时钟的下降沿之后,释放DATA(恢复高电平)。命令集如下:

SHT10温湿度传感器_第3张图片

  1. 温湿度测量:发布一组测量命令(‘00000101’表示相对湿度RH,‘00000011’表示温度T)后,控制器要等待测量结束。这个过程需要大约20/80/320ms,分别对应8/12/14bit测量。SHT1x 通过下拉DATA至低电平并进入空闲模式,表示测量的结束。控制器在再次触发SCK 时钟前,必须等待这个“数据备妥”信号来读出数据。接着传输2个字节的测量数据和1个字节的CRC 奇偶校验(可选择读取)。控制器需要通过下拉DATA为低电平,以确认每个字节。所有的数据从MSB开始,右值有效(例如:对于12bit 数据,从第5个SCK时钟起算作MSB;而对于8bit 数据,首字节则无意义。默认分辨率:14bit (温度) 和 12bit (湿度)可以被降低为12和8bit. 尤其适用于要求测量速度极高或者功耗极低的应用)。在收到CRC的确认位之后,表明通讯结束。如果不使用CRC-8校验,控制器可以在测量值LSB后,通过保持ACK高电平终止通讯。在测量和通讯完成后,SHT1x自动转入休眠模式。
  2. 通讯复位时序:如果与SHT1x通讯中断,可通过下列信号时序复位:当DATA保持高电平时,触发SCK时钟9次或更多,接着发送一个“传输启动”时序。复位时序如下:

SHT10温湿度传感器_第4张图片

  • 测量时序:传感器的通讯过程为:发送开始时序,启动传感器 -> 发送命令 -> 等待传感器应答及测量结束 -> 接收传感器数据值 -> 接收CRC校验数据 -> 休眠,等待下一次传输开始。

SHT10温湿度传感器_第5张图片

SHT10温湿度传感器_第6张图片

信号转换:

  • 相对湿度的转换:为获得精确的测量数据,建议用以下公式进行信号转换。

                                        RHlinear = C1 + C2 * SORH + C3 * SORH2(%RH)

公式参数如下:

  • 湿度信号的温度补偿:由于实际温度与测试参考温度25℃ (~77℉)的显著不同, 湿度信号需要温度补偿。

                                                   RHtrue = (T℃ - 25) *(t1 + t2 * SORH) + RHlinear

公式参数如下:

  • 温度值转换:可用如下公式将数字输出 (SO T ) 转换为温度值。

                                                  T = d1+d2 * SOT

公式参数如下:

SHT10温湿度传感器_第7张图片

  • 露点的定义:露点温度指空气在此温度下能保持最多的水汽,当温度冷却到露点,空气变得饱和,就会出现雾、露或霜。SHT1x并不直接进行露点测量,但露点可以通过温度和湿度读数计算得到。由于温度和湿度在同一块集成电路上测量,所以SHT1x可测量露点。露点计算公式如下:

SHT10温湿度传感器_第8张图片

 

4、 Sensor_Humidity.c

#include "sensor_humidity.h"

// 开始传输信号
static void SHT10_Start(void)
{           
    SHT10_SDA_H; // 将数据线拉高
    SHT10_SCK_L; // 将信号线拉低
    SHT10_DELAY_1US(); // 延时1us
    SHT10_SCK_H;
    SHT10_DELAY_1US();
    SHT10_SDA_L;
    SHT10_DELAY_1US();
    SHT10_SCK_L;
    SHT10_DELAY_1US();
    SHT10_SCK_H;
    SHT10_DELAY_1US();
    SHT10_SDA_H;
    SHT10_DELAY_1US();
    SHT10_SCK_L;
    SHT10_DELAY_1US();
}

// 通讯复位
static void SHT10_Reset(void)
{
    SHT10_SDA_H;
    SHT10_SCK_L;	
	
    for(uint8_t i=0; i<9; i++) // 触发SCK时钟9次      
    {
	SHT10_SCK_H;
	SHT10_DELAY_1US();
	SHT10_SCK_L;
	SHT10_DELAY_1US();
    }
}

// 引脚初始化
void SHT10_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;        

    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); // 使能时钟       
   
    GPIO_InitStructure.GPIO_Pin = Pin_SCK | Pin_SDA; // 传感器对应IO口
    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; // 开漏模式
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; // 上拉
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; // 输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3; // 50MHZ   
    GPIO_Init(SHT10_GPIOx, &GPIO_InitStructure); // 初始化GPIO
	
    SHT10_Reset(); // 传感器复位
}

// 向传感器写1字节
uint8_t SHT10_WriteByte(uint8_t value)
{	
    uint8_t state = ERR_NONE;
    for(uint8_t i=0; i<8; i++) // 写一个字节
    {
	if(value&0x80)
	    SHT10_SDA_H;
	else
	    SHT10_SDA_L;
	SHT10_DELAY_1US();
	SHT10_SCK_H;
	SHT10_DELAY_1US();
	SHT10_DELAY_1US();
	SHT10_SCK_L;
	SHT10_DELAY_1US();
	value <<= 1;
    }
    SHT10_SCK_H;
    SHT10_DELAY_1US();
    if(Read_SDA_Pin) // 读取SHT10的应答位
    {
	state = ERR_NO_ACK;
    }
    SHT10_SCK_L;
    SHT10_DELAY_1US();
    return state;
}

// 从传感器中读1字节数据
uint8_t SHT10_ReadByte(uint8_t Ack)
{
    uint8_t val = 0;
	           
    for(uint8_t i=0; i<8; i++) // 读取1字节数据
    {
	val <<= 1;
	SHT10_SCK_H;
	SHT10_DELAY_1US();
	if(Read_SDA_Pin)
	    val |= 1;
	SHT10_SCK_L;		
	SHT10_DELAY_1US();
    }         
    if(Ack)           
        SHT10_SDA_L;// 应答,则会接受后面的数据(校验数据)           
    else              
	SHT10_SDA_H; // 不应答        
    SHT10_DELAY_1US();
    SHT10_SCK_H;
    SHT10_DELAY_1US();
    SHT10_SCK_L;
    SHT10_DELAY_1US();
    SHT10_SDA_H;
    return val;                                        
}

// 从温湿度传感器读取温湿度
uint8_t SHT10_Measure(uint8_t cmd, uint16_t *p_value)
{
    uint8_t status = ERR_NONE;
	
    // 开始传输
    SHT10_Start(); 
	
    // 写测量命令
    if(SHT10_WriteByte(cmd) == ERR_NO_ACK) 
    {
	SHT10_Reset();
	status = ERR_NO_ACK;
	return status;
    }
	
    // 等待DATA信号被拉低,正常应该在320ms内测量完成
    for(uint32_t i = 0; i < 72000000; i++) 
    {
	if(!(Read_SDA_Pin)) break; // 检测到DATA被拉低了,跳出循环         
    }
	
    // 检查转换完成状态
    if(Read_SDA_Pin) // 如果等待超时了
    {
	SHT10_Reset();
	status = ERR_TIME_OUT;
	return status;
    }
    else // 完成测量
    {
	uint8_t value_H = SHT10_ReadByte(ACK); // 读取高8位数据
	uint8_t value_L = SHT10_ReadByte(ACK); // 读取低8位数据
	uint8_t checksum = SHT10_ReadByte(NO_ACK); // 读取校验数据
//	if(checksum) // 校验不正确
//	{
//	    status = ERR_CHECK_NUM;
//	}
	*p_value = (value_H << 8) | value_L;
	}
	return status;
}

// 计算温湿度的值
void SHT10_Calculate(uint16_t SOt, uint16_t SOrh, float* T, float* RH)
{
    const float C1=-2.0468f;    // 12 Bit
    const float C2= 0.0367f;    // 12 Bit
    const float C3=-1.5955e-6f; // 12 Bit
	
    const float t1=0.01f;     // 12 Bit
    const float t2=0.00008f;  // 12 Bit	
	
    const float d1=-39.6f;  // for 3v
    const float d2= 0.01f;  // for 14 Bit
	
    *T = d1 + d2 * SOt; // 计算温度值
	
    float RH_Linear = C1 + C2 * SOrh + C3 * SOrh	* SOrh;	// 计算湿度值
    *RH = (*T - 25) * (t1 + t2 * SOrh) + RH_Linear; // 湿度的温度补偿,计算实际的湿度值
}

// 计算露点
void SHT10_CalDewPoint(float T, float RH, float* Td)
{
//    RH = 10^((7.45*td)/(235+td)) / 10^((7.45*t)/(235+t))
//    float x = log10(pow(10, (7.45f * T) / (235 + T)) * RH*0.01f);
//    *Td = x * 235 / (7.45f - x);
	
    float Tn = T>=0 ? 243.12f : 272.62;
    float m  = T>=0 ? 17.62f  : 22.46;
    float a = log(RH / 100.f);
    float b = (m * T) / (Tn + T);
    *Td = Tn * (a + b) / (m - a -b);
}

// 测量温湿度及露点
uint8_t SHT10_GetMessure(float *T , float *RH, float* Td)
{
    uint16_t SOt, SOrh;
	
    uint8_t status_temp = SHT10_Measure(MEASURE_TEMP, &SOt);                  
    uint8_t status_humi = SHT10_Measure(MEASURE_HUMI, &SOrh); 	
	
    if(status_temp == ERR_NONE && status_humi == ERR_NONE)
    {
	SHT10_Calculate(SOt, SOrh, T, RH); // 计算得到温度、湿度
	SHT10_CalDewPoint(*T, *RH, Td); // 计算出露点值,并且返回
    }
    return status_temp | status_humi;
}

5、Sensor_Humidity.h

#ifndef _SENSOR_HUMIDITY_H_
#define _SENSOR_HUMIDITY_H_

#include "stm32f0xx.h"
#include "bsp_systick.h"
#include 
#include 

enum {TEMP, HUMI};

 // 定义内联延时函数
static inline void SHT10_DELAY_1US(void)
{
	__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
	__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
	__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
	__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
	__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
	__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
}	

#define	SHT10_GPIOx  	GPIOB
#define Pin_SCK				GPIO_Pin_10
#define Pin_SDA				GPIO_Pin_11

#define SHT10_SCK_L		SHT10_GPIOx->ODR &= ~Pin_SCK
#define SHT10_SCK_H		SHT10_GPIOx->ODR |=  Pin_SCK

#define SHT10_SDA_L		SHT10_GPIOx->ODR &= ~Pin_SDA
#define SHT10_SDA_H		SHT10_GPIOx->ODR |=  Pin_SDA

#define Read_SDA_Pin	SHT10_GPIOx->IDR & Pin_SDA

#define  NO_ACK       0
#define  ACK          1

#define ERR_NONE		   0
#define ERR_TIME_OUT   1
#define ERR_NO_ACK     2
#define ERR_CHECK_NUM  4

#define STATUS_REG_W        0x06  // 写状态寄存器    
#define STATUS_REG_R        0x07  // 读状态寄存器
#define MEASURE_TEMP        0x03  // 测量温度    
#define MEASURE_HUMI        0x05  // 测量湿度    
#define SOFTRESET      			0x1E  // 复位   

void SHT10_Init(void);
uint8_t SHT10_GetMessure(float *T , float *RH, float* Td);
	
#endif

5、主函数

float RH; // 湿度值变量
float T;  // 温度值变量
float Td; // 露点值变量

int main()
{
    SYSTICK_Init(1); // 滴答定时器初始化
    SHT10_Init();	// 传感器初始化
    USART1_Init(); // 串口初始化
	
    while(1)
    {
	if(SHT10_GetMessure(&T ,&RH, &Td) == ERR_NONE)	//读取露点
	{
	    printf("T: %.2f RH: %.2f Td: %.2f \r\n",T, RH, Td);
	}
	SYSTICK_DelayMs(500);
    }
}

 

你可能感兴趣的:(传感器开发)