1. 项目需求
本次参加活动funpack使用的板卡是MAX32655FTHR
本次完成的活动任务是任务二:
使用BLE功能读取米家温湿度计的读数,并显示在LCD屏幕上
2.思路解析
本次要求显示到LCD屏幕上,所以我们就需要自己使用LCD屏幕,我手头上有一块LCD屏幕,来完成我们这次活动的显示。
其中驱动型号是:ST7735S

之后要处理其中BLE相关的,所以我们在下载MAX的SDK之后,选择相关BLE例程进行我们的开发。

我们选择BLE_datc作为我们的开发例程
这里需要米家温湿度计,这里我选择了小米温湿度计3mini作为我们的获取温度湿度的器件。

这里关于BLE的获取,我们还需要准备一个软件nRF Connect
有手机板和电脑板这里我就选择了手机版

3.实现流程图

4.实现步骤
4.1 获取服务与特征的UUID
在查找相关教程,基本都是通过ESP32实现的,根据其中的说明的经验,首先我们需要扫描到小米温湿度传感器的GATT的服务和特征。
在低功耗蓝牙俗称BLE,其中传输实现是通过GATT来实现的,在GATT下面是通过ATT协议来进行传输,其中将蓝牙的一些服务和特征实现我们的消息的沟通,所以我们需要先将扫描到信息获取到。
这里我们打开手机APP扫描周围的蓝牙名称:
在小米外壳上就是这个MJWSD06MMC,我们点击连接

在外层上面看,我们的BLE设备拥有很多的服务,这里我们选择其中服务包括我们的温湿度传感器的。

上面我们已经找到相关服务的UUID,注意这里的UUID要保存好,因为这里的UUID是每一个特征或者服务的唯一识别码。
接下来我们要保存我们的存放温湿度的特征的服务UUID
我们可以点击旁边的下载,可以获取到Value就可以知道这个当前的特征传递着什么内容,好我们现在成功获取俩个UUID。

4.2 配置BLE_datc
我们要先修改烧录的板卡设备的整个环境,在MAX32655有俩款设备,默认不是我们的FTHR,所以我们要进行修改。
在目录下的makelife修改我们的BOARD

之后这里也要修改,因为这里是在make编译也会识别这里的宏定义,然后将下面也进行修改,下面修改为我们小米温湿度传感器的名称
BOARD = FTHR_Apps_P1
ADV_NAME?=MJWSD06MMC

我们就将其中的UUID填写进去,这里会根据UUID来获取,这里将小端形式格式存放。

之后我们就需要处理识别的逻辑,其中获取的数值是16进制,我们需要对其进行转换。
我们成功连接之后其中的数值会通过这个函数来进行通知
static void datcValueNtf(attEvt_t *pMsg)
{
if (pMsg->handle == pSecDatHdlList[pMsg->hdr.param - 1][SEC_DAT_HDL_IDX])
printf(">> Notification from secure data service <<<\n");
/* 处理接收到的数据 */
if (datcCb.speedTestCounter == 0) {
// 调用小米传感器数据处理函数
Deal_MISensor(pMsg->pValue, pMsg->valueLen);
}
}
在这里我们获取到其中的数值实现Deal_MISensor函数对其中的数值进行解析
基本代码如下,其中返回的16进制包含了温湿度和电压,所以我们通过将进制转换显示到LCD屏幕上。
// 定义存储小米传感器数据的结构体
typedef struct {
float temperature;
uint8_t huminity;
float batVoltage;
} MI_SENSOR_DATA_t;
// 全局变量存储传感器数据
static MI_SENSOR_DATA_t Mi_Sensor_data;
// 处理小米传感器数据
static void Deal_MISensor(uint8_t *rawdata, uint8_t rawdata_len)
{
uint8_t rawdata_len_copy = rawdata_len;
uint8_t rawdata_copy[rawdata_len_copy + 2];
uint16_t temp = 0;
uint8_t buffer[32] = {0};
memcpy(rawdata_copy, rawdata, rawdata_len_copy);
printf("REC data len: %d\n", rawdata_len_copy);
// 打印原始16进制数据
printf("Raw data (hex): ");
for (int i = 0; i < rawdata_len_copy; i++) {
printf("%02X ", rawdata_copy[i]);
}
printf("\n");
/* 数据格式: 42 0a 3f 2a 0b */
/* 0x0a42 -> 温度, 0x3f -> 湿度, 0x0b2a -> 电量 */
// 方法1: 小端序 (原始方法)
temp = rawdata_copy[1];
temp = (temp << 8) + rawdata_copy[0];
Mi_Sensor_data.temperature = (float)temp / 100.0;
printf("Method1 - Temp (LE): 0x%04X = %.2f°C\n", temp, Mi_Sensor_data.temperature);
// 湿度 (字节2)
temp = rawdata_copy[2];
Mi_Sensor_data.huminity = temp;
printf("Humi: 0x%02X (%d%%)\n", temp, temp);
// 电压 - 方法1: 小端序
temp = rawdata_copy[4];
temp = (temp << 8) + rawdata_copy[3];
Mi_Sensor_data.batVoltage = (float)temp / 1000.0;
printf("Method1 - Volt (LE): 0x%04X = %.3fV\n", temp, Mi_Sensor_data.batVoltage);
// 电压 - 方法2: 大端序
// 使用单个打印调用输出所有结果
printf("Result: temp=%.2f, humi=%d, vol=%.3fV\n",
Mi_Sensor_data.temperature,
Mi_Sensor_data.huminity,
Mi_Sensor_data.batVoltage);
// 在LCD上显示温湿度数据
// 显示标题
sprintf((char *)buffer, "Xiaomi Sensor 3mini");
LCD_ShowString(0, 25, (uint8_t *)buffer, BRRED, BLACK, 16, 0);
// 显示温度
sprintf((char *)buffer, "Temp:");
LCD_ShowString(10, 40, (uint8_t *)buffer, GREEN, BLACK, 16, 0);
sprintf((char *)buffer, "%.2f C", Mi_Sensor_data.temperature);
LCD_ShowString(100, 40, (uint8_t *)buffer, WHITE, BLACK, 16, 0);
// 显示湿度
sprintf((char *)buffer, "Humidity:");
LCD_ShowString(10, 60, (uint8_t *)buffer, BLUE, BLACK, 16, 0);
sprintf((char *)buffer, "%d %%", Mi_Sensor_data.huminity);
LCD_ShowString(100, 60, (uint8_t *)buffer, WHITE, BLACK, 16, 0);
// 显示电压
sprintf((char *)buffer, "Voltage:");
LCD_ShowString(10, 80, (uint8_t *)buffer, RED, BLACK, 16, 0);
sprintf((char *)buffer, "%.3f V", Mi_Sensor_data.batVoltage);
LCD_ShowString(100, 80, (uint8_t *)buffer, WHITE, BLACK, 16, 0);
// 显示状态
// sprintf((char *)buffer, "Status: Connected");
// LCD_ShowString(10, 120, (uint8_t *)buffer, YELLOW, BLACK, 12, 0);
}
在main函数下我们初始化了LCD,上电显示等待连接,LCD不是本次的重点,这里没有对其详细讲解,如果感兴趣可以查看我存放的代码进行移植。

最后我们点击终端任务,去执行bulid 和flash就可以成功将代码烧录到我们的板卡上了。

5.效果展示
串口显示我们的相关数据,这里对字符支持不好,所以显示乱码。
上电状态

成功连接,由于屏幕太亮了所以调节了以下亮度会导致有点模糊

遇到的问题
一开始想着可以使用
通过elf下载,导致程序一直没有正常烧录,最后还是修复了电脑的环境实现通过task通过openocd进行烧录程序。