一、项目介绍
本次活动主题是ADI CodeFusion Studio™嵌入式软件开发平台的使用,大赛共提供3款开发板,MAX32650FTHR(15套)、MAX32655FTHR(40套)、MAX32690EVKIT(8套),本文采用的是MAX32655FTHR套件,任务选择的是赛道六:自命题。使用MAX32655和小米温湿度传感器,通过CodeFusion Studio进行编程开发,使用蓝牙技术连接传感器设备并订阅对应的topic,从而实时获取对应的温湿度数据及电量等数据,并打印输出。
二、硬件介绍
采用的板卡是MAX32655FTHR,它是一款快速开发平台,可帮助工程师使用MAX32655 Arm© Cortex®-M4F和Bluetooth® 5.2低功耗(LE)快速实施超低功耗无线解决方案。该电路板还包括MAX20303 PMIC以实现电池和电源管理。0.9 x 2.6英寸小尺寸双排接头与Adafruit Feather Wing外设扩展板兼容。该电路板包括各种外设,如数字麦克风、低功耗立体声音频编解码器、128MB QSPI闪存、micro SD卡连接器、RGB指示器LED和按钮。MAX32655FTHR提供功率优化的灵活平台,以便进行快速概念验证和早期软件开发,从而加快产品上市。

板卡优势与特点:
- MAX32655微控制器
- ARM Cortex-M4F,100MHz
- 32位RISC-V协处理器,可减轻时序关键型蓝牙处理负荷
- 512KB闪存
- 128KB SRAM
- 16KB缓存
- 蓝牙5.2 LE无线电
- 带电量计的MAX20303可穿戴PMIC
- 通过USB充电
- 用于Arm Cortex-M4F的板载DAPLink调试和编程接口
- 试验板兼容接头
- Micro USB连接器
- Micro SD卡连接器
- 集成外设
- RGB指示灯LED
- 用户按钮
- 低功耗立体声音频编解码器
- 数字麦克风
- SWD调试器
- 虚拟UART控制台
三、软件设计
这是一个基于 Analog Devices MAX32655(Cortex-M4)微控制器的 BLE 主机(Central/Client) 应用,核心功能是:作为 BLE 中央设备,扫描并连接小米温湿度计(MJWSD05MMC),订阅其安全数据服务,接收并解析温度/湿度/电压/电量,通过串口打印输出。整个项目是基于 SDK 的示例工程(ble_otac)进行修改,已经配置好了蓝牙相关配置和连接功能实现。使用没有修改固件的小米温湿度传感器,只能通过长连接的方式获取数据;订阅需要米家的密钥,所以无法广播读取数据。采用 CodeFusion Studio(vs code)进行系统开发的。
CodeFusion Studio是面向多内核的AI调试助手,AI助手通过模型上下文协议(MCP),直接连接实时调试会话,让调试工作更加智能调试助手兼容GitHub Copilot、Claude Code及任何支持MCP的AI客户端,能够提供智能化、上下文感知的调试能力:
- 使用自然语言进行硬件检查、故障诊断和根本原因分析
- 通过10个预置诊断提示词,自主调查崩溃、内存损坏和外设配置错误
- 利用专门的ARM Cortex-M和RISC-V故障解码技术,检查寄存器、内存、变量和堆栈回溯信息
- 通过自然语言命令,设置断点、条件断点和硬件监视点
- 执行原始GDB命令,内置安全机制可有效防范破坏性操作
- 搜索工作区源代码,分析嵌入式C/C++中的常见漏洞模式
- 在统一环境中查看RTOS线程及跨内核交互
- 同时支持实时调试和事后内核转储分析
3.1 系统架构
系统采用 “采集-转发-显示” 的三层架构:
- 感知层:BLE 传感器(LYWSD03MMC)。
- 传输/网关层 (MAX32655):
- 运行 BLE 协议栈,作为 Client 角色。
- 实现自动扫描、过滤特定 MAC 地址、建立连接。
- 利用定时器(Timer)周期性发起 GATT Read 请求。
- 定义自定义串口通信协议,将解析后的数据封包发送。
- 应用/展示层 (M1w dock suit):
- 监听 UART 端口,基于帧头/帧尾和校验和进行解包。
- 利用 GUI 库绘制仪表盘、电池电量图标和实时数值。
- 对应方框图

3.2 系统流程图
四、 代码介绍
4.1 系统初始化
/* 分配UART发送缓冲区并初始化UART,用于trace日志输出 */
WsfCsEnter();
WsfHeapAlloc(PLATFORM_UART_TERMINAL_BUFFER_SIZE);
WsfBufIoUartInit(WsfHeapGetFreeStartAddress(), PLATFORM_UART_TERMINAL_BUFFER_SIZE);
WsfCsExit();
/* 初始化WSF框架(内存池、OS、定时器和trace系统) */
mainWsfInit();
/* 初始化应用终端(命令行交互接口) */
AppTerminalInit();
/* 链路层初始化完成,退出临界区 */
WsfCsExit();
/* 从NVM加载蓝牙设备地址(BD Address)并设置到控制器 */
bdAddr_t bdAddr;
PalCfgLoadData(PAL_CFG_ID_BD_ADDR, bdAddr, sizeof(bdAddr_t));
LlSetBdAddr((uint8_t *)&bdAddr);
/* Start the 32 MHz crystal and the BLE DBB counter to trim the 32 kHz crystal */
PalBbEnable();
/* Execute the trim procedure - skip for simplicity */
/* Note: Crystal trim requires specific hardware setup. For basic BLE operation, */
/* the default trim values are sufficient. */
wutTrimComplete = 1; /* Pretend trim is done */
/* Shutdown the 32 MHz crystal and the BLE DBB */
PalBbDisable();
4.2 数据扫描
/* 【1】打印扫描报告:源 MAC + 设备名(完整名或短名)*/
APP_TRACE_INFO0("=== Scan Report ===");
WsfTrace(" Addr: %02x:%02x:%02x:%02x:%02x:%02x",
pMsg->scanReport.addr[5], pMsg->scanReport.addr[4],
pMsg->scanReport.addr[3], pMsg->scanReport.addr[2],
pMsg->scanReport.addr[1], pMsg->scanReport.addr[0]);
/* 在广播数据中查找 Local Name 或 Short Name AD 字段并打印 */
if ((pData = DmFindAdType(DM_ADV_TYPE_LOCAL_NAME, pMsg->scanReport.len,
pMsg->scanReport.pData)) != NULL) {
WsfTrace(" Name: %.*s", pData[DM_AD_LEN_IDX], &pData[DM_AD_DATA_IDX]);
} else if ((pData = DmFindAdType(DM_ADV_TYPE_SHORT_NAME, pMsg->scanReport.len,
pMsg->scanReport.pData)) != NULL) {
WsfTrace(" Short Name: %.*s", pData[DM_AD_LEN_IDX], &pData[DM_AD_DATA_IDX]);
}
/* 【2】匹配策略 A:已绑定设备(Bond 匹配)
* - AppDbFindByAddr 在 NVM Bond 列表中命中 → 直接 connect
* - 对端用定向广播+RPA → 先解析 RPA 确认是否写给本设备,解析成功再 connect
* - 对端自身用 RPA → 调用 AppMasterResolveAddr 用 Bond 列表中的 IRK 解析
*/
if ((dbHdl = AppDbFindByAddr(pMsg->scanReport.addrType, pMsg->scanReport.addr)) !=
APP_DB_HDL_NONE) {
if (DM_RAND_ADDR_RPA(pMsg->scanReport.directAddr, pMsg->scanReport.directAddrType)) {
AppMasterResolveAddr(pMsg, dbHdl, APP_RESOLVE_DIRECT_RPA);
} else {
connect = TRUE;
}
} else if (DM_RAND_ADDR_RPA(pMsg->scanReport.addr, pMsg->scanReport.addrType)) {
AppMasterResolveAddr(pMsg, APP_DB_HDL_NONE, APP_RESOLVE_ADV_RPA);
}
4.3 接收到数据进行数据解析
/* 【2】字段解析(小端序:低字节在前,高字节在后) */
int16_t temp = (int16_t)(pMsg->pValue[0] | (pMsg->pValue[1] << 8));
uint8_t humidity = pMsg->pValue[2];
uint16_t voltage = (uint16_t)(pMsg->pValue[3] | (pMsg->pValue[4] << 8));
/* 【3】电池电量估算:小米传感器以 2.000V 为 0%、3.000V(实测上限)为 100%
* 经验公式:battery = (V - 2000) * 100 / 1000,然后夹取 100(上限保护)*/
uint16_t battery = (uint16_t)(((voltage - 2000) * 100) / 1000);
if (battery > 100) battery = 100;
/* 【4】格式化输出到串口 Trace:
* Temperature 注意温度用商/余数格式输出,避免浮点打印;du 是 °C(便于人类看)
*/
APP_TRACE_INFO0("=====Notification from Xiaomi temperature/humidity sensor");
APP_TRACE_INFO5("Temperature: %d.%02ddu, Humidity: %d%%, Voltage: %dmV, Battery: %d%%",
temp/100, abs(temp%100), humidity, voltage, battery);
/* 【5】UI 指示:点亮 LED1 并启动 300ms 定时器
* 连续数据间隔 ≤ 300ms 时 WsfTimerStartMs 会重置定时器,LED 保持常亮(持续接收中)*/
LED_On(LED_BLINK_IDX);
WsfTimerStartMs(&datcCb.ledTimer, LED_BLINK_ON_MS);
4.4 系统运行日志

五、实物演示


六、 难点及体会
由于是第一次使用CodeFusionStudio,所以在使用过程中花了比较长的时间去了解其功能及使用,总体来说该软件实现了开发、调试、刷机的所有操作流程,极大的方便了开发者的使用,具有简洁易用性。