STM32实战项目-温湿度传感器

news2024/11/17 9:51:20

程序功能:

1、软件模拟I2C协议与SHT30数字温湿度传感器通讯;

2、数码管显示环境温湿度;

3、串口打印环境温湿度。


目录

一、硬件电路

二、技术讲解 

2.1IIC简介

2.2 IIC总线协议

2.2设备接入

 三、SHT30数字温湿度传感器

 3.1性能介绍

3.1.1湿度最优测量环境

3.1.2温度最优测量环境

3.1.3测量配置

3.2通讯介绍

3.2.1单周期数据采集模式

 3.2.2周期采集

 四、软件编程

4.1参数配置

4.2软件框架 

4.3运行函数 

 4.4 I2C函数

4.4.1 iic结构体 

 4.4.2iic函数

4.5SHT30函数

4.5.1结构体函数

4.5.2SHT30函数

5结果演示



一、硬件电路

二、技术讲解 

2.1IIC简介

IIC (I2C,Inter-Integrated Circuit)即集成电路总线,是一种两线式串行总线,由PHILIPS公司开发用于连接微控制器及其外围设备。多用于主机和从机在数据量不大且传输距离短的场合下的主从通信。

I2C总线由数据线SDA和时钟线SCL构成通信线路,既可用于发送数据,也可接收数据。只有一根数据线,属于半双工通信方式。

标准模式:100Kbit/s 快速模式:400kbit/s 高速模式:3.4Mbit/s

2.2 IIC总线协议

 

 

 

I2C协议特点:

1、串行协议,多主机模式;

2、起始信号,SCL为高电平时,SDA下降沿,主机发出;

3、停止信号,SCL为高电平时,SDA上升沿,主机发出;

4、数据与地址按8位/字节传输(附带读写位),高位在前;

5、传输过程中,SCL为低电平时,SDA更改状态,SCL为高电平时,SDA状态需稳定;

6、每传输一个字节,接收器必须回应1个应答位(ACK)给发送器。

 

2.2设备接入

通过上面IIC协议的介绍,我们知道,通信是相互的,从机接收到读的命令,也会像主机发送数据,所以 I2C 器件一般采用开漏结构与总线相连,SCL 和 SDA 均需接上拉电阻。也正因此,当总线空闲时,这两条线路都处于高电平状态,当连到总线上的任一器件输出低电平,都将使总线拉低,即各器件的 SDA 及 SCL 都是“线与”关系。I2C 总线支持多主和主从两种工作方式。在主从工作方式中,主机启动数据的发送(发出启动信号)并产生时钟信号,数据发送完成后,发出停止信号。
 

 三、SHT30数字温湿度传感器

 3.1性能介绍

 

SHT30工作电压范围:2.4v--5.5v,通信速率:最高1MHz,接口:提供两个用户可选择地址的IIC接口,精度:2%RH,0.3° C的典型精度。

3.1.1湿度最优测量环境

3.1.2温度最优测量环境

 

   该传感器在推荐的正常温度和湿度范围内分别为5-60° C和20-80%RH时显示出最佳的性能。 长期暴露在正常范围以外的条件下, 特别是在高湿度下, 可能会暂时抵消RH信号(例如在80%RH条件下60h后+3%RH)。 在恢复到正常的温度和湿度范围后, 传感器将自行缓慢地恢复到校准状态。 长期暴露在极端条件下可能会加速衰老。 为了确保湿度传感器的稳定运行, 必须满足文件“SMD包装的SHTxx组装” 中关于接触挥发性有机化合物的“储存和处理说明” 一节中所描述的条件。 请注意, 这不仅适用于运输和制造, 而且也适用于SHT3x-DIS的操作。

3.1.3测量配置

 

  

3.2通讯介绍

 测量通信序列由START条件、 I2C写报头(7位I2C设备)组成地址加0(R)作为写位)和16位测量命令(高八位,低八位)。 每个字节的正确接收由传感器指示。 它将SDA引脚拉低(ACK位)后, 第8个SCL时钟的下降边缘 以指示接收。 描述了一个完整的测量周期。通过确认测量命令, SHT3x-DIS开始测量湿度和温度。

3.2.1单周期数据采集模式
 

在这种模式下, 一个发出的测量命令触发一个数据对的获取。 每个数据对由一个16位温度
和一个16位湿度值(按此顺序)组成) 。 在传输期间, 数据对总是后面跟着CRC校验位, 请
在单周期模式下, 可以选择不同的测量命令。 16位命令显示在它们在重复性( 低、中、 高)和时钟拉伸(启用或禁用)方面不同) 。重复性设置影响传感器的测量持续时间和电流消耗。  传感器通常不响应任何I2C活动, 即不承认I2C读写标题(NACK)。 然而, 当发出带有时钟拉伸的命令时, 传感器用ACK响应读报头, 然后拉下SCL线。 将SCL线拉下, 直至测量完成。 测量完成后, 传感器释放SCL线并发送测量结果。图解如下:


 

 3.2.2周期采集

 在这种模式下, 一个发出的测量命令产生一个数据对流。 每个数据对由一个16位温度和一
个16位湿度值(按此顺序)组成) 。在周期模式下, 可以选择不同的测量命令。相应的16位命令显示在重复性(低、 中、 高)和数据采集频率(每秒0.5、 1、 2、 4和10次测量, MPS)方面)。  无法在此模式下选择时钟拉伸。数据采集频率和重复性设置影响传感器的测量持续时间和电流消耗

 四、软件编程

4.1参数配置

 只需要配置gpio口味开漏输出就可以了,如下图所示:

4.2软件框架 

在原有的基础上,新增I2C和SHT30源文件。如下图所示:

 

 

4.3运行函数 

static void Run()
{
	float    Temp_float = 0;
	uint16_t Temp_uint  = 0;
	
	//周期性测量获取SHT30的温湿度
	SHT30.Measure_Period_Mode();
	
	//串口打印
	printf("Wendu = %.1f¡æ\r\n",SHT30.fTemperature); 
	printf("shidu = %d%%RH\r\n\r\n",(uint16_t)SHT30.ucHumidity); 
	
	数码管显示
	//温度
	if(SHT30.fTemperature < 0) //负温
	{
		Temp_float = 0 - SHT30.fTemperature;
		Display.Disp_Other(Disp_NUM_4,0x40,Disp_DP_OFF); //4号数码管
	}
	else
	{
		Temp_float = SHT30.fTemperature;
		Display.Disp_Other(Disp_NUM_4,0x00,Disp_DP_OFF); //4号数码管
	}
	Temp_uint = (uint16_t)(Temp_float*10);
	
	Display.Disp_HEX(Disp_NUM_3,Temp_uint/100,Disp_DP_OFF);
	Display.Disp_HEX(Disp_NUM_2,Temp_uint%100/10,Disp_DP_ON);
	Display.Disp_HEX(Disp_NUM_1,Temp_uint%10,Disp_DP_OFF);
	
	
	//湿度
	Display.Disp_HEX(Disp_NUM_6,SHT30.ucHumidity/10,Disp_DP_OFF);
	Display.Disp_HEX(Disp_NUM_5,SHT30.ucHumidity%10,Disp_DP_OFF);
	
	HAL_Delay(500);
}

 4.4 I2C函数

4.4.1 iic结构体 

枚举,ACK,和NACK,结构体封装,iic的起始,停止 读 写函数。 

typedef enum
{
	ACK	 = GPIO_PIN_RESET,//响应
	NACK = GPIO_PIN_SET,//不响应
}ACK_Value_t;

//定义结构体类型
typedef struct
{
	void (*Init)(void);  //初始化
	void (*Start)(void); //起始信号
	void (*Stop)(void);  //停止信号
	ACK_Value_t (*Write_Byte)(uint8_t);      //I2c写字节
	uint8_t     (*Read_Byte) (ACK_Value_t);  //I2读字节
}I2C_Soft_t

 4.4.2iic函数

1.将设置sda,scl引脚的端口,宏定义,方便代码编写,以及后期移植, 

//置位与清零SCL管脚
#define	SET_SCL	HAL_GPIO_WritePin(SHT30_SCL_GPIO_Port,SHT30_SCL_Pin,GPIO_PIN_SET) 
#define	CLR_SCL	HAL_GPIO_WritePin(SHT30_SCL_GPIO_Port,SHT30_SCL_Pin,GPIO_PIN_RESET)
//置位与清零SDL管脚
#define	SET_SDA	HAL_GPIO_WritePin(SHT30_SDA_GPIO_Port,SHT30_SDA_Pin,GPIO_PIN_SET)
#define	CLR_SDA	HAL_GPIO_WritePin(SHT30_SDA_GPIO_Port,SHT30_SDA_Pin,GPIO_PIN_RESET)
//读SDA管脚状态
#define READ_SDA	HAL_GPIO_ReadPin(SHT30_SDA_GPIO_Port,SHT30_SDA_Pin)

 2.初始化

将sda和scl均拉高

static void Init(void)
{
	SET_SCL;
	SET_SDA;
}

 3起始

拉低sda,延时一会拉低scl等待发送

static void Start(void)
{
	//SCL为该电平,SDA为下降沿IIC起始信号
	SET_SDA;
	SET_SCL;
	I2C_Delay_us(1);
	
	CLR_SDA;
	I2C_Delay_us(10);
	
	CLR_SCL;
	I2C_Delay_us(1);
}

 4停止

拉低SDA,拉高SCL再次拉高SDA 停止

static void Stop(void)
{
	//SCL为高电平,SDA上升沿为IIC停止信号
	CLR_SDA;
	SET_SCL;
	I2C_Delay_us(1);
		
	I2C_Delay_us(10);
	SET_SDA;
}

5写数据

BIT7为1,将数据位和他与 判断为高定电平,选择对应的SDA位。

static ACK_Value_t Write_Byte(uint8_t WR_Byte)
{
	uint8_t i;
	ACK_Value_t  ACK_Rspond;
	
	//SCL为低电平,SDA准备数据,接着SCL为高电平,读取SDA数据
	//数据按八位传输,高位在前,利用for循环逐个接收
	for(i=0;i<8;i++)
	{
		//SCL清零,主机SDA 准备数据
		CLR_SCL;
		I2C_Delay_us(1);
		if((WR_Byte&BIT7) == BIT7)
		{
			SET_SDA;
		}
		else
		{
			CLR_SDA;
		}
		I2C_Delay_us(1);
		//SCL置高,传输数据
		SET_SCL;
		I2C_Delay_us(10);
		
		//准备发送下一个bit
		WR_Byte <<= 1;
	}
	
	CLR_SCL;	
	//释放SDA,等待从机yingda
	SET_SDA;
	I2C_Delay_us(1);
	
	SET_SCL;
	I2C_Delay_us(10);
	
	ACK_Rspond = (ACK_Value_t)READ_SDA;
	
	CLR_SCL;
	I2C_Delay_us(1);
	
	//返回从机应答信号
	return ACK_Rspond;
}

 6读数据

static uint8_t Read_Byte(ACK_Value_t ACK_Value)
{
	uint8_t RD_Byte = 0,i;
		
	接收数据
	//SCL位低电平,SDA准备数据,接着SCL为高电平,读取SDA数据
	//数据传输八位,高位在前,利用for循环诸葛接收
	for(i=0;i<8;i++)
	{
		//准备接收下一个bit
		RD_Byte <<= 1;
		
		//SCL清零,从机SDA准备数据
		CLR_SCL;
		I2C_Delay_us(10);
		
		//SCL志高,获取数据
		SET_SCL;
		I2C_Delay_us(10);	

		RD_Byte |= READ_SDA;		
	}
	
	
	//SCL清零,主机准备应答信号
	CLR_SCL;
	I2C_Delay_us(1);
	
	//主机发送应答信号
	if(ACK_Value == ACK)
	{
		CLR_SDA;
	}
	else
	{
		SET_SDA;	
  }	
	I2C_Delay_us(1);
	
	
	SET_SCL; 	
	I2C_Delay_us(10);
	
	//Note:
  //释放SDA数据线
	//SCL先清零,在释放SDA,防止连续传输数据时。从机错将SDA释放。
	CLR_SCL;
  SET_SDA; 	
	I2C_Delay_us(1);

	//返回数据
	return RD_Byte;
}

4.5SHT30函数

4.5.1结构体函数

 选择周期测量模式,因为SHT30地址位是七位,所以需要左移 然后与读写位与或 加上读写位构成八位数据传输。

#define SHT30_ADDR  (uint8_t)(0x44 << 1) //´传感器地址
//#define SHT30_ADDR  (unsigned char)(0x45 << 1) //´另一种模式传感器地址

#define	Write_CMD   0xFE
#define	Read_CMD    0x01


//定义结构体类型

typedef struct
{
	float   fTemperature;  //温度 -40 至 125 精度 百一
	uint8_t ucHumidity;    //湿度 0 - 100 精度 百一       
	
	void (*Measure_Period_Mode)(void);  //周期测量模式
}SHT30_t;

4.5.2SHT30函数

1.信号输出的转换

测量数据总是以16位值( 无符号整数)的形式传输) 。 这些值已经线性化, 并补偿了温度
和电源电压的影响。 将这些原始值转换为物理标度可以使用以下公式实现。相对湿度换算公式(结果为%RH):

 

  

static void Measure_Period_Mode(void)
{
  uint8_t   temp_array[6] = {0};
	uint16_t  temp_uint     = 0;
	float     temp_float    = 0;

	//启动周期性测量
	I2C_Soft.Start();
	I2C_Soft.Write_Byte(SHT30_ADDR & Write_CMD);
	I2C_Soft.Write_Byte(0x27); //High repeat , mps = 10
	I2C_Soft.Write_Byte(0x37);
	
	Timer6.SHT30_Measure_Timeout = 0;
	//发送接收数据命令
	do
	{		
		if(Timer6.SHT30_Measure_Timeout >= TIMER6_2S) //2s内没获取跳出
			break;
		
		I2C_Soft.Start();
		I2C_Soft.Write_Byte(SHT30_ADDR & Write_CMD);
		I2C_Soft.Write_Byte(0xE0);
		I2C_Soft.Write_Byte(0x00);
		
		I2C_Soft.Start();
	}
	while(I2C_Soft.Write_Byte(SHT30_ADDR | Read_CMD) ==NACK);
		
	//开始接收测量数据,并计算
	if(Timer6.SHT30_Measure_Timeout < TIMER6_2S)
	{
		temp_array[0] = I2C_Soft.Read_Byte(ACK);
		temp_array[1] = I2C_Soft.Read_Byte(ACK);
		temp_array[2] = I2C_Soft.Read_Byte(ACK);
		temp_array[3] = I2C_Soft.Read_Byte(ACK);
		temp_array[4] = I2C_Soft.Read_Byte(ACK);
		temp_array[5] = I2C_Soft.Read_Byte(NACK);
		I2C_Soft.Stop();
		
		计算温度 精度0.1
		if(CRC_8(temp_array,2) == temp_array[2]) //CRC-8 УÑé
		{
			temp_uint         = temp_array[0]*256+temp_array[1];
			temp_float        = ((float)temp_uint)*0.267032-4500;
			SHT30.fTemperature = temp_float*0.01;
	  }
		
		计算湿度 1%RH
		if(CRC_8(&temp_array[3],2) == temp_array[5]) //CRC-8 УÑé
		{
			temp_uint      = temp_array[3]*256+temp_array[4];
			temp_float     = ((float)temp_uint)*0.152590;
			temp_float     = temp_float*0.01;
			SHT30.ucHumidity = (unsigned char)temp_float;  
	  }
	}
}

校验

static uint8_t CRC_8(uint8_t *Crc_ptr,uint8_t LEN)
{
	uint8_t CRC_Value = 0xFF;
	uint8_t i = 0,j = 0;

	for(i=0;i<LEN;i++)
	{
		CRC_Value ^= *(Crc_ptr+i);
		for(j=0;j<8;j++)
		{
			if(CRC_Value & 0x80)
				CRC_Value = (CRC_Value << 1) ^ 0x31;
			else
				CRC_Value = (CRC_Value << 1);
		}
	}
	return CRC_Value;
}

5结果演示

 

 

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/419759.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Rollup 实践:插件生态和实用技巧(续)

在前面的文章中&#xff0c;我们已经了解了 Rollup 的性能优化和高级用法。本篇文章将继续探讨 Rollup 的插件生态和实用技巧。 插件生态 Rollup 拥有一个丰富的插件生态&#xff0c;下面我们介绍几个实用的插件&#xff1a; rollup-plugin-terser&#xff1a;使用 Terser 压…

FlowForge 使用教程 团队资源管理

前言 本篇文章结合FF的操作来给大家解释一下,FF在团队管理上都与那些资源可以操作。 团队创建 使用超管第一次登录FF平台,默认什么资源都没有,你只能先去创建一个团队才能继续往下操作。 在FF平台上,团队就代表一个租户,也是一种资源隔离的手段。 创建团队可以通过右上…

Rollup 实践:性能优化和高级用法(续)

在前面的文章中&#xff0c;我们已经了解了 Rollup 的基本概念和配置。本篇文章将继续探讨 Rollup 的性能优化和高级用法。 懒加载 通过 Rollup 的代码分割功能&#xff0c;我们可以实现懒加载&#xff0c;从而减小初始页面加载时间。假设我们有一个动态导入的模块 dynamic.j…

vue项目用后端返回的文件流实现docx和pdf文件预览

前端docx和pdf文件预览实现效果图docx-preview文件预览pdf文件预览写这篇文章的目的&#xff0c;是因为我比较懒&#xff0c;想把代码记录一下&#xff0c;方便日后使用&#xff1b;哈哈&#xff0c;如果你也需要&#xff0c;也可以复制粘贴啊&#xff0c;为了方便自己和需要的…

windows10开发环境下部署kafka消息服务

下载kafka&#xff0c;官方地址https://kafka.apache.org/downloads 百度网盘链接&#xff1a;https://pan.baidu.com/s/1h3iXtfzEIBoajGPId5Dcag?pwd0000 提取码&#xff1a;0000直接把下载的文件解压到某个盘的根目录&#xff0c;要不然后面的命令就会遇到“命令行过长”的报…

linux 系统的一些使用小技巧

实现RedHat非正常关机的自动磁盘修复 先登录到服务器&#xff0c;然后在/etc/sysconfig里增加一个文件autofsck,内容如下&#xff1a; AUTOFSCK_DEF_CHECKyes PROMPTyes 改变文件或目录之最后修改时间(变为当前时间) 执行格式&#xff1a;touch name ( name 可为文件或目录名称…

Matlab vs Python:哪个更适合数据分析和可视化?

当谈到数据分析和可视化时&#xff0c;许多人会思考使用哪种编程语言来实现这一目标。在IT行业&#xff0c;最流行的两种编程语言是Matlab和Python。这两种语言都有广泛的应用&#xff0c;但是对于初学者来说&#xff0c;选择哪种语言可能会有些困难。在本文中&#xff0c;我们…

【ENVI】监督分类

好久没用ENVI了&#xff0c;用起来有点生疏&#xff0c;这里记录一下操作流程。。。 基础数据&#xff1a;从91卫图下载相应地区影像数据。 下载影像推荐&#xff1a;地理空间数据云、91卫图、水经注等。 1、加载tif数据 2、样本选择 &#xff08;1&#xff09;在图层管理器…

Baumer工业相机堡盟工业相机如何通过BGAPISDK里的工具函数来计算工业相机的实时帧率(C#)

Baumer工业相机堡盟工业相机如何通过BGAPISDK里函数来计算相机的实时帧率&#xff08;C#&#xff09;Baumer工业相机Baumer工业相机的帧率的技术背景Baumer工业相机的帧率计算方式在BufferEvent声明显示FrameID设计显示帧率的函数Baumer工业相机通过BGAPI SDK计算帧率的优势​B…

亚马逊云科技:智能家居时代已来,如何抢滩海外市场的“真空区”?

在充满着不确定性的2022年&#xff0c;电子消费市场一片哀鸿遍野&#xff0c;智能家居行业却如同逆水行舟&#xff0c;显示出稳健的发展之势&#xff0c;宣告着智能家居时代已来。在2023年3月24日举办的“智能家居&#xff0c;出海闭门会”上&#xff0c;为进一步发挥产业带潜力…

微前端--qiankun原理概述

demo放最后了。。。 一、微前端 一》微前端概述 微前端概念是从微服务概念扩展而来的&#xff0c;摒弃大型单体方式&#xff0c;将前端整体分解为小而简单的块&#xff0c;这些块可以独立开发、测试和部署&#xff0c;同时仍然聚合为一个产品出现在客户面前。可以理解微前端是…

2023.04.16 学习周报

文章目录摘要文献阅读1.题目2.摘要3.简介4.Dual-Stage Attention-Based RNN4.1 问题定义4.2 模型4.2.1 Encoder with input attention4.2.2 Decoder with temporal attention4.2.3 Training procedure5.实验5.1 数据集5.2 参数设置和评价指标5.3 实验结果6.结论MDS降维算法梯度…

亚马逊listing如何提高?测评要满足什么条件?

为什么有些大卖就可以卖得很好&#xff0c;而有些卖家始终都做不起来&#xff1f;其中的影响因素之一就是listing&#xff0c;listing页面做得好&#xff0c;转化率自然就提高了。而这其中的原理还需要卖家去具体了解亚马逊的算法。 首先来看一下亚马逊最大的流量搜索&#xf…

第十三届蓝桥杯Web组国赛真题 开学礼物大放送

介绍 又是一年开学季&#xff0c;蓝桥为大家准备了开学礼物&#xff0c;想制作一个页面来宣传一下该活动。 本题需要按照要求完成一个以“开学季”为主题的页面布局。 准备 开始答题前&#xff0c;需要先打开本题的项目代码文件夹&#xff0c;目录结构如下&#xff1a; ├─…

微服务-微服务为什么要用到 API 网关

什么是微服务 微服务架构&#xff08;通常简称为微服务&#xff09;是指开发应用所用的一种架构形式。通过微服务&#xff0c;可将大型应用分解成多个独立的组件&#xff0c;其中每个组件都有各自的责任领域。 在处理一个用户请求时&#xff0c;基于微服务的应用可能会调用许多…

C语言标准CRC-16校验函数

C语言标准CRC-16校验函数 CRC-16校验产生2个字节长度的数据校验码&#xff0c;通过计算得到的校验码和获得的校验码比较&#xff0c;用于验证获得的数据的正确性。获得的校验码是随数据绑定获得。 CRC校验原理及标准CRC-8校验函数可参考&#xff1a;C语言标准CRC-8校验函数。…

48.现有移动端开源框架及其特点—MDL(mobile-deep-learning)

48.1 功能特点 一键部署,脚本参数就可以切换ios或者android支持iOS gpu运行MobileNet、squeezenet模型已经测试过可以稳定运行MobileNet、GoogLeNet v1、squeezenet、ResNet-50模型体积极小,无任何第三方依赖。纯手工打造。提供量化函数,对32位float转8位uint直接支持,模型…

嵌套列表,与摩尔投票进阶

title: “Python fishC 22” author: “hou wei” date: “2023-04-16” output: html_document knitr::opts_chunk$set(echo TRUE)问答题 0.请问 运算符和 is 运算符有什么区别呢&#xff1f; 在Python中运算符用于比较两个变量的值是否相等&#xff0c;而is运算符用于判断…

2023年MathorCup数模A题赛题详细思路

MathorCup俗称妈杯&#xff0c;是除了美赛国赛外参赛人数首屈一指的比赛&#xff0c;而我们的妈杯今天也如期开赛。今年的妈杯难度&#xff0c;至少在我看来应该是2023年截至目前来讲最难的一场比赛。问题的设置、背景的选取等各个方面都吐露着我要难死你们的想法。难度是恒定的…

MySQL-自带工具介绍

目录 &#x1f341;mysql &#x1f341;mysqladmin &#x1f990;博客主页&#xff1a;大虾好吃吗的博客 &#x1f990;MySQL专栏&#xff1a;MySQL专栏地址 MySQL数据库不仅提供了数据库的服务器端应用程序&#xff0c;同时还提供了大量的客户端工具程序&#xff0c;如mysql&a…