Nordic实战--从零到一构建nRF Connect SDK应用(图文详解)
1. 从“Hello World”到“Blinky”你的第一个nRF应用如果你已经按照官方指南在VS Code里装好了nRF Connect SDK看着那个整洁的界面心里可能既兴奋又有点发怵。兴奋的是一个强大的开发环境已经就绪发怵的是接下来该从哪里下手呢面对一个空白的工程就像面对一个空旷的仓库工具材料齐全但不知道第一锤该敲在哪里。别担心这正是每个开发者都会经历的阶段。今天我们就来一起敲下这第一锤目标不是复杂的物联网应用而是两个最经典、也最关键的起点在串口打印“Hello World”以及让板载LED闪烁起来Blinky。这两个看似简单的例子实际上会贯穿你未来所有复杂应用开发的核心流程。我刚开始接触nRF Connect SDK时也卡在这一步很久。官方文档虽然详尽但信息分散对于新手来说很难形成一个从创建到验证的完整闭环认知。我踩过的坑包括工程创建后不知道如何与SDK关联、编译选项选错导致烧录失败、串口死活没输出等等。所以我会把这些经验教训都揉进接下来的步骤里让你能避开这些“暗礁”顺利起航。我们的路径非常清晰创建应用 - 配置板型 - 理解并修改关键代码 - 编译构建 - 下载到开发板 - 通过串口验证结果。整个过程我会配上详细的截图确保你能够按图索骥一步步实现。这里有一个非常重要的概念需要先建立起来nRF Connect SDK基于Zephyr RTOS。这意味着你写的不是一个裸机程序而是一个运行在实时操作系统上的“任务”或“线程”。Zephyr提供了硬件抽象层、驱动、协议栈如BLE等一系列组件我们的应用就是这些组件的“消费者”。理解这一点能帮你更好地理解后续的工程结构和配置方式。好了铺垫完毕我们直接进入实战。2. 工程创建与工作区配置打好地基万事开头难但开个好头后面就顺了。工程创建不仅仅是点几个按钮它决定了你后续开发的便利性和代码的可维护性。很多新手在这里图省事直接打开一个示例工程就开始改结果遇到问题根本不知道从何查起。我强烈建议你从“空白应用”开始亲手搭建一遍这对理解整个框架有莫大的好处。2.1 创建空白应用首先确保你的VS Code已经打开并且侧边栏的“nRF Connect”插件视图是激活状态。在“WELCOME”视图里你会看到一个非常醒目的按钮“Create a new application”。点击它。这时会弹出一个快速选择菜单让你选择应用模板。这里我们选择“Create a blank application”。为什么选这个因为“复制示例”虽然快但会带入大量示例特有的代码和配置对于学习核心流程反而是一种干扰。空白应用就像一张白纸所有东西都需要你自己添加这能让你最清晰地看到每个文件、每行配置的作用。接下来你需要选择这个应用基于哪个版本的nRF Connect SDK。如果你只安装了一个版本直接选择即可。如果安装了多个务必选择你打算长期使用或与团队一致的那个版本。然后系统会要求你输入应用的名字和存放位置。名字我建议用有意义的英文比如my_first_blinky。位置最好不要放在系统盘或过于深的路径下避免后续命令行操作出现权限或路径问题。一个简单的做法是在用户目录下创建一个nrf_projects文件夹专门存放所有工程。点击“Create”后VS Code会开始生成工程文件。这个过程很快完成后会弹出一个提示问你是否要打开这个新应用。一定要点击“Open”。这时你的资源管理器里应该能看到一个以你应用名命名的文件夹里面包含了一些基础文件比如src目录、CMakeLists.txt和prj.conf。2.2 配置工作区Workspace连接工程与SDK创建完独立工程后一个至关重要但极易被忽略的步骤来了配置工作区。如果你不这么做虽然也能编译但在VS Code中阅读代码时会遇到大麻烦——比如你想查看某个Zephyr API函数的定义按Ctrl鼠标左键跳转时VS Code会提示找不到定义或者跳转到一些缓存的不完整信息中根本无法进行高效的代码导航和阅读。这是因为你的工程目录和庞大的nRF Connect SDKZephyr目录是分离的。我们需要把它们“关联”到同一个VS Code工作区里。操作很简单点击VS Code顶部的菜单栏File-Add Folder to Workspace...。在弹出的文件选择器中找到你安装nRF Connect SDK的根目录。通常路径像C:\ncs\v2.6.0或/home/yourname/ncs/v2.6.0。选中这个SDK根目录点击“Add”。此时VS Code左侧的资源管理器会显示两个根目录你的应用目录和SDK目录。这就对了最后记得保存这个工作区配置点击File-Save Workspace As...给它起个名字比如my_blinky_workspace.code-workspace。以后开发时直接打开这个.code-workspace文件就能同时加载工程和SDK享受完整的代码智能提示和跳转功能了。这是一个能极大提升开发效率的习惯务必养成。2.3 初始化Git可选但推荐如果你打算使用Git进行版本管理强烈推荐现在是初始化仓库的好时机。在工程根目录打开终端运行git init。然后必须编辑或创建.gitignore文件把编译产生的中间文件排除在外。一个基础的.gitignore内容可以如下build/ zephyr/ *.hex *.elf *.bin *.map这能保证你的Git仓库里只存放干净的源代码和配置文件避免提交数百MB的编译垃圾。3. 解剖应用骨架关键文件解读打开新创建的空白应用你会发现文件不多结构清晰。但每一个文件都有其特定的使命理解它们是你从“会用”到“懂为什么这么用”的关键一步。我们一个个来看。src/main.c这是你应用的“心脏”所有自定义的C代码逻辑都写在这里。初始状态下它可能只有一个简单的main()函数里面调用了printk打印一条日志。printk是Zephyr内核提供的打印函数输出会定向到串口控制台。这是你与开发板沟通的最基本方式。CMakeLists.txt这是构建系统的“总指挥”。它告诉CMake构建工具如何编译你的应用。最重要的两行是cmake_minimum_required(VERSION 3.20.0) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(my_first_blinky) # 这里的名字应与你的工程名一致 target_sources(app PRIVATE src/main.c)第一行指定CMake版本。第二行是灵魂它找到了Zephyr的包从而引入了整个SDK的构建框架。最后一行指明你的应用源代码文件。在后续开发中如果你添加了新的.c文件就需要在这里用target_sources添加进去。prj.conf这是应用的“配置中枢”。Zephyr采用Kconfig系统来管理成千上万的配置选项而prj.conf就是你覆盖默认配置、启用特定功能的地方。例如默认配置可能没有启用GPIO驱动或特定的串口你需要在这里打开它们。文件内容就是一系列的CONFIG_XXXy或CONFIG_XXXn。例如一个让LED闪烁和串口打印的基础配置可能包含CONFIG_PRINTKy CONFIG_CONSOLEy CONFIG_UART_CONSOLEy CONFIG_GPIOyy表示启用n表示禁用。如何知道需要配置什么通常驱动或模块的文档会说明其依赖的Kconfig选项。你也可以在编译后在build目录下使用ninja menuconfig命令来图形化地浏览和修改所有配置它会自动同步到prj.conf。boards/目录可选如果你的开发板是官方尚未支持的或者你需要自定义板级配置如LED引脚定义你可能需要在这里创建board_name.conf和board_name.overlay文件。对于大多数Nordic官方开发板如nRF52840 DK, nRF5340 DKSDK已经提供了完整的板级支持你通常不需要动这里。理解这几个文件的关系你就能把握住应用的命脉main.c写逻辑CMakeLists.txt组织代码prj.conf定制功能。接下来我们就要往main.c里注入灵魂了。4. 编写核心逻辑让代码“活”起来现在我们让这个空白应用做点实际的事情。我们将完成两个经典任务通过串口周期性地打印“Hello World”以及控制一颗LED闪烁。我会详细解释每一行关键代码的作用。4.1 串口打印“Hello World”首先确保你的prj.conf已经像上面那样配置了CONFIG_PRINTK和CONFIG_CONSOLE。然后打开src/main.c。一个典型的、周期打印的main.c如下#include zephyr/kernel.h // 包含内核API如睡眠函数k_sleep #include zephyr/sys/printk.h // 包含打印函数printk void main(void) { int count 0; printk(Hello from nRF Connect SDK!\n); // 启动时打印一次 while (1) { // 这是一个无限循环模拟应用的主线程 printk(Loop count: %d\n, count); // 打印计数 k_sleep(K_SECONDS(1)); // 让当前线程睡眠1秒。这是Zephyr中非阻塞的延迟方式。 } }我来拆解一下#include引入必要的头文件。Zephyr的所有API都通过这类头文件提供。printk相当于标准C的printf但专为内核设计。它的输出默认连接到串口0。k_sleep(K_SECONDS(1))这是关键在Zephyr中你不能使用while循环空转来实现延迟那会独占CPU。必须使用k_sleep这样的内核函数它会让出CPU控制权让其他线程或系统任务得以运行。K_SECONDS是一个宏将秒数转换为内核 ticks。4.2 实现LED闪烁Blinky让LED闪烁需要用到GPIO驱动。首先我们得知道开发板上LED连接的是哪个GPIO引脚。以最常见的nRF52840 DK开发板为例其板载LED1通常连接在GPIO0.13这个引脚上。你可以在SDK的板级定义文件如boards/arm/nrf52840dk_nrf52840/nrf52840dk_nrf52840.dts里找到这些信息。然后我们需要在prj.conf中启用GPIOCONFIG_GPIOy接着修改src/main.c#include zephyr/kernel.h #include zephyr/sys/printk.h #include zephyr/drivers/gpio.h // 引入GPIO驱动头文件 /* 定义LED设备树节点标识符。对于nRF52840 DKLED1的别名是led0 */ #define LED0_NODE DT_ALIAS(led0) /* 静态获取LED的设备指针 */ static const struct gpio_dt_spec led GPIO_DT_SPEC_GET(LED0_NODE, gpios); void main(void) { int ret; bool led_state false; printk(Blinky example started\n); // 1. 检查设备是否就绪设备树中是否有定义且驱动已初始化 if (!device_is_ready(led.port)) { printk(Error: LED device is not ready\n); return; } // 2. 配置LED引脚为输出模式并初始化为低电平熄灭 ret gpio_pin_configure_dt(led, GPIO_OUTPUT_INACTIVE); if (ret 0) { printk(Error %d: failed to configure LED pin\n, ret); return; } while (1) { // 3. 设置引脚电平实现LED状态翻转 led_state !led_state; ret gpio_pin_set_dt(led, (int)led_state); if (ret 0) { printk(Error %d: failed to set LED pin\n, ret); return; } // 4. 睡眠500毫秒 k_sleep(K_MSEC(500)); } }这段代码包含了几个重要概念设备树Device TreeZephyr使用设备树来描述硬件。DT_ALIAS(led0)和GPIO_DT_SPEC_GET是通过设备树获取硬件配置的标准方式这使得代码与具体引脚解耦移植到其他板子时通常只需修改设备树而不用改C代码。device_is_ready在操作任何外设前必须检查其驱动是否已初始化完成。这是一个好习惯。gpio_pin_configure_dt使用设备树信息来配置引脚模式输出、输入、上拉等。GPIO_OUTPUT_INACTIVE表示初始输出低电平。gpio_pin_set_dt设置引脚电平。K_MSEC毫秒级的睡眠宏。如果你的开发板不是nRF52840 DK你需要找到对应的LED别名。一个通用的方法是在SDK目录中搜索你的开发板型号的.dts文件查看led0别名指向哪个引脚。写完了代码接下来就是把它变成能在开发板上运行的程序。5. 编译构建生成可执行文件代码写好了但它现在只是文本。我们需要通过“编译”这个工序把它翻译成开发板能理解的机器码。在nRF Connect SDK中编译的核心工具是west。不过VS Code插件为我们提供了更友好的图形化界面。5.1 创建编译目标Build Configuration在VS Code的nRF Connect插件视图中找到“APPLICATIONS”栏你的工程应该已经列在那里了。点击工程右边的“Add build configuration”一个齿轮加号图标。这时会弹出一个配置向导Board Target板型目标这是最关键的一步。在下拉框中选择你的开发板型号例如nrf52840dk_nrf52840。下方的过滤器很有用Compatible boards如果你的应用是从某个示例复制的这里会列出已验证兼容的板子。Nordic SoC列出所有使用Nordic芯片的板子包括第三方。Nordic Kits仅列出Nordic官方的开发套件。All boards列出Zephyr支持的所有板子非常多。 对于我们的空白应用直接从Nordic Kits里找最方便。Configuration files配置文件这里默认会包含你的prj.conf。你还可以添加其他*.conf文件来覆盖或追加配置比如针对调试的debug.conf或针对不同硬件的board.conf。初次使用保持默认即可。Build configuration构建配置Build directory编译输出的目录默认是build。你可以保持默认也可以改成build/board_name这样的格式来区分不同板型的构建。Optimization level优化等级。Debug会关闭优化并包含调试信息方便单步调试Release会进行速度或尺寸优化。初次开发选Debug。Sysbuild这是v2.7.0之后引入的用于管理多镜像构建如同时构建应用和引导程序的系统。对于单个应用通常不需要勾选。配置完成后点击“Generate build configuration”。插件会为你生成一个对应的构建目标出现在你的工程下方。5.2 执行编译创建好构建目标后编译就很简单了。在“APPLICATIONS”栏展开你的工程选中刚才创建的构建目标比如nrf52840dk_nrf52840/debug。然后右侧“ACTIONS”栏会出现可操作的按钮点击那个大大的“Build”按钮。编译过程会在VS Code内置的终端中显示。第一次编译某个目标时时间会比较长可能需要几分钟因为CMake需要配置整个构建系统并编译Zephyr内核及所有启用的模块。后续如果只修改了应用代码编译会快很多因为构建系统只编译有变动的部分。如果编译成功你会在最后看到类似[XX/XX] Linking C executable zephyr/zephyr.elf和Build complete的提示。生成的固件文件如zephyr.hex,zephyr.bin位于你指定的构建目录如build/zephyr/下。5.3 使用命令行编译进阶虽然图形化很方便但了解命令行编译也很有必要特别是在自动化脚本或CI/CD流程中。你可以打开VS Code的终端Terminal确保当前目录是你的工程根目录然后运行west命令west build -b nrf52840dk_nrf52840 -- -DCMAKE_BUILD_TYPEDebug-b指定板型。--后面的参数会传递给CMake。-DCMAKE_BUILD_TYPEDebug设置构建类型为调试。如果你想彻底清理上次的构建结果重新编译可以加上-p(pristine) 参数west build -b nrf52840dk_nrf52840 -p编译成功后固件文件的位置与图形化编译相同。掌握了编译下一步就是让固件“住”进开发板里。6. 程序下载与调试让开发板“动”起来编译生成的.hex或.bin文件还在你的电脑上我们需要把它烧录到开发板的Flash存储器中。Nordic的开发板通常都集成了SEGGER J-Link调试器这使得下载和调试变得非常方便。6.1 连接开发板与下载程序硬件连接使用USB线将开发板的J-Link USB口通常标记为J-Link或USB连接到电脑。注意不是所有的USB口都支持编程一定要接对。连接后开发板应通电并且电脑可能会识别出新的串口和J-Link设备。识别设备在VS Code的nRF Connect插件视图中找到“CONNECTED DEVICES”栏。点击刷新按钮你应该能看到一个J-Link设备被识别出来显示其SN号或型号如J-Link OB...。执行下载确保在“APPLICATIONS”栏选中了你刚刚编译好的构建目标然后在“ACTIONS”栏点击“Program”按钮一个向下的箭头图标。插件会自动调用nrfjprog或west flash命令将固件烧录到开发板。烧录过程很快终端会显示擦除、编程、校验的进度。成功后你会看到Programming complete或类似的提示。此时程序已经驻留在开发板的Flash中开发板复位后就会开始执行。6.2 串口监控与验证程序跑起来了吗我们需要通过串口来“听”它说话。大多数Nordic开发板在通过J-Link USB连接时会虚拟出两个串口COM端口一个用于RTTSegger Real Time Transfer日志另一个用于标准的UART控制台输出。我们通常使用后者。打开串口终端在VS Code的nRF Connect插件视图的“CONNECTED DEVICES”栏找到你的J-Link设备下面通常会列出可用的串口如COM6或/dev/ttyACM0。点击旁边的“Connect”按钮一个插头图标。配置串口参数连接时通常会弹窗让你配置波特率。对于Zephyr的默认控制台波特率通常是115200数据位8停止位1无校验8N1。保持默认即可。观察输出连接成功后一个串口终端面板会在VS Code中打开。此时按一下开发板上的复位按钮RESET。你应该立刻在终端里看到打印信息“Hello from nRF Connect SDK!” 以及每秒递增的 “Loop count: x”。同时开发板上的LED1如果代码正确应该开始以1秒的周期闪烁亮500ms灭500ms。常见问题排查没有输出首先检查串口是否选对有时是两个中的另一个。检查代码中printk和CONFIG_CONSOLE是否已启用。检查开发板是否已复位。LED不闪检查prj.conf中CONFIG_GPIOy。检查代码中的LED设备树别名是否与你的开发板匹配。用万用表或逻辑分析仪测量对应引脚是否有电平变化可以排除是代码问题还是LED硬件问题。下载失败检查USB线是否连接稳定尝试给开发板重新上电。检查是否有其他软件如J-Link Commander、其他IDE占用了J-Link设备。当你在串口终端看到规律的打印并且LED按照你的指令闪烁时那种成就感是无与伦比的。这意味着你已经完整地走通了从编码、构建到部署、验证的整个闭环。这个流程将是未来你开发任何复杂nRF应用的基础模板。

相关新闻

用中文维基百科训练Word2Vec模型:从数据清洗到模型评估的全流程指南

用中文维基百科训练Word2Vec模型:从数据清洗到模型评估的全流程指南

从中文维基百科到高质量词向量:一份面向实践者的Word2Vec模型构建与调优手册 在自然语言处理的工具箱里,词向量模型就像是一把瑞士军刀,基础但不可或缺。尽管如今大语言模型风头正劲,但理解并亲手构建一个经典的Word2Vec模型&…

2026/5/17 0:50:38 阅读更多 →
【实战指南】Audition多音轨工程搭建与ASIO驱动通道映射全解析

【实战指南】Audition多音轨工程搭建与ASIO驱动通道映射全解析

1. 从零开始:你的第一个Audition多音轨工程 如果你刚接触音频制作,或者一直用Audition处理单轨录音,那么“多音轨工程”这个词听起来可能有点唬人。别担心,其实它就像你熟悉的音乐播放列表,只不过更高级。想象一下&…

2026/7/3 13:53:06 阅读更多 →
006 低功耗蓝牙BLE——音频数据无法直接免驱传输分析与折中方案

006 低功耗蓝牙BLE——音频数据无法直接免驱传输分析与折中方案

蓝牙设备的音频传输方式主要依赖于其采用的分层​​传输协议​​和​​音频编解码器​​,两者共同决定了音质、延迟、功耗等核心体验。本次产品核心需求——免驱!00 市面上的USB免驱麦克风方案分析USB麦克风的免驱特性依赖​​操作系统内置的UAC&#xf…

2026/5/17 7:00:41 阅读更多 →

最新新闻

AI Agent开发实战:从环境搭建到生产部署

AI Agent开发实战:从环境搭建到生产部署

1. AI Agent 开发概述:自动化执行利器的核心价值AI Agent(人工智能代理)正在重塑我们处理重复性工作的方式。想象一下,你有一个不知疲倦的数字化助手,能够724小时处理客户咨询、自动整理数据、甚至帮你完成复杂的业务流…

2026/7/4 2:21:32 阅读更多 →
AI Agent开发实战:从理论到部署的完整指南

AI Agent开发实战:从理论到部署的完整指南

1. AI Agent学习全景图:从认知到实战的完整路径AI Agent作为当前人工智能领域最具前景的技术方向之一,正在重塑人机交互的范式。不同于传统AI模型,AI Agent具备自主感知、决策和执行能力,能够像人类员工一样完成复杂任务。我在实际…

2026/7/4 2:19:31 阅读更多 →
DeepSeek零代码办公自动化实战指南

DeepSeek零代码办公自动化实战指南

1. 项目概述:DeepSeek如何赋能零代码办公自动化去年我在帮一家中小型贸易公司做流程优化时,发现他们80%的日常操作都在重复处理Excel表格和邮件往来。当我建议引入自动化工具时,财务主管的第一反应是"我们没人会编程"。这正是DeepS…

2026/7/4 2:19:31 阅读更多 →
Python数据分析实战:帕默群岛企鹅数据集探索

Python数据分析实战:帕默群岛企鹅数据集探索

1. 项目背景与数据集介绍帕默群岛企鹅数据集是生态学研究中的经典案例,记录了南极洲帕默群岛三个岛屿上三种企鹅(阿德利企鹅、巴布亚企鹅和帽带企鹅)的形态测量数据。这个数据集之所以成为数据科学入门的理想选择,主要因为以下几个…

2026/7/4 2:17:31 阅读更多 →
Pandas数据读取全攻略:从CSV到数据库实战技巧

Pandas数据读取全攻略:从CSV到数据库实战技巧

1. Pandas数据读取基础认知作为Python数据分析的瑞士军刀,Pandas的数据读取能力是其核心功能之一。我初次接触Pandas时,最让我惊讶的是它能够用一行代码读取各种格式的数据文件。但真正深入使用后才发现,这看似简单的功能背后隐藏着许多值得深…

2026/7/4 2:15:31 阅读更多 →
BGA芯片手工焊接全流程:从植球到对齐的12个关键步骤与避坑点

BGA芯片手工焊接全流程:从植球到对齐的12个关键步骤与避坑点

BGA芯片手工焊接全流程:从植球到对齐的12个关键步骤与避坑点在电子维修和研发领域,BGA封装芯片的手工焊接一直被视为一项高难度操作。这种底部布满锡球的封装形式,虽然带来了更高的引脚密度和更好的散热性能,但也让焊接过程变得&q…

2026/7/4 2:13:30 阅读更多 →

日新闻

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 发布:关键安全修复版本,多项问题得到解决

Memcached 1.6.43 正式发布,这是一个关键的安全修复版本,修复了多个方面的问题,还对部分功能进行了优化。 安全修复亮点 此次发布在安全修复上表现突出。binprot 避免了项目引用计数溢出,mcmc 因安全问题提升了上游版本号&#xf…

2026/7/4 0:04:29 阅读更多 →
终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案

终极指南:使用HMCL启动器跨平台畅玩Minecraft的完整解决方案 【免费下载链接】HMCL A Minecraft Launcher which is multi-functional, cross-platform and popular 项目地址: https://gitcode.com/gh_mirrors/hm/HMCL HMCL(Hello Minecraft! Lau…

2026/7/4 0:06:29 阅读更多 →
KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

KMX63与PIC18F66K40在嵌入式HMI中的硬件协同与低功耗设计

1. KMX63与PIC18F66K40的硬件协同架构解析KMX63作为一款三轴加速度计和磁力计组合传感器,与PIC18F66K40微控制器的搭配堪称嵌入式HMI开发的黄金组合。这套硬件组合的核心优势在于KMX63提供的高精度运动感知能力与PIC18F66K40强大的信号处理能力形成了完美互补。KMX6…

2026/7/4 0:06:29 阅读更多 →

周新闻

月新闻