【DigiKey好物畅享】ST NUCLEO-WBA65RI开发板连接小米温湿度传感器

项目介绍

本次使用NUCLEO-WBA65RI连接小米温湿度传感器,将WBA作为GATT连接端,连接小米温湿度传感器,获取其中采集的温湿度和电压信息,通过串口将其中的数据打印出来。

工程准备

我们根据ST提供的示例工程进行修改BLE_DataThroughput_Client ,其中连接到我们的小米温湿度传感器。

实现步骤

当我们下载好示例工程,我们需要修改其中相关代码,这里我们先通过nrf connect来获取小米温湿度传感器的BLE信息。

这里我们看到其中的相关信息

接下来我们开始修改工程的代码

设备发现与识别 (Scanning)

在 BLE 扫描阶段,通过解析广播包中的 Complete Local Name (AD Type 0x09) 来识别目标设备。

  • 文件: STM32_WPAN/App/app_ble.c

  • 函数: analyse_adv_report

  • 逻辑:

    1. 遍历扫描到的广播数据字段。

    2. 查找类型为 AD_TYPE_COMPLETE_LOCAL_NAME 的字段。

    3. 使用 strncmp 比较名称是否为 “MJWSD06MMC”。

    4. 匹配成功后,记录设备 MAC 地址并停止扫描,发起连接。

代码片段:

case AD_TYPE_COMPLETE_LOCAL_NAME:
/* Check if the device name is the Xiaomi sensor */
if (strncmp((char*)&p_adv_data[i + 2], “MJWSD06MMC”, ad_length - 1) == 0)
{
LOG_INFO_APP(“— Xiaomi Sensor detected: MJWSD06MMC\n”);
// … (保存设备地址代码) …
bleAppContext.deviceServerFound = 0x01;
found_status = 1;
}
break;

服务与特征发现 (GATT Discovery)

小米设备使用了自定义的 128 位 UUID,且在 STM32 的小端序内存中需要特殊处理。

  • UUID 分析:

    • 服务 UUID: ebe0ccb0-7a0a-4b0c-8a1a-6ff2997da3a6

    • 特征 UUID: ebe0ccc1-7a0a-4b0c-8a1a-6ff2997da3a6 (负责传输数据)

    • 关键识别字: 128 位 UUID 的高位字节在内存中以 0xA6 0xA3 开头(小端序)。

  • 文件: STM32_WPAN/App/gatt_client_app.c

  • 修改点:

    1. 定义 UUID 短码:

    #define DT_SERVICE_UUID (0xCCB0) // 从日志分析得出的 16 位别名
    #define DT_TX_CHAR_UUID (0xCCC1) // 数据特征

    1. 服务发现 (gatt_parse_services):
      增加了针对 128 位 UUID 的字节级匹配逻辑。当检测到 UUID 字节数组以 0xA6, 0xA3 开头时,自动将其标记为目标服务。

    2. 特征发现 (gatt_parse_chars):
      同样增加了字节匹配逻辑,用于精确定位到数据传输特征的句柄 (Handle)。

开启数据通知 (Enable Notifications)

设备默认不发送数据。必须向特征的 CCCD (Client Characteristic Configuration Descriptor) 写入 0x0001 以开启 Notification。

  • 文件: STM32_WPAN/App/gatt_client_app.c

  • 流程:

    1. 在 gatt_parse_descs 中发现 0xCCC1 特征下的描述符。

    2. 在 PROC_GATT_PROPERTIES_ENABLE_ALL 状态机中,调用 aci_gatt_write_char_value 向该描述符写入 Enable 命令。

数据解析 (Data Parsing)

接收到的数据是原始十六进制字节,需要根据小米的数据格式进行转换。

  • 文件: STM32_WPAN/App/gatt_client_app.c

  • 函数: gatt_parse_notification

  • 数据格式:

    • Byte 0-1: 温度 (Little Endian int16),单位 0.01 ℃。

    • Byte 2: 湿度 (uint8),单位 %。

    • Byte 3-4: 电压 (Little Endian uint16),单位 mV。

解析代码:

/* USER CODE BEGIN gatt_parse_notification_1 */
if (p_evt->Attribute_Handle == a_ClientContext[0].DTTXValueHdle)
{
if (p_evt->Attribute_Value_Length >= 3)
{
// 温度转换: Hex → Int16 → Float (/100)
int16_t temp_raw = (int16_t)(p_evt->Attribute_Value[0] | (p_evt->Attribute_Value[1] << 8));
float temperature = temp_raw / 100.0f;

// 湿度直接读取
uint8_t humidity = p_evt->Attribute_Value\[2\];

LOG_INFO_APP("\*\* Data: Temp=%.2f C, Humi=%d %%\\n", temperature, humidity);

// 电压转换 (如果有)
if (p_evt->Attribute_Value_Length >= 5)
{
   uint16_t voltage = (uint16_t)(p_evt->Attribute_Value\[3\] | (p_evt->Attribute_Value\[4\] << 8));
   float volt_v = voltage / 1000.0f;
   LOG_INFO_APP("\*\* Voltage: %.3f V\\n", volt_v);
}

}
}
/* USER CODE END gatt_parse_notification_1 */

成果展示

上电时候,我们点击最左边的按键,开始扫描小米温湿度传感器的BLE,就能获取到。

我们可以很清楚的看见其中的温湿度和电压都显示在串口上。