stm32通过I2C接口实现温湿度(AHT20)的采集

2023-11-05

一、I2C总线协议详解

(一)I2C总线物理拓扑结构

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

(二)I2C总线协议

I2C协议规定,总线上数据的传输必须以一个起始信号作为开始条件,以一个结束信号作为传输的停止条件。起始和结束信号总是由主设备产生。总线在空闲状态 时,SCL和SDA都保持着高电平,当SCL为高电平而SDA由高到低的跳变,表示产生一个起始条件;当SCL为高而SDA由低到高的跳变,表示产生一个 停止条件。在起始条件产生后,总线处于忙状态,由本次数据传输的主从设备独占,其他I2C器件无法访问总线;而在停止条件产生后,本次数据传输的主从设备 将释放总线,总线再次处于空闲状态。如图所示:
在这里插入图片描述
在了解起始条件和停止条件后,我们再来看看在这个过程中数据的传输是如何进行的。数据传输以字节为单位。主设备在SCL线上产生每个 时钟脉冲的过程中将在SDA线上传输一个数据位,当一个字节按数据位从高位到低位的顺序传输完后,紧接着从设备将拉低SDA线,回传给主设备一个应答位, 此时才认为一个字节真正的被传输完成。当然,并不是所有的字节传输都必须有一个应答位,比如:当从设备不能再接收主设备发送的数据时,从设备将回传一个否 定应答位。数据传输的过程如图所示:
在这里插入图片描述
I2C总线上的每一个设备都对应一个唯一的地址,主从设备之间的数据传输是建立在地址的基础上,也就是说,主设备在传输有效数据之前 要先指定从设备的地址,地址指定的过程和上面数据传输的过程一样,只不过大多数从设备的地址是7位的,然后协议规定再给地址添加一个最低位用来表示接下来 数据传输的方向,0表示主设备向从设备写数据,1表示主设备向从设备读数据。如图所示:

在这里插入图片描述

(三)硬件I2C和模拟I2C

1.硬件I2C

所谓硬件I2C对应芯片上的I2C外设,有相应I2C驱动电路,其所使用的I2C管脚也是专用的;软件I2C一般是用GPIO管脚,用软件控制管脚状态以模拟I2C通信波形。

2.模拟I2C

模拟I2C 是通过GPIO,软件模拟寄存器的工作方式,而硬件(固件)I2C是直接调用内部寄存器进行配置。如果要从具体硬件上来看,可以去看下芯片手册。因为固件I2C的端口是固定的,所以会有所区别。

3.区别

  • 硬件I2C的效率要远高于软件的,而软件I2C由于不受管脚限制,接口比较灵活。
  • 可以看底层配置,比如IO口配置,如果配置了IO口的功能(IIC功能)那就是固件IIC,否则就是模拟
  • 可以看IIC写函数,看里面有木有调用现成的函数或者给某个寄存器赋值,如果有,则肯定是固件IIC功能,没有的话肯定是数据一个bit一个bit模拟发生送的,肯定用到了循环,则为模拟。
  • 根据代码量判断,模拟的代码量肯定比固件的要大。
  • (1)硬件IIC用法比较复杂,模拟IIC的流程更清楚一些。

  • (2) 硬件IIC速度比模拟快,并且可以用DMA

  • (3)模拟IIC可以在任何管脚上,而硬件只能在固定管脚上。

软件i2c是程序员使用程序控制SCL,SDA线输出高低电平,模拟i2c协议的时序。一般较硬件i2c稳定,但是程序较为繁琐,但不难。

硬件i2c程序员只要调用i2c的控制函数即可,不用直接的去控制SCL,SDA高低电平的输出。但是有些单片机的硬件i2c不太稳定,调试问题较多。

二、实现AHT20采集程序

(一)了解AHT20芯片的相关信息

具体信息请到官方下载对应产品介绍文档,资料链接如下
http://www.aosong.com/class-36.html

(二)具体代码添加过程

在野火提供的示例代码中,打开一个只包含固件库的空项目。向工程中添加相关代码,添加代码的具体内容请参考下面链接:
https://blog.csdn.net/hhhhhh277523/article/details/111397514

(三)主要代码的分析

1.AHT20芯片的使用过程

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

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

(四)线路接法

温湿度传感器接法 由于本程序采用的软件I2C实现的,采用GPIO引脚是PB6,PB7。具体定义代码如下
#define SDA_IN() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}
#define IIC_SCL PBout(6) //SCL
#define IIC_SDA PBout(7) //SDA
#define READ_SDA PBin(7) 所以,SCL连接PB6,SDA连接PB7。 如果采用硬件I2C进行实现,可以查看关于STM32的原理图,可以看到硬件I2C接口,野火stm32mini开发板的I2C接口是PA2,PA3,要实现硬件I2C读取数据,就根据上面使用的方式进行配置,就可以完成通讯

在这里插入图片描述

(五)运行结果

在这里插入图片描述

三、温湿度采集——OLED显示

(一)OLED具体内容请参考

OLED接法

(二)添加显示温湿度的代码

void read_AHT20(void)
{
	uint8_t   i;
	for(i=0; i<6; i++)
	{
		readByte[i]=0;
	}

	//-------------
	I2C_Start();

	I2C_WriteByte(0x71);
	ack_status = Receive_ACK();
	readByte[0]= I2C_ReadByte();
	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();

	//--------------
	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("lyy");

	}
	/*通过串口显示采集得到的温湿度
	printf("\r\n");
	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");*/
	t=T1/10;
	t1=T1%10;
	a=(float)(t+t1*0.1);
	h=H1/10;
	h1=H1%10;
	b=(float)(h+h1*0.1);
	sprintf(strTemp,"%.1f",a);   //调用Sprintf函数把DHT11的温度数据格式化到字符串数组变量strTemp中  
    sprintf(strHumi,"%.1f",b);    //调用Sprintf函数把DHT11的湿度数据格式化到字符串数组变量strHumi中  
	GUI_ShowCHinese(16,00,16,"温湿度显示",1);
	GUI_ShowCHinese(16,20,16,"温度",1);
	GUI_ShowString(53,20,strTemp,16,1);
	GUI_ShowCHinese(16,38,16,"湿度",1);
	GUI_ShowString(53,38,strHumi,16,1);
	delay_ms(1500);		
	delay_ms(1500);
}

(三)汉字点阵

在这里插入图片描述

(四)main函数调用

#include "delay.h"
#include "usart.h"
#include "bsp_i2c.h"
#include "sys.h"

#include "oled.h"
#include "gui.h"
#include "test.h"

int main(void)
{	
	delay_init();	    	       //延时函数初始化    	  
	uart_init(115200);	 
	IIC_Init();
		  
	NVIC_Configuration(); 	   //设置NVIC中断分组2:2位抢占优先级,2位响应优先级 	
	OLED_Init();			         //初始化OLED  
	OLED_Clear(0); 
	while(1)
	{
		//printf("温度湿度显示");
		read_AHT20_once();
		OLED_Clear(0); 
		delay_ms(1500);
  }
}

(五)烧录运行结果

在这里插入图片描述

四、总结

本次实验了解了I2C总线协议的具体内容、了解了硬件I2C和模拟I2C的主要区别,硬件I2C的效率要远高于软件的,而软件I2C由于不受管脚限制,接口比较灵活。学会了如何用stm32实现用实现温湿度的测量。

五、参考资料

stm32通过I2C接口实现温湿度(AHT20)的采集
硬件IIC和软件IIC区别
基于STM32的温湿度采集——OLED显示

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

stm32通过I2C接口实现温湿度(AHT20)的采集 的相关文章

  • 行为树的原理及实现

    查阅了一些行为树资料 目前最主要是参考了这篇文章 看完后感觉行为树实乃强大 绝对是替代状态机的不二之选 但从理论看起来很简单的行为树 真正着手起来却发现很多细节无从下手 总结起来 就是 1 行为树只是单纯的一棵决策树 还是决策 控制树 为了
  • 如何管理技术团队?我的 6 个建议

    我工作近 10 年 是程序员出身 有大概 5 年的管理经验 最多管理过 40 人的技术团队 本文是个人的一些观点和建议 以及这些年的一点感悟 希望对于管理人员 特别是中层管理者有点用处 管理技术团队 其实也是管理的一种 我个人认为 管理能力

随机推荐

  • ms08-067漏洞复现

    文章目录 ms08 067简介 复现 实验环境 漏洞利用 ms08 067简介 Windows Server服务RPC请求缓冲区溢出漏洞 MS08 067 漏洞类别 远程溢出 CVE ID 2008 4250 漏洞详情 MicrosoftW
  • 更改软件计算机无法启动怎么办,无法开机:windows未能启动,原因可能是最近更改了硬件或软件...

    win7系统 电脑无法启动 屏幕提示 windows未能启动 原因可能是最近更改了硬件或软件 这个问题我电脑出现过一模一样的 不用从装系统 简单一步就能开机 1 开机出现第一个页面 就是这个图片这样按F8 进入安全模式 2 然后就是这个页面
  • QT-------UI基础到进阶,干货满满!!!

    目录 一 UI基础 1 QWidget类 掌握 2 添加子组件 掌握 3 样式表 熟悉 二 UI进阶 1 Designer 设计师 掌握 2 布局 Layout 掌握 3 QWidget属性 掌握 4 UI指针 掌握 5 基础组件 熟悉 5
  • 云服务器配置环境Linux初学常用命令以及操作步骤

    云服务器Linux初学常用命令 ls 查看此目录下所有文件夹的名称 cd 返回上一个文件夹 cd 返归根目录 cd file 查看指定的文件夹 file是你自己指定的文件夹的名称 tar zxvf file 解压你指定的gz包 file是你
  • layui 日期范围选择

    layui时间范围选择 相信很多时候项目中会遇到时间范围选择 废话不多说上图 上代码 div class layui inline div class layui input inline style width 160px div div
  • “数字孪生城市”的概念,你知道多少?

    随着大数据时代的到来以及互联网 云计算 物联网 人工智能技术等新一代先进信息技术的发展 近年来陆续诞生了数字城市 智慧城市以及数字孪生城市等各种 新型城市 概念 数字城市是随着1998年美国前副总统阿尔 戈尔提出 数字地球 之后而产生的概念
  • W25Q256学习

    一 基本特性 容量256Mb 最小的组织单位是页每个页256个字节 可进行页编程 一次写256个字节 16个页组成4KB的扇区 可进行扇区擦除 128个扇区组成32KB块 64KB的组 可以整片擦除 256有8192个扇区和512个块 25
  • 在 Web.config 中,配置允许多个指定的域名进行跨域访问

    一般来说 如果是要允许跨域访问 最简单的设置 就是在 Web config 中 将 Access Control Allow Origin 设置为 即可 如下所示
  • 谈谈初级软件测试工程师具备的知识与技能

    什么是软件测试 软件测试的经典定义是 在规定的条件下对程序进行操作 以发现程序错误 衡量软件品质 并对其是否能满足设计要求进行评估的过程 软件测试的现实定义是 软件测试是贯穿整个软件开发生命周期 对软件产品 包括阶段性产品 进行验证和确认的
  • 【OpenHarmony】L1 烧录的启动参数

    OpenHarmony L1 烧录的启动参数 启动参数 linux liteos a uboot位置 linux liteos a和linux共用 启动参数 linux setenv bootargs mem 128M console tt
  • Portscan一款局域网端口扫描器

    Portscan是一款局域网端口扫描器 可以用于扫描目的主机的开放端口 并猜测目的主机的操作系统 支持Edge Wi Fi和3G网络 打开PortScan软件后默认会帮你填好超始IP及端口号 结束IP可以自已根据需求填写好 然后扫描即可 它
  • 控制台I/O显示格式化的结果

    不经常使用Console WriteLine 所以记录下所有的格式化的写法 以供分享 1 格式字符串 不考虑大小写 除了e E C 货币格式 C2 货币格式 精度为两位小数 eg 73 23 D 十进制格式 E 科学计数法 System C
  • Java入门-向下转型的安全判断

    向下转型的安全判断 向下转型的安全判断使用原因 多态实现了引用类型的向上转型 我们也可以进行向下转型 但是向下转型不一定是安全的 要先进行安全判断 只有父引用原本指向的类型和与向下转型的类型一致 才能转 因此我们需要进行向下转型的安全判断
  • SpringBoot 项目打成 .exe 程序

    https mp weixin qq com s XmNYqyZeY 1gSBxpAX4TRQ
  • 抖音设计系统Semi Design:解构、原理与实现

    摘要 本文将深入探讨抖音设计系统Semi Design 阐述其定义 分析其原理 并通过详细代码展示其实现方法 本文旨在为设计师 开发人员和相关领域的研究者提供有关Semi Design的深入理解和实用指南 引言 抖音 作为一款全球流行的短视
  • Vue+style 动态样式绑定(收藏图标)

    主要代码 0 未收藏 1 已收藏
  • 函数隐藏和函数覆盖

    函数隐藏和函数覆盖 1 函数隐藏 派生类中函数具有与基类同名的函数 参数列表不一定相同 从而派生类中隐藏了基类的同名函数 2 函数覆盖 定义 派生类中函数将基类中的函数覆盖的情况称为函数覆盖 条件 1 基类是虚函数 2 发生覆盖的两个函数分
  • static与const的区别

    一 static主要有三个作用 1 修饰局部变量 成为静态局部变量 2 修饰全局变量 成为静态全局变量 3 修饰函数 成为静态函数 1 修饰局部变量 成为静态局部变量 没有加static的情况 如果加了static会有什么变化呢 栈区 存放
  • iOS完整学习路线图

    今晚特地花时间整理出了iOS的完整学习路线图 希望对大家有帮助 FROM http blog csdn net q199109106q article details 8596506
  • stm32通过I2C接口实现温湿度(AHT20)的采集

    stm32通过I2C接口实现温湿度 AHT20 的采集 一 I2C总线协议详解 一 I2C总线物理拓扑结构 二 I2C总线协议 三 硬件I2C和模拟I2C 1 硬件I2C 2 模拟I2C 3 区别 二 实现AHT20采集程序 一 了解AHT