基于I2C协议完成AHT20温湿度传感器数据采集

前言

  目前利用嵌入式平台进行数据采集,已经习以为常,一方面处于工程本身考虑,嵌入式平台易于安装;其次嵌入式技术具有良好的软硬件可裁剪性,功能较强、可靠性高、成本低廉、 体积小、质量轻、功耗低,因而非常适合用于各类复杂现场的数据采集系统。

  在此次博客,通过嵌入式系统实现对温度的的采集,并通过 串口将采集到的数据发送出去,上位机是 Windows系统的 PC 机

一、I2C介绍

  大家自己做项目或者在网上查阅资料的时候就会发现嵌入式很多传感器的实现是通过I2C实现的,下面介绍一下I2C的基本概念及工作通信流程。

Ⅰ.什么是I2C

  I2C(集成电路总线),由Philips公司(2006年迁移到NXP)在1980年代初开发的一种简单、双线双向同步串行总线,它利用一根时钟线和一根数据线在连接总线的两个器件之间进行信息的传递,为设备之间数据交换提供了一种简单高效的方法。每个连接到总线上的器件都有唯一的地址,任何器件既可以作为主机也可以作为从机,但同一时刻只允许有一个主机。

  I2C 标准是一个具有冲突检测机制和仲裁机制的真正意义上的多主机总线,它能在多个主机同时请求控制总线时利用仲裁机制避免数据冲突并保护数据。在之前也讲过:在嵌入式开发中,使用I2C总线通信的场景有很多,例如驱动FRAM、传感器等。

  I2C结合了SPI和UART的优点。使用I2C,可以将多个从设备连接到单个主设备上(如SPI),并且可以让多个主器件控制单个或多个从器件。

Ⅱ.I2C原理

  与UART通信一样,I2C仅使用两条线在设备之间传输数据:

在这里插入图片描述

  SDA(串行数据) :主站和从站发送和接收数据的线路。

  SCL(串行时钟) :承载时钟信号的线路。

  I2C是一种串行通信协议,因此数据沿着单线(SDA线)逐位传输。

  与SPI一样,I2C是同步的,因此位输出通过主机和从机之间共享的时钟信号与位采样同步。时钟信号始终由主机控制。

  下图为一个单片机(或称MCU)和两个模块通过IIC总线进行通信的简图。
在这里插入图片描述

  因为IIC总线是支持一个主机和多个从机通信的,即支持“一主多从”通信(也支持“多主多从”通信),故参与通信的器件都需要将自己接口中的数据引脚和时钟引脚分别接入总线中的SDA和SCL。

  IIC总线在硬件设计上需要为串行数据线SDA和串行时钟线增加上拉电阻,阻值一般选用10KΩ及以下。

  该上拉电阻的主要作用有:增强总线的驱动能力、以及使总线空闲时其状态自动被拉高。同时阻值的选择也影响当前IIC总线支持的通信速度。

Ⅲ.通信流程

  I2C时序图如下:
在这里插入图片描述

  IIC通信基本流程:主机建立通信开始条件,数据传输阶段,主机建立通信停止条件

🎈开始条件:主机控制SCL维持高电平状态,控制SDA先拉高一段时间,再拉低一段时间(这也是“重复开始条件” / “再开始条件”)。
🎈停止条件:主机控制SCL维持高电平状态,控制SDA先拉低一段时间,再拉高一段时间。

🎈数据传输阶段的时序:空闲时SCL拉低。在SCL上升沿时传输数据à在SCL拉低期间准备数据(调整SDA状态),在SCL拉高期间,保持数据(SDA状态不变)。

:若在数据传输阶段,SCL拉高期间,更改了数据线状态,可能导致从机误认为接收到“开始条件”或“停止条件”信号,导致通信流程混乱。

Ⅳ.I2C优缺点

1.优点

  🎈只使用两根电线
  🎈支持多个主服务器和多个从服务器
  🎈ACK / NACK位确认每个帧都已成功传输
  🎈硬件没有UART那么复杂

2.缺点

  🎐数据传输速率比SPI慢
  🎐数据帧的大小限制为8位
  🎐实现比SPI更复杂的硬件

Ⅴ.软件I2C与硬件I2C

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

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

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

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

二、小试牛刀——采集温湿度数据

Ⅰ.实验内容

  阅读AHT20数据手册,编程实现:每隔2秒钟采集一次温湿度数据,并通过串口发送到上位机(win10)

Ⅱ.实验分析

1.了解温湿度传感器模块——AHT20

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

  这里要强调一下:一定要注意管脚号,不要接反
在这里插入图片描述

  STM32F103系列,接引脚说明
在这里插入图片描述

2. 理解官方资料后,编写代码

  看懂官方给的资料,明白传感器的具体用法,根据实验要求进行代码编写。

3.编译,上板测试

  编译成功后,将程序烧录到单片机中,通过串口助手观察输出!

Ⅲ.实验步骤

1编写main()函数

  代码如下:

#include "System.h"
#include "Delay.h"
#include "UART.h"
#include "AHT20.h"

struct AHT20_INF AHT20;

int main(void)
{
	
		IIC_Init();
    Delay_Init();
		My_Uart_Init(115200);
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC,ENABLE);

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
    GPIO_Init(GPIOC,&GPIO_InitStructure);
		GPIO_ResetBits(GPIOC,GPIO_Pin_13);

		AHT20.alive = !AHT20_Init();
    while(1)
    {
		if(AHT20.alive)
		{
			AHT20.flag = AHT20_ReadHT(AHT20.ht);
			StandardUnitCon(&AHT20);
		}
		
		TEST_MainPage();
		printf("温度:%.2f°c  湿度:%.2f%%\n",AHT20.te,AHT20.rh);
    Delay_ms(1000);

    }
}

2.部分代码——读取传感器的关键代码及注解

#include "AHT20.h"

//读AHT20的状态字
static uint8_t AHT20_ReadStatusCmd(void)
{
	uint8_t tmp[1];
	Soft_I2C_Read(AHT20_SLAVE_ADDRESS,AHT20_STATUS_REG,1,tmp);
	return tmp[0];
}

//读AHT20标准使能位
static uint8_t AHT20_ReadCalEnableCmd(void)
{
	uint8_t tmp;
	tmp = AHT20_ReadStatusCmd();
	return (tmp>>3)&0x01;
}

//读取AHT20 忙标志位
static uint8_t AHT20_ReadBusyCmd(void)
{
	uint8_t tmp;
	tmp = AHT20_ReadStatusCmd();
	return (tmp>>7)&0x01;
}

//AHT20芯片初始化函数
static void AHT20_IcInitCmd(void)
{
	uint8_t tmp[2];
	tmp[0] = 0x08;
	tmp[1] = 0x00;
	Soft_I2C_Write(AHT20_SLAVE_ADDRESS, AHT20_INIT_REG, 2, tmp);
}

//触发AHT20测量
static void AHT20_TrigMeasureCmd(void)
{
	uint8_t tmp[2];
	tmp[0] = 0x33;
	tmp[1] = 0x00;
	Soft_I2C_Write(AHT20_SLAVE_ADDRESS, AHT20_Measure, 2, tmp);
}

//AHT20软复位函数
static void AHT20_SoftResetCmd(void)
{
	uint8_t tmp[1];
	Soft_I2C_Write(AHT20_SLAVE_ADDRESS, AHT20_Reset, 0, tmp);
}

//AHT20 设备初始化
uint8_t AHT20_Init(void)
{
	uint8_t rcnt = 2+1;//软复位命令 重试次数,2次
	uint8_t icnt = 2+1;//初始化命令 重试次数,2次
	
	while(--rcnt)
	{
		icnt = 2+1;
		
		Delay_ms(40);//上电后要等待40ms
		// 读取温湿度之前,首先检查[校准使能位]是否为1
		while((!AHT20_ReadCalEnableCmd()) && (--icnt))// 2次重试机会
		{
			Delay_ms(10);
			// 如果不为1,要发送初始化命令
			AHT20_IcInitCmd();
			Delay_ms(200);//这个时间不确定,手册没讲
		}
		
		if(icnt)//[校准使能位]为1,校准正常
		{
			break;//退出rcnt循环
		}
		else//[校准使能位]为0,校准错误
		{
			AHT20_SoftResetCmd();//软复位AHT20器件,重试
			Delay_ms(200);//这个时间不确定,手册没讲
		}
	}
	
	if(rcnt)
	{
		Delay_ms(200);//这个时间不确定,手册没讲
		return 0;// AHT20设备初始化正常
	}
	else
	{
		return 1;// AHT20设备初始化失败
	}
}

//读取AHT20的数据

uint8_t AHT20_ReadHT(uint32_t *HT)
{
	uint8_t cnt=3+1;//忙标志 重试次数,3次
	uint8_t tmp[6];
	uint32_t RetuData = 0;
	
	// 发送触发测量命令
	AHT20_TrigMeasureCmd();
	
	do{
		Delay_ms(75);//等待75ms待测量完成,忙标志Bit7为0
	}while(AHT20_ReadBusyCmd() && (--cnt));//重试3次
	
	if(cnt)//设备闲,可以读温湿度数据
	{
		Delay_ms(5);
		// 读温湿度数据
		Soft_I2C_Read(AHT20_SLAVE_ADDRESS, AHT20_STATUS_REG, 6, tmp);
		// 计算相对湿度RH。原始值,未计算为标准单位%。
		RetuData = 0;
		RetuData = (RetuData|tmp[1]) << 8;
		RetuData = (RetuData|tmp[2]) << 8;
		RetuData = (RetuData|tmp[3]);
		RetuData = RetuData >> 4;
		HT[0] = RetuData;
		
		// 计算温度T。原始值,未计算为标准单位°C。
		RetuData = 0;
		RetuData = (RetuData|tmp[3]) << 8;
		RetuData = (RetuData|tmp[4]) << 8;
		RetuData = (RetuData|tmp[5]);
		RetuData = RetuData&0xfffff;
		HT[1] = RetuData;
		
		return 0;
	}
	else//设备忙,返回读取失败
	{
		return 1;
	}
}

//原始数据转换函数
uint8_t StandardUnitCon(struct AHT20_INF* aht)
{
	aht->rh = (double)aht->ht[0] *100 / 1048576;//2^20=1048576 //原式:(double)aht->HT[0] / 1048576 *100,为了浮点精度改为现在的
	aht->te = (double)aht->ht[1] *200 / 1048576 -50;
	
	//限幅,RH=0~100%; Temp=-40~85°C
	if((aht->rh >=0)&&(aht->rh <=100) && (aht->te >=-40)&&(aht->te <=85))
	{
		aht->flag = 0;
		return 0;//测量数据正常
	}
	else
	{
		aht->flag = 1;
		return 1;//测量数据超出范围,错误
	}
}


uint8_t Soft_I2C_Write(uint8_t addr,uint8_t reg_addr,uint8_t len,uint8_t *data_buf)
{

    uint8_t i;
	
	I2C_Start();
	I2C_Send_Byte(addr << 1 | I2C_Direction_Transmitter);//发送器件地址+写命令
	if(I2C_Wait_ACK())//等待应答
	{
		I2C_Stop();
		return 1;
	}
	
	I2C_Send_Byte(reg_addr);//写寄存器地址
    I2C_Wait_ACK();//等待应答
	
	for(i=0;i<len;i++)
	{
		I2C_Send_Byte(data_buf[i]);//发送数据
		if(I2C_Wait_ACK())//等待ACK
		{
			I2C_Stop();
			return 1;
		}
	}
    I2C_Stop();
	return 0;
}

uint8_t Soft_I2C_Read(uint8_t addr,uint8_t reg_addr,uint8_t len,uint8_t *data_buf)
{

	uint8_t result;
	
	I2C_Start();
	I2C_Send_Byte(addr << 1 | I2C_Direction_Transmitter);//发送器件地址+写命令
	if(I2C_Wait_ACK())//等待应答
	{
		I2C_Stop();
		return 1;
	}
	
	I2C_Send_Byte(reg_addr);//写寄存器地址
    I2C_Wait_ACK();//等待应答
	
	I2C_Start();
	I2C_Send_Byte(addr << 1 | I2C_Direction_Receiver);//发送器件地址+读命令
	I2C_Wait_ACK();//等待应答
	
    while(len)
	{
		if(len==1)*data_buf=I2C_Read_Byte(0);//读数据,发送nACK
		else *data_buf=I2C_Read_Byte(1);//读数据,发送ACK
		len--;
		data_buf++;
	}
    I2C_Stop();//产生一个停止条件
	return 0;
}

  获取全部代码请点这里👉参考代码

3编译并烧录。

  编译成功之后,使用Flymcu软件将代码烧录到程序中,利用串口助手观察结果如下所示:

在这里插入图片描述
动图演示如下:
在这里插入图片描述

三、总结

  在此次实验中,碰到很多问题,一开始由于接线不稳导致采集不到数据,后续可以采集到数据,可能是因为供电原因期间会出现”错误数据“,后续改到5V供电,输出稳定。

四、参考文献

[1] https://blog.csdn.net/hhhhhh277523/article/details/111397514
[2] https://blog.csdn.net/qq_43279579/article/details/111597278

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: AHT10是一种温湿度传感器,它可以测量环境中的温度和湿度。它可以用于各种应用,如温室控制、恒温恒湿环境监控、工业过程控制等。AHT10拥有高精度和高稳定性,并且可以在极端温度条件下工作。此外,AHT10还有一个I2C接口,可以与其他电子设备相连,方便数据采集和处理。 ### 回答2: AHT10温湿度传感器是一种高精度的数字温湿度传感器,采用了先进的CMOSens®技术。它可以测量温度和湿度,并将结果以数字形式输出。AHT10具有很高的精确度和稳定性,能够提供可靠的温湿度测量结果。 AHT10传感器的特点之一是其小巧的封装和低功耗设计。它采用超薄的封装,适用于空间有限的应用场景,例如智能手机、电子设备等。同时,AHT10传感器的功耗非常低,可以在长时间使用的情况下保持高精度的温湿度测量。 此外,AHT10传感器还具有很好的抗干扰能力和快速的响应时间。它采用数字传感技术,能够有效抵抗电磁干扰和温度梯度变化对温湿度测量的影响,确保测量结果的准确性和稳定性。同时,AHT10传感器响应时间快,能够迅速对环境的温湿度变化做出反应。 除了以上特点,AHT10传感器还具有多种应用领域。它可以应用于室内环境监测、气象观测、温湿度控制等领域。在智能家居领域,AHT10传感器可以与其他智能设备进行连接,实现智能温湿度控制和环境监测。在农业领域,AHT10传感器可以应用于温室监测和农作物生长环境控制,提高农作物产量和质量。 总的来说,AHT10温湿度传感器是一种高精度、稳定性好、功耗低的数字温湿度传感器。它具有多种应用领域,能够满足不同场景的温湿度测量需求。 ### 回答3: AHT10温湿度传感器是一种具有高精度和可靠性的传感器,用于测量环境中的温度和湿度。它具有很多特点和优势,以下是对AHT10温湿度传感器的回答。 首先,AHT10温湿度传感器采用表面贴装技术,可以方便地集成到各种设备和系统中。它的体积小、重量轻,适合于嵌入式应用和对空间有要求的领域。它还具有超低功耗,在节能环保方面具有较大优势。 其次,AHT10温湿度传感器具有高度的精确度和稳定性。它采用了先进的温湿度校准算法和数字信号处理技术,可以实时准确地测量和反馈环境中的温度和湿度数据。同时,它还具有较低的误差和漂移,保证了传感器的可靠性和长期稳定性。 另外,AHT10温湿度传感器具有广泛的应用领域。它可以被应用于气象观测、环境监测、空调系统、智能家居等领域。无论是工业生产还是日常生活,AHT10温湿度传感器都能够提供准确的温湿度数据,帮助我们更好地了解和控制环境条件。 总结起来,AHT10温湿度传感器是一种功能强大、高精度和可靠性的传感器。它的小体积、超低功耗使得它在嵌入式应用和对空间有要求的领域具有较大优势。它的高度精确度、稳定性和广泛的应用领域使得它成为了温湿度测量领域的重要组成部分。无论是在工业生产还是日常生活中,AHT10温湿度传感器都能够为我们提供准确的环境温湿度数据,帮助我们更好地了解和控制环境条件。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值