1. 项目全貌:为什么又是nRF52840?
做低功耗物联网设备的人,选型绕不开这颗芯片。nRF52840是Nordic在高性能低功耗蓝牙路线上的一个标志性节点,它不只是“比nRF52832多了个Cortex-M4F”这么简单,而是把射频性能、处理能力、外设丰富度和低功耗特性拉到了一个比较均衡的位置。这篇开发指南不打算照抄数据手册,而是想从硬件架构、软件栈、实际调试三个层面,把从零到一跑通一个nRF52840物联网项目的完整路径说清楚。
适合看这篇内容的人,我理解有三类:一是准备用nRF52840做产品的嵌入式工程师,二是做物联网毕设或竞赛的学生,三是从ESP32等生态转过来的开发者。尤其第三类朋友要注意,ESP32和nRF52840的玩法差异很大,前者偏向“All-in-One+Wi-Fi”,后者偏向“极致低功耗+BLE/Thread/Matter”,代码组织方式和功耗评估思路都需要切换。
1.1 核心需求解析:低功耗蓝牙项目的典型诉求
低功耗蓝牙项目看起来简单,无非是“连接、发数据、睡觉”,但实际落地时往往要同时满足几个硬指标:
- 峰值电流不能大,尤其是纽扣电池场景,瞬间拉电流过大会把电池电压拖垮;
- 平均功耗要低,这取决于睡眠占比、广播间隔、连接间隔和数据处理策略;
- 射频链路要稳定,室内多径、2.4G干扰、天线匹配都会影响连接质量;
- 开发效率要可控,毕竟从原型到量产的时间窗口很短。
nRF52840在这些维度上的表现比较均衡。它的广播、扫描、连接、GATT、ATT、L2CAP等BLE协议栈功能全部由Nordic官方SoftDevice或新架构的Zephyr协议栈实现,应用层只需要关注业务逻辑。这对于物联网场景尤其重要,因为你在写代码时不需要关心链路层怎么重传、加密怎么协商,只需要把数据塞给协议栈接口即可。
1.2 适用场景与选型理由:不是所有设备都适合它
很多人一上来就问“nRF52840和ESP32哪个强”,这个问题本身就有问题。它们的目标场景不同:
- 需要Wi-Fi、音视频、屏幕、跑复杂算法时,选ESP32-S3,成本低、生态大、性能强;
- 需要纽扣电池供电、长续航、稳定BLE连接、多协议支持时,nRF52840更有优势;
- 需要Mesh组网或Matter协议时,nRF52840原生支持Thread、Zigbee、BLE,选型空间更大;
- 需要超低功耗传感器节点时,nRF52840的RX电流在BLE模式下大约5.4mA左右,TX电流与发射功率有关,但配合休眠策略,平均功耗可以做到微安级别。
我之前做过一个环境监测节点,用ESP32做原型很顺利,但换成电池供电后就尴尬了,Wi-Fi功耗太高,睡眠唤醒又慢。换成nRF52840后,用BLE广播上传温湿度数据,两节AA电池撑了半年多。可以说,选nRF52840的场景,核心关键词就是“低功耗”和“无线连接”,而不是“跑复杂应用”。
1.3 项目目标:你将从这篇指南得到什么
这篇指南会带着你走完一条完整的项目路径:
- 理解nRF52840的硬件架构,包括内核、电源管理、射频收发器和常用外设;
- 搭建开发环境,用官方SDK和nRF Connect配置工程;
- 实现BLE广播、连接、GATT服务和数据传输;
- 接入物联网云平台或本地上位机,完成端到端数据链路;
- 掌握BLE抓包、功耗测量和常见问题排查的方法。
这些都是我在实际项目中反复用到的能力,不是“能跑就行”的演示级别,而是“能扛住真机测试”的工程级别。接下来先从硬件架构讲起。
2. 硬件架构拆解:这颗芯片到底强在哪?
2.1 Cortex-M4F内核和内存布局的决定性作用
nRF52840搭载一颗64MHz的ARM Cortex-M4F内核,带FPU和DSP指令,RAM有256KB,Flash有1MB。这个配置放在前几年是相当奢侈的。对比同门的nRF52832只有64KB RAM和512KB Flash,跑复杂的应用逻辑时经常捉襟见肘。而52840的256KB RAM意味着你可以跑Zephyr RTOS,可以加载较复杂的协议栈,可以缓存传感器数据做离线处理。
内核频率64MHz看着不高,但对于BLE节点来说完全够用。BLE协议栈是事件驱动的,大部分时间都在等待射频事件、定时器事件或GPIO事件,CPU忙的时间其实非常少。真正吃算力的是加密运算,比如AES-128、CCM、ECDH等,而nRF52840内置了ARM CryptoCell-312加密加速单元,这些运算基本不占用主核太多时间。
内存布局上有一点要特别注意:如果使用传统的SoftDevice方案,协议栈会占据Flash的开头部分,且地址固定,比如SoftDevice S140占用Flash从0x00000开始的约152KB区域,RAM也要预留一部分给协议栈。因此你的应用程序Flash起始地址不是0x00000,而是0x26000附近。如果你从其他单片机转过来,容易在这里踩坑,写Flash时一个不小心就会覆盖协议栈区域。
2.2 2.4GHz射频前端的硬实力:链路预算与现实意义
nRF52840在BLE模式下的发射功率范围是-20dBm到+8dBm,可以按4dB步进配置。接收灵敏度在BLE 1Mbps模式下典型值为-96dBm,在125kbps的编码模式(Coded PHY)下可以达到-103dBm左右。
这组数据意味着什么?用一个简单的链路预算来算:假定发射功率0dBm,接收灵敏度-96dBm,路径损耗预算就是96dB。在理想开阔环境下,2.4GHz自由空间路径损耗大约是40 + 20log10(d) dB(d以米为单位),可以算出理论通信距离超过100米。实际环境中墙体、金属物、人体遮挡带来的损耗远大于理论值,但相比很多国产BLE芯片,nRF52840的射频余量确实更好。
如果你做的是室外传感器、资产追踪这类设备,建议把发射功率设置为+4dBm或+8dBm,同时选择带外部PA/LNA的参考设计。另外,PCB天线的匹配网络一定要按Nordic参考设计来画,一字之差可能损失10dB以上的辐射性能。
2.3 丰富外设与GPIO复用:真正常被忽略的细节
nRF52840的GPIO数量是48个,可配置为多种复用功能。它支持的外设包括:
- SPI/SPIM、TWI/I2C、UART,均为多实例,且支持EasyDMA,外设可自动搬运数据,不需要CPU介入;
- 12位ADC(SAR型)、比较器、PWM、正交解码器(QDEC);
- USB 2.0全速设备控制器,这也是相对nRF52832的一个明显升级;
- 安全相关的AES、真随机数发生器TRNG、CRC等。
GPIO复用是实际开发时最头疼的问题。因为引脚功能不是固定的,你可以通过PSEL寄存器任意映射SPI的SCK/MISO/MOSI到任意GPIO,但因为同时还有EasyDMA、外设冲突等限制,不是所有引脚都能承担全部功能。我在布局时通常会把I2C、UART、SPI这些较高速的外设固定在推荐引脚上,剩下引脚留给GPIO按键和LED。
外设还有一个重要特性:PWM实例可以产生多路独立占空比输出,非常适合做LED渐变、蜂鸣器音调控制。而QDEC可以直接接机械旋转编码器,不需要额外加消抖电路。配合PPI(可编程外设互联)系统,你甚至可以让外设之间直接联动而不经过CPU,这对低功耗设计很有价值。
2.4 电源管理架构:从内部稳压器到低功耗策略
nRF52840内部有多个LDO和DC/DC稳压器。最重要的是VDDH引脚:它可以直接连接电池电压(最高5.5V),内部通过DC/DC降压后为系统供电。相比单纯用LDO,DC/DC模式在高电压输入时效率提升非常明显。比如3.6V输入、1.8V核心电压时,LDO效率只有50%左右,而DC/DC可以做到80%~90%。
代码里配置DC/DC的步骤很简单:在协议栈初始化后,调用sd_power_dcdc_mode_set(NRF_POWER_DCDC_ENABLE)即可。如果你不用SoftDevice,则需要直接操作POWER寄存器。很多新手会忽略这一步,导致整体功耗比数据手册标称值高出一大截。
低功耗策略上,nRF52840有System ON和System OFF两种睡眠模式:
- System ON:CPU暂停,但RAM保持,定时器、GPIO唤醒源等可用,电流约1.5μA左右;
- System OFF:几乎全部断电,只有GPIO检测和某些复位源能唤醒,电流可以低至0.3μA级别。
实际物联网节点中,90%以上的时间应该处于System ON加RTC唤醒的状态,这样既能保证事件响应,又能把平均功耗压到极低。
3. 开发环境搭建与工程实践:从点灯到跑通BLE
3.1 工具链选型:官方SDK还是Zephyr RTOS?
nRF52840的官方开发套件是nRF5 SDK。SDK的优点是文档齐全、示例丰富、上手快,但缺点是工程组织比较老派,函数名长,依赖关系复杂。新项目也可以考虑Zephyr RTOS,Nordic现在是Zephyr项目的主要贡献者,nRF52840是Zephyr的Tier 1平台。Zephyr的好处是代码复用率高、驱动抽象统一、支持DeviceTree配置硬件,但学习曲线也更陡。
我的建议是:如果你是做产品原型验证、项目时间紧,优先用nRF5 SDK加SoftDevice S140;如果你想做长期维护、多硬件平台复用代码,可以考虑Zephyr。我自己早期学nRF52840时是从nRF5 SDK入门的,先跑通示例,再逐步理解协议栈机制,后期切换到Zephyr就轻松很多。
另外,官方还提供了nRF Connect for Desktop工具包,里面有Programmer、Power Profiler、RTT Viewer等模块。在做功耗测试和Flash烧录时,这几个工具的配合效率比命令行高不少。
3.2 SDK工程结构:不要被一堆文件夹吓到
nRF5 SDK的目录看起来庞大,但核心目录其实只有几个:
components:底层驱动、协议栈头文件、硬件抽象层;examples:大量官方示例,在此基础上改代码比从零写快得多;integration:第三方IDE或RTOS的集成文件;modules:新版本SDK中的模块化组件。
我建议你复制examples/ble_peripheral下的一个完整示例作为起点,而不是手动创建工程。BLE应用需要同时链接应用代码、SoftDevice协议栈、芯片启动文件和链接脚本,手动配工程很容易漏掉某个关键文件。
比如,想做一个自定义BLE服务,可以参考ble_app_template示例。这个示例已经实现了完整的SoftDevice初始化、GAP初始化、广播配置和连接事件处理,你要做的就是添加Service、Characteristic以及对应的回调函数。
3.3 编译烧录与调试:SES、VS Code和J-Link的搭配
官方推荐Segger Embedded Studio(SES)作为IDE。SES对Nordic工程的配置很完善,下载调试、功耗测量、RTT打印都能直接支持。如果不想用SES,也可以用VS Code加ARM GCC工具链,配合CMake或Makefile管理工程,然后用pyOCD或J-Link命令行烧录。
实际调试中,RTT(Real Time Transfer)是最高效的日志输出方式。它通过调试接口与目标芯片通信,不占用UART引脚,也不影响睡眠电流,非常适合低功耗调试。一个典型的使用流程是:在代码中包含SEGGER_RTT_printf,然后在nRF Connect的RTT Viewer里观察输出。相比串口打印,RTT速度快、不会阻塞CPU,尤其适合在中断上下文打日志。
烧录时要注意SoftDevice和App是分开烧录的,顺序是先烧SoftDevice,再烧Application。如果顺序反了,或者用全擦除工具把SoftDevice删了,再启动App时芯片会一直复位,这是新手最常见的启动失败原因。
3.4 引脚规划与最小系统设计:量产前必须想清楚的事
IO规划是硬件设计中最容易被低估的环节。建议在原理图阶段就做好一张引脚分配表,明确每个引脚的功能、默认电平、是否复用。尤其要注意:
- 不能将外部晶振引脚(XL1、XL2)复用作普通IO;
- NFC引脚(P0.09、P0.10)默认作为NFC天线引脚,如果不用NFC,可以配置为GPIO,但需要修改UICR寄存器中的NFCPINS配置;
- 有些引脚在芯片上电时有特殊状态,比如某些引脚内部上拉或下拉,设计按键或LED时要评估是否会产生漏电流。
最小系统方面,除了必须的电源退耦、外部32.768kHz晶振和天线匹配网络外,建议预留SWD调试接口。在原型阶段,至少引出SWDIO、SWCLK、GND和VDD,方便后续调试和功耗测量。很多PCB尺寸紧张的项目会把调试接口砍掉,结果出了问题只能飞线,反而更浪费时间。
4. 低功耗蓝牙应用层开发:广播、连接、GATT与功耗调优
4.1 广播与扫描:低功耗数据通道的设计思路
BLE的广播是物联网节点最常用的数据传输方式之一。广播包无需连接就能被主机扫描到,非常适合传感器上报、信标定位等场景。
广播有两种模式:
- 传统广播(ADV_IND):设备周期性地发送可连接广播事件,等待主机扫描或连接;
- 可扫描广播(ADV_SCAN_IND):设备发送可扫描广播事件,主机可以发起扫描请求获取附加数据。
在nRF5 SDK中,广播配置的核心是gap_params_init和advertising_init函数。你需要设置广播数据、扫描响应数据、广播间隔等参数。广播间隔的选择对功耗影响很大:间隔越短,发现越快,但平均电流越高。
举个例子:广播间隔100ms时,单次广播事件约2ms左右,平均电流大约在几十微安级别。如果把间隔降到20ms,平均电流可能会翻倍。对需要快速配网或按键触发广播的设备,可以在事件发生时用短间隔广播,之后自动切换回长间隔,这种“事件触发广播”策略是我在做产品时最常用的。
4.2 GATT服务设计:看似简单,实则处处有坑
GATT(通用属性协议)是BLE应用层的核心。一个服务由若干个Characteristic组成,每个Characteristic有UUID、属性、值以及可选的描述符。写一个自定义服务不难,但设计得合理与否,直接影响兼容性和功耗。
设计GATT服务时需要注意以下几点:
- UUID尽量使用16位蓝牙标准UUID,只有自定义服务才用128位UUID,否则在iOS和Android端的兼容性会有差异;
- Characteristic的属性(读、写、通知、指示)要按需开放,不要滥用通知,避免频繁唤醒主机和从机;
- 对于传感器数据上报,优先使用“通知(Notify)”而不是“读(Read)”,因为通知可以由从机主动推送,省去主机轮询;
- 多个小数据建议合并成一个Characteristic一次发送,减少空中包数量。
以温湿度计为例,可以把温度、湿度、电池电量放在同一个Service里,分别建Temperature、Humidity、Battery Level三个Characteristic。温度精度用int16,单位0.01摄氏度;湿度用uint16,单位0.01%。这个约定要在设计文档里写清楚,否则对接上位机时极容易发生单位错乱。
4.3 连接参数与功耗公式:用数学算清楚你的设备能撑多久
设备连接后的功耗主要由连接间隔(Connection Interval)决定。连接间隔可以设置为7.5ms到4s的偶数倍,比如7.5、10、20、50、100ms等。在每次连接事件中,从机接收主机的数据或发送通知,其余时间可以睡得越深越好。
一次连接事件的平均电流(不考虑数据传输时)大约可以按以下过程估算:唤醒、RX接收约2ms,电流5.4mA;处理后CPU忙约1ms,电流约4mA;再进入睡眠。如果连接间隔为50ms,那么平均电流约等于(2ms × 5.4mA + 1ms × 4mA) / 50ms ≈ 0.3mA,加上RAM保持电流约1.5μA,总体仍处于很低水平。如果主机有大量的通知数据下发,电流会明显升高。
另一个影响功耗的关键参数是从机延迟(Slave Latency)。它允许从机在指定次数内跳过连接事件而不听主机广播,比如Slave Latency设为4,意味着最多可以跳过4个连接间隔不监听,这样从机可以睡更久。设计时可以根据业务容忍的最大延迟来设置这个值,既能保连接,又能省电。
4.4 蓝牙Mesh与多协议支持:什么时候用Mesh?
如果你的设备数量很多,比如智能照明、传感器阵列,点对点BLE连接管理起来非常费劲。nRF52840支持BLE Mesh(基于Flooding)和Thread两种组网方式。BLE Mesh适合低速率、数量多、不要求低延迟的场合;Thread则是基于IPv6的路由协议,适合承载更多数据量、更复杂的网络。
从实际落地看,BLE Mesh的开发门槛比点对点BLE高不少,需要理解节点、元素、模型、发布订阅等概念。如果你刚接触nRF52840,我建议先跑通点对点BLE,再评估是否上Mesh。另外,Mesh网络中每个节点都要维持中继转发,功耗会比普通BLE节点高一个量级,设计时要有心理准备。
5. 物联网端到端实战:从传感器数据到云端/上位机
5.1 典型系统架构:BLE节点 + 网关 + 云端
物联网应用最常见的架构是“传感器节点通过BLE上报,手机或专用网关透传,再上传云端”,这种设计的好处是节点侧只负责采集和广播/通知,复杂的数据处理和网络协议放在网关或手机上,可以实现节点的高续航和小体积。
我做过的一个设备巡检项目就是这样:每个设备挂一个nRF52840节点,定时采集电流、振动、温度数据。BLE把数据发给挂在现场的一个安卓平板(充当网关),平板通过Wi-Fi/4G上传到云端服务器。这样节点端功耗极低,电池可以用一年以上,而平板负责处理数据压缩、补传等复杂逻辑。
如果你不想自建网关,可以考虑涂鸦智能这类模组解决方案,直接用涂鸦的蓝牙模组接入其IoT平台,App端和设备端SDK都有现成的,能大幅减少开发量。不过要注意,这类方案的可定制性不如自己写协议灵活,数据格式、OTA策略都受平台约束。
5.2 BLE与手机端交互:Android、iOS和Flutter的兼容性
手机端和BLE设备交互,最常见的问题在iOS和Android的差异上。Android的BLE接口基于BluetoothGatt,API比较底层,但自由度大;iOS基于CoreBluetooth,系统权限和状态机管理相对严格,部分接口行为也和Android不同。
值得专门提醒的是Flutter跨平台方案。Flutter官方有flutter_blue_plus等社区插件,但在iOS上踩坑的概率不低。最常见的问题是:iOS需要正确设置后台模式(UIBackgroundModes包含bluetooth-central或bluetooth-peripheral)、必须请求蓝牙权限、以及在系统蓝牙关闭时插件状态回调不稳定。有一个道友用Flutter做iOS端,调试了整整一周才发现是Info.plist忘了加蓝牙描述,导致首次请求权限直接崩溃。
因此我的建议是:如果只是做原型验证,用Android手机+nRF ConnectApp就够了;如果做正式产品,客户端用原生方案更稳,或者用Flutter时提前把所有平台权限清单测试一遍。
5.3 上位机开发思路:串口/蓝牙/Wi-Fi之间的选择
物联网项目经常需要一个PC上位机来查看数据或控制设备。C#是工控和制造业场景里非常常见的上位机语言,配合Windows.Forms或WPF能快速画出仪表盘。如果设备直接用USB连接(nRF52840支持USB),C#可以通过串口或HID接口与设备通信;如果是BLE设备,可以加一个USB-dongle作为BLE网关,再用C#调用Windows的WinRT Bluetooth API。
在选用C#做上位机时,先确定数据帧格式。常见做法是定义一帧数据为帧头、长度、命令字、数据域、校验五位结构,比如AA 55 0B 01 ... CRC16。这个协议在MCU端和上位机端要保持一致,最好在项目初期就用文档固定下来,否则后期联调时改协议的成本很高。
5.4 云平台接入:MQTT并不是唯一的选择
节点通过网关把数据传上来后,云平台的选择有很多。国内常见的IoT平台包括阿里云IoT、腾讯云IoT、涂鸦智能、OneNET等。如果你只是自用或做毕设,最省事的方式是直接用MQTT协议连接公共Broker(比如EMQX、Mosquitto),在服务器上写一个简单的数据接收脚本即可。
MQTT协议能胜任大部分数据上报和控制下发场景,但也要知道它的局限。在弱网环境下,MQTT的长连接会频繁断线重连;如果数据量很大,MQTT的Topic和Payload设计不合理会让Broker压力剧增。一个更先进的做法是使用CoAP(受限应用协议),它基于UDP,更适合低功耗设备与网关之间的通信。不过在BLE节点本地,你通常只需要把数据交给网关,上云的那一段用MQTT就够了,中间加一个协议转换层,系统会更有弹性。
6. 协议抓包与功耗实测:像调试单片机一样调试无线
6.1 nRF52840 BLE抓包实战:软件、硬件和方法
无线调试最大的痛点是“看不见链路层在干什么”。幸运的是,nRF52840的调试手段比很多国产芯片丰富得多。最简单的方式是使用nRF Connect for Desktop中的Sniffer功能:你需要一块nRF52840 Dongle或开发板,烧录Sniffer固件,然后在PC上用Wireshark实时抓取BLE广播包和连接包。
抓包的典型场景是排查“设备明明广播了,手机为什么扫不到”这一类问题。在Wireshark里你可以看到广播信道(37/38/39)的发送情况、广播包的内容、扫描请求和扫描响应是否正常。通过分析这些信息,可以定位是广播功率太低、广播数据格式错误,还是信道拥挤被其他设备干扰。
我遇到过的一个真实案例是:设备在实验室广播正常,到了客户现场就扫不到。抓包发现设备在37、38、39三个广播信道中的38信道持续遇到高强度干扰,导致手机没有及时收到广播。后来修改了广播信道映射并提高了广播功率,问题解决。这个很难靠“看代码”定位,抓包是唯一高效的手段。
6.2 功耗测量:用DK板自带电流计,还是外接精密电阻?
nRF52840 DK开发板自带一个板载电流测量电路,配合Power Profiler Kit(PPK)可以实时画出电流曲线。这是调低功耗的利器。你可以在代码里设置不同场景(广播、连接、睡眠、外设读取),然后观察电流曲线是否符合设计预期。
如果没有PPK,也可以在电源输入串联一个10Ω采样电阻,用示波器测电阻两端的压降来估算电流。注意,数字示波器测量微小电流时噪声较大,建议用差分探头或高精度万用表配合。另一个更准的方式是使用Joulescope这类专业功耗分析仪,它不仅能显示电流曲线,还能统计平均功耗和总能量消耗。
测量时有一个容易忽略的细节:调试器的RTT、串口打印、甚至调试探针本身都会额外消耗电流。因此在做最终功耗评估时,一定要断开调试器、用电池供电、关闭所有调试打印,这样才能测到设备真实运行功耗。
6.3 功耗实测的常见误区:数据手册值为什么对不上?
有次我在调一个门磁传感器,数据手册上说System ON电流1.5μA,但实测却有20μA。排查了很久,发现罪魁祸首是GPIO浮空输入导致的漏电流。外部没有接上下拉电阻的几个引脚在睡眠时处于不定状态,引起了额外的电流消耗。
这类问题太常见了,排查顺序一般是这样:
- 检查所有GPIO在睡眠前是否被配置为确定电平,必要时开启内部上下拉;
- 检查外部传感器、Flash芯片等是否处于低功耗模式,很多外部芯片默认就是全速运行;
- 检查DC/DC模式是否启用,没启用时电流会明显偏高;
- 检查SoftDevice是否启用了RTC等外设,如果RTC不必要地频繁唤醒,功耗也会上去;
- 检查按键检测电路,很多设计中按键外部下拉电阻本身就一直在耗电。
只要按这个顺序排查,绝大多数“实测功耗比手册高”的问题都能找到原因。
7. 常见问题与避坑实录:锁定、内存、选型
7.1 芯片锁定(Protect)问题:不小心就变砖?
“nrf52840 永久锁定”是开发圈里经常出现的话题。其实这不是真正的永久损坏,而是芯片的Access Port(调试口保护)被意外使能,导致调试器无法再连接,无法读取或擦除Flash。
常见的触发场景是:在UICR寄存器中误设置了APPROTECT,或者在代码里调用了相关保护接口,然后意外复位。还有一类情况是CRC校验失败后,SoftDevice的看门狗不断复位,主机端因连接频繁断开被反复复位而不稳定,但严格来说那不是“锁死”,而是程序跑飞或协议栈崩溃。
如果遇到真的无法连接,解决方法是通过连接到RESET引脚的方式强制暂停内核复位,再使用nRF Connect的“Recover”功能擦除全部Flash。如果仍然连接不上,可以检查是否处于System OFF模式下,需要拉低一个唤醒引脚或者重新上电。真正“永久”锁死的案例非常少,大部分都能通过硬件复位和恢复操作救回来。
7.2 Flash与RAM布局问题:跑飞、进HardFault,先查这两个地方
nRF52840的开发中,最常见的崩溃原因就是内存越界和Flash写入越界。
SoftDevice S140的起始地址是0x00000,大约占用152KB的Flash;应用程序从0x26000开始,而RAM地址分成两部分:从0x20000000开始给应用,另外还有一部分高地址RAM是给SoftDevice的。如果你在链接脚本中设置错了RAM起始地址,或者在代码中定义了大数组、栈溢出,都可能直接覆盖到协议栈的数据区,导致出现非常奇怪的随机性崩溃。
排查方法:先用崩溃日志找到PC指针,再看是访问了无效地址还是触发了HardFault。nRF5 SDK中有HardFault handler示例,可以把异常现场打印出来。不要一上来就怀疑协议栈,大多数HardFault都源自自己的指针越界。
7.3 天线匹配与PCB布局:为什么同一套代码,不同板子效果差很多?
射频性能不仅取决于芯片,更取决于天线的匹配和PCB布局。nRF52840参考设计推荐使用特定尺寸的PCB天线匹配网络,一般为2个电容和1个电感组成的π型网络。如果你改动了PCB厚度或天线形状,匹配网络需要重新调试。
我见过一个做智能手环的案子,样品在实验室通信距离很好,小批量后距离缩短了一半。一查原因,是生产时换了一款价格更低的PCB板材,介电常数变化导致天线失谐。这类问题在原型阶段完全测不出来,但一到量产就暴露了。如果对射频设计不够自信,建议优先选用Nordic官方的参考设计,不要自己“优化”。
另外,在PCB布局上,RF引脚附近要尽量避免铺地和走线,天线净空区周围不要放金属件。电池、喇叭、马达这类金属物体对天线的影响很大,必要时可以在天线区域加屏蔽罩来减少干扰。
7.4 选型对比:比nRF52840更好的芯片有哪些?
有人总问“有没有比nRF52840更好的BLE芯片”,这要看你怎么定义“更好”。如果你追求更低功耗和更小体积,Nordic自家的nRF52833、nRF52810都比52840低端,但也更便宜;如果你追求更强的处理和更大的Flash,nRF5340是双核芯片,性能更强,但功耗和开发复杂度也上去了。
需要指出的是,“更好”是一个相对概念。nRF52840在低成本、低功耗、协议丰富度之间找到了一个很好的平衡点。对于绝大多数物联网传感器、穿戴设备、医疗健康设备来说,它依然是首选之一。如果你有更高性能需求,可以考虑nRF5340或者加一颗Wi-Fi协处理器;如果只需要纯BLE发送,国产的PHY6222、泰凌微TLSR8258等芯片则可能在成本上更有竞争力。
选型的最终标准不是参数堆叠,而是你产品的电池容量、通信距离、成本目标和开发周期。这几点决定下来的答案,往往就是最优解。
8. 一些题外话和我的体会
回到开头那句话:nRF52840并不是一颗完美芯片,但它是我用过的BLE芯片里综合体验最省心的一颗。做物联网项目,真正考验人的不是“代码能不能跑”,而是功耗能不能压下去、无线能不能稳定、问题能不能快速定位。这三件事在nRF52840上都有成熟的工具链和资料支撑,这也是它一直能在开发圈保持热度的原因。
我个人的一个小习惯是:每个项目开始之前,先花半天时间把功耗预算和通信距离算清楚,再动手画板。很多人觉得这是浪费时间,但等到板子做出来再改,成本就不只是半天了。
最后再分享一个小技巧:在你的开发板上留一个测试点,把电池供电和测量仪器的接线分开。调试时直接用外接电源,测试低功耗时才切换到电池。这个小改动在很多项目里都帮了大忙,不用每次焊线拆线,也减少了因反复插拔导致的接触不良问题。希望这篇指南对你也有用。