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 highdelay_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;elseIIC_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();//发送nACKelseIIC_Ack(); //发送ACK return receive;
}