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

一、I2C简介

IC( Inter-- Integrated Circuit)总线是一种由 PHILIPS公司开发的两线式串行总线,用于连接微控制器及其外围设备。它是由数据线SDA和时钟SCL构成的串行总线,可发送和接收数据。
在CPU与被控I2C之间、I2C与I2C之间进行双向传送,高速IC总线一般可达400kbps以上。 I2C总线在传送数据过程中共有三种类型信号,它们分别是:开始信号、结束信号和应答信号。

开始信号:SCL为高电平时,SDA由高电平向低电平跳变,开始传送数据。
结束信号:SCL为高电平时,SDA由低电平向高电平跳变,结東传送数据。
应答信号:接收数据的IC在接收到8bit数据后,向发送数据的IC发出特定的低电平脉冲表示已收到数据。CPU向受控单元发出一个信号后,等待受控单元发出一个应答信号,CPU接收到应答信号后,根据实际情况作出是否继续传递信号的判断。若未收到应答信号,由判断为 受控单元出现故障。

这些信号中,起始信号是必需的,结束信号和应答信号,都可以不要。
stm32(正点原子)的SLC和SDA的连接如下:
在这里插入图片描述
I2C 通讯协议(Inter-Integrated Circuit)是由 Phiilps公司开发的,由于它引脚少,硬件实 现简单,可扩展性强,不需要 USART、CAN 等通讯协议的外部收发设备,现在被广泛地 使用在系统内多个集成电路(IC)间的通讯。

在计算机科学里,大部分复杂的问题都可以通过分层来简化。如芯片被分为内核层和 片上外设;STM32 标准库则是在寄存器与用户代码之间的软件层。对于通讯协议,我们也 以分层的方式来理解,最基本的是把它分为物理层和协议层。物理层规定通讯系统中具有机械、电子功能部分的特性,确保原始数据在物理媒体的传输。协议层主要规定通讯逻辑,统一收发双方的数据打包、解包标准。简单来说物理层规定我们用嘴巴还是用肢体来交流,协议层则规定我们用中文还是英文来交流。

I2C 物理层
(1) 它是一个支持设备的总线。“总线”指多个设备共用的信号线。在一个 I2C 通讯总线 中,可连接多个 I2C 通讯设备,支持多个通讯主机及多个通讯从机。

(2) 一个 I2C 总线只使用两条总线线路,一条双向串行数据线(SDA) ,一条串行时钟线 (SCL)。数据线即用来表示数据,时钟线用于数据收发同步。

(3) 每个连接到总线的设备都有一个独立的地址,主机可以利用这个地址进行不同设备之 间的访问。

(4) 总线通过上拉电阻接到电源。当 I2C 设备空闲时,会输出高阻态,而当所有设备都空 闲,都输出高阻态时,由上拉电阻把总线拉成高电平。

(5) 多个主机同时使用总线时,为了防止数据冲突,会利用仲裁方式决定由哪个设备占用 总线。

扫描二维码关注公众号,回复: 12684403 查看本文章

(6) 具有三种传输模式:标准模式传输速率为 100kbit/s ,快速模式为 400kbit/s,高速模式 下可达 3.4Mbit/s,但目前大多 I2C设备尚不支持高速模式。

(7) 连接到相同总线的 IC 数量受到总线的最大电容 400pF 限制。

I2C 协议层
I2C 的协议定义了通讯的起始和停止信号、数据有效性、响应、仲裁、时钟同步和地址广播等环节

①通讯的起始和停止信号
当 SCL 线是高电 平时 SDA 线从高电平向低电平切换,这个情况表示通讯的起始。当 SCL 是高电平时 SDA 线由低电平向高电平切换,表示通讯的停止。起始和停止信号一般由主机产生。

②数据传输
(1) 起始信号后,总线上所有的从机开始等待主机紧接下来的从机地址广播。因为总线上每个设备的地址都是唯一的,当主机广播的地址与某个设备地址相同时,该设备就被选中,并向主机发出应答(ACK)或者非应答(NACK),主机只有在接收到应答信号后继续发送/接收数据,没选中的设备将会忽略之后的数据信号。根据I2C协议,从机地址可以是7位或者10位。

(2) I2C总线上传输的数据包括上述的地址信号,又包括真正的数据信号。在起始信号后需传送一个从机地址(7位),第8位是数据的传输方向(接收/发送),“0”表示主机发送数据,“1”表示主机接收数据。每次数据的传输总是由主机产生结束信号以结束传输,但若主机希望继续占用总线进行新的数据传输时,则可以不产生结束信号,而是再次发送起始信号对另一从机地址寻址。

(3) 若配置为写数据方向,主机开始向从机传输数据,数据包大小为8位,主机每发送完1字节数据都有等到从机的应答信号(ACK),多字节数据发送时重复此过程。传输结束后,主机向从机发送一个停止信号表不再传输数据。

(4) 若配置为读方向,从机开始向主机返回数据,数据包大小还是8位。同理,从机每发送完一字节数据都要等到主机的应答信号(ACK),重复此过程可以返回多个数据。当主机希望停止接收数据时就向返回一个非应答信号(NACK),数据传输将结束。

(5) 实际I2C通讯采用的是读写复合的格式。传输过程中主机需要发出2次起始信号:第一次传输主机通过从机地址找到从机设备,发送一段数据,这个数据是从设备内部寄存器或者存储器地址;第二次传输是对该地址进行读/写。主机要读取从机数据时,主机会释放对SDA总线的控制,由从机控制SDA总线,主机负责接收信号;主机要向从机设备写数据时,SDA由主机控制,从机负责接收信号。

二、硬件I2C与软件I2C

硬件I2C

硬件I2C对应芯片上的I2C外设,有相应I2C驱动电路,其所使用的I2C管脚也是专用的

软件I2C

软件I2C一般是用GPIO管脚,用软件控制管脚状态以模拟I2C通信波形

硬件I2C的效率要远高于软件的,而软件I2C由于不受管脚限制,接口比较灵活
模拟I2C
是通过GPIO,软件模拟寄存器的工作方式,而硬件(固件)I2C是直接调用内部寄存器进行配置。如果要从具体硬件上来看,可以去看下芯片手册。因为固件I2C的端口是固定的,所以会有所区别。

区分他们:

可以看底层配置,比如IO口配置,如果配置了IO口的功能(IIC功能)那就是固件IIC
可以看IIC写函数,看里面有木有调用现成的函数或者给某个寄存器赋值,如果有,则肯定是固件IIC功能,没有的话肯定是数据一个bit一个bit模拟发生送的,肯定用到了循环,则为模拟。
根据代码量判断,模拟的代码量肯定比固件的要大。

三、实现I2CAHT20温湿度传感器的数据采集

1、AHT20简介
AHT20是国内奥松生成的I2C接口的MEMS温湿度传感器,ADC位数为20Bit,具有体积小、精度高、成本低等优点。

由于AHT10/15/20 具有国产化、体积小、精度高、成本低等特点,可以替代 DHT11/DHT12/AM2320/SHT20/SHT30,单芯片价格在¥2~3,体积小巧很轻松嵌入到产品上

2、配置函数库,编写函数
参考 正点原子STM32开发板第27章 IIC实验

step0:驱动代码(官网下载),下载AHT20.c和AHT20.h,官网都有,另外最重要的还是I2C可以参考原子的代码在myiic下就是关于i2c的代码。

对于正点原子的精英版,其SCL和SDL分别对应的就是PB6和PB7,我们用普通IO口来模拟I2C的功能,来实现功能。
在这里插入图片描述
**第一步:**用例程原子I2C例程,例程需要改动,这里不做详细说明了。基本函数库的基本框架不用变,因为做的串口通信,所以就不需要lcd与key的系列函数了,并且加入我们的代码。

这里你可以把上面的两个代码复制在HARDWARE问件夹下

点击manage project items 在HARDWRE下加入上面.c文件。
在这里插入图片描述

然后点击魔术棒,C/C++,路径添加AHT20文件夹
在这里插入图片描述
第二步: 编写主函数

1、检测AHT20是否采集到数据,如果采到就处理数据

2、根据如下两个公式

c1 = AHT20.HT[0]10010/1024/1024; //湿度
t1 = AHT20.HT[1]20010/1024/1024-500;//温度计算公式

来计算得出温度。

3、通过指示灯翻转标识正常工作

4、AHT20函数中,有定义结构体,根据结构体来得到相关值

下面是主函数:

#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"
#include "usmart.h"	 
#include "24cxx.h"	 
#include "AHT20.h"
/****my code start lee***/		 	
struct m_AHT20 AHT20;
int main(void)
{
    
    
	volatile int  c1,t1;
	float c2,t2;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置中断优先级
	LED_Init();									//初始化LED
	delay_init();	    				//延时初始化
	IIC_Init();							//IIC初始化
  uart_init(115200);	 //串口初始化为115200
	AHT20.alive=!AHT20_Init();	        //AHT20初始化
 
	while(1)
	{
    
    
		if(AHT20.alive)//是否存活
		{
    
    
			//读取其原始数据
			AHT20.flag = AHT20_ReadHT(AHT20.HT);
			c1 = AHT20.HT[0]*100*10/1024/1024;  //湿度
			t1 = AHT20.HT[1]*200*10/1024/1024-500;//温度计算公式
			//结果都放大了10倍
			c2=c1/10.0;
			t2=t1/10.0;
			printf("湿度:\r\n%f\r\n",c2);
			printf("温度:\r\n%f\r\n\r\n",t2);
			//正常工作双灯翻转
			LED0=!LED0;
			LED1=!LED1;
		}
		delay_ms(2000);
		
	}
}

第三步: 编译连接,烧入程序

3、最终结果展示
在这里插入图片描述

四、总结

这次实验让我学会了如何使用I2C,对我有很大帮助。

猜你喜欢

转载自blog.csdn.net/lyjccchong/article/details/111568039