前言

  • 学习I2C总线通信协议,使用STM32F103完成基于I2C协议的AHT20温湿度传感器的数据采集,并将采集的温度-湿度值通过串口输出。具体任务:
    1)解释什么是“软件I2C”和“硬件I2C”? (阅读野火配套教材的第23章“I2C–读写EEPROM”原理章节)
    2)阅读AHT20数据手册,编程实现:每隔2秒钟采集一次温湿度数据,并通过串口发送到上位机(win10)。

一、I2C总线通信协议

1.I2C总线

  • I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息。
  • 主器件用于启动总线传送数据,并产生时钟以开放传送的器件,此时任何被寻址的器件均被认为是从器件.在总线上主和从、发和收的关系不是恒定的,而取决于此时数据传送方向。如果主机要发送数据给从器件,则主机首先寻址从器件,然后主动发送数据至从器件,最后由主机终止数据传送;如果主机要接收从器件的数据,首先由主器件寻址从器件.然后主机接收从器件发送的数据,最后由主机终止接收过程。在这种情况下.主机负责产生定时时钟和终止数据传送。
  • I2C 总线接口连接微控制器和串行 I2C 总线。它提供多主机功能,控制所有 I2C 总线特定的时序、协议、仲裁和定时。支持标准和快速两种模式,同时与 SMBus 2.0 兼容。I2C 总线有多种用途,包括 CRC 码的生成和校验、SMBus(系统管理总线 System Management Bus)、PMBus(电源管理总线 Power Management Bus)。根据特定设备的需要,可以使用 DMA 以减轻 CPU 的负担。

2.工作原理

SDA(串行数据线)和SCL(串行时钟线)都是双向I/O线,接口电路为开漏输出。需通过上拉电阻接电源VCC。
当总线空闲时,两根线都是高电平,连接总线的外同器件都是CMOS器件,输出级也是开漏电路。在总线上消耗的电流很小,因此,总线上扩展的器件数量主要由电容负载来决定,因为每个器件的总线接口都有一定的等效电容。而线路中电容会影响总线传输速度。当电容过大时,有可能造成传输错误。所以,其负载能力为400pF,因此可以估算出总线允许长度和所接器件数量。
主器件用于启动总线传送数据,并产生时钟以开放传送的器件,此时任何被寻址的器件均被认为是从器件。在总线上主和从、发和收的关系不是恒定的,而取决于此时数据传送方向。如果主机要发送数据给从器件,则主机首先寻址从器件,然后主动发送数据至从器件,最后由主机终止数据传送;如果主机要接收从器件的数据,首先由主器件寻址从器件。然后主机接收从器件发送的数据,最后由主机终止接收过程。在这种情况下。主机负责产生定时时钟和终止数据传送。

在这里插入图片描述

I2C模块接收和发送数据,并将数据从串行转换成并行,或并行转换成串行。可以开启或禁止中断。接口通过数据引脚(SDA)和时钟引脚(SCL)连接到I2C总线。允许连接到标准(高达100kHz)或快速(高达400kHz)的I2C总线。

注意:IIC是为了与低速设备通信而发明的,所以IIC的传输速率比不上SPI

3.I2C特点

● 并行总线/I2C 总线协议转换器
● 多主机功能:同一接口既可做主设备也可做从设备
● I2C 主设备功能
− 产生时钟
− 产生起始和停止信号
● I2C 从设备功能
− 可编程的 I2C 地址检测
− 可响应 2 个从地址的双地址能力
− 停止位检测
● 产生和检测 7 位/10 位地址和广播呼叫
● 支持不同的通讯速度
− 标准速度(高至 100 kHz)
− 快速(高至 400 kHz)
● 状态标志:
− 发送器/接收器模式标志
− 字节发送结束标志
− I2C 总线忙标志
● 错误标志
− 主模式时的仲裁丢失
− 地址/数据传输后的应答(ACK)错误
− 检测到起始和停止错位
− 禁止拉长时钟功能后的上溢或下溢
● 2 个中断向量
− 1 个中断用于地址/数据通讯成功
− 1 个中断用于出错
● 可选的拉长时钟功能
● 具单字节缓冲器的 DMA
● 可配置的 PEC(信息包错误检测)的产生或校验:
− 发送模式中 PEC 值可以作为最后一个字节传输
− 用于最后一个接收字节的 PEC 错误校验
● 兼容 SMBus 2.0
− 25 ms 时钟低超时延时
− 10 ms 主设备累积时钟低扩展时间
− 25 ms 从设备累积时钟低扩展时间
− 带 ACK 控制的硬件 PEC 产生/校验
− 支持地址分辨协议(ARP)
● 兼容 SMBus

4.I2C模式选择

● 从发送器模式
● 从接收器模式
● 主发送器模式
● 主接收器模式

  • 默认模式为从模式。接口在生成起始条件后自动从从模式切换到主模式;当仲裁 丢失或产生停止信号,则从主模式切换到从模式。允许多主机功能。
  • 主模式时,I2C 接口启动数据传输并产生时钟信号。串行数据传输总是以起始条
    件开始和停止条件结束。主模式时,由软件控制产生起始条件和停止条件。
  • 从模式时,I2C 接口能识别它自己的地址(7 位或 10 位)和广播呼叫地址。软件控 制开启或禁止广播呼叫地址的识别。
  • 数据和地址按 8 位/字节进行传输,高位在前。跟在起始条件后的第一、二个字节
    是地址(7 位模式为 1 个字节,10 位模式为 2 个字节)。地址只在主模式发送。
  • 在一个字节传输的 8 个时钟后的第 9 个时钟期间,接收器必须回送一个应答位 (ACK)给发送器。

参考下图

在这里插入图片描述

软件可以开启或禁止应答(ACK),I2C 接口的地址(7 位、10 位地址或广播呼叫地
址)可通过软件设置。
I2C接口的功能框图

在这里插入图片描述

5.软件I2C和硬件I2C

硬件I2C的效率要远高于软件的,而软件I2C由于不受管脚限制,接口比较灵活。

  • 软件I2C:软件IIC通信指的是用单片机的两个I/O端口模拟出来的IIC,用软件控制管脚状态以模拟I2C通信波形,软件模拟寄存器的工作方式。
    直接使用 CPU 内核按照 I2C 协议的要求控制 GPIO 输出高低电平,从而模拟I2C。

  • 硬件I2C:一块硬件电路,硬件I2C对应芯片上的I2C外设,有相应I2C驱动电路,其所使用的I2C管脚也是专用的,硬件(固件)I2C是直接调用内部寄存器进行配置。
    直接利用 STM32 芯片中的硬件 I2C 外设。

二、串口输出温湿度传感器的数据

1.核心代码分析

  • AHT20芯片的使用过程read_AHT20_once函数:

代码如下

void  read_AHT20_once(void)
{
	delay_ms(10);

	reset_AHT20();//重置AHT20芯片
	delay_ms(10);

	init_AHT20();//初始化AHT20芯片
	delay_ms(10);

	startMeasure_AHT20();//开始测试AHT20芯片
	delay_ms(80);

	read_AHT20();//读取AHT20采集的到的数据
	delay_ms(5);
}
  • AHT20芯片读取数据 read_AHT20函数

代码如下

void read_AHT20(void)
{
	uint8_t   i;

	for(i=0; i<6; i++)
	{
		readByte[i]=0;
	}
	I2C_Start();//I2C启动

	I2C_WriteByte(0x71);//I2C写数据
	ack_status = Receive_ACK();//收到的应答信息
	readByte[0]= I2C_ReadByte();//I2C读取数据
	Send_ACK();//发送应答信息

	readByte[1]= I2C_ReadByte();
	Send_ACK();

	readByte[2]= I2C_ReadByte();
	Send_ACK();

	readByte[3]= I2C_ReadByte();
	Send_ACK();

	readByte[4]= I2C_ReadByte();
	Send_ACK();

	readByte[5]= I2C_ReadByte();
	SendNot_Ack();
	//Send_ACK();

	I2C_Stop();//I2C停止函数
	//判断读取到的第一个字节是不是0x08,0x08是该芯片读取流程中规定的,如果读取过程没有问题,就对读到的数据进行相应的处理
	if( (readByte[0] & 0x68) == 0x08 )
	{
		H1 = readByte[1];
		H1 = (H1<<8) | readByte[2];
		H1 = (H1<<8) | readByte[3];
		H1 = H1>>4;

		H1 = (H1*1000)/1024/1024;

		T1 = readByte[3];
		T1 = T1 & 0x0000000F;
		T1 = (T1<<8) | readByte[4];
		T1 = (T1<<8) | readByte[5];

		T1 = (T1*2000)/1024/1024 - 500;

		AHT20_OutData[0] = (H1>>8) & 0x000000FF;
		AHT20_OutData[1] = H1 & 0x000000FF;

		AHT20_OutData[2] = (T1>>8) & 0x000000FF;
		AHT20_OutData[3] = T1 & 0x000000FF;
	}
	else
	{
		AHT20_OutData[0] = 0xFF;
		AHT20_OutData[1] = 0xFF;

		AHT20_OutData[2] = 0xFF;
		AHT20_OutData[3] = 0xFF;
		printf("读取失败!!!");

	}
	printf("\r\n");
	//根据AHT20芯片中,温度和湿度的计算公式,得到最终的结果,通过串口显示
	printf("温度:%d%d.%d",T1/100,(T1/10)%10,T1%10);
	printf("湿度:%d%d.%d",H1/100,(H1/10)%10,H1%10);
	printf("\r\n");
}

完整代码可从我的gitee网址下载:
https://gitee.com/caidongqi/embedded-system-development/tree/master/AHT20

2.硬件实操连接

2.1 USB转TTL

3v3—3v3,GND—GND,RXD—A9,TXD—A10

2.2 温湿度传感器

在这里插入图片描述

SDA和PB7,SCL和PB6连接
注意正反面,1接3v3,3接GND,不要接反,否则直接芯片g!

3.最终结果演示

  1. 打开Flymcu进行烧录

在这里插入图片描述

  1. 打开串口调试助手
    在这里插入图片描述
    在这里插入图片描述

  2. 结果演示

AHT20


总结

本篇博客主要简略介绍了I2C总线通信协议,使用STM32F103完成基于I2C协议的AHT20温湿度传感器的数据采集,并将采集的温度-湿度值通过串口输出。而且并对硬件I2C和软件I2C进行了一个简短介绍。
此次实操过程中,我发现了许多问题,代码烧录进去后,串口调试后却发现从温湿度传出来的温度-湿度都为0,结果经老师提醒发现可能是由于电压不够的情况,最好给予5伏左右的电压。且要注意连线时候的接触不良情况,有时会导致不能烧录,有时候烧录成功也不能运行。
希望大家多多给出意见,欢迎交流!

参考: https://blog.csdn.net/qq_43279579/article/details/111597278
https://blog.csdn.net/qq_46467126/article/details/121436790?spm=1001.2014.3001.5502

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐