AHT10原理讲解(I2C驱动)-基于江科大源码开发

ops/2024/10/19 1:35:02/

一、原理图

根据数据手册中的要求(以上两图),可以看出SDA和SCL接主芯片的引脚就可以,但是注意我们在接的过程中,给了两个上拉电阻。

上拉电阻的作用:

  • 提高抗干扰能力:适当的上拉电阻值可以帮助减少外部噪声对信号的影响,增强系统的稳定性。
  • 降低功耗:相对于内部集成的上拉结构,外部选择合适的上拉电阻可以在一定程度上帮助控制整个电路的静态电流消耗。

ADR需要接地,NC就保持悬空,悬空就是保持直接什么也不接就可以。

二、原理介绍

1、启动与停止信号

首先,一个完整的传输序列一定是启动信号开始,停止信号结尾的,无论这个信号要给相应的器件传输何种信号。

启动信号的执行顺序与原理

这里的启动信号确切的说,就是I2C协议中的启动信号,如果大家了解I2C协议的启动原理,这里完全可以跳过,包括下面的停止信号

启动传输状态( S )当 SCL 为高电平时,SDA 由高电平转换为低电平。因此一般在写启动信号时,我们都会先把SCL时钟线和SDA数据线先同时置高位,然后把SDA置低位,这个时候就可以百分百保证是在SCL时钟线高电平期间将SDA置低位,形成了开始信号

/*** 函    数:I2C起始* 参    数:无* 返 回 值:无*/
void MyI2C_Start(void)
{MyI2C_W_SDA(1);							//释放SDA,确保SDA为高电平MyI2C_W_SCL(1);							//释放SCL,确保SCL为高电平MyI2C_W_SDA(0);							//在SCL高电平期间,拉低SDA,产生起始信号MyI2C_W_SCL(0);							//起始后把SCL也拉低,即为了占用总线,也为了方便总线时序的拼接
}

最后将时钟线置低位的作用(强调一下,在正常发送数据期间,当SCL高电平期间,SDA不可以发生跳变,以保证数据稳定,产生启动和停止信号的时候除外)

  • 控制总线:一旦产生起始条件后,主设备需要继续控制总线,防止其他可能成为主设备的节点抢占总线。
  • 同步时序:将SCL拉低可以确保下一个上升沿之前有足够的时间进行数据设置。I²C通信中的每一位数据都是在SCL的上升沿采样的。因此,在发送下一位数据之前,先将SCL保持在低电平状态,可以让发送方有时间改变SDA的状态。
  • 准备传输:它还允许系统准备好接下来的数据位或地址位的发送。通过这种方式,可以确保每次SCL上升沿时,SDA上的数据已经被正确设置了。

停止信号的执行顺序与原理

停止传输状态(P)-当SCL 高电平时,SDA 线上从 低电平转换为高电平。停止状态是由主机控制的一种特殊的 总线状态,指示从机传输结束(Stop 之后,BUS 总线一般被 认为处于闲置状态)。

/*** 函    数:I2C终止* 参    数:无* 返 回 值:无*/
void MyI2C_Stop(void)
{MyI2C_W_SDA(0);							//拉低SDA,确保SDA为低电平MyI2C_W_SCL(1);							//释放SCL,使SCL呈现高电平MyI2C_W_SDA(1);							//在SCL高电平期间,释放SDA,产生终止信号
}

先拉低SDA数据线,拉高时钟线,再拉低数据线,保证绝对产生停止信号

2、发送测量命令函数

将图中所示信息构成中的二进制转化为十六进制分别是0x70、0xAC、0x33、0x00。

/*
*********************************************************************************************************
*	函 数 名: void AHT10_SendAC(void)
*	功能说明: 触发传感器进行测量
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/
void AHT10_SendAC(void)
{MyI2C_Start();MyI2C_SendByte(0x70);MyI2C_ReceiveAck();MyI2C_SendByte(0xAC);MyI2C_ReceiveAck();MyI2C_SendByte(0x33);MyI2C_ReceiveAck();MyI2C_SendByte(0x00);MyI2C_ReceiveAck();MyI2C_Stop();
}

3、软复位函数

这个命令(见表9)用于在无需关闭和再次打 开电源的情况下,重新启动传感器系统。在接 收到这个命令之后,传感器系统开始重新初始 化,并恢复默认设置状态,软复位所需时间不超过20毫秒

/*
*********************************************************************************************************
*	函 数 名: void AHT10_SendBA(void)
*	功能说明: 软复位模块
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/
void AHT10_SendBA(void)
{MyI2C_Start();MyI2C_SendByte(0x70);MyI2C_ReceiveAck();MyI2C_SendByte(0xBA);MyI2C_ReceiveAck();MyI2C_Stop();
}

4、读取检测到的数据

根据上图所示,读取信息的过程应该是发送读信号,写入0x71,这个信号意味着要读取信息了,其中蓝色代表的是从机发过来的数据,第一位字节代表的是状态信息,可以忽略,后面五个字节对半分为湿度和温度的对应的字节

/*
*********************************************************************************************************
*	函 数 名: void AHT10_Read_CTdata(uint32_t *ct) //读取AHT10的温度和湿度数据
*	功能说明: 
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/
void AHT10_Read_CTdata(uint32_t *ct) //读取AHT10的温度和湿度数据
{uint8_t Byte_1th = 0;uint8_t Byte_2th = 0;uint8_t Byte_3th = 0;uint8_t Byte_4th = 0;uint8_t Byte_5th = 0;uint8_t Byte_6th = 0;uint32_t RetuData = 0;uint16_t cnt = 0;AHT10_SendAC(); //向AHT10发送AC指令Delay_ms(75); //等待75mscnt = 0;while(((AHT10_Read_Status()&0x80)==0x80))//等待忙状态结束{Delay_us(1508);if(cnt++>=100){break;}}MyI2C_Start();MyI2C_SendByte(0x71);MyI2C_ReceiveAck();Byte_1th = MyI2C_ReceiveByte();MyI2C_ReceiveAck();Byte_2th = MyI2C_ReceiveByte();MyI2C_ReceiveAck();Byte_3th = MyI2C_ReceiveByte();MyI2C_ReceiveAck();Byte_4th = MyI2C_ReceiveByte();MyI2C_ReceiveAck();Byte_5th = MyI2C_ReceiveByte();MyI2C_ReceiveAck();Byte_6th = MyI2C_ReceiveByte();MyI2C_ReceiveAck();MyI2C_Stop();RetuData = (RetuData|Byte_2th)<<8;RetuData = (RetuData|Byte_3th)<<8;RetuData = (RetuData|Byte_4th);RetuData =RetuData >>4;ct[0] = RetuData;RetuData = 0;RetuData = (RetuData|Byte_4th)<<8;RetuData = (RetuData|Byte_5th)<<8;RetuData = (RetuData|Byte_6th);RetuData = RetuData&0xfffff;ct[1] =RetuData; }

5、AHT10初始化函数

/*
*********************************************************************************************************
*	函 数 名: uint8_t AHT10_Init(void)//初始化AHT10
*	功能说明: AHT10初始化函数
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/uint8_t AHT10_Init(void)//初始化AHT10
{uint16_t count=0;MyI2C_Start();MyI2C_SendByte(0x70);		//进行写操作MyI2C_ReceiveAck();MyI2C_SendByte(0xE1);		//写系统配置寄存器MyI2C_ReceiveAck();MyI2C_SendByte(0x08);		//校准位置1MyI2C_ReceiveAck();MyI2C_SendByte(0x00);MyI2C_ReceiveAck();MyI2C_Stop();Delay_ms(500);while( AHT10_Read_Cal_Enable() == 0)//如果校准位没有置1,就一直初始化{AHT10_SendBA();Delay_ms(100);MyI2C_Start();MyI2C_SendByte(0x70);		//进行写操作MyI2C_ReceiveAck();MyI2C_SendByte(0xE1);		//写系统配置寄存器MyI2C_ReceiveAck();MyI2C_SendByte(0x08);		//校准位置1MyI2C_ReceiveAck();MyI2C_SendByte(0x00);MyI2C_ReceiveAck();MyI2C_Stop();if(count++>=10)return 0;Delay_ms(500);}return 1;}

6、应答位

大家一路看过来,应该发现每段信号的发送都有一个MyI2C_ReceiveAck();不要急,我现在就给大家解释一下这里。

应答位的作用

  1. 确认数据接收:当从设备正确接收到主设备发送的数据字节后,它会通过拉低SDA线来发送一个应答位,表示已经成功接收了数据。
  2. 错误检测:如果从设备没有准备好接收数据或未能识别出其地址,则不会响应应答位,SDA保持高电平(称为NACK, No Acknowledge)。这可以提示主设备存在通信问题,如地址不匹配、从设备忙或未准备好等。
  3. 控制流:在某些情况下,例如读操作期间,主设备也可以发送NACK来通知从设备停止发送更多的数据。

应答时序

  • 在每个数据字节的第9个时钟周期(即最后一个时钟周期),SCL为高时,SDA的状态由接收方决定:
    • 如果是应答(ACK),则SDA会被拉低;
    • 如果是非应答(NACK),则SDA保持高电平。
/*** 函    数:I2C接收应答位* 参    数:无* 返 回 值:接收到的应答位,范围:0~1,0表示应答,1表示非应答*/
uint8_t MyI2C_ReceiveAck(void)
{uint8_t AckBit;							//定义应答位变量MyI2C_W_SDA(1);							//接收前,主机先确保释放SDA,避免干扰从机的数据发送MyI2C_W_SCL(1);							//释放SCL,主机机在SCL高电平期间读取SDAAckBit = MyI2C_R_SDA();					//将应答位存储到变量里MyI2C_W_SCL(0);							//拉低SCL,开始下一个时序模块return AckBit;							//返回定义应答位变量
}

三、源码分享

AHT10.c

#include <stm32f10x.h>
#include "I2C.h"
#include "Delay.h"
#include "uart.h"
#include "SHT10.h"#define AHT10_ADDRESS   0x38		//Sht10的I2C从机地址/*
*********************************************************************************************************
*	函 数 名: uint8_t AHT10_Read_Status(void)
*	功能说明: 读取AHT10状态寄存器
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/
uint8_t AHT10_Read_Status(void)
{uint8_t Byte_first;MyI2C_Start();MyI2C_SendByte(0x71);MyI2C_ReceiveAck();Byte_first = MyI2C_ReceiveByte();MyI2C_Stop();return Byte_first;
}
/*
*********************************************************************************************************
*	函 数 名: uint8_t AHT10_Read_Cal_Enable(void)
*	功能说明: 查询校准使能位有没有使能
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/
uint8_t AHT10_Read_Cal_Enable(void)
{uint8_t val = 0;val = AHT10_Read_Status();if((val & 0x68)==0x08)  //判断NOR模式和校准输出是否有效return 1;else  return 0;
}/*
*********************************************************************************************************
*	函 数 名: void AHT10_SendAC(void)
*	功能说明: 触发传感器进行测量
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/
void AHT10_SendAC(void)
{MyI2C_Start();MyI2C_SendByte(0x70);MyI2C_ReceiveAck();MyI2C_SendByte(0xAC);MyI2C_ReceiveAck();MyI2C_SendByte(0x33);MyI2C_ReceiveAck();MyI2C_SendByte(0x00);MyI2C_ReceiveAck();MyI2C_Stop();
}
/*
*********************************************************************************************************
*	函 数 名: void AHT10_SendBA(void)
*	功能说明: 软复位模块
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/
void AHT10_SendBA(void)
{MyI2C_Start();MyI2C_SendByte(0x70);MyI2C_ReceiveAck();MyI2C_SendByte(0xBA);MyI2C_ReceiveAck();MyI2C_Stop();
}/*
*********************************************************************************************************
*	函 数 名: void AHT10_Read_CTdata(uint32_t *ct) //读取AHT10的温度和湿度数据
*	功能说明: 
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/
void AHT10_Read_CTdata(uint32_t *ct) //读取AHT10的温度和湿度数据
{uint8_t Byte_1th = 0;uint8_t Byte_2th = 0;uint8_t Byte_3th = 0;uint8_t Byte_4th = 0;uint8_t Byte_5th = 0;uint8_t Byte_6th = 0;uint32_t RetuData = 0;uint16_t cnt = 0;AHT10_SendAC(); //向AHT10发送AC指令Delay_ms(75); //等待75mscnt = 0;while(((AHT10_Read_Status()&0x80)==0x80))//等待忙状态结束{Delay_us(1508);if(cnt++>=100){break;}}MyI2C_Start();MyI2C_SendByte(0x71);MyI2C_ReceiveAck();Byte_1th = MyI2C_ReceiveByte();MyI2C_ReceiveAck();Byte_2th = MyI2C_ReceiveByte();MyI2C_ReceiveAck();Byte_3th = MyI2C_ReceiveByte();MyI2C_ReceiveAck();Byte_4th = MyI2C_ReceiveByte();MyI2C_ReceiveAck();Byte_5th = MyI2C_ReceiveByte();MyI2C_ReceiveAck();Byte_6th = MyI2C_ReceiveByte();MyI2C_ReceiveAck();MyI2C_Stop();RetuData = (RetuData|Byte_2th)<<8;RetuData = (RetuData|Byte_3th)<<8;RetuData = (RetuData|Byte_4th);RetuData =RetuData >>4;ct[0] = RetuData;RetuData = 0;RetuData = (RetuData|Byte_4th)<<8;RetuData = (RetuData|Byte_5th)<<8;RetuData = (RetuData|Byte_6th);RetuData = RetuData&0xfffff;ct[1] =RetuData; }
/*
*********************************************************************************************************
*	函 数 名: uint8_t AHT10_Init(void)//初始化AHT10
*	功能说明: AHT10初始化函数
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/uint8_t AHT10_Init(void)//初始化AHT10
{uint16_t count=0;MyI2C_Start();MyI2C_SendByte(0x70);MyI2C_ReceiveAck();MyI2C_SendByte(0xE1);MyI2C_ReceiveAck();MyI2C_SendByte(0x08);MyI2C_ReceiveAck();MyI2C_SendByte(0x00);MyI2C_ReceiveAck();MyI2C_Stop();Delay_ms(500);while( AHT10_Read_Cal_Enable() == 0){AHT10_SendBA();Delay_ms(100);MyI2C_Start();MyI2C_SendByte(0x70);MyI2C_ReceiveAck();MyI2C_SendByte(0xE1);MyI2C_ReceiveAck();MyI2C_SendByte(0x08);MyI2C_ReceiveAck();MyI2C_SendByte(0x00);MyI2C_ReceiveAck();MyI2C_Stop();if(count++>=10)return 0;Delay_ms(500);}return 1;}
/*
*********************************************************************************************************
*	函 数 名: Get_Value()
*	功能说明: 获取温湿度的值
*	形    参:无
*	返 回 值: 无
*********************************************************************************************************
*/
void Set_temp_humid()
{float c1,t1;uint32_t CT_data[2];while(AHT10_Read_Cal_Enable()==0){AHT10_Init();Delay_ms(10);}AHT10_Read_CTdata(CT_data);  //读取温度和湿度 , 可间隔1.5S读一次c1= CT_data[0]*1000/1024/1024/10.00;  //计算得到湿度值(放大了10倍,如果c1=523,表示现在湿度为52.3%)t1= (CT_data[1] *200*10/1024/1024-500)/10.00;//计算得到温度值(放大了10倍,如果t1=245,表示现在温度为24.5℃)Serial_Printf("湿度:%.2f,温度:%.2f",c1,t1);}

AHT10.h

#ifndef __SHT10_H
#define __SHT10_Huint8_t AHT10_Read_Status(void);//读取状态
uint8_t AHT10_Read_Cal_Enable(void);//检测校准位
uint8_t AHT10_Init(void);//初始化AHT10void AHT10_SendAC(void);//发送触发检测信号
void AHT10_SendBA(void);//软复位信号
void AHT10_Read_CTdata(uint32_t *ct);//读取AHT10的温度和湿度数据
void Set_temp_humid();//计算湿度和温度#endif

main.c

#include "stm32f10x.h"                  // Device header
#include "uart.h"
#include "Sht10.h"
#include "I2C.h"
#include "Delay.h"uint8_t RxData;int main(void)
{		UART_Init();MyI2C_Init();AHT10_Init();					while (1){
//			Serial_Printf("湿度:%.2f,温度:%.2f",AHT10_Data -> humi,AHT10_Data -> temp);Set_temp_humid();Delay_s(2);}}

四、工程分享

以下是我分享的资源,我设置了免费下载,大家同时可以在评论区留言邮箱

https://download.csdn.net/download/weixin_54210362/89853007?spm=1001.2014.3001.5503icon-default.png?t=O83Ahttps://download.csdn.net/download/weixin_54210362/89853007?spm=1001.2014.3001.5503


http://www.ppmy.cn/ops/122359.html

相关文章

利用 Python 爬虫采集 1688商品详情

1688是中国的一个大型B2B电子商务平台&#xff0c;主要用于批发和采购各种商品。对于需要从1688上获取商品详情数据、工程数据或店铺数据的用户来说&#xff0c;可以采用以下几种常见的方法&#xff1a; 官方API接口&#xff1a;如果1688提供了官方的API接口&#xff0c;那么可…

index.html 调用 ajax

index.html <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><title>AJAX 请求示例</title><script>// 封装 Ajax 为公共函数&#xff1a;传入回调函数 success 和 failfunction myAjax (url, suc…

按分类调用标签 调用指定分类下的TAG

按分类调用标签 调用指定分类下的TAG <?php query_posts(category_namenews); if (have_posts()) : while (have_posts()) : the_post(); if( get_the_tag_list() ){ echo $posttags get_the_tag_list(<li class"jquery">,</li><li>,</li…

AEye激光雷达公司的战略调整与成本控制分析

AEye激光雷达公司的战略调整与成本控制分析 当地时间9月3日,美国激光雷达领域的知名上市公司AEye在其向美国证券交易委员会(SEC)提交的8-K报告中披露了一项重大战略调整措施。报告指出,作为公司全面成本控制计划的一部分,AEye已对员工总数进行了大幅缩减,减少比例约达三分…

阿里巴巴开源的FastJson 1反序列化漏洞复现攻击保姆级教程

免责申明 本文仅是用于学习检测自己搭建的靶场环境有关FastJson1反序列化漏洞的原理和攻击实验,请勿用在非法途径上,若将其用于非法目的,所造成的一切后果由您自行承担,产生的一切风险和后果与笔者无关;本文开始前请认真详细学习《‌中华人民共和国网络安全法》‌及其所在…

【FPGA开发】Xilinx FPGA差分输入时钟的使用方法

正文 以前在使用ZYNQ的领航者ZYNQ7020进行FPGA学习时&#xff0c;它们使用的单端50M的输入时钟&#xff0c;在verlog代码编写上比较简单&#xff0c;而现在使用Alinx的AXU3EG开发板时&#xff0c;发现它使用的是200M的差分输入时钟&#xff0c;哪这个时候&#xff0c;输入时钟要…

HC、OC、JD 极简理解(招聘领域概念)

HC&#xff08;Head Count&#xff09; HC 指公司计划招聘的员工数量 当公司的某个部门或者岗位需要新人加入时&#xff0c;就需要向人事部门申请 HC&#xff0c;以便开展招聘工作 JD&#xff08;Job Description&#xff09; JD 指描述一个职位的主要工作内容、任职要求等信…

新闻推荐系统:Spring Boot与大数据

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…