基于STM32F030驱动SHT10温湿度传感器

2023-05-16

目的

了解温湿度传感器SHT10的驱动原理,通过配置 STM32F030 的GPIO来采集温湿度传感器的温度、湿度和露点的值。

原理

SHT1x (包括 SHT10, SHT11 和 SHT15) 属于Sensirion温湿度传感器家族中的贴片封装系列。传感器将传感元件和信号处理电路集成在一块微型电路板上,输出完全标定的数字信号。传感器具有体积小、响应速度快、接口简单、性价比高等特点。

传感器接口定义如下:

SHT10的供电电压范围为2.4v-5.5v,建议供电电压为3.3v。SHT1x的串行接口,在传感器信号的读取及电源损耗方面,都做了优化处理;传感器不能按照I2C协议编址,但是如果I2C总线上没有挂接别的元件,传感器可以连接到I2C总线上,但单片机必须按照传感器的协议工作。

串行时钟输入(SCK): SCK 用于单片机与SHT10之间的通讯同步。

串行数据(DATA):DATA引脚为三态结构,用于读取传感器数据。当向传感器发送命令时, DATA在SCK上升沿有效且在SCK高电平时必须保持稳定,DATA在SCK下降沿之后改变。

传感器的通讯如下:

  • 启动传感器:首先,选择供电电压后将传感器通电,上电速率不能低于1V/ms。通电后传感器需要11ms 进入休眠状态,在此之前不允许对传感器发送任何命令。
  • 发送命令:用一组“启动传输”时序,来完成数据传输的初始化。它包括当SCK 时钟高电平时DATA 翻转为低电平,紧接着SCK变为低电平,随后是在SCK时钟高电平时DATA 翻转为高电平。启动时序如下图:

 后续命令包含三个地址位(目前只支持“000”),和五个命令位。SHT1x会以下述方式表示已正确地接收到指令:在第8个SCK时钟的下降沿之后,将DATA下拉为低电平(ACK 位)。在第9个SCK时钟的下降沿之后,释放DATA(恢复高电平)。命令集如下:

  •  温湿度测量:发布一组测量命令(‘00000101’表示相对湿度RH,‘00000011’表示温度T)后,控制器要等待测量结束。这个过程需要大约20/80/320ms,分别对应8/12/14bit测量。SHT1x 通过下拉DATA至低电平并进入空闲模式,表示测量的结束。控制器在再次触发SCK 时钟前,必须等待这个“数据备妥”信号来读出数据。接着传输2个字节的测量数据和1个字节的CRC 奇偶校验(可选择读取)。控制器需要通过下拉DATA为低电平,以确认每个字节。所有的数据从MSB开始,右值有效(例如:对于12bit 数据,从第5个SCK时钟起算作MSB;而对于8bit 数据,首字节则无意义。默认分辨率:14bit (温度) 和 12bit (湿度)可以被降低为12和8bit. 尤其适用于要求测量速度极高或者功耗极低的应用)。在收到CRC的确认位之后,表明通讯结束。如果不使用CRC-8校验,控制器可以在测量值LSB后,通过保持ACK高电平终止通讯。在测量和通讯完成后,SHT1x自动转入休眠模式。
  • 通讯复位时序:如果与SHT1x通讯中断,可通过下列信号时序复位:当DATA保持高电平时,触发SCK时钟9次或更多,接着发送一个“传输启动”时序。复位时序如下:

 

  1. 测量时序:传感器的通讯过程为:发送开始时序,启动传感器 -> 发送命令 -> 等待传感器应答及测量结束 -> 接收传感器数据值 -> 接收CRC校验数据 -> 休眠,等待下一次传输开始。

  信号转换:

  • 相对湿度的转换:为获得精确的测量数据,建议用以下公式进行信号转换。

RHlinear = C1 + C2 * SORH + C3 * SORH2(%RH)

公式参数如下:

  •  湿度信号的温度补偿:由于实际温度与测试参考温度25℃ (~77℉)的显著不同, 湿度信号需要温度补偿。

RHtrue = (T℃ - 25) *(t1 + t2 * SORH) + RHlinear

公式参数如下:

  • 温度值转换:可用如下公式将数字输出 (SO T ) 转换为温度值。

T = d1+d2 * SOT

公式参数如下:

  •  露点的定义:露点温度指空气在此温度下能保持最多的水汽,当温度冷却到露点,空气变得饱和,就会出现雾、露或霜。SHT1x并不直接进行露点测量,但露点可以通过温度和湿度读数计算得到。由于温度和湿度在同一块集成电路上测量,所以SHT1x可测量露点。露点计算公式如下:

步骤

  • 在工程中新建两个文件分别命名为sensor_humidity.c和sensor_humidity.h,并将sensor_humidity.c文件保存在该工程文件夹中,并添加sensor_humidity.h文件路径。
  • 在sensor_humidity.h文件中,引用相关头文件,定义1微秒延时函数和操作指令相关宏定义(因传感器时序比较严格,而滴答定时器延时在短时间存在些误差,所以需要定义一个1us的机器周期延时函数,供程序使用),最后进行函数声明。
#ifndef _SENSOR_HUMIDITY_H_
#define _SENSOR_HUMIDITY_H_

#include "stm32f0xx.h"
#include "bsp_systick.h"
#include <stdbool.h>
#include <math.h>
	
enum {TEMP, HUMI};

 // 定义内联延时函数
static inline void SHT10_DELAY_1US(void)
{
	__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
	__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
	__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
	__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
	__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
	__nop();__nop();__nop();__nop();__nop();__nop();__nop();__nop();
}	

#define SHT10_GPIOx  	GPIOB
#define Pin_SCK		GPIO_Pin_10
#define Pin_SDA		GPIO_Pin_11

#define SHT10_SCK_L	SHT10_GPIOx->ODR &= ~Pin_SCK
#define SHT10_SCK_H	SHT10_GPIOx->ODR |=  Pin_SCK

#define SHT10_SDA_L	SHT10_GPIOx->ODR &= ~Pin_SDA
#define SHT10_SDA_H	SHT10_GPIOx->ODR |=  Pin_SDA

#define Read_SDA_Pin	SHT10_GPIOx->IDR & Pin_SDA

#define  NO_ACK       0
#define  ACK          1

#define ERR_NONE	     0
#define ERR_TIME_OUT   1
#define ERR_NO_ACK     2
#define ERR_CHECK_NUM  4

#define STATUS_REG_W        0x06  // 写状态寄存器    
#define STATUS_REG_R        0x07  // 读状态寄存器
#define MEASURE_TEMP        0x03  // 测量温度    
#define MEASURE_HUMI        0x05  // 测量湿度    
#define SOFTRESET		  0x1E  // 复位   

void SHT10_Init(void);
uint8_t SHT10_GetMessure(float *T , float *RH, float* Td);

#endif
  • 在sensor_humidity.c文件中添加相应头文件。
  • 在sensor_humidity.c文件中定义SHT10_Init()函数,函数中初始化了传感器使用到GPIO引脚,最后对传感器进行复位。
// 引脚初始化
void SHT10_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;        

	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE); // 使能时钟       
   
	GPIO_InitStructure.GPIO_Pin = Pin_SCK | Pin_SDA; // 传感器对应IO口
	GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; // 开漏模式
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; // 上拉
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; // 输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_Level_3; // 50MHZ   
	GPIO_Init(SHT10_GPIOx, &GPIO_InitStructure); // 初始化GPIO
	
	SHT10_Reset(); // 传感器复位
}
  • 在sensor_humidity.c文件中添加SHT10_Start()函数,通过这个函数发送开始传输信号。
// 开始传输信号
void SHT10_Start(void)
{
	SHT10_SDA_H; // 将数据线拉高
	SHT10_SCK_L; // 将信号线拉低
	SHT10_DELAY_1US(); // 延时1us
	SHT10_SCK_H;
	SHT10_DELAY_1US();
	SHT10_SDA_L;
	SHT10_DELAY_1US();
	SHT10_SCK_L;
	SHT10_DELAY_1US();
	SHT10_SCK_H;
	SHT10_DELAY_1US();
	SHT10_SDA_H;
	SHT10_DELAY_1US();
	SHT10_SCK_L;
	SHT10_DELAY_1US(); 
}
  • 在sensor_humidity.c文件中添加SHT10_Reset()函数,用于通讯复位。
// 通讯复位
void SHT10_Reset(void)
{
	SHT10_SDA_H;
	SHT10_SCK_L;	
	
	for(uint8_t i=0; i<9; i++) // 触发SCK时钟9次      
	{
	    SHT10_SCK_H;
	    SHT10_DELAY_1US();
	    SHT10_SCK_L;
	    SHT10_DELAY_1US();
	}
}
  • 在sensor_humidity.c文件中添加SHT10_WriteByte()函数,实现向传感器写一个字节的操作。
// 向传感器写1字节
bool SHT10_WriteByte(uint8_t value)
{
	uint8_t state = ERR_NONE;
	for(uint8_t i=0; i<8; i++) // 写一个字节
	{
	    if(value&0x80)
		SHT10_SDA_H;
	    else
		SHT10_SDA_L;
	    SHT10_DELAY_1US();
	    SHT10_SCK_H;
	    SHT10_DELAY_1US();
	    SHT10_DELAY_1US();
	    SHT10_SCK_L;
	    SHT10_DELAY_1US();
	    value <<= 1;
	}
	SHT10_SCK_H;
	SHT10_DELAY_1US();
	if(Read_SDA_Pin) // 读取SHT10的应答位
	{
	    state = ERR_NO_ACK;
	}
	SHT10_SCK_L;
	SHT10_DELAY_1US();
	return state;
}
  • 在sensor_humidity.c文件中添加SHT10_ReadByte()函数,用来从传感器中读取一个字节数据。
// 从传感器中读1字节数据
uint8_t SHT10_ReadByte(uint8_t Ack)
{
	uint8_t val = 0;
	           
	for(uint8_t i=0; i<8; i++) // 读取1字节数据
	{
	    val <<= 1;
	    SHT10_SCK_H;
	    SHT10_DELAY_1US();
	    if(Read_SDA_Pin)
		val |= 1;
	    SHT10_SCK_L;		
	    SHT10_DELAY_1US();
	}         
	if(Ack)           
	    SHT10_SDA_L;// 应答,则会接受后面的数据(校验数据)           
	else              
	    SHT10_SDA_H; // 不应答        
	SHT10_DELAY_1US();
	SHT10_SCK_H;
	SHT10_DELAY_1US();
	SHT10_SCK_L;
	SHT10_DELAY_1US();
	SHT10_SDA_H;
	return val;   
}
  • 在sensor_humidity.c文件中添加SHT10_Measure()函数,从传感器中读取温湿度。

第一步:发送开始传输信号,紧接着发送测量命令。

第二步:等待转换是否完成,如果等待超时则退出函数,否则读取传感器数据并计算,最后返回读取的值。

// 从温湿度传感器读取温湿度
uint8_t SHT10_Measure(uint8_t cmd, uint16_t *p_value)
{
	uint8_t status = ERR_NONE;
	
	// 开始传输
	SHT10_Start(); 
	
	// 写测量命令
	if(SHT10_WriteByte(cmd) == ERR_NO_ACK) 
	{
	    SHT10_Reset();
	    status = ERR_NO_ACK;
	    return status;
	}
	
	// 等待DATA信号被拉低,正常应该在320ms内测量完成
	for(uint32_t i = 0; i < 72000000; i++) 
	{
	    if(!(Read_SDA_Pin)) break; // 检测到DATA被拉低了,跳出循环         
	}
	
	// 检查转换完成状态
	if(Read_SDA_Pin) // 如果等待超时了
	{
	    SHT10_Reset();
	    status = ERR_TIME_OUT;
	    return status;
	}
	else // 完成测量
	{
	    uint8_t value_H = SHT10_ReadByte(ACK); // 读取高8位数据
	    uint8_t value_L = SHT10_ReadByte(ACK); // 读取低8位数据
	    uint8_t checksum = SHT10_ReadByte(NO_ACK); // 读取校验数据
//	    if(checksum) // 校验不正确
//	    {
//		status = ERR_CHECK_NUM;
//	    }


	    *p_value = (value_H << 8) | value_L;
	}
	return status;
}
  • 在sensor_humidity.c文件中添加SHT10_Calculate()函数,通过这个函数实现校准温度和湿度的值。
// 计算温湿度的值
void SHT10_Calculate(uint16_t SOt, uint16_t SOrh, float* T, float* RH)
{
const float C1=-2.0468f;    // 12 Bit
  	const float C2= 0.0367f;    // 12 Bit
  	const float C3=-1.5955e-6f; // 12 Bit
	
  	const float t1=0.01f;     // 12 Bit
  	const float t2=0.00008f;  // 12 Bit	
	
	const float d1=-39.6f;  // for 3v
	const float d2= 0.01f;  // for 14 Bit
	
	*T = d1 + d2 * SOt; // 计算温度值
	
	float RH_Linear = C1 + C2 * SOrh + C3 * SOrh	* SOrh;	// 计算湿度值
	*RH = (*T - 25) * (t1 + t2 * SOrh) + RH_Linear; // 湿度的温度补偿,计算实际的湿度值
}
  • sensor_humidity.c文件中添加SHT10_CalcuDewPoint()函数,通过这个函数实现计算露点的值。
// 计算露点
void SHT10_CalDewPoint(float T, float RH, float* Td)
{
	float Tn = T>=0 ? 243.12f : 272.62;
	float m  = T>=0 ? 17.62f  : 22.46;
	float a = log(RH); // / 100.f
	float b = (m * T) / (Tn + T);
	*Td = Tn * (a + b) / (m - a -b);
}
  • 在sensor_humidity.c文件中添加SHT10_GetMessure()函数,函数中首先使用SHT10_Measure()函数测量并计算传感器的温湿度值,然后通过SHT10_CalcuDewPoint()函数计算露点的值,最后通过return返回测量的状态。
// 测量温湿度及露点
uint8_t SHT10_GetMessure(float *T , float *RH, float* Td)
{
	uint16_t SOt, SOrh;
	
	uint8_t status_temp = SHT10_Measure(MEASURE_TEMP, &SOt);                  
	uint8_t status_humi = SHT10_Measure(MEASURE_HUMI, &SOrh); 	
	
	if(status_temp == ERR_NONE && status_humi == ERR_NONE)
	{
	    SHT10_Calculate(SOt, SOrh, T, RH); // 计算得到温度、湿度
	    SHT10_CalDewPoint(*T, *RH, Td); // 计算出露点值,并且返回
	}
	return status_temp | status_humi;
}
  •  在main.c文件的main()函数中实现测量温度、湿度以及露点值功能。

第一步:引用相应头文件。

第二步:定义存储温度、湿度、露点值的变量。

第三步:在主函数中初始化滴答定时器、传感器和串口。

第四步:在主函数的while循环中调用SHT10_GetMessure测量温度、湿度和露点值,最后使用printf函数通过串口打印。

#include "Sensor_Humidity.h"
#include "bsp_usart.h" 
#include <stdio.h>

float RH; // 湿度值变量
float T;  // 温度值变量
float Td; // 露点值变量

int main()
{
	SYSTICK_Init(1); // 滴答定时器初始化
	SHT10_Init();	// 传感器初始化
	USART1_Init(); // 串口初始化	
	while(1)
	{
	    if(SHT10_GetMessure(&T ,&RH, &Td) == ERR_NONE)
	    {
		printf("T: %.2f RH: %.2f Td: %.2f \r\n",T, RH, Td);
	    }
	    SYSTICK_DelayMs(500);
	}
}

现象

将程序下载到开发板中,等待传感器初始化后,看到串口调试助手打印出温度、湿度和露点的值。

 更多交流欢迎关注作者抖音号:81849645041​​​​​​

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于STM32F030驱动SHT10温湿度传感器 的相关文章

  • 基于RPLIDAR激光雷达开发无人机机载室内二维重建装置(2)——RPLIDAR测试

    从官网上 xff08 http www slamtec com xff09 下载开发用的SDK及数据手册等相关资料 xff0c 但Arduino相关资料貌似已失效 xff0c 之后尝试从其他渠道下载 先安装对应系统的驱动 xff0c 之后打
  • Visio2016与office2016安装解决方法终极版

    基本解决方案 删除注册表 office软件在我们日常生活中的应用十分广泛 xff0c 在购买电脑时大部分会给电脑装上office家庭版 xff0c 但是有些人由于工作需要可能使用office更多的功能 xff0c 因此可以选择安装专业版 而
  • 微带天线学习

    微带天线学习 侧馈矩形微带天线同轴馈电矩形微带天线双频微带天线 学习方法是根据HFSS软件学习微带天线的优化 参数计算 xff0c 以及根据HFSS仿真结果进一步理解微带天线中参数对天线性能的影响 微带天线贴片尺寸计算方法及matlab代码
  • Zotero IEEE trans期刊cls格式调整

    Zotero IEEE trans期刊cls格式调整 Zotero软件自带的IEEE期刊的引用格式不符合期刊投稿要求 xff0c 因此需要改变cls文件 xff0c 改变引用格式 cls格式编辑网站 xff1a https editor c
  • ADS2021安装

    1 ADS简介 先进设计系统 Advanced Design system xff08 ADS xff09 Agilent Technologies 是领先的电子设计自动化软件 xff0c 适用于射频 微波和信号完整性应用 2 ADS的安装

随机推荐

  • Mysql整体介绍(适用于5.X版本)(上)(标贝科技)

    标贝科技 https ai data baker com source 61 qwer12 填写邀请码fwwqgs xff0c 每日免费调用量还可以翻倍 Mysql整体介绍 xff08 适用于5 X版本 xff09 标贝科技 Mysql 8
  • TE、TM、TEM模式的区别

    在一众电磁仿真软件的使用中 xff0c 牵涉到平面波的设置或Floquet端口的设置 在设置平面波时 xff0c 论坛里有不少人提到TE波 TM波 xff1b 在设置Floquet端口时 xff0c 又有不少人提到TE极化 TM极化 其实
  • linux下TCP socket编程入门案例(二)——非阻塞的TCP server&client

    文章目录 1 相关概念介绍1 1 阻塞与非阻塞1 2 两者区别1 3 select模型 2 编码实现2 1 代码改进2 2 实现服务端客户端 3 运行结果 在 上一篇 阻塞的TCP server amp client 中 xff0c 介绍了
  • cartographer 主从机rviz订阅地图出错

    cartographer 主从机rviz订阅地图出错 配置及想法 机器人以及虚拟机都是ubuntu16 43 kinetic xff0c 本意想在虚拟机端查看机器人cartographer的建图情况 直接在虚拟机端运行命令 rviz d t
  • TCP的连接和建立(三次握手和四次挥手)

    1 TCP连接的建立 连接的建立 xff0c 通常称为三次握手 建立连接前服务器处在收听状态 第一步 xff1a 客户机的TCP向服务器的TCP发送连接请求报文段 同步位 61 1 这时客户进程进入同步已发送状态 第二步 xff1a 服务器
  • 网络编程(8)自定义网络通讯协议

    C C 43 43 网络通讯真正要用起来 xff0c 不但要写一个好的网络服务器 xff0c 还要定好一套通讯协议才能真正实用 通讯协议业界目前除了用开源的如XMPP以外 xff0c 基本上都是自定义一套通讯协议 xff0c 自已负责封包
  • libtorch导致OPENCV错误:对‘cv::imread(std::string const&, int)’未定义的引用

    1 问题描述 xff1a 报错 xff1a cmakelist txt 提示 xff1a 如果你报了相同的错误 xff0c 但是没有安装libtorch的话 xff0c 可能是cmakelist中没有target link librarie
  • 串口调试助手-QT

    串口调试助手 该程序使用Qt框架 xff0c C 43 43 语言编译而成 项目文件介绍 xff1a main cpp 该文件为该程序的入口程序 mainwindow h 该文件为该程序的主要声明部分 mainwindow cpp 该文件为
  • 基于STM32的电机--电机概述

    文章目录 电机直流有刷电机步进电机伺服电机直流无刷电机舵机 电机 电机 xff1a 俗称 马达 xff0c 依据电磁感应定律实现 电能转换或传递 的一种电磁装置 包括 xff1a 电动机和发电机 电动机在电路中是用M表示 xff0c 它的主
  • 免费公测 标贝声音理解,检测声音性别和年龄

    古有听声辨位 xff0c 今有听声 识 人 说到声音 xff0c 其本质是不同频率声音的集合 xff0c 以波的形式振动 xff08 震动 xff09 传播 由于每个人的发声器官 xff08 口腔 鼻腔 声带 xff09 各不相同 xff0
  • 前后端分离Token验证流程

    1 根据header获取token request getHeader Authorization 2 判断token 是否存在 3 token 不存在 过滤器放行 存在 根据token 获取用户名 根据用户名查询用户记录 UserDeta
  • 车载毫米波雷达MIMO阵列的天线发射问题

    说明 关于MIMO Multiple Input Multiple Output xff0c 多发多收 就不做过多介绍了 xff0c MIMO技术用于车载毫米波雷达主要的目的是增加虚拟通道 xff0c 以期使用较少的收发天线数量来达到较大的
  • 毫米波雷达的硬件架构与射频前端

    说明 本篇博文梳理 车载 毫米波雷达的系统构成 xff0c 特别地 xff0c 对其射频前端各部件做细节性的原理说明 本篇博文会基于对这方面知识理解的加深以及读者的反馈长期更新内容和所附资料 xff0c 有不当之处或有其它有益的参考资料可以
  • 串口+DMA 数据收发编程实践

    更多交流欢迎关注作者抖音号 xff1a 81849645041 目标 了解DMA 的工作原理 xff0c 通过配置 STM32F407 芯片的DMA xff0c 实现串口 43 DMA数据收发 原理 基于USART的数据通讯中采用中断方式可
  • W25Q128读写实验

    更多交流欢迎关注作者抖音号 xff1a 81849645041 目的 熟悉W25Q128串行FLASH的特性和操作指令 掌握通过SPI通讯读写W25Q128数据 原理 本章是结合SPI通讯对串行FLASH的读写 xff0c 通过SPI发送指
  • TFTLCD屏幕实验

    更多交流欢迎关注作者抖音号 xff1a 81849645041 目的 了解TFTLCD屏幕和FSMC的驱动原理 xff0c 通过STM32F4的FSMC接口来控制TFTLCD的显示 原理 1 液晶显示器 显示器属于计算机的I O设备 xff
  • STM32F4主板硬件设计与接口

    更多交流欢迎关注作者抖音号 xff1a 81849645041 本专栏的所有程序都在飞航科技 STM32 F407 开发板上测试通过 xff0c 本文介绍一下STM32 F407 开发板硬件设计与接口 xff0c 便于读者学习交流 STM3
  • 基于STM32F0实现人体红外传感器

    目的 了解人体红外传感器 HC SR501 的驱动原理和STM32F030的中断机制 xff0c 通过配置 STM32F030 芯片 GPIO 相关寄存器和外部触发中断实现人体红外传感器检测人体 原理 中断是指当CPU执行程序时 xff0c
  • STM32F0底板硬件架构设计与原理

    STM32F0底板接口明细 xff1a STM32F0底板作为整块节点的核心 xff08 如下图所示 xff09 xff0c 因此其接口相对应来说较多 xff0c 具体的接口有 xff1a 1 xff1a 5V电源输入口 xff0c STM
  • 基于STM32F030驱动SHT10温湿度传感器

    目的 了解温湿度传感器SHT10的驱动原理 xff0c 通过配置 STM32F030 的GPIO来采集温湿度传感器的温度 湿度和露点的 值 原理 SHT1x 包括 SHT10 SHT11 和 SHT15 属于Sensirion温湿度传感器家