I2C协议介绍以及HAL库实现I2C对SHT30温湿度采样

这篇具有很好参考价值的文章主要介绍了I2C协议介绍以及HAL库实现I2C对SHT30温湿度采样。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


1- I2C协议介绍

(1)I2C协议简介

I2C总线是Philips公司在八十年代初推出的一种串行、半双工的总线,主要用于近距离、低速的芯片之间的通信。
12C Bus(IIC, Inter-Integrated Circuit Bus)是由一根数据线SDA用于收发数据,一根时钟线SCL用于通信双方时钟的同步,利用上拉电阻将它们拉成高电平(表示总线空闲),其典型的电压准位为+3.3V或+5V,具有电路简单、连接线少、控制简单、通信速率高等优点。

I2C协议介绍以及HAL库实现I2C对SHT30温湿度采样

I2C总线是一种主从结构(Master/Slave)总线, I2C总线上的每一个设备都可以作为主设备或者从设备,但一个总线上一般只有一个主设备,可以带多个从设备。其中主设备用来产生允许传输的时钟信号,并初始化总线的数据传输,所以主设备通常是CPU,而从设备只能被动响应主设备发起的通信请求,所以各种12C接口芯片将作为从设备使用。

(2)I2C从设备地址

因为一个12C总线上可以有多个从设备,这样主设备需要通过地址来确定与哪个器件进行通信。I2C总线上每个从设备都有一个唯一的7bit地址物理识别,这个地址固化在芯片内部,并可以从芯片datasheet上找到。因为12C地址全0为广播地址,所以12C总线理论上最多能带2^7-1=127个从设备。

其中I2C的从器件地址(我只用到了7位的)的组成如下:

1byte = 7bit地址 + 1bit读写标志

:1bit读写标志中,0-发送数据(写),1-请求数据(读)

有些时候一个总线上可能需要挂多个同一芯片,这样有些芯片还需要引出一个或几个引脚,由开发板设计电路来决定其具体地址,从而让不同芯片具有不同的7bit物理地址。如下图:

如果ADDR连VSS,则其7bit地址为0x44
如果ADDR连VDD,则其7bit地址为0x45

I2C协议介绍以及HAL库实现I2C对SHT30温湿度采样


2- I2C通信时序

在12C总线上传送的每一位数据都由一个同步时钟脉冲相对应,即在SCL串行时钟的配合下,数据在SDA上从高位向低位依次串行传送每一位的数据。下面是12C通信的时序图:
I2C协议介绍以及HAL库实现I2C对SHT30温湿度采样

(1)起始位

12C总线在空闲时SDA和SCL都处于高电平状态(由上拉电阻拉成高电平),当主设备要开始一次12C通信时就发送一个START(S)信号,这个起始位就可以告诉所有12C从机, “我”要开始进行12C通信了;当要结束一次12C通信时,则发送一个STOP§信号结束本次通信。

START(S):当SCL保持高电平时候,SDA出现下降沿,产生一个起始位,注意SCL一定要在高电平。
STOP( P ):当SCL保持高电平时候,SDA出现上升沿,产生一个停止位,注意SCL一定要在高电平。
I2C协议介绍以及HAL库实现I2C对SHT30温湿度采样

(2)读写地址

主机在发送START信号之后,第2个时序应该立刻给出要通信的目标从机物理地址。此外,I2C总线是一种能够实现半双工通信的同步串行通信协议,站在主设备的角度来看应该具有读/写从设备的功能。

这时候12C的读写地址除了7bit物理地址以外,还有1bit用来标识读/写方向位。这样12C的从设备读写地址通常是一个字节,其中高7bit是上面描述的物理地址,最低位用来表示读写方向(0为写操作, 1为读操作)

I2C协议介绍以及HAL库实现I2C对SHT30温湿度采样

(3)I2C应答信号

主机往12C总线上传输器件地址,所有的从机接收到这个地址后与自己的地址相比较若相同则发出一个应答ACK(Acknowledge)信号,主机收到这个应答信号后通讯连接建立成功,若未收到应答信号则表示寻址失败。

I2C协议介绍以及HAL库实现I2C对SHT30温湿度采样

此外,主/从机在之后的数据通信中,数据接收方(可能是主机也可能是从机)收到传输的一个字节数据后,需要给出响应,此时处在第九个时钟,发送端释放SDA线控制权,将SDA电平拉高,由接收方控制。

  • 若希望继续,则给出“应答(ACK, Acknowledge)”信号,即SDA为低电平
  • 若不希望继续,则给出“非应答(NACK,Not Acknowledge) ”信号,即SDA为高电平

(4)数据位发送与接收

主机在收到从机的应答信号之后,开始给从机发送数据。SDA数据线上的每个字节必须是8位,每次传输的字节数量没有限制,每个字节发送完成之后,从机必须跟一个应答信号。

I2C协议介绍以及HAL库实现I2C对SHT30温湿度采样

12C总线通信时数据位传输采用MSB(最高位优先)方式发送,其中高电平表示数据位1,低电平表示数据位0。
当传输的数据位需要改变时(如上一个位发送的是1,下一个位要发送0),必须发生在SCL为低电平期间。另外在传输过程中, SDA上的数据位在SCL高电平期间必须保持稳定不变。

假设SCL在高电平,想一下是不是就会触发起始位或者终止位。想一想起始信号与停止信号是怎么发送的就会明白为什么SCl一定要在高电平才能改变SDA。


3- I2C协议主机收发数据流程

(1)主机发送数据

  • 主机在检测到总线为“空闲状态”(即 SDA、SCL 线均为高电平)时,发送一个启动信号“S”,开始一次通信的开始;
  • 主机接着发送一个从设备地址,它由7bit物理地址和1bit读写控制位R/w组成(此时R/W=0);
  • 相对应的从机收到命令字节后向主机回馈应答信号 ACK(ACK=0);
  • 主机收到从机的应答信号后开始发送第一个字节的数据;
  • 从机收到数据后返回一个应答信号 ACK;
  • 主机收到应答信号后再发送下一个数据字节;
  • 当主机发送最后一个数据字节并收到从机的 ACK 后,通过向从机发送一个停止信号P结束本次通信并释放总线。从机收到P信号后也退出与主机之间的通信。
    I2C协议介绍以及HAL库实现I2C对SHT30温湿度采样

注意:

  • 主机通过发送地址码与对应的从机建立了通信关系,而挂接在总线上的其它从机虽然同时也收到了地址码,但因为与其自身的地址不相符合,因此提前退出与主机的通信;
  • 主机的一次发送通信,其发送的数据数量不受限制。主机是通过 P 信号通知发送的结束,从机收到 P 信号后退出本次通信;
  • 主机的每一次发送后都是通过从机的 ACK 信号了解从机的接收状况,如果应答错误则重发。

(2)主机接收数据

  • 主机发送起始信号后,接着发送地址字节(其中R/W=1);
  • 对应的从机收到地址字节后,返回一个应答信号并向主机发送数据;
  • 主机收到数据后向从机反馈一个应答信号ACK;
  • 从机收到应答信号后再向主机发送下一个数据;
  • 当主机完成接收数据后,向从机发送一个NAK,从机收到非应答信号后便停止发送;
  • 主机发送非应答信号后,再发送一个停止信号,释放总线结束通信。I2C协议介绍以及HAL库实现I2C对SHT30温湿度采样

注意:

  • 主机所接收数据的数量是由主机自身决定,当发送“非应答信号NAK”时从机便结束传送并释放总线。
  • 非应答信号的两个作用:前一个数据接收成功,停止从机的再次发送。

4- SHT30传感器介绍

(1)SHT30简介

SHT30数字温湿度传感器采用业内知名的瑞士Sensirion公司推出的新一代SHT30温湿度传感器芯片,它能够提供极高的可靠性和出色的长期稳定性,具有功耗低、反应快、抗干扰能力强等优点。IIC通讯,兼容3.3V/5V,可以非常容易的集成到智能楼宇、天气站、仓库存储、养殖、孵化等应用场景中,其中小米的温湿度传感器使用的也是SHT30。

I2C协议介绍以及HAL库实现I2C对SHT30温湿度采样

  • 高精度,内部自动校准,数字输出
  • 低功耗、响应速度快、抗干扰能力强
  • 兼容3.3V/5V控制器

(2)SHT30工作原理

SHT30 芯片有八个引脚,利用12C进行数据传输,具有两个可选地址,宽电源电压从2.4V到5.5V。下面是引脚说明:
I2C协议介绍以及HAL库实现I2C对SHT30温湿度采样
下面是小熊座NB-loT开发板上SHT30传感器的原理图,其中12C接口连到了MCU的PB13和PB14两个引脚上,这两个引脚可以设置为12C2模式工作。
I2C协议介绍以及HAL库实现I2C对SHT30温湿度采样


5- HAL库中I2C发送接收数据函数

开始实现HAL库实现I2C对SHT30温湿度采样我们首先了解一下HAL库中的两个函数。

(1)HAL_I2C_Master_Transmit()

(1)函数原型:

HAL_I2C_Master_Transmit(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);

(2)函数功能:IIC发送数据,主机需要将数据通过IIC发送过去
(3)参数介绍:

  • *hi2c 设置使用的是那个IIC
  • DevAddress 写入的地址,设置写入数据的地址
  • *pData 需要写入的数据
  • Size 要发送的字节数
  • Timeout 最大传输时间,超过传输时间将自动退出传输函数

(4) 使用到的函数参数讲解(举例子):

HAL_I2C_Master_Transmit(&hi2c2, SHT30_ADDR_WR, (uint8_t*)buf, 2, 0xFFFF);
  • &hi2c2:我们使用的是:hi2c2,传地址&hi2c2
  • SHT30_ADDR_WR:我们宏定义了写的地址,传写的地址c #define SHT30_ADDR_WR (SHT30_ADDR<<1)
  • (uint8_t*)buf:我们将需要传的数据保存在buf中
  • 2:传2个字节,16个位
  • 0xFFFF超时:oxFFFF(4 294 967 295也就是无符号整型所能表示的最大值)

(2)HAL_I2C_Master_Receive()

(1)函数原型:

HAL_I2C_Master_Receive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint8_t *pData, uint16_t Size, uint32_t Timeout);

(2)函数功能:IIC接收数据,从机发送给主机,主机需要将数据通过IIC接收
(3)函数参数和HAL_I2C_Master_Transmit()大概是一样的,只是取到的数据保存在pData中。
(4)使用到的函数参数讲解(举例子):

HAL_I2C_Master_Receive(&hi2c2, SHT30_ADDR_RD, buf, SHT30_DATA_SIZE, 0xFFFF);
  • &hi2c2:我们使用的是:hi2c2,传地址&hi2c2
  • SHT30_ADDR_RD:我们宏定义了读的地址,传读的地址c #define SHT30_ADDR_RD ((SHT30_ADDR<<1) | 0x01)
  • buf:我们将获取到的数据保存在buf中
  • SHT30_DATA_SIZE:宏定义,6个字节c #define SHT30_DATA_SIZE 6
  • 0xFFFF超时:oxFFFF(4 294 967 295也就是无符号整型所能表示的最大值)

6- SHT30温湿度采样

(1)配置

先配置SHT30连接的I2C管脚PB13 和PB14为I2C模式,此时因为I2C功能并没有使能,管脚状态为黄色。接下来再在Connectivity里选择12C2并配置为I2C模式,这是12C功能配置完成。配置好之后按Ctrl+S将会自动生成I2C总线初始化代码。
I2C协议介绍以及HAL库实现I2C对SHT30温湿度采样

(2)创建sht30.c

/*
 * sht30.c
 *
 *  Created on: Nov 3, 2022
 *      Author: Administrator
 */

#include <stdio.h>
#include "stm32l4xx_hal.h"
#include "i2c.h"
#include "sht30.h"

#define CONFIG_SHT30_DEBUG

#ifdef CONGIF_SHT30_DEBUG
#define sht30_print(format, args...) printf(format, ##args)
#else
#define sht30_print(format, args...) do{} while(0)
#endif

static int sht30_send_cmd(SHT30_CMD cmd)
{
	uint8_t buf[2];

	buf[0] = cmd >> 8;
	buf[1] = cmd & 0xFF;

	return HAL_I2C_Master_Transmit(&hi2c2, SHT30_ADDR_WR, (uint8_t*)buf, 2, 0xFFFF);
}

static void sht30_soft_reset(void)
{
	sht30_send_cmd(SOFT_RESET_CMD);
	HAL_Delay(1);
}

static int sht30_single_shot_measurement(uint8_t *buf, uint8_t buf_size)
{
	uint16_t cmd = HIGH_ENABLED_CMD;
	uint8_t  rv;

	if( !buf || buf_size < SHT30_DATA_SIZE )
	{
		sht30_print("%s(): Invalid input argument\n", __func__);
		return -1;
	}

	rv = sht30_send_cmd(cmd);
	if( rv )
	{
		sht30_print("ERROR: HST30 send messurement command failure, rv = &d\n", rv);
		sht30_soft_reset();
		return -2;
	}

	rv = HAL_I2C_Master_Receive(&hi2c2, SHT30_ADDR_RD, buf, SHT30_DATA_SIZE, 0xFFFF);
	if(rv)
	{
		sht30_print("ERROR: SHT30 read measurement result failure, rv = %d\n", rv);
		return -3;
	}

	return 0;
}

static uint8_t sht30_crc8(const uint8_t *data, int len)
{
	const uint8_t POLYNOMIAL = 0x31;
	uint8_t       crc = 0xFF;
	int           i,j;

	for (i=0; i<len; ++i)
	{
		crc ^= *data++;

		for (j=0; j<8; j++)
		{
			crc = (crc & 0x80)? (crc << 1) ^ POLYNOMIAL:(crc << 1);
		}
	}
	return crc;
}

int SHT30_SampleData(float *temperature, float *humidity)
{
	uint8_t buf[SHT30_DATA_SIZE];
	int rv;
	uint16_t temp;
	uint16_t humd;
	uint16_t crc;

	if(!temperature || !humidity)
	{
		sht30_print("%s(): Invalid input argument\n", __func__);
		return -1;
	}

	rv = sht30_single_shot_measurement(buf, SHT30_DATA_SIZE);
	if(rv)
	{
		sht30_print("SHT30 Single Short measurement failure, rv=%d\n", rv);
		return -2;
	}

#ifdef CONFIG_SHT30_DEBUG
	{
		int i;

		sht30_print("SHT30 get %d bytes sample data: \n", SHT30_DATA_SIZE);
		for(i=0; i<SHT30_DATA_SIZE; i++)
		{
			sht30_print("0x%02x ", buf[i]);
		}
		sht30_print("\n");
	}
#endif

	crc = sht30_crc8(buf, 2);
	sht30_print("SHT30 temperature Cal_CRC: [%02x] EXP_CRC: [%02x]\n", crc, buf[2]);
	if(crc != buf[2])
	{
		sht30_print("SHT30 measurement temperature got CRC error\n");
		return -3;
	}

	crc = sht30_crc8(&buf[3], 2);
	sht30_print("SHT30 humidity Cal_CRC: [%02x] EXP_CRC: [%02x]\n", crc, buf[5]);
	if(crc != buf[5])
	{
		sht30_print("SHT30 messurement temperature got CRC error\n");
		return -4;
	}

	temp = (buf[0]<<8) | buf[1];
	humd = (buf[3]<<8) | buf[4];

	*temperature = -45 + 175*((float)temp/65535);
	*humidity = 100 * ((float)humd/65535);

	return 0;
}

(3)创建sht30.h

/*
 * sht30.h
 *
 *  Created on: Nov 3, 2022
 *      Author: Administrator
 */

#ifndef INC_SHT30_H_
#define INC_SHT30_H_

#include "stm32l4xx_hal.h"

#define SHT30_ADDR 0x44

#define SHT30_ADDR_WR (SHT30_ADDR<<1)
#define SHT30_ADDR_RD ((SHT30_ADDR<<1) | 0x01)

#define SHT30_DATA_SIZE 6

typedef enum
{
	SOFT_RESET_CMD = 0x30A2,

	HIGH_ENABLED_CMD = 0x2C06,
	MEDIUM_ENABLED_CMD =0x2C0D,
	LOW_ENSABLED_CMD = 0x2C10,
	HIGH_DISABLED_CMD = 0x2400,
	MEDIUM_DISABLED_CMD = 0X240B,
	LOW_DISABLED_CMD = 0x2416,


	HIGH_0_5_CMD = 0x2032,
	MEDIUM_0_5_CMD = 0x2024,
	LOW_0_5_CMD = 0x202F,
	HIGH_1_CMD = 0x2130,
	MEDIUM_1_CMD = 0x2126,
	LOW_1_CMD = 0x212D,
	HIGH_2_CMD = 0x2236,

	MEDIUM_2_CMD = 0x2220,
	LOW_2_CMD = 0x222B,
	HIGH_4_CMD = 0x2334,
	MEDIUM_4_CMD = 0x2322,
	LOW_4_CMD = 0x2329,
	HIGH_10_CMD = 0x2737,
	MEDIUM_10_CMD = 0x2721,
	LOW_10_CMD = 0x272A,
}SHT30_CMD;

extern int SHT30_SampleData(float *temperature, float *humidity);

#endif /* INC_SHT30_H_ */

(4)修改main.c

printf()函数实现的代码前期博客中有,就不多说了。

/* USER CODE BEGIN Includes */
#include "sht30.h"
#include "string.h"
/* USER CODE END Includes */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
static int report_tempRH_json(void);
/* USER CODE END 0 */
  printf ("The sht30 starts to obtain temperature and humidity data.\r\n");
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	  report_tempRH_json();
	  HAL_Delay(3000);
  }
  /* USER CODE END 3 */
/* USER CODE BEGIN 4 */
int report_tempRH_json(void)
{
	char      buf[128];
	float     temperature, humidity;

	if(SHT30_SampleData(&temperature, &humidity) < 0)
	{
		printf("ERROR: SHT30 Sample data failure\n");
		return -1;
	}

	memset(buf, 0, sizeof(buf));
	snprintf(buf, sizeof(buf), "{\"Temperature\":\"%.2f\", \"Humidity\":\"%.2f\"}", temperature, humidity);

	HAL_UART_Transmit(&huart1, (uint8_t*)buf, strlen(buf), 0xFFFF);

	return 0;
}
/* USER CODE END 4 */

7- 结果呈现

对着开发板上的温湿度传感器哈气,就会看见变化,说明成功。
I2C协议介绍以及HAL库实现I2C对SHT30温湿度采样文章来源地址https://www.toymoban.com/news/detail-423601.html


到了这里,关于I2C协议介绍以及HAL库实现I2C对SHT30温湿度采样的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 详细介绍GPIO、I2C、SPI通讯原理以及物理层原理

    目录 一. GPIO 1. 什么是GPIO? 2. GPIO组成原理 3. GPIO工作原理 二. I2C 1. 什么是I2C? 2. I2C组成原理 3. I2C的特性 4. I2C的通讯模式 5. I2C的通讯过程 6. I2C接口工作模式 7. 硬件拉高拉低的过程 8. 一对多 9. 开发流程 三. SPI 1. 什么是SPI? 2. SPI优与缺点 3. SPI组成原理 4. SPI通讯模式 5. 通讯

    2024年02月02日
    浏览(108)
  • 【ARM】Day9 cortex-A7核I2C实验(采集温湿度)

     1. 2、编写IIC协议,采集温湿度值 iic.h si7006.h iic.c si7006.c main.c 运行结果: 2.思维导图  

    2024年02月11日
    浏览(37)
  • STM32 HAL库函数学习 I2C篇

    本篇内容讲述STM32的硬件IIC功能。硬件IIC的使用在F1系列上可能会有问题。本次使用的测试平台是H7,用于AT24C02芯片的读写正常,暂不清楚在其他芯片上使用是否正常。 1、HAL_StatusTypeDef HAL_I2C_Init (I2C_HandleTypeDef * hi2c) I2C初始化函数,使用CubeMx生成。需要选中I2C硬件指定的IO口。

    2023年04月08日
    浏览(42)
  • STM32 HAL FreeRTOS 硬件I2C 使用

    因为某个项目想要颜色识别,去识别球的颜色,但是又不想多来个摄像头,所以想尝试一下颜色传感器的方案。但是经过尝试,HAL库生成的 FreeRTOS 硬件 I2C 读写一直在报错。 刚好手头上有九轴陀螺仪的例程代码。最后用FreeRTOS 硬件 I2C 读取数据。 这里提到了阻塞式 HAL 函数(

    2024年02月20日
    浏览(52)
  • 【STM32 CubeMX】I2C层次结构、I2C协议

    在STM32 CubeMX环境中,I2C(Inter-Integrated Circuit)是一种常用的串行通信协议,广泛应用于连接各种外设和传感器。理解I2C的层次结构、协议和硬件结构对于STM32微控制器的开发至关重要。通过STM32 CubeMX提供的图形化配置工具,我们能够更轻松地理解和配置I2C通信,同时深入了解

    2024年02月22日
    浏览(81)
  • 【STM32L496】使用HAL库实现I2C写入/读取数据(M24C32)

    IIC原理超详细讲解—值得一看 【嵌入式硬件芯片开发笔记】EEPROM芯片M24C32配置流程 STM32硬件I2C与软件模拟I2C超详解 实现通信功能的芯片为M24C32,对此,芯片手册上第一页就有对其概括描述。 Automotive 32-Kbit serial I²C bus EEPROM with 1 MHz clock 启动/停止条件 :当串行时钟(SCL)位于

    2024年02月03日
    浏览(71)
  • I2C总线 | I2C总线介绍

    目录 I2C 总线 | I2C 总线介绍 I2C 总线介绍 I2C有如下特点: I2C 总线术语 I2C 总线位传输 IIC总线数据传输 1.字节格式 2.应答响应 IIC 总线寻址方式 1.7位寻址 2.10位寻址 快速和高速模式 1.快速模式 2.高速模式 I2C ( Inter - Intergrated Circuit )总线(也称 IIC 或 I2C )是由 PHILIPS 公司开发

    2024年02月04日
    浏览(57)
  • STM32之I2C总线知识和HAL库函数

    一、 I2C总线知识 I2C总线物理拓扑结构 I2C 总线在物理连接上非常简单,分别由SDA(串行数据线)和SCL(串行时钟线)及上拉电阻组成。通信原理是通过对SCL和SDA线高低电平时序的控制,来 产生I2C总线协议所需要的信号进行数据的传递。在总线空闲状态时,这两根线一般被上面所接

    2024年02月21日
    浏览(49)
  • STM32基于CubeMX与HAL库的I2C应用

    1.1 物理层         I2C协议和摩托罗拉公司的SPI协议一样,是一种通讯协议。串行外围设备接口,是一种高速全双工的通信总线,是由 Phiilps 公司开发的。由于它引脚少,硬件实现简单,可扩展性强,不需要 USART、CAN 等通讯协议的外部收发设备,现在被广泛地使用在系统内

    2024年02月21日
    浏览(70)
  • 关于STM32硬件I2C HAL_I2C_Mem_Read,在I2C_WaitOnTXISFlagUntilTimeout返回HAL_ERROR

    在使用NUCLEO-L452RE开发版的IIC总线作为主机和其他设备从机通信时主机IIC在以下代码处返回HAL_ERROR. /* Wait until TXIS flag is set */   if (I2C_WaitOnTXISFlagUntilTimeout(hi2c, Timeout, Tickstart) != HAL_OK)   {     return HAL_ERROR;   } 在调试中发现如果使用模拟IIC,可以与从机正常通信,但是使用硬件

    2024年04月28日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包