首先讲讲SHT10这款温室度传感器。SHT1x(包括SHT10,SHT11和SHT15)属于Sersirion温湿度传感器家族中的贴片封装系列。更之前我讲过的DHT11这款温湿度传感器相比,体积小了许多,特别适合用于产品中。SHT10温湿度传感器包括一个电容性聚合体测湿敏感元件、一个用能隙材料制成的测温元件(文绉绉的),传感器内部有一个精度高达14为位的A/D转换器,适应串行接口电路实现无缝连接。该产品具有品质卓越、响应速度速度快,抗干扰能力强、性价比高等优点。
1、接口定义:
SHT10的接口定义如下图所示:
如上图所示,1脚为GND,4脚为VDD。它的供电电压范围为2.4~5.5V,建议的电压为3.3V,在电源引脚(VDD、GND)之间必须加上一个0.1uf的电容,应于去耦滤波用。它的2脚DATA为数据引脚,3脚SCK为时钟控制引脚,没有发现这两个引脚很像IIC所使用的引脚功能?没错,这个传感器确实可以认为是IIC接口,但是又有却别。该传感器不能按照IIC的协议编址,但是,如果IIC总线上没有挂接别的元件,传感器可以直接连到IIC总线上,但是单片机必须按照传感器的协议工作。传感器与单片机的接线如下图所示:
2、传感器的通讯
2.1、“启动传输”时序
用一组“启动传输”时序来完成数据传输的初始化。它包括:当SCK时钟高电平时DATA翻转为低电平,紧接着SCK变成低电平,随后是在SCK时钟高电平,随后是在SCK时钟高电平DATA翻转位高电平。时序如下:
2.2、复位时序
如果与SHT1x 通讯中断,可通过下列信号时序复位:当DATA 保持高电平时,触发SCK 时钟9 次或更多。时序图如下:
2.3、命令集
传感器的命令包含三个地址位(目前只支持000,这就是他只能挂接在空闲的IIC总线上的原因)和五个命令位。。SHT1x 会以下述方式表示已正确地接收到指令:在第8 个SCK 时钟的下降沿之后,将DATA 下拉为低电平(ACK 位)。在第9 个SCK 时钟的下降沿之后,释放DATA(恢复高电平)。命令集如下:
2.4、温湿度测量
发布一组测量命令(‘00000101’表示相对湿度RH,‘00000011’表示温度T)后,控制器要等待测量结束。这个过程需要大约20/80/320ms,分别对应8/12/14bit 测量。确切的时间随内部晶振速度,最多可能有-30%的变化。。SHT1x 通过下拉DATA 至低电平并进入空闲模式,表示测量的结束。控制器在再次触发SCK 时钟前,必须等待这个“数据备妥”信号来读出数据。检测数据可以先被存储,这样控制器可以继续执行其它任务在需要时再读出数据。
在收到CRC 的确认位之后,表明通讯结束。如果不使用CRC-8 校验,控制器可以在测量值LSB 后,通过保持ACK高电平终止通讯。在测量和通讯完成后,SHT1x 自动转入休眠模式。
2.5、状态寄存器
SHT1x 的某些高级功能可以通过给状态寄存器发送指令来实现,如选择测量分辨率,电量不足提醒,使用 OTP 加载或启动加热功能等。状态寄存器度、写如下:
测量分辨率:默认分辨率 14bit (温度) 和 12bit (湿度) 可以被降低为 12 和 8bit. 尤其适用于要求测量速度极高或者功耗极低的应用。
电量不足检测功能:在电压不足 2.47V 发出警告。精度为±0.05 V。
加热:可通过向状态寄存器内写入命令启动传感器内部加热器.。加热器可以使传感器的温度高于周围环境 5 – 10°C12 。功耗大约为 8mA @ 5V 。
OPT加载:开启此功能,标定数据将在每次测量前被上传到寄存器。如果不开启此功能,可减少大约 10ms的测量时间。
上面的寄存器如果没有什么特殊要求或应用于特定的场合,则无需配置,选择默认就可以了。
2.6、通讯过程
传感器的通讯过程为:发送”启动传输“时序,初始化传感器——>发送命令——>等待传感器应答,及测量结束——>接收传感器的16位数据值——>接收8为的CRC校验数据——>休眠,等待下一次传输开始。
传输的过程的测量时序可以由下图示意:
下面举个实际测量时的相对湿度测量时序例子。时序如下:
2.7、信号转化
2.7.1 温度的转化
设T 2 1 SOt为从传感器上读出来的测量数值,我们需要用下面的公式将测量数值转换成整整的温度值。
T = d1 + d2 * SOt (其中d1,d2的值根据实际情况选择,选项如下)
2.7.2 湿度的转换
湿度的转换公式如下: 。其中湿度的转化参数如下选择:根据采样的精度不同而不同。
2.7.3、露点的计算
露点的定义:露点温度指空气在此温度下能保持最多的水汽,当温度冷却到露点,空气变得饱和,就会出现雾、露或霜。
SHT1x 并不直接进行露点测量,,但露点可以通过温度和湿度读数计算得到.。由于温度和湿度在同一块集成电路上测量,SHT1x 可测量露点。 一块集成电路上测量,SHT1x 可测量露点。 下面直接给出结论性的露点计算公式了。
LogEW=(0.66077+7.5*T/(237.3+T)+(log10(RH)-2)
露点:Dp=((0.66077-logEW)*237.3/(logEW-8.16077)
例如:RH=10% T=25C ->EW=23.7465->露点=-8.69℃
RH=90% T=50C ->EW=92.4753->露点=47.89℃
2.8、STM32上的SHT10驱动程序
2.8.1、SHT10.h文件的编写
这个文件主要定义些重要的参数,以及更硬件相关的一些定义。
/************************************************************* \(^o^)/ Copyright (C), 2013-2020, ZheJiang University of Technology File name : SHT10.h Author : ziye334 Version : V1.0 Data : 2014/3/10 Description: Digital temperature and humidity sensor driver code *************************************************************/ #ifndef __SHT10_H__ #define __SHT10_H__ #include "stm32f10x.h" enum {TEMP, HUMI}; /* GPIO相关宏定义 */ #define SHT10_AHB2_CLK RCC_APB2Periph_GPIOD #define SHT10_DATA_PIN GPIO_Pin_0 #define SHT10_SCK_PIN GPIO_Pin_1 #define SHT10_DATA_PORT GPIOD #define SHT10_SCK_PORT GPIOD #define SHT10_DATA_H() GPIO_SetBits(SHT10_DATA_PORT, SHT10_DATA_PIN) //拉高DATA数据线 #define SHT10_DATA_L() GPIO_ResetBits(SHT10_DATA_PORT, SHT10_DATA_PIN) //拉低DATA数据线 #define SHT10_DATA_R() GPIO_ReadInputDataBit(SHT10_DATA_PORT, SHT10_DATA_PIN) //读DATA数据线 #define SHT10_SCK_H() GPIO_SetBits(SHT10_SCK_PORT, SHT10_SCK_PIN) //拉高SCK时钟线 #define SHT10_SCK_L() GPIO_ResetBits(SHT10_SCK_PORT, SHT10_SCK_PIN) //拉低SCK时钟线 /* 传感器相关宏定义 */ #define noACK 0 #define ACK 1 //addr 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_HUMI 0x05 //000 0010 1 测量湿度 #define SOFTRESET 0x1E //000 1111 0 复位 void SHT10_Config(void); void SHT10_ConReset(void); u8 SHT10_SoftReset(void); u8 SHT10_Measure(u16 *p_value, u8 *p_checksum, u8 mode); void SHT10_Calculate(u16 t, u16 rh,float *p_temperature, float *p_humidity); float SHT10_CalcuDewPoint(float t, float h); #endif
2.8.2、SHT10.c驱动程序的编写
不废话了,直接贴代码:
/************************************************************* \(^o^)/ Copyright (C), 2013-2020, ZheJiang University of Technology File name : SHT10.c Author : ziye334 Version : V1.0 Data : 2014/3/10 Description: Digital temperature and humidity sensor driver code *************************************************************/ #include "SHT10.h" #include <math.h> /************************************************************* Function :SHT10_Dly Description:SHT10时序需要的延时 Input : none return : none *************************************************************/ void SHT10_Dly(void) { u16 i; for(i = 500; i > 0; i--); } /************************************************************* Function :SHT10_Config Description:初始化 SHT10引脚 Input : none return : none *************************************************************/ void SHT10_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; //初始化SHT10引脚时钟 RCC_APB2PeriphClockCmd(SHT10_AHB2_CLK ,ENABLE); //PD0 DATA 推挽输出 GPIO_InitStructure.GPIO_Pin = SHT10_DATA_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(SHT10_DATA_PORT, &GPIO_InitStructure); //PD1 SCK 推挽输出 GPIO_InitStructure.GPIO_Pin = SHT10_SCK_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(SHT10_SCK_PORT, &GPIO_InitStructure); SHT10_ConReset(); //复位通讯 } /************************************************************* Function :SHT10_DATAOut Description:设置DATA引脚为输出 Input : none return : none *************************************************************/ void SHT10_DATAOut(void) { GPIO_InitTypeDef GPIO_InitStructure; //PD0 DATA 推挽输出 GPIO_InitStructure.GPIO_Pin = SHT10_DATA_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(SHT10_DATA_PORT, &GPIO_InitStructure); } /************************************************************* Function :SHT10_DATAIn Description:设置DATA引脚为输入 Input : none return : none *************************************************************/ void SHT10_DATAIn(void) { GPIO_InitTypeDef GPIO_InitStructure; //PD0 DATA 浮动输入 GPIO_InitStructure.GPIO_Pin = SHT10_DATA_PIN; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(SHT10_DATA_PORT, &GPIO_InitStructure); } /************************************************************* Function :SHT10_WriteByte Description:写1字节 Input : value:要写入的字节 return : err: 0-正确 1-错误 *************************************************************/ u8 SHT10_WriteByte(u8 value) { u8 i, err = 0; SHT10_DATAOut(); //设置DATA数据线为输出 for(i = 0x80; i > 0; i /= 2) //写1个字节 { if(i & value) SHT10_DATA_H(); else SHT10_DATA_L(); SHT10_Dly(); SHT10_SCK_H(); SHT10_Dly(); SHT10_SCK_L(); SHT10_Dly(); } SHT10_DATAIn(); //设置DATA数据线为输入,释放DATA线 SHT10_SCK_H(); err = SHT10_DATA_R(); //读取SHT10的应答位 SHT10_SCK_L(); return err; } /************************************************************* Function :SHT10_ReadByte Description:读1字节数据 Input : Ack: 0-不应答 1-应答 return : err: 0-正确 1-错误 *************************************************************/ u8 SHT10_ReadByte(u8 Ack) { u8 i, val = 0; SHT10_DATAIn(); //设置DATA数据线为输入 for(i = 0x80; i > 0; i /= 2) //读取1字节的数据 { SHT10_Dly(); SHT10_SCK_H(); SHT10_Dly(); if(SHT10_DATA_R()) val = (val | i); SHT10_SCK_L(); } SHT10_DATAOut(); //设置DATA数据线为输出 if(Ack) SHT10_DATA_L(); //应答,则会接下去读接下去的数据(校验数据) else SHT10_DATA_H(); //不应答,数据至此结束 SHT10_Dly(); SHT10_SCK_H(); SHT10_Dly(); SHT10_SCK_L(); SHT10_Dly(); return val; //返回读到的值 } /************************************************************* Function :SHT10_TransStart Description:开始传输信号,时序如下: _____ ________ DATA: |_______| ___ ___ SCK : ___| |___| |______ Input : none return : none *************************************************************/ void SHT10_TransStart(void) { SHT10_DATAOut(); //设置DATA数据线为输出 SHT10_DATA_H(); SHT10_SCK_L(); SHT10_Dly(); SHT10_SCK_H(); SHT10_Dly(); SHT10_DATA_L(); SHT10_Dly(); SHT10_SCK_L(); SHT10_Dly(); SHT10_SCK_H(); SHT10_Dly(); SHT10_DATA_H(); SHT10_Dly(); SHT10_SCK_L(); } /************************************************************* Function :SHT10_ConReset Description:通讯复位,时序如下: _____________________________________________________ ________ DATA: |_______| _ _ _ _ _ _ _ _ _ ___ ___ SCK : __| |__| |__| |__| |__| |__| |__| |__| |__| |______| |___| |______ Input : none return : none *************************************************************/ void SHT10_ConReset(void) { u8 i; SHT10_DATAOut(); SHT10_DATA_H(); SHT10_SCK_L(); for(i = 0; i < 9; i++) //触发SCK时钟9c次 { SHT10_SCK_H(); SHT10_Dly(); SHT10_SCK_L(); SHT10_Dly(); } SHT10_TransStart(); //启动传输 } /************************************************************* Function :SHT10_SoftReset Description:软复位 Input : none return : err: 0-正确 1-错误 *************************************************************/ u8 SHT10_SoftReset(void) { u8 err = 0; SHT10_ConReset(); //通讯复位 err += SHT10_WriteByte(SOFTRESET);//写RESET复位命令 return err; } /************************************************************* Function :SHT10_ReadStatusReg Description:读状态寄存器 Input : p_value-读到的数据;p_checksun-读到的校验数据 return : err: 0-正确 0-错误 *************************************************************/ u8 SHT10_ReadStatusReg(u8 *p_value, u8 *p_checksum) { u8 err = 0; SHT10_TransStart(); //开始传输 err = SHT10_WriteByte(STATUS_REG_R);//写STATUS_REG_R读取状态寄存器命令 *p_value = SHT10_ReadByte(ACK); //读取状态数据 *p_checksum = SHT10_ReadByte(noACK);//读取检验和数据 return err; } /************************************************************* Function :SHT10_WriteStatusReg Description:写状态寄存器 Input : p_value-要写入的数据值 return : err: 0-正确 1-错误 *************************************************************/ u8 SHT10_WriteStatusReg(u8 *p_value) { u8 err = 0; SHT10_TransStart(); //开始传输 err += SHT10_WriteByte(STATUS_REG_W);//写STATUS_REG_W写状态寄存器命令 err += SHT10_WriteByte(*p_value); //写入配置值 return err; } /************************************************************* Function :SHT10_Measure Description:从温湿度传感器读取温湿度 Input : p_value-读到的值;p_checksum-读到的校验数 return : err: 0-正确 1—错误 *************************************************************/ u8 SHT10_Measure(u16 *p_value, u8 *p_checksum, u8 mode) { u8 err = 0; u32 i; u8 value_H = 0; u8 value_L = 0; SHT10_TransStart(); //开始传输 switch(mode) { case TEMP: //测量温度 err += SHT10_WriteByte(MEASURE_TEMP);//写MEASURE_TEMP测量温度命令 break; case HUMI: err += SHT10_WriteByte(MEASURE_HUMI);//写MEASURE_HUMI测量湿度命令 break; default: break; } SHT10_DATAIn(); for(i = 0; i < 72000000; i++) //等待DATA信号被拉低 { if(SHT10_DATA_R() == 0) break; //检测到DATA被拉低了,跳出循环 } if(SHT10_DATA_R() == 1) //如果等待超时了 err += 1; value_H = SHT10_ReadByte(ACK); value_L = SHT10_ReadByte(ACK); *p_checksum = SHT10_ReadByte(noACK); //读取校验数据 *p_value = (value_H << 8) | value_L; return err; } /************************************************************* Function :SHT10_Calculate Description:计算温湿度的值 Input : Temp-从传感器读出的温度值;Humi-从传感器读出的湿度值 p_humidity-计算出的实际的湿度值;p_temperature-计算出的实际温度值 return : none *************************************************************/ void SHT10_Calculate(u16 t, u16 rh, float *p_temperature, float *p_humidity) { const float d1 = -39.7; const float d2 = +0.01; const float C1 = -2.0468; const float C2 = +0.0367; const float C3 = -0.0000015955; const float T1 = +0.01; const float T2 = +0.00008; float RH_Lin; //RH线性值 float RH_Ture; //RH真实值 float temp_C; temp_C = d1 + d2 * t; //计算温度值 RH_Lin = C1 + C2 * rh + C3 * rh * rh; //计算湿度值 RH_Ture = (temp_C -25) * (T1 + T2 * rh) + RH_Lin; //湿度的温度补偿,计算实际的湿度值 if(RH_Ture > 100) //设置湿度值上限 RH_Ture = 100; if(RH_Ture < 0.1) RH_Ture = 0.1; //设置湿度值下限 *p_humidity = RH_Ture; *p_temperature = temp_C; } /************************************************************* Function :SHT10_CalcuDewPoint Description:计算露点 Input : h-实际的湿度;t-实际的温度 return : dew_point-露点 *************************************************************/ float SHT10_CalcuDewPoint(float t, float h) { float logEx, dew_point; logEx = 0.66077 + 7.5 * t / (237.3 + t) + (log10(h) - 2); dew_point = ((0.66077 - logEx) * 237.3) / (logEx - 8.16077); return dew_point; } 2.8.3、main函数的编写: int main(void) { u16 humi_val, temp_val; u8 err = 0, checksum = 0; float humi_val_real = 0.0; float temp_val_real = 0.0; float dew_point = 0.0; BSP_Init(); printf("\nSHT10温室度测试程序!!!\n"); SHT10_Config(); while(1) { err += SHT10_Measure(&temp_val, &checksum, TEMP); //获取温度测量值 err += SHT10_Measure(&humi_val, &checksum, HUMI); //获取湿度测量值 if(err != 0) SHT10_ConReset(); else { SHT10_Calculate(temp_val, humi_val, &temp_val_real, &humi_val_real); //计算实际的温湿度值 dew_point = SHT10_CalcuDewPoint(temp_val_real, humi_val_real); //计算露点温度 } printf("当前环境温度为:%2.1f℃,湿度为:%2.1f%%,露点温度为%2.1f℃\r\n", temp_val_real, humi_val_real, dew_point); LED1_Toggle(); Delay_ms(1000); } }原文出处: http://ziye334.blog.163.com/blog/static/224306191201421265639956/