STM32驱动 HTU21D温湿度传感器
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 0x40//查询数据手册或者看时序图得到 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个字节 *//* 每读完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简单的处理方法为:按字节写操作模式,没写1个字节,都发送地址为了提高连续写的效率: 本函数采用page wirte操作。*/Addr = Address; for (i = 0; i < Size; i++){/* 当发送第1个字节或是页面首地址时,需要重新发起启动信号和地址 */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();/* 第2步:发起控制字节,高7bit是地址,bit0是读写控制位,0表示写,1表示读 */i2c_SendByte(HTDU21D_ADDRESS | I2C_WR); /* 此处是写指令 *//* 第3步:发送一个时钟,判断器件是否正确应答 */if (i2c_WaitAck() == 0){break;}}if (m == 1000){goto cmd_fail; /* EEPROM器件写超时 */}/* 第4步:发送字节地址,24C02只有256字节,因此1个字节就够了,如果是24C04以上,那么此处需要连发多个地址 */i2c_SendByte((uint8_t)Addr);/* 第5步:等待ACK */if (i2c_WaitAck() != 0){goto cmd_fail; /* EEPROM器件无应答 */}}/* 第6步:开始写入数据 */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^16return f_Temp;}else if(_ucOrder == NOHOLD_HUMI_MEASURE){f_Humi = (f_RetVal*125)/65536-6;//湿度: RH%= -6 + 125 * SRH/2^16return f_Humi;}elsereturn 0;
}
测试展示
参考:
- STM32 驱动温湿度传感器 HTU21D
- 野火I2C相关视频