IIC协议之SHT30温湿度采样

1 篇文章 0 订阅

1.IIC协议介绍

1.1 协议简介

IIC由SDA(串行数据线)和SCL(串行时钟线)及上拉电阻组成(总线空闲时是高电平)。IIC是一种主从结构总线,在IIC总线上,每一个设备都可以作为主设备或者从设备,但一个IIC总线上一般只有一个主设备,多个从设备。主设备来产生时钟信号,一般主设备是CPU,而从设备只是用来相应主设备的通信请求,一般从设备是传感器。

1.2 SHT30设备地址

一个IIC总线上可以挂载多个从设备,所以主设备就需要通过从设备的地址来确定与哪个设备进行通信。在IIC总线上每个从设备都有唯一确定的地址,设备地址在芯片内部就固定好了,可以从芯片的datasheet上找到。因为IIC地址全为0时为广播地址,所以IIC总线上最多可以挂载2^7-1=127个从设备。

有时候IIC总线上需要挂载多个同一芯片,为了实现地址的不同,芯片引出了一个或者多个引脚,来使同一芯片具有不同的地址。如SHT30温湿度传感器,芯片引出一个ADDR引脚,当ADDR引脚接VSS时,其7bit地址为0x44,ADDR接VDD时地址为0x45。
SHT30地址

2.协议时序

2.1 IIC通信时序图

时序图
下面这个图片更好的看出数据的传输。
IIC时序

2.2 起始信号

IIC通信以起始信号开始传输数据,所以在发送数据之前,需要先给个起始信号。由时序图可以知道,总线空闲时SCL和SDA都是高电平,时钟线先拉低,然后数据线拉低,这样就产生了一个起始信号。起始信号是在SCL为高电平时,SDA由高电平向低电平转变,产生一个下降沿,即为起始信号。

2.3 结束信号

IIC通信以结束信号停止传输数据。当收到结束信号后,主从设备停止传输数据。由时序图可以知道,当SCL为高电平时,SDA由低电平向高电平跳转,SDA产生一个上升沿,产生一个结束信号。

2.4 应答信号

在8bit数据传输的后面,紧跟着一个应答信号,用来判断是不是要结束传输数据或者继续传输数据。

当主设备连接从设备时,发送一个地址信号,当在总线上从设备接收到和自己地址相同的地址信息后,给出一个应答信号,表示自己与主设备建立通信。

当主设备接收到从设备的一个字节的数据后,给出自己的应答或者非应答信号,来表示是否需要继续传输数据,给的应答信号,“应答”为低电平,“非应答”为高电平。

2.5 数据位收发

发数据:
先把SCL拉低,然后把SDA拉高,再把SCL拉高,这样就发送一个bit的“1”。
先把SCL拉低,然后把SDA拉低,再把SCL拉高,这样就发送一个bit的“0”。

为什么要这样做?因为数据传输是在SCL为高电平时传输,并且前面讲到起始信号和终止信号的时候,在SCL为高电平时,只要有上升沿或者下降沿的到来,那么就会认为是起始信号或者结束信号。所以在传输bit的时候,得在SCL为低电平时改变SDA的电平,然后在SCL为高电平时,保证SDA的电平稳定,这样才能保证正确发送“0”,“1”。

收数据:同样,接收数据也是在SCL为高电平时接收,因为数据的传输在SCL为高电平,所以在接收数据前,把SCL拉高,然后读取SDA的电平即可。

3.协议代码

3.1 起始信号

void IIC_Start()//产生开始信号
{
	IIC_SDA_On();//输出模式
	SCL_H();
	SDA_H();
	delay_us(2);
	SDA_L();
	delay_us(2);
	SCL_L();
}

3.2 结束信号

void IIC_Stop()//产生结束信号
{
	IIC_SDA_On();//输出模式
	SCL_L();
	SDA_L();
	delay_us(2);
	SCL_H();
	delay_us(2);
	SDA_H();
	delay_us(2);
}

3.3 应答信号

void IIC_Ack()//应答模式,SCL高电平时,SDA=0为应答
{
	SCL_L();
	IIC_SDA_On();//输出模式
	SDA_L();
	/*SCL__---
	 *
	 *SDA_____
	 *传输数据0
	*/
	delay_us(2);
	SCL_H();
	delay_us(2);
	SCL_L();
}

3.4 非应答信号

void IIC_NAck()
{
	SCL_L();
	IIC_SDA_On();//输出模式
	SDA_H();
	/*SCL__---
	 *
	 *SDA-----
	 *传输数据1
	*/
	delay_us(2);
	SCL_H();
	delay_us(2);
	SCL_L();
}

3.5 等待从机应答

从机无应答时,应结束连接,所以发送IIC终止信号

uint8_t IIC_Wait_Ack()
{
	uint8_t ucErrTime=0;
	IIC_SDA_In();
	SCL_H();
	while(SDA_Read())
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			IIC_Stop();
			return 1;
		}
	}
	SCL_L();
	return 0;
}

3.6 主机发送一个字节

void IIC_Send_Byte(uint8_t data)
{
	uint8_t i,txd;
	IIC_SDA_On();
	SCL_L();//拉低时钟线,选择传输的SDA电平,因为数据传输需要在SCL低电平时改变,高电平时输出
	for(i=0;i<8;i++)
	{
		txd=(data&0x80)>>7;//把最高位取出来
		data<<=1;
		if(txd)
			SDA_H();
		else
			SDA_L();
		delay_us(2);
		SCL_H();//开始传输
		delay_us(2);
		SCL_L();
		delay_us(2);
	}
}

3.7 接收从机一个字节

在接收从机数据的时候,需要给应答或者非应答信号,来决定是否需要继续传输数据。

uint8_t IIC_Receive_Byte(uint8_t ack)//方便理解,逻辑和从机应答相反,1为应答 0为非应答
{
	uint8_t i,recevie=0;
	IIC_SDA_In();
	for(i=0;i<8;i++)
	{
		SCL_L();
		delay_us(2);
		SCL_H();
		recevie<<=1;
		recevie+=SDA_Read();
		delay_us(2);
	}
	if(ack)
		IIC_Ack();
	else
		IIC_NAck();
	return recevie;
}

4.SHT30代码

4.1 SHT30初始化

发送测量指令,让SHT30开始循环采集温湿度。我采用的是SHT30的周期性数据采集模式的测量指令。
sht30周期采集模式

void Sht30_Init()
{
	IIC_Start();
	IIC_Send_Byte(0x44<<1|0);//0为写
	IIC_Wait_Ack();
	IIC_Send_Byte(0x21);
	IIC_Wait_Ack();
	IIC_Send_Byte(0x30);
	IIC_Wait_Ack();
	IIC_Stop();
	HAL_Delay(150);
}

4.2 SHT30获取温湿度

周期模式测量结果的读出。
sht30读取温湿度
在温度湿度后面会紧跟一个检验和数据CRC。

void Read_IIC_Data(float *Temperature,float *Humidity)
{
	uint16_t data[6];
	uint16_t temp,humi;
	IIC_Start();
	IIC_Send_Byte(0x44<<1|0);//0为写
	IIC_Wait_Ack();
	IIC_Send_Byte(0xe0);
	IIC_Wait_Ack();
	IIC_Send_Byte(0x00);
	IIC_Wait_Ack();

	IIC_Start();
	IIC_Send_Byte(0x44<<1|1);
	IIC_Wait_Ack();
//温度数据
	data[0]=IIC_Receive_Byte(1);
	data[1]=IIC_Receive_Byte(1);
//CRC
	data[2]=IIC_Receive_Byte(1);
//湿度数据
	data[3]=IIC_Receive_Byte(1);
	data[4]=IIC_Receive_Byte(1);

	data[5]=IIC_Receive_Byte(0);
	IIC_Stop();
//校验和就不计算了
	temp=(data[0]<<8)|data[1];
	humi=(data[3]<<8)|data[4];
	
	/*转换实际温度*/
	*Temperature=(175.0*(float)temp/65535.0-45.0) ;// T = -45 + 175 * tem / (2^16-1)
	*Humidity=(100.0*(float)humi/65535.0);// RH = hum*100 / (2^16-1)

}
  • 17
    点赞
  • 102
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值