2. 开发环境搭建:Zephyr SDK安装、west工具配置、创建第一个传感器工程、编译与烧录流程

好,咱们正式开始动手了。这一章我带你走一遍环境搭建的全流程。说实话,很多初学者卡就卡在这一步——不是工具装不上,就是版本对不上。我当年刚接触Zephyr时,光装环境就折腾了两天。嗯,咱们争取一小时内搞定。

2.1 Zephyr SDK安装——别选错版本

Zephyr SDK不是普通的编译器,它包含了交叉编译工具链、调试器、QEMU模拟器等一整套东西。说白了,你装好它,就能在PC上编译出给ARM、RISC-V等嵌入式平台跑的代码。

下载地址:Zephyr官方GitHub Release页面。我个人习惯用0.16.x版本,稳定,坑少。

⚠ 注意:SDK版本必须与Zephyr RTOS主版本匹配。比如Zephyr 3.5 LTS建议搭配SDK 0.16.5。我曾经因为图新鲜装了最新SDK,结果编译报了一堆莫名其妙的链接错误——后来发现是ABI不兼容。

安装步骤(Linux环境,我推荐Ubuntu 22.04):

  1. 下载SDK安装包:wget https://github.com/zephyrproject-rtos/sdk-ng/releases/download/v0.16.5/zephyr-sdk-0.16.5_linux-x86_64.tar.xz
  2. 解压:tar xf zephyr-sdk-0.16.5_linux-x86_64.tar.xz
  3. 运行安装脚本:cd zephyr-sdk-0.16.5 && ./setup.sh
  4. 设置udev规则(烧录调试用):sudo cp sysroots/x86_64-pokysdk-linux/usr/share/openocd/contrib/60-openocd.rules /etc/udev/rules.d/
  5. 重新加载udev:sudo udevadm control --reload
💡 我的习惯:把SDK装到 /opt/zephyr-sdk 下,然后设置环境变量 export ZEPHYR_SDK_INSTALL_DIR=/opt/zephyr-sdk。这样多个项目都能共用。

2.2 west工具配置——Zephyr的瑞士军刀

west是Zephyr的元构建工具。它管理源码、配置项目、编译烧录全包了。你想想看,没有它,你要手动管理几十个Git仓库——那画面太美我不敢看。

安装west:

pip3 install west

装完后验证一下:west --version。如果报错,八成是pip路径没加到PATH里。我遇到过这问题,加个 export PATH=$HOME/.local/bin:$PATH.bashrc 就行。

初始化Zephyr工作区:

mkdir zephyr_project
cd zephyr_project
west init
west update

west init 会拉取Zephyr主仓库,west update 会同步所有模块。这个过程取决于网速,我建议用代理或者换国内镜像源。

🔧 换国内镜像(以清华源为例):

west init -m https://mirrors.tuna.tsinghua.edu.cn/git/zephyr/main.git
west update

导出Zephyr环境变量:

cd zephyr
pip3 install -r scripts/requirements.txt
source zephyr-env.sh

每次打开新终端都要source一次?我建议你把它加到 .bashrc 里:

echo "source ~/zephyr_project/zephyr/zephyr-env.sh" >> ~/.bashrc

2.3 创建第一个传感器工程——从模板开始

好,环境搭好了,咱们来建个工程。我选BME280温湿度传感器作为例子,因为它是I2C接口,很典型。

创建工程:

west create -b nucleo_f411re bme280_demo
cd bme280_demo

-b 指定开发板,这里用STM32 Nucleo-F411RE。你手头有其他板子?换成对应的board name就行。

工程结构长这样:

bme280_demo/
├── CMakeLists.txt
├── prj.conf
├── src/
│   └── main.c
└── boards/
    └── nucleo_f411re.overlay

咱们重点看 prj.confmain.c

配置prj.conf:

# 启用I2C
CONFIG_I2C=y
# 启用传感器子系统
CONFIG_SENSOR=y
# 启用BME280驱动
CONFIG_BME280=y
# 启用日志
CONFIG_LOG=y
CONFIG_LOG_DEFAULT_LEVEL=3

为什么这么配?我解释一下:BME280驱动依赖I2C和传感器子系统,所以这三行缺一不可。日志嘛,调试时很有用,我习惯默认开着。

编写main.c:

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/sensor.h>

void main(void)
{
    const struct device *dev = DEVICE_DT_GET_ANY(bosch_bme280);

    if (!device_is_ready(dev)) {
        printk("BME280 not found!\n");
        return;
    }

    printk("BME280 found, starting sampling...\n");

    while (1) {
        struct sensor_value temp, humidity, pressure;

        sensor_sample_fetch(dev);
        sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP, &temp);
        sensor_channel_get(dev, SENSOR_CHAN_HUMIDITY, &humidity);
        sensor_channel_get(dev, SENSOR_CHAN_PRESS, &pressure);

        printk("Temp: %d.%d C, Humidity: %d.%d%%, Pressure: %d.%d kPa\n",
               temp.val1, temp.val2,
               humidity.val1, humidity.val2,
               pressure.val1, pressure.val2);

        k_sleep(K_SECONDS(2));
    }
}

这段代码的逻辑很直白:找设备、检查就绪、循环采样。注意 DEVICE_DT_GET_ANY 这个宏——它会自动从设备树里匹配BME280。你不需要手动指定I2C地址,Zephyr帮你干了。

💡 避坑指南:我曾经忘了加 device_is_ready 检查,结果在某个板子上程序直接跑飞。后来养成习惯——任何外设驱动,必须先检查就绪状态。

2.4 编译与烧录——见证奇迹的时刻

代码写好了,咱们编译一下。

编译命令:

west build -b nucleo_f411re .

第一次编译会下载工具链和依赖,稍等几分钟。如果一切顺利,你会看到:

-- Build files have been written to: /home/user/bme280_demo/build
[100%] Built target zephyr_final

常见编译错误及解决:

错误信息 原因 解决方法
CMake Error: Zephyr not found 环境变量未设置 执行 source zephyr-env.sh
undefined reference to `sensor_channel_get' prj.conf未启用SENSOR 添加 CONFIG_SENSOR=y
No board named 'nucleo_f411re' board name拼写错误 west boards | grep nucleo 查正确名称

烧录到开发板:

west flash

Nucleo板自带ST-Link,插上USB就能识别。烧录成功后,按复位键,串口会输出:

BME280 found, starting sampling...
Temp: 25.3 C, Humidity: 48.2%, Pressure: 101.3 kPa
Temp: 25.3 C, Humidity: 48.1%, Pressure: 101.3 kPa

看到数据了吗?嗯,这就是你的第一个Zephyr传感器工程。

⚠ 注意:如果串口没输出,检查两点:一是板子的虚拟串口驱动装了没,二是终端波特率设置对不对(默认115200)。我吃过这个亏,折腾了半小时才发现是串口助手波特率设成了9600。

2.5 本章小结

咱们这一章干了三件事:装SDK、配west、建工程。你可能会觉得步骤有点多,但相信我——这套流程走一遍,后面所有传感器工程都是复制粘贴的节奏。

下一章,咱们深入传感器驱动框架,看看Zephyr是怎么把不同厂家的传感器统一成一套API的。到时候你会发现,换一个传感器,代码改动量不超过10行。

好,先到这。有问题随时翻翻Zephyr官方文档,或者直接看 zephyr/drivers/sensor/bme280/ 下的源码——那才是最权威的教材。