AHT10温湿度传感器STM32驱动

AHT10温湿度传感器STM32驱动

大家所熟悉都用过的温湿度传感器应该是DHT11了吧,基本上学习单片机的都用过,但是DHT11的精度不是很高,湿度±5%RH,温度±1℃,而且测试的时候一般还要延时3S左右测一下,测试频率慢,而且体积大,价格大概3块多一个吧。在淘宝上搜索温湿度传感器,偶然发现AHT10传感器,价格2.5一个,体积小,精度湿度±2%RH,温度精度±0.3℃。这个是国产温湿度传感器,性价比是比较高的,所以在这里介绍一下AHT10温湿度传感器的使用。

关于AHT10温湿度传感器的数据手册在官方网站上面可以下载到:AHT10温湿度传感器的数据手册
例程程序下载链接:AHT10温湿度传感器STM32驱动程序

引脚说明:
在这里插入图片描述

电路设计:
在这里插入图片描述

AHT10通信协议为IIC协议驱动代码如下所示,采用的是STM32103C8T6单片机。

AHT10.H

#ifndef _AHT10_H__
#define _AHT10_H__

#include  "sys.h"

#define AHT10_ADDRESS 0x70
#define AHT10_WRITE 0x70
#define AHT10_READ 0x71

/*****************函数声明******************/
extern void AHT10Init(void);
extern u8 AHT10Check(void);
extern void AHT10Reset(void);
extern u8 AHT10ReadData(float *temperature,u8 *humidity);

#endif

AHT10.c文件

#include "aht10.h"
#include "myiic.h"
#include "delay.h"

/**
brief AHT10初始化函数
param NONE
return NONE
*/
void AHT10Init()
{
	//IIC_Init();
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO|RCC_APB2Periph_GPIOB, ENABLE);
	GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable , ENABLE);
	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_3|GPIO_Pin_4;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //设置为推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化GPIOBA	
	GPIO_SetBits(GPIOB,GPIO_Pin_3|GPIO_Pin_4);				 //PA4 输出高
	
	IIC_Start();
	IIC_Send_Byte(AHT10_ADDRESS);
	IIC_Send_Byte(0xe1);	
	IIC_Send_Byte(0x08);
	IIC_Send_Byte(0x00);
	IIC_Stop();	
	delay_ms(40);//延时20ms让传感器稳定
}

/**
brief 检查AHT10是否存在
param NONE
return 0存在  1不存在
*/
u8 AHT10Check(void)
{
	u8 ack=0;
	IIC_Start();
	IIC_Send_Byte(AHT10_ADDRESS);
	ack=IIC_Wait_Ack();
	IIC_Stop();	
	return ack;
}

/**
brief AHT10软复位
param NONE
return NONE
*/
void AHT10Reset(void)
{
	IIC_Start();
	IIC_Send_Byte(AHT10_WRITE);
	IIC_Wait_Ack();
	IIC_Send_Byte(0xba);
	IIC_Wait_Ack();
	IIC_Stop();	
}

/**
brief 检查AHT10读温湿度数据
param *temperature:需要读出的温度数据,float指针类型,精度范围+-0.3C
param *humidity:需要读出的湿度数据,u8指针类型,精度范围+-2RH
return 0 读数据正常 1读数据失败
*/
u8 AHT10ReadData(float *temperature,u8 *humidity)
{
	u8 ack;
	u32 SRH=0,ST=0;
	u8 databuff[6];
	IIC_Start();
	IIC_Send_Byte(AHT10_WRITE);
	IIC_Wait_Ack();
	IIC_Send_Byte(0xac);
	IIC_Wait_Ack();
	IIC_Send_Byte(0x33);
	IIC_Wait_Ack();
	IIC_Send_Byte(0x00);
	IIC_Wait_Ack();
	IIC_Stop();	  
	delay_ms(80);//延时一会等待数据读出
	IIC_Start();
	IIC_Send_Byte(AHT10_READ);
	IIC_Wait_Ack();
	ack=IIC_Read_Byte(1);
	if((ack&0x40)==0)
	{
		databuff[0]=IIC_Read_Byte(1);
		databuff[1]=IIC_Read_Byte(1);
		databuff[2]=IIC_Read_Byte(1);
		databuff[3]=IIC_Read_Byte(1);
		databuff[4]=IIC_Read_Byte(0);
		IIC_Stop();
		SRH=(databuff[0]<<12)+(databuff[1]<<4)+(databuff[2]>>4);
		ST=((databuff[2]&0X0f)<<16)+(databuff[3]<<8)+(databuff[4]);
		*humidity=(int)(SRH*100.0/1024/1024+0.5);
		*temperature=((int)(ST*2000.0/1024/1024+0.5))/10.0-50;
		return 0;
	}
	IIC_Stop();	
	return 1;
}

这里需要注意的是我用的 IIC引脚:SCL PB3,SDA PB4,所以使用的时候需要将JTAG功能关闭,一开始调试的时候因为没注意所以弄了一下午,才发现这个问题。

u8 AHT10ReadData(float *temperature,u8 *humidity);
读出温湿度数据只需通过这个函数就行了,需要输入定义的数据类型地址,温度为浮点型数据,精度范围到小数点后一位,湿度为无符号char型数据,因为本身传感器的精度就是±2%RH,如果精度再设置成浮点型数据也没啥意义了所以就弄了u8类型。

下图是获取到的温湿度数据,在我对传感器哈了一口气候效果如图所示,Temp表示温度,hum表示湿度。
在这里插入图片描述

关于整个例程的程序我上传到了我的博客上面,大家可以自行下载,采用的单片机是STM32F103C8T6单片机,就是淘宝上10块钱一个的那种,里面还带了一些别的驱动文件我懒得删掉了,大家不用就行了,下面是IIC的实现函数。

myiic.h

#ifndef __MYIIC_H
#define __MYIIC_H
#include "sys.h"

//IO方向设置
 
#define SDA_IN()  {GPIOB->CRL&=0XFFF0FFFF;GPIOB->CRL|=(u32)8<<16;}
#define SDA_OUT() {GPIOB->CRL&=0XFFF0FFFF;GPIOB->CRL|=(u32)3<<16;}

//IO操作函数	 
#define IIC_SCL    PBout(3) //SCL
#define IIC_SDA    PBout(4) //SDA	 
#define READ_SDA   PBin(4)  //输入SDA 

//IIC所有操作函数
void IIC_Init(void);                //初始化IIC的IO口				 
void IIC_Start(void);				//发送IIC开始信号
void IIC_Stop(void);	  			//发送IIC停止信号
void IIC_Send_Byte(u8 txd);			//IIC发送一个字节
u8 IIC_Read_Byte(unsigned char ack);//IIC读取一个字节
u8 IIC_Wait_Ack(void); 				//IIC等待ACK信号
void IIC_Ack(void);					//IIC发送ACK信号
void IIC_NAck(void);				//IIC不发送ACK信号

void IIC_Write_One_Byte(u8 daddr,u8 addr,u8 data);
u8 IIC_Read_One_Byte(u8 daddr,u8 addr);	  
#endif

myiic.c

#include "myiic.h"
#include "delay.h"

//初始化IIC
void IIC_Init(void)
{					     
	GPIO_InitTypeDef GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(	RCC_APB2Periph_GPIOB, ENABLE );	//使能GPIOB时钟
	   
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	GPIO_SetBits(GPIOB,GPIO_Pin_3|GPIO_Pin_4); 	//PB6,PB7 输出高
}
//产生IIC起始信号
void IIC_Start(void)
{
	SDA_OUT();     //sda线输出
	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总线,准备发送或接收数据 
}	  
//产生IIC停止信号
void IIC_Stop(void)
{
	SDA_OUT();//sda线输出
	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总线结束信号
	delay_us(4);							   	
}
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
u8 IIC_Wait_Ack(void)
{
	u8 ucErrTime=0;
	SDA_IN();      //SDA设置为输入  
	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;//时钟输出0 	   
	return 0;  
} 
//产生ACK应答
void IIC_Ack(void)
{
	IIC_SCL=0;
	SDA_OUT();
	IIC_SDA=0;
	delay_us(2);
	IIC_SCL=1;
	delay_us(2);
	IIC_SCL=0;
}
//不产生ACK应答		    
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发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答			  
void IIC_Send_Byte(u8 txd)
{                        
    u8 t;   
	SDA_OUT(); 	    
    IIC_SCL=0;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        //IIC_SDA=(txd&0x80)>>7;
		if((txd&0x80)>>7)
			IIC_SDA=1;
		else
			IIC_SDA=0;
		txd<<=1; 	  
		delay_us(2);   //对TEA5767这三个延时都是必须的
		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设置为输入
    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;
}

猜你喜欢

转载自blog.csdn.net/Dinvent/article/details/105953462