STM32 - IIC协议读取温湿度数据

STM32 - IIC协议读取温湿度数据

实验任务

  1. 学习I2C总线通信协议,了解什么是“软件I2C”和“硬件I2C”;
  2. 了解AHT20模块,编程实现:每隔2秒钟采集一次温湿度数据,并通过串口发送到上位机(win10)。

实验过程

I2C通信协议介绍

I2C(Inter-Integrated Circuit)是一种用于连接微处理器和外部设备的串行通信协议。该协议由飞利浦公司(现在的恩智浦半导体,NXP Semiconductors)在 1982 年首次引入,如今已成为广泛应用于各种嵌入式系统中的标准通信协议之一。

以下是关于I2C通信协议的一些基本概念:

物理连接

I2C使用两根线进行通信:

  1. SDA(Serial Data Line): 用于传输实际的数据位。
  2. SCL(Serial Clock Line): 用于同步数据传输的时钟信号。

这两根线都是开漏输出的,通过上拉电阻连接到电源线,形成一个开漏的输出结构。

工作原理

I2C协议是主从式的通信协议,支持多主设备和多从设备。在总线上可以有一个或多个主设备,但只能有一个活动的主设备。

通信的开始和停止由主设备控制。一个典型的I2C通信周期包括以下几个阶段:

  1. 开始条件(Start Condition): 主设备产生一个从高电平到低电平的SDA脉冲,同时保持SCL为高电平。这标志着通信的开始。

  2. 地址传输: 主设备发送从设备的地址,指定是读操作还是写操作。地址是7位或10位,取决于设备的寻址方式。8位的地址是最常见的。

  3. 数据传输: 在地址传输后,主设备和从设备之间可以传输数据。数据的传输方式是在时钟脉冲的上升沿或下降沿改变数据线上的电平。

  4. 应答位(ACK/NACK): 数据的每个字节传输后,接收设备会发送一个应答(ACK)或非应答(NACK)位。ACK表示继续传输,而NACK表示结束传输。

  5. 重复开始条件: 主设备在不释放总线的情况下可以发起另一个通信周期,这称为重复开始条件。

  6. 停止条件(Stop Condition): 主设备发送一个从低电平到高电平的SDA脉冲,同时保持SCL为高电平。这标志着通信的结束。

优势和应用

  1. 简单和灵活: I2C协议简单易懂,适用于连接多种类型的芯片和传感器。

  2. 双向通信: I2C允许主设备和从设备之间的双向通信,这使得它适用于复杂的数据传输任务。

  3. 多设备支持: 支持多个设备在同一总线上工作,通过唯一的地址进行区分。

  4. 低复杂度硬件: 需要的硬件资源相对较少,特别适用于资源有限的嵌入式系统。

I2C通信协议因其简单、灵活且广泛应用于各种嵌入式系统中,被广泛接受。在许多嵌入式设备中,例如传感器、存储器、显示屏等,都可以通过I2C进行连接和通信。

软件I2C和硬件I2C

软件I2C和硬件I2C都是实现I2C通信协议的方式,但它们在实现原理和应用场景上有所不同。

硬件I2C

硬件I2C是指使用专门的I2C硬件控制器来实现I2C通信的方式。这些硬件控制器通常集成在微控制器、微处理器或其他专用芯片中。硬件I2C的特点包括:

  1. 高效性: 由于使用硬件控制器,硬件I2C通常更为高效,能够在较高的时钟频率下工作,实现更快的数据传输。

  2. 实时性: 硬件I2C通常具有更好的实时性能,适用于对时间要求较为严格的应用场景。

  3. 占用硬件资源: 硬件I2C需要专门的硬件控制器,因此可能占用一定的芯片空间和资源。

  4. 适用于复杂任务: 由于其高效性和实时性,硬件I2C适用于需要大量数据传输或对通信速度要求较高的场景。

软件I2C

软件I2C是通过编程方式模拟实现I2C通信的方式,通常使用通用输入输出(GPIO)引脚来模拟I2C的SDA和SCL线。软件I2C的特点包括:

  1. 灵活性: 软件I2C具有较高的灵活性,因为它可以通过编程调整实现细节,适应不同的硬件环境。

  2. 资源消耗较小: 由于不需要专门的硬件控制器,软件I2C通常占用的硬件资源较少。

  3. 适用于简单任务: 软件I2C通常适用于较为简单的数据传输任务,例如连接一些简单的传感器或执行基本的通信功能。

  4. 低成本: 由于不需要专门的硬件支持,软件I2C在成本上可能相对较低。

选择和应用

选择使用软件I2C还是硬件I2C通常取决于具体的应用场景和需求:

  • 如果应用对通信速度、实时性要求较高,或者需要处理大量的数据,通常更适合选择硬件I2C。

  • 如果应用对资源消耗较为敏感,或者只需要进行简单的数据传输,软件I2C可能是更经济、更灵活的选择。

在嵌入式系统设计中,通常会根据具体的应用需求来选择使用软件I2C还是硬件I2C,以平衡性能、成本和资源占用等因素。

I2C协议实现温湿度采集

这里基于STM32CubeMX进行编程。

配置引脚

本次实验使用PB6模拟SCL,PB7模拟SDA。

编写代码

在奥松官网下载AHT20芯片代码:奥松电子下载中心

官方代码使用的是PB14,PB15引脚需要修改对应的引脚才可以正常使用。

AHT20-21_DEMO_V1_3.c中的SDA相关函数修改如下:(其中的SDA_Pin就是GPIO_PIN_7)

void SDA_Pin_Output_High(void)   //将PB7配置为输出 , 并设置为高电平, PB7作为I2C的SDA
{
	GPIO_InitTypeDef  GPIO_InitStruct;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;//推挽输出
	GPIO_InitStruct.Pin = SDA_Pin;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(GPIOB,& GPIO_InitStruct);
	HAL_GPIO_WritePin(GPIOB,SDA_Pin,GPIO_PIN_SET);
}

void SDA_Pin_Output_Low(void)  //将P7配置为输出  并设置为低电平
{
	GPIO_InitTypeDef  GPIO_InitStruct;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;//推挽输出
	GPIO_InitStruct.Pin = SDA_Pin;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(GPIOB,& GPIO_InitStruct);
	HAL_GPIO_WritePin(GPIOB,SDA_Pin,GPIO_PIN_RESET);
}

void SDA_Pin_IN_FLOATING(void)  //SDA配置为浮空输入
{
	GPIO_InitTypeDef  GPIO_InitStruct;
	GPIO_InitStruct.Mode = GPIO_MODE_INPUT;//浮空
	GPIO_InitStruct.Pin = SDA_Pin;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init( GPIOB,&GPIO_InitStruct);
}

AHT20-21_DEMO_V1_3.c中的SCL相关函数修改如下:(其中的SCL_Pin就是GPIO_PIN_6)

void SCL_Pin_Output_High(void) //SCL输出高电平,P6作为I2C的SCL
{
	HAL_GPIO_WritePin(GPIOB,SCL_Pin,GPIO_PIN_SET);
}

void SCL_Pin_Output_Low(void) //SCL输出低电平
{
	HAL_GPIO_WritePin(GPIOB,SCL_Pin,GPIO_PIN_RESET);
}

void Init_I2C_Sensor_Port(void) //初始化I2C接口,输出为高电平
{	
	GPIO_InitTypeDef  GPIO_InitStruct;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;//推挽输出
	GPIO_InitStruct.Pin = SDA_Pin;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(GPIOB,& GPIO_InitStruct);
	HAL_GPIO_WritePin(GPIOB,SDA_Pin,GPIO_PIN_SET);

	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;//推挽输出
	GPIO_InitStruct.Pin = SCL_Pin;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(GPIOB,& GPIO_InitStruct);
	HAL_GPIO_WritePin(GPIOB,SDA_Pin,GPIO_PIN_SET);
}

main.c代码如下:

int main(void)
{
  /* USER CODE BEGIN 1 */
	uint32_t CT_data[2]={0,0};
	volatile int  c1,t1;
	
	Delay_1ms(500);

	HAL_Init();

	SystemClock_Config();

	MX_GPIO_Init();
	MX_DMA_Init();
	MX_USART1_UART_Init();
	
	//初始化AHT20
	AHT20_Init();
	Delay_1ms(500);

  while (1)
  { 
    /* USER CODE END WHILE */
		AHT20_Read_CTdata(CT_data);       //不经过CRC校验,直接读取AHT20的温度和湿度数据    推荐每隔大于1S读一次
		//AHT20_Read_CTdata_crc(CT_data);  //crc校验后,读取AHT20的温度和湿度数据 
	
		c1 = CT_data[0]*1000/1024/1024;  //计算得到湿度值c1(放大了10倍)
		t1 = CT_data[1]*2000/1024/1024-500;//计算得到温度值t1(放大了10倍)

		printf("温度:%d%d.%d",t1/100,(t1/10)%10,t1%10);
		printf("湿度:%d%d.%d",c1/100,(c1/10)%10,c1%10);
		printf("\r\n");
	  
	  	HAL_Delay(2000);
		
  /* USER CODE END 3 */
	}
}

电路连接

AHT20模块的引脚图如下:

其中,SDA接PB7,SCL接PB6。

效果

参考

STM32F103基于I2C协议的AHT20温湿度传感器的数据采集

posted @ 2023-11-12 17:41  回文串多放孜然  阅读(99)  评论(0编辑  收藏  举报