锐单电子商城 , 一站式电子元器件采购平台!
  • 电话:400-990-0325

STM32F1 & SHT3x温湿度模块

时间:2023-11-27 16:37:02 sht3x传感器

STM32F1 & SHT3x温湿度模块

提示:以下程序是基于STM32F103和SHT3x系列硬件


文章目录

  • STM32F1 & SHT3x温湿度模块
  • 一、STM32CubeMX工程配置
  • 二、程序&说明
    • 1.模拟IIC程序
    • 2,SHT3x底层
    • 3,使用说明


一、STM32CubeMX工程配置

说明:本例程采用模拟IIC,因此需要对应IO配置为推输出,默认为高电平
在这里插入图片描述

二、程序&说明

1.模拟IIC程序

myiic.c

#include "myiic.h" #include "delay.h"  //产生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,接收应答成功
uint8_t IIC_Wait_Ack(void)
{ 
        
	uint8_t 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(uint8_t txd)
{ 
                                
	uint8_t 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 
uint8_t 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;
}

myiic.h

#ifndef _MYIIC_H
#define _MYIIC_H

#include "delay.h"
#include "main.h"

//IO方向设置
#define SDA_IN() { 
          GPIOB->CRH&=0XFFFFFFF0;GPIOB->CRH|=(uint32_t)8<<0;} //PB7输入模式
#define SDA_OUT() { 
          GPIOB->CRH&=0XFFFFFFF0;GPIOB->CRH|=(uint32_t)3<<0;} //PB7输出模式

//IO操作
#define IIC_SCL(n) (n ? HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_SET) : HAL_GPIO_WritePin(GPIOB,GPIO_PIN_9,GPIO_PIN_RESET)) //SCL
#define IIC_SDA(n) (n ? HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_SET) : HAL_GPIO_WritePin(GPIOB,GPIO_PIN_8,GPIO_PIN_RESET)) //SDA
#define READ_SDA HAL_GPIO_ReadPin(GPIOB,GPIO_PIN_8) //输入SDA

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

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

以上底层是基于STM32F103,若要使用在STM32其他系列上请自行移植
提示:需要修改delay.hdelay.c文件,注意时序,并且更改myiic.h中的引脚配置,如下图(注::F4和F1的IO方向设置寄存器不一样,请自行查看数据手册进行修改)

2,SHT3x底层

sht3x.c

#include "sht3x.h"
#include "myiic.h"

_TW data_process;  //定义温湿度结构体

static void SHT3x_WriteCommand(uint16_t COMMAND);	//SHT30命令写入

void SHT3x_Init(void)		//SHT30初始化
{ 
        
	IIC_Start();
	IIC_Send_Byte(SHTx_Device_ADDR << 1 | Write_DATA);	//写入地址和写命令
	SHT3x_WriteCommand(PERI_HIGH_1_CMD);								//设置为周期读取频率为1hz
	IIC_Stop();
}

static void SHT3x_WriteCommand(uint16_t COMMAND)	//SHT30命令写入
{ 
        
	IIC_Wait_Ack();
	IIC_Send_Byte(COMMAND >> 8);		//传输高8位
	IIC_Wait_Ack();
	IIC_Send_Byte(COMMAND & 0xFF);	//传输低8位
	IIC_Wait_Ack();
}

void SHT3x_READ_TEMP_Humi(uint16_t *dat)	//SHT3x读取数据
{ 
        
	IIC_Start();
	IIC_Send_Byte(SHTx_Device_ADDR << 1 | Write_DATA); //写入地址和写命令
	SHT3x_WriteCommand(READOUT_FOR_PERIODIC_MODE);		 //读取周期测量寄存器中的值
	
	//下面是开始读取数据,其中的指针dat存放结果,前三个存放温度值,后三个是湿度值,在前三个温度值里面,
	//dat[0]是温度的高八位,dat[1]是低八位,dat[2]是CRC校验
   
	IIC_Start();
	IIC_Send_Byte(SHTx_Device_ADDR << 1 | Read_DATA);	//写入地址和读命令
	IIC_Wait_Ack();

	//前五次读取都要发送ack信号,最后一次就不用发了。
	dat[0] = IIC_Read_Byte(1);	//温度的高八位
	dat[1] = IIC_Read_Byte(1);	//温度的低八位
	dat[2] = IIC_Read_Byte(1);	//温度的CRC位
	
	dat[3] = IIC_Read_Byte(1);	//湿度的高八位
	dat[4] = IIC_Read_Byte(1);	//湿度的低八位
	dat[5] = IIC_Read_Byte(0);	//湿度的CRC位
	IIC_Stop();
}

/* CRC校验函数(是确保通信过程中数据传输没问题的,没有缺少任何数据, 当我们接收到数据后,按照一定的方式计算一个crc校验码, 经过和提供的crc校验码进行比较,如果两个码一样,那么数据就是没问题的。) */
int CRC8_Compute(uint8_t *check_data, uint8_t num_of_data)
{ 
        
	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 < num_of_data; byteCtr++)
	{ 
        
		crc ^= (check_data[byteCtr]);
		//crc校验,最高位是1就^0x31
		for(bit = 8; bit > 0; --bit) 
		{ 
        
			if(crc & 0x80) 
				 crc = (crc << 1) ^ 0x31;
			else
				 crc = (crc << 1);
     }
 }
 return crc;
}

int SHT3x_CRC8_Check(uint8_t *p,uint8_t num_of_data,uint8_t CrcData)
{ 
        
  uint8_t crc;
  crc = CRC8_Compute(p, num_of_data);// calculates 8-Bit checksum
 if(crc != CrcData) 
 { 
           
     return 1;           
 }
 return 0;
}

uint8_t SHT3x_Data_Process(void)	//温湿度测量函数
{ 
        
	uint8_t temporary[3];
  uint16_t data;
  uint8_t crc_result;
  
  SHT3x_READ_TEMP_Humi(data_process.sht30_data_buffer);
  //先处理温度的相关数据,位于数组的前三个
  temporary[0]=data_process.sht30_data_buffer[0];
  temporary[1]=data_process.sht30_data_buffer[1];
  temporary[2]=data_process.sht30_data_buffer[2];
  //crc校验
  crc_result=SHT3x_CRC8_Check(temporary,2,temporary[2]);
  //crc校验要是不成功就返回1,同时不会更新温度值
  if(crc_result==0)
  { 
        
		//把2个8位数据拼接为一个16位的数据
		data=((uint16_t)temporary[0] << 8) | temporary[1];
		//温度转换,将16位温度数据转化为10进制的温度数据,这里保留了一位小数,data_process.SHT30_temperature这是一个全局变量
		data_process.SHT30_temperature = ((175.0f * ((float)data) / 65535.0f - 45.0f) *1.0f);
  }
  else
  { 
        
		return 1;
  }
  temporary[0]=data_process.sht30_data_buffer[3];
  temporary[1]=data_process.sht30_data_buffer[4];
  temporary[2]=data_process.sht30_data_buffer[5];
  //crc校验
  crc_result=SHT3x_CRC8_Check(temporary,2,temporary[2]);
  if(crc_result==0)
  { 
        
		//参考上面温度的代码
		data=((uint16_t)temporary[0] << 8) | temporary[1];
		//湿度转换,将16位温度数据转化为10进制的温度数据,这里保留了一位小数,data_process.SHT30_temperature这是一个全局变量
		data_process.SHT30_humidity = ((100.0f * (float)data / 65535.0f) *1.0f); 
		return 0;
  }
  else
  { 
        
		return 2;
  }
}

sht3x.h

#ifndef __SHT3x_H
#define __SHT3x_H 

#include "stm32f1xx_hal.h"
#include "myiic.h"
#include "usart.h"

typedef enum{ 
        
	
	SHTx_Device_ADDR		=	0x44,		//设备地址
	Write_DATA 					= 0x00,		//写数据/命令
	Read_DATA 					= 0x01,		//读数据/命令

	SOFT_RESET_CMD = 0x30A2,			//软件复位命令
	
	/* 单次测量模式 */
	CLOCK_HIGH_ENABLED_CMD    = 0x2C06,
	CLOCK_MEDIUM_ENABLED_CMD  = 0x2C0D,
	CLOCK_LOW_ENABLED_CMD     = 0x2C10,
	CLOCK_HIGH_DISABLED_CMD   = 0x2400,
	CLOCK_MEDIUM_DISABLED_CMD = 0x240B,
	CLOCK_LOW_DISABLED_CMD    = 0x2416,

	/* 周期测量模式 */
	PERI_HIGH_0_5_CMD   	= 0x2032,
	PERI_MEDIUM_0_5_CMD 	= 0x2024,
	PERI_LOW_0_5_CMD    	= 0x202F,
	
	PERI_HIGH_1_CMD     	= 0x2130,
	PERI_MEDIUM_1_CMD   	= 0x2126,
	PERI_LOW_1_CMD      	= 0x212D,		//1s测量一次(1Hz)
	
	PERI_HIGH_2_CMD     	= 0x2236,
	PERI_MEDIUM_2_CMD   	= 0x2220,
	PERI_LOW_2_CMD      	= 0x222B,
	
	PERI_HIGH_4_CMD     	= 0x2334,
	PERI_MEDIUM_4_CMD   	= 0x2322,
	PERI_LOW_4_CMD      	= 0x2329,
	
	PERI_HIGH_10_CMD    	= 0x2737,
	PERI_MEDIUM_10_CMD  	= 0x2721,
	PERI_LOW_10_CMD     	= 0x272A,	//1s测量10次(10Hz)
	
	HEATER_ENABLED_CMD		= 0x306D,	//加热器使能
	HEATER_DISABLED_CMD		= 0x3066,	//加热器失能
	
	READ_STATUS_CMD				= 0xF32D,	//读取状态寄存器
	CLEAR_STATUS_CMD			= 0x3041,	//清除状态寄存器

	READOUT_FOR_PERIODIC_MODE = 0xE000,	// 周期测量模式读取数据命令
}SHT30_CMD;

typedef struct
{ 
        
	unsigned short int sht30_data_buffer[6];
	float SHT30_temperature;	//温度
	float SHT30_humidity;			//湿度
	
}_TW;

extern _TW data_process;  //定义温湿度结构体

void SHT3x_Init(void);										//SHT30初始化
void SHT3x_READ_TEMP_Humi(uint16_t *dat);	//写一个命令给SHT30,并读取数据
uint8_t SHT3x_Data_Process(void);					//温湿度测量函数

// CRC校验函数
int  CRC8_Compute(uint8_t *check_data, uint8_t num_of_data);
int SHT3x_CRC8_Check(uint8_t *p,uint8_t num_of_data,uint8_t CrcData);

#endif 

3,使用说明

  • 调用SHT3x_Init初始化函数
  • 周期调用SHT3x_Data_Process数据测量函数
  • 所需数据在结构体data_process
锐单商城拥有海量元器件数据手册IC替代型号,打造电子元器件IC百科大全!

相关文章