Funpack4-3 - 用MAX32655的BLE协议获取米家温湿度计数据
该项目使用了max32655的ble模块,实现了通过蓝牙低功耗获取小米米家温湿度传感器2的实时数据的设计,它的主要功能为:max32655作为BLE client,米家温湿度计作为BLE SERVER。连接成功后,开启notification功能,然后实时获取传感器数据并显示在圆形TFT屏幕上。。
标签
BLE
Funpack活动
MAX32655
Funpack S4 #3
米家温湿度计2
BLE Client
playlikework
更新2026-02-02
27

任务目标:

本次活动选择了max32655的任务2:通过蓝牙低功耗获取小米米家温湿度传感器2的实时数据。

任务分解:

  1. 主控板卡具有BLE模块,因此只需要实现BLE client功能即可。
  2. 米家温湿度计的device name, service, characteristic如何获取。也就是在那个特征值下面包含有本次项目用到的温湿度数据。
  3. 如何显示在TFT屏幕上?这里使用到了圆形的TFT屏幕。


具体的实现思路:

  • max32655作为BLE client,米家温湿度计作为BLE SERVER。
  • max32655上电后开始扫描并寻找米家温湿度计,找到后开始连接。
  • 连接成功后,开启notification功能,然后实时获取传感器数据并显示在圆形TFT屏幕上。

主控板卡介绍:

image.png

ADI MAX326555 FTHR板载了ADI MAX32655 微控制器 (MCU),这 是一款先进的片上系统 (SoC),配备 Arm Cortex-M4F CPU,可高效计算复杂函数和算法,适合在 -40°C 至 +105°C 的温度范围内工作。SoC 将电源调节和管理与单电感多输出 (SIMO) 降压稳压器系统集成在一起。板载最新一代 Bluetooth 5.2 低功耗 (LE) 无线电,支持长距离(编码)和高吞吐量模式以及医疗体域网络 (MBAN)。该器件提供大容量板载内存,包括 512 KB 闪存和 128 KB SRAM,并在一个 32 KB SRAM 库上配备可选纠错编码 (ECC)。此 32 KB 存储库可选择在备份模式下保留。有 8 KB 用户 OTP 区域可用。

  • Bluetooth 5.2 LE 无线电
  • 专用的超低功耗 32 位 RISC-V 协处理器,用于时间关键型蓝牙处理
  • 提供完全开源的 Bluetooth 5.2 栈
  • 支持医疗体域网 (MBAN) 和网状网络
  • 高吞吐量 (2 Mbps) 模式
  • 远程(125 kbps 和 500 kbps)模式
  • Rx 灵敏度:-97 dBm;Tx 功率:+5.5 dBm
  • 单端天线连接 (50 Ω)

系统框图:

简易的实物框图如下:

  • 左侧是SPI接口的TFT屏幕,通过软件模拟SPI的方式来进行数据显示。
  • 右侧是米家温湿度计2,通过BLE协议获取其温湿度数据。

image.png

软件流程图:

image.png

实现细节:

米家温湿度计的device name, service, characteristic:

参考公开资料,以及使用BLE DONGLE测试发现:小米温湿度计2 是从设备,同时也是BLE SERVER,部署了多个sevice,其中serviceUUID("ebe0ccb0-7a0a-4b0c-8a1a-6ff2997da3a6")里面的charUUID("ebe0ccc1-7a0a-4b0c-8a1a-6ff2997da3a6")就是温湿度数据。

 

MAX32655是主设备,同时也是BLE CLIENT,通过BLE的协议来访问Server上的Characteristic,从而获取到温湿度数据。

max32655启动后,会开始扫描周围的BLE设备,此时进行一个判断,设备名称是否为XiaomiDeviceName = "LYWSD03MMC".


体现在代码里:

/**************************************************************************************************

Secure Service and Data UUIDs

**************************************************************************************************/

#define ATT_UUID_SEC_DATA_SERVICE \
0xA6, 0xA3, 0x7D, 0x99, 0xF2, 0x6F, 0x1A, 0x8A, 0x0C, 0x4B, 0x0A, 0x7A, 0xB0, 0xCC, 0xE0, 0xEB

/* MCS service GATT characteristic UUIDs*/
#define ATT_UUID_SEC_DATA \
0xA6, 0xA3, 0x7D, 0x99, 0xF2, 0x6F, 0x1A, 0x8A, 0x0C, 0x4B, 0x0A, 0x7A, 0xC1, 0xCC, 0xE0, 0xEB

/**************************************************************************************************
Local Variables
**************************************************************************************************/
/* UUIDs */
const uint8_t SecDatSvcUuid[] = { ATT_UUID_SEC_DATA_SERVICE }; /*! Secured service */
const uint8_t SecDatChUuid[] = { ATT_UUID_SEC_DATA }; /*! Secured data */


实现BLE client:

MAX32655的官方GIT仓库提供了Cordio Bluetooth LE的相关固件。链接: https://jake-carter.github.io/msdk/Libraries/Cordio/docs/CORDIO_USERGUIDE/


本次项目上,MAX32655作为BLE client,要获取小米温湿度计提供的相关service,以及包含的characteristic。它们都属于GATT层的内容。

image.png



借助于CORDIO库,在开发的时候只需要调用WSF接口即可。


image.png



首先要初始化data client的协议栈,这部分可以参考官方例程:BLe_dataC.

/*************************************************************************************************/

/*!
* \brief Initialize stack.
*
* \return None.
*/

/*************************************************************************************************/
void StackInitDatc(void)
{
wsfHandlerId_t handlerId;
SecInit();
SecAesInit();
SecCmacInit();
SecEccInit();

handlerId = WsfOsSetNextHandler(HciHandler);
HciHandlerInit(handlerId);

handlerId = WsfOsSetNextHandler(DmHandler);
DmDevVsInit(0);
DmDevPrivInit();
DmConnInit();
DmScanInit();
DmConnMasterInit();
DmSecInit();
DmSecLescInit();
DmPrivInit();
DmHandlerInit(handlerId);

L2cInit();
L2cMasterInit();

handlerId = WsfOsSetNextHandler(AttHandler);
AttHandlerInit(handlerId);
AttsInit();
AttsIndInit();
AttcInit();

handlerId = WsfOsSetNextHandler(SmpHandler);
SmpHandlerInit(handlerId);
SmpiInit();
SmpiScInit();
HciSetMaxRxAclLen(256);

handlerId = WsfOsSetNextHandler(AppHandler);
AppHandlerInit(handlerId);
handlerId = WsfOsSetNextHandler(DatcHandler);
DatcHandlerInit(handlerId);
}


然后是启动ble client:

/*************************************************************************************************/
/*!
* \brief Start the application.
*
* \return None.
*/
/*************************************************************************************************/
void DatcStart(void)
{
/* Initialize handle pointers */
datcInitSvcHdlList();

/* Register for stack callbacks */
DmRegister(datcDmCback);
DmConnRegister(DM_CLIENT_ID_APP, datcDmCback);
AttRegister(datcAttCback);

/* Register for app framework button callbacks */
AppUiBtnRegister(datcBtnCback);

/* Register for app framework discovery callbacks */
AppDiscRegister(datcDiscCback);

/* Initialize attribute server database */
SvcCoreAddGroup();

#if (BT_VER > 8)
DmPhyInit();
#endif /* BT_VER */

WsfNvmInit();

/* Initialize with button press handler */
PalBtnInit(btnPressHandler);

/* Reset the device */
DmDevReset();
}


在处理BLE事件的时候,如果接收到notification,进入回调处理小米传感器数据。

image.png



还有一点需要注意修改projet.mk:

# Enable Cordio library

LIB_CORDIO = 1

# Cordio library options
INIT_PERIPHERAL = 0
INIT_CENTRAL = 1

# TRACE option
# Set to 0 to disable
# Set to 1 to enable serial port trace messages
# Set to 2 to enable verbose messages
TRACE = 1

# set ADVTISEMENT name you want to connect
ADV_NAME?=LYWSD03MMC
PROJ_CFLAGS += -DADV_NAME=\"$(ADV_NAME)\"

### CONFIGURE security
# /*! TRUE to initiate security upon connection*/
PROJ_CFLAGS += -DINIT_SECURITY=FALSE

屏幕驱动:


采用GPIO模拟软件SPI:

mxc_gpio_cfg_t tft_scl_pin = { MXC_GPIO2, MXC_GPIO_PIN_0,
MXC_GPIO_FUNC_OUT, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIOH };


mxc_gpio_cfg_t tft_sda_pin = { MXC_GPIO2, MXC_GPIO_PIN_1,
MXC_GPIO_FUNC_OUT, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIOH };
mxc_gpio_cfg_t tft_dc_pin = { MXC_GPIO2, MXC_GPIO_PIN_2,
MXC_GPIO_FUNC_OUT, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIOH };
mxc_gpio_cfg_t tft_cs_pin = { MXC_GPIO2, MXC_GPIO_PIN_3,
MXC_GPIO_FUNC_OUT, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIOH };
mxc_gpio_cfg_t tft_reset_pin = { MXC_GPIO2, MXC_GPIO_PIN_4,
MXC_GPIO_FUNC_OUT, MXC_GPIO_PAD_NONE, MXC_GPIO_VSSEL_VDDIOH };

#define LCD_SCLK_Clr() MXC_GPIO_OutClr(tft_scl_pin.port, tft_scl_pin.mask) //SCL=SCLK
#define LCD_SCLK_Set() MXC_GPIO_OutSet(tft_scl_pin.port, tft_scl_pin.mask)
#define LCD_MOSI_Clr() MXC_GPIO_OutClr(tft_sda_pin.port, tft_sda_pin.mask) //SDA=MOSI
#define LCD_MOSI_Set() MXC_GPIO_OutSet(tft_sda_pin.port, tft_sda_pin.mask)
#define LCD_DC_Clr() MXC_GPIO_OutClr(tft_dc_pin.port, tft_dc_pin.mask)//DC
#define LCD_DC_Set() MXC_GPIO_OutSet(tft_dc_pin.port, tft_dc_pin.mask)
#define LCD_CS_Clr() MXC_GPIO_OutClr(tft_cs_pin.port, tft_cs_pin.mask)//CS
#define LCD_CS_Set() MXC_GPIO_OutSet(tft_cs_pin.port, tft_cs_pin.mask)
#define LCD_RES_Clr() MXC_GPIO_OutClr(tft_reset_pin.port, tft_reset_pin.mask)//RES
#define LCD_RES_Set() MXC_GPIO_OutSet(tft_reset_pin.port, tft_reset_pin.mask)


相关的屏幕读写最终都落实到向SPI总线发送数据:

void LCD_Writ_Bus(u8 dat)

{

u8 i;
LCD_CS_Clr();
for(i=0;i<8;i++)
{
LCD_SCLK_Clr();
if(dat&0x80)
{
LCD_MOSI_Set();
}
else
{
LCD_MOSI_Clr();
}
LCD_SCLK_Set();
dat<<=1;
}

LCD_CS_Set();

}

由于编译系统是make控制,相关的驱动需要添加到Makefile文件。

image.png

项目硬件实物:

室温环境下的米家数据和传输给max32655的数据完全一致。

image.png


image.png

image.png


对着米家温湿度传感器“呼口气”,让湿度产生改变。可以看到数据实时的传输给max32655并准确展示在TFT屏幕上。

image.png

image.png



心得体会:

感谢硬禾提供的活动平台,学习了ADI的max32655芯片及其开发环境eclispe和MSDK固件库 的使用,也学习了BLE模块的驱动以及spi驱动tft屏幕的基本原理。

整体完成了平台要求的任务,受益良多。期待funpack活动越来越好




附件下载
BLE_DataC.zip
团队介绍
电子飞虎队
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号