【无标题】

STM32开发实战—基于I2C协议的AHT20温湿度传感器的数据采集

软件I2C”和“硬件I2C”

软件I2C和硬件I2C是两种不同的实现方式,用于在嵌入式系统和电子设备中进行I2C通信。
软件I2C

软件I2C是通过软件控制GPIO引脚来模拟I2C通信的方式。
特点 描述
实现方式 通过软件控制GPIO引脚来模拟I2C通信
速度 相对较慢
灵活性 相对灵活,可适应特殊硬件环境
可靠性 受限于软件实现,可能受到中断和延迟的影响
资源占用 需要使用额外的GPIO引脚和软件资源
硬件I2C

硬件I2C是通过专门的硬件电路来实现I2C通信的方式。
特点 描述
实现方式 通过硬件电路控制和传输I2C总线上的时钟和数据线
速度 快速
稳定性 由硬件电路控制,提供稳定的时序和信号质量
可靠性 高可靠性,减少通信错误和干扰
资源占用 集成在芯片或模块中,无需额外引脚和软件资源

选择使用软件I2C还是硬件I2C取决于具体的应用需求和硬件环境。通常情况下,如果硬件上已经有集成的硬件I2C接口,建议使用硬件I2C以提供更高的性能和可靠性。而在无法使用硬件I2C接口或需要在特定环境下模拟I2C通信时,可以选择使用软件I2C。
在这里插入图片描述
在这里插入图片描述
从图中可以看出I2C在通讯的时候,只有在SCL处于高电平时,SDA的数据传输才是有效的。SDA 信号线是用于传输数据,SCL 信号线是保证数据同步。
当SDA传输数据后,接收方对接受到的数据进行一个应答。如果希望继续进行传输数据,则回应应答信号(低电平),否则回应非应答信号(高电平)。
AHT20温湿度传感器

AHT20是一款数字式温湿度传感器,具有高精度、快速响应和低功耗的特点。它采用先进的CMOSens®技术,能够准确测量环境的温度和湿度,并通过I2C接口与主控设备进行通信。
AHT20主要特点

高精度测量:AHT20传感器具有出色的温度和湿度测量精度,可达到±0.3°C的温度精度和±2%的湿度精度。
快速响应:AHT20传感器能够在快速响应时间内提供准确的温湿度数据,响应时间仅为8毫秒。
低功耗:AHT20传感器采用超低功耗设计,工作电流仅为3μA,有效延长电池寿命。
广温范围:AHT20传感器能够在-40°C至+85°C的广泛温度范围内提供稳定和可靠的测量。
数字输出:AHT20传感器通过I2C接口输出数字信号,与主控设备进行通信和数据交互。
校准和线性化:AHT20传感器在出厂前进行了校准和线性化处理,提供了准确的测量结果。

开始实验

#include "bsp_i2c.h"
#include "delay.h"

uint8_t   ack_status=0;
uint8_t   readByte[6];
uint8_t   AHT20_status=0;

uint32_t  H1=0;  //Humility
uint32_t  T1=0;  //Temperature

uint8_t  AHT20_OutData[4];
uint8_t  AHT20sendOutData[10] = {0xFA, 0x06, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF};

void IIC_Init(void)
{					     
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );	
	   
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //¨ª?¨ª¨¬¨º?3?
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
 
	IIC_SCL=1;
	IIC_SDA=1;
 
}
//2¨²¨¦¨²IIC?e¨º?D?o?
void IIC_Start(void)
{
	SDA_OUT();     //sda??¨º?3?
	IIC_SDA=1;	  	  
	IIC_SCL=1;
	delay_us(4);
 	IIC_SDA=0;//START:when CLK is high,DATA change form high to low 
	delay_us(4);
	IIC_SCL=0;//?¡¥¡Á?I2C¡Á¨¹??¡ê?¡Á?¡À?¡¤¡é?¨ª?¨°?¨®¨º?¨ºy?Y 
}	  
//2¨²¨¦¨²IIC¨ª¡ê?1D?o?
void IIC_Stop(void)
{
	SDA_OUT();//sda??¨º?3?
	IIC_SCL=0;
	IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
 	delay_us(4);
	IIC_SCL=1; 
	IIC_SDA=1;//¡¤¡é?¨ªI2C¡Á¨¹???¨¢¨º?D?o?
	delay_us(4);							   	
}
//¦Ì¨¨¡äy¨®|¡äeD?o?¦Ì?¨¤¡ä
//¡¤¦Ì???¦Ì¡êo1¡ê??¨®¨º?¨®|¡äe¨º¡ì¡ã¨¹
//        0¡ê??¨®¨º?¨®|¡äe3¨¦1|
u8 IIC_Wait_Ack(void)
{
	u8 ucErrTime=0;
	SDA_IN();      //SDA¨¦¨¨???a¨º?¨¨?  
	IIC_SDA=1;delay_us(1);	   
	IIC_SCL=1;delay_us(1);	 
	while(READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			IIC_Stop();
			return 1;
		}
	}
	IIC_SCL=0;//¨º¡À?¨®¨º?3?0 	   
	return 0;  
} 
//2¨²¨¦¨²ACK¨®|¡äe
void IIC_Ack(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=0;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}
//2?2¨²¨¦¨²ACK¨®|¡äe		    
void IIC_NAck(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=1;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}					 				     
//IIC¡¤¡é?¨ª¨°???¡Á??¨²
//¡¤¦Ì??¡ä¨®?¨²¨®D?T¨®|¡äe
//1¡ê?¨®D¨®|¡äe
//0¡ê??T¨®|¡äe			  
void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
		SDA_OUT(); 	    
    IIC_SCL=0;//¨¤-¦Ì¨ª¨º¡À?¨®?a¨º?¨ºy?Y¡ä?¨º?
    for(t=0;t<8;t++)
    {              
        IIC_SDA=(txd&0x80)>>7;
        txd<<=1; 	  
		delay_us(2);   //??TEA5767?a¨¨y???¨®¨º¡À??¨º?¡À?D?¦Ì?
		IIC_SCL=1;
		delay_us(2); 
		IIC_SCL=0;	
		delay_us(2);
    }	 
} 	    
//?¨¢1??¡Á??¨²¡ê?ack=1¨º¡À¡ê?¡¤¡é?¨ªACK¡ê?ack=0¡ê?¡¤¡é?¨ªnACK   
u8 IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	SDA_IN();//SDA¨¦¨¨???a¨º?¨¨?
  for(i=0;i<8;i++ )
	{
    IIC_SCL=0; 
    delay_us(2);
		IIC_SCL=1;
    receive<<=1;
    if(READ_SDA)receive++;   
		delay_us(1); 
  }					 
	if (!ack)
			IIC_NAck();//¡¤¡é?¨ªnACK
	else
			IIC_Ack(); //¡¤¡é?¨ªACK   
	return receive;
}
 
void IIC_WriteByte(uint16_t addr,uint8_t data,uint8_t device_addr)
{
	IIC_Start();  
	
	if(device_addr==0xA0) //eeprom¦Ì??¡¤¡ä¨®¨®¨²1¡Á??¨²
		IIC_Send_Byte(0xA0 + ((addr/256)<<1));//¡¤¡é?¨ª??¦Ì??¡¤
	else
		IIC_Send_Byte(device_addr);	    //¡¤¡é?¡Â?t¦Ì??¡¤
	IIC_Wait_Ack(); 
	IIC_Send_Byte(addr&0xFF);   //¡¤¡é?¨ª¦Ì¨ª¦Ì??¡¤
	IIC_Wait_Ack(); 
	IIC_Send_Byte(data);     //¡¤¡é?¨ª¡Á??¨²							   
	IIC_Wait_Ack();  		    	   
  IIC_Stop();//2¨²¨¦¨²¨°???¨ª¡ê?1¨¬??t 
	if(device_addr==0xA0) //
		delay_ms(10);
	else
		delay_us(2);
}
 
uint16_t IIC_ReadByte(uint16_t addr,uint8_t device_addr,uint8_t ByteNumToRead)  //?¨¢??¡ä??¡Â?¨°?¨¢¨ºy?Y
{	
		uint16_t data;
		IIC_Start();  
		if(device_addr==0xA0)
			IIC_Send_Byte(0xA0 + ((addr/256)<<1));
		else
			IIC_Send_Byte(device_addr);	
		IIC_Wait_Ack();
		IIC_Send_Byte(addr&0xFF);   //¡¤¡é?¨ª¦Ì¨ª¦Ì??¡¤
		IIC_Wait_Ack(); 
 
		IIC_Start();  	
		IIC_Send_Byte(device_addr+1);	    //¡¤¡é?¡Â?t¦Ì??¡¤
		IIC_Wait_Ack();
		if(ByteNumToRead == 1)//LM75???¨¨¨ºy?Y?a11bit
		{
			data=IIC_Read_Byte(0);
		}
		else
			{
				data=IIC_Read_Byte(1);
				data=(data<<8)+IIC_Read_Byte(0);
			}
		IIC_Stop();//2¨²¨¦¨²¨°???¨ª¡ê?1¨¬??t	    
		return data;
}


/**********
*¨¦???2?¡¤??aIO?¨²?¡ê?¨¦I2C????
*
*¡ä¨®?a¨°????a¨º??aAHT20¦Ì?????I2C
*o¡¥¨ºy??¨®DIICo¨ªI2C¦Ì???¡Àe¡ê???¡Á¡é¨°a¡ê?¡ê?¡ê?¡ê?¡ê?
*
*2020/2/23¡Á?o¨®DT??¨¨??¨²
*
***********/
void  read_AHT20_once(void)
{
	delay_ms(10);

	reset_AHT20();
	delay_ms(10);

	init_AHT20();
	delay_ms(10);

	startMeasure_AHT20();
	delay_ms(80);

	read_AHT20();
	delay_ms(5);
}


void  reset_AHT20(void)
{

	I2C_Start();

	I2C_WriteByte(0x70);
	ack_status = Receive_ACK();
	if(ack_status) printf("1");
	else printf("1-n-");
	I2C_WriteByte(0xBA);
	ack_status = Receive_ACK();
		if(ack_status) printf("2");
	else printf("2-n-");
	I2C_Stop();

	/*
	AHT20_OutData[0] = 0;
	AHT20_OutData[1] = 0;
	AHT20_OutData[2] = 0;
	AHT20_OutData[3] = 0;
	*/
}



void  init_AHT20(void)
{
	I2C_Start();

	I2C_WriteByte(0x70);
	ack_status = Receive_ACK();
	if(ack_status) printf("3");
	else printf("3-n-");	
	I2C_WriteByte(0xE1);
	ack_status = Receive_ACK();
	if(ack_status) printf("4");
	else printf("4-n-");
	I2C_WriteByte(0x08);
	ack_status = Receive_ACK();
	if(ack_status) printf("5");
	else printf("5-n-");
	I2C_WriteByte(0x00);
	ack_status = Receive_ACK();
	if(ack_status) printf("6");
	else printf("6-n-");
	I2C_Stop();
}



void  startMeasure_AHT20(void)
{
	//------------
	I2C_Start();

	I2C_WriteByte(0x70);
	ack_status = Receive_ACK();
	if(ack_status) printf("7");
	else printf("7-n-");
	I2C_WriteByte(0xAC);
	ack_status = Receive_ACK();
	if(ack_status) printf("8");
	else printf("8-n-");
	I2C_WriteByte(0x33);
	ack_status = Receive_ACK();
	if(ack_status) printf("9");
	else printf("9-n-");
	I2C_WriteByte(0x00);
	ack_status = Receive_ACK();
	if(ack_status) printf("10");
	else printf("10-n-");
	I2C_Stop();
}



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




uint8_t  Receive_ACK(void)
{
	uint8_t result=0;
	uint8_t cnt=0;

	IIC_SCL = 0;
	SDA_IN(); 
	delay_us(4);

	IIC_SCL = 1;
	delay_us(4);

	while(READ_SDA && (cnt<100))
	{
		cnt++;
	}

	IIC_SCL = 0;
	delay_us(4);

	if(cnt<100)
	{
		result=1;
	}
	return result;
}



void  Send_ACK(void)
{
	SDA_OUT();
	IIC_SCL = 0;
	delay_us(4);

	IIC_SDA = 0;
	delay_us(4);

	IIC_SCL = 1;
	delay_us(4);
	IIC_SCL = 0;
	delay_us(4);

	SDA_IN();
}



void  SendNot_Ack(void)
{
	SDA_OUT();
	IIC_SCL = 0;
	delay_us(4);

	IIC_SDA = 1;
	delay_us(4);

	IIC_SCL = 1;
	delay_us(4);

	IIC_SCL = 0;
	delay_us(4);

	IIC_SDA = 0;
	delay_us(4);
}


void I2C_WriteByte(uint8_t  input)
{
	uint8_t  i;
	SDA_OUT();
	for(i=0; i<8; i++)
	{
		IIC_SCL = 0;
		delay_ms(5);

		if(input & 0x80)
		{
			IIC_SDA = 1;
			//delaymm(10);
		}
		else
		{
			IIC_SDA = 0;
			//delaymm(10);
		}

		IIC_SCL = 1;
		delay_ms(5);

		input = (input<<1);
	}

	IIC_SCL = 0;
	delay_us(4);

	SDA_IN();
	delay_us(4);
}	


uint8_t I2C_ReadByte(void)
{
	uint8_t  resultByte=0;
	uint8_t  i=0, a=0;

	IIC_SCL = 0;
	SDA_IN();
	delay_ms(4);

	for(i=0; i<8; i++)
	{
		IIC_SCL = 1;
		delay_ms(3);

		a=0;
		if(READ_SDA)
		{
			a=1;
		}
		else
		{
			a=0;
		}

		//resultByte = resultByte | a;
		resultByte = (resultByte << 1) | a;

		IIC_SCL = 0;
		delay_ms(3);
	}

	SDA_IN();
	delay_ms(10);

	return   resultByte;
}


void  set_AHT20sendOutData(void)
{
	/* --------------------------
	 * 0xFA 0x06 0x0A temperature(2 Bytes) humility(2Bytes) short Address(2 Bytes)
	 * And Check (1 byte)
	 * -------------------------*/
	AHT20sendOutData[3] = AHT20_OutData[0];
	AHT20sendOutData[4] = AHT20_OutData[1];
	AHT20sendOutData[5] = AHT20_OutData[2];
	AHT20sendOutData[6] = AHT20_OutData[3];

//	AHT20sendOutData[7] = (drf1609.shortAddress >> 8) & 0x00FF;
//	AHT20sendOutData[8] = drf1609.shortAddress  & 0x00FF;

//	AHT20sendOutData[9] = getXY(AHT20sendOutData,10);
}


void  I2C_Start(void)
{
	SDA_OUT();
	IIC_SCL = 1;
	delay_ms(4);

	IIC_SDA = 1;
	delay_ms(4);
	IIC_SDA = 0;
	delay_ms(4);

	IIC_SCL = 0;
	delay_ms(4);
}



void  I2C_Stop(void)
{
	SDA_OUT();
	IIC_SDA = 0;
	delay_ms(4);

	IIC_SCL = 1;
	delay_ms(4);

	IIC_SDA = 1;
	delay_ms(4);
}
#include "delay.h"
#include "usart.h"
#include "bsp_i2c.h"
#include "stm32f10x.h"                  // Device header


int main(void)
{	
	delay_init();     //?¨®¨º¡Ào¡¥¨ºy3?¨º??¡¥	  
	uart_init(115200);	 //¡ä??¨²3?¨º??¡¥?a115200
	IIC_Init();
		while(1)
	{
		printf("温度湿度显示:");
		read_AHT20_once();
		delay_ms(1500);
  }
}

实验结果如下
在这里插入图片描述

总结

在本次实验中,我们学习了如何使用STM32开发板通过I2C协议来采集AHT20温湿度传感器的数据。
首先,我们了解了I2C协议的基本原理和通信过程。I2C是一种串行通信协议,使用两条线路(SDA和SCL)进行数据传输。其中,SDA线用于数据传输,SCL线用于时钟同步。
接下来,我们连接了AHT20传感器到STM32开发板上的I2C总线,并在代码中初始化了I2C控制器。然后,我们通过发送I2C Start信号、发送设备地址、发送寄存器地址、发送数据等步骤,实现了与AHT20传感器的通信。
在数据采集方面,我们通过读取AHT20传感器的温度和湿度寄存器,获取了实时的温湿度数据。然后,我们对原始的数据进行了处理和转换,得到了可读性更好的温湿度数值。
最后,我们将采集到的温湿度数据通过串口输出,以便进一步的数据分析和处理。
通过本次实验,我们掌握了基于I2C协议的AHT20温湿度传感器的数据采集方法。这对于我们在实际项目中应用温湿度传感器、进行环境监测等方面具有重要意义。
我们还可以进一步拓展这个实验,例如将采集到的数据存储到SD卡或云平台上,实现远程监控和数据分析等功能。
总的来说,本次实验帮助我们深入理解了I2C协议的应用和AHT20温湿度传感器的工作原理,为我们后续的物联网和嵌入式系统开发提供了很好的基础。
经过一次又一次的嵌入式实验,真的让我对于老师上课讲的内容有了更加深层的理解,受益匪浅

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值