STM32、GD32驱动SHT30温湿度传感器源码分享

一、SHT30介绍

1、简介

SHT30是一种数字湿度和温度传感器,由Sensirion公司生产。它是基于物理蒸发原理的湿度传感器,具有高精度和长期稳定性。SHT30采用I2C数字接口,可以直接与微控制器或其他设备连接。该传感器具有低功耗和快速响应的特点,能够在广泛的温度和湿度范围内准确测量。SHT30还具有内置的温度补偿功能,可以提供精确的湿度和温度测量结果。它广泛用于气象观测、室内环境监测、农业、工业自动化等领域。

2、引脚图

二、原理图

iic记得接上拉电阻哦

三、源码分享

1、iic.h

c 复制代码
#ifndef _MYIIC_H
#define _MYIIC_H
#include "sys.h"

//IO方向设置
#define SDA_IN()  {GPIOG->MODER&=~(3<<(12*2));GPIOG->MODER|=0<<12*2;}	//PH5输入模式
#define SDA_OUT() {GPIOG->MODER&=~(3<<(12*2));GPIOG->MODER|=1<<12*2;}  //PH5输出模式
//IO操作
#define IIC_SCL(n)  (n?HAL_GPIO_WritePin(GPIOG,GPIO_PIN_11,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOG,GPIO_PIN_11,GPIO_PIN_RESET)) //SCL
#define IIC_SDA(n)  (n?HAL_GPIO_WritePin(GPIOG,GPIO_PIN_12,GPIO_PIN_SET):HAL_GPIO_WritePin(GPIOG,GPIO_PIN_12,GPIO_PIN_RESET)) //SDA
#define READ_SDA    HAL_GPIO_ReadPin(GPIOG,GPIO_PIN_12)  //输入SDA

//IIC所有操作函数
void IIC_Init(void);                //初始化IIC的IO口				 
void IIC_Start(void);				//发送IIC开始信号
void IIC_Stop(void);	  			//发送IIC停止信号
void IIC_Send_Byte(u8 txd);			//IIC发送一个字节
u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
u8 IIC_Wait_Ack(void); 				//IIC等待ACK信号
void IIC_Ack(void);					//IIC发送ACK信号
void IIC_NAck(void);				//IIC不发送ACK信号

void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
u8 IIC_Read_One_Byte(u8 daddr,u8 addr);	 
#endif

2、iic.c

c 复制代码
#include "myiic.h"
#include "delay.h"


//IIC初始化
void IIC_Init(void)
{
    GPIO_InitTypeDef GPIO_Initure;
    
    __HAL_RCC_GPIOG_CLK_ENABLE();   //使能GPIOH时钟
    
    //PH4,5初始化设置
    GPIO_Initure.Pin=GPIO_PIN_11|GPIO_PIN_12;
    GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;  //推挽输出
    GPIO_Initure.Pull=GPIO_PULLUP;          //上拉
    GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH;    //快速
    HAL_GPIO_Init(GPIOG,&GPIO_Initure);
    
    IIC_SDA(1);
    IIC_SCL(1);  
}

//产生IIC起始信号
void IIC_Start(void)
{
	SDA_OUT();     //sda线输出
	IIC_SDA(1);	  	  
	IIC_SCL(1);
	delay_us(4);
 	IIC_SDA(0);//START:when CLK is high,DATA change form high to low 
	delay_us(4);
	IIC_SCL(0);//钳住I2C总线,准备发送或接收数据 
}	  
//产生IIC停止信号
void IIC_Stop(void)
{
	SDA_OUT();//sda线输出
	IIC_SCL(0);
	IIC_SDA(0);//STOP:when CLK is high DATA change form low to high
 	delay_us(4);
	IIC_SCL(1); 
	IIC_SDA(1);//发送I2C总线结束信号
	delay_us(4);							   	
}
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
u8 IIC_Wait_Ack(void)
{
	u8 ucErrTime=0;
	SDA_IN();      //SDA设置为输入  
	IIC_SDA(1);delay_us(1);	   
	IIC_SCL(1);delay_us(1);	 
	while(READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			IIC_Stop();
			return 1;
		}
	}
	IIC_SCL(0);//时钟输出0 	   
	return 0;  
} 
//产生ACK应答
void IIC_Ack(void)
{
	IIC_SCL(0);
	SDA_OUT();
	IIC_SDA(0);
	delay_us(2);
	IIC_SCL(1);
	delay_us(2);
	IIC_SCL(0);
}
//不产生ACK应答		    
void IIC_NAck(void)
{
	IIC_SCL(0);
	SDA_OUT();
	IIC_SDA(1);
	delay_us(2);
	IIC_SCL(1);
	delay_us(2);
	IIC_SCL(0);
}					 				     
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答			  
void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
	SDA_OUT(); 	    
    IIC_SCL(0);//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        IIC_SDA((txd&0x80)>>7);
        txd<<=1; 	  
		delay_us(2);   //对TEA5767这三个延时都是必须的
		IIC_SCL(1);
		delay_us(2); 
		IIC_SCL(0);	
		delay_us(2);
    }	 
} 	    
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
u8 IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
	{
        IIC_SCL(0); 
        delay_us(2);
		IIC_SCL(1);
        receive<<=1;
        if(READ_SDA)receive++;   
		delay_us(1); 
    }					 
    if (!ack)
        IIC_NAck();//发送nACK
    else
        IIC_Ack(); //发送ACK   
    return receive;
}

3、sht30.h

c 复制代码
#ifndef __SHT30_H
#define __SHT30_H
#include "sys.h"
#include "myiic.h"




#define SHT30_State 0xF32D

#define CMD_CLEAR_STATUS  0x3041 // clear status register
#define CMD_HEATER_ENABLE  0x306D // enabled heater
#define CMD_HEATER_DISABLE  0x3066 // disable heater
#define CMD_MEAS_CLOCKSTR_H  0x2C06
#define CMD_MEAS_POLLING_H  0x2400
#define POLYNOMIAL 0x131 // P(x) = x^8 + x^5 + x^4 + 1 = 100110001// Generator polynomial for CRC


void sht30_init(uint8_t slaveAddr);
uint8_t sht30_read_data(uint8_t slaveAddr,uint16_t mode,uint16_t *temp,uint16_t *humid);

#endif

4、sht30.c

c 复制代码
#include "sht30.h"
#include "delay.h"


//SHT30写命令
void sht30_write_cmd(uint8_t slaveAddr,uint16_t cmd)
{
	IIC_Start();
	IIC_Send_Byte(slaveAddr << 1);
	IIC_Wait_Ack();
	IIC_Send_Byte(cmd >> 8);
	IIC_Wait_Ack();
	IIC_Send_Byte(cmd);
	IIC_Wait_Ack();
	IIC_Stop();
}


uint8_t sht30_calc_crc(uint8_t data[], uint8_t Bytes)
{
	uint8_t bit; // bit mask
	uint8_t crc = 0xFF; // calculated checksum
	uint8_t byteCtr; // byte counter
	// calculates 8-Bit checksum with given polynomial
	for(byteCtr = 0; byteCtr < Bytes; byteCtr++)
	{
		crc^= (data[byteCtr]);
		for(bit = 8; bit > 0; --bit)
		{
			if(crc & 0x80) 
				crc = (crc << 1) ^ POLYNOMIAL;
			else 
				crc = (crc << 1);
		}
	}
	return crc;
}

uint8_t sht30_check_crc(uint8_t data[], uint8_t Bytes, uint8_t checksum)
{
	uint8_t crc; // calculated checksum
		// calculates 8-Bit checksum
	crc = sht30_calc_crc(data, Bytes);
	// verify checksum
	if(crc != checksum) 
		return 0;
	else 
		return 1;
}


//读SHT30状态

uint16_t sht30_read_state(uint8_t slaveAddr)
{
	uint8_t temp[2],crc;
	uint16_t sta;
	IIC_Start();
	IIC_Send_Byte(slaveAddr << 1);
	IIC_Wait_Ack();
	IIC_Send_Byte(SHT30_State >> 8);
	IIC_Wait_Ack();
	IIC_Send_Byte((u8)SHT30_State);
	IIC_Wait_Ack();
	
	IIC_Start();
	IIC_Send_Byte(slaveAddr << 1 | 0x01);
	IIC_Wait_Ack();
	
	temp[0] = IIC_Read_Byte(1);//高位
	temp[1] = IIC_Read_Byte(1);//低位
	crc = IIC_Read_Byte(0);//校验
	IIC_Stop();

	if(sht30_check_crc(temp,2,crc))
	{
		sta = temp[0] << 8 | temp[1];
		return sta;
	}
	else
		return 0;
}
float sht30_calc_temperature(uint16_t rawValue)
{
// calculate temperature [°C]
// T = -45 + 175 * rawValue / (2^16-1)
	return 175.0f * (float)rawValue / 65535.0f - 45.0f;
}
float sht30_calc_humidity(u16 rawValue)
{
// calculate relative humidity [%RH]
// RH = rawValue / (2^16-1) * 100
	return 100.0f * (float)rawValue / 65535.0f;
}

//读取SHT30数据

uint8_t sht30_read_data(uint8_t slaveAddr,uint16_t mode,uint16_t *temp,uint16_t *humid)
{
	uint8_t temp1[2],crc1,temp2[2],crc2;
	uint16_t tempValue;
	sht30_write_cmd(slaveAddr,mode);					//发送测量模式命令,并开始测量
	//delay_ms(5);
	//No Clock Stretching 模式下传感器对第一次微控制器发送的I2CStart() 是没有	ACK的 
	IIC_Start();               
	IIC_Send_Byte(slaveAddr << 1 | 0x01);
	IIC_Stop();
	delay_ms(50);
	//第二次微控制器发送的I2CStart()数据采集转换完成 有ACK
	IIC_Start();
	IIC_Send_Byte(slaveAddr << 1 | 0x01);
	IIC_Wait_Ack();
	
	
	temp1[0] = IIC_Read_Byte(1);//温度高位
	temp1[1] = IIC_Read_Byte(1);//温度低位
	crc1 = IIC_Read_Byte(1);//温度CRC校验值
	
	temp2[0] = IIC_Read_Byte(1);//湿度高位
	temp2[1] = IIC_Read_Byte(1);//湿度低位
	crc2 = IIC_Read_Byte(0);//湿度CRC校验值
	IIC_Stop();
	//CRC 校验
	uint8_t tempCheck = sht30_check_crc(temp1,2,crc1);
	uint8_t humCheck = sht30_check_crc(temp2,2,crc2);
	if(tempCheck)
	{
		tempValue = temp1[0];
		tempValue <<= 8;
		tempValue |= temp1[1];
		*temp = sht30_calc_temperature(tempValue) * 10; //精度0.3°
		
		tempValue = temp2[0];
		tempValue <<= 8;
		tempValue |= temp2[1];
		*humid = sht30_calc_humidity(tempValue);//精度 %2
		return 1;
	}
	else
		return 0;
}

void sht30_init(uint8_t slaveAddr)
{

}
相关推荐
yutian06062 小时前
Keil MDK下载程序后MCU自动重启设置
单片机·嵌入式硬件·keil
析木不会编程5 小时前
【小白51单片机专用教程】protues仿真独立按键控制LED
单片机·嵌入式硬件·51单片机
枯无穷肉9 小时前
stm32制作CAN适配器4--WinUsb的使用
stm32·单片机·嵌入式硬件
不过四级不改名6779 小时前
基于HAL库的stm32的can收发实验
stm32·单片机·嵌入式硬件
嵌入式科普9 小时前
十一、从0开始卷出一个新项目之瑞萨RA6M5串口DTC接收不定长
c语言·stm32·cubeide·e2studio·ra6m5·dma接收不定长
嵌入式大圣9 小时前
单片机UDP数据透传
单片机·嵌入式硬件·udp
云山工作室10 小时前
基于单片机的视力保护及身姿矫正器设计(论文+源码)
stm32·单片机·嵌入式硬件·毕业设计·毕设
嵌入式-老费10 小时前
基于海思soc的智能产品开发(mcu读保护的设置)
单片机·嵌入式硬件
qq_3975623112 小时前
MPU6050 , 设置内部低通滤波器,对于输出数据的影响。(简单实验)
单片机
liyinuo201712 小时前
嵌入式(单片机方向)面试题总结
嵌入式硬件·设计模式·面试·设计规范