作为电子爱好者,近期基于 FRDM-MCXN947 开发板 DIY 了一款低功耗蓝牙温湿度计,核心搭配 SHT30 温湿度传感器与 ESP32 蓝牙模块,全程从底层驱动开发到逻辑整合一步步调试,这篇过程贴聚焦驱动层的开发与调试。硬件层面,SHT30 温湿度传感器通过 ADC 引脚(ADC0_A0/ADC0_B0)与开发板通信,负责采集温湿度模拟信号;ESP32 则通过 UART(flexcomm2_lpuart2)与主控交互,借助 AT 指令实现 BLE 透传。硬件接线很简洁:FRDM-MCXN947 的 TX/RX 分别对接 ESP32 的 RX(GPIO16)、TX(GPIO17),LED0 用于运行状态指示,整体采用 3.3V 供电,兼顾低功耗需求。SHT30 驱动是整个项目的数据采集基础,基于 Zephyr 的 ADC 子系统开发。为降低 MCU 运算开销,我全程采用整数运算,完全沿用 Sensirion 官方转换公式,将采集到的 ADC 原始值先换算为电压,再转换为 0.1℃/0.1% 精度的温湿度数值。驱动封装为标准的初始化、采集、取值三段式接口,上层业务无需关心底层 ADC 配置细节。
/* SHT30 转换系数 (放大1000倍实现整数运算) */
#define SHT30_T_COEFF 72917
#define SHT30_T_OFFSET (-66875)
#define SHT30_RH_COEFF 41667
#define SHT30_RH_OFFSET (-12500)
/* 电压(mV)转温度(0.1°C) */
static int32_t mv_to_temp(int32_t mv)
{
int32_t t = (int32_t)mv * SHT30_T_COEFF / 1000 + SHT30_T_OFFSET;
return t / 100;
}
/* 采集并转换温湿度数据 */
int sht30_fetch(void)
{
int ret = adc_read(adc_channels[0].dev, &sequence);
int32_t mv_t = adc_to_mv(adc_buf[0]);
int32_t mv_h = adc_to_mv(adc_buf[1]);
last_temp = mv_to_temp(mv_t);
last_rh = mv_to_rh(mv_h);
return 0;
}蓝牙驱动围绕 ESP32 AT 指令集设计,核心采用 “UART 中断接收 + 有限状态机” 的架构,避免阻塞式等待影响主循环实时性。我设计了 6 种运行状态,从模块复位、参数配置到等待连接、进入透传,全部由状态机自动流转;接收端采用 512 字节环形缓冲区缓存中断收到的字节,逐行解析 AT 响应,零延迟处理连接、应答等关键事件
/* 蓝牙状态机定义 */
enum ble_state {
BLE_STATE_INIT, /* 初始化复位 */
BLE_STATE_SETUP, /* 发送BLE配置命令 */
BLE_STATE_WAIT_CONN, /* 等待客户端连接 */
BLE_STATE_READY, /* 准备进入透传 */
BLE_STATE_TRANSPARENT, /* 透传数据模式 */
BLE_STATE_ERROR, /* 错误重试状态 */
};
/* UART 中断接收回调 (零延迟入队) */
static void uart_isr(const struct device *dev, void *user_data)
{
uint8_t ch;
while (uart_irq_update(dev) && uart_irq_rx_ready(dev)) {
if (uart_fifo_read(dev, &ch, 1) == 1) {
uint16_t next = (rx_head + 1) % RX_BUF_SIZE;
if (next != rx_tail) {
rx_buf[rx_head] = ch;
rx_head = next;
}
}
}
}整个驱动开发过程,分层封装的思路贯穿始终:传感器采集、蓝牙通信各自独立成模块,对外只暴露简洁的调用接口,既方便单模块单元测试,也为后续加入低功耗策略、数据校准等功能留出了充足的扩展空间。目前驱动层已稳定运行,温湿度采集精度与蓝牙透传稳定性均达到预期。DIY 的乐趣正在于从 0 到 1 搭建完整系统,每一个 bug 的排查都是对底层原理的深化理解。这款温湿度计虽结构简单,却完整覆盖了 ADC 采集、UART 中断通信、BLE 协议适配等嵌入式核心知识点。后续成果贴会分享应用层优化细节和完整实测效果,包括续航表现、传输距离、数据精度等核心指标。
我要赚赏金
