一、SHT30介绍
1、简介
SHT30是一种数字湿度和温度传感器,由Sensirion公司生产。它是基于物理蒸发原理的湿度传感器,具有高精度和长期稳定性。SHT30采用I2C数字接口,可以直接与微控制器或其他设备连接。该传感器具有低功耗和快速响应的特点,能够在广泛的温度和湿度范围内准确测量。SHT30还具有内置的温度补偿功能,可以提供精确的湿度和温度测量结果。它广泛用于气象观测、室内环境监测、农业、工业自动化等领域。
2、引脚图
二、原理图
iic记得接上拉电阻哦
三、源码分享
1、iic.h
#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
#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
#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
#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)
{
}