高情已逐晓云空,不与梨花同梦。 ————苏轼《
西江月·梅花
》
HTU21
温湿度传感器采用基于法国Humirel
高性能的湿度感应元件制成,HTU21
系列模块为OEM
客户应用提供了准确可靠的温湿度测量数据。HTU21
不仅输出方式多样化,工作电压范围比较宽,同时具有很高的温度精度和湿度精度。
HTU21D
温湿度传感器可通过一个微控制器的接口和模块的连接达到温度和湿度的数字输出。HTU21D
的分辨率可以通过输入命令进行改变( 8/12bit
乃至 12/14bit
的 RH/T
),传感器可以检测到电池低电量状态,并且输出校验和,有助于提高通信的可靠性。传感器输出经过标定的数字信号,标准 I2C
格式。
补充说明:
OEM
为Original Equipment Manufacturer(原始设备制造商)
之缩写,意为通常拥有充裕、廉价的劳动力,提供国际市场所需的制造、组装产品之委托服务的厂商,即代工厂。由制造方负责生产、提供人力和场地,采购方负责销售的一种现代流行生产方式。
传感器的特点 | 应用举例 |
---|---|
完整的互换性,在标准环境下无需校准 | 家庭应用 |
长期处于湿度饱和状态,可以迅速恢复 | 医疗领域 |
自动组装工艺生产,无铅材料制成,适合回流焊 | 打印机 |
每个传感器具有单独标记,可追溯生产源头 | 加湿器 |
这四个引脚分别为GND, VCC(+), SCL, SDA
,具体的引脚已经在简介的图中标明了。
VCC
:接电源正极 3.3~5V
;GND
:接地;SCL
(串行时钟输入):PB10 (I2C2_SCL)
SDA
(船型数据端口):PB11 (I2C2_SDA)
接线表:
温湿度传感器的接口 | STM32的IO口 | 设置的工作模式 |
---|---|---|
VCC | VCC(3.3V) | - |
GND | GND | - |
SCL(串行时钟输入) | PB10 | I2C的时钟信号线 |
SDA(串行数据端口) | PB11 | I2C的数据信号线 |
- | PA9 | TX(USART1 串口1通信) |
- | PA10 | RX(USART1 串口1通信) |
(VDD, GND)
:HTU21
的供电范围为 1.8VDC - 3.6VDC
,推荐电压为 3.0V
。电源(VDD
)和接地(VSS
)之间须连接一个0.1uF
的去耦电容,且电容的位置应尽可能靠近传感器。SCL
):SCL
用于微处理器与 HTU21D
之间的通讯同步。由于接口包含了完全静态逻辑,因而不存在最小 SCL
频率。DATA
): DATA
引脚为三态结构,用于读取传感器数据。当向传感器发送命令时, DATA
在 SCK
上升沿有效且在 SCK
高电平时必须保持稳定。 DATA
在 SCK
下降沿之后改变。当从传感器读取数据时, DATA
在 SCK
变低以后有效,且维持到下一个 SCK
的下降沿。为避免信号冲突,微处理器应驱动 DATA
在低电平。需要一个外部的上拉电阻(例如: 10kΩ
)将信号提拉至高电平。上拉电阻通常已包含在微处理器的 I/O
电路中。STM32
单片机与传感器的 “交流”将传感器上电,电压所选择的VDD
电源电压(范围介于1.8V与3.6V之间
),上电后,传感器最多需要15毫秒时间(此时SCL
为高电平)用来达到空闲状态,即做好准备接收有主机(MCU
)发送的命令(做好与MCU
交流的准备)。
启动传输,发送一位数据,包括DATA
线在SCK
线高电平期间,出现一个向低电平的跳变。
I2C
总线传输数据过程中的三种类型信号:
SCL
为高电平时,SDA
由高电平向低电平跳变,开始传送数据。SCL
为高电平时,SDA
由低电平向高电平跳变,结束传送数据。I2C
在接收到 8bit
数据后,向发送数据的 I2C
发出特定的低电平脉冲,表示已收到数据。 CPU
向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU
接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为受控单元出现故障。终止传输,停止发送数据时,包括DATA线在SCK线高电平期间,出现一个向高电平的跳变。
I2C
数据传输SCL
时钟电平为低, 可以改换 SDA
数据线的电平,在 SCL
上升沿的过程将 SDA
数据发送出去。SCL
为高电平时,SDA
上的数据保持稳定。
在非主机模式下, MCU 需要对传感器状态进行查询。此过程通过发送一个启动传输时序,之后紧接着是如图所示的 I2C 首字节(1000 0001)来完成。如果内部处理工作完成,单片机查询到传感器发出的确认信号后,相关数据就可以通过 MCU 进行读取。如果测量处理工作没有完成,传感器无确认位(ACK)输出,此时必须重新发送启动传输时序。
传感器内部设置的默认分辨率为相对湿度12位和温度14 位。 SDA
的输出数据被转换成两个字节的数据包,高字节MSB
在前(左对齐)。每个字节后面都跟随一个应答位。两个状态位,即LSB
的后两位在进行物理计算前须置'0'
。
具体学习可以参考:博客网站-RCC学习
输入项目名称和路径。(注:路径中不允许出现中文。)
选择应用的IDE
,开发环境MDK-ARM V5
每个外设生成独立的 ’.c/.h’ 文件
main.c
GPIO
初始化代码生成在 gpio.c
中。在main.c
文件中,添加一下代码:
fget
和fput
函数:勾选微库(这个很重要),添加头文件
;/* USER CODE BEGIN Includes */
#include
/* USER CODE END Includes */
/**
* 函数功能: 重定向c库函数printf到DEBUG_USARTx
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
int fputc(int ch, FILE *f)
{
HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xffff);
return ch;
}
/**
* 函数功能: 重定向c库函数getchar,scanf到DEBUG_USARTx
* 输入参数: 无
* 返 回 值: 无
* 说 明:无
*/
int fgetc(FILE *f)
{
uint8_t ch = 0;
HAL_UART_Receive(&huart1, &ch, 1, 0xffff);
return ch;
}
htu21d
文件对(.c/.h):htu21d.h
:#ifndef __HTU21D_H_
#define __HTU21D_H_
#include "i2c.h"
//句柄定义
#define HTU21D_I2C hi2c2
//读写命令
#define HTU21D_WRITE_CMD 0x80
#define HTU21D_READ_CMD 0x81
//传感器命令
#define HTU21D_TRIGGER_T_M 0xe3 //触发温度测量(保持主机) 0xe3 = 1110 0011
#define HTU21D_TRIGGER_RH_M 0xe5 //触发相对湿度测量(保持主机) 0xe5 = 1110 0101
#define HTU21D_TRIGGER_T_NO_M 0xf3 //触发温度测量(非保持主机) 0xf3 = 1111 0011
#define HTU21D_TRIGGER_RH_NO_M 0xf5 //触发相对湿度测量(非保持主机) 0xf5 = 1111 0101
#define HTU21D_WRITE_USER_REGISTER 0xe6 //写用户寄存器 0xe6 = 1110 0110
#define HTU21D_READ_USER_REGISTER 0xe7 //读用户寄存器 0xe7 = 1110 0111
#define HTU21D_SOFT_RESER 0xfe //软复位 0xfe = 1111 1110
//HTU21D值结构体
typedef struct{
float temperature; //温度
float humidity; //湿度
}HTU21D_Value;
/*软件复位*/
void HTU21D_SoftReset(void);
/*读用户寄存器*/
uint8_t HTU21D_ReadUserReg(void);
/*读温度和湿度(无等待主控芯片)*/
float read_temperture(uint8_t cmd);
float read_humidity(uint8_t cmd);
#endif /*__HTU21D_H_*/
htu21d.c
:#include "HTU21D.h"
static HTU21D_Value HTU21DValue;
/*外部函数*/
/*软件复位*/
void HTU21D_SoftReset(void)
{
HAL_I2C_Master_Transmit(&HTU21D_I2C, HTU21D_WRITE_CMD<<1, (uint8_t *)HTU21D_SOFT_RESER, 1, 100);//发送软件复位
}
/*读用户寄存器*/
uint8_t HTU21D_ReadUserReg(void)
{
uint8_t data=0;
HAL_I2C_Master_Transmit(&HTU21D_I2C, HTU21D_WRITE_CMD<<1, (uint8_t *)HTU21D_READ_USER_REGISTER, 1, 100);//发送读用户寄存器指令
HAL_I2C_Master_Receive(&HTU21D_I2C, HTU21D_WRITE_CMD<<1, &data, 1, 100);
return data;
}
/*读温度和湿度*/
float read_temperture(uint8_t cmd)
{
uint8_t data = cmd;
uint8_t tempBuff[2];
uint16_t temp1=0;
HAL_I2C_Master_Transmit(&HTU21D_I2C, HTU21D_WRITE_CMD, &data, 1, 100);
HAL_I2C_Master_Receive(&HTU21D_I2C, HTU21D_READ_CMD, tempBuff, 2, 100);
temp1 = (uint16_t)tempBuff[0];
temp1 <<= 8;
temp1 |= tempBuff[1];
HTU21DValue.temperature = -46.85 + 175.72*((float)temp1/(1<<16)); //数据手册温度转换公式
return HTU21DValue.temperature;
}
float read_humidity(uint8_t cmd)
{
uint8_t data = cmd;
uint8_t humiBuff[2];
uint16_t humi1=0;
HAL_I2C_Master_Transmit(&HTU21D_I2C, HTU21D_WRITE_CMD, &data, 1, 100);
HAL_I2C_Master_Receive(&HTU21D_I2C, HTU21D_READ_CMD, humiBuff, 2, 100);
humi1 = (uint16_t)humiBuff[0];
humi1 <<= 8;
humi1 |= humiBuff[1];
HTU21DValue.humidity = -6 + 125*((float)humi1/(1<<16)); //数据手册湿度转换公式
return HTU21DValue.humidity;
}
main.c
中添加代码:/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
float temperture; //接收温度
float humidity;//接收湿度
uint8_t cmd;
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_I2C2_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
cmd = HTU21D_ReadUserReg();
temperture = read_temperture(cmd);
humidity = read_humidity(cmd);
printf("读取当前环境状态:\r\n");
printf("温度为:%f 摄氏度\r\n",temperture);
printf("湿度:%f RH\r\n",humidity);
printf("\n");
HAL_Delay(10000);
}
/* USER CODE END 3 */
}