欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

STM32 F030C8 AHT10驱动程序 温湿度传感器

程序员文章站 2024-02-25 18:26:21
...

STM32 F030C8 AHT10驱动程序 温湿度传感器
本工程通过STM32CubeMX创建,使用HAL库。
添加.h和.c文件可以使用。
以下是.h文件(需要修改对应引脚与延迟函数):

#ifndef _AHT10_H__
#define _AHT10_H__
#include "stm32f0xx.h"

#include "delay.h"
#define AHT10_Delay_us(time)				delay_us(time)
#define AHT10_Delay_ms(time)				delay_ms(time)


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

#define AHT10_I2C_SCL_PIN      				GPIO_PIN_6
#define AHT10_I2C_SCL_GPIO_PORT   	       	GPIOB  
#define AHT10_I2C_SCL_GPIO_RCC      		__HAL_RCC_GPIOB_CLK_ENABLE()  
 
#define AHT10_I2C_SDA_PIN      				GPIO_PIN_7   
#define AHT10_I2C_SDA_GPIO_PORT   	       	GPIOB  
#define AHT10_I2C_SDA_GPIO_RCC      		__HAL_RCC_GPIOB_CLK_ENABLE()  

/* Private define ------------------------------------------------------------*/
#define AHT10_SCL_H         HAL_GPIO_WritePin(AHT10_I2C_SCL_GPIO_PORT, AHT10_I2C_SCL_PIN, GPIO_PIN_SET)   
#define AHT10_SCL_L         HAL_GPIO_WritePin(AHT10_I2C_SCL_GPIO_PORT, AHT10_I2C_SCL_PIN, GPIO_PIN_RESET)
   
#define AHT10_SDA_H         HAL_GPIO_WritePin(AHT10_I2C_SDA_GPIO_PORT, AHT10_I2C_SDA_PIN, GPIO_PIN_SET)
#define AHT10_SDA_L         HAL_GPIO_WritePin(AHT10_I2C_SDA_GPIO_PORT, AHT10_I2C_SDA_PIN, GPIO_PIN_RESET)
#define AHT10_READ_SDA      HAL_GPIO_ReadPin(AHT10_I2C_SDA_GPIO_PORT,AHT10_I2C_SDA_PIN)


/*****************函数声明,对外接口******************/
void AHT10Init(void);
uint8_t AHT10Check(void);
void AHT10Reset(void);
uint8_t AHT10ReadData(uint16_t *temperature,uint16_t *humidity);
#endif

以下是.c文件:

#include "AHT10.h"


//初始化IIC
static void AHT10_IIC_Init(void)
{					     
	GPIO_InitTypeDef GPIO_InitStruct;
	AHT10_I2C_SCL_GPIO_RCC;
	AHT10_I2C_SDA_GPIO_RCC;//使能GPIO时钟

	GPIO_InitStruct.Pin = AHT10_I2C_SCL_PIN;
  	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  	GPIO_InitStruct.Pull = GPIO_NOPULL;
  	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  	HAL_GPIO_Init(AHT10_I2C_SCL_GPIO_PORT, &GPIO_InitStruct);
	
	GPIO_InitStruct.Pin = AHT10_I2C_SDA_PIN;
  	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  	GPIO_InitStruct.Pull = GPIO_NOPULL;
  	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  	HAL_GPIO_Init(AHT10_I2C_SDA_GPIO_PORT, &GPIO_InitStruct);
	
	AHT10_SDA_H;
	AHT10_SCL_H;
}

static void AHT10_SDA_OUT(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	AHT10_I2C_SDA_GPIO_RCC;	//使能GPIO时钟
	GPIO_InitStruct.Pin = AHT10_I2C_SDA_PIN;
  	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  	GPIO_InitStruct.Pull = GPIO_NOPULL;
  	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;	
  	HAL_GPIO_Init(AHT10_I2C_SDA_GPIO_PORT, &GPIO_InitStruct);
}

static void AHT10_SDA_IN(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	AHT10_I2C_SDA_GPIO_RCC;	//使能GPIO时钟
	GPIO_InitStruct.Pin = AHT10_I2C_SDA_PIN;
  	GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  	GPIO_InitStruct.Pull = GPIO_NOPULL;
  	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;	
  	HAL_GPIO_Init(AHT10_I2C_SDA_GPIO_PORT, &GPIO_InitStruct);
}

//产生IIC起始信号
static void AHT10_IIC_Start(void)
{
	AHT10_SDA_OUT();     //sda线输出
	AHT10_SDA_H;	  	  
	AHT10_SCL_H;
	AHT10_Delay_us(4);
 	AHT10_SDA_L;//START:when CLK is high,DATA change form high to low 
	AHT10_Delay_us(4);
	AHT10_SCL_L;//钳住I2C总线,准备发送或接收数据 
}	  
//产生IIC停止信号
static void AHT10_IIC_Stop(void)
{
	AHT10_SDA_OUT();//sda线输出
	AHT10_SCL_L;
	AHT10_SDA_L;//STOP:when CLK is high DATA change form low to high
 	AHT10_Delay_us(4);
	AHT10_SCL_H; 
	AHT10_SDA_H;//发送I2C总线结束信号
	AHT10_Delay_us(4);							   	
}
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
static uint8_t AHT10_IIC_Wait_Ack(void)
{
	uint8_t ucErrTime=0;
	AHT10_SDA_IN();      //SDA设置为输入  
	AHT10_SDA_H;
	AHT10_Delay_us(1);	   
	AHT10_SCL_H;
	AHT10_Delay_us(1);	 
	while(AHT10_READ_SDA)
	{
		ucErrTime++;
		if(ucErrTime>250)
		{
			AHT10_IIC_Stop();
			return 1;
		}
	}
	AHT10_SCL_L;//时钟输出0 	   
	return 0;  
} 
//产生ACK应答
static void AHT10_IIC_Ack(void)
{
	AHT10_SCL_L;
	AHT10_SDA_OUT();
	AHT10_SDA_L;
	AHT10_Delay_us(2);
	AHT10_SCL_H;
	AHT10_Delay_us(2);
	AHT10_SCL_L;
}
//不产生ACK应答		    
static void AHT10_IIC_NAck(void)
{
	AHT10_SCL_L;
	AHT10_SDA_OUT();
	AHT10_SDA_H;
	AHT10_Delay_us(2);
	AHT10_SCL_H;
	AHT10_Delay_us(2);
	AHT10_SCL_L;
}					 				     
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答			  
static void AHT10_IIC_Send_Byte(uint8_t txd)
{                        
    uint8_t t;   
	AHT10_SDA_OUT(); 	    
    AHT10_SCL_L;//拉低时钟开始数据传输
    for(t=0;t<8;t++)
    {              
        //IIC_SDA=(txd&0x80)>>7;
		if((txd&0x80)>>7)
			AHT10_SDA_H;
		else
			AHT10_SDA_L;
		txd<<=1; 	  
		AHT10_Delay_us(2);   //对TEA5767这三个延时都是必须的
		AHT10_SCL_H;
		AHT10_Delay_us(2); 
		AHT10_SCL_L;	
		AHT10_Delay_us(2);
    }	 
} 	    
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK   
static uint8_t AHT10_IIC_Read_Byte(unsigned char ack)
{
	unsigned char i,receive=0;
	AHT10_SDA_IN();//SDA设置为输入
    for(i=0;i<8;i++ )
	{
        AHT10_SCL_L; 
        AHT10_Delay_us(2);
		AHT10_SCL_H;
        receive<<=1;
        if(AHT10_READ_SDA)receive++;   
			AHT10_Delay_us(1); 
    }					 
    if (!ack)
        AHT10_IIC_NAck();//发送nACK
    else
        AHT10_IIC_Ack(); //发送ACK   
    return receive;
}



/**
brief 检查AHT10是否存在
param NONE
return 0存在  1不存在
*/
uint8_t AHT10Check(void)
{
	uint8_t ack=0;
	AHT10_IIC_Start();
	AHT10_IIC_Send_Byte(AHT10_ADDRESS);
	ack=AHT10_IIC_Wait_Ack();
	AHT10_IIC_Stop();	
	return ack;
}

/**
brief AHT10软复位
param NONE
return NONE
*/
void AHT10Reset(void)
{
	AHT10_IIC_Start();
	AHT10_IIC_Send_Byte(AHT10_WRITE);
	AHT10_IIC_Wait_Ack();
	AHT10_IIC_Send_Byte(0xba);
	AHT10_IIC_Wait_Ack();
	AHT10_IIC_Stop();	
}



/**
brief AHT10初始化函数
param NONE
return NONE
*/
void AHT10Init()
{
	AHT10_IIC_Init();
	
	AHT10_IIC_Start();
	AHT10_IIC_Send_Byte(AHT10_ADDRESS);
	AHT10_IIC_Send_Byte(0xe1);	
	AHT10_IIC_Send_Byte(0x08);
	AHT10_IIC_Send_Byte(0x00);
	AHT10_IIC_Stop();	
	AHT10_Delay_ms(40);//延时20ms让传感器稳定
}

/**
brief 检查AHT10读温湿度数据
param *temperature:需要读出的温度数据,uint16_t指针类型,精度范围+-0.3C
param *humidity:需要读出的湿度数据,uint16_t指针类型,精度范围+-2RH
return 1 读数据正常 0读数据失败
*/
uint8_t AHT10ReadData(uint16_t *temperature,uint16_t *humidity)
{
	uint8_t ack;
	uint32_t SRH=0,ST=0;
	uint8_t databuff[6];
	AHT10_IIC_Start();
	AHT10_IIC_Send_Byte(AHT10_WRITE);
	AHT10_IIC_Wait_Ack();
	AHT10_IIC_Send_Byte(0xac);
	AHT10_IIC_Wait_Ack();
	AHT10_IIC_Send_Byte(0x33);
	AHT10_IIC_Wait_Ack();
	AHT10_IIC_Send_Byte(0x00);
	AHT10_IIC_Wait_Ack();
	AHT10_IIC_Stop();	  
	AHT10_Delay_ms(80);//延时一会等待数据读出
	AHT10_IIC_Start();
	AHT10_IIC_Send_Byte(AHT10_READ);
	AHT10_IIC_Wait_Ack();
	ack=AHT10_IIC_Read_Byte(1);
	if((ack&0x40)==0)
	{
		databuff[0]=AHT10_IIC_Read_Byte(1);
		databuff[1]=AHT10_IIC_Read_Byte(1);
		databuff[2]=AHT10_IIC_Read_Byte(1);
		databuff[3]=AHT10_IIC_Read_Byte(1);
		databuff[4]=AHT10_IIC_Read_Byte(0);
		AHT10_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;//未放大,不过返回值最好为float
		*humidity = SRH*1000/1024/1024;  //计算得到湿度值(放大了10倍,如果c1=523,表示现在湿度为52.3%)
	  	*temperature = ST *200*10/1024/1024-500;//计算得到温度值(放大了10倍,如果t1=245,表示现在温度为24.5℃)
		//为读取的数据更稳定,还可以使用平均值滤波或者窗口滤波,或者前面读取的值与后面的值相差不能太大。
		return 1;
	}
	AHT10_IIC_Stop();	
	return 0;
}

工程文件以及AHT10规格书:AHT10驱动程序