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

程序功能:

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结果演示



一、硬件电路

STM32实战项目-温湿度传感器_第1张图片

二、技术讲解 

2.1IIC简介

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

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

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

2.2 IIC总线协议

 STM32实战项目-温湿度传感器_第2张图片

 

 

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 总线支持多主和主从两种工作方式。在主从工作方式中,主机启动数据的发送(发出启动信号)并产生时钟信号,数据发送完成后,发出停止信号。
 

STM32实战项目-温湿度传感器_第3张图片

 三、SHT30数字温湿度传感器

 3.1性能介绍

 

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

3.1.1湿度最优测量环境

STM32实战项目-温湿度传感器_第4张图片

3.1.2温度最优测量环境

STM32实战项目-温湿度传感器_第5张图片 

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

3.1.3测量配置

STM32实战项目-温湿度传感器_第6张图片

 

  

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线并发送测量结果。图解如下:

STM32实战项目-温湿度传感器_第7张图片
 

 3.2.2周期采集

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

STM32实战项目-温湿度传感器_第8张图片

 四、软件编程

4.1参数配置

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

STM32实战项目-温湿度传感器_第9张图片

4.2软件框架 

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

STM32实战项目-温湿度传感器_第10张图片 

 

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):

STM32实战项目-温湿度传感器_第11张图片

 

  

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

5结果演示

 

 

 

 STM32实战项目-温湿度传感器_第12张图片

 

你可能感兴趣的:(stm32,单片机,嵌入式硬件)