STM32驱动 HTU21D温湿度传感器
时间:2023-09-02 01:07:01
STM32驱动 HTU21D温湿度传感器
温湿度传感器模块HTU21D产品简介
基于法国Humirel由新一代制成的高性能湿度感应元件HTU21D温湿度传感器在尺寸和智能方面建立了新的标准:嵌入了适合回流焊的双列扁平无引脚DFN 封装, 底面3x3mm,高度1.1mm。传感器输出标准数字信号 I2C格式。输出方式多样,工作电压范围宽,温度精度和湿度精度高。HTU21系列模块专为低功耗小体积应用设计,质量好,响应速度快,抗干扰能力强,性价比高,体积小(3x3mm)、极低的功耗
数字输出温湿度传感器模块HTU21D重要的传感器参数
供电电压:1.5V—3.6V
湿度测量范围:0-100%RH
温度测量范围: -40℃—125℃
最大消耗功率: 2.7uW
通信方式:I2C
湿度精度范围(10%)RH to 95%RH): ±2%RH
湿度迟滞:±1%RH
测量时间:50ms
年漂移量:-0.5%RH/year
响应时间:5 s
main函数
/// 主函数 LED_GPIO_Config(); LED_BLUE; //串口初始化 USART_Config(); //I2C初始化 i2c_Config(); printf("开始温湿度检测\n"); printf("\n"); while(1) { HTU21D_Display(); }
部分地址封装
#define HTDU21D_ADDRESS 0x查询数据手册或查看时序图 HTDU21D_ADDRESS是7位地址1000000 #define SOFT_RESET 0xFE//软件复位 #define NOHOLD_TEMP_MEASURE 0xF3//非主机模式下的温度测量 #define NOHOLD_HUMI_MEASURE 0xF5//非主机模式下湿度测量 #define HTDU21D_ADDRESS_WR 0x80//7位地址1000000 0写 #define HTDU21D_ADDRESS_RD 0x81//7位地址1000000 1读
从外设指定的地址读取若干数据
/******************************************************* **函数 ReadBytes **功能 从外设指定的地址读取若干数据 **形参 Address 起始地址 ** Size 数据长度 ** *pReadBuf 缓冲区指针(用于存储读取的数据) **返回值 1、正常运行 ** 0、运行异常 *******************************************************/ uint8_t ReadBytes(uint8_t *pReadBuf, uint16_t Address, uint16_t Size) { uint16_t i; /* 发起I2C总线启动信号 */ i2c_Start(); /* 发起控制字节,高7bit是地址,bit0是读写控制位,0表示写作,1表示读 */ i2c_SendByte(HTDU21D_ADDRESS | I2C_WR); /*等待ACK */ if (i2c_WaitAck() != 0) { goto cmd_fail; /* 器件无应答 */ } /* 发送字节地址 */ i2c_SendByte((uint8_t)Address); /* 等待ACK */ if (i2c_WaitAck() != 0) { goto cmd_fail; /* 器件无应答 */ } /*重新启动I2C总线。前代码的目的是将地址传输到外设,下面开始读取数据 */ i2c_Start(); /* 发起控制字节,高7bit是地址,bit0是读写控制位,0表示写作,1表示读 */ i2c_SendByte(HTDU21D_ADDRESS | I2C_RD); /* 这是阅读指令 */ /* 发送ACK */ if (i2c_WaitAck() != 0) { goto cmd_fail; /* 器件无应答 */ } /*循环读取数据 */ for (i = 0; i < Size; i ) { pReadBuf[i] = i2c_ReadByte(); /* 读1个字节 */ /* 每读一个字节后,需要发送Ack, 不需要最后一个字节Ack,发Nack */ if (i != Size - 1) { i2c_Ack(); /* 读完中间字节后,CPU产生ACK信号(驱动SDA = 0) */ } else { i2c_NAck(); /* 最后1个字节读完后,CPU产生NACK信号(驱动SDA = 1) */ } } /* 发送I2C总线停止信号 */ i2c_Stop(); return 1; /* 执行成功 */ cmd_fail: /* 命令执行失败后,记得发送停止信号,避免影响I2C其他总线设备 */ /* 发送I2C总线停止信号 */ i2c_Stop(); return 0; }
向外设指定的地址处开始写入若干数据
/************************************************************************* **函数 WriteBytes **功能 向外设置指定的地址开始写入数据 **形参 Address 起始地址 ** Size 数据长度 ** *pWriteBuf 缓冲区指针(用于存储需要写入的数据) **返回值 1、正常运行 ** 0、运行异常 ***********************************************************************/ uint8_t WriteBytes(uint8_t *pWriteBuf, uint16_t Address, uint16_t Size) { uint16_t i,m; uint16_t Addr; uint8_t PAGE_SIZE=8; /* 写串行EEPROM与阅读操作不同,许多字节可以连续阅读,每次写作操作只能在同一个字节中page。 对于24xx02,page size = 8 简单的处理方法是:按字节写操作模式,不写字节,发送地址 为提高连续写作效率: 本函数采用page wirte操作。 */ Addr = Address; for (i = 0; i < Size; i ) { /* 当发送第一个字节或页面的第一个地址时,启动信号和地址需要重启 */ if ((i == 0) || (Addr & (PAGE_SIZE - 1)) == 0) { /* 第0步:发送停止信号,启动内部写作操作 */ i2c_Stop(); /* 判断内部写作操作是否通过检查器件响应来完成, 一般小于 10ms CLK频率为200KHz时,查询次数约为30次 */ for (m = 0; m < 1000; m ) { /* 第1步:发起I2C总线启动信号 */ i2c_Start(); /* 第二步:启动控制字节,高7bit是地址,bit0是读写控制位,0表示写作,1表示读 */ i2c_SendByte(HTDU21D_ADDRESS | I2C_WR); /* 这是写指令 */ /* 第三步:发送一个时钟,判断器件是否正确响应 */ if (i2c_WaitAck() == 0) { break; } } if (m == 1000) { goto cmd_fail; /* EEPROM器件写超时 */ } /* 第4步:发送字节地址,24C02只有256字节,所以一个字节就够了,如果是24C04以上,这里需要连发多个地址 */ i2c_SendByte((uint8_t)Addr); /* 第5步:等待ACK */ if (i2c_WaitAck() != 0) { goto cmd_fail; /* EEPROM器件无应答 */ } } /* 第六步:开始写入数据 */ i2c_SendByte(pWriteBuf[i]); /* 第7步:发送ACK */ if (i2c_WaitAck() != 0) { goto cmd_fail; /* EEPROM器件无应答 */ } Addr ; /* 地址增1 */ } /* 成功执行命令,发送I2C总线停止信号 */ i2c_Stop(); return 1; cmd_fail: /* 命令执行失败后切记发送停止信号,避免影响I2C总线上其他设备 */
/* 发送I2C总线停止信号 */
i2c_Stop();
return 0;
}
获取温湿度数据
/*************************************************
**函数名称 : float Htu_Measure(uint8_t order
**功 能 : htu21d测量温湿度
**参 数 : order:测量触发命令
**返 回 值 : temp--温度值 humi--湿度值
*************************************************/
float Htu_Measure(uint8_t _ucOrder)
{
uint8_t ucMsb,ucLsb;
volatile float f_Temp,f_Humi,f_RetVal;
i2c_Start();
i2c_SendByte(HTDU21D_ADDRESS_WR); //地址+写命令
i2c_WaitAck();
// if(i2c_WaitAck()==0)
// printf("3应答\n");
// else
// printf("3不应答\n");
SysTick_Delay_ms(4);
i2c_SendByte(_ucOrder); //触发测量命令
i2c_WaitAck();
// if(i2c_WaitAck()==0)
// printf("4应答\n");
// else printf("4不应答\n");
do{
SysTick_Delay_ms(5);
i2c_Start();
i2c_SendByte(HTDU21D_ADDRESS_RD); //地址+读命令
}while(i2c_WaitAck() == 1);
ucMsb = i2c_ReadByte();
i2c_Ack();
SysTick_Delay_ms(5);
ucLsb = i2c_ReadByte();
i2c_Ack();
SysTick_Delay_ms(5);
i2c_NAck();
i2c_Stop();
ucLsb &= 0xfc; //设置分辨率,最低两位为0,温度:14位;湿度:12位
f_RetVal = ucMsb * 256 + ucLsb;/*MSB=(MSB<<=8)+LSB;即将MSB移位到高8位*/
if(_ucOrder == NOHOLD_TEMP_MEASURE)
{
f_Temp = (175.72)*f_RetVal/65536-46.85;//温度:T= -46.85 + 175.72 * ST/2^16
return f_Temp;
}
else if(_ucOrder == NOHOLD_HUMI_MEASURE)
{
f_Humi = (f_RetVal*125)/65536-6;//湿度: RH%= -6 + 125 * SRH/2^16
return f_Humi;
}
else
return 0;
}
测试展示
参考:
- STM32 驱动温湿度传感器 HTU21D
- 野火I2C相关视频