openharmony1.1.3-通过i2c进行温湿度采集
openharmony1.1.3 通过i2c进行温湿度采集
温湿度传感器 也是挂载这个i2c总线上
初始化?
读数据
写数据
1.1.3 版本的i2c底层接口:
默认 系统没有开启i2c
CONFIG_I2C_SUPPORT is not set
CONFIG_I2C_SUPPORT = y
开启i2c
写一套通过i2c 读写温湿度的文件:
aht20.h:
#ifndef AHT20_H
#define AHT20_H
#include <stdbool.h> // 提供 bool 类型
#include "iot_errno.h" // 提供 IOT_SUCCESS/IOT_FAILURE
#include <stdint.h>
unsigned int AHT20_Init(void);
unsigned int AHT20_Calibrate(void);
unsigned int AHT20_SoftReset(void);
unsigned int AHT20_GetMeasureResult(float* temp, float* humi);
#endif // AHT20_H
aht20.c:
/*
* Copyright (C) 2021 HiHope Open Source Organization .
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "aht20.h"
#include <stdio.h>
#include <string.h>
// OpenHarmony HAL层I2C头文件(替换原海思私有头文件)
#include "iot_i2c.h"
// 延时函数头文件
#include "hi_time.h"
// 传感器硬件参数
#define AHT20_I2C_IDX 0 // OpenHarmony标准I2C总线索引
// 传感器命令定义
#define AHT20_INIT_CMD 0xBE // 初始化命令
#define AHT20_CALIBRATE_CMD 0xBA // 校准命令
#define AHT20_MEASURE_CMD 0xAC // 测量命令
#define AHT20_SOFT_RESET_CMD 0xBA // 软复位命令
#define AHT20_STARTUP_TIME 20*1000 // 上电启动时间
#define AHT20_CALIBRATION_TIME 40*1000 // 初始化(校准)时间
#define AHT20_MEASURE_TIME 75*1000 // 测量时间
#define AHT20_DEVICE_ADDR 0x38
#define AHT20_READ_ADDR ((0x38<<1)|0x1)
#define AHT20_WRITE_ADDR ((0x38<<1)|0x0)
#define AHT20_CMD_CALIBRATION 0xBE // 初始化(校准)命令
#define AHT20_CMD_CALIBRATION_ARG0 0x08
#define AHT20_CMD_CALIBRATION_ARG1 0x00
/**
* 传感器在采集时需要时间,主机发出测量指令(0xAC)后,延时75毫秒以上再读取转换后的数据并判断返回的状态位是否正常。
* 若状态比特位[Bit7]为0代表数据可正常读取,为1时传感器为忙状态,主机需要等待数据处理完成。
**/
#define AHT20_CMD_TRIGGER 0xAC // 触发测量命令
#define AHT20_CMD_TRIGGER_ARG0 0x33
#define AHT20_CMD_TRIGGER_ARG1 0x00
// 用于在无需关闭和再次打开电源的情况下,重新启动传感器系统,软复位所需时间不超过20 毫秒
#define AHT20_CMD_RESET 0xBA // 软复位命令
#define AHT20_CMD_STATUS 0x71 // 获取状态命令
/**
* STATUS 命令回复:
* 1. 初始化后触发测量之前,STATUS 只回复 1B 状态值;
* 2. 触发测量之后,STATUS 回复6B: 1B 状态值 + 2B 湿度 + 4b湿度 + 4b温度 + 2B 温度
* RH = Srh / 2^20 * 100%
* T = St / 2^20 * 200 - 50
**/
#define AHT20_STATUS_BUSY_SHIFT 7 // bit[7] Busy indication
#define AHT20_STATUS_BUSY_MASK (0x1<<AHT20_STATUS_BUSY_SHIFT)
#define AHT20_STATUS_BUSY(status) ((status & AHT20_STATUS_BUSY_MASK) >> AHT20_STATUS_BUSY_SHIFT)
#define AHT20_STATUS_MODE_SHIFT 5 // bit[6:5] Mode Status
#define AHT20_STATUS_MODE_MASK (0x3<<AHT20_STATUS_MODE_SHIFT)
#define AHT20_STATUS_MODE(status) ((status & AHT20_STATUS_MODE_MASK) >> AHT20_STATUS_MODE_SHIFT)
// bit[4] Reserved
#define AHT20_STATUS_CALI_SHIFT 3 // bit[3] CAL Enable
#define AHT20_STATUS_CALI_MASK (0x1<<AHT20_STATUS_CALI_SHIFT)
#define AHT20_STATUS_CALI(status) ((status & AHT20_STATUS_CALI_MASK) >> AHT20_STATUS_CALI_SHIFT)
// bit[2:0] Reserved
#define AHT20_STATUS_RESPONSE_MAX 6
#define AHT20_RESOLUTION (1<<20) // 2^20
#define AHT20_MAX_RETRY 10
// 全局变量:标记传感器是否初始化完成
static bool g_aht20Initialized = false;
/**
* @brief 内部函数:I2C读取数据(调用OpenHarmony HAL层接口)
*/
static unsigned int AHT20_I2C_Read(uint8_t* buffer, uint32_t buffLen) {
if (buffer == NULL || buffLen == 0) {
return IOT_FAILURE;
}
// 调用HAL层I2C读函数
return IoTI2cRead(AHT20_I2C_IDX, AHT20_READ_ADDR, buffer, buffLen);
}
/**
* @brief 内部函数:I2C写入数据(调用OpenHarmony HAL层接口)
*/
static unsigned int AHT20_I2C_Write(uint8_t* buffer, uint32_t buffLen) {
if (buffer == NULL || buffLen == 0) {
return IOT_FAILURE;
}
// 调用HAL层I2C写函数
return IoTI2cWrite(AHT20_I2C_IDX, AHT20_WRITE_ADDR, buffer, buffLen);
}
/**
* @brief 软件复位AHT20
*/
unsigned int AHT20_SoftReset(void) {
uint8_t resetCmd = AHT20_SOFT_RESET_CMD;
unsigned int retval = AHT20_I2C_Write(&resetCmd, 1);
hi_udelay(20000); // 复位后等待20ms
if (retval != IOT_SUCCESS) {
printf("AHT20 soft reset failed, err: %u\n", retval);
return retval;
}
return IOT_SUCCESS;
}
/**
* @brief 校准AHT20
*/
unsigned int AHT20_Calibrate(void) {
uint8_t calCmd[3] = {AHT20_CALIBRATE_CMD, 0x00, 0x00};
unsigned int retval = AHT20_I2C_Write(calCmd, 3);
hi_udelay(30000); // 校准等待30ms
if (retval != IOT_SUCCESS) {
printf("AHT20 calibrate failed, err: %u\n", retval);
return retval;
}
return IOT_SUCCESS;
}
/**
* @brief 初始化AHT20
*/
unsigned int AHT20_Init(void) {
uint8_t initCmd[3] = {AHT20_INIT_CMD, 0x08, 0x00};
unsigned int retval = 0;
// 1. 软复位传感器
retval = AHT20_SoftReset();
if (retval != IOT_SUCCESS) {
return retval;
}
// 2. 发送初始化命令
hi_udelay(40000); // 复位后等待40ms
retval = AHT20_I2C_Write(initCmd, 3);
if (retval != IOT_SUCCESS) {
printf("AHT20 init cmd failed, err: %u\n", retval);
return retval;
}
// 3. 标记初始化完成
g_aht20Initialized = true;
return IOT_SUCCESS;
}
/**
* @brief 获取温湿度测量结果
* @param temp 温度结果指针(单位:℃)
* @param humi 湿度结果指针(单位:%RH)
* @return 成功返回IOT_SUCCESS,失败返回对应错误码
*/
unsigned int AHT20_GetMeasureResult(float* temp, float* humi) {
// 参数合法性检查
if (temp == NULL || humi == NULL) {
return IOT_FAILURE;
}
if (!g_aht20Initialized) {
printf("AHT20 not initialized!\n");
return IOT_FAILURE;
}
uint8_t measureCmd[3] = {AHT20_MEASURE_CMD, 0x33, 0x00};
uint8_t dataBuf[6] = {0};
unsigned int retval = 0;
// 1. 发送测量命令
retval = AHT20_I2C_Write(measureCmd, 3);
if (retval != IOT_SUCCESS) {
printf("AHT20 measure cmd failed, err: %u\n", retval);
return retval;
}
// 2. 等待测量完成(最大80ms)
hi_udelay(80000);
// 3. 读取测量数据
retval = AHT20_I2C_Read(dataBuf, 6);
if (retval != IOT_SUCCESS) {
printf("AHT20 read data failed, err: %u\n", retval);
return retval;
}
// 4. 解析测量状态
if ((dataBuf[0] & 0x80) != 0) {
printf("AHT20 measure not ready!\n");
return IOT_FAILURE;
}
// 5. 计算温湿度
uint32_t humiRaw = ((uint32_t)dataBuf[1] << 12) |
((uint32_t)dataBuf[2] << 4) |
((dataBuf[3] & 0xF0) >> 4);
*humi = (humiRaw / 1048576.0f) * 100.0f;
uint32_t tempRaw = ((uint32_t)(dataBuf[3] & 0x0F) << 16) |
((uint32_t)dataBuf[4] << 8) |
dataBuf[5];
*temp = (tempRaw / 1048576.0f) * 200.0f - 50.0f;
return IOT_SUCCESS;
}
#define AHT20_I2C_IDX 0 // OpenHarmony标准I2C总线索引 hi3861 就一条总线
AHT20第地址:
#define AHT20_DEVICE_ADDR 0x38
#define AHT20_READ_ADDR ((0x38«1)|0x1)
#define AHT20_WRITE_ADDR ((0x38«1)|0x0)
**通I2C读写的方法:**这个是1.1.3 当中的方法 具体看i2c头文件的描述
/**
* @brief 内部函数:I2C读取数据(调用OpenHarmony HAL层接口)
/
static unsigned int AHT20_I2C_Read(uint8_t buffer, uint32_t buffLen) {
if (buffer == NULL || buffLen == 0) {
return IOT_FAILURE;
}
// 调用HAL层I2C读函数
return IoTI2cRead(AHT20_I2C_IDX, AHT20_READ_ADDR, buffer, buffLen);
}
/**
* @brief 内部函数:I2C写入数据(调用OpenHarmony HAL层接口)
/
static unsigned int AHT20_I2C_Write(uint8_t buffer, uint32_t buffLen) {
if (buffer == NULL || buffLen == 0) {
return IOT_FAILURE;
}
// 调用HAL层I2C写函数
return IoTI2cWrite(AHT20_I2C_IDX, AHT20_WRITE_ADDR, buffer, buffLen);
}
第一个最底层BUILD.gn:
import("//build/lite/config/component/lite_component.gni")
lite_component("iothardware") {
features = [
":aht20", #
]
}
static_library("aht20") {
sources = [
"aht20.c",
]
include_dirs = [
"//utils/native/lite/include",
"//kernel/liteos_m/components/cmsis/2.0",
"//base/iot_hardware/interfaces/kits/wifiiot_lite",
"//base/iot_hardware/peripheral/interfaces/kits",
]
}
在 ~/openharmony3/1.1.3/applications/sample/wifi-iot/app下 新建目录:aht20_test
目录下放2个文件: aht20_test.c 与BUILD.gn。 这里 aht20_test.c 就是根据厂家文档的 test 目录下的那个.c文件,进行的修改:
aht20_test.c 与BUILD.gn
aht20_test.c
/*
* Copyright (C) 2021 HiHope Open Source Organization .
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "aht20.h" // 引入驱动头文件
#include <stdio.h>
#include <unistd.h>
// OpenHarmony系统头文件(使用HAL层接口替代海思私有头文件)
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "hi_gpio.h"
#include "hi_io.h"
#include "iot_i2c.h" // HAL层I2C接口头文件
#include "iot_errno.h" // HAL层错误码定义
// 任务函数:循环采集温湿度
void Aht20TestTask(void* arg) {
(void)arg; // 消除未使用参数警告
unsigned int retval = 0; // 错误码类型统一为unsigned int(匹配HAL层)
float temp = 0.0f, humi = 0.0f;
// 步骤1:配置GPIO13/GPIO14为I2C0功能(Hi3861默认I2C0引脚)
hi_io_set_func(HI_IO_NAME_GPIO_13, HI_IO_FUNC_GPIO_13_I2C0_SDA); // SDA引脚
hi_io_set_func(HI_IO_NAME_GPIO_14, HI_IO_FUNC_GPIO_14_I2C0_SCL); // SCL引脚
// 步骤2:初始化I2C0(使用HAL层接口,波特率400kHz)
retval = IoTI2cInit(0, 400 * 1000); // 替换为HAL层初始化函数
if (retval != IOT_SUCCESS) { // 使用HAL层错误码(IOT_SUCCESS)
printf("I2C0 init failed, err: %u\n", retval);
return;
}
// 步骤3:初始化AHT20传感器
retval = AHT20_Init();
if (retval != IOT_SUCCESS) { // 与驱动中错误码统一
printf("AHT20 init failed, err: %u\n", retval);
return;
}
printf("AHT20 init success!\n");
// 步骤4:循环采集并打印数据(1秒/次)
while (1) {
retval = AHT20_GetMeasureResult(&temp, &humi);
if (retval == IOT_SUCCESS) {
printf("AHT20: Temp = %.2f℃, Humi = %.2f%%RH\n", temp, humi);
} else {
printf("AHT20 read failed, err: %u\n", retval);
}
sleep(1); // 延时1秒
}
}
// 任务创建函数:注册为OpenHarmony启动项
void Aht20Test(void) {
osThreadAttr_t taskAttr; // CMSIS-OS2任务属性结构体
// 配置任务属性
taskAttr.name = "Aht20TestTask"; // 任务名称
taskAttr.attr_bits = 0U; // 任务属性(默认0)
taskAttr.cb_mem = NULL; // 回调函数内存(无)
taskAttr.cb_size = 0U; // 回调函数内存大小(无)
taskAttr.stack_mem = NULL; // 任务栈内存(使用系统分配)
taskAttr.stack_size = 4096; // 任务栈大小(4KB)
taskAttr.priority = osPriorityNormal; // 任务优先级(正常)
// 创建任务
if (osThreadNew(Aht20TestTask, NULL, &taskAttr) == NULL) {
printf("Create Aht20TestTask failed!\n");
}
}
// 注册任务:系统启动时自动执行Aht20Test
APP_FEATURE_INIT(Aht20Test);
BUILD.gn:
static_library("aht20_test") {
sources = [
"aht20_test.c",
]
include_dirs = [
"/home/dragon/openharmony/1.1.3/applications/sample/wifi-iot/app/iothardware",
"//utils/native/lite/include",
"//kernel/liteos_m/kal",
"//base/iot_hardware/peripheral/interfaces/kits",
]
deps = [
"/home/dragon/openharmony/1.1.3/applications/sample/wifi-iot/app/iothardware:aht20",
]
}
第5步:修改app 下的 BUILD.gn
import("//build/lite/config/component/lite_component.gni")
lite_component("app") {
features = [
"aht20_test:aht20_test",
]
}