/* 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 协议适配等嵌入式核心知识点。后续成果贴会分享应用层优化细节和完整实测效果,包括续航表现、传输距离、数据精度等核心指标。
我要赚赏金
