STM32F4控制AHT20读取温湿度

STM32F4控制AHT20读取温湿度1. IIC协议相关 IIC协议实现可以是硬件IIC和软件IIC 硬件IIC的优点是直接通过硬件操作,速度比较快,一般是在一些传感器的器件中。 软件IIC一般都是在单片机中通过控制管脚来实现的,特点是

1. IIC协议相关

  1. IIC协议实现可以是硬件IIC软件IIC
1. 硬件IIC是需要发送命令给他,然后器件里面的集成电路,硬件实现IIC发送数据,
硬件接收到命令后,就会将数据保存到寄存器里面,然后就可以通过单片机实现的软件IIC来进行读取数据
2. 软件IIC就是通过操作单片机中的两个GPIO管脚来进行IIC时序的操作

硬件IIC的优点是直接通过硬件操作,速度比较快,一般是在一些传感器的器件中。

软件IIC一般都是在单片机中通过控制管脚来实现的,特点是比较灵活。

  1. 有关IIC时序的知识 参考如下链接,程序相关 电路相关

2. AHT20的温湿度读取

  1. 一般AHT20的地址是0x38
  2. 有关的一些命令是如下图

image.png

  1. 使用的流程图是

image.png

  1. 有关程序如下

    软硬件环境

     硬件:AHT20模块网上购买,单片机STM32F429
     软件:keil V5
    

AHT20.h

#ifndef __AHT20_H
#define __AHT20_H
#include "system.h"
#include "myiic.h"
#include "SysTick.h"
 
#define ATH20_SLAVE_ADDRESS		0x38		/* I2C从机地址 */
 
//****************************************
// 定义 AHT20 内部地址
//****************************************
#define	AHT20_STATUS_REG		0x71	//状态字 寄存器地址
#define	AHT20_INIT_REG			0xBE	//初始化 寄存器地址
#define	AHT20_SoftReset			0xBA	//软复位 单指令
#define	AHT20_TrigMeasure_REG	0xAC	//触发测量 寄存器地址
 
// 存储AHT20传感器信息的结构体
struct m_AHT20
{
	uint8_t alive;	// 0-器件不存在; 1-器件存在
	uint8_t flag;	// 读取/计算错误标志位。0-读取/计算数据正常; 1-读取/计算设备失败
	uint32_t HT[2];	// 湿度、温度 原始传感器的值,20Bit
	
	float RH;		// 湿度,转换单位后的实际值,标准单位%
	float Temp;		// 温度,转换单位后的实际值,标准单位°C
};
 
 
uint8_t AHT20_Init(void);
uint8_t AHT20_ReadHT(uint32_t *HT);
uint8_t StandardUnitCon(struct m_AHT20* aht);
 
#endif

AHT20.c

#include "AHT20.h"
 
/** * @brief 读AHT20 设备状态字 * @param void * @retval uint8_t 设备状态字 */
static uint8_t AHT20_ReadStatusCmd(void)
{
	uint8_t tmp[1];
	Soft_I2C_Read(ATH20_SLAVE_ADDRESS, AHT20_STATUS_REG, 1, tmp);
	return tmp[0];
}
 
/** * @brief 读AHT20 设备状态字 中的Bit3: 校准使能位 * @param void * @retval uint8_t 校准使能位:1 - 已校准; 0 - 未校准 */
static uint8_t AHT20_ReadCalEnableCmd(void)
{
	uint8_t tmp;
	tmp = AHT20_ReadStatusCmd();
	return (tmp>>3)&0x01;
}
 
/** * @brief 读AHT20 设备状态字 中的Bit7: 忙标志 * @param void * @retval uint8_t 忙标志:1 - 设备忙; 0 - 设备空闲 */
static uint8_t AHT20_ReadBusyCmd(void)
{
	uint8_t tmp;
	tmp = AHT20_ReadStatusCmd();
	return (tmp>>7)&0x01;
}
 
/** * @brief AHT20 芯片初始化命令 * @param void * @retval void */
static void AHT20_IcInitCmd(void)
{
	uint8_t tmp[2];
	tmp[0] = 0x08;
	tmp[1] = 0x00;
	Soft_I2C_Write(ATH20_SLAVE_ADDRESS, AHT20_INIT_REG, 2, tmp);
}
 
/** * @brief AHT20 触发测量命令 * @param void * @retval void */
static void AHT20_TrigMeasureCmd(void)
{
	uint8_t tmp[2];
	tmp[0] = 0x33;
	tmp[1] = 0x00;
	Soft_I2C_Write(ATH20_SLAVE_ADDRESS, AHT20_TrigMeasure_REG, 2, tmp);
}
 
/** * @brief AHT20 软复位命令 * @param void * @retval void */
static void AHT20_SoftResetCmd(void)
{
	uint8_t tmp[1];
	Soft_I2C_Write(ATH20_SLAVE_ADDRESS, AHT20_SoftReset, 0, tmp);
}
 
/** * @brief AHT20 设备初始化 * @param void * @retval uint8_t:0 - 初始化AHT20设备成功; 1 - 初始化AHT20失败,可能设备不存在或器件已损坏 */
uint8_t AHT20_Init(void)
{
	uint8_t rcnt = 2+1;//软复位命令 重试次数,2次
	uint8_t icnt = 2+1;//初始化命令 重试次数,2次
	
	while(--rcnt)
	{
		icnt = 2+1;
		
		delay_ms(40);//上电后要等待40ms
		// 读取温湿度之前,首先检查[校准使能位]是否为1
		while((!AHT20_ReadCalEnableCmd()) && (--icnt))// 2次重试机会
		{
			delay_ms(10);
			// 如果不为1,要发送初始化命令
			AHT20_IcInitCmd();
			delay_ms(200);//这个时间不确定,手册没讲
		}
		
		if(icnt)//[校准使能位]为1,校准正常
		{
			break;//退出rcnt循环
		}
		else//[校准使能位]为0,校准错误
		{
			AHT20_SoftResetCmd();//软复位AHT20器件,重试
			delay_ms(200);//这个时间不确定,手册没讲
		}
	}
	
	if(rcnt)
	{
		delay_ms(200);//这个时间不确定,手册没讲
		return 0;// AHT20设备初始化正常
	}
	else
	{
		return 1;// AHT20设备初始化失败
	}
}
 
/** * @brief AHT20 设备读取 相对湿度和温度(原始数据20Bit) * @param uint32_t *HT:存储20Bit原始数据的uint32数组 * @retval uint8_t:0-读取数据正常; 1-读取设备失败,设备一直处于忙状态,不能获取数据 */
uint8_t AHT20_ReadHT(uint32_t *HT)
{
	uint8_t cnt=3+1;//忙标志 重试次数,3次
	uint8_t tmp[6];
	uint32_t RetuData = 0;
	
	// 发送触发测量命令
	AHT20_TrigMeasureCmd();
	
	do{
		delay_ms(75);//等待75ms待测量完成,忙标志Bit7为0
	}while(AHT20_ReadBusyCmd() && (--cnt));//重试3次
	
	if(cnt)//设备闲,可以读温湿度数据
	{
		delay_ms(5);
		// 读温湿度数据
		Soft_I2C_Read(ATH20_SLAVE_ADDRESS, AHT20_STATUS_REG, 6, tmp);
		// 计算相对湿度RH。原始值,未计算为标准单位%。
		RetuData = 0;
		RetuData = (RetuData|tmp[1]) << 8;
		RetuData = (RetuData|tmp[2]) << 8;
		RetuData = (RetuData|tmp[3]);
		RetuData = RetuData >> 4;
		HT[0] = RetuData;
		
		// 计算温度T。原始值,未计算为标准单位°C。
		RetuData = 0;
		RetuData = (RetuData|tmp[3]) << 8;
		RetuData = (RetuData|tmp[4]) << 8;
		RetuData = (RetuData|tmp[5]);
		RetuData = RetuData&0xfffff;
		HT[1] = RetuData;
		
		return 0;
	}
	else//设备忙,返回读取失败
	{
		return 1;
	}
}
 
/** * @brief AHT20 温湿度信号转换(由20Bit原始数据,转换为标准单位RH=%,T=°C) * @param struct m_AHT20* aht:存储AHT20传感器信息的结构体 * @retval uint8_t:0-计算数据正常; 1-计算数据失败,计算值超出元件手册规格范围 */
uint8_t StandardUnitCon(struct m_AHT20* aht)
{
	aht->RH = (double)aht->HT[0] *100 / 1048576;//2^20=1048576 //原式:(double)aht->HT[0] / 1048576 *100,为了浮点精度改为现在的
	aht->Temp = (double)aht->HT[1] *200 / 1048576 -50;
	      printf("Humidity:%.1f%%\r\n",aht->RH);
        printf("Temperature:%.1f\r\n",aht->Temp);
        printf("\r\n");
	
	
	//限幅,RH=0~100%; Temp=-40~85°C
	if((aht->RH >=0)&&(aht->RH <=100) && (aht->Temp >=-40)&&(aht->Temp <=85))
	{
		aht->flag = 0;
		return 0;//测量数据正常
	}
	else
	{
		aht->flag = 1;
		return 1;//测量数据超出范围,错误
	}
}

3. 总结

  1. 代码中间调试出问题是在初始发送地址的地方出错了,地址是0x38,发送的时候是高7位是地址,低地址位是读写位读是1,写是0。
  2. 这份代码看起来比较好,封装的比较好。
  3. 测试过另一份代码,问题是出在获取数据的时候,主机(单片机)需要发送应答位是1,而函数IIC_wait_ack()函数返回值,如果是接受成功,会返回ack是0,误以为ack是1,导致后面没有发送应答位

image.png

  1. 总之,调试的过程中,看着文档,单步调试,细心就能够找到问题。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/22734.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注