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

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温湿度芯片驱动实例**


###### **C51**GXHT30.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


######   **C51**GXHT30.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();
SCL = 1;
delay_5us();
SDA = 0;
delay_5us();
SCL = 0;
delay_5us();
}

///I2C总线停止函数******/
void I2C_Stop(void)
{
SDA = 0;
SCL = 0;
delay_5us();
SCL = 1;
delay_5us();
SDA = 1;
delay_5us();
}

///================================================================
//【名 称】unsigned char I2CWRByte(unsigned char WRByte)
//【功 能】I2C写一个字节数据,返回ACK或者NACK
//【备 注】从高到低,依次发送
//================================================================
/
etError I2CWRByte(unsigned char WRByte)
{
unsigned char i;
P3CR = 0xFF; //设置SDA输出
SCL = 0;
for(i=0;i<8;i++)
{
if(WRByte&0x80)
{
SDA = 1;
}
else
{
SDA = 0;
}
delay_5us();
SCL=1; //输出SDA稳定后,拉高SCL给出上升沿,从机检测到后进行数据采样
delay_5us();
SCL=0;

最后

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

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

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

img

img

img

img

img

img

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

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

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

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

[外链图片转存中…(img-Sh4AO2YT-1715599824467)]

[外链图片转存中…(img-c2T0JZbz-1715599824468)]

[外链图片转存中…(img-svAhGaBt-1715599824468)]

[外链图片转存中…(img-Jb25Dp2Z-1715599824469)]

[外链图片转存中…(img-iEDWZYvE-1715599824470)]

[外链图片转存中…(img-3cF1QRlf-1715599824470)]

[外链图片转存中…(img-uFXBezra-1715599824471)]

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

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

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

  • 11
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值