简介:这是一份面向Android开发初学者的BLE蓝牙4.2通信Demo,聚焦设备扫描、连接、读写与数据透传的核心流程,代码经过刻意精简,便于快速理解蓝牙API的调用逻辑。压缩包内共1244个文件,整体约9.24MB,除少量构建缓存外,主要包含Java源码、class/dex、XML布局及JSON配置文件,并附有可直接安装调式用的APK,方便对照运行与验证。目前已有508人学习下载。通过学习该工程目录,读者可以弄清BLE从广播扫描到建立连接、再到特征值读写与通知的完整链路,快速掌握Android系统蓝牙模块的接入方式;同时工程包含Gradle配置、权限声明和回调处理等参考实现,可作为新手搭建蓝牙4.2数据透传应用的入门脚手架,对希望快速打通基础通信流程的开发者很有帮助。
1. bluetooth4.zip 不是普通压缩包:先弄懂它是什么再动手
拿到一个名为 bluetooth4.zip 的文件,第一反应通常是直接解压、找 README、然后开始编译。我在实际项目里见过太多次因为这个顺序而翻车的场景:解压出来的是一整套蓝牙 4.0(BLE)软件工程包,里面可能混着协议栈源码、芯片 SDK、示例工程和一堆看似无关的配置文件。如果一上来就敲 make,大概率会被几十个编译错误淹没。
这个 zip 背后承载的是低功耗蓝牙方案的落地需求——可能是某个外设项目的协议栈基线,也可能是芯片厂商提供的 SDK 裁剪版。它对三类人最有价值:做 BLE 外设开发的嵌入式工程师、想快速评估某颗芯片蓝牙能力的硬件选型人员、以及带学生做无线项目的实验室团队。下面按我处理这类工程包的完整思路走一遍,从验包到编译、烧录、排查,最后让它变成你自己能维护的工程。
2. 解压前先验包:三个命令确认它是不是一份能用的源码包
2.1 用文件签名和完整性测试识别包的真实状态
压缩包翻车最常见的原因不是代码写错,而是这个 zip 本身在传输、拷贝过程中已经损坏。损坏的 zip 在解压时可能只报一行警告,但后面编译阶段会以"缺头文件"、"宏未定义"的形式出现,浪费半天时间排查。
我拿到 bluetooth4.zip 后的第一步从来不是解压,而是先看它的文件签名和条目列表:
# 查看文件基本信息,确认大小和类型 ls -l bluetooth4.zip # 检查文件签名,zip 正常应显示 Zip archive data file bluetooth4.zip # 列出压缩包内所有条目,观察目录结构 unzip -l bluetooth4.zip | head -40 # 测试压缩包完整性,报错说明有损坏 unzip -t bluetooth4.zip这里file命令会读文件头,普通 zip 的开头是PK魔数,如果输出显示Zip archive data说明格式没问题。unzip -l用来在解压前看目录结构,这一步很关键:你会发现包内是单个工程根目录,还是散落一堆文件,这决定了解压时要不要加-d指定目录。unzip -t是完整性测试,它会逐个条目校验 CRC,只要有一个文件校验失败,后面编译时那个文件对应的 obj 就会出问题。
参数说明:head -40是防止条目太多刷屏,只先看前 40 行足够判断结构。unzip如果提示End-of-central-directory signature not found,几乎可以断定这个 zip 不完整或被截断,没救,直接找重新打包的版本。
2.2 解压后按三个维度检查目录结构、文件类型与外部依赖
完整性测试通过后,解压并做一次三维度体检。三维度分别是目录结构是否合理、关键文件类型是否正确、以及工程对外部工具链和 SDK 的依赖是否清晰。
# 解压到独立目录,避免污染当前环境 unzip bluetooth4.zip -d bluetooth4 # 进入工程目录看整体结构 cd bluetooth4 ls -la # 递归查看两层目录,掌握核心模块位置 find . -maxdepth 2 -type d | sort # 对关键文件做类型识别,确认没有空文件或损坏的文本文件 file ./README* ./Makefile* ./main.c 2>/dev/null # 看 README 里声明的工具链和依赖,这是最快获取有效信息的途径 cat README* 2>/dev/null | head -60常见做法是解压时始终加-d指定目录名,不让压缩包直接把文件散在当前目录。目录结构上,一个规范的 BLE 工程包通常有app(应用层)、stack或lib(协议栈库)、hal(硬件抽象)、drivers(外设驱动)和projects或examples(工程入口)这几类目录。如果find输出显示所有源码平铺在根目录,说明这不是一份维护良好的源码包,你的编译成本会更高,要有心理准备。
第三方源码包里常见的坑是文件类型名实不符——README.txt实际是 GBK 编码的 Word 文档,main.c其实是从 IDE 里导出的空壳。file命令能把这些伪装识破,特别是可以配合wc -l看关键源文件的行数,如果主程序只有几十行,它大概率是个模板而不是完整实现。
2.3 根据文件组成判断源码包类型:协议栈、芯片 SDK 还是 demo 工程
同样的 bluetooth4.zip,内部可能是三种完全不同的东西,判断错误会直接导致后续编译方案选错。我的经验是先按下面的特征分类,再决定下一步怎么走。
| 类型 | 典型特征 | 编译方式 |
|---|---|---|
| 完整协议栈源码包 | 有stack/目录,包含大量.c/.h,内有L2CAP、GATT、SM等子目录 | 需要自己编译协议栈库,再做应用链接 |
| 芯片 SDK 包 | 有厂商头文件目录、examples/下有多个板级工程,通常带烧录算法文件 | 使用厂商工具链或 IDE 工程导入 |
| demo 工程包 | 只有一个应用目录、一个 IDE 工程文件、README 教你点按钮编译 | 直接交给 IDE,命令行编译需补 Makefile |
判断代码不复杂,用一条命令就能把顶层目录结构打出来:
# 只看第一层目录,快速分类 find . -maxdepth 1 -type d | sort # 找工程文件类型,判断主要面向 IDE 还是命令行 ls projects/ examples/ 2>/dev/null ls *.uvprojx *.eww Makefile CMakeLists.txt 2>/dev/null逻辑说明:如果存在*.uvprojx这类 IDE 工程文件,说明作者默认你使用集成开发环境;如果只有 Makefile 或 CMakeLists.txt,说明工程天生面向命令行编译。很多 bluetooth4 源码包会同时带 IDE 工程和 Makefile,这时优先看 README 声明支持哪条路径,没有声明就把 Makefile 作为默认。
值得注意的一点:包内如果有预编译的.a或.lib库文件,你的源码改动就只能局限在应用层,协议栈部分是黑匣子。这种情况下不要花时间尝试反汇编改库,正确做法是确认库和头文件的版本匹配关系,别把新版头文件配旧版库,那属于自找麻烦。
3. 读懂 BLE 4.0 工程的主干:从 main 入口追到协议栈配置
3.1 顺着 main 函数画调用关系:先定位初始化流程再动代码
拿到一份解压好的 BLE 工程,最容易犯的错误是直接全局搜索"广播参数"然后乱改。正确进入方式是从main函数入手,把初始化流程画出来。BLE 4.0 工程虽然各家 SDK 风格不同,但初始化骨架高度相似。
int main(void) { /* 第一步:时钟、GPIO、串口、电源等基础硬件初始化 */ hw_init(); /* 第二步:BLE 协议栈初始化,分配内存并启用 */ ble_stack_init(); /* 第三步:注册 GATT 服务,添加服务、特征值 */ gatt_server_init(); /* 第四步:配置广播参数,加载广播数据 */ advertising_init(); /* 第五步:启动广播,让手机可以扫描到 */ advertising_start(); /* 第六步:主循环,处理协议栈事件 */ while (1) { process_events(); } }这是一个典型的 BLE 4.0 外设工程启动序列,顺序不能乱。hw_init先于协议栈初始化是因为协议栈依赖系统时钟;ble_stack_init负责把链路层调度跑起来,这一步失败后面所有 API 都会返回错误码;gatt_server_init注册服务必须在广播启动之前,否则设备已经可连接了却还没有任何服务,手机端连上也会因为读不到服务而断开。
定位每个函数实现的位置,用 grep 比在 IDE 里手动翻目录快很多:
# 找到 hw_init 的定义位置,排除掉头文件的声明 grep -rn "void hw_init" --include="*.c" . # 追踪 ble_stack_init 的实现以及它调用的底层函数 grep -rn "ble_stack_init" --include="*.c" .这里-r是递归,-n显示行号,--include="*.c"限定只搜 C 源文件,避免在头文件声明里浪费时间。改代码前先把这个调用链画出来,哪怕是在纸上画,也能让你搞清楚改动的影响范围——是只影响应用层行为,还是会影响协议栈配置。
3.2 广播间隔、连接间隔与超时参数:BLE 4.0 三大核心参数怎么调
BLE 工程里 90% 的"搜不到设备"、“连接就断”问题出在三个参数上:广播间隔、连接间隔、超时时间。它们直接影响功耗、发现速度和连接稳定性,是这部分的重头戏。
/* 广播配置:典型的可连接低功耗广播 */ static ble_adv_params_t adv_params = { .adv_type = ADV_TYPE_CONNECTABLE, /* 可连接广播,手机能发起连接 */ .adv_interval = 160, /* 单位 0.625ms,160*0.625=100ms */ .channel_map = ADV_CH_ALL, /* 三个广播信道都开,37/38/39 */ .timeout = 0, /* 0 表示持续广播,不自动停止 */ };逻辑说明:adv_interval的单位是 0.625ms,这是一个历史遗留标准,源自蓝牙核心规范对广播时隙的定义。填 160 表示 100ms 广播一次,这是开发调试期的推荐值——手机扫描响应快、体验好。调试完成后如果做 Beacon 类应用,可以拉到 1000ms 以上省电,代价是手机端扫描到设备的延迟变高。timeout如果填非零值,广播会在指定秒数后自动停止,适合需要限时被发现的产品。
连接参数是连接建立后协商的关键,协议栈会通过连接参数更新请求来协商:
/* 连接参数:间隔 30ms,从设备延迟 0,超时 2 秒 */ static ble_conn_params_t conn_params = { .min_conn_interval = 48, /* 单位 1.25ms,48*1.25=60ms */ .max_conn_interval = 48, /* 最小和最大设为相同值,表示固定间隔 */ .slave_latency = 0, /* 从设备跳过连接事件次数,0 表示不跳 */ .conn_sup_timeout = 200, /* 单位 10ms,200*10=2000ms,即 2 秒 */ };连接间隔参数的单位是 1.25ms,超时时间的单位是 10ms,两套单位不同,新手常在这里栽跟头。连接间隔取 30-50ms 适合数据吞吐较高的透传应用,取 100ms 以上适合低功耗传感器。slave_latency允许从设备在无数据时跳过多个连接事件,是省电利器,但要注意跳过的次数不能导致超时判负——超时时间必须大于连接间隔乘上(1 + slave_latency)的值,否则对端会认为连接丢失。
3.3 协议栈配置与芯片手册的对应关系:另类的“参数映射”思路
一份 BLE 4.0 工程里最让人困惑的往往是把协议栈配置宏和芯片手册中的硬件资源对应起来。比如协议栈要占用固定大小的 RAM,这个值不是随便给的,它决定了你能跑多大服务、多少连接。
/* 协议栈使能配置:RAM 与连接数量的映射关系 */ #define BLE_STACK_HEAP_SIZE (1024 * 8) /* 协议栈运行堆 8KB */ #define BLE_MAX_CONN_COUNT 1 /* 最多 1 个连接 */ #define BLE_MAX_MTU_SIZE 247 /* 单包最大 247 字节 */常见的对应关系是:连接数量越多、MTU 越大、GATT 服务越多,需要的堆空间就越大。如果你在配置里开了 8KB 堆但实际服务有十几个特征值,运行时会直接断言失败。这类问题的排查方式就是观察协议栈返回的错误码——初始化阶段如果返回内存不足,不要犹豫,先把BLE_MAX_CONN_COUNT降到 1,或者精简服务,而不是继续加大堆空间把芯片 RAM 挤爆。
操作上还要养成对照芯片手册的习惯。协议栈 API 的宏定义一般能在 SDK 头文件里找到注释,注释会引用手册章节,顺着这个引用能找到它对硬件资源的确切要求。有些工程初始化失败的真正原因是时钟配置——BLE 协议栈对低频时钟的精度有要求,外部晶振没起振时协议栈初始化会直接卡死。这类问题看代码很难发现,拿示波器点一下晶振引脚比盯代码有效得多。
4. 本地编译与烧录:把 bluetooth4.zip 变成一颗能广播的芯片
4.1 工具链选型:按工程现状决定用 IDE 还是命令行
bluetooth4.zip 里如果自带工程文件,离线编译首选就是它配套的工具链。但很多从前辈手里传下来的包,工具链版本和 README 里写的早就对不上了,这时候要靠下面的判断表来选路径。
| 工程内存在的文件 | 推荐编译方式 | 风险点 |
|---|---|---|
| Makefile 或 CMakeLists.txt | 命令行交叉编译 | 工具链路径需手动配 |
| Keil 工程(.uvprojx) | Keil 直接导入 | 版本不兼容会迁移失败 |
| IAR 工程(.eww/.ewp) | IAR 直接导入 | 芯片支持包需安装 |
| 只有源码无工程文件 | 自己补 Makefile | 耗时最长,需要懂链接脚本 |
没有工程文件时要自己补 Makefile,这才是真正考验功力的部分。大多数 BLE 4.0 芯片都是 Cortex-M 内核,可以用通用的arm-none-eabi-工具链,但链接脚本必须从芯片 SDK 里找,芯片型号不同RAM和FLASH起始地址就不同,这个不能拍脑袋写。
4.2 交叉编译三板斧:工具链前缀、头文件路径、链接脚本
让一份从 zip 里解出来的 BLE 工程在命令行下编出固件,说到底就是三件事:编译器选对、头文件找全、链接地址不错。下面是我常用的一份极简 Makefile 片段,保留了最关键的三个变量。
# 工具链前缀,Cortex-M 系列统一用 arm-none-eabi CROSS_COMPILE := arm-none-eabi- # 编译器和链接器 CC := $(CROSS_COMPILE)gcc LD := $(CROSS_COMPILE)gcc OBJCOPY := $(CROSS_COMPILE)objcopy # 头文件路径:按实际目录调整,每缺一个 -I 就少一片头文件 CFLAGS := -mcpu=cortex-m4 -mthumb -I./app -I./stack -I./hal -I./drivers # 链接脚本:芯片 RAM/FLASH 地址布局都写在里面,不要改 LDFLAGS := -T./ldscripts/chip.ld -Wl,--gc-sections # 最终固件输出 firmware.hex: main.elf $(OBJCOPY) -O ihex main.elf firmware.hex参数说明:-mcpu=cortex-m4要跟芯片实际内核匹配,Cortex-M0 的芯片用这个参数会生成非法指令,编译不报错但跑起来就 hardfault。--gc-sections是裁剪未使用函数的关键,配合-ffunction-sections -fdata-sections使用,能把链接后的固件体积压下去不少,BSS 段占用也会更干净。链接脚本文件如果在源码包里找不到,去芯片厂商 SDK 的示例工程里复制,这不是什么丢人的事。
实际编译时不要直接 make,先确认工具链真的存在并且版本符合要求:
# 确认工具链存在且可用 arm-none-eabi-gcc --version # 执行编译,保留完整输出便于定位错误 make V=1 2>&1 | tee build.log # 编译失败时,按错误类型快速定位 grep -n "error:" build.log | head -20首屏错误的前几条最能说明问题。如果全是No such file or directory,检查-I路径是否存在;如果是undefined reference,检查链接脚本的--gc-sections是不是把需要的函数裁掉了,这时候可以在对应文件里加__attribute__((used))临时保留。
4.3 烧录验证:固件进芯片后第一件事是看日志和广播
编译通过不等于程序能跑,烧录是另一个容易出差错的环节。BLE 4.0 芯片的烧录接口一般是 SWD,使用 OpenOCD 是跨厂商的通用方案:
# 用 OpenOCD 擦除并烧录 hex 文件到目标芯片 openocd -f interface/swd.cfg -f target/chip.cfg \ -c "init" \ -c "halt" \ -c "flash write_image erase firmware.hex" \ -c "reset run" \ -c "shutdown"这里interface/swd.cfg是调试器配置文件,target/chip.cfg是芯片配置文件,这两个文件要从 OpenOCD 的脚本目录里根据实际型号选。flash write_image erase会先擦除再写入,避免旧固件残留导致启动异常。如果连接失败,先检查 SWDIO/SWCLK 两根线有没有接反,这两个引脚接反不会烧芯片,但会一直报JTAG-DP STICKY ERROR。
烧录成功后的验证路径讲究一个由内到外。先看串口日志有没有打印协议栈初始化成功的标记;再观察板载 LED 是否按广播间隔闪烁,LED 翻转是最廉价的逻辑分析仪;最后用手机上的通用 BLE 调试工具扫描,能扫到设备名说明协议栈已经在工作,接下来才轮到连接和读写测试。
5. BLE 工程跑不通的常见问题与避坑记录
5.1 解压时没报错,编译却缺文件:先查完整度再查编码
现象:unzip -t全部通过,解压过程无任何错误,但一编译就报某个.h文件找不到,手动去目录里找,文件明明就在那里。
原因:这类问题一半出在文件名编码上——压缩包在 Windows 下打包时用了 GBK 编码文件名,Linux 下解压后文件名乱码,Makefile 里引用的是正常名字,对不上自然找不到。另一半出在大小写上,main.c和Main.c在 Windows 下是同一个文件,到 Linux 下就是两个文件。
解决:文件名编码问题用ls -b看转义后的真实文件名,如果显示\XXX转义序列,说明编码异常,用支持编码转换的解压工具重新解压,或者用convmv转换文件名编码。大小写问题则在工程里全局搜索引用了这个头文件的地方,统一改大小写。这种问题最坑的点在于它会间歇性出现,改完一个又冒出一个,处理完记得全量重新编译一次确认。
5.2 同样的 make 命令,别人能过你不能:环境变量的玄学
现象:从同事那里拿到完全一样的 bluetooth4.zip,在他机器上一条 make 命令出固件,你这边一模一样的操作就是编译不过,报错还五花八门,从找不到编译器到链接脚本语法错误都有。
原因:几乎可以断定是 PATH 环境变量里有多个交叉编译工具链,版本互相冲突。arm-none-eabi-gcc这个名字太常见了,装过多个 SDK 的开发机,PATH 里前一个工具链是 v9.x,后面工程依赖的是 v7.x,版本差异导致编译选项不兼容。
解决:先执行which arm-none-eabi-gcc和arm-none-eabi-gcc --version确认你实际调用的是哪个版本。然后修改 Makefile,把CROSS_COMPILE写成工具链的绝对路径,不要只写前缀名。做完之后make clean重新编译,避免旧的.o文件干扰。这是血泪经验,绝对路径能让这类问题彻底消失。
5.3 手机扫不到设备:广播配置背了 90% 的锅
现象:固件烧录成功,串口日志显示协议栈初始化完成、广播已启动,但手机上的 BLE 调试工具就是扫不到任何设备。
原因:最常发生的是广播数据超过了 31 字节——BLE 4.0 的 legacy advertising 数据包上限就是 31 字节,广播名称太长加上服务 UUID 放一起就超了,协议栈会静默丢弃或者只发部分数据。其次是广播间隔配置得太大,比如改到了 1000ms 以上,手机扫描窗口刚好错过广播包。
解决:先临时把广播间隔调到 100ms,也就是adv_interval=160,这是调试期最稳的值。然后把广播数据里的设备名缩短,或者把设备名从广播数据里去掉,只保留服务 UUID,名字让手机连接后再通过 GATT 读取。改完重新编译烧录,再用手机扫描,这一步能过滤掉绝大多数"搜不到设备"的案例。
5.4 连接建立几秒后就断开:先说清楚超时时间和服务端角色
现象:手机能扫到设备,点击连接也能连上,但保持不了几秒就自动断开。串口日志里能看到connection timeout、link loss之类的关键字,或者根本没有打印,只是悄悄断掉。
原因:排查顺序先看超时参数。conn_sup_timeout如果配得比连接间隔还短,或者只大一点点,链路层在稍微有点干扰的情况下就会判定连接丢失。另一个常被忽略的原因是手机作为中心设备发起了连接参数更新请求,但固件里的回调函数直接拒绝了请求,手机端等待超时后主动断开。
解决:把conn_sup_timeout调到大于连接间隔加从设备延迟的总时间,保守做法是让超时时间至少是连接间隔的四到六倍。比如连接间隔 50ms,超时设成 2000ms 就非常稳。连接参数更新请求的回调里,不要一律拒绝,把请求里的参数打印出来看实际值,让请求通过再观察连接稳定性,这一步能区分是参数问题还是协议栈 bug。
5.5 编译通过但一运行就 hardfault:栈溢出和 RAM 布局是常客
现象:固件烧录后设备重启,串口打印停在某一步,或者直接进入 hardfault 中断,调试器里看到 PC 指针飞到了奇怪地址。
原因:BLE 协议栈对 RAM 有硬性要求,而工程自带的链接脚本可能没有给协议栈预留合适的内存段,导致协议栈数据被应用数据覆盖,一运行就崩。另一个高发原因是中断优先级配置不当,BLE 协议栈的中断优先级有上限要求,蓝牙中断被高优先级任务抢占后协议栈内部状态错乱。
解决:先把hardfault_handler里打印出故障时的 LR 和 PC 值,定位是内存踩踏还是非法指令。如果指向协议栈库内部,九成是 RAM 布局问题,检查链接脚本里协议栈是否与主栈共用区域,必要时给协议栈单独划分段。中断优先级按 SDK 示例里的配置来,不要自己"优化"成更高优先级,这个玄学问题让协议栈厂商的建议值说了算。
6. 把 bluetooth4.zip 变成自己的工程:patch 维护与裁剪实战
6.1 先建立基线再动手:第三方代码改前必须做的版本管理习惯
拿到一份能编译通过的 bluetooth4 工程后,我强烈建议你在修改任何代码之前先把它提交到一个 git 仓库。对第三方源码包直接开改是自找麻烦——厂商发新版本时你想合并更新,如果没有基线,diff 都不知道跟谁比。很多做过 BLE 项目的工程师都有过合并 patch 合并到怀疑人生的经历。
# 在工程目录初始化 git 仓库 git init git add -A git commit -m "import bluetooth4 baseline, unmodified" # 后续所有改动用统一前缀描述,便于回溯 git checkout -b feature/beacon_adv逻辑说明:git init后首次commit建立的基线是你的后悔药,之后任何改动都可以对照基线回滚。建立feature分支再动手,主分支永远保持可编译状态。这个习惯成本极低,但能救你无数次——特别是协议栈升级时,一条git log能看清本地改过哪些文件、哪些可以保留、哪些需要重做。
6.2 裁剪最小化:用配置宏关功能,而不是直接删源文件
BLE 4.0 工程的裁剪逻辑和普通 C 工程不同。协议栈内部的.c文件牵扯重重引用,直接删除会引发连锁缺失。正规做法是通过配置头文件里的宏来关闭功能,让编译器和链接器的裁剪机制去去除非用代码。
/* 裁剪配置示例:只保留外设角色和一个自定义服务 */ #define BLE_ROLE_PERIPHERAL 1 /* 外设角色 */ #define BLE_ROLE_CENTRAL 0 /* 关闭中心设备角色,省下大量 RAM */ #define BLE_SVC_CUSTOM_SERVICE 1 /* 保留自定义透传服务 */ #define BLE_SVC_DEVICE_INFO 0 /* 关闭设备信息服务 */ #define BLE_SVC_BATTERY 0 /* 关闭电池服务 */参数说明:关闭中心角色能省下最多资源,因为中心设备需要同时维护多个连接的上下文。但注意别关掉自己实际在用的服务,关闭后头文件里对应的 API 声明可能还在,链接时才报 undefined reference,看到这类错误先回来检查宏开关。
改完配置后务必加一条只读不改的验证命令,确认固件体积确实减少了:
# 对比裁剪前后的固件大小,FLASH 和 RAM 占用一目了然 arm-none-eabi-size main.elfsize输出里的text是 FLASH 占用,data + bss是 RAM 占用。裁剪生效时text会明显下降。如果配置改了但text毫无变化,多半是宏开关没有被实际编译条件引用,或者编译器没开--gc-sections,回去检查 Makefile。
6.3 改动后的回归验证清单:五项检查确认没改坏基础能力
每次改动完,我都会跑一遍下面的验证清单,按顺序执行,任何一项失败都意味着改动引入了回归问题。
| 验证项 | 预期结果 | 失败时优先检查 |
|---|---|---|
| 正常广播 | 手机能扫描到设备名 | 广播数据长度、广播间隔 |
| 可连接 | 点击连接能建立链路 | 可连接广播类型、连接参数 |
| GATT 读写 | 特征值能读写、数据无错乱 | 服务注册顺序、MTU 协商结果 |
| 连接稳定性 | 持续连接 10 分钟不掉线 | 超时时间、从设备延迟 |
| 待机功耗 | 电流在标称范围内 | 关闭的宏是否真正生效、外设时钟 |
这一轮验证跑完,你的 bluetooth4.zip 才算真正变成自己能维护的工程。早年我拿到协议栈包都是直接上手改源码,结果厂商发布新版本后 merge 冲突几百处,最后只能推倒重来。现在的习惯是先提交基线、再开分支、所有裁剪靠配置宏、每次改动跑一遍验证清单。希望帮到你。
本文还有配套的精品资源,点击获取