Sensor: SHT30 temperature and humidity sensor to detect ambient temperature and humidity experiment (code attached at the bottom)

1. Introduction

The SHT30 temperature and humidity sensor module is driven by IIC, so when you use this module, you need to have basic knowledge of IIC. This article will guide you to use the SHT30 module to measure temperature and humidity. Of course, the principles of DHT10/DHT10 are the same. Okay, Let’s learn together!

2. IIC knowledge

1. Introduction to IIC bus

The I2C (Inter-Integrated Circuit) bus is a two-wire serial bus developed by PHILIPS and is used to connect microcontrollers and their peripheral devices. It is a bus standard widely used in the field of microelectronics communication control. It is a special form of synchronous communication. It has the advantages of fewer interface lines, simple control method, small device packaging form, and high communication rate. The I2C bus has only two bidirectional signal lines. One is the data line SDA, and the other is the clock line SCL. Due to its few pins, simple hardware implementation, and strong scalability, it is widely used in major integrated chips. Next, we will learn about IIC from the physical layer and protocol layer of IIC.

1.1. IIC physical layer

Insert image description here
Physical layer:
(1) It is a bus that supports multiple devices
(2) The I2C bus only uses two bus lines, SDA and SCL.
(3) Each device connected to the bus has an independent address, and the host can use this address to access different devices.
(4) The bus is connected to the power supply through a pull-up resistor. When the I2C device is idle, it will output a high-impedance state. When all devices are idle and all output a high-impedance state, the pull-up resistor will pull the bus to a high level.
(5) When multiple hosts use the bus at the same time, in order to prevent data conflicts, arbitration will be used to determine which device will occupy the bus.
(6) It has three transmission modes: the standard mode transmission rate is 100kbit/s, the fast mode is 400kbit/s, and the high-speed mode can reach 3.4Mbit/s. However, most I2C devices currently do not support high-speed mode
.
(7) The number of ICs connected to the same bus is limited by the bus's maximum capacitance of 400pF.

1.2. IIC protocol layer

(1) Data validity regulations
Insert image description here
As shown in the figure above, when the clock line SCL is high level and SDA is high level, the data is required to be stable, that is, no change is allowed. SCL is the carrier of SDA when the clock line is high level. When the line SCL is low, the data of SDA is allowed to change at this time, that is, data transmission is allowed, so we can program well through the timing diagram and it is easy to get started with IIC. (Note: Each transmission is in bytes)
(2) The start signal and stop signal
Insert image description here
can be seen in the figure above. When the clock line SCL is high level, and SDA changes from high level to low level, at this time It indicates that the IIC has been started. We will also design it in the program later. It is very convenient. When the clock line SCL is high level and SDA changes from low level to high level, it indicates that the IIC has been stopped. From here, you can see that no matter whether you start IIC or stop IIC, the clock line remains high, and only the level of SDA changes.
(3) Response (ACK) and non-response signal (NACK)
Insert image description here
As you can see in the figure above, when IIC starts, it starts transmitting data. As mentioned earlier, IIC transmission is transmitted in bytes, for example, a byte is 8 bits. , then IIC first transmits 8 bits. After the transmission is completed, it is followed by the 9th bit, which represents the response bit. What does it mean? That is to say, as long as 8 bits of a byte must be transmitted correctly bit by bit, when the transmission is completed, the slave will respond whether the data is transmitted correctly. If it is correct, the slave will respond with a response signal and set SDA to low level to indicate response. If there is a transmission error, the slave responds to a non-response signal, sets SDA to a high level, and the host generates a termination signal to terminate this data transmission, and then the host starts the next transmission. Therefore, it can be seen from this timing diagram that after each byte transmission is completed, it needs to be followed by an acknowledge bit/non-acknowledge bit.
(4) Bus addressing mode
There are generally two bus addressing modes, one is 7-bit addressing and the other is 10-bit addressing. 7-bit addressing is usually used, that is, the address of the transmission device is 7-bit, 7-bit addressing timing diagram is as follows:
Insert image description here
As you can see in the figure above, bus transmission is in bytes. When addressing with 7 bits, the first 7 bits indicate the slave address, and the 8th bit indicates whether the host is writing or reading. First, you must understand why addressing is required (7 Bit)? As mentioned before, there are many devices connected to the IIC bus. At this time, the bus will assign unique addresses to the devices connected to the bus, similar to how a router assigns different and unique IPs to WIFI devices connected to the router. Address, so the host can communicate with different devices based on the address. The first 7 bits are clearly explained, and then the 8th bit is explained; the 8th bit indicates whether the slave receives data from the host or writes data to the host.
(5) Bus data transmission mode
The data signals transmitted on the I2C bus are broad, including both address signals and real data signals. A slave address (7 bits) must be transmitted after the start signal. The 8th bit is the data transmission direction bit (R/W). Use "0" to indicate that the host sends (writes) data (W), and "1" Indicates that the host receives data (R). Each data transfer is always terminated by a termination signal generated by the host. However, if the master wishes to continue occupying the bus for new data transmission, it can immediately send a start signal again to address another slave without generating a termination signal. As shown below: S represents the IIC start signal, 0 represents the host writing to the slave, 1 represents the host reading from the slave, A represents the response signal, non-A represents the non-response signal, and P represents the stop signal. The first transmission method:
host Send data to the slave, and the data transmission direction remains unchanged during the entire transmission process.
Insert image description here
The second transmission method: the host reads the data from the slave immediately after transmitting the first byte.
Insert image description here
The third transmission method: during the transmission process, when When the transfer direction needs to be changed, both the start signal and the slave address are
generated repeatedly, but the two read/write direction bits are exactly inverted.
Insert image description here

3. SHT30 source code

1. sht30.c source file

/*
设定温度阈值范围:-20℃——125℃
设定相对湿度范围:0%——100%
*/
#include"stm32f10x.h"
#include"sht30.h"
#include"stdio.h"

#define write 0 //IIC设备地址一般是7位,也有10位,本程序使用7位IIC设备地址,第8位是写命令
#define read  1 //IIC设备地址一般是7位,也有10位,本程序使用7位IIC设备地址,第8位是读命令

//IIC总线接口定义
#define SCL PBout(6)//设置时钟端口
//SHT30数据SDA传输口,有输出也有输入,所以需配置它的输入和输出
#define SDA_OUT PBout(7)//设置输出数据端口
#define SDA_IN PBin(7)//设置输入数据端口
//设置端口高8位的工作模式(具体可以参照端口位配置表),即I/O输入输出方向设置,先用与(&)对PB7引脚的四个位清0,再用或(|)置1
#define IIC_INPUT_MODE_SET()  {
      
      GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=8<<28;}//改变PB7对应位为1000(CNF[1:0]MODE[1:0]),设置成上拉或者下拉输入
#define IIC_OUTPUT_MODE_SET() {
      
      GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=3<<28;}//改变PB7对应位为0011,设置成通用推挽输出
//#define IIC_INPUT_MODE_SET()  {GPIOB->CRH&=0XFFFF0FFF;GPIOB->CRH|=8<<12;}//改变PB7对应位为1000(CNF[1:0]MODE[1:0]),设置成上拉或者下拉输入
//#define IIC_OUTPUT_MODE_SET() {GPIOB->CRH&=0XFFFF0FFF;GPIOB->CRH|=3<<12;}//改变PB7对应位为0011,设置成通用推挽输出

 //定义温湿度存储变量
u8 humiture_buff1[20];

void SHT30_Init(void)//初始化SHT30的SCL与SDA接口
{
    
    
	GPIO_InitTypeDef GPIO_InitStructure; 
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;//定于SCL连接到STM32的PB6引脚上,定于SDA_OUT/SDA_IN连接到STM32的PB7引脚上
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
 	SCL=1;//根据SHT30时序要求,默认时序是高电平(SDA拉低时,SCL跟着拉低,开始数据的传输)
	SDA_OUT=1;//高电平还未开始数据的传输,拉低时开始数据的传输
}	
//主机发送确认字符ACK
void IIC_ACK(void)//IIC协议,需要主机发送确认字符ACK来判断数据是否接收无误
{
    
    
  IIC_OUTPUT_MODE_SET();//配置PB7的SDA输出为推挽输出模式
  SCL=0;
  delay_us(2); 
  SDA_OUT=0;
  delay_us(2);     
  SCL=1;//数据接收完成之后,将SCL拉高,以便与后面主机发送ACK给从机
  delay_us(2);                  
  SCL=0;//数据接收完成,主机发送ACK                     
  delay_us(1);    
}
//主机不发送确认字符ACK
void IIC_NACK(void)//IIC协议,数据传输未完成或者数据传输有误,主机不发送确认字符ACK
{
    
    
  IIC_OUTPUT_MODE_SET();//配置PB7的SDA输出为推挽输出模式
  SCL=0;
  delay_us(2); 
  SDA_OUT=1;
  delay_us(2);      
  SCL=1;
  delay_us(2);                   
  SCL=0;                     
  delay_us(1);    
}
//主机等待从机的确认字符ACK
u8 IIC_wait_ACK(void)//主机等待从机发送ACK,从而判断数据是否接收完成
{
    
    
    u8 t = 200;
    IIC_OUTPUT_MODE_SET();
    SDA_OUT=1;//8位发送完后释放数据线,准备接收应答位 
    delay_us(1);
    SCL=0;
    delay_us(1); 
    IIC_INPUT_MODE_SET();
    delay_us(1); 
    while(SDA_IN)//等待SHT30应答
    {
    
    
	t--;
	delay_us(1); 
	if(t==0)
	{
    
    
	  SCL=0;
	  return 1;
	}
	delay_us(1); 
    }
    delay_us(1);      
    SCL=1;
    delay_us(1);
    SCL=0;             
    delay_us(1);    
    return 0;	
}
//启动IIC总线进行通讯,发送IIC通讯的起始条件
void IIC_Start(void)//启动IIC通讯
{
    
    
  IIC_OUTPUT_MODE_SET();//设置PB7的SDA为推挽输出
  SDA_OUT=1;//根据SHT30时序,启动之前,SDA配置为高电平
  SCL=1;根据SHT30时序,启动之前,SCL配置为高电平
  delay_us(4);//延时4us,给硬件一个反应时间
  SDA_OUT=0;//SDA引脚拉低,开始数据的传输
  delay_us(4);
  SCL=0;//SCL拉低,与SDA对应,响应SDA数据的拉低,表示正式开始数据的传输
}
 
//结束IIC总线通讯,发送IIC通讯的结束条件
void IIC_Stop(void)
{
    
    
	IIC_OUTPUT_MODE_SET();
	SCL=0;//结束IIC通讯之前,查看SCL是否是拉低状态
	SDA_OUT=0;//结束IIC通讯之前,查看SDA是否是拉低状态  
	delay_us(4);	
	SCL=1;//将时钟拉高,表示已经结束IIC通讯
	delay_us(4);
	SDA_OUT=1;//将数据传输引脚拉高,表示正式结束数据的传输
	delay_us(4);
}
 
//将byte数据发送出去
void  IIC_SendByte(u8 byte)
{
    
    
	u8  Count;
	IIC_OUTPUT_MODE_SET();
	SCL=0;//将时钟拉低,开始数据的传输
	for(Count=0;Count<8;Count++)//要传送的数据长度为8位
	{
    
    
		if(byte&0x80) SDA_OUT=1;//判断发送位,发送位为1,则还未发送数据
		else SDA_OUT=0; //判断发送位为0,则开始数据的发送
		byte<<=1;
		delay_us(2); 
		SCL=1;
		delay_us(2);
		SCL=0;
		delay_us(2);
	}
}

// 用来接收从器件传来的数据    
u8 IIC_RcvByte(void)
{
    
    
  u8 retc;
  u8 Count;
  retc=0; 
  IIC_INPUT_MODE_SET();//配置数据线为输入方式
  delay_us(1);                    
  for(Count=0;Count<8;Count++)
  {
    
      
	SCL=0;//配置时钟线为低,准备接收数据位
	delay_us(2);               
	SCL=1;//配置时钟线为高使数据线上数据有效                
	retc=retc<<1;
	if(SDA_IN) retc |=1;//读数据位,接收的数据位放入retc中 
	delay_us(1);
  }
  SCL=0;    
  return(retc);
}
//用来接收从器件采集并合成温湿度 
void SHT30_read_result(u8 addr)
{
    
    
	//SHT30有两种读取数值的方法,分别是状态查询和数值查询,这里我使用的是数值查询,发送指令为0x2C06
	u16 tem,hum;//定义存放温湿度计算公式的变量
	u16 buff[6];//定义6个字节的数组,存放温度高、低八位,湿度高、低八位,两个字节的CRC校验位
	float Temperature=0;//定义存放温度拼接的变量Temperature,初始化温度为0
	float Humidity=0;//定义存放湿度拼接的变量Humidity,初始化湿度为0
	//发送指令为0x2C06(默认)
	IIC_Start();
	IIC_SendByte(addr<<1 | write);//写7位I2C设备地址加0作为写取位,1为写取位
	IIC_wait_ACK();
//	delay_us(1);
	IIC_SendByte(0x2C);//前半段发送指令为0x2C
	IIC_wait_ACK();
//	delay_us(1);
	IIC_SendByte(0x06);//后半段发送指令为0x06
	IIC_wait_ACK();
//	delay_us(1);
	IIC_Stop();
	delay_ms(50);
	IIC_Start();
	IIC_SendByte(addr<<1 | read);//写7位I2C设备地址加1作为读取位,1为读取位
//SHT30返回的数值是6个元素的数组
	if(IIC_wait_ACK()==0)
	{
    
    
//  	delay_us(1);
		buff[0]=IIC_RcvByte();//返回温度高8位
		IIC_ACK();
		buff[1]=IIC_RcvByte();//返回温度低8位
		IIC_ACK();
		buff[2]=IIC_RcvByte();//温度crc校验位
		IIC_ACK();
		buff[3]=IIC_RcvByte();//返回湿度高8位
		IIC_ACK();
		buff[4]=IIC_RcvByte();//返回湿度低8位
		IIC_ACK();
		buff[5]=IIC_RcvByte();//湿度crc校验位
		IIC_NACK();
		IIC_Stop();
	}
//	tem = (buff[0]<<8) + buff[1];
//	hum = (buff[3]<<8) + buff[4];
	tem = ((buff[0]<<8) | buff[1]);//将buff[0]采集到的温度8位数据与buff[1]采集到的低8位数据相或,实现温度拼接
	hum = ((buff[3]<<8) | buff[4]);//将buff[3]采集到的湿度8位数据与buff[4]采集到的低8位数据相或,实现湿度拼接

//查询SHT30数据手册可知,温湿度的计算方法如下	
	Temperature= 175.0*(float)tem/65535.0-45.0 ;// T = -45 + 175 * tem / (2^16-1)
	Humidity= 100.0*(float)hum/65535.0;// RH = hum*100 / (2^16-1)
	
	if((Temperature>=-20)&&(Temperature<=125)&&(Humidity>=0)&&(Humidity<=100))//设定温度和湿度的阈值,超过这个阈值则返回错误提示
	{
    
    
		printf("温度:%6.2f℃\r\n",Temperature);
		printf("湿度:%6.2f%%\r\n",Humidity);
	}
	else
	{
    
    
		printf("温湿度超过给定阈值!\r\n");
	}
	hum=0;
	tem=0;	

}

2. sht30.h header file

#ifndef _SHT30_H
#define _SHT30_H

#include "delay.h"
#include "sys.h"
#include "stdio.h"
#include "usart.h"
#include "string.h"
 
extern u8 humiture_buff1[20];

void SHT30_Init(void);
void IIC_ACK(void);//确认字符,表示发来的数据已经确认接收无误
void IIC_NACK(void);//无确认字符,表示数据接收有误或者还未接收完成
u8 IIC_wait_ACK(void);//等待接收确认字符
void IIC_Start(void);//等待IIC传输数据开始
void IIC_Stop(void);//IIC传输数据停止
void IIC_SendByte(u8 byte);//IIC发送数据
u8 IIC_RcvByte(void);//IIC接收数据
void SHT30_read_result(u8 addr);//SHT30温湿度传感器开始读取数据

#endif

3. main.c main function

/*
本程序只供学习使用,未经作者许可,不得用于其他用途!
开 发 板:普中STM32-F1开发板
实验项目:基于STM32F103ZET6的SHT30温湿度检测实验
作    者:xxx//姓名暂时隐藏,有问题可以联系我下面邮箱
邮    箱:[email protected]
日    期:2022年06月08日
版权所有,盗版必究。
*/
#include"stm32f10x.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "SHT30.h"
  	

 int main(void)
 {
    
     
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
	delay_init();	    	 //延时函数初始化	 
	uart_init(9600);	 	//串口初始化为9600
	SHT30_Init();//初始化SHT30 
	printf("SHT30初始化正常,已准备就绪!\r\n");
	while(1)
	{
    
    
		SHT30_read_result(0x44);//ADDR寄存器,地址选择引脚,接GND地址为0x44,接VDD地址为0x45
		delay_ms(1000);
	}
}

4. Summary

1. You must read the timing diagram carefully. The corresponding source code program is built step by step according to the timing diagram. If you encounter an error when building it privately, come back and see how my program was built. .
2. I have not posted the source code of the following three header files in the source code:
#include "delay.h"
#include "sys.h"
#include "usart.h"
First delay is just for delay, and then sys is just System configuration, finally usart is just for printing, so you can refer to the codes written by other institutions for these three files, such as Punctual Atom
3. Only by understanding IIC from the bottom layer can you master IIC well. Currently, there are many graphical interfaces, such as : STM32CubeMX does not need to manually write IIC, just configure it directly on the software.
4. The temperature and humidity conversion formulas have been posted in the sht30.c file. You can also check the official data manual of sht30. 5. You must read the
IIC principle at the beginning of the article carefully. Read every word carefully. I believe it. After reading this, you will have a deeper understanding of IIC.

Guess you like

Origin blog.csdn.net/Mr_zhang1911116/article/details/125178130