GXHT30可兼容SHT30的Modbus协议RS485通讯温湿度变送器

GXHT30可兼容SHT30的Modbus协议RS485通讯温湿度变送器

一、文章摘要

二、技术参数

三、通信协议

四、相关测试

五、参考驱动

一、文章摘要

        为解决IIC通信距离短,不可多节点组网使用的缺陷,为满足具有长远距离通信、总线上多节点应用场景需求,本文介绍使用中科银河芯GXHT30C温湿度芯片设计的Modbus协议RS485通讯温湿度变送器。

RS485优点:

● RS485的接口信号与其他接口信号相比降低了,因此不易损坏芯片

● 可以有效减少噪声信号的干扰

● 通信速度快、相对稳定

● 可以延长通信的距离,最大可达2000m

● 总线可实现多节点组网应用

产品应用场景:

● HVAC 环境控制

● 粮情测控

● 智慧农业

● 智能仓储、冷链

● 工业系统

● 物联网等众多温湿度环境监测领域

二、技术参数

2.1产品功能特点

● RS485 通信接口,标准 ModBus-RTU 协议,通信线最长可达 2000 米;

● CMOS + MEMS 集成工艺,保证产品性能、可长期稳定工作;

● 温度精度±0.5℃ 、湿度精度±3%RH,高精度、低漂移;

● 5-24V 宽电压范围供电,远距离集中供电仍能正常工作;

● 产品应用简单、可无需任何外围电路器件;

● 电源防接反保护功能,正负极接反不会烧坏设备;

● 灵敏度高、反应迅速,防水、防腐蚀,高可靠性。

2.2产品功能特点

2.3产品外观形态

三、通信协议

3.1基本通信参数

3.2数据帧格式及定义 

3.3通讯示例说明 

 四、相关测试

4.1 ESD测试

      GXHT30C温湿度变送器经过ESD测试,空气放电 ±12kV、接触式放电 ±8kV。

4.2 通讯测试

        常温环境进行数据收发挂测,实测15万+ 条数据收发测试 0 掉包。

4.3 一致性测试 

        以下为高湿环境,进行数据一致性测试,测试截图如下。

4.4  成品展示

五、GXHT30C温湿度芯片驱动 

5.1 GXHT30C.c
#include "GXHT30.h"
#include "stdlib.h"

#define write 0
#define read  1

uint16_t temp_buff[2] = {0};
uint16_t hum_buff[2] = {0};

void sys_delay_us(uint16_t time)
{
	for(int i = 0; i < time; i++);
}

void GXHT30Reset(void);


//初始化IIC
void GXHT30_IIC_Init(void)
{					     
	GPIO_InitTypeDef GPIO_InitStruct;
	GXHT30_I2C_SCL_GPIO_RCC;
	GXHT30_I2C_SDA_GPIO_RCC;//使能GPIO时钟

	GPIO_InitStruct.Pin = GXHT30_I2C_SCL_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GXHT30_I2C_SCL_GPIO_PORT, &GPIO_InitStruct);
	
	GPIO_InitStruct.Pin = GXHT30_I2C_SDA_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GXHT30_I2C_SDA_GPIO_PORT, &GPIO_InitStruct);
		
	GXHT30_SDA_H;
	GXHT30_SCL_H;
		
	HAL_Delay(10);	//延时一会等待初始化稳定
	GXHT30Reset();	//复位芯片
}


static void GXHT30_SDA_OUT(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	GXHT30_I2C_SDA_GPIO_RCC;	//使能GPIO时钟
	GPIO_InitStruct.Pin = GXHT30_I2C_SDA_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;	
    HAL_GPIO_Init(GXHT30_I2C_SDA_GPIO_PORT, &GPIO_InitStruct);
}

static void GXHT30_SDA_IN(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	GXHT30_I2C_SDA_GPIO_RCC;	//使能GPIO时钟
	GPIO_InitStruct.Pin = GXHT30_I2C_SDA_PIN;
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;	
    HAL_GPIO_Init(GXHT30_I2C_SDA_GPIO_PORT, &GPIO_InitStruct);
}

//产生IIC起始信号
static void GXHT30_IIC_Start(void)
{
	GXHT30_SDA_OUT();     //sda线输出
	GXHT30_SDA_H;	  	  
	GXHT30_SCL_H;
	GXHT30_Delay_us(4);
 	GXHT30_SDA_L;//START:when CLK is high,DATA change form high to low 
	GXHT30_Delay_us(4);
	GXHT30_SCL_L;//钳住I2C总线,准备发送或接收数据 
}	 

//产生IIC停止信号
static void GXHT30_IIC_Stop(void)
{
	GXHT30_SDA_OUT();//sda线输出
	GXHT30_SCL_L;
	GXHT30_SDA_L;//STOP:when CLK is high DATA change form low to high
 	GXHT30_Delay_us(4);
	GXHT30_SCL_H; 
	GXHT30_SDA_H;//发送I2C总线结束信号
	GXHT30_Delay_us(4);							   	
}

//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
static uint8_t GXHT30_IIC_Wait_Ack(void)
{
	uint8_t ucErrTime=0;
	GXHT30_SDA_IN();      //SDA设置为输入  
	GXHT30_SDA_H;
	GXHT30_Delay_us(1);	   
	GXHT30_SCL_H;
	GXHT30_Delay_us(1);	 
	while(GXHT30_READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			GXHT30_IIC_Stop();
			return 1;
		}
	}
	GXHT30_SCL_L;//时钟输出0 	   
	return 0;  
} 

//产生ACK应答
static void GXHT30_IIC_Ack(void)
{
	GXHT30_SCL_L;
	GXHT30_SDA_OUT();
	GXHT30_SDA_L;
	GXHT30_Delay_us(2);
	GXHT30_SCL_H;
	GXHT30_Delay_us(2);
	GXHT30_SCL_L;
}

//不产生ACK应答		    
static void GXHT30_IIC_NAck(void)
{
	GXHT30_SCL_L;
	GXHT30_SDA_OUT();
	GXHT30_SDA_H;
	GXHT30_Delay_us(2);
	GXHT30_SCL_H;
	GXHT30_Delay_us(2);
	GXHT30_SCL_L;
}	

//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答			  
static void GXHT30_IIC_Send_Byte(uint8_t txd)
{                        
    uint8_t t;   
		GXHT30_SDA_OUT(); 	    
    GXHT30_SCL_L;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
			if((txd&0x80)>>7)
				GXHT30_SDA_H;
			else
				GXHT30_SDA_L;
			txd<<=1; 	  
			GXHT30_Delay_us(2);   
			GXHT30_SCL_H;
			GXHT30_Delay_us(2); 
			GXHT30_SCL_L;	
			GXHT30_Delay_us(2);
    }	 
} 

//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
static uint8_t GXHT30_IIC_Read_Byte(unsigned char ack)
{
		unsigned char i,receive=0;
		GXHT30_SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
		{
        GXHT30_SCL_L; 
        GXHT30_Delay_us(2);
				GXHT30_SCL_H;
        receive<<=1;
        if(GXHT30_READ_SDA)receive++;   
				GXHT30_Delay_us(1); 
    }					 
    if (!ack)
        GXHT30_IIC_NAck();//发送nACK
    else
        GXHT30_IIC_Ack(); //发送ACK   
    return receive;
}

/**
brief 检查GXHT30是否存在
param NONE
return 0存在  1不存在
*/
uint8_t GXHT30Check(void)
{
	uint8_t ack=0;
	GXHT30_IIC_Start();
	GXHT30_IIC_Send_Byte(GXHT30_ADDRESS);
	ack=GXHT30_IIC_Wait_Ack();
	GXHT30_IIC_Stop();	
	return ack;
}


/**
brief GXHT30软复位
param NONE
return NONE
*/
void GXHT30Reset(void)
{
	GXHT30_IIC_Start();
	GXHT30_IIC_Send_Byte(GXHT30_ADDRESS << 1 |  write);
	GXHT30_IIC_Wait_Ack();
	GXHT30_IIC_Send_Byte(0x30);
	GXHT30_IIC_Wait_Ack();
	GXHT30_IIC_Send_Byte(0xA2);
	GXHT30_IIC_Wait_Ack();
	GXHT30_IIC_Stop();	
}


uint8_t GXHT30_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;
}


/**
brief 检查GXHT30读温湿度数据
param *temperature:需要读出的温度数据,uint16_t指针类型,精度范围+-0.3C
param *humidity:需要读出的湿度数据,uint16_t指针类型,精度范围+-2RH
return 1 读数据正常 0读数据失败
*/
float temperature_data;
float humidity_data;

uint8_t Read_GXHT30_Data(void)
{
	uint16_t SRH=0,ST=0;
	uint8_t databuff[6];
		
	GXHT30_IIC_Start();
	GXHT30_IIC_Send_Byte(GXHT30_ADDRESS << 1 | write);
	GXHT30_IIC_Wait_Ack();
	GXHT30_IIC_Send_Byte(0x2C);
	GXHT30_IIC_Wait_Ack();
	GXHT30_IIC_Send_Byte(0x06);
	GXHT30_IIC_Wait_Ack();
	GXHT30_IIC_Stop();	
  
	HAL_Delay(20);//延时一会等待数据读出
	
	GXHT30_IIC_Start();
	GXHT30_IIC_Send_Byte(GXHT30_ADDRESS << 1 | read);	
	
	if(GXHT30_IIC_Wait_Ack() ==0)
	{
		databuff[0]=GXHT30_IIC_Read_Byte(1);
		databuff[1]=GXHT30_IIC_Read_Byte(1);
		databuff[2]=GXHT30_IIC_Read_Byte(1);
		databuff[3]=GXHT30_IIC_Read_Byte(1);
		databuff[4]=GXHT30_IIC_Read_Byte(1);
		databuff[5]=GXHT30_IIC_Read_Byte(0);
		GXHT30_IIC_Stop();
		
		if(GXHT30_CRC_8(databuff, 2) == databuff[2] && GXHT30_CRC_8(databuff + 3, 2) == databuff[5])
		{			
			/* 转换温度数据 */
			ST = (uint16_t)((0x0000|databuff[0])<<8|databuff[1]);
			temperature_data = (-45 + 175*((float)ST/65535))*10;
			
			/* 转换湿度数据 */
			SRH = (uint16_t)((0x0000|databuff[3])<<8|databuff[4]);
			humidity_data = 10 * (100 * ((float)SRH / 65535));		
			
		
			temp_buff[0] = ((uint16_t)(temperature_data)&0xff00)>>8;	//将温度高八位存到temp_buff[0]
			temp_buff[1] = ((uint16_t)(temperature_data))&0x00ff;			//将温度低八位存到temp_buff[1]
			
			hum_buff[0] = ((uint16_t)(humidity_data)&0xff00)>>8;//将湿度高八位存到hum_buf[0]
			hum_buff[1] = ((uint16_t)(humidity_data))&0xff;//将湿度高八位存到hum_buf[1]		
		}		
		return 1;
	}
	
	return 0;
}
 5.2 GXHT30C.h
#ifndef _GXHT30_H__
#define _GXHT30_H__
#include "stm32f0xx.h"
#include "delay.h"

extern uint16_t temp_buff[2];
extern uint16_t hum_buff[2];

void sys_delay_us(uint16_t time);


#define GXHT30_Delay_us(time)								sys_delay_us(time)
#define GXHT30_Delay_ms(time)								delay_ms(time)


#define GXHT30_ADDRESS 0x44

#define GXHT30_I2C_SCL_PIN      					 		GPIO_PIN_9
#define GXHT30_I2C_SCL_GPIO_PORT   	       		            GPIOA 
#define GXHT30_I2C_SCL_GPIO_RCC      			  __HAL_RCC_GPIOA_CLK_ENABLE()  
 
#define GXHT30_I2C_SDA_PIN      					 		GPIO_PIN_10   
#define GXHT30_I2C_SDA_GPIO_PORT   	       		            GPIOA 
#define GXHT30_I2C_SDA_GPIO_RCC      			  __HAL_RCC_GPIOA_CLK_ENABLE()  

/* Private define ------------------------------------------------------------*/
#define GXHT30_SCL_H         HAL_GPIO_WritePin(GXHT30_I2C_SCL_GPIO_PORT, GXHT30_I2C_SCL_PIN, GPIO_PIN_SET)   
#define GXHT30_SCL_L         HAL_GPIO_WritePin(GXHT30_I2C_SCL_GPIO_PORT, GXHT30_I2C_SCL_PIN, GPIO_PIN_RESET)
   
#define GXHT30_SDA_H         HAL_GPIO_WritePin(GXHT30_I2C_SDA_GPIO_PORT, GXHT30_I2C_SDA_PIN, GPIO_PIN_SET)
#define GXHT30_SDA_L         HAL_GPIO_WritePin(GXHT30_I2C_SDA_GPIO_PORT, GXHT30_I2C_SDA_PIN, GPIO_PIN_RESET)
#define GXHT30_READ_SDA      HAL_GPIO_ReadPin(GXHT30_I2C_SDA_GPIO_PORT,GXHT30_I2C_SDA_PIN)


/*****************函数声明,对外接口******************/
void GXHT30_IIC_Init(void);
void GXHT30Reset(void);

extern uint8_t Read_GXHT30_Data(void);

#endif

友谊提示:

欢迎咨询交流GXHT30C、RS485通信温湿度变送器,联系如下:
TEL : 13128272535 
  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值