它广泛应用于暖通空调 、除湿器、测试及检测设备、消费品、汽车 、自动控制、数据记录器、气象站、家电、湿度调节、医疗及其他相关湿度检测控制等领域。
查看我们之前分享的网文,对比DHT21的参数如下:
DHT11及DHT21温湿度传感器时序图解析(STM32)
由上对比,AHT20的精度要比DHT21的精度要好,而且价格又低了很多。
与开发板连接情况如下:
管脚名称 | 复用描述 |
---|---|
GPIO_13 | GPIO_13/ADC6/PWM4_OUT/I2C0_SDA/ UART0_LOG_TXD |
GPIO_14 | GPIO_14/PWM5_OUT/I2C0_SCL/ UART0_LOG_RXD |
由上我们知道,这个AHT20使用的Hi3861芯片的I2C0。
AHT20的鸿蒙驱动代码,润和公司的开源库中已经有了,我们就不重复造轮子了,直接使用,然后结合AHT20的数据手册分析一下代码。
润和公司开源的鸿蒙OS AHT20 数字温湿度传感器驱动库:https://gitee.com/hihopeorg/harmonyos-aht20
~/harmony/code/code-1.0/applications/sample/wifi-iot/app
目录下执行
git clone https://github.com/xusiwei/harmonyos-aht20
,获取源码。
~/harmony/code/code-1.0
目录下执行:
python build.py wifiiot
I2C发送的首字节包括7位的I2C设备地址 0x38和一个SDA方向位X(读R:'1',写W:'0')。
手册中描述的模块地址定义如下:
由上分析,我们得到读数据操作的首字节AHT20_READ_ADDR
和写数据操作的首字节AHT20_WRITE_ADDR
分别定义如下:
#define AHT20_DEVICE_ADDR 0x38
#define AHT20_READ_ADDR ((0x38<<1)|0x1)
#define AHT20_WRITE_ADDR ((0x38<<1)|0x0)
AHT20 采用标准的 I2C协议进行通讯。
对于I2C通信我们之前分享过网文:
STM32 I2C通信操作24C02写数据、读数据
4位数码管显示模块驱动
基于鸿蒙OS移植OLED驱动程序
上图中的AHT20_Write()
函数中调用了I2cWrite()
函数。
I2cWrite()
函数是系统中I2C进行写操作的函数,这个函数的参数含义解释如下:
参数1:WifiIotI2cIdx id ,这个参数是使用的I2C的ID,这个参数可选下面枚举中的一个值:
typedef enum {
/** I2C hardware index 0 */
WIFI_IOT_I2C_IDX_0,
/** I2C hardware index 1 */
WIFI_IOT_I2C_IDX_1,
} WifiIotI2cIdx;
因为我们这里使用的是I2C0,所以这个参数应该为:WIFI_IOT_I2C_IDX_0 。
参数2:unsigned short deviceAddr,这个参数是I2C总线下面的设备地址,因为这是一个写操作,所以这个参数我们选用上面的宏定义:AHT20_WRITE_ADDR 。
参数3:const WifiIotI2cData *i2cData ,这个参数是我们要发送的数据,该变量的数据类型为一个结构体类型:HalWifiIotI2cData ,该结构体的定义如下。
/**
* @brief Defines I2C data transmission attributes.
*/
typedef struct {
/** Pointer to the buffer storing data to send */
unsigned char *sendBuf;
/** Length of data to send */
unsigned int sendLen;
/** Pointer to the buffer for storing data to receive */
unsigned char *receiveBuf;
/** Length of data received */
unsigned int receiveLen;
} HalWifiIotI2cData;
上图中的AHT20_Read()
函数中调用了I2cRead()
函数。
I2cRead()
函数是系统中I2C进行读操作的函数。
I2cRead()
函数的参数与I2cWrite()
函数的参数类似,只是参数3:const WifiIotI2cData \*i2cData
,这个参数用于接收我们读取到的数据。
AHT20常用的命令有:
通过发送0x71可以获取一个字节的状态字,状态字各位的含义描述如下:
AHT20模块的状态判断通过下面AHT20_Calibrate()
函数来判断,具体执行过程如下图所示:
注:在第一步的校准状态检验只需要上电时检查,在正常过程无需操作。
上面代码中有一个这样的指令:AHT20_ResetCommand()
这个命令用于在无需关闭和再次打开电源的情况下,重新启动传感器系统。
在接收到这个命令之后,传感器系统开始重新初始化,并恢复默认设置状态,软复位所需时间不超过 20 毫秒。
图中灰色部分由 AHT20 控制。
#define AHT20_CMD_RESET 0xBA // 软复位命令
// 发送软复位命令
static uint32_t AHT20_ResetCommand(void)
{
uint8_t resetCmd[] = {AHT20_CMD_RESET};
return AHT20_Write(resetCmd, sizeof(resetCmd));
}
触发测量命令发送的数据如下:
具体使用的代码如下:
#define AHT20_CMD_TRIGGER 0xAC // 触发测量命令
#define AHT20_CMD_TRIGGER_ARG0 0x33
#define AHT20_CMD_TRIGGER_ARG1 0x00
// 发送 触发测量 命令,开始测量
uint32_t AHT20_StartMeasure(void)
{
uint8_t triggerCmd[] = {AHT20_CMD_TRIGGER, AHT20_CMD_TRIGGER_ARG0, AHT20_CMD_TRIGGER_ARG1};
return AHT20_Write(triggerCmd, sizeof(triggerCmd));
}
注:传感器在采集时需要时间,主机发出测量指令(0xAC)后,延时75毫秒以上再读取转换后的数据并判断返回的状态位是否正常。若状态比特位[Bit7]为0代表设备闲,可正常读取,为1时传感器为忙状态,主机需要等待数据处理完成。
上图中蓝色背景的六个字节数据中,红色方框框住的为湿度数据,组成一个20bit长度的一个整形数;紫色方框框住的20bit为温度数据。
湿度数据按下面代码实现拼接:
#define AHT20_RESOLUTION (1<<20) // 2^20
uint32_t humiRaw = buffer[1];
humiRaw = (humiRaw << 8) | buffer[2];
humiRaw = (humiRaw << 4) | ((buffer[3] & 0xF0) >> 4);
通过手册我们得知相对湿度的计算公式如下:
上面代码求得的 humiRaw 即为上图公式中的Srh,所以根据上图公式,使用如下代码即可获得相对湿度RH。
*humi = humiRaw / (float)AHT20_RESOLUTION * 100;
按如下方式合并温度数据的20bit数据:
uint32_t tempRaw = buffer[3] & 0x0F;
tempRaw = (tempRaw << 8) | buffer[4];
tempRaw = (tempRaw << 8) | buffer[5];
查看手册,我们知道20bit的温度数据跟℃的换算关系如下:
用代码具体实现如下:
*temp = tempRaw / (float)AHT20_RESOLUTION * 200 - 50;
将上面编译之后的结果下载验证,输出如下:
公众号留言区置顶留言获取AHT20的数据手册。
结合数据手册一起看本文,理解更透彻,自己试试拿自己手里的硬件能否顺利驱动AHT20,无论STM32还是51单片机驱动原理都是一样的,自己试试哈。
如果通过本文你学会了看数据手册的方法,点个“在看”,让我看看有多少人有收获呗?
ps: 文章首发于电子发烧友。
程序员小哈带你玩转嵌入式,微信搜索:嵌入式从0到1,更多干货等着你。