ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

EFR32BG22低功耗蓝牙透传实战:环境搭建与GATT服务开发避坑指南

EFR32BG22低功耗蓝牙透传实战:环境搭建与GATT服务开发避坑指南 1. 为什么要折腾EFR32BG22这颗芯片到底适合谁先说结论EFR32BG22是一颗为低功耗蓝牙BLE专门优化的SoCCortex-M33内核主频能跑到38.4MHzFlash从352KB到512KB可选RAM从32KB起步。单看性能它不算激进但它最值钱的地方在于极低的休眠电流和不错的射频表现。官方标称的接收电流在3.6mA左右TX 0dBm时大约4.1mAEM2模式下电流能到1.4uA级别。做纽扣电池供电的传感器、门锁、ibeacon、医疗贴片这类设备这个功耗曲线非常关键。我当初选它主要有三个原因。第一它原生支持Bluetooth 5.2协议栈包含LE Coded PHY能跑远距离模式。第二Silicon Labs的协议栈叫Bluetooth SDK以源码或库的形式集成在Simplicity Studio里BLE的GATT操作、连接管理、广播等全都有现成API不需要自己啃蓝牙规范硬实现。第三这颗芯片的封装选择多QFN32、QFN40都有板上面积能压得很小。不过说实话它的开发方式和ESP32、nRF52840那种比较灵活的开源生态有区别。Silicon Labs的整个工具链围绕Simplicity Studio展开环境安装、SDK管理、工程生成、调试烧录基本都在这一个IDE里完成。好处是集成度高坏处是如果你刚接触这个生态光是环境配置就能卡你两三天。这篇就把从装环境到写出一个能用的透传服务的过程完整走一遍把我在里面踩过的坑全部标出来。我默认你已经有一点嵌入式基础至少用过Keil、IAR或者STM32CubeIDE这类工具对CMSIS、MDK这些概念不陌生。如果你是完全零基础建议先补一点ARM Cortex-M的基础知识再来折腾蓝牙协议栈不然遇到问题会很难定位是硬件问题还是协议栈问题。2. Simplicity Studio安装与工程创建避坑2.1 下载与安装器的坑Simplicity Studio的下载入口在Silicon Labs官网选择对应操作系统的安装包就行。Windows版本是一个exeLinux版本是压缩包macOS也有对应版本。这里有个很关键的细节这个安装器启动后会在线下载一堆组件所以你的网络环境最好稳定不然下载到一半失败、重新再来你会非常崩溃。安装时它会问你安装路径默认在C盘但我强烈建议改到其他盘。因为后面SDK、Gecko SDK、无线协议栈都会解压到这个目录下随便几个G就没了。我一开始装在C盘后来SDK升级时C盘直接满了迁移的时候又要把所有路径重新配一遍非常折腾。安装完成后第一次打开它会让你登录Silicon Labs账号。这个步骤不是可选的是必须的因为SDK组件、文档下载都和账号绑定。注册很简单在官网注册一个免费账号就行。这里提示一下注册时邮箱一定要填真实有效的因为后面下载SDK和激活一些功能要用它收验证信息。我见过有人随便填了个临时邮箱结果SDK下载权限一直激活不了卡了好几天。2.2 SDK版本选择别追新要选稳登录之后进入主界面在“Installation Manager”里可以安装SDK。这里有一个非常容易踩的坑SDK版本的选择。Simplicity Studio提供多个SDK版本比如Gecko SDK 4.x系列里面包含Bluetooth SDK、EmberZNetZigbee、Proprietary等协议栈。建议安装时只勾选你需要的那几个别一次全装否则下载量大而且后续编译时容易出莫名其妙的依赖冲突。版本怎么选我的经验是除非有新功能刚需否则不装最新版选上一个稳定版本。比如目前4.3.x和4.4.x都算稳定但4.4.x我刚用时遇到过一次GATT配置生成器的小bug后来回退到4.3.x才稳定。如果做量产项目版本选定之后就不要轻易在项目中途升级SDK了因为Silicon Labs的SDK在不同小版本之间的API改动有时候是不兼容的特别是BLE的事件结构体字段升级后你的代码可能编译不过。安装SDK的方法在Installation Manager里选择“Bluetooth”相关组件勾选后点击安装它会自己下载并解压。装完以后主界面会显示可用的SDK和示例工程。2.3 创建第一个蓝牙工程创建工程的入口是主界面右上角的“Create New Project”。这里有两种常用的工程类型Bluetooth - SoC Empty空工程只有最基本的蓝牙协议栈初始化和系统循环适合完全自定义的玩法。Bluetooth - SoC Empty (with bootloader)带bootloader的空工程如果你后面打算做OTA升级选这个。对于第一次做透传服务的人来说我建议选“Bluetooth - SoC Empty”然后自己手动添加服务和逻辑这样你能清楚掌握整个流程。因为一旦用模板工程模板里会包含大量无关组件很多新手在改模板的时候越改越乱。创建时需要选择目标芯片型号。我用的开发板是EFR32BG22 Thunderboard芯片型号自动识别为EFR32BG22C224。如果你的板子是自定义PCB选对应的芯片型号即可。工程名字按自己的习惯取路径不要有中文和空格。工程生成之后界面会左右分栏左边是工程结构树和配置文件右边是代码编辑区。此时工程还不能直接编译出能用的固件因为蓝牙协议栈的配置还需要你来定比如广播名称、连接参数、GATT服务等。2.4 编译器与调试器配置Simplicity Studio自带GCC编译器也可以切换IAR或者Keil。如果你是习惯用IAR的人可以在工程的Properties里改Toolchain。不过我个人建议直接用自带的GCC因为Studio对GCC的集成最顺畅编译、烧录、调试一条龙切换第三方编译器反而会出现在线调试不识别设备的问题。调试器方面Thunderboard板载了J-Link调试器插上USB之后电脑会自动识别。如果设备管理器里看不到端口或者调试器设备大概率是驱动问题。Silicon Labs的驱动有时候会被Windows自动更新覆盖掉解决方法是重新安装SEGGER J-Link驱动。Studio菜单里也有一个“Install J-Link Driver”的选项可以直接点。提示插上板子后如果Studio右下角的Device列表里没有出现你的设备检查USB线是不是只有充电没有数据功能的那种线。这种线我踩过好几次尤其在办公室随机拿一根线就插结果就是识别不了设备排查半天发现是线的问题。3. 透传服务的第一步GATT结构设计3.1 什么是透传服务透传简单说就是手机APP向设备发一包数据设备原封不动或者按协议解析后收到设备要向手机发数据时也通过相同的通道发出去。在BLE的GATT模型里这个通道就是一个具有Write和Notify属性的特征值。你可能在别的项目里用过HC05、HC06这种经典蓝牙模块它们的透传模式是串口透明传输手机上用蓝牙串口助手就能收发。BLE和经典蓝牙不太一样BLE的传输单位是一个个Attribute属性数据被组织成Service、Characteristic、Descriptor这样的结构。手机端收发数据的逻辑需要按照这些属性来做而不是像串口那样直接流式读写。所以BLE透传服务本质上就是用GATT定义几个特征值设备的应用层把收到的数据转成业务处理把要发送的数据写入特征值并通过Notification主动推给手机。3.2 自定义GATT Service的配置方法在Simplicity Studio中GATT的配置不是在代码里手写而是通过一个图形化配置文件来完成的。这个文件叫gatt_configuration.btconf在工程根目录下。双击它就能打开GATT配置器。我们先说一个最容易出错的地方。GATT服务的UUID决定了手机端App识别Service的方式。你可以使用标准UUID比如电池服务0x180F、设备信息服务0x180A这类服务的使用方式和字段定义在蓝牙规范里有明确要求。而透传服务属于自定义服务需要自定义UUID。自定义UUID的典型格式是128位比如0x0000AA01-0000-1000-8000-00805F9B34FB这里前面的AA01就是你的服务特征。我通常习惯用一个固定的128位UUID来标识整个透传服务再用两个不同的特征值UUID分别表示“发送”设备接收数据和“通知”设备发送数据。具体怎么定义没有硬性规定只要和手机端一致就行。一个参考方案角色UUID全128位属性服务0x0000AA00-0000-1000-8000-00805F9B34FB主服务接收通道0x0000AA01-0000-1000-8000-00805F9B34FBWrite发送通道0x0000AA02-0000-1000-8000-00805F9B34FBRead, Notify在GATT配置器里点击“Add Service”新建一个自定义服务填入上面的服务UUID然后在这个服务下添加两个Characteristic。接收通道的Properties勾选Write也可以勾选Write Without Response这个后续说发送通道勾选Read和Notify同时还需要在Descriptor里加入Client Characteristic Configuration DescriptorCCCD否则手机端没法订阅Notify。CCCD这个东西是BLE里特别容易漏的一环。它的作用就是让设备知道手机是否已经订阅了Notification。如果特征值有Notify属性但没有添加CCCD描述符手机端的setCharacteristicNotification接口就算调用了设备端也不会真正发送通知。很多新手在写透传的时候数据一直发不出去最后发现是GATT配置里忘了勾选CCCD。3.3 GATT事件机制数据是怎么流转的Silicon Labs的蓝牙协议栈是基于事件Event驱动的。协议栈运行在一颗独立的内核RAIL上应用逻辑运行在M33内核上两者通过IPC通信。当蓝牙底层发生某件事比如手机连上了、断开连接了、写了一个特征值协议栈会给应用层抛一个事件你的代码就在事件回调里处理它。理解这一点非常重要。因为你不能在应用层用while(1)死等数据而是要注册一个事件处理函数在对应的case里处理收到的数据。核心的事件处理代码长这样void sl_bt_on_event(sl_bt_msg_t *evt) { switch (SL_BT_MSG_ID(evt-header)) { case sl_bt_evt_gatt_server_attribute_write_request_id: handle_write_request(evt); break; case sl_bt_evt_gatt_server_notification_sent_id: break; case sl_bt_evt_connection_opened_id: break; case sl_bt_evt_connection_closed_id: break; } }收到数据的事件是sl_bt_evt_gatt_server_attribute_write_request_id它和你GATT配置里的特征值对应。怎么知道手机写的是哪个特征值通过事件里的evt-data.evt_gatt_server_attribute_write_request.attribute字段判断。这个attribute的编号就是你在GATT配置器里定义特征值时自动生成的ID。例如我的接收通道特征值在配置器里的ID是4那么写入处理就需要判断if (evt-data.evt_gatt_server_attribute_write_request.attribute 4) { uint8_t *data evt-data.evt_gatt_server_attribute_write_request.value.data; uint8_t len evt-data.evt_gatt_server_attribute_write_request.value.len; // 这里data就是手机发过来的数据len是长度 }这里有个容易混乱的地方attribute的ID不是UUID而是GATT配置器里每个特征值的一个内部编号。如果你在配置器里删掉重新添加了特征值ID可能会变。所以建议你在配置器里为每个特征值设置一个语义化的名字如rx_char、tx_char然后在代码里用宏定义来对应避免ID写死之后改配置导致代码要同步改。3.4 Notification的发送方式设备向手机发数据的核心API是sl_bt_gatt_server_send_notification。它的原型大致是sl_status_t sl_bt_gatt_server_send_notification( uint8_t connection, uint16_t characteristic, uint16_t len, const uint8_t *data);这里connnection是连接句柄characteristic是特征值的IDlen和data就是要发送的数据缓冲。这个函数是异步的调用后不会立即完成发送数据会被协议栈缓存发送完成后上报sl_bt_evt_gatt_server_notification_sent_id事件。一个典型发送函数void send_to_phone(const uint8_t *buf, uint16_t len) { uint8_t conn get_active_connection(); if (conn 0xFF) return; // 没有连接时不发送 sl_status_t sc sl_bt_gatt_server_send_notification( conn, TX_CHAR_ID, len, buf); if (sc ! SL_STATUS_OK) { // 打印错误比如缓冲区满、未订阅等 } }注意如果手机没有订阅Notification调用这个函数会返回错误码SL_STATUS_INVALID_STATE或者类似的值。所以发送前最好维护一个标志位在CCC更新事件里记录手机是否已订阅。不然连接上之后设备主动往手机推数据时会频繁报错日志里刷屏影响问题排查。4. 透传项目实战从SDK配置到代码实现4.1 初始化流程协议栈和硬件外设SDK生成的工程会自动生成app.c里面已经包含了app_init和app_process_action这两个函数。app_init在系统上电后被调用你可以在这里做硬件初始化比如串口、GPIO、传感器等。蓝牙协议栈的初始化由SDK自动完成你不需要手动调用。不过有一个地方要特别留意如果你想在开机之后立刻开始广播SDK默认的例程里会调用sl_bt_start_advertising或者类似接口。这个接口通常在app_process_action里通过一个状态机调用。但如果你用的是Empty工程它可能没有默认启动广播需要你自己在app_init里显式开启。开启广播的常用方式static void start_advertising(void) { sl_bt_advertiser_create_set(advertising_set_handle); sl_bt_advertiser_set_connectable(advertising_set_handle, 1); sl_bt_legacy_advertiser_set_configuration(advertising_set_handle, 0); sl_bt_legacy_advertiser_generate_data(advertising_set_handle, sl_bt_advertiser_general_discoverable, NULL); sl_bt_legacy_advertiser_start(advertising_set_handle, sl_bt_advertiser_connectable_scannable); }如果这个流程没做你很可能遇到“手机搜不到设备”的问题。空工程不会自动启动广播这是新手最容易摔的一个坑。4.2 UART透传的硬件通路大多数情况下你的MCU会有外部传感器或者主控MCU通过UART和BG22通信。比如一个典型的架构主控单片机通过串口把数据发给BG22BG22把数据通过BLE透传给手机手机发来的数据BG22通过串口转发给主控单片机。那么这个透传服务就需要在BLE事件和UART中断之间做一个桥接。我们以EFM32系列自带的EUSART外设为例。初始化时需要配置波特率、数据位、停止位、流控等。我的常用配置是115200-8-N-1无流控。注意BG22有些型号的引脚支持EUSART有些引脚是普通GPIO复用不能随便接需要查阅数据手册确认。串口接收的处理方法有两种。一种是中断接收在中断回调里把数据存入环形缓冲区然后主循环从缓冲区取出数据调用sl_bt_gatt_server_send_notification发送。另一种是DMA接收到设定长度后触发DMA完成中断。DMA方式效率高但实现复杂度也更高。对于透传这种小数据量场景串口中断加环形缓冲区就够用了。一个简易的环形缓冲区实现#define RING_BUF_SIZE 256 static uint8_t ring_buf[RING_BUF_SIZE]; static volatile uint16_t head 0, tail 0; void uart_rx_isr(uint8_t byte) { ring_buf[head] byte; head (head 1) % RING_BUF_SIZE; // 如果head和tail相遇说明缓冲区满这里可以做丢包或覆盖处理 }主循环里这样处理while (head ! tail) { uint8_t dat ring_buf[tail]; tail (tail 1) % RING_BUF_SIZE; send_to_phone(dat, 1); }要注意BLE单次Notification的最大长度受MTU限制。默认MTU是23字节扣除3字节的ATT头实际有效负载最多20字节。如果你想一次发送更多的数据需要协商MTU。在连接建立后的connection_opened事件里可以调用sl_bt_gatt_server_open_connection或者类似的API来请求更大的MTU手机端也会在连接后发起MTU协商。两端协商成功后发送长度可以提升到247字节BLE 5.0的默认最大值。所以透传模块的设计目标如果一次要发送超过20字节的数据你要么自己分包要么协商MTU。我一般建议协商MTU到185或者247这样对一个简单协议来说绝大多数包一次就能发完省去组包拆包逻辑。4.3 广播参数的合理选择广播这一块除了要启动之外参数也影响实际体验。广播间隔越短手机搜到设备越快但功耗越高。我常用的是广播间隔100ms到200ms广播类型可连接、可扫描connectable scannable广播名称建议短一点不超过8个字符。因为广播包的总长度有限如果你想包含厂商自定义数据设备名太长会挤占自定义数据的位置广播里还能包含厂商特定数据可以用sl_bt_legacy_advertiser_set_data接口设置。比如我的设备会在广播包里放温湿度数据手机不用连接就能在广播里看到当前值。这种用法在电子价签、ibeacon门牌号这样的场景里非常常见。关于广播名称很多人会在这个地方踩坑。SDK默认的广播名可能叫“Empty Example”或者“EFR32BG22”如果你没有在GATT配置器里改设备名称特征值Device Name Characteristic手机上看到的就是默认名字。要改名字有两种方式一种是在GATT配置器的Device Information Service里修改“Device Name”字段另一种是代码里调用sl_bt_gatt_server_write_attribute_value动态修改。前者适合固定名称后者适合需要量产不同名称的场景。4.4 应用逻辑完整的透传代码框架我把一个最精简但可运行的透传代码框架贴出来你可以直接在这个骨架上再加业务逻辑。#include sl_bt_api.h #include sl_board_control.h #include em_eusart.h #include em_cmu.h #define RX_CHAR_ID 4 // 注意这个ID要和你gatt_configuration.btconf里一致 #define TX_CHAR_ID 6 static uint8_t active_connection 0xFF; static uint8_t notify_enabled 0; void app_init(void) { // 初始化串口、GPIO等 init_uart(); init_gpio(); // 打开广播 start_advertising(); } void app_process_action(void) { // 从串口读数据并发送到BLE while (ring_buf_not_empty()) { uint8_t d ring_buf_read(); send_to_phone(d, 1); } } void sl_bt_on_event(sl_bt_msg_t *evt) { switch (SL_BT_MSG_ID(evt-header)) { case sl_bt_evt_connection_opened_id: active_connection evt-data.evt_connection_opened.connection; break; case sl_bt_evt_connection_closed_id: active_connection 0xFF; notify_enabled 0; // 可选重新启动广播 start_advertising(); break; case sl_bt_evt_gatt_server_attribute_write_request_id: if (evt-data.evt_gatt_server_attribute_write_request.attribute RX_CHAR_ID) { uint8_t len evt-data.evt_gatt_server_attribute_write_request.value.len; const uint8_t *val evt-data.evt_gatt_server_attribute_write_request.value.data; // 数据通过串口转发给外部MCU uart_send_buf(val, len); } break; case sl_bt_evt_gatt_server_characteristic_status_id: if (evt-data.evt_gatt_server_characteristic_status.characteristic TX_CHAR_ID) { // 这个事件在CCCD变化时触发用来判断手机是否订阅了Notify notify_enabled (evt-data.evt_gatt_server_characteristic_status.status_flags sl_bt_gatt_server_client_configuration) ! 0; } break; case sl_bt_evt_gatt_server_notification_sent_id: // 一包通知发完了可以准备发下一包 break; } } void send_to_phone(const uint8_t *buf, uint16_t len) { if (active_connection 0xFF || !notify_enabled) { return; } sl_bt_gatt_server_send_notification(active_connection, TX_CHAR_ID, len, buf); }注意上面这个代码里start_advertising在connection_closed里又调用了一次。原因是BG22在连接关闭后不会自动重新广播这是协议栈的默认行为。如果你的设备生产后要反复连接断开这里必须显式重启广播。我记得第一次调的时候手机断开连接后设备就不广播了我当时没看事件日志以为设备死机了排查半天才发现是这个原因。另外一个值得改进的地方上面的串口往手机发数据是一个字节一个字节调用send_to_phone的这个效率很低而且如果数据量一大容易把协议栈的通知缓冲区打满。更合理的做法是先把整包数据攒在Buffer里等收到一个结束标志比如换行符、特定帧尾再一次性调用send_to_phone发送完整包。这样既降低协议栈压力也方便手机端做分包解析。5. 常见问题与排查技巧实录5.1 手机搜不到设备优先级最高的排查方向设备有没有真正进入广播状态。检查日志里是否有sl_bt_evt_connection_opened之类的连接相关打印。更简单的操作是用nRF Connect之类的工具抓包看能不能扫到设备。如果连nRF Connect都扫不到说明设备端广播没开或者广播参数有问题。广播参数是否配置成不可发现。检查sl_bt_legacy_advertiser_start传入的发现模式参数如果用了sl_bt_advertiser_non_discoverable手机当然扫不到。电源问题。BG22的最低工作电压需要满足要求如果电池电压掉到1.8V以下射频部分可能无法正常工作。不良的LDO或DC-DC配置也会导致发射功率异常。5.2 能连接但收不到数据这个问题分两个方向设备收不到手机数据检查GATT配置器的Write属性是否勾选。有人会不小心只勾了Read那手机写完设备端事件不会触发。另一个可能是attribute ID判断错误你写代码时把ID号写错了导致数据被事件收到但switch里没进到正确的分支。手机收不到设备数据首先看手机是否已经订阅Notification。如果你用nRF Connect调试点开特征值旁边的“Notify”按钮才算订阅。设备端可以打印CCCD更新事件来确认。其次看MTU大小如果MTU是默认23字节而你发送的数据超过20字节协议栈会把数据丢弃或者返回错误。我排查这种问题时最常用到的工具就是Wireshark配合BLE抓包器。如果你手上有nRF52840 DK或者官方Blue Gecko的抓包固件把抓包器放到设备旁边能看到完整的GATT交互流程事件帧、ATT请求、LL连接的通信过程一目了然。5.3 烧录调试时出现“Cannot connect to J-Link”这个问题出现的频率非常高。先检查设备管理器里的驱动是否正常如果有感叹号就更新驱动。其次如果你用的是自定义PCB而不是官方开发板要确认SWDIO和SWCLK有没有接错。然后检查复位引脚是否被拉低或者被外部电容拉得异常。BG22的复位引脚是RESETN如果被强拉低或者悬空受干扰J-Link连不上也不要奇怪。还有就是如果芯片进入了EM4休眠模式有些调试器和芯片之间的连接会被切断需要在复位之后迅速连接。这个在低功耗调试中很常见解决方式是按住复位键再点下载或者使用J-Link的“connect under reset”模式。5.4 透传丢包问题丢包的本质是发送速度超过了BLE链路或接收端的处理能力。BLE实际上的有效吞吐量受物理层速率、连接间隔、单个包大小共同影响。比如你的连接间隔是30ms每个连接事件能传6个包每个包最多251字节数据在DLE和MTU都很大的情况下理论上最大吞吐率能达到2Mbps左右。但实际场景中连接间隔、从机延迟、对端手机的处理能力都会限制实际速度。手机端很多BLE App处理速度并不快如果你设备端从串口收到的数据量太大一股脑往notification里塞协议栈发送缓冲区瞬间就满了然后就丢包。解决丢包的方法有几个方向加大缓冲区在应用层做缓存按连接事件周期性发送而不是有数据就发。根据notification_sent事件做流控发完一包再发下一包形成一个简单的发送队列。在协议层设计重传机制比如给每个包加序号接收方收到后回ACK。但BLE本身有链路层重传如果是偶尔丢包大概率是缓冲溢出先做流控再看是否还需要应用层重传。5.5 为什么串口打印乱码Simplicity Studio的串口终端默认波特率是115200但有些板子的默认日志端口波特率可能是其他值。先看你的初始化代码里UART配置是多少。另外BG22的调试日志输出接口和你的业务串口如果复用了同一个UART会造成数据混流。我一般会把调试日志单独放到一个IO口上或者直接用SWO输出业务串口完全留给数据通信。硬件层面还有一个常见坑板子的串口TXRX有没有接反。很多初学者把MCU的TX接到了调试器的TX上数据完全对不上。串口通信是交叉连接的MCU的TX接对端RXMCU的RX接对端TX这个基础操作我甚至见过老手在赶工期时也栽了跟头。6. 一些关于量产和性能优化的额外建议如果你只是做个Demo玩玩到这一步已经完成了。但如果目标是量产有几个点我要额外提醒。第一频偏校准。BLE对射频的频率精度要求比较严BG22的时钟源可以选HFXO或者内部振荡器。如果使用内部振荡器频偏可能偏得比较多导致连接稳定性下降、有效距离缩短。量产阶段建议使用外部晶振并且要做频率校准。Silicon Labs提供了一个RF调试工具可以读到当前频偏值配合板子上的匹配网络作微调。第二天线匹配问题。这是很多自行设计PCB的团队最容易忽略的。BG22的射频输出是差分形式的需要经过匹配网络转成单端50欧姆再接天线。匹配网络里的电感电容取值不是随便抄的不同layout、不同板厚、不同叠层都会影响匹配结果。建议第一版打样就留出π型匹配电路的位置方便调试时调整。有条件的话送去做无源S11测试驻波比调到1.5以下再考虑量产。第三电池寿命估算。BG22在部署后的实际平均电流取决于你广播间隔、连接间隔、数据处理时间、休眠时间这几个参数的组合。不要只看数据手册上的峰值电流。一个比较实用的估算方法估算一个周期内工作状态TX/RX/CPU活跃的时间占比然后乘以对应的电流值再加上休眠电流乘以休眠占比得出平均电流最后除以电池容量得到理论续航。这个方法在数据手册上可能没有但项目管理中非常有用。第四量产固件的生产测试流程。至少要有这么几步上电自检、频偏测试、发射功率测试、接收灵敏度抽检、固件版本校验。如果测出不良品要有能力单独进入测试模式重新校准不在这一块省钱。7. 写在最后的实战体会从安装Simplicity Studio到写出第一个能用的透传服务这条路我走过不止一遍每次换电脑、换SDK版本、换芯片型号都会遇到新问题。但核心的思路是不变的先让环境转起来再理解事件驱动的机制然后用一个最简单的服务跑通全链路最后再添油加醋加入自己的业务逻辑。我自己在实际项目中最大的体会是不要一上来就追求完美。先做个最简单的回环测试——手机发数据给设备设备收到后原样发回手机俗称echo服务。这个链路一旦通了后面加任何业务功能都只是改数据解析逻辑而已。如果连echo都调不通就先不要碰协议栈业务回去查环境和GATT配置。另外分享一个测试小工具组合nRF Connect做日常扫描、连接、读写测试LightBlue也可以备一份用于对比Wireshark加抓包器用来查深层协议问题串口助手看设备的调试日志。这三个工具组合起来基本能覆盖从应用层到链路层的所有排查需求。EFR32BG22这颗芯片整体而言开发体验还是不错的尤其是它的低功耗表现在同类产品里非常有竞争力。只要跨过环境配置这道坎后面的事情会顺利很多。希望这篇避坑指南能帮你少走点弯路。
返回列表