SHT3x是一款能读取温湿度的传感器,正负0.1摄氏度的温度误差和正负1.5%的湿度误差,手册上说i2c速率能到1Mhz,但是我实际用,高速下容易错误,还是低速下稳定。
以下是shtx的封装,包括初始化和读取温湿度。其中需要自己实现i2c的读写函数,具体看代码,不论是硬件i2c还是模拟的i2c都要注意:速率快了很容易出错!!!
SHT3X_init初始化函数,需要一个i2c读和写函数,由于传感器是采用i2c双字节地址,就是寄存器地址是两个字节(command),需要自己实现i2c读写函数,并将函数作为参数传入初始化。另外要传入一个设备地址,按照手册有0X45和0x44两种,具体看手册
SHT3X_temperature_humidity用于读取温湿度,实现上没有采用crc校验,因为总是出错。
SHT3X.c文件
/*************************************************************************************
Srh读值,RH转换后的湿度值
Tsr读值, T(C)摄氏度,T(F)华氏度
RH= 100*Srh / 65535
//W
T(C) = -45 + 175 * Tsr / 65535
T(F) = -49 + 315 * Tsr / 65535
***********************************************************************************/
#include "SHT3X.h"
#define SHTX_TC(St) (175 * (float)St / 65535 -45)
#define SHTX_TF(St) (315 * (float)St / 65535 -49)
#define SHTX_RH(St) (100 * (float)St / 65535)
const uint16_t Measurementcommands[] = {0x2032,0x2024,0x202F,0x2130,0x2126,0x212D,0x2236,0x2220,0x222B,0x2334,0x2322,0x2329,0x2737,0x2721,0x272A};
static uint16_t SHT3X_crc8(unsigned char *addr,uint8_t num);
/***********************************************************************
* 描 述: SHT3X温湿度传感初始化
* 入口参数: NONE
* 出口参数: NONE
* 附加信息:
* 说 明:
************************************************************************/
uint8_t SHT3X_init(SHT3X_DEV* base,
void (*read)(uint8_t,uint16_t,uint8_t*,uint8_t),
void (*write)(uint8_t,uint16_t,uint8_t*,uint8_t),
SHTXDEVADDR dev_addr
)
{
base->read = read;
base->write = write;
base->bad_crc_count = 0;
SHT3X_soft_reset(base);
set_SHT3x_Periodic_mode(base, MPS_1HZ,REFRESH_HIGH); //设置温湿度传感器输出方式
base->dev_addr = dev_addr;
return 0;
}
//***********************************************************************************************
// 函 数 名 : Check_SHT3X
// 输入参数 : NONE
// 返回参数 : stauts 在线TRUE,不在线FALSH
// 说 明 : 查找温湿度传感器是否在线
// 随便读取一个SHT中的寄存器,若有返回 0:在线
//***********************************************************************************************
uint8_t Check_SHT3X(SHT3X_DEV* base)
{
uint8_t ReadBuf[2];
return 0;
base->read(base->dev_addr,0xE000,ReadBuf,2);
if((ReadBuf[0] != 0) && (ReadBuf[0] != 0xff))
{
return 0;
}
return 1;
}
//***********************************************************************************************
// 函 数 名 : SHT3X_soft_reset
// 输入参数 : InExt(内外部湿度)
// 返回参数 : NONE
// 说 明 : 软件复位
//***********************************************************************************************
void SHT3X_soft_reset(SHT3X_DEV* base)
{
uint8_t buf;
base->write(base->dev_addr,0x30A2,&buf,0);
}
//***********************************************************************************************
// 函 数 名 : read_temperature_humidity
// 输入参数 : InExt(内外部湿度)
// 返回参数 : TEMP_ADCVal(温度读值),RH_ADCVal(湿度读值)
// 说 明 : 读取温湿度值,且进行CRC比较
//***********************************************************************************************
void SHT3X_temperature_humidity(SHT3X_DEV* base,float *TEMP_ADCVal,float *RH_ADCVal)
{
uint8_t ReadBuf[8] = {0x00};
uint16_t temp = 0;
uint16_t remp = 0;
base->read(base->dev_addr,0xE000,ReadBuf,6);
// (SHT3X_crc8(&ReadBuf[3],2) == ReadBuf[5])&&(SHT3X_crc8(&ReadBuf[0],2) == ReadBuf[2])
temp = (ReadBuf[0]<<8) + ReadBuf[1];
remp = (ReadBuf[3]<<8) + ReadBuf[4];
if( (temp != 0xffff)&&(0x0000 != temp)&&
(remp != 0xffff)&&(0x0000 != remp))
{
*TEMP_ADCVal = base->temperature = SHTX_TC(temp);
*RH_ADCVal = base->humidity = SHTX_RH(remp);
base->good_crc_count++;
}
else
{
*TEMP_ADCVal = 0xffff;//crc校验不通过
*RH_ADCVal = 0;
base->bad_crc_count++;
}
base->right_percent = base->good_crc_count/(base->good_crc_count + base->bad_crc_count);
}
//***********************************************************************************************
// 函 数 名 : set_SHT3x_Periodic_mode
// 输入参数 : mps(采样率),refresh(刷新率),InExt(内外部湿度)
// 返回参数 : NONE
// 说 明 : 设置周期性输出方式
// 刷新率越低,数值跳变越明显
// mps,采样率有:0.5Hz,1Hz,2Hz,4Hz,10Hz(MPS_05HZ,MPS_1HZ,MPS_2HZ...)
// refresh刷新率,高中低(REFRESH_HIGH,REFRESH_MID,REFRESH_LOW)
//***********************************************************************************************
void set_SHT3x_Periodic_mode(SHT3X_DEV* base,SHT3XMPS mps,SHT3XREFRESH refresh) //设置周期性输出方式
{
uint8_t buf[1];
uint8_t index = 0;
index = (mps-MPS_05HZ)*3;
index = index + refresh;
if(index >= sizeof(Measurementcommands))
{
index = 0;
}
base->write(base->dev_addr,Measurementcommands[index],buf,0);
}
//*************************************************************************************************
// 函 数 名 : SHT3X_crc8
// 输入参数 : 参与运算的值addr,长度
// 返回参数 : CRC
// 说 明 : SHT3X CRC校验
// P(x) = x^8 + x^5 + x^4 + 1
//此CRC计算方式仅适用小数据量运算,多数据运算时,请使用查表方式
//***********************************************************************************************
static uint16_t SHT3X_crc8(unsigned char *addr,uint8_t num)
{
uint8_t i;
uint8_t crc = 0xFF;
for (; num > 0; num--) // Step through bytes in memory
{
crc ^= (*addr++);
for (i = 0; i < 8; i++) // Prepare to rotate 8 bits
{
if (crc & 0x80) // b7 is set...
crc = (crc << 1) ^ 0x31; // P(x) = x^8 + x^5 + x^4 + 1 = 100110001
else // b7 is clear...
crc <<= 1; // just rotate
} // Loop for 8 bits
crc &= 0xFF; // Ensure CRC remains 16-bit value
} // Loop until num=0
return(crc); // Return updated CRC
}
SHT3X.h文件
#ifndef __SHT3x_H__
#define __SHT3x_H__
//#include "stm32l0xx_hal.h"
#include "stm32f722xx.h"
typedef enum{
DEV_0X44 = 0X44,
DEV_0X45 = 0X45
}SHTXDEVADDR;
typedef enum
{
MPS_05HZ = 1, //2S1次
MPS_1HZ = 2, //1S1次
MPS_2HZ =3, //1S2次
MPS_4HZ = 4, //1S4次
MPS_10HZ = 5 //1S10次
}SHT3XMPS;
typedef enum
{
REFRESH_HIGH = 1, //刷新率高(重复率高)
REFRESH_MID = 2, //刷新率中(重复率中)
REFRESH_LOW = 3 //刷新率低(重复率低)
}SHT3XREFRESH;
// 温湿度传感器都使用I2C1进行通迅 通信scl速率设置成50hz比较合适,很低,即使如此也有10%的错误率
typedef void (*sht_read)(uint8_t i2caddr,uint16_t regaddr,uint8_t*databuf,uint8_t datalen);
typedef void (*sht_write)(uint8_t i2caddr,uint16_t regaddr,uint8_t*databuf,uint8_t datalen);
typedef struct SHT3X
{
sht_read read;
sht_write write;
SHTXDEVADDR dev_addr;
float temperature;
float humidity;
uint16_t bad_crc_count;
uint16_t good_crc_count;
float right_percent;
}SHT3X_DEV;
//------------------------------------------------------------------------
// dev_addr:DEV_0X44,DEV_0X45
uint8_t SHT3X_init(SHT3X_DEV* base,
void (*sht_read)(uint8_t,uint16_t,uint8_t*,uint8_t),
void (*sht_write)(uint8_t,uint16_t,uint8_t*,uint8_t),
SHTXDEVADDR dev_addr
);
uint8_t check_sensor_SHT(SHT3X_DEV* base);
void SHT3X_soft_reset(SHT3X_DEV* base);
void SHT3X_temperature_humidity(SHT3X_DEV* base,float *TEMP_ADCVal,float *RH_ADCVal);
void set_SHT3x_Periodic_mode(SHT3X_DEV* base,SHT3XMPS mps,SHT3XREFRESH refresh); //设置周期性输出方式;
//W------------------------------------------------------------------------
#endif