【嵌入式系统开发17】理解I2C总线通信协议,STM32F103下基于I2C协议的AHT20温湿度传感器的数据采集并进行串口输出

本文目的是主要介绍通过STM32F103C8T6学习I2C总线通信协议,并使用STM32F103完成基于I2C协议的AHT20温湿度传感器的数据采集,并将采集的温度-湿度值通过串口输出。


前言

※ I2C总线通信协议详解,可参考博客进行学习:https://blog.csdn.net/Michael177/article/details/121483139
本文主要讲解I2C总线通信协议,并使用STM32F103完成基于I2C协议的AHT20温湿度传感器的数据采集,并将采集的温度-湿度值通过串口输出。
在这里插入图片描述他日若是金榜题名,不忘一路艰难困苦在这里插入图片描述


(一)需求分析

解释什么是“软件I2C”和“硬件I2C”?
阅读AHT20数据手册,编程实现:每隔2秒钟采集一次温湿度数据,并通过串口发送到上位机(win10)。
所需工具:

1、芯片: STM32F103C8T6
2、STM32CubeMx软件
3、IDE: MDK-Keil软件
4、STM32F1xx/STM32F4xxHAL库
5、AHT20


(二)I2C总线通信协议介绍

1.I2C的前生今世

● (Inter-Integrated Circuit),是一种同步、多主、多从、分组交换、单端、串行计算机总线,由飞利浦半导体(现在的 NXP 半导体)在 1982 年发明。它广泛用于在短距离、板内通信中将低速外设集成电路附加到处理器和微控制器上。 也可以写成 I2C 或 IIC。
● 自 2006 年 10 月 10 日起,实施 I2C 协议不需要任何许可费用。但是,获得恩智浦分配的 I2C 从设备地址则需要付费。一些竞争者如西门子(后来的英飞凌技术,现在的英特尔移动通信)、NEC、德州仪器 TI、意法半导体(以前的 SGS-Thomson)、摩托罗拉(后来的飞思卡尔,现在与 NXP 合并)、Nordic 半导体和 Intersil,自 20 世纪 90 年代中期以来已经陆续发布了很多兼容的 I2C 标准的芯片。
● 说到总线,其种类很多,但其目的基本一致,就是一个用于传递信息的公共干线。如芯片内部地址总线、数据总线其对象可能为CPU核与各外设(RAM/ROM/外设控制器电路等);芯片级总线I2C,SPI等,设备级总线如RS422/RS485/HART/CAN/Ethernet/Fieldbus......
在这里插入图片描述

2.I2C简介

● 在消费电子,工业电子等领域,会使用各种类型的芯片,如微控制器,电源管理,显示驱动,传感器,存储器,转换器等,他们有着不同的功能,有时需要快速的进行数据的交互,为了使用最简单的方式使这些芯片互联互通,于是I2C诞生了,I2C(Inter-Integrated Circuit)是一种通用的总线协议。它是由Philips(飞利浦)公司,现NXP(恩智浦)半导体开发的一种简单的双向两线制总线协议标准。
● 对于硬件设计人员来说,只需要2个管脚,极少的连接线和面积,就可以实现芯片间的通讯,对于软件开发者来说,可以使用同一个I2C驱动库,来实现实现不同器件的驱动,大大减少了软件的开发时间。极低的工作电流,降低了系统的功耗,完善的应答机制大大增强通讯的可靠性。
在这里插入图片描述

2.1 I2C的特性

● I2C的特性如下:

1、双向的同步串行总线
2、支持设备之间的短距离通信
3、标准通信速率:100Kbps 快速模式:400Kbps 高速模式:3.4Mbps
4、各个设备之间的SCL和SDA线都是线与关系
5、扩展的器件的数量主要由电容负载来决定,其负载能力为400pF
6、具有极低的电流消耗

2.2 I2C总线的物理层

● 由于SDA、SCL为漏极开路结构(OD),因此它们必须接有上拉电阻,阻值的大小常为 1k8、4k7、10k,但1k8时性能最好。则在总线空闲时,两根线均为高电平。I2C总线的上拉电阻的阻值要精心考虑,如果上拉电阻的阻值太大,则由于I2C设备输入端的输入电容的存在,会造成信号上升沿和下降沿变缓,以至于不能满足I2C设备的建立时间和保持时间,造成通信的错误发生;如果上拉电阻的阻值过小,则会造成较大的功率损耗。因此I2C通信的上拉电阻的阻值要满足设备上升沿和下降沿要求的同时尽量选择较大的阻值,以降低消耗的功耗问题。
在这里插入图片描述

3.I2C标准协议

3.1 I2C的位传输

● 数据传输:SCL为高电平时,SDA线若保持稳定,那么SDA传输数据bit
● 数据改变:SCL为低电平时,SDA线才能改变传输bit
在这里插入图片描述
① 开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。
② 结束信号:SCL为高电平时,SDA由低电平向高电平跳变,结束传送数据。
在这里插入图片描述
应答信号
① Master每发送完8bit数据后等待Slave的ACK
② 即在第9个clock,若从IC发出ACK,SDA会被拉低。
③ 若没有ACK,SDA会被置高,这会引起Master发生RESTART或STOP流程

3.2 I2C总线协议

在这里插入图片描述
● 小结整体时序:串行协议,多主机模式。(注:主端必须是带有CPU的逻辑模块,在同一总线上同一时刻使能有一个主端,可以有多个从端)

1、起始信号:SCL为高电平时,SDA下降沿,主机发送;
2、停止信号:SCL为高电平时,SDA上升沿,主机发出;
3、数据与地址按8位/字节传输,高位在前;
4、传输过程中,SCL为低电平时,SDA更改状态,SCL为高电平时,SDA状态需稳定;
5、每传输一个字节,接收器必须回应1个应答位(ACK)给发送器

4.I2C通信工程

● 主机发送起始信号启用总线
● 主机发送一个字节数据指明从机地址和后续字节的传送方向
● 被寻址的从机发送应答信号回应主机
● 发送器发送一个字节数据
● 接收器发送应答信号回应发送器
● … (循环步骤4、5)
● 通信完成后主机发送停止信号释放总线
● 第4步和第5步用的是发送器和接收器,不是主机和从机,这是由第一个字节的最后一位决定主给从发,还是从给主发。
也就是说,第一个字节和最后的停止信号一定是主机发给从机,但中间就不一定了。
发送数据过程中不允许改变发送方向(除非重启一次通信,详见后文典型I2C时序(3)部分)。

5.字节传送与应答

※ I2C总线通信时每个字节为8位长度,数据传送时,先传送最高位,后传送低位,发送器发送完一个字节数据后接收器必须发送1位应答位来回应发送器,即一帧共有9位。
注意:I2C每次发送数据必须是8位。 MSB固定,先发高位,再发低位。
在这里插入图片描述

6.I2C同步数据信号

🎈 I2C总线在进行数据传送时,时钟线SCL为低电平期间发送器向数据线上发送一位数据,在此期间数据线上的信号允许发生变化,时钟线SCL为高电平期间接收器从数据线上读取一位数据,在此期间数据线上的信号不允许发生变化,必须保持稳定。
在这里插入图片描述

7.I2C时钟同步与仲裁

7.1 时钟同步

🎈 时钟同步是通过I2C总线上的SCL之间的线“与”(wire-AND)来完成的,即如果有多个主机同时产生时钟,那么只有所有master都发送高电平时,SCL上才表现为高电平,否则SCL都表现为低电平。
在这里插入图片描述

7.2 仲裁

🎈 总线仲裁与时钟同步类似,当所有主机在SDA上都写1时,SDA的数据才是1,只要有一个主机写0,那此时SDA上的数据就是0.
🎈 一个主机每发送一个bit数据,在SCL为高电平时,就检查SDA的电平是否和发送的数据一致,如果不一致,这个主机便知道自己输掉了仲裁,然后停止向SDA写数据。也就是说,如果主机一致检查到总线上数据和自己发送的数据一致,则继续传输,这样在仲裁过程中就保证了赢得仲裁的master不会丢失数据。
🎈 输掉仲裁的主机在检测到自己输了之后也就不再产生时钟脉冲,并且要在总线空闲时才能重新传输。
🎈 仲裁的过程可能要经过多个bit的发送和检查,实际上两个主机如果发送的时序和数据完全一样,则两个主机都能正常完成整个数据传输。
在这里插入图片描述
注意:多个主机仲裁时,因为线“与”特性,谁低谁能强制SDA为低,也就是跟自己匹配,所以先高(高电平1)的那个就会仲裁失败。

8.典型I2C时序

🎈 主机向从机发送数据。
在这里插入图片描述
🎈 从机向主机发送数据。
在这里插入图片描述
🎈 主机先向从机发送数据,然后从机再向主机发送数据。
在这里插入图片描述
注:S:起始信号,A:应答信号,A非表示非应答,P:终止信号

A、阴影部分表示数据由主机向从机传送,无阴影部分表示从机向主机发送数据。
B、据传输中间如果想转换发送方向,不用发P停止信号,就不会释放总线,直接再发起始信号。
C、怎么发起始信号,怎么发停止信号,这些都不用关心,由I2C控制器完成,我们使用的时候只需要正确配置控制器相应的寄存器就可以了。

9.软件I2C和硬件I2C

🎈 IIC分为软件IIC硬件IIC
软件IIC 通信指的是用单片机的两个I/O端口模拟出来的IIC,用软件控制管脚状态以模拟I2C通信波形,软件模拟寄存器的工作方式。

直接使用 CPU 内核按照 I2C 协议的要求控制 GPIO 输出高低电平,从而模拟I2C。
使用: 需要在控制产生 I2C 的起始信号时,控制作为SCL 线的 GPIO 引脚输出高电平,然后控制作为 SDA 线的 GPIO 引脚在此期间完成由高电平至低电平的切换,最后再控制SCL线切换为低电平,这样就输出了一个标准的 I2C 起始信号。

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

直接利用 STM32 芯片中的硬件 I2C 外设。
使用: 只要配置好对应的寄存器,外设就会产生标准串口协议的时序。在初始化好 I2C 外设后,只需要把某寄存器位置 1,此时外设就会控制对应的 SCL 及 SDA 线自动产生 I2C 起始信号,不需要内核直接控制引脚的电平。

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


(三)Keil编译程序

1.环境预置

🎈 首先需要将有关温湿度传感器AHT20的资料进行学习。
所需配置:

温湿度传感器AHT20
串口调试助手

了解AHT20芯片的相关信息,具体信息请到官方下载对应产品介绍文档
资料链接:http://www.aosong.com/class-36.html

2.代码编写

🎈 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");
}

3.编译文件

在这里插入图片描述
🎈 发现没有报错


(四)烧录实现

1.AHT20简介

🎈 本次实验SCL-->PB6,SDA-->PB7。
在这里插入图片描述

2.硬件搭建

🎈 硬件电路搭建如下:
在这里插入图片描述

3.打开FlyMcu

在这里插入图片描述

4.效果实现

🎈 温湿度采集实现效果如下,可以发现,当用手捂住AHT20的时候,湿度与温度都会上升。

温湿度


(五)总结

🎈 本文介绍了通过STM32F103C8T6了解I2C总线通信协议,并使用STM32F103完成基于I2C协议的AHT20温湿度传感器的数据采集,并将采集的温度-湿度值通过串口输出。
🎈 本次实验较为简单,只要按部就班即可完成,但需要去细心耐心的学习,温湿度传感器AHT20的学习与使用,其实也挺好玩的,而且可以在很多设计上运用,例如实现温湿度检测,从而来控制蜂鸣器响应,耐心细心便是学习上上策。
想念小时候无忧无虑的自在。
但更加钦佩长大后振翅高飞的勇敢!!

寄语:小时候
   哆啦A梦伴你成长
   长大后
   自请长缨,万夫莫开!


(六)参考文献

[1]https://blog.csdn.net/Michael177/article/details/121483139
[2]https://blog.csdn.net/qq_46467126/article/details/121436790
[3]https://blog.csdn.net/zhangduang_KHKW/article/details/121953275

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值