这篇文章记录一下我使用 FRDM-MCXW72 开发板,在 Zephyr RTOS 下驱动 SHT30 温湿度传感器 的过程。
本实验通过 I2C 接口读取 SHT30 的温度和湿度数据,然后通过串口打印出来。
一、实验目标
本次实验实现以下功能:
使用 FRDM-MCXW72 运行 Zephyr 程序;
通过 I2C 接口连接 SHT30 温湿度传感器;
使用 Zephyr 的 Sensor API 读取温度和湿度;
通过串口终端周期性打印温湿度数据。
二、硬件准备
需要准备以下硬件:
| 硬件 | 数量 |
| - | - |
| FRDM-MCXW72 开发板 | 1 |
| SHT30 温湿度传感器模块 | 1 |
| 杜邦线 | 若干 |
| USB 数据线 | 1 |
SHT30 是一款常见的数字温湿度传感器,通信接口一般为 I2C。
常见 SHT30 模块默认 I2C 地址为:
0x44
有些模块可以通过 ADDR 引脚切换为:
0x45
本文默认使用地址:
0x44
三、硬件接线
SHT30 通过 I2C 与开发板通信,一般只需要连接 4 根线。
| SHT30 引脚 | FRDM-MCXW72 引脚 | 说明 |
| - | - | - |
| VCC / VIN | 3.3V | 电源 |
| GND | GND | 地 |
| SDA | I2C SDA | I2C 数据线 |
| SCL | I2C SCL | I2C 时钟线 |
注意事项:
SHT30 建议使用 3.3V 供电;
SDA 和 SCL 不要接反;
如果使用的是带 Arduino 接口的模块,可以优先接到开发板 Arduino 接口的 SDA / SCL;
如果后面读取失败,优先检查 I2C 总线和地址是否正确。
四、Zephyr 环境准备
我这里使用的是 Windows 下的 Zephyr 开发环境。
如果已经安装好 Zephyr,可以直接进入工作目录并激活虚拟环境:
cd D:\Zephyr zephyrproject\.venv\Scripts\Activate.ps1
进入 Zephyr 工作区:
cd D:\Zephyr\zephyrproject
查看 west 是否正常:
west --version
查看当前 Zephyr 是否支持 FRDM-MCXW72:
west boards | Select-String -Pattern "mcxw72" -CaseSensitive:$false
如果能看到类似下面的开发板名称,说明环境正常:
frdm_mcxw72
或者可能是带 qualifier 的形式,例如:
frdm_mcxw72/mcxw727c
后面编译时,板卡名称以自己电脑上 west boards 实际输出为准。
五、创建工程目录
在 Zephyr 工作区下面创建一个 SHT30 示例工程。
cd D:\Zephyr\zephyrproject mkdir sht30_demo cd sht30_demo mkdir src
工程结构如下:
sht30_demo ├── CMakeLists.txt ├── prj.conf ├── app.overlay └── src └── main.c
六、编写 CMakeLists.txt
在 sht30_demo 目录下新建 CMakeLists.txt 文件,内容如下:
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(frdm_mcxw72_sht30_demo)
target_sources(app PRIVATE src/main.c)七、编写 prj.conf
在 sht30_demo 目录下新建 prj.conf 文件,内容如下:
CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y CONFIG_I2C=y CONFIG_SENSOR=y CONFIG_SHT3XD=y CONFIG_LOG=y CONFIG_SENSOR_LOG_LEVEL_INF=y
这里几个关键配置说明一下:
CONFIG_I2C=y
表示启用 I2C 总线。
CONFIG_SENSOR=y
表示启用 Zephyr 传感器框架。
CONFIG_SHT3XD=y
表示启用 Sensirion SHT3x 系列传感器驱动,SHT30 就属于这个系列。
八、编写设备树 overlay
在 sht30_demo 目录下新建 app.overlay 文件。
这里需要根据开发板实际使用的 I2C 总线来写。一般可能是 i2c0、i2c1 或 i2c2。
这里先以 i2c1 为例:
&i2c1 {
status = "okay";
sht30: sht30@44 {
compatible = "sensirion,sht3xd";
reg = <0x44>;
status = "okay";
};
};如果你的 SHT30 地址是 0x45,则改成:
&i2c1 {
status = "okay";
sht30: sht30@45 {
compatible = "sensirion,sht3xd";
reg = <0x45>;
status = "okay";
};
};如果编译时报 i2c1 不存在,就需要查看 FRDM-MCXW72 的设备树,确认实际使用的 I2C 节点。
可以进入 Zephyr 根目录搜索:
cd D:\Zephyr\zephyrproject\zephyr Get-ChildItem -Recurse boards | Select-String -Pattern "frdm_mcxw72"
也可以搜索 I2C 相关内容:
Get-ChildItem -Recurse boards | Select-String -Pattern "i2c"
如果发现开发板使用的是 i2c0 或 i2c2,就把 overlay 里的 &i2c1 改掉即可。
例如:
&i2c0 {
status = "okay";
sht30: sht30@44 {
compatible = "sensirion,sht3xd";
reg = <0x44>;
status = "okay";
};
};九、编写 main.c
在 src 目录下新建 main.c 文件,内容如下:
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/sys/printk.h>
#define SHT30_NODE DT_NODELABEL(sht30)
int main(void)
{
const struct device *sht30 = DEVICE_DT_GET(SHT30_NODE);
struct sensor_value temperature;
struct sensor_value humidity;
printk("FRDM-MCXW72 SHT30 demo start\r\n");
if (!device_is_ready(sht30)) {
printk("SHT30 device is not ready\r\n");
return 0;
}
printk("SHT30 device is ready\r\n");
while (1) {
int ret;
ret = sensor_sample_fetch(sht30);
if (ret < 0) {
printk("Failed to fetch sample, ret = %d\r\n", ret);
k_sleep(K_SECONDS(2));
continue;
}
ret = sensor_channel_get(sht30, SENSOR_CHAN_AMBIENT_TEMP, &temperature);
if (ret < 0) {
printk("Failed to get temperature, ret = %d\r\n", ret);
k_sleep(K_SECONDS(2));
continue;
}
ret = sensor_channel_get(sht30, SENSOR_CHAN_HUMIDITY, &humidity);
if (ret < 0) {
printk("Failed to get humidity, ret = %d\r\n", ret);
k_sleep(K_SECONDS(2));
continue;
}
printk("Temperature: %d.%06d C, Humidity: %d.%06d %%RH\r\n",
temperature.val1,
temperature.val2,
humidity.val1,
humidity.val2);
k_sleep(K_SECONDS(2));
}
return 0;
}十、编译工程
进入工程目录:
cd D:\Zephyr\zephyrproject\sht30_demo
如果你的板卡名称是:
frdm_mcxw72
则执行:
west build -p always -b frdm_mcxw72 .
如果你的板卡名称是带 qualifier 的形式,例如:
frdm_mcxw72/mcxw727c
则执行:
west build -p always -b frdm_mcxw72/mcxw727c .
编译成功后,可以看到类似输出:
[xxx/xxx] Linking C executable zephyr/zephyr.elf Memory region Used Size Region Size %age Used FLASH: xxx KB RAM: xxx KB
十一、烧录程序
使用 USB 线连接 FRDM-MCXW72 开发板,然后执行:
west flash
如果烧录正常,会看到类似输出:
-- west flash: rebuilding ninja: no work to do. -- west flash: using runner ... -- runners.xxx: Flashing file: build/zephyr/zephyr.hex
十二、打开串口查看数据
烧录完成后,打开串口工具,例如:
PuTTY
MobaXterm
Tera Term
VS Code Serial Monitor
串口参数一般设置为:
波特率:115200 数据位:8 停止位:1 校验位:None 流控:None
打开串口后,按一下开发板 Reset 按键,可以看到类似输出:
FRDM-MCXW72 SHT30 demo start SHT30 device is ready Temperature: 25.123456 C, Humidity: 48.654321 %RH Temperature: 25.125678 C, Humidity: 48.612345 %RH Temperature: 25.126789 C, Humidity: 48.598765 %RH
这样就说明 FRDM-MCXW72 已经成功读取到了 SHT30 的温湿度数据。
十三、完整代码汇总
下面把整个工程的代码整理到一起,方便复制。
1. CMakeLists.txt
cmake_minimum_required(VERSION 3.20.0)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(frdm_mcxw72_sht30_demo)
target_sources(app PRIVATE src/main.c)2. prj.conf
CONFIG_SERIAL=y CONFIG_CONSOLE=y CONFIG_UART_CONSOLE=y CONFIG_I2C=y CONFIG_SENSOR=y CONFIG_SHT3XD=y CONFIG_LOG=y CONFIG_SENSOR_LOG_LEVEL_INF=y
3. app.overlay
&i2c1 {
status = "okay";
sht30: sht30@44 {
compatible = "sensirion,sht3xd";
reg = <0x44>;
status = "okay";
};
};如果使用 0x45 地址,则改为:
&i2c1 {
status = "okay";
sht30: sht30@45 {
compatible = "sensirion,sht3xd";
reg = <0x45>;
status = "okay";
};
};4. src/main.c
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/sensor.h>
#include <zephyr/sys/printk.h>
#define SHT30_NODE DT_NODELABEL(sht30)
int main(void)
{
const struct device *sht30 = DEVICE_DT_GET(SHT30_NODE);
struct sensor_value temperature;
struct sensor_value humidity;
printk("FRDM-MCXW72 SHT30 demo start\r\n");
if (!device_is_ready(sht30)) {
printk("SHT30 device is not ready\r\n");
return 0;
}
printk("SHT30 device is ready\r\n");
while (1) {
int ret;
ret = sensor_sample_fetch(sht30);
if (ret < 0) {
printk("Failed to fetch sample, ret = %d\r\n", ret);
k_sleep(K_SECONDS(2));
continue;
}
ret = sensor_channel_get(sht30, SENSOR_CHAN_AMBIENT_TEMP, &temperature);
if (ret < 0) {
printk("Failed to get temperature, ret = %d\r\n", ret);
k_sleep(K_SECONDS(2));
continue;
}
ret = sensor_channel_get(sht30, SENSOR_CHAN_HUMIDITY, &humidity);
if (ret < 0) {
printk("Failed to get humidity, ret = %d\r\n", ret);
k_sleep(K_SECONDS(2));
continue;
}
printk("Temperature: %d.%06d C, Humidity: %d.%06d %%RH\r\n",
temperature.val1,
temperature.val2,
humidity.val1,
humidity.val2);
k_sleep(K_SECONDS(2));
}
return 0;
}十四、常见问题1. 编译提示 CONFIG_SHT3XD 未定义
如果出现类似提示:
warning: attempt to assign the value 'y' to the undefined symbol SHT3XD
说明当前 Zephyr 版本中可能没有这个驱动,或者驱动配置名称不同。
可以在 Zephyr 根目录搜索:
cd D:\Zephyr\zephyrproject\zephyr Get-ChildItem -Recurse . | Select-String -Pattern "config SHT3"
根据搜索到的 Kconfig 名称修改 prj.conf。
2. 编译提示 i2c1 未定义
如果出现:
undefined node label 'i2c1'
说明 app.overlay 里的 I2C 节点写错了。
解决方法是查看 FRDM-MCXW72 的设备树文件,确认实际可用的是 i2c0、i2c1 还是 i2c2,然后修改 overlay。
3. 串口输出 SHT30 device is not ready
如果输出:
SHT30 device is not ready
可能原因:
I2C 控制器没有启用;
overlay 里 I2C 总线选错;
SHT30 地址写错;
SDA / SCL 接反;
传感器没有供电;
I2C 上拉电阻异常。
建议优先检查接线和地址。
4. 反复输出 Failed to fetch sample
如果程序运行后反复输出:
Failed to fetch sample
说明设备树里的 SHT30 节点已经创建,但是实际 I2C 通信失败。
重点检查:
SHT30 地址是 0x44 还是 0x45;
SDA 和 SCL 是否接反;
I2C 总线是否选错;
模块供电是否正常;
杜邦线是否接触不良。
十五、常用命令汇总
激活 Zephyr 环境:
cd D:\Zephyr zephyrproject\.venv\Scripts\Activate.ps1
进入工程目录:
cd D:\Zephyr\zephyrproject\sht30_demo
编译:
west build -p always -b frdm_mcxw72 .
如果板卡名称带 qualifier:
west build -p always -b frdm_mcxw72/mcxw727c .
烧录:
west flash
查看板卡名称:
west boards | Select-String -Pattern "mcxw72" -CaseSensitive:$false
十六、实验现象
程序烧录后,打开串口终端,可以看到温湿度数据每 2 秒刷新一次:
FRDM-MCXW72 SHT30 demo start SHT30 device is ready Temperature: 25.123456 C, Humidity: 48.654321 %RH Temperature: 25.125678 C, Humidity: 48.612345 %RH Temperature: 25.126789 C, Humidity: 48.598765 %RH
至此,FRDM-MCXW72 驱动 SHT30 温湿度传感器实验完成。
我要赚赏金
