如何正确解码Characteristic UUID 2A37的RR间隔值?解码异常求助
问题分析与解决
核心问题:字节序错误
蓝牙BLE特征数据采用**小端序(Little-Endian)**存储多字节数值,你的代码错误地按大端序拼接了RR间隔的字节,导致计算出异常大的数值。
数据解析过程
原始数据:0x10, 0x54, 0xAA, 0x02, 0x99, 0x02
- Flags字节(0x10):二进制为
00010000,说明:- 心率格式为8位(第0位为0)
- 存在RR间隔数据(第4位为1)
- 心率值:第1字节
0x54,即84bpm,这部分你的代码是正确的。 - RR间隔数据:从第2字节开始,每2字节代表一个RR间隔值。小端序要求低位字节在前,高位字节在后,所以第一个RR间隔的两个字节
0xAA(低位)和0x02(高位)应拼接为0x02AA(十进制682),而不是你的代码中拼接的0xAA02(十进制43522)。
修正后的计算逻辑
RR间隔的单位是1/1024秒,转换为毫秒的公式是:RR间隔(ms) = (拼接后的十进制值 / 1024) * 1000
代入682计算:682 / 1024 * 1000 ≈ 666ms,这是合理的生理数值。
修正后的C++代码
#include <iostream> #include <cmath> using namespace std; const int RR_INTERVAL_PRESENT_BIT = 4; const int HEART_RATE_FORMAT_BIT = 0; const int RR_INTERVAL_UNIT = 1024; int main() { // characteristic UUID value unsigned char characteristic[] = {0x10, 0x54, 0xAA, 0x02, 0x99, 0x02}; // read the flags unsigned char flags = characteristic[0]; int heartRateFormat = (flags & (1 << HEART_RATE_FORMAT_BIT)) ? 2 : 1; int rrIntervalPresent = (flags & (1 << RR_INTERVAL_PRESENT_BIT)) ? 1 : 0; // calculate heart rate and rr-interval int heartRate = 0; int rrInterval = 0; int index = 1; if (heartRateFormat == 2) { // 心率的多字节同样是小端序,修正此处逻辑 heartRate = (characteristic[index + 1] << 8) | characteristic[index]; index += 2; } else { heartRate = characteristic[index]; index += 1; } if (rrIntervalPresent) { // 修正小端序拼接逻辑:低位在前,高位在后 rrInterval = (characteristic[index + 1] << 8) | characteristic[index]; rrInterval = round(rrInterval / (double)RR_INTERVAL_UNIT * 1000); // 读取第二组RR间隔(原始数据包含两组) int rrInterval2 = (characteristic[index + 3] << 8) | characteristic[index + 2]; rrInterval2 = round(rrInterval2 / (double)RR_INTERVAL_UNIT * 1000); cout << "Second RR interval: " << rrInterval2 << " ms" << endl; } cout << "Heart rate: " << heartRate << " bpm" << endl; cout << "RR interval: " << rrInterval << " ms" << endl; return 0; }
额外说明
- 蓝牙BLE的多字节数值(如16位、32位数据)均采用小端序存储,解析时必须注意字节顺序。
- 你的原始数据包含两组RR间隔(
0xAA 0x02和0x99 0x02),第二个值计算后约为653ms,符合正常心率的RR间隔范围。
内容的提问来源于stack exchange,提问作者Kwang Chee Seng
相关产品推荐
相关产品推荐

