实际上我们这里就算已经完成了基本功能了,变化的数据已经有了,那么我们就加入使用的传感器,实际上就是SHT40,我们在SDK中\zephyr\zephyr\drivers\sensor\sensirion\sht4x就有对应的驱动,我们直接融合到现在的工程就行,然后通过蓝牙透传。
接下来我们看一下如何实现,首先将传感器连接到开发板:

之前我们搭好了"连接后每2s透传一个数字"的蓝牙骨架。但说实话,光推编号没意思——谁要看 MCU在那数数呢?真正的物联网节点得有"感官",能采集真实数据。我们本次的最终要完成的也是蓝牙温湿度计。最后阶段的目标:让板子读SHT40温湿度传感器的数据,然后通过同一个BLE Notify特征把数据推出来。最终效果:手机连上BLE test设备 → 订阅特征 → 收到形如T:25.3,H:60.1的字符串,每2s一帧。
SHT40是Sensirion推出的一款高精度温湿度传感器,I2C 接口,典型地址 0x44。重复精度±0.2°C / ±1.8%RH,I2C速率最高1MHz。我们的板子(FRDM-MCXW72)默认只开了lpi2c1(上面挂着板载的 FXLS8974 加速度计),lpi2c0 是关的而且引脚和 PWM LED 冲突。所以SHT40外接的话,最稳的方案是直接挂lpi2c1——和加速度计共用总线,地址0x44不冲突。
Zephyr 这边怎么改
跟阶段一一样,整个改动落三个文件:
peripheral/ ├── boards/ │ └── frdm_mcxw72.overlay ← 新增:把 SHT40 挂到 lpi2c1 ├── prj.conf ← 追加:I2C、Sensor、Float printf └── src/ └── main.c ← 改造:把"数数"换成"读传感器"
设备树 overlay:告诉板子"我有 SHT40"
Zephyr跟硬件打交道全靠设备树。我们新建一个boards/frdm_mcxw72.overlay,把SHT40节点塞到 lpi2c1下面:
&lpi2c1 { status = "okay"; sht40: sht4x@44 { compatible = "sensirion,sht4x"; reg = <0x44>; repeatability = <2>; /* 高精度模式(单次测量约 8.3 ms)*/ }; };prj.conf:开 I2C、传感器、浮点打印
# 阶段一就有的 CONFIG_BT=y CONFIG_BT_PERIPHERAL=y CONFIG_LOG=y CONFIG_BT_DEVICE_NAME="BLE test" # 这阶段新增的 CONFIG_I2C=y CONFIG_SENSOR=y CONFIG_PICOLIBC_IO_FLOAT=y
最后一行是大坑,先记住:Picolibc(Zephyr 默认的精简 libc)默认不开启 %f 浮点打印支持,不显式打开的话snprintf("%.1f", ...) 会输出乱七八糟的东西。
CONFIG_SHT4X 你可能注意到我没写。这是因为SHT4X驱动的 Kconfig 写了 default y + depends on DT_HAS_SENSIRION_SHT4X_ENABLED,只要设备树里有 sht4x@44 节点,构建系统就自动把这个驱动编进去。
main.c:读传感器 + 蓝牙通知
代码结构跟阶段一几乎一样,只改"工作回调"里那个原本数数的部分:
#include <zephyr/drivers/sensor.h> /* 新增 */ static const struct device *const sht = DEVICE_DT_GET(DT_NODELABEL(sht40)); /* 一行拿到 sensor device */ static void sensor_work_handler(struct k_work *work) { struct sensor_value temp, hum; int err; err = sensor_sample_fetch(sht); /* 触发一次测量,等结果 */ if (err) { printk("sensor_sample_fetch failed (err %d)\n", err); goto reschedule; } if (sensor_channel_get(sht, SENSOR_CHAN_AMBIENT_TEMP, &temp) || sensor_channel_get(sht, SENSOR_CHAN_HUMIDITY, &hum)) { goto reschedule; } /* 拼成短字符串,最大 12 字节,能塞进默认 ATT MTU 的 20 字节值字段 */ sensor_len = (uint16_t)snprintf((char *)sensor_buf, sizeof(sensor_buf), "T:%.1f,H:%.1f", sensor_value_to_double(&temp), sensor_value_to_double(&hum)); printk("Notify: %s\n", sensor_buf); if (notify_enabled) { err = bt_gatt_notify(NULL, &sensor_svc.attrs[2], sensor_buf, sensor_len); if (err) { printk("bt_gatt_notify failed (err %d)\n", err); } } reschedule: if (streaming) { k_work_schedule(&sensor_work, K_MSEC(NOTIFY_INTERVAL_MS)); } }演示效果
小程序扫描 → 找到 BLE test → CONNECT,找到未知服务(UUID 末段 ...9abcdef0)→ 进去,订阅 Notify 特征(UUID 末段 ...9abcdef1),这个时候就可以看到无线传输的效果了:

中途我把手指放在了传感器上,可以看到传感器反应还是挺快的,温度就上升上来了。
我要赚赏金
