介绍
本篇教程基于 Hi3861 WiFi-IoT 开发板 + OpenHarmony 1.0 环境,实现SHT40 温湿度采集 + 温度超过阈值自动开启风扇功能。
代码说明
- 每秒钟采集一次温度、湿度
- 温度超过设定阈值 → 自动开启风扇
- 温度低于阈值 → 自动关闭风扇
- 串口实时打印温湿度与运行状态
代码
// 标准输入输出头文件:用于 printf 打印
#include <stdio.h>
// 延时头文件:用于 usleep、sleep 延时函数
#include <unistd.h>
// 标准数据类型头文件:定义 uint8_t 等类型
#include <stdint.h>
// 老版本 Hi3861 GPIO 驱动头文件
#include "wifiiot_gpio.h"
// 老版本 Hi3861 GPIO 复用功能配置头文件
#include "wifiiot_gpio_ex.h"
// 老版本 Hi3861 I2C 驱动头文件
#include "wifiiot_i2c.h"
// OpenHarmony 系统初始化头文件
#include "ohos_init.h"
// ==================== 宏定义配置区(规范、专业、适合博客) ====================
// 温度阈值:超过该温度自动开启风扇
#define TEMP_THRESHOLD 25.0f
// SHT40 传感器 I2C 地址
#define SHT40_ADDR 0x88
// SHT40 高精度测量命令(官方固定值)
#define SHT40_MEASURE_HIGH 0xFD
// ==================== I2C 初始化函数 ====================
// 作用:初始化 I2C 通信引脚,用于 SHT40 温湿度传感器
static void I2C_Init(void)
{
// GPIO13 复用为 I2C0_SDA 数据引脚
IoSetFunc(WIFI_IOT_IO_NAME_GPIO_13, WIFI_IOT_IO_FUNC_GPIO_13_I2C0_SDA);
// GPIO14 复用为 I2C0_SCL 时钟引脚
IoSetFunc(WIFI_IOT_IO_NAME_GPIO_14, WIFI_IOT_IO_FUNC_GPIO_14_I2C0_SCL);
// 初始化 I2C0,波特率 400KHz
I2cInit(WIFI_IOT_I2C_IDX_0, 400 * 1000);
}
// ==================== 风扇 GPIO 初始化函数 ====================
// 作用:初始化风扇控制的两个 GPIO 引脚
static void Fan_Init(void)
{
// 初始化 GPIO 外设
GpioInit();
// 配置 GPIO8 为普通输出模式(风扇使能)
IoSetFunc(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_IO_FUNC_GPIO_8_GPIO);
GpioSetDir(WIFI_IOT_IO_NAME_GPIO_8, WIFI_IOT_GPIO_DIR_OUT);
// 配置 GPIO12 为普通输出模式(风扇电源/继电器)
IoSetFunc(WIFI_IOT_IO_NAME_GPIO_12, WIFI_IOT_IO_FUNC_GPIO_12_GPIO);
GpioSetDir(WIFI_IOT_IO_NAME_GPIO_12, WIFI_IOT_GPIO_DIR_OUT);
}
// ==================== 风扇开启函数 ====================
// 作用:同时打开 GPIO8 和 GPIO12,风扇开始转动
static void Fan_On(void)
{
GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_8, 1); // 风扇使能打开
GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_12, 1); // 风扇电源打开
}
// ==================== 风扇关闭函数 ====================
// 作用:关闭风扇使能,风扇停止
static void Fan_Off(void)
{
GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_8, 0); // 风扇使能关闭
GpioSetOutputVal(WIFI_IOT_IO_NAME_GPIO_12, 1); // 电源保持开启
}
// ==================== SHT40 温湿度读取函数 ====================
static int SHT40_Read(float *temp, float *humi)
{
// 定义变量存储测量命令(正确!可正常取地址)
uint8_t cmd = SHT40_MEASURE_HIGH;
uint8_t data[6] = {0};
WifiIotI2cData i2cData;
// 发送测量指令给 SHT40
i2cData.sendBuf = &cmd;
i2cData.sendLen = 1;
i2cData.receiveBuf = NULL;
i2cData.receiveLen = 0;
I2cWrite(WIFI_IOT_I2C_IDX_0, SHT40_ADDR, &i2cData);
// 等待传感器测量完成
usleep(20000);
// 读取 6 字节温湿度原始数据
i2cData.sendBuf = NULL;
i2cData.sendLen = 0;
i2cData.receiveBuf = data;
i2cData.receiveLen = 6;
I2cRead(WIFI_IOT_I2C_IDX_0, SHT40_ADDR, &i2cData);
// SHT40 官方公式计算温度
*temp = -45.0f + 175.0f * ((data[0] << 8) | data[1]) / 65535.0f;
// SHT40 官方公式计算湿度
*humi = -6.0f + 125.0f * ((data[3] << 8) | data[4]) / 65535.0f;
// 限制湿度范围
if (*humi < 0) *humi = 0;
if (*humi > 100) *humi = 100;
return 0;
}
// ==================== 主任务函数 ====================
void AutoFanTask(void)
{
float temp, humi;
I2C_Init(); // 初始化 I2C
Fan_Init(); // 初始化风扇
printf("=== Auto Fan Control ===\r\n");
printf("Temp Threshold: %.1f C\r\n\r\n", TEMP_THRESHOLD);
while (1) {
SHT40_Read(&temp, &humi); // 读取温湿度
printf("Temp: %.1f C Humi: %.1f %%RH\r\n", temp, humi);
// 温度超过阈值 → 开风扇
if (temp > TEMP_THRESHOLD) {
Fan_On();
printf("Status: Hot -> Fan ON\r\n\r\n");
} else {
Fan_Off();
printf("Status: Normal -> Fan OFF\r\n\r\n");
}
sleep(1);
}
}
// 系统启动时自动运行
SYS_RUN(AutoFanTask);
BUILD.gn
# static_library中指定业务模块的编译结果.为静态库文件libmyapp.a,开发者根据实际情况完成填写。
#sources中指定静态库.a所依赖的.c文件及其路径,若路径中包含"//"则表示绝对路径(此处为代码根路径),若不包含"//"则表示相对路径。
#include_dirs中指定source所需要依赖的.h文件路径。
static_library("app") {
sources = [
"main.c"
]
include_dirs = [
"//utils/native/lite/include",
"//base/iot_hardware/interfaces/kits/wifiiot_lite",
"//kernel/liteos_m/components/cmsis/2.0",
]
}
运行
- 当温度高于
25°时,风扇开始转动 - 当温度低于
25°时,风扇才停止
打印
可以查看温湿度
缺点
- 当温度高于
25°时,风扇开始转动 - 当温度低于
25°时,如:24.9°风扇就停止 - 风扇停止后,温度立即上升,导致风扇马上开始转
解决bug,详见链接:
https://www.malaoshi.top/show_1GW32HhN3EC9.html
