调试SHT30温湿度传感器模块,外码工程使用

调试SHT30代码,工程使用

本文主要目标是学习IIC协议及传感器模块,旨在传到STM32单片机优化代码,亲测可用

一、环境搭建,

1、野火开发板
2、JLINK下载器(腾创电子家的,不得不说这个下载器是真的好用,店主推荐购买企业版就买了,把链接发出来,方便大家,JLINK店家地址

二、首先搭建好iic驱动代码
三、编辑好SHT30初始化代码
四、写好SHT30读写温湿度代码

SHT30读取温度值有两种模式,1、状态查询模式2、数值查询模式,本文采用数值查询模式
iic.h

#define	EEPROM_I2C_WR  0	/* 写控制bit */
#define	EEPROM_I2C_RD  1	/* 读控制bit */

/* 定义IIC总线连接GPIO端口,用户只需要修改下面4行代码即可任意改变SCL和SDA的引脚 */
#define	EEPROM_GPIO_PORT		GPIOB					/* GPIO端口 */
#define	EEPROM_RCC_PORT			RCC_APB2Periph_GPIOB	/* GPIO端口时钟 */
#define EEPROM_I2C_SCL_PIN		GPIO_Pin_6				/* 连接SCL时钟线引脚 */
#define EEPROM_I2C_SDA_PIN		GPIO_Pin_7				/* 连接SDA时钟线引脚 */


/* 定义读写SCL和SDA的宏,已增加的代码可移植性和可阅读性 */
#if 0 /*条件编译  1选择GPIO的库函数实现IO读写 */
#define EEPROM_I2C_SCL_1()		GPIO_SetBits(EEPROM_GPIO_PORT,EEPROM_I2C_SCL_PIN)
#define EEPROM_I2C_SCL_0()		GPIO_ResetBits(EEPROM_GPIO_PORT,EEPROM_I2C_SCL_PIN)

#define EEPROM_I2C_SDA_1()		GPIO_SetBits(EEPROM_GPIO_PORT,EEPROM_I2C_SDA_PIN)
#define EEPROM_I2C_SDA_0()		GPIO_ResetBits(EEPROM_GPIO_PORT,EEPROM_I2C_SDA_PIN)

#define EEPROM_I2C_SDA_READ()	GPIO_ReadInputDataBit(EEPROM_GPIO_PORT,EEPROM_I2C_SDA_PIN)

#else 	/* 这个分支选择直接寄存器实现IO读写 */
		/* 注意:如下写法:在IAR最高级优化时,会被编译器错误优化 */
#define EEPROM_I2C_SCL_1()		GPIO_SetBits(EEPROM_GPIO_PORT,EEPROM_I2C_SCL_PIN)
#define EEPROM_I2C_SCL_0()		GPIO_ResetBits(EEPROM_GPIO_PORT,EEPROM_I2C_SCL_PIN)

#define EEPROM_I2C_SDA_1()		GPIO_SetBits(EEPROM_GPIO_PORT,EEPROM_I2C_SDA_PIN)
#define EEPROM_I2C_SDA_0()		GPIO_ResetBits(EEPROM_GPIO_PORT,EEPROM_I2C_SDA_PIN)

#define EEPROM_I2C_SDA_READ()	((EEPROM_GPIO_PORT->IDR & EEPROM_I2C_SDA_PIN) != 0)


#endif

iic.c


```c
static void i2c_cfGpio(void);
static void i2c_Delay(void);

/* 
	下面的时间是通过逻辑分析仪测试得到的
	工作条件:CPU:72MHz,MDK编译环境,1级优化
	循环次数为10时,SCL频率 = 205khz
	循环次数为7时, SCL频率 = 347khz  SCL高电平时间1.5us,SCL低电平时间2.87us
	循环次数为5时, SCL频率 = 421khz,SCL高电平时间1.2us,SCL低电平时间2.37us
*/
static void i2c_Delay(void){
	uint8_t i;
	for(i=0; i<10; i++);
}


 /**
  * @brief  CPU发起I2C总线启动信号
  * @param  无
  * @retval 无
  */
void i2c_Start(void){
	
	/*  当SCL高电平时,SDA出现一个下跳沿表示I2C总线启动信号 */
	EEPROM_I2C_SDA_1();
	EEPROM_I2C_SCL_1();
	
	i2c_Delay();
	EEPROM_I2C_SDA_0();
	i2c_Delay();
	EEPROM_I2C_SCL_0();
	i2c_Delay();
}

 /**
  * @brief  CPU发起I2C总线停止信号
  * @param  无
  * @retval 无
  */
void i2c_Stop(void){
	
	/*  当SCL高电平时,SDA出现一个下跳沿表示I2C总线停止信号 */
	EEPROM_I2C_SDA_0();
	EEPROM_I2C_SCL_1();
	
	i2c_Delay();
	EEPROM_I2C_SDA_1();
}


 /**
  * @brief  CPU向I2C总线设备发送8bit数据
  * @param  ucByte -[in]等待发送的字节
  * @retval 无
  */
void i2c_SendByte(uint8_t _ucByte){
	
	uint8_t i;
	/* 先发送字节的高bit7 */
	for(i=0; i<8; i++){
		if(_ucByte & 0x80){
			EEPROM_I2C_SDA_1();
		}
		else{
			EEPROM_I2C_SDA_0();
		}
		i2c_Delay();
		EEPROM_I2C_SCL_1();
		i2c_Delay();
		EEPROM_I2C_SCL_0();
		
		if(i==7){
			EEPROM_I2C_SDA_1();
		}
		_ucByte <<= 1;	/* 左移一个bit */
		i2c_Delay();
	
	}
}

 /**
  * @brief  CPU从I2C总线设备 读取 8bit数据
  * @param  无
  * @retval 读到的数据
  */
uint8_t i2c_ReadByte(void){
	
	uint8_t i;
	uint8_t value;
	value = 0;
	/* 读取第1个bit为数据的bit7 */
	for(i=0; i<8; i++){
		
//		EEPROM_I2C_SCL_0();
//		Delay_us(5);
//		EEPROM_I2C_SCL_1();
		value <<= 1;
		EEPROM_I2C_SCL_1();
		i2c_Delay();
		if(EEPROM_I2C_SDA_READ()){
			value++;
		}
		EEPROM_I2C_SCL_0();
		i2c_Delay();
	}		
	return value;
}

/**
  * @brief  CPU产生一个时钟,并读取器件的ack应答信号
  * @param  无
  * @retval 返回0表示正确应答,1表示无器件响应
  */
uint8_t i2c_WaitAck(void){
	uint8_t re;
	
	EEPROM_I2C_SDA_1();		/* 释放SDA总线 */
	i2c_Delay();
	EEPROM_I2C_SCL_1();		/* CPU驱动SCL = 1,此时器件会返回ack应答 */
	i2c_Delay();
	
	if(EEPROM_I2C_SDA_READ()){		/* CPU读取SDA口线状态*/
		re = 1;
	}else{
		re = 0;
	}
	
	EEPROM_I2C_SCL_0();
	i2c_Delay();      
	
	return re;
}

/**
  * @brief  CPU产生ack应答信号
  * @param  无
  * @retval 无
  */
void i2c_Ack(void){
	
	EEPROM_I2C_SDA_0();		/* CPU驱动 SDA = 0*/
	i2c_Delay();
	EEPROM_I2C_SCL_1();		/* CPU产生一个时钟*/
	i2c_Delay();
	EEPROM_I2C_SCL_0();		
	i2c_Delay();
	EEPROM_I2C_SDA_1();		/* CPU释放SDA总线*/
}

/**
  * @brief  CPU产生1个nack应答信号
  * @param  无
  * @retval 无
  */
void i2c_NAck(void){
	
	EEPROM_I2C_SDA_1();
	i2c_Delay();
	EEPROM_I2C_SCL_1();
	i2c_Delay();
	EEPROM_I2C_SCL_0();
	i2c_Delay();
}

/**
  * @funct  local function 
  * @brief  配置I2C总线GPIO,采用模拟IO的方式实现
  * @param  无
  * @retval 0无
  */

void i2c_cfGpio(void){
	
	GPIO_InitTypeDef	GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	
	GPIO_InitStructure.GPIO_Mode 	= GPIO_Mode_Out_OD;		/* 开漏输出 */
	GPIO_InitStructure.GPIO_Speed 	= GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin 	= EEPROM_I2C_SCL_PIN | EEPROM_I2C_SDA_PIN;
	GPIO_Init(EEPROM_GPIO_PORT,&GPIO_InitStructure);
	
	/* 给一个停止信号,复位I2C总线上所有设备待机模式 */
	i2c_Stop();
}

/**
  * @brief  检测I2C总线设备,CPU向设备发送地址,然后读取该设备应答来判断该设备是否存在
  * @param  _Address -[in]设备的I2C总线地址
  * @retval 0表示正确,返回1表示未探测到 
  */
uint8_t i2c_CheakDevice(uint8_t _Address){
	
	uint8_t ucAck;
	i2c_cfGpio();	/* 配置GPIO端口 */
	
	i2c_Start();
	
	/* 发送该设备地址+读写控制bit (0 = w,1 = r)bit7先传 */
	i2c_SendByte(_Address | EEPROM_I2C_WR);
	ucAck = i2c_WaitAck();	/* 检测设备的ack应答信号 */
	
	i2c_Stop();
	
	return ucAck;
}

/**
  * @brief  检测I2C总线设备,CPU向设备发送地址,然后读取该设备应答来判断该设备是否存在
  * @param  _Address -[in]设备的I2C总线地址
  * @retval 0表示正确,返回1表示未探测到 
  */
void Check(uint8_t _Address){
	i2c_cfGpio();
}



sht30.c
 

```c
#include "./sht30/bsp_sht30.h"   
#include "./iic/bsp_iic.h" 
#include "./systick/bsp_systick.h" 
#include "bsp_usart.h"

float humiture[4];
uint8_t  humiture_buff1[20];


void SHT30_Init(void){
	GPIO_InitTypeDef	GPIO_InitStructure;

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	GPIO_InitStructure.GPIO_Mode 	= GPIO_Mode_Out_OD;		/* 开漏输出 */
	GPIO_InitStructure.GPIO_Speed 	= GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Pin 	= EEPROM_I2C_SDA_PIN;
	GPIO_Init(EEPROM_GPIO_PORT,&GPIO_InitStructure);
	
	GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_Out_PP;		/* 推挽输出 */
	GPIO_InitStructure.GPIO_Pin     = EEPROM_I2C_SCL_PIN;
	GPIO_Init(EEPROM_GPIO_PORT,&GPIO_InitStructure);
	
}
 /**
  * @brief  初始化SHT30的IO
  * @param  无
  * @retval 无
  */
void SHT30_Read_Value(uint8_t addr){
	
	/* SHT30有两种读取数值得方法,分别是状态查询和数值查询,*/
	uint16_t tem,hum;
	u16 buff[6];
	float Temperature = 0;
	float Humidity = 0;
	
	/* 发送指令 默认0x2c06 */
	i2c_Start();
	i2c_SendByte(addr<<1 |EEPROM_I2C_WR);
	i2c_WaitAck();
	i2c_SendByte(0x2c);
	i2c_WaitAck();
	i2c_SendByte(0x06);
	i2c_WaitAck();
	
	i2c_Stop();
	Delay_ms(50);
	
	i2c_Start();
	i2c_SendByte(addr<<1 |EEPROM_I2C_RD);

	if(i2c_WaitAck() == 0){
		buff[0] = i2c_ReadByte();i2c_Ack();	//返回温度高8位
		buff[1] = i2c_ReadByte();i2c_Ack();	//返回温度低8位
		buff[2] = i2c_ReadByte();i2c_Ack();	//温度crc校验位
		buff[3] = i2c_ReadByte();i2c_Ack();	//返回湿度高8位
		buff[4] = i2c_ReadByte();i2c_Ack();	//返回湿度低8位
		buff[5] = i2c_ReadByte();			//湿度crc校验位
		
		i2c_NAck();
		i2c_Stop();
	}
	
	tem = ((buff[0]<<8) | buff[1]);	//取出温度数据  温度拼接
	hum = ((buff[3]<<8) | buff[4]);	//取出湿度数据	湿度拼接
	
	/* 转换实际温湿度 */
	Temperature = (175.0*(float)tem/65535.0 - 45.0);
	Humidity    = (100.0*(float)hum/65535.0);	
	
	if(addr == 0x44 || addr == 0x45){
		/* 判断超范围语句 */
		if((Temperature >= -20) && (Temperature <= 125) && ((Humidity >= 0)) && ((Humidity <= 100))){
			humiture[0] = Temperature;
			humiture[2] = Humidity;
			printf("TEM and HUM %6.1f*C    %6.1f*RH\r\n",Temperature,Humidity);
		}else	/* 数据错误 */
		{
			humiture[0] = 0;
			humiture[2] = 0;
		}
	}
	hum = 0;
	tem = 0;
}

在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值