合泰杯(HT32F52352)IIC读取SHT3X类温湿度传感器

目录

SHT30介绍

IIC协议

IIC.c

IIC.h

SHT30驱动

SHT30.c

SHT30.h

主函数

main.c

演示


SHT30介绍

        最近在做项目,在选材的时候要求一种传感器能够测量水温,传统的DHT11,DS18B20等一些可以检测的传感器做不到防水问题,在不断地挑选下,选择了这款性价比较低,且能防水的传感器SHT3X,下面看看它的介绍。

这款传感器淘宝卖10几块,性能方面不用说了,温度,湿度方面基本满足大多项目要求,下面来注入灵魂。首先是IIC协议,如果说是stm32f1x系列网上一整套资源写好,但是我用HT32移植stm32写的时候遇到问题挺多的,你们可以看看和stm32的有什么区别。

IIC协议

IIC.c

#include "iic.h"
#include "delay.h"
#include "usart.h"



//开启时钟
static void I2C_CKCU_Config()
{
	CKCU_PeripClockConfig_TypeDef CCLOCK;
	
	CCLOCK.Bit.PA     = 1;
	CCLOCK.Bit.AFIO  = 1;
	
	CKCU_PeripClockConfig(CCLOCK, ENABLE);
}

//引脚配置
static void I2C_GPIO_Config()
{
	AFIO_GPxConfig(I2C_SCL_GPIO_ID, I2C_SCL_PIN, I2C_SCL_AFIO_MODE);
	AFIO_GPxConfig(I2C_SDA_GPIO_ID, I2C_SDA_PIN, I2C_SDA_AFIO_MODE);
	
	/* Configure the GPIO pin                                                                                 */
	GPIO_PullResistorConfig(I2C_SCL_PORT, I2C_SCL_PIN, GPIO_PR_DISABLE);
	GPIO_DriveConfig(I2C_SCL_PORT, I2C_SCL_PIN, GPIO_DV_8MA);
	GPIO_DirectionConfig(I2C_SCL_PORT, I2C_SCL_PIN, GPIO_DIR_OUT);
	
	GPIO_PullResistorConfig(I2C_SDA_PORT, I2C_SDA_PIN, GPIO_PR_DISABLE);
	GPIO_DriveConfig(I2C_SDA_PORT, I2C_SDA_PIN, GPIO_DV_8MA);
	GPIO_DirectionConfig(I2C_SDA_PORT, I2C_SDA_PIN, GPIO_DIR_OUT);
}
//初始化 
void I2C_Initia()
{
	I2C_CKCU_Config();
	I2C_GPIO_Config();
	
	/* 一定要先发一遍停止信号 */
	I2C_Stop();
}

//I2C起始信号
void I2C_Start()
{
	
	I2C_SDA_InputConfig();
	I2C_SDA_Direction_Output(); //sda线输出
	I2C_SDA_1();
	I2C_SCL_1();
	
	delay_us(4);
	
	I2C_SDA_0();
	delay_us(4);
	
	I2C_SCL_0();  //钳住I2C总线,准备发送或接收数据 
}

//产生IIC停止信号
void I2C_Stop()
{
	I2C_SDA_Direction_Output(); //sda线输出
	I2C_SCL_0();
	I2C_SDA_0();
	delay_us(4);
	I2C_SCL_1();
	I2C_SDA_1();  //发送I2C总线结束信号
	delay_us(4);
}

/* 返回0表示正确应答,1表示无器件响应 */
u8 I2C_WaitAck()
{
	u8 ucErrTime = 0;
	I2C_SDA_Direction_Input();  //SDA设置为输入 
	I2C_SDA_1();
	delay_us(2);
	I2C_SCL_1();
	delay_us(2);
//	I2C_SDA_Direction_Input();
//	I2C_SDA_InputConfig();
	
//	if( I2C_SDA_READ() ) {
//		ack = 1;
//	}
//	else {
//		ack = 0;
//	}
		while( I2C_SDA_READ() )
		{
			ucErrTime ++;
			if(ucErrTime > 250)
			{
				I2C_Stop();
				return 1;
			}
		}

	I2C_SCL_0();
	return 0;
}

产生ACK应答
// void I2C_Ack()
//{
//	I2C_SDA_0();	/* CPU驱动SDA = 0 */
//	delay_us(DELAYTIME);
//	
//	I2C_SCL_1();	/* CPU产生1个时钟 */
//	delay_us(DELAYTIME);
//	
//	I2C_SCL_0();
//	delay_us(DELAYTIME);
//	I2C_SDA_1();	/* CPU释放SDA总线 */
//}
//产生ACK应答
 void I2C_Ack()
{
	I2C_SCL_0();
	I2C_SDA_Direction_Output();
	I2C_SDA_0();	/* CPU驱动SDA = 1 */
	delay_us(2);
	
	I2C_SCL_1();	/* CPU产生1个时钟 */
	delay_us(2);
	
	I2C_SCL_0();
	
//	delay_us(2);
//	I2C_SDA_1();	/* CPU释放SDA总线 */
}

//不产生ACK应答	
void I2C_NAck()
{
//	I2C_SDA_1();	/* CPU驱动SDA = 1 */
//	delay_us(DELAYTIME);
//	
//	I2C_SCL_1();	/* CPU产生1个时钟 */
//	delay_us(DELAYTIME);
//	
//	I2C_SCL_0();
//	delay_us(DELAYTIME);
		I2C_SCL_0();
	I2C_SDA_Direction_Output();
	I2C_SDA_1();	/* CPU驱动SDA = 1 */
	delay_us(2);
	
	I2C_SCL_1();	/* CPU产生1个时钟 */
	delay_us(2);
	
	I2C_SCL_0();
}
void I2C_SendByte(u8 txd)
{
	u8 i;
	I2C_SDA_Direction_Output();
	I2C_SCL_0();//拉低时钟开始数据传输
	/* 先发送字节的高位bit7 */
	for (i = 0; i < 8; i++)
	{		
		if ((txd & 0x80)>>7)
			I2C_SDA_1();
		else
			I2C_SDA_0();
			txd<<=1;
		
		delay_us(2);
		I2C_SCL_1();
		delay_us(2);
		I2C_SCL_0();
		delay_us(2);
		
//		if (i == 7)
//		{
//			 I2C_SDA_1(); // 释放总线
//		}
//		_ucByte <<= 1;	/* 左移一个bit */
//		delay_us(DELAYTIME);
	}
}

u8 I2C_ReadByte(unsigned char ack)
{
	u8 i,receive=0;
	I2C_SDA_Direction_Input();
	
	for(i = 0;i < 8;i++)
	{
//		data <<= 1;
		I2C_SCL_0();
		delay_us(2);
		I2C_SCL_1();
//		I2C_SDA_Direction_Input();
		receive <<= 1;
		
		if( I2C_SDA_READ() ) 
			receive++;
			delay_us(1);
		}
		//I2C_SCL_0();
			
	    if (!ack)
        I2C_NAck();//发送nACK
    else
        I2C_Ack(); //发送ACK  
	return receive;
}
 

 

IIC.h

#ifndef _IIC_H
#define _IIC_H
 
#include "ht32f5xxxx_01.h"
 
/* 定义I2C的SCL连接的GPIO端口 */
#define I2C_SCL_GPIO_ID					GPIO_PA					/* GPIO端口 */
#define I2C_SCL_PIN						GPIO_PIN_0				/* 连接到SCL时钟线的GPIO */
#define I2C_SCL_AFIO_MODE				AFIO_FUN_GPIO
#define I2C_SCL_PORT					HT_GPIOA
 
/* 定义I2C的SDA连接的GPIO端口 */
#define I2C_SDA_GPIO_ID					GPIO_PA					/* GPIO端口 */
#define I2C_SDA_PIN						GPIO_PIN_1				/* 连接到SCL时钟线的GPIO */
#define I2C_SDA_AFIO_MODE				AFIO_FUN_GPIO
#define I2C_SDA_PORT					HT_GPIOA
//IO操作函数 
#define I2C_SCL_1()						GPIO_SetOutBits(I2C_SCL_PORT, I2C_SCL_PIN)  // 高电平
#define I2C_SCL_0()						GPIO_ClearOutBits(I2C_SCL_PORT, I2C_SCL_PIN) //低电平	
#define I2C_SDA_1()						GPIO_SetOutBits(I2C_SDA_PORT, I2C_SDA_PIN)
#define I2C_SDA_0()						GPIO_ClearOutBits(I2C_SDA_PORT, I2C_SDA_PIN)
#define I2C_SDA_READ()					GPIO_ReadInBit(I2C_SDA_PORT, I2C_SDA_PIN) //输入SDA

//IO方向设置
#define I2C_SDA_Direction_Input()		GPIO_DirectionConfig(I2C_SDA_PORT, I2C_SDA_PIN, GPIO_DIR_IN)
#define I2C_SDA_Direction_Output()		GPIO_DirectionConfig(I2C_SDA_PORT, I2C_SDA_PIN, GPIO_DIR_OUT) //SDA线输出

#define I2C_SDA_InputConfig()			GPIO_InputConfig(I2C_SDA_PORT, I2C_SDA_PIN, ENABLE) //使能输入输出
#define I2C_SDA_InputDisable()			GPIO_InputConfig(I2C_SDA_PORT, I2C_SDA_PIN, DISABLE)

 
 
void I2C_Initia(void);
void I2C_Start(void);
void I2C_Stop(void);
u8 I2C_WaitAck(void);
void I2C_SendByte(u8 _ucByte);
u8 I2C_ReadByte(unsigned char ack);
void I2C_Ack(void);
void I2C_NAck(void);
 

#endif

总的来说,HT32的库还是比较丰富的,至少比stm32库函数多。当然,我这里没有写出IIC时序图,感兴趣的朋友可以去网上搜索自己理解。接下来是驱动SHT30传感器,主要是去淘宝官方拿的代码,然后自己封装一下就行啦。

SHT30驱动

SHT30.c

#include "IIC.h"
#include "sht30.h"
#include "delay.h"
#include "usart.h"
#include "ht32f5xxxx_01.h"              // Device header


//*********************************************************************************
//SHT30驱动
//淘宝店铺:https://shop296378919.taobao.com/
//修改日期:2018/6/25
//版本:V1.0
//版权所有,盗版必究。
//All rights reserved
//*********************************************************************************
extern int temp1;
extern u16 humi;

#define POLYNOMIAL_CXDZ 0x31 // X^8 + X^5 + X^4 + 1
//SHT3X CRC校验
unsigned char SHT3X_CRC(u8 *data, u8 len)
{
	unsigned char bit;        // bit mask
	unsigned char crc = 0xFF; // calculated checksum
	unsigned char byteCtr;    // byte counter

	// calculates 8-Bit checksum with given polynomial @GZCXDZ
	for(byteCtr = 0; byteCtr < len; byteCtr++) {
			crc ^= (data[byteCtr]);
//		printf("1");
			for(bit = 8; bit > 0; --bit) {
					if(crc & 0x80) {
						//printf("2");
							crc = (crc << 1) ^ POLYNOMIAL_CXDZ;
					}  else {
						//printf("1");
							crc = (crc << 1);
					}
			}
	}
  return crc;
}

//SHT30命令函数
void SHT30_CMD(u16 cmd)
{
	I2C_Start();
  I2C_SendByte(SHT30_ADDR+0);  //发送设备地址,写寄存器
	I2C_WaitAck();
	I2C_SendByte((cmd>>8)&0xff); //MSB
	I2C_WaitAck();
	I2C_SendByte(cmd&0xff); //LSB
	I2C_WaitAck();
	I2C_Stop();
	//printf("1");
	delay_ms(50);//命令发完后需要等待20ms以上才能读写
}



//SHT30读取温湿度
//temp:温度,-400~1250,实际温度=temp/10,分辨率0.1℃,精度±0.3℃
//humi:湿度,0~1000,实际湿度=humi/10,分辨率0.1%rh,精度±3
//返回0成功,1失败
u8 SHT30_Read_Humiture(int *temp,u16 *humi)
{
	u8 buff[6];
	
	SHT30_CMD(SHT30_READ_HUMITURE);//读温湿度命令
	
	I2C_Start();
	I2C_SendByte(SHT30_ADDR+1); //发送设备地址,读寄存器
	I2C_WaitAck();
	buff[0]=I2C_ReadByte(1);//继续读,给应答
	buff[1]=I2C_ReadByte(1);//继续读,给应答
	buff[2]=I2C_ReadByte(1);//继续读,给应答
	buff[3]=I2C_ReadByte(1);//继续读,给应答
	buff[4]=I2C_ReadByte(1);//继续读,给应答
	buff[5]=I2C_ReadByte(0);//不继续给停止应答
	I2C_Stop();
	
	//printf("buff=%d,%d,%d,%d,%d,%d\r\n",buff[0],buff[1],buff[2],buff[3],buff[4],buff[5]);
	//CRC校验
	if(SHT3X_CRC(&buff[0],2)==buff[2] && SHT3X_CRC(&buff[3],2)==buff[5])
	{
		//printf("1");
		*temp=(-45+(175.0*((buff[0]<<8)+buff[1])/65535.0));
		*humi=100*((buff[3]<<8)+buff[4])/65535.0;
		
		
		if(*humi>100) *humi=100;
		else if(*humi<0) *humi=-0;
		
		if(*temp>125) *temp=125;
		else if(*temp<-40) *temp=-40;
		return 0;
		//printf("temp1=%d\n",temp);
	}
	else return 1;
	
}

//SHT30初始化
void SHT30_Init()
{
	I2C_Initia();
}


SHT30.h

#ifndef __SHT30_H
#define __SHT30_H 




#define SHT30_ADDR (u8)(0x44<<1) //sht30 i2c地址,ADDR管脚接低电平时为0x44,接高电平为0x45

//SHT30命令
#define SHT30_READ_HUMITURE (u16)0x2c06  //读温湿度

//CRC多项式
#define POLYNOMIAL 0x31 // X^8 + X^5 + X^4 + 1

u8 SHT30_Read_Humiture(int *temp,u16 *humi);
void SHT30_Init(void);

#endif


这部分代码就是对读取到的数据进行读取、校验,然后对数据进行处理。

主函数

main.c

#include "ht32.h"
#include "ht32_board.h"
#include "led.h"
#include "delay.h"
#include "USART.h"
#include "IIC.h"
#include "SHT30.h"
//#include "Timer.h"


int temp1;
u16 humi;

volatile u32 milliseconds = 0;
volatile u32 seconds = 0;
u8 led_flag,light_in;



//往小程序发送数据
void Send_Data(void)
	{
		printf("{\"light\":\"%d\",\n	\"led\":\"%d\",\n}",light_in,led_flag);		
	}
	

int main()
{
		//LED_Init();	
		SHT30_Init();
	I2C_Initia();
		//BFTM0_Configuration();
		USART_Configuration();
		//Send_Data();
	
	while(1)
	{
		SHT30_Read_Humiture(&temp1,&humi);//获取温湿度
		printf("temp1=%2d℃\r\n",temp1);	
		printf("humi=%2d%\r\n",humi);
		delay_ms(1000);
		
	}
	
}

演示

  • 16
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值