重庆建设招标网站,厦门高端网站建设公司,电子商务网络营销是什么,龙岗招聘网常见温湿度传感器测量范围#xff1a;(价格仅供参考#xff0c;具体性能要看折线图)
型号DHT11DHT20AHT10AHT20AHT30SHT20价格#xffe5; 2.49#xffe5;3.04#xffe5; 1.9#xffe5;1.4#xffe5; 1.3#xffe5;5.5温度测量范围20—90%RH0—100%RH0—100%RH0—…常见温湿度传感器测量范围(价格仅供参考具体性能要看折线图)
型号DHT11DHT20AHT10AHT20AHT30SHT20价格 2.493.04 1.91.4 1.35.5温度测量范围20—90%RH0—100%RH0—100%RH0—100%RH0—100%RH0—100%RH湿度测量精度±5%RH±3%RH±2%RH±2%RH±2%RH±2%RH温度测量范围0—50℃-40—80℃-40—85℃-40—85℃-40—85℃-40—125℃温度测量精度±2℃±0.5℃±0.3℃±0.3℃±0.3℃±0.3℃工作电压DC5V/3.3VDC5V/3.3VDC3.3VDC5V/3.3VDC5V/3.3VDC5V/3.3V
型号SHT30SHT31SHT35SHT40SHT41SHT45价格 3.9 6.9 18.5 3.256.6 19温度测量范围0—100%RH0—100%RH0—100%RH0—100%RH0—100%RH0—100%RH湿度测量精度±2%RH±2%RH±1.5%RH±1.8%RH±1.8%RH±1.5%RH温度测量范围-40—125℃-40—125℃-40—125℃-40—125℃-40—125℃-40—125℃温度测量精度±0.2℃±0.2℃±0.1℃±0.2℃±0.2℃±0.1℃工作电压DC5V/3.3VDC5V/3.3VDC5V/3.3VDC3.3VDC3.3VDC3.3V
SHT30概述 数据 SHT30是一款完全校准的线性化的温湿度数字传感器增强了数字信号。I2C通讯频率达1MHz。具有高可靠性及高稳定性。
供电 供电电压2.15V-5.5V数据接口电压可5V或3.3V(不同供电系统可对接但尽量避免)。
功能 单次读取或周期性读取温度和湿度传感器数值通过公式转换为摄氏度和相对湿度值。
连接 使用I2C进行连接也可使用普通GPIO引脚模拟I2C进行通讯但通讯速率较低。
SHT30引脚说明 引脚名称功能1SDA数据信号2ADDR连接到高电平或低电平不可以悬空3ALERT报警引脚不用必须悬空4SCL时钟信号5VDD电源正极6nRESET低电平复位如果不使用建议悬空也可以使用大于2Ω电阻连接到VDD7R无功能请连到电源地8VSS电源地9pad中间引脚与电源地相通散热引脚
SHT30电气特性 温度误差 湿度误差
SHT30 MCU连接 Rp是I2C上拉电阻I2C总线上只连接一个设备时推荐阻值为10K其他视情况而定该数值不能太小也不能太大。
SDASCL接上拉电阻后再接MCU用于数据读取。
nRESET不用时悬空。 ALERT不用时悬空。
SHT30通信协议
SHT30的通讯协议是基于I2C的这里主要理解I2C通讯协议。
SHT30写命令顺序
1、设置I2C Start。此时I2C状态为0x08已发送起始条件 2、发送SHT30的I2C写地址。注意上图中ADDR接地则设备地址为0x44若ADDR接高电平则设备地址为0x45。同时该地址为7位再加读写标志位1位才凑够8byte写时读写标志位为零则该byte为0x441。 3、等待收到SHT30的确认ACK。 此时I2C状态为0x18已发送设备地址和写命令已接收到ACK 4、发送控制命令高字节。 5、等待收到SHT30的确认ACK。 此时I2C状态为0x28已发送1byte数据已接收到ACK 6、发送控制命令低字节。 7、等待收到SHT30的确认ACK。 此时I2C状态为0x28已发送1byte数据已接收到ACK 8、如无后续数据设置I2C Stop。SHT30写命令只有这一种
如周期性数据测量模式命令Command 0x2220 SHT30读命令顺序先和写命令一样写入一个命令数据再读取温湿度数据
1、设置I2C Start。此时I2C状态为0x08已发送起始条件 2、发送SHT30的I2C写地址。注意上图中ADDR接地则设备地址为0x44若ADDR接高电平则设备地址为0x45。同时该地址为7位再加读写标志位1位才凑够8byte写时读写标志位为零则该byte为0x441。 3、等待收到SHT30的确认ACK。 此时I2C状态为0x18已发送设备地址和写命令已接收到ACK 4、发送控制命令高字节。 5、等待收到SHT30的确认ACK。 此时I2C状态为0x28已发送1byte数据已接收到ACK 6、发送控制命令低字节。 7、等待收到SHT30的确认ACK。 此时I2C状态为0x28已发送1byte数据已接收到ACK
8、如使用周期性测量命令设定过SHT30则无需等待重新设置I2C Start。 此时I2C状态为0x08已发送起始条件 9、发送SHT30的I2C读地址。注意上图中ADDR接地则设备地址为0x44若ADDR接高电平则设备地址为0x45。同时该地址为7位再加读写标志位1位才凑够8byte读时读写标志位为1则该byte为0x441|0x01。 10、等待收到SHT30的确认ACK。 此时I2C状态为0x40已发送设备地址和读命令已接收到ACK 11、设置使能主机应答功能即主机进行接收数据后发送ACK确认。 12、接收温度高字节。 此时I2C状态为0x50已接收数据字节并已返回ACK信号 13、接收温度低字节。 此时I2C状态为0x50已接收数据字节并已返回ACK信号 14、接收温度CRC字节。 此时I2C状态为0x50已接收数据字节并已返回ACK信号 15、接收湿度高字节。 此时I2C状态为0x50已接收数据字节并已返回ACK信号 16、接收湿度低字节。 此时I2C状态为0x50已接收数据字节并已返回ACK信号 17、设置关闭主机应答功能最后一个数据不需要ACK。 17、接收湿度CRC字节。 此时I2C状态为0x58已接收到最后一个数据NACK已返回 18、设置I2C Stop.
如读取周期性数据测量数据命令Command 0xE000 SHT30命令说明
单次测量命令单次读取使用通讯中需要等待测量结果
周期测量命令(mps每秒多少次。设置使用用于设置周期测量模式)
读取周期测量结果命令读取使用读取上一次周期测量的测量结果。 加速相应时间命令周期测量命令一样的功能不过更快周期更短 停止周期测量命令设置使用用于停止周期测量) 软件重置命令使用命令进行重置此外使用I2C协议的一般重置功能也能进行重置。经实验下图最后一个ACK收不到可能是因为收到重置命令后立即重置所以就没有发送ACK。 加热器控制命令可加热几摄氏度用于检测设备好坏。 读取状态寄存器可获取各种设备状态 设备状态说明 清除状态寄存器
SHT30校验和计算
校验使用CRC-8 代码说明
uint8_t CheckCrc8(uint8_t* const message, uint8_t initial_value)
{uint8_t remainder; //余数uint8_t i 0, j 0; //循环变量/* 初始化 */remainder initial_value;for(j 0; j 2;j){remainder ^ message[j];/* 从最高位开始依次计算 */for (i 0; i 8; i){if (remainder 0x80){remainder (remainder 1)^CRC8_POLYNOMIAL;}else{remainder (remainder 1);}}}/* 返回计算的CRC码 */return remainder;
}计算温度ST 传感器温度返回值 计算湿度SRH 传感器湿度返回值 代码说明 /* 转换温度数据 */recv_temperature ((uint16_t)dat[0]8)|dat[1];*temperature -45 175*((float)recv_temperature / 65535);/* 转换湿度数据 */recv_humidity ((uint16_t)dat[3]8)|dat[4];*humidity 100 * ((float)recv_humidity / 65535);SHT30 样例代码(基于HC32L130
样例代码使用周期性测量模式。先设置周期性测量模式再通过读取周期性测量结果获得温湿度数据。 sht3x.h文件
#ifndef __SHT3X_H__
#define __SHT3X_H__#include gpio.h/*
//ADDR Pin Conect to VSS
#define SHT30_ADDR_WRITE 0x441 //10001000
#define SHT30_ADDR_READ (0x441)1 //10001011
*///SHT30 I2C地址
#define I2C_DEVADDR 0x44
//CRC-8多项式
#define CRC8_POLYNOMIAL 0x31typedef enum
{/* 软件复位命令 */SOFT_RESET_CMD 0x30A2, /*单次测量模式命名格式Repeatability_CS_CMDCSClock stretching*/HIGH_ENABLED_CMD 0x2C06,MEDIUM_ENABLED_CMD 0x2C0D,LOW_ENABLED_CMD 0x2C10,HIGH_DISABLED_CMD 0x2400,MEDIUM_DISABLED_CMD 0x240B,LOW_DISABLED_CMD 0x2416,/*周期测量模式命名格式Repeatability_MPS_CMDMPSmeasurement per second*/HIGH_0_5_CMD 0x2032,MEDIUM_0_5_CMD 0x2024,LOW_0_5_CMD 0x202F,HIGH_1_CMD 0x2130,MEDIUM_1_CMD 0x2126,LOW_1_CMD 0x212D,HIGH_2_CMD 0x2236,MEDIUM_2_CMD 0x2220,LOW_2_CMD 0x222B,HIGH_4_CMD 0x2334,MEDIUM_4_CMD 0x2322,LOW_4_CMD 0x2329,HIGH_10_CMD 0x2737,MEDIUM_10_CMD 0x2721,LOW_10_CMD 0x272A,/* 周期测量模式读取数据命令 */READOUT_FOR_PERIODIC_MODE 0xE000,
} SHT30_CMD;void I2C_Port_Init(void);
void I2C_Cfg_Init(void);
void SHT30_reset(void);
uint8_t SHT30_Init(void);
uint8_t SHT30_Send_Cmd(SHT30_CMD cmd);
uint8_t SHT30_Read_Dat(uint8_t* dat);
uint8_t SHT30_Dat_To_Float(uint8_t* const dat, float* temperature, float* humidity);#endif /* __SHT3X_H__ */
sht3x.c文件
#include sht3x.h
#include gpio.h
#include i2c.h// I2C端口配置
void I2C_Port_Init(void)
{stc_gpio_cfg_t stcGpioCfg;DDL_ZERO_STRUCT(stcGpioCfg);Sysctrl_SetPeripheralGate(SysctrlPeripheralGpio,TRUE); //开启GPIO时钟门控 stcGpioCfg.enDir GpioDirOut; /// 端口方向配置-输出 stcGpioCfg.enOD GpioOdEnable; /// 开漏输出stcGpioCfg.enPu GpioPuEnable; /// 端口上拉配置-使能stcGpioCfg.enPd GpioPdDisable; /// 端口下拉配置-禁止stcGpioCfg.bOutputVal TRUE;Gpio_Init(GpioPortB,GpioPin13,stcGpioCfg); /// 端口初始化Gpio_Init(GpioPortB,GpioPin14,stcGpioCfg);Gpio_SetAfMode(GpioPortB,GpioPin13,GpioAf2); /// 配置PB13为SCLGpio_SetAfMode(GpioPortB,GpioPin14,GpioAf2); /// 配置PB14为SDA
}// I2C 模块配置
void I2C_Cfg_Init(void)
{stc_i2c_cfg_t stcI2cCfg;DDL_ZERO_STRUCT(stcI2cCfg); /// 初始化结构体变量的值为0Sysctrl_SetPeripheralGate(SysctrlPeripheralI2c1,TRUE); /// 开启I2C0时钟门控stcI2cCfg.u32Pclk Sysctrl_GetPClkFreq(); /// 获取PCLK时钟stcI2cCfg.u32Baud 100000; /// 100kHzSHT30最大支持1MHz,但要I2C fast mode,且硬件设计过关stcI2cCfg.enMode I2cMasterMode; /// 主机模式stcI2cCfg.u8SlaveAddr 0x55; /// 从地址主模式无效stcI2cCfg.bGc FALSE; /// 广播地址应答使能关闭I2C_Init(M0P_I2C1,stcI2cCfg); /// 模块初始化
}// CRC-8校验
uint8_t CheckCrc8(uint8_t* const message, uint8_t initial_value)
{uint8_t remainder; //余数uint8_t i 0, j 0; //循环变量/* 初始化 */remainder initial_value;for(j 0; j 2;j){remainder ^ message[j];/* 从最高位开始依次计算 */for (i 0; i 8; i){if (remainder 0x80){remainder (remainder 1)^CRC8_POLYNOMIAL;}else{remainder (remainder 1);}}}/* 返回计算的CRC码 */return remainder;
}// SHT30写命令函数只进行写命令操作
en_result_t I2C_SHT30WriteCmd(M0P_I2C_TypeDef* I2CX,uint8_t *pu8Data)
{en_result_t enRet Error;uint8_t sendCount0,u8State;I2C_SetFunc(I2CX,I2cStart_En); ///发送起始条件while(1){while(0 I2C_GetIrq(I2CX)){;}u8State I2C_GetState(I2CX);switch(u8State){case 0x08: ///已发送起始条件I2C_ClearFunc(I2CX, I2cStart_En);I2C_WriteByte(I2CX,(I2C_DEVADDR1)); ///发送设备地址W写标志0break;case 0x18: ///已发送SLWW已接收ACKcase 0x28: ///已发送I2Cx_DATA中的数据已接收ACKif(sendCount2){I2C_WriteByte(I2CX,pu8Data[sendCount]); ///发送数据}else{//发送两字节命令后收到ACK,退出sendCount;}break;case 0x20: ///已发送SLWW已接收非ACKcase 0x38: ///上一次在SLA写数据时丢失仲裁I2C_SetFunc(I2CX,I2cStart_En); ///当I2C总线空闲时发送起始条件break;case 0x30: ///已发送I2Cx_DATA中的数据已接收非ACK将传输一个STOP条件I2C_SetFunc(I2CX,I2cStop_En); ///发送停止条件break;default:break;} if(sendCount2){I2C_SetFunc(I2CX,I2cStop_En); ///此顺序不能调换出停止条件I2C_ClearIrq(I2CX);break;}I2C_ClearIrq(I2CX); ///清除中断状态标志位}enRet Ok;return enRet;
}// 主机读取数据函数只进行读数据操作
en_result_t I2C_MasterReadData(M0P_I2C_TypeDef* I2CX,uint16_t u8Cmd,uint8_t *pu8Data,uint32_t u32Len)
{en_result_t enRet Error;uint8_t u8State0;uint8_t receiveCount0;uint8_t sendAddrCount0;uint8_t sendCmdCount0;I2C_SetFunc(I2CX,I2cStart_En);while(1){while(0 I2C_GetIrq(I2CX)){;}u8State I2C_GetState(I2CX);switch(u8State){case 0x08: /// 已发送起始条件将发送SLAWsendAddrCount;if(sendAddrCount1){I2C_ClearFunc(I2CX,I2cStart_En);I2C_WriteByte(I2CX,I2C_DEVADDR1); }if(sendAddrCount1){I2C_ClearFunc(I2CX,I2cStart_En);I2C_WriteByte(I2CX,I2C_DEVADDR1|0x01);/// 发送SLAR开始从从机读取数据 }break;case 0x18: /// 已发送SLAW,并接收到ACKI2C_WriteByte(I2CX,(uint8_t)(u8Cmd8)); ///命令高8位break;case 0x28: /// 已发送数据接收到ACK, 此处是已发送从机内存地址u8Addr并接收到ACKsendCmdCount;I2C_WriteByte(I2CX,(uint8_t)u8Cmd); ///命令低8位if(sendCmdCount1)I2C_SetFunc(I2CX,I2cStart_En); /// 发送重复起始条件break;case 0x10: /// 已发送重复起始条件I2C_ClearFunc(I2CX,I2cStart_En);I2C_WriteByte(I2CX,I2C_DEVADDR|0x01); /// 发送SLAR开始从从机读取数据break;case 0x40: /// 已发送SLAR并接收到ACKif(u32Len1){I2C_SetFunc(I2CX,I2cAck_En); /// 使能主机应答功能}break;case 0x50: /// 已接收数据字节并已返回ACK信号pu8Data[receiveCount] I2C_ReadByte(I2CX);if(receiveCountu32Len-1){I2C_ClearFunc(I2CX,I2cAck_En); /// 已接收到倒数第二个字节关闭ACK应答功能}break;case 0x58: /// 已接收到最后一个数据NACK已返回pu8Data[receiveCount] I2C_ReadByte(I2CX);I2C_SetFunc(I2CX,I2cStop_En); /// 发送停止条件break;case 0x38: /// 在发送地址或数据时仲裁丢失I2C_SetFunc(I2CX,I2cStart_En); /// 当总线空闲时发起起始条件break;case 0x48: /// 发送SLAR后收到一个NACKI2C_SetFunc(I2CX,I2cStop_En); /// 发送停止条件I2C_SetFunc(I2CX,I2cStart_En); /// 发送起始条件break;default:I2C_SetFunc(I2CX,I2cStart_En); /// 其他错误状态重新发送起始条件break;}I2C_ClearIrq(I2CX); /// 清除中断状态标志位if(receiveCountu32Len) /// 数据全部读取完成跳出while循环{break;}}enRet Ok;return enRet;
}// 向SHT30发送一条指令(16bit)
uint8_t SHT30_Send_Cmd(SHT30_CMD cmd)
{uint8_t cmd_buffer[2];cmd_buffer[0] cmd 8;cmd_buffer[1] cmd;return I2C_SHT30WriteCmd(M0P_I2C1, cmd_buffer);
}// 复位SHT30
void SHT30_reset(void)
{SHT30_Send_Cmd(SOFT_RESET_CMD);delay1us(20);
}// 初始化SHT30 周期测量模式0x2220
uint8_t SHT30_Init(void)
{return SHT30_Send_Cmd(MEDIUM_2_CMD);
}// 从SHT30读取一次数据
uint8_t SHT30_Read_Dat(uint8_t* dat)
{return I2C_MasterReadData(M0P_I2C1,READOUT_FOR_PERIODIC_MODE, dat, 6);
}// 将SHT30接收的6个字节数据进行CRC校验并转换为温度值和湿度值
uint8_t SHT30_Dat_To_Float(uint8_t* const dat, float* temperature, float* humidity)
{uint16_t recv_temperature 0;uint16_t recv_humidity 0;/* 校验温度数据和湿度数据是否接收正确 */if(CheckCrc8(dat, 0xFF) ! dat[2] || CheckCrc8(dat[3], 0xFF) ! dat[5])return 1;/* 转换温度数据 */recv_temperature ((uint16_t)dat[0]8)|dat[1];*temperature -45 175*((float)recv_temperature/65535);/* 转换湿度数据 */recv_humidity ((uint16_t)dat[3]8)|dat[4];*humidity 100 * ((float)recv_humidity / 65535);return 0;
}
main.c文件
#include sht3x.h
#include gpio.h
#include ddl.h
#include i2c.huint8_t recv_dat[6] {0};float temperature 0.0;
float humidity 0.0;int main(void)
{I2C_Cfg_Init();I2C_Port_Init();/// 向I2C总线发起开始信号I2C_SetFunc(M0P_I2C1,I2cStart_En); SHT30_Init();while (1){delay1ms(1000);if(SHT30_Read_Dat(recv_dat) Ok){SHT30_Dat_To_Float(recv_dat, temperature, humidity);}}
}