前言
高情已逐晓云空,不与梨花同梦。 ————苏轼《
西江月·梅花
》
一、简介
以法国为基础
Humirel
由高性能湿度感应元件制成,HTU21
系列模块为OEM
客户应用程序提供了准确可靠的温湿度测量数据。HTU21
不仅输出方式多样化,工作电压范围广,而且温湿度精度高。
HTU21D
通过微控制器的接口和模块连接,温湿度传感器可以实现温湿度的数字输出。HTU21D
输入命令可以改变分辨率( 8/12bit
乃至 12/14bit
的 RH/T
),传感器可以检测到电池的低功率状态,并进行输出验证,有助于提高通信的可靠性。
OEM
为Original Equipment Manufacturer(原始设备制造商)
之缩写,制造商通常拥有丰富、廉价的劳动力,提供国际市场所需的制造和组装产品的委托服务,即OEM托服务。制造商负责生产、提供人力和场地,买方负责销售。
传感器的特点 | 应用举例 |
---|---|
在标准环境下,不需要校准完整的互换性 | 家庭应用 |
长期处于湿度饱和状态,能迅速恢复 | 医疗领域 |
适用于回流焊 | 打印机 |
每个传感器都有单独的标记,可以追溯到生产来源 | 加湿器 |
- 数据手册下载地址:温湿度敏感芯片传感器HTU21D
实物图:
二、引脚配置
这四个引脚分别是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通信) |
HTU21
供电范围为1.8VDC - 3.6VDC
,推荐电压为3.0V
。电源(VDD
)和接地(VSS
)之间必须连接一个0.1uF
电容器应尽可能靠近传感器。SCL
用于微处理器和HTU21D
通信同步。由于界面包含完全静态逻辑,因此没有最小值SCL
频率。-
DATA
引脚是读取传感器数据的三态结构。当命令发送到传感器时,DATA
在SCK
上升边有效且在SCK
平时高电必须保持稳定。DATA
在SCK
下降边缘后变化。从传感器读取数据时,DATA
在SCK
降低后有效,保持到下一个SCK
下降边缘。微处理器应驱动以避免信号冲突DATA
低电平。需要外部上拉电阻(例如:10kΩ
)将信号提升到高电平。微处理器中通常包含上拉电阻I/O
电路中。
三、STM32
单片机和传感器 “交流”
1. 启动传感器
将传感器上电,电压所选择的VDD
电源电压(范围介于1.8V与3.6V之间
),传感器上电后最多需要15毫秒(此时)SCL
用于实现高电平的空闲状态,即准备接收主机(MCU
)发送命令(做好和MCU
准备沟通)。
a id="2__65">2. 启动信号
启动传输,发送一位数据,包括DATA
线在SCK
线高电平期间,出现一个向低电平的跳变。
-
-
SCL
为高电平时,SDA
由高电平向低电平跳变,开始传送数据。 -
SCL
为高电平时,SDA
由低电平向高电平跳变,结束传送数据。 - 接收数据的
I2C
在接收到8bit
数据后,向发送数据的I2C
发出特定的,CPU
向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU
接收到应答信号后,根据实际情况作出是否继续传递信号的判断。
-
- 这些信号中,,结束信号和应答信号,都可以不要。
3. 停止信号
终止传输,停止发送数据时,包括DATA线在SCK线高电平期间,出现一个向高电平的跳变。
4. I2C
数据传输
SCL
时钟电平为低, 可以改换 SDA
数据线的电平,在 SCL
上升沿的过程将 SDA
数据发送出去。SCL
为高电平时,SDA
上的数据保持稳定。
5. HTU21D数据测量
-
MCU与传感器之间的通讯方式有两种不同的工作方式:主机模式和非主机模式
- 主机模式下:在测量过程中,SCL线被封锁(由传感器进行控制),
- 非主机模式下:在测量过程中,SCL线依然保持开放状态,可进行其他通讯。
在非主机模式下, MCU 需要对传感器状态进行查询。此过程通过发送一个启动传输时序,之后紧接着是如图所示的 I2C 首字节(1000 0001)来完成。如果内部处理工作完成,单片机查询到传感器发出的确认信号后,相关数据就可以通过 MCU 进行读取。如果测量处理工作没有完成,传感器无确认位(ACK)输出,此时必须重新发送启动传输时序。
6. HTU21D数据读取与转换
传感器内部设置的默认分辨率为。 SDA
的输出数据被转换成两个字节的数据包,高字节MSB
在前(左对齐)。每个字节后面都跟随一个应答位。两个状态位,即LSB
的后两位在进行物理计算前须置'0'
。
四、新建工程
1.打开STM32CubeMX软件,点击“新建工程”
2. 选择 MCU 和封装
3.配置时钟
博客网站-RCC学习
4.配置调试模式
5.串口(USART1)配置
6. I2C配置
7.生成代码
输入项目名称和路径。 选择应用的IDE
,开发环境MDK-ARM V5
- 所有初始化代码都生成在
main.c
- 初始化代码生成在对应的外设文件。 如
GPIO
初始化代码生成在gpio.c
中。
8.构建工程
四、编写代码
在main.c
文件中,添加一下代码:
- 重写
fget
和fput
函数:,添加头文件<stdio.h>
;
/* USER CODE BEGIN Includes */
#include<stdio.h>
/* 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.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;
}
/**
* @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 */
}