STM32驱动 HTU21D温湿度传感器

STM32驱动 HTU21D温湿度传感器

温湿度传感器模块HTU21D产品简介

基于法国Humirel公司高性能的湿度感应元件制成,新一代HTU21D温度和湿度传感器在尺寸与智能方面建立了新的标准:它嵌入了适于回流焊的双列扁平无引脚DFN 封装, 底面3x3mm,高度1.1mm。传感器输出经过标定的数字信号,标准 I2C格式。多样化的输出方式,宽的工作电压范围,同时具有很高的温度精度和湿度精度。HTU21系列模块专为低功耗小体积应用设计,具有良好的品质、快的响应速度、抗干扰能力强、性价比高等优点,微小的体积(3x3mm)、极低的功耗
HTU21D封装
数字输出温湿度传感器模块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^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;
} 

测试展示

参考:

  1. STM32 驱动温湿度传感器 HTU21D
  2. 野火I2C相关视频
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

会点灯的大力水手

科研需要动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值