Stm32F4标准库驱动Sht4温湿度传感器

SHT4温湿度传感器

1.1 SHT4参数

Stm32F4标准库驱动Sht4温湿度传感器_第1张图片

  • 精度 湿度ΔRH = ±1.0% RH,温度 ΔT =±0.1°C
  • 工作范围:0 ~ 100% RH,−40 ~ 125℃

1.2 IIC通讯读取温湿度

Stm32F4标准库驱动Sht4温湿度传感器_第2张图片

1.3 数据格式

​ 总共6个字节

​ 湿度和温度数据将始终以以下方式传输:第一个值是温度信号(2 * 8位数据+ 8位CRC),第二个值是湿度信号(2 * 8位数据+ 8位CRC)。

1.4 CRC校验

Stm32F4标准库驱动Sht4温湿度传感器_第3张图片

  • 单字节
unsigned char cal_table_high_first(unsigned char value)
{
    unsigned char i, crc;
    crc = value;
    /* 数据往左移了8位,需要计算8次 */
    for (i=8; i>0; --i)
    { 
        if (crc & 0x80)  /* 判断最高位是否为1 */
        {
        /* 最高位为1,不需要异或,往左移一位,然后与0x31异或 */
        /* 0x31(多项式:x8+x5+x4+1,100110001),最高位不需要异或,直接去掉 */
            crc = (crc << 1) ^ 0x31;        }
        else
        {
            /* 最高位为0时,不需要异或,整体数据往左移一位 */
            crc = (crc << 1);
        }
    }
 
    return crc;
}
  • 多字节
unsigned char crc_high_first(unsigned char *ptr, unsigned char len)
{
    unsigned char i; 
    unsigned char crc=0x00/* 计算的初始crc值 */ 
 
    while(len--)
    {
        crc ^= *ptr++;  /* 每次先与需要计算的数据异或,计算完指向下一数据 */  
        for (i=8; i>0; --i)   /* 下面这段计算过程与计算一个字节crc一样 */  
        { 
            if (crc & 0x80)
                crc = (crc << 1) ^ 0x31;
            else
                crc = (crc << 1);
        }
    }
 
    return (crc); 
}

1.5 通讯命令与计算公式

Stm32F4标准库驱动Sht4温湿度传感器_第4张图片

  • 0xFD 启用高精度温湿度检测。

1.6 实例

Stm32F4标准库驱动Sht4温湿度传感器_第5张图片

立创商城搜索对应的原件看对应的数据手册

1.6.1 STM32F4标准库程序

  • iic.h
#ifndef __IICTEST_H
#define __IICTEST_H

#ifdef __cplusplus
extern "C"{
#endif

#include "delay.h"
#include "stm32f4xx.h"

//IO方向设置产考F4手册
/**********************************begin**************************************/
#define SDA_In()  {GPIOC->MODER&=~(3<<(7*2));GPIOC->MODER|=0<<7*2;}
#define SDA_Out() {GPIOC->MODER&=~(3<<(7*2));GPIOC->MODER|=1<<7*2;}
/**********************************end************************************/

#define IIC_SCL_PIN																	GPIO_Pin_6
#define IIC_SDA_PIN																	GPIO_Pin_7
#define IIC_GPIO_PORT																GPIOC

#define Delay_ms(x)    															delay_ms(x)
#define Delay_us(x)    															delay_us(x)

//IO操作函数	 
#define IIC_Scl(a)   																GPIO_WriteBit(IIC_GPIO_PORT, IIC_SCL_PIN, a)
#define IIC_Sda(a)  																GPIO_WriteBit(IIC_GPIO_PORT, IIC_SDA_PIN, a)
#define READ_Sda   	  															GPIO_ReadInputDataBit(IIC_GPIO_PORT, IIC_SDA_PIN)

//IIC所有操作函数
void IIC_Init_S(uint32_t RCC_CLK);   												//初始化IIC的IO口				 
void IIC_Start(void);																			//发送IIC开始信号
void IIC_Stop(void);	  																	  //发送IIC停止信号
void IIC_Send_Byte(uint8_t txd);														//IIC发送一个字节
void IIC_Ack(void);																				//IIC发送ACK信号
void IIC_NAck(void);																			  //IIC不发送ACK信号										  
uint8_t  IIC_Wait_Ack(void); 															//IIC等待ACK信号
uint8_t  IIC_Read_B(uint8_t ack);													//IIC读取一个字节
uint32_t  IIC_Read_Byte(uint8_t ack,uint8_t* recvdata,uint8_t num);//IIC读取n个字节

#ifdef __cplusplus
}
#endif
#endif
  • iic.c
#include "iictest.h"
/*----------------------------------*/
/*									*/
/*			初始化IIC				*/
/*									*/
/*----------------------------------*/
void IIC_Init_S(uint32_t RCC_CLK)
{					     
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_AHB1PeriphClockCmd(	RCC_CLK, ENABLE );						
	   
	GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN|IIC_SCL_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
	GPIO_Init(IIC_GPIO_PORT, &GPIO_InitStructure);
	GPIO_SetBits(IIC_GPIO_PORT,IIC_SCL_PIN|IIC_SDA_PIN);
}

/*----------------------------------*/
/*									*/
/*	     产生IIC起始信号			*/
/*  								*/
/*----------------------------------*/
void IIC_Start(void)
{
	SDA_Out();
	IIC_Sda(1);	  	  
	IIC_Scl(1);
	Delay_us(4);
 	IIC_Sda(0);
	Delay_us(4);
	IIC_Scl(0);
}

/*----------------------------------*/
/*									*/
/*	    	产生IIC停止信号 		*/
/*									*/
/*----------------------------------*/
void IIC_Stop(void)
{
	SDA_Out();
	IIC_Scl(0);
	IIC_Sda(0);
 	Delay_us(4);
	IIC_Scl(1); 
	IIC_Sda(1);
	Delay_us(2);						   	
}

/*----------------------------------*/
/*									*/
/*	       等待应答					*/
/*	返回值	1:接收应答失败			*/
/*			0:接收应答成功			*/
/*----------------------------------*/
uint8_t IIC_Wait_Ack(void)
{
	uint8_t ucErrTime=0;
	SDA_In();      													
	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);
	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(1);
}

/*----------------------------------*/
/*									*/
/*			不产生ACK应答			*/
/*									*/
/*----------------------------------*/	    
void IIC_NAck(void)
{
	IIC_Scl(0);
	SDA_Out();							
  IIC_Sda(1);Delay_us(2);	
	IIC_Scl(1);Delay_us(2);
	IIC_Scl(1);
}		

/*----------------------------------*/
/*									*/
/*	 IIC发送一个字节			    */
/*	    @txd:	要发送的数据		*/
/*	    返回值:1,有应答			*/
/*		    	0,无应答			*/
/*----------------------------------*/		  
void IIC_Send_Byte(uint8_t txd)
{                        
		uint8_t t;   
		SDA_Out(); 	    												
		IIC_Scl(0);															
		for(t=0;t<8;t++)
		{              
			if((txd&0x80)>>7)									
				IIC_Sda(1);
			else
				IIC_Sda(0);
			txd<<=1; 	  											
			Delay_us(2);   														
			IIC_Scl(1);	
			Delay_us(2); 
			IIC_Scl(0);	
			Delay_us(2);
    }	 
} 	


/*----------------------------------*/
/*									*/
/*	IIC读取连续2个字节			        */
/*	    返回值:接收到的数据		*/
/*	    @ ack:	1
,需要应答			*/
/*				0,不需要应答		*/
/*----------------------------------*/		 
	
uint32_t  IIC_Read_Byte(uint8_t ack,uint8_t* recvdata,uint8_t num)
{
	uint32_t    data=0;
	while(num--)
	{
		*recvdata++ = IIC_Read_B(ack);
	}
	return  data;
}

uint8_t  IIC_Read_B(uint8_t ack)
{
	unsigned char i;
	uint8_t receive;
	SDA_In();								
	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();	
  else 
		IIC_Ack(); 	
									
  return receive;
}
  • SHT4.h
#ifndef 	__SHT1000_H
#define 	__SHT1000_H
#include   "delay.h"
#include   "iictest.h"

void SHT45_Init(void);
uint8_t SHT45_ReadPdata(uint8_t ack,uint8_t *arr,float* T,float* H );
extern uint32_t SHT45_Data1[2];
#endif

  • SHT4.c
#include	 "SHT1000.h"

uint32_t SHT45_Data1[2]={0};

void SHT45_Init(void)             //初始化IIC        PC6:SCL     PC7:SDA
{
	IIC_Init_S(RCC_AHB1Periph_GPIOC);
}

/* 读取压力数据寄存器*/ 
uint8_t SHT45_ReadPdata(uint8_t ack,uint8_t *arr,float* T,float* H )
{
	  int32_t CRC1=0XFF;
	  int32_t CRC2=0XFF;
	
		//开启温度转换
		IIC_Start();														
		IIC_Send_Byte (0x88);	//0x44 <<1 +0
		delay_us(2);
		while(IIC_Wait_Ack ()!=0){}; 
		IIC_Send_Byte (0xFD);
		while(IIC_Wait_Ack ()!=0){}; 
		IIC_Stop();
			
		delay_ms(10);
		//读取温度
		IIC_Start();
    IIC_Send_Byte (0x89);	//0x44 <<1 +1
		delay_us(2);
    while(IIC_Wait_Ack()!=0){}; 
    IIC_Read_Byte(ack,arr,6);
		IIC_Stop();
		SHT45_Data1[0] =arr[0]<<8|arr[1];
		*T = (-45 + 175*(SHT45_Data1[0])/65535.0);
    CRC1= arr[2];
		SHT45_Data1[1] =arr[3]<<8|arr[4];
		*H =(-6 + 125 *( SHT45_Data1[1])/65535.0);
		CRC2= arr[5];
    return 1;          
}
  • main.c
uint8_t arr[6]={0};
float T,H;	
int main(void)
{ 
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
	delay_init(168);    //初始化延时函数
	uart_init(115200);	//初始化串口波特率为115200
	
 	LED_Init();			//初始化LED 
	SHT45_Init();
	delay_us(2);
	
  	while(1)
	{
        delay_ms(1000);
        SHT45_ReadPdata(1,arr,&T,&H);
        printf("T:%f....H:%f\r\n",T,H);
	}		
}
  • 效果
    Stm32F4标准库驱动Sht4温湿度传感器_第6张图片

你可能感兴趣的:(STM32小实验,stm32,嵌入式硬件,单片机)