STM32、C51驱动中科银河芯GXHT30温湿度芯片,可PIN TO PIN软硬件兼容SHT30 SHT31_gxht30驱动程序(2)

| — | — |
| 产品型号 | GXHT30 |
| 通信方式 | IIC-bus |
| 分辨率 | 16bit ADC |
| 封装大小 | 2.5mm × 2.5mm x 0.9mm (DFN-8) |
| 工作电压 | 2.5~5.5V |
| 工作范围 | -45~130℃ |
| 温度精度(典型) | ±0.3°C (-40°C ~ 90°C) |
| 湿度精度(典型) |  ±3% (10% ~ 90%) |
| IIC地址 | 0x44、0x45可选 |
| 平均功耗 | 2uA(@3.3V) |
| 空闲状态 | 0.2uA(@3.3V) |
| 抗静电能力 | 8KV(HBM),850V(CDM) |

三、参考驱动

通信时序

驱动实例
1、STM32F103 + GXHT30/GXHT31温湿度芯片驱动实例
STM32 GXHT30.h文件
#ifndef _GXHT30_H
#define _GXHT30_H

#include "stm32f10x.h"
#include "string.h"
#include "stdio.h"

extern float GXHT30_temp;

//如果移植程序时只要改一下三个地方就行了
#define GXHT30_SCL GPIO_Pin_5	                    //SCL-PA5
#define GXHT30_SDA GPIO_Pin_6	                    //SDA-PA6
#define GPIO_GXHT30 GPIOA

#define GXHT30_SCL_H GPIO_SetBits(GPIO_GXHT30,GXHT30_SCL)
#define GXHT30_SCL_L GPIO_ResetBits(GPIO_GXHT30,GXHT30_SCL)

#define GXHT30_SDA_H GPIO_SetBits(GPIO_GXHT30,GXHT30_SDA)
#define GXHT30_SDA_L GPIO_ResetBits(GPIO_GXHT30,GXHT30_SDA)

/* 声明全局函数 */
void GXHT30_INIT(void);
void GXHT30_SDA_OUT(void);
void GXHT30_SDA_IN(void);
void GXHT30_SDA_in(void);
void GXHT30_StarT(void);
void GXHT30_StoP(void);
void GXHT30_Ack(void);
void GXHT30_NAck(void);
u8   GXHT30_Wait_Ack(void);
void GXHT30_Send_Byte(u8 txd);
u8   GXHT30_Read_Byte(u8 ack);
void GXHT30_read_result(u8 addr);

void al_get_gxth30_temp(void);

#endif
STM32 GXHT30.c文件
#include "GXHT30.h"
#include "delay.h"

#define write 0
#define read  1

//定义全局变量
float GXHT30_temp,GXHT30_humi,GXHT30_Temperature,GXHT30_Humidity;

/*
* @name   CRC_8
* @brief  CRC-8校验
* @param  Crc_ptr   -> 校验数据首地址
		L  EN       -> 校验数据长度
* @retval CRC_Value -> 校验值      
*/
static uint8_t CRC_8(uint8_t *Crc_ptr,uint8_t LEN)
{
	uint8_t CRC_Value = 0xFF;
	uint8_t i = 0,j = 0;

	for(i=0;i<LEN;i++)
	{
		CRC_Value ^= *(Crc_ptr+i);
		for(j=0;j<8;j++)
		{
			if(CRC_Value & 0x80)
				CRC_Value = (CRC_Value << 1) ^ 0x31;
			else
				CRC_Value = (CRC_Value << 1);
		}
	}
	return CRC_Value;
}

/****************************************************************************
* Function Name  : GXHT30_INIT
* Description    : 初始化GPIO.
****************************************************************************/
void GXHT30_INIT()
{	
	GPIO_InitTypeDef GPIO_InitStructure;	
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitStructure.GPIO_Pin=GXHT30_SDA;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
			
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitStructure.GPIO_Pin=GXHT30_SCL;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;
	GPIO_Init(GPIOA,&GPIO_InitStructure);

	GXHT30_SCL_H;
	GXHT30_SDA_H;
}

/*******************************************************************************
* 函 数 名         : GXHT30_SDA_OUT
* 函数功能		   : SDA输出配置	   
*******************************************************************************/
void GXHT30_SDA_OUT()
{
  GPIO_InitTypeDef GPIO_InitStructure;	
	
	GPIO_InitStructure.GPIO_Pin=GXHT30_SDA;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
}

/*******************************************************************************
* 函 数 名         : GXHT30_SDA_IN
* 函数功能		   : SDA输入配置	   
*******************************************************************************/
void GXHT30_SDA_IN(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;	
	
	GPIO_InitStructure.GPIO_Pin=GXHT30_SDA;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_OD;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
}

void GXHT30_SDA_in(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;	
	
	GPIO_InitStructure.GPIO_Pin=GXHT30_SDA;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
}

/*******************************************************************************
* 函 数 名         : GXHT30_StarT
* 函数功能		   : IIC起始信号	   
*******************************************************************************/
void GXHT30_StarT(void)
{
    GXHT30_SDA_OUT();

	GXHT30_SDA_H;
	GXHT30_SCL_H;
	delay_us(5);
	GXHT30_SDA_L;
	delay_us(6);
	GXHT30_SCL_L;
}

/*******************************************************************************
* 函 数 名         : GXHT30_StoP
* 函数功能		   : 产生停止信号   
*******************************************************************************/
void GXHT30_StoP(void)
{
   GXHT30_SDA_OUT();

   GXHT30_SCL_L;
   GXHT30_SDA_L;
   GXHT30_SCL_H;
   delay_us(6);
   GXHT30_SDA_H;
   delay_us(6);
}

/*******************************************************************************
* 函 数 名         : GXHT30_Ack
* 函数功能		   : 主机产生应答信号ACK   
*******************************************************************************/
void GXHT30_Ack(void)
{
   GXHT30_SCL_L;
   GXHT30_SDA_OUT();
   GXHT30_SDA_L;
   delay_us(2);
   GXHT30_SCL_H;
   delay_us(5);
   GXHT30_SCL_L;
}

/*******************************************************************************
* 函 数 名         : GXHT30_NAck
* 函数功能		   : 主机不产生应答信号NACK   
*******************************************************************************/

void GXHT30_NAck(void)
{
   GXHT30_SCL_L;
   GXHT30_SDA_OUT();
   GXHT30_SDA_H;
   delay_us(2);
   GXHT30_SCL_H;
   delay_us(5);
   GXHT30_SCL_L;
}

/*******************************************************************************
* 函 数 名         : GXHT30_Wait_Ack
* 函数功能		   : 等待从机应答信号
                     返回值: 1 接收应答失败
                    		 0 接收应答成功 
*******************************************************************************/
u8 GXHT30_Wait_Ack(void)
{
	u8 tempTime=0;
	GXHT30_SDA_IN();
	GXHT30_SDA_H;
	delay_us(1);
	GXHT30_SCL_H;
	delay_us(1);

	while(GPIO_ReadInputDataBit(GPIO_GXHT30,GXHT30_SDA))
	{
		tempTime++;
		delay_us(1);
		if(tempTime>250)
		{
			GXHT30_StoP();
			return 1;
		}	 
	}
	GXHT30_SCL_L;
	delay_us(1);
	return 0;
}

/*******************************************************************************
* 函 数 名         : GXHT30_Send_Byte
* 函数功能		   : 主机发送一个字节
*******************************************************************************/
void GXHT30_Send_Byte(u8 txd)
{
	u8 i=0;
	GXHT30_SDA_OUT();
	GXHT30_SCL_L;        //拉低时钟开始数据传输

	for(i=0;i<8;i++)
	{
		if((txd&0x80)>0) //0x80  1000 0000
			GXHT30_SDA_H;
		else
			GXHT30_SDA_L;

		txd<<=1;
		delay_us(1);
		GXHT30_SCL_H;
		delay_us(2); 
		GXHT30_SCL_L;
		delay_us(2);
	}
}

/*******************************************************************************
* 函 数 名         : GXHT30_Read_Byte
* 函数功能		   : 主机读取一个字节
*******************************************************************************/
u8 GXHT30_Read_Byte(u8 ack)
{
   u8 i=0,receive=0;

   GXHT30_SDA_in();
   for(i=0;i<8;i++)
   {
   		GXHT30_SCL_L;
		delay_us(2);
		GXHT30_SCL_H;
		while(!GPIO_ReadInputDataBit(GPIO_GXHT30,GXHT30_SCL));
		receive<<=1;
		if(GPIO_ReadInputDataBit(GPIO_GXHT30,GXHT30_SDA))
		   receive++;
		delay_us(1);	
   }

   	if(ack==0)
	   	GXHT30_NAck();
	else
		GXHT30_Ack();

	return receive;
}

/*******************************************************************************
* 函 数 名         : GXHT30_read_result
* 函数功能		   : 读数据 addr->0x44 0x45
*******************************************************************************/
void GXHT30_read_result(u8 addr)
{
	u16 tem,hum;
	unsigned char buff[6];

	float Temperature=0;
	float Humidity=0;
		
	GXHT30_StarT();
	GXHT30_Send_Byte(addr<<1 | write);//写7位GXHT30设备地址加0作为写取位,1为读取位
	GXHT30_Wait_Ack();
	GXHT30_Send_Byte(0x2C);
	GXHT30_Wait_Ack();
	GXHT30_Send_Byte(0x10);
	GXHT30_Wait_Ack();
	GXHT30_StoP();
	
	delay_ms(15);                    //数据转换
	
	GXHT30_StarT();
	GXHT30_Send_Byte(addr<<1 | read);//写7位GXHT30设备地址加0作为写取位,1为读取位
	
	if(GXHT30_Wait_Ack()==0)
	{
		GXHT30_SDA_in();
			
		buff[0]=GXHT30_Read_Byte(1);
		buff[1]=GXHT30_Read_Byte(1);
		buff[2]=GXHT30_Read_Byte(1);
		buff[3]=GXHT30_Read_Byte(1);
		buff[4]=GXHT30_Read_Byte(1);
		buff[5]=GXHT30_Read_Byte(0);
		GXHT30_StoP();
		
		if(CRC_8(buff, 2) == buff[2] && CRC_8(buff + 3, 2) == buff[5])
		{
			tem = ((buff[0]<<8) | buff[1]);//温度拼接
			hum = ((buff[3]<<8) | buff[4]);//湿度拼接
			
/*转换实际温度*/
			Temperature = (175.0*(float)tem/65535.0-45.0) ;// T = -45 + 175 * tem / (2^16-1)
			Humidity = (100.0*(float)hum/65535.0);// RH = hum*100 / (2^16-1)
		}
		else
		{
			GXHT30_temp = 0;
			GXHT30_humi = 0;
		}
	}
	
	if((Temperature>=-20)&&(Temperature<=125)&&(Humidity>=0)&&(Humidity<=100))//过滤错误数据
	{
		GXHT30_temp = Temperature;
		GXHT30_humi = Humidity;
	}

	tem = 0;
	hum = 0;
}

/*******************************************************************************
* 函 数 名         : al_float_buffer_sort
* 函数功能		   : 多次读数值排序取中间值平均
*******************************************************************************/
void al_float_buffer_sort(float *buf, uint8_t length)
{
	uint8_t i, j;
	float tmp;
	for (i = 0; i < length; i++)
	{
		for (j = i + 1; j < length; j++)
		{
			if (buf[j] < buf[i])
			{
				tmp = buf[j];
				buf[j] = buf[i];
				buf[i] = tmp;
			}
		}
	}
}

void al_get_gxth30_temp(void)
{
	float buff_temp[20],buff_humi[20];
	for(u8 i = 0;i < 10;i++)
	{	
		GXHT30_read_result(0x44);
		buff_temp[i] = GXHT30_temp;
		buff_humi[i] = GXHT30_humi;
	}
	
	al_float_buffer_sort(buff_temp,10);
	al_float_buffer_sort(buff_humi,10);
	
	GXHT30_Temperature = (buff_temp[4] + buff_temp[5]) / 2;
	GXHT30_Humidity = (buff_humi[4] + buff_humi[5]) / 2;
	
	printf("温度:%0.2f, 湿度:%0.2f",GXHT30_Temperature,GXHT30_Humidity);
}


2、C51 + GXHT30/GXHT31温湿度芯片驱动实例
C51GXHT30.h文件
#ifndef _gxht30_H_
#define _gxht30_H_

#include "main.h"

sbit SCL  = P3^2;    //I2C时钟线
sbit SDA  = P3^3;    //I2C数据线

#define ACK	0
#define NACK	1

extern float Temp,Humi;

// Error codes
typedef enum{
  NO_ERROR       = 0x00, // no error
  ACK_ERROR      = 0x01, // no acknowledgment error
  CHECKSUM_ERROR = 0x02, // checksum mismatch error
  TIMEOUT_ERROR  = 0x04, // timeout error
  PARM_ERROR     = 0x80, // parameter out of range error
}etError;

extern etError error;

// Sensor Commands
typedef enum
{
	CMD_MEAS_CLOCKSTR_H = 0x2C06, // meas. clock stretching, high rep.
	CMD_MEAS_CLOCKSTR_M = 0x2C0D, // meas. clock stretching, medium rep.
	CMD_MEAS_CLOCKSTR_L = 0x2C10, // meas. clock stretching, low rep.
	CMD_MEAS_POLLING_H  = 0x2400, // meas. no clock stretching, high rep.
	CMD_MEAS_POLLING_M  = 0x240B, // meas. no clock stretching, medium rep.
	CMD_MEAS_POLLING_L  = 0x2416, // meas. no clock stretching, low rep.

}etCommands;


#define gxht30ADDR 0x44                 //gxht30的I2C地址 0s44/0x45
#define gxht30WriteHeader gxht30ADDR << 1
#define gxht30ReadHeader  gxht30WriteHeader | 1

extern void sys_iic_init(void);
extern etError gxht30_XHGetTempAndHumi(float        *temp,
                                       float        *humi);
extern void al_get_gxthc3_tempandhumi(void);

#endif

C51GXHT30.c文件
#include "gxht30.h"

#include <intrins.h>
#include <stdio.h>

include "delay.h"
#include "io.h"

etError error;

//定义全局温湿度变量
float gxht30_temp_val,gxht30_humi_val;

void sys_iic_init(void)
{
	P3CR = 0x0C;			//PxCR=0是输入,=1是输出
	P3PCR = 0x0C;
	
	SCL = 1;       		    //I2C时钟线
    SDA = 1;       		    //I2C数据线
}


#define POLYNOMIAL  0x31   // P(x) = x^8 + x^5 + x^4 + 1 = 00110001

//CRC校验函数
unsigned char gxht30_CalcCrc(unsigned char *crcdata, unsigned char nbrOfBytes)
{
  unsigned char Bit;        // bit mask
  unsigned char crc = 0xFF; // calculated checksum
  unsigned char byteCtr;    // byte counter
  
  // calculates 8-Bit checksum with given polynomial 
  for(byteCtr = 0; byteCtr < nbrOfBytes; byteCtr++)
  {
    crc ^= (crcdata[byteCtr]);
    for(Bit = 8; Bit > 0; --Bit)
    {
      if(crc & 0x80) crc = (crc << 1) ^ POLYNOMIAL;
      else           crc = (crc << 1);
    }
  }
	return crc;
}

///*******延时函数、可自行适当调整*************/
void delay_5us(void)
{
	uint8_t i;
	for(i=0;i<3;i++);
}

///*******I2C总线启动函数*************/
void I2C_Start(void)
{
    SDA = 1;
    delay_5us();
## 最后

**自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。**

**深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。**

**因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。**

![img](https://img-blog.csdnimg.cn/img_convert/bdb2086207341c9fe186ca6cf5284b08.png)

![img](https://img-blog.csdnimg.cn/img_convert/e7f664cf5ed073a0860143e3a29b2878.jpeg)

![img](https://img-blog.csdnimg.cn/img_convert/61879e0436015f6a0d60d985ebdd0d46.png)

 ![img](https://img-blog.csdnimg.cn/img_convert/d9416c92cda18dd55ee08aff6225b5c5.png)

![img](https://img-blog.csdnimg.cn/img_convert/c69d7ec1a6109755bdf9c7145e4ceb60.png)

![img](https://img-blog.csdnimg.cn/img_convert/a5e918a9091173bfeaf5661edc8b2118.png)

![](https://img-blog.csdnimg.cn/img_convert/0e33a904e235d7943dd51fff187cb0e4.png)

 

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618654289)

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**!!


又不知道该从何学起的朋友,同时减轻大家的负担。**

[外链图片转存中...(img-w2htkhOI-1715599859264)]

[外链图片转存中...(img-9wiAZTWA-1715599859265)]

[外链图片转存中...(img-TtuKyRz4-1715599859265)]

 [外链图片转存中...(img-16hM5hOS-1715599859266)]

[外链图片转存中...(img-mNSZVkH5-1715599859266)]

[外链图片转存中...(img-48hblJ3r-1715599859267)]

[外链图片转存中...(img-UHFmkCzv-1715599859267)]

 

**既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!**

[**如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!**](https://bbs.csdn.net/topics/618654289)

**由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新**!!


sht30的基于c51单片机驱动程序:#include #include #include "I2C.h" #include "SHT30.h" #define uint unsigned int #define uchar unsigned char void display(); unsigned char code tableduan[]= { 0x3f,0x06,0x5b,0x4f, 0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c, 0x39,0x5e,0x79,0x71 }; uchar data DIS_ROME[6]= {0,0,0,0,0,0}; //显示缓存区(4) uchar DISP=0;//缓存区指针 uchar SCANF=0xDF;//扫描指针 sbit LED1=P1^0; sbit LED2=P1^1; sbit LED3=P1^2; sbit LED4=P1^3; sbit VOC_A=P3^5; sbit VOC_B=P3^6; sbit dula=P2^6; //IO口定义 sbit wela=P2^7; sbit key=P3^4; sbit beep_dr=P2^3; uint pm1 = 0; uint pm2 = 0; uint pm10 = 0; uchar vr=0; uint intrcnt=0; bit F_1HZ; uint voice_time_cnt; uchar Uart_Buf; uchar Rec_Addr=0; uchar mode=0; uchar Rec_Uart=0; uchar Recive_Buf[30]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; #define key P34 #define const_key_time1 50 unsigned char ucKeySec=0; //被触发的按键编号 unsigned int uiKeyTimeCnt1=0; //按键去抖动延时计数器 unsigned char ucKeyLock1=0; //按键触发后自锁的变量标志 unsigned char displaycnt=0; void keyscan() { if(key==1)//IO是高电平,说明按键没有被按下,这时要及时清零一些标志位 { ucKeyLock1=0; //按键自锁标志清零 uiKeyTimeCnt1=0;//按键去抖动延时计数器清零,此行非常巧妙,是我实战中摸索出来的。 } else if(ucKeyLock1==0)//有按键按下,且是第一次被按下 { uiKeyTimeCnt1++; //累加定时中断次数 if(uiKeyTimeCnt1>const_key_time1) { uiKeyTimeCnt1=0; ucKeyLock1=1; //自锁按键置位,避免一直触发 ucKeySec=1; //触发1号键 } } } void keyservice() { if(ucKeySec) { displaycnt=!displaycnt; } ucKeySec=0; } void UartInit(void) //9600bps@12.000MHz { TMOD=0x01; //设置定时器0为工作方式1 TH0=0xf8; //重装初始值(65535-500)=65035=0xfe0b TL0=0x2f; SCON=0x50; TMOD=0X21; IP =0x10; //把串口中断设置为最高优先级, EA=1; ES=1; ET0=1; TR0=1; } void T0_time(void) interrupt 1 //定时中断 { TF0=0; //清除中断标志 TR0=0; //关中断 keyscan(); keyservice(); display(); if(++intrcnt==1000) { intrcnt=0; } TH0=0xf8; TL0=0x2f; TR0=1; //开中断 } void display() //LED扫描 { if(displaycnt==1) { DIS_ROME[0]=0; DIS_ROME[1]=Hum_num[4]; DIS_ROME[2]=Hum_num[3]; DIS_ROME[3]=Hum_num[2]; DIS_ROME[4]=Hum_num[1]; DIS_ROME[5]=Hum_num[0]; } else { DIS_ROME[0]=0; DIS_ROME[1]=TEMP_num[4]; DIS_ROME[2]=TEMP_num[3]; DIS_ROME[3]=TEMP_num[2]; DIS_ROME[4]=TEMP_num[1]; DIS_ROME[5]=TEMP_num[0]; } wela=1; P0=SCANF; wela=0; dula=1; P0=tableduan[DIS_ROME[DISP]];//数据端口送数据 dula=0; DISP++;//缓存指针加1 SCANF=_cror_(SCANF,1);//扫描切换 if(DISP==7)//缓存指针到尾 { DISP=0;//计数归零 SCANF=0xDF;//扫完四个数码管,扫描复位 } // delay(5); } void main(void) //主函数 { UartInit(); I2C_inita(); while(1) { Getdat_SHT30(); SHT30_DATEChange(); } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值