51单片机AHT20-21源代码

AHT20,新一代温湿度传感器在尺寸与智能方面建立了新的标准:它嵌入了适 于回流焊的双列扁平无引脚SMD封装,底面3 x 3mm ,高度1.0mm。传感器输出经过 标定的数字信号,标准 I 2 C 格式。AHT20 配有一个全新设计的 ASIC专用芯片、一 个经过改进的MEMS半导体电容式湿度传感元件和一个标准的片上温度传感元件,其 性能已经大大提升甚至超出了前一代传感器的可靠性水平,新一代温湿度传感器, 经过改进使其在恶劣环境下的性能更稳定。每一个传感器都经过校准和测试,在产 品表面印有产品批号。由于对传感器做了改良和微型化改进,因此它的性价比更高, 并且最终所有设备都将得益于尖端的节能运行模式。

但是现在网上的大多数原码都是针对stm32等的这种多位单片机,而我们都知道51单片机是8位单片机,无法对浮点数进行运算,对32位的整数计算有时候也不是很准确,所以我对网上stm32的例程进行了修改。

#include "AHT20.h"
#include "intrins.h"



//定义IIC引脚
sbit SDA=P1^3;
sbit SCL=P1^2;

char buffer[100]={0};//串口打印的缓存
u8  CTDATA[7]={0};//用于CRC传递数组
u8 CRC_WrongFlag=0;//CRC错误标志位   1:Wrong,0:True
u8 ACK_Flag=0;//应答标志位   1:ACK,0:NACK



/**************************延时部分*****************************
用逻辑分析仪测得:1个nop:6us, 2个Nop:7us, 3个Nop:8.5us, 4个Nop:9.5us,
								5个Nop:10.5us, 6个Nop:11.5us
****************************************************************/
void delay_10us()//延时10us
{
	unsigned char i;

	i = 35;
	while (--i);
}

//**********************************************
void delay_1ms()		//延时1ms,用逻辑分析仪测得i=84时,延时为1ms
{
	unsigned char i, j;

	i = 15;
	j = 90;
	do
	{
		while (--j);
	} while (--i);
}



//**********************************************
void delay_ms(u16 i)	//延时 i ms,不是十分精准,当i大于58时误差会超过1ms
{
	for(;i>0;i--)
	{
		delay_1ms();
	}
}









/**************************IIC部分*****************************/

//送起始位 sda=1->0
void I2C_Start2()
{
  SDA=1;
  SCL=1;
  delay_10us();
  SDA=0;
  delay_10us();
  SCL=0; 
}
//送停止位 sda=0->1
void Stop_I2C()
{
  SDA=0;
  SCL=1;
  delay_10us();
  SDA=1;
}
//主机发送ACK(包含ack:sda=0)
void Send_ACK(void)
{  //设置SDA 口为输出
   SDA=0;
   SCL=0;
   delay_10us();
   SCL=1;
   delay_10us();	
   SCL=0;
   SDA=1;
}
//主机发送NACK(no_ack:sda=1)
void Send_NOT_ACK(void)
{  //设置SDA 口为输出
   SDA=1;  
   SCL=0;
   delay_10us();
   SCL=1;
   delay_10us();
   SDA=1;
   SCL=0;
}

// 检测 SDA是否回ACK(ack:sda=1;Nack:sda=0)
u8 Receive_ACK(void)
{  //设置SDA 口为输入
	u8 cnt=0;
   SCL=0;
   delay_10us();
   SCL=1;
   delay_10us();
	while((SDA==1)&&cnt<100)
		cnt++;
	if(cnt==100)
	{
		ACK_Flag=0;//nack
	}else
	{
		ACK_Flag=1;//ack
	}
	SCL=0;
	delay_10us();
	 return ACK_Flag;
}






void AHT20_WR_Byte(u8 Byte) //往AHT20写一个字节
{
	u8 Data,N,i;	
	Data=Byte;
	i = 0x80;
	for(N=0;N<8;N++)
	{
		SCL=0; 
		delay_10us();	
		if(i&Data)
		{
			SDA=1;
		}
		else
		{
			SDA=0;
		}	
		SCL=1;
		delay_10us();
		Data <<= 1;
		 
	}
	SCL=0;
	delay_10us();   
}	


u8 AHT20_RD_Byte(void)//从AHT20读取一个字节
{
	u8 Byte,i,a;
	Byte = 0;
	
	for(i=0;i<8;i++)
	{
		SCL=0;
		delay_10us();
		SCL=1;
		delay_10us();
		a=0;
		if(SDA==1)a=1;
		Byte=(Byte<<1);
		Byte|=a;
		SCL=0;
		
	}
	return Byte;
	
	
	
}




u8 AHT20_Read_Status(void)//读取AHT20的状态寄存器
{

	u8 Byte_first;	
	I2C_Start2();
	AHT20_WR_Byte(0x71);
	
	Receive_ACK();
	Byte_first = AHT20_RD_Byte();
	Send_NOT_ACK();
	Stop_I2C();
	return Byte_first;
}

//u8 AHT20_Read_Cal_Enable(void)  //查询cal enable位有没有使能
//{
//	u8 val = 0;//ret = 0,
//  val = AHT20_Read_Status();
//	 if((val & 0x68)==0x08)
//		 return 1;
//   else  return 0;
// }

void AHT20_SendAC(void) //向AHT20发送AC命令
{

	I2C_Start2();
	AHT20_WR_Byte(0x70);
	Receive_ACK();
	AHT20_WR_Byte(0xac);//0xAC采集命令
	Receive_ACK();
	AHT20_WR_Byte(0x33);
	Receive_ACK();
	AHT20_WR_Byte(0x00);
	Receive_ACK();
	Stop_I2C();

}


//CRC校验类型:CRC8/MAXIM
//多项式:X8+X5+X4+1
//Poly:0011 0001  0x31
//高位放到后面就变成 1000 1100 0x8c
//C现实代码:
u8 Calc_CRC8(u8 *message,u8 Num)
{
        u8 i;
        u8 byte;
        u8 crc=0xFF;
  for(byte=0; byte<Num; byte++)
  {
    crc^=(message[byte]);
    for(i=8;i>0;--i)
    {
      if(crc&0x80) crc=(crc<<1)^0x31;
      else crc=(crc<<1);
    }
  }
        return crc;
}





void AHT20_Read_CTdata(u16 *ct) //没有CRC校验,直接读取AHT20的温度和湿度数据
{
	volatile u8  Byte_1th=0;
	volatile u8  Byte_2th=0;
	volatile u8  Byte_3th=0;
	volatile u8  Byte_4th=0;
	volatile u8  Byte_5th=0;
	volatile u8  Byte_6th=0;
	volatile u8  Byte_7th=0;
	u16 RetuData = 0;
	u16 cnt = 0;
	AHT20_SendAC();//向AHT10发送AC命令
	delay_ms(80);//延时80ms左右	
    cnt = 0;
	while(((AHT20_Read_Status()&0x80)==0x80))//直到状态bit[7]为0,表示为空闲状态,若为1,表示忙状态
	{
		delay_ms(2);
		if(cnt++>=100)
		{
		 break;
		 }
	}
	I2C_Start2();
	AHT20_WR_Byte(0x71);
	Receive_ACK();
	CTDATA[0]=Byte_1th = AHT20_RD_Byte();//状态字,查询到状态为0x98,表示为忙状态,bit[7]为1;状态为0x1C,或者0x0C,或者0x08表示为空闲状态,bit[7]为0
	Send_ACK();
	CTDATA[1]=Byte_2th = AHT20_RD_Byte();//湿度
	Send_ACK();
	CTDATA[2]=Byte_3th = AHT20_RD_Byte();//湿度
	Send_ACK();
	CTDATA[3]=Byte_4th = AHT20_RD_Byte();//湿度/温度
	Send_ACK();
	CTDATA[4]=Byte_5th = AHT20_RD_Byte();//温度
	Send_ACK();
	CTDATA[5]=Byte_6th = AHT20_RD_Byte();//温度
	Send_NOT_ACK();
	Stop_I2C();

	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>>4)&0x00ff;
	ct[1] =RetuData; //温度
	

}


void AHT20_Read_CTdata_crc(u16 *ct) //CRC校验后,读取AHT20的温度和湿度数据
{
	volatile u8  Byte_1th=0;
	volatile u8  Byte_2th=0;
	volatile u8  Byte_3th=0;
	volatile u8  Byte_4th=0;
	volatile u8  Byte_5th=0;
	volatile u8  Byte_6th=0;
	volatile u8  Byte_7th=0;
	 u16 RetuData = 0;
	 u16 cnt = 0;

	
	AHT20_SendAC();//向AHT10发送AC命令
	delay_ms(80);//延时80ms左右	
    cnt = 0;
	while(((AHT20_Read_Status()&0x80)==0x80))//直到状态bit[7]为0,表示为空闲状态,若为1,表示忙状态
	{
		delay_ms(1);
		if(cnt++>=100)
		{
		 break;
		}
	}
	
	I2C_Start2();

	AHT20_WR_Byte(0x71);
	Receive_ACK();
	CTDATA[0]=Byte_1th = AHT20_RD_Byte();//状态字,查询到状态为0x98,表示为忙状态,bit[7]为1;状态为0x1C,或者0x0C,或者0x08表示为空闲状态,bit[7]为0
	Send_ACK();
	CTDATA[1]=Byte_2th = AHT20_RD_Byte();//湿度
	Send_ACK();
	CTDATA[2]=Byte_3th = AHT20_RD_Byte();//湿度
	Send_ACK();
	CTDATA[3]=Byte_4th = AHT20_RD_Byte();//湿度/温度
	Send_ACK();
	CTDATA[4]=Byte_5th = AHT20_RD_Byte();//温度
	Send_ACK();
	CTDATA[5]=Byte_6th = AHT20_RD_Byte();//温度
	Send_ACK();
	CTDATA[6]=Byte_7th = AHT20_RD_Byte();//CRC数据
	Send_NOT_ACK();                           //注意: 最后是发送NAK
	Stop_I2C();
	
	if(Calc_CRC8(CTDATA,6)==Byte_7th)
	{
	CRC_WrongFlag=0;
		
	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>>4)&0x00ff;
	ct[1] =RetuData; //温度
		
	}
	else
	{
//		ct[0]=0x00;
//		ct[1]=0x00;//校验错误返回值,客户可以根据自己需要更改
		CRC_WrongFlag=1;//CRC错误标志位

	}//CRC数据
}


void AHT20_Init(void)   //初始化AHT20
{	
	I2C_Start2();
	AHT20_WR_Byte(0x70);
	Receive_ACK();
	AHT20_WR_Byte(0xa8);//0xA8进入NOR工作模式
	Receive_ACK();
	AHT20_WR_Byte(0x00);
	Receive_ACK();
	AHT20_WR_Byte(0x00);
	Receive_ACK();
	Stop_I2C();

	delay_ms(10);//延时10ms左右

	I2C_Start2();
	AHT20_WR_Byte(0x70);
	Receive_ACK();
	AHT20_WR_Byte(0xbe);//0xBE初始化命令,AHT20的初始化命令是0xBE,   AHT10的初始化命令是0xE1
	Receive_ACK();
	AHT20_WR_Byte(0x08);//相关寄存器bit[3]置1,为校准输出
	Receive_ACK();
	AHT20_WR_Byte(0x00);
	Receive_ACK();
	Stop_I2C();
	delay_ms(10);//延时10ms左右
}
void JH_Reset_REG(u8 addr)
{
	
	u8 Byte_first,Byte_second,Byte_third;
	I2C_Start2();
	AHT20_WR_Byte(0x70);//原来是0x70
	Receive_ACK();
	AHT20_WR_Byte(addr);
	Receive_ACK();
	AHT20_WR_Byte(0x00);
	Receive_ACK();
	AHT20_WR_Byte(0x00);
	Receive_ACK();
	Stop_I2C();

	delay_ms(5);//延时5ms左右
	I2C_Start2();
	AHT20_WR_Byte(0x71);//
	Receive_ACK();
	Byte_first = AHT20_RD_Byte();
	Send_ACK();
	Byte_second = AHT20_RD_Byte();
	Send_ACK();
	Byte_third = AHT20_RD_Byte();
	Send_NOT_ACK();
	Stop_I2C();
	
    delay_ms(10);//延时10ms左右
	I2C_Start2();
	AHT20_WR_Byte(0x70);///
	Receive_ACK();
	AHT20_WR_Byte(0xB0|addr);寄存器命令
	Receive_ACK();
	AHT20_WR_Byte(Byte_second);
	Receive_ACK();
	AHT20_WR_Byte(Byte_third);
	Receive_ACK();
	Stop_I2C();
	
	Byte_second=0x00;
	Byte_third =0x00;
}

void AHT20_Start_Init(void)
{
	JH_Reset_REG(0x1b);
	JH_Reset_REG(0x1c);
	JH_Reset_REG(0x1e);
}

在这里我选用的是stc8g的单片机,所以延时函数和传统的51单片机有所不同,请大家根据实际情况进行更改。

在这个程序中最主要的其实就是这两个函数:

void AHT20_Read_CTdata(u16 *ct)
void AHT20_Read_CTdata_crc(u16 *ct)

因为我此次的设计只是为了日常的使用,所以不需要用到太高的精度,只从AHT20的寄存器中读取了温度和湿度的最高八位,并返回。在主函数调用读取函数后需用公式进行换算。 

c1 = CT_data[0]*100/255;      
t1 = (CT_data[1]*200/255)-50; 

同时,AHT20的寄存器如下图:

我们也可以根据需要的精度对函数进行修改和换算。 

### 回答1: AHT20和BMP280是两种常见的温湿度传感器。这两种传感器都是数字式传感器,可以测量周围环境的温度和湿度,并将结果以数字信号的形式输出。 AHT20是一款由爱尔兰公司Aosong Electronics开发的温湿度传感器。它具有高精度、低功耗、抗干扰等特点。AHT20的工作电压范围广泛,可以在1.6V至3.6V的电压下正常工作。该传感器可以测量的温度范围为-40℃至+85℃,湿度范围为0%RH至100%RH。另外,AHT20还具有快速响应速度和良好的长期稳定性。 BMP280是由德国公司Bosch Sensortec开发的温度和气压传感器。与AHT20相比,BMP280可以同时测量温度和大气压强。该传感器使用了先进的纳米技术,具有低功耗和高精度的特点。BMP280的工作电压范围为1.71V至3.6V,温度测量范围为-40℃至+85℃,气压测量范围为300hPa至1100hPa。BMP280还具有多种工作模式,可以根据需求选择不同的工作模式,以实现更好的平衡性能和功耗。 综上所述,AHT20和BMP280都是常用的温湿度传感器,可以满足不同场景下的温湿度测量需求。选择使用哪种传感器需要根据具体的应用环境和需求来决定。 ### 回答2: AHT20和BMP280是两种常见的传感器,用于测量环境的温度和气压。 AHT20是一种数字式温湿度传感器。它采用先进的CMOSens®技术,具有高精度和低功耗的特点。使用AHT20传感器,可以实时监测和测量环境的温度和湿度。它的测量范围为-40℃至+ 80℃,湿度测量范围为0%至100%。AHT20通过I2C总线与主控板连接,可以方便地与各种微控制器、单片机和开发板集成。 BMP280是一种数字式气压传感器,也采用了CMOSens®技术。它可以实时测量大气压力,并通过计算获得海拔高度。与传统的气压计相比,BMP280具有更高的分辨率和更低的功耗。它的测量范围为300hPa至1100hPa,可以在从-40℃到+ 85℃的温度范围内工作。与AHT20类似,BMP280也通过I2C总线与主控板连接,并可以与各种微控制器和开发板集成。 综上所述,AHT20和BMP280是用于测量环境的温度和气压的两种常见传感器。它们具有高精度、低功耗和方便集成的特点,适用于各种应用领域,如气象观测、室内环境监测和工业自动化等。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值