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

}
相关推荐
智者知已应修善业1 小时前
【51单片机用数码管显示流水灯的种类是按钮控制数码管加一和流水灯】2022-6-14
c语言·经验分享·笔记·单片机·嵌入式硬件·51单片机
智商偏低7 小时前
单片机之helloworld
单片机·嵌入式硬件
青牛科技-Allen9 小时前
GC3910S:一款高性能双通道直流电机驱动芯片
stm32·单片机·嵌入式硬件·机器人·医疗器械·水泵、
森焱森11 小时前
无人机三轴稳定控制(2)____根据目标俯仰角,实现俯仰稳定化控制,计算出升降舵输出
c语言·单片机·算法·架构·无人机
白鱼不小白11 小时前
stm32 USART串口协议与外设(程序)——江协教程踩坑经验分享
stm32·单片机·嵌入式硬件
S,D11 小时前
MCU引脚的漏电流、灌电流、拉电流区别是什么
驱动开发·stm32·单片机·嵌入式硬件·mcu·物联网·硬件工程
芯岭技术14 小时前
PY32F002A单片机 低成本控制器解决方案,提供多种封装
单片机·嵌入式硬件
youmdt15 小时前
Arduino IDE ESP8266连接0.96寸SSD1306 IIC单色屏显示北京时间
单片机·嵌入式硬件
嘿·嘘15 小时前
第七章 STM32内部FLASH读写
stm32·单片机·嵌入式硬件
Meraki.Zhang15 小时前
【STM32实践篇】:I2C驱动编写
stm32·单片机·iic·驱动·i2c