第一个BLE项目:创建项目、配置prj.conf、理解main.c结构、编译与烧录
好,咱们正式开始动手了。
前面铺垫了那么多理论,说实话,我自己当年学蓝牙协议栈的时候,最烦的就是光看不练。所以这一章,咱们直接创建一个真正的BLE项目。你跟着我走一遍,跑通了,信心就有了。
1. 创建项目:从零开始搭架子
我个人习惯用 west 命令来管理Zephyr项目。你想想看,如果每次都要手动复制一堆模板文件,多累啊。
打开终端,先确认你的工作目录。我一般放在 ~/zephyr_workspace 下。然后执行:
west init -m https://github.com/zephyrproject-rtos/zephyr --mr v3.5.0 zephyr_project
cd zephyr_project
west update
嗯,这里要注意:west update 这一步会下载所有依赖模块,包括蓝牙协议栈的核心库。我第一次跑的时候,网络不好,卡了半小时。建议你找个网络稳定的环境。
项目初始化完成后,我们创建一个自己的应用目录:
mkdir -p apps/my_first_ble
cd apps/my_first_ble
在这个目录下,你需要创建三个文件:
prj.conf—— 项目配置文件src/main.c—— 主程序文件CMakeLists.txt—— 构建描述文件
说白了,这三个文件就是Zephyr项目的骨架。缺一个都跑不起来。
2. 配置prj.conf:打开蓝牙的开关
Zephyr的配置系统基于Kconfig。你不需要理解它的全部原理,只要知道:prj.conf 里写的每一行,都是在告诉编译器“我要用这个功能”。
对于最基础的BLE项目,我建议你这样配置:
# 启用蓝牙功能
CONFIG_BT=y
# 启用蓝牙中心角色(可以扫描和连接其他设备)
CONFIG_BT_CENTRAL=y
# 启用蓝牙外设角色(可以被其他设备连接)
CONFIG_BT_PERIPHERAL=y
# 设置蓝牙设备名称
CONFIG_BT_DEVICE_NAME="MyFirstBLE"
# 启用日志输出,方便调试
CONFIG_LOG=y
CONFIG_LOG_BACKEND_UART=y
我在项目中遇到过一个问题:有些初学者只开了 CONFIG_BT=y,结果发现设备能广播但连不上。为什么?因为没开 CONFIG_BT_PERIPHERAL。你想想看,广播只是喊一嗓子,真正要建立连接,必须把外设角色打开。
CONFIG_BT_DEVICE_NAME,结果手机扫描到的设备名是乱码。后来查了半天才发现,默认名称是Zephyr的默认字符串,长度和编码都不对。所以,设备名一定要显式配置。
3. 理解main.c结构:BLE程序的骨架
好,现在来看核心代码。一个最简单的BLE程序,main.c 长这样:
#include <zephyr/kernel.h>
#include <zephyr/bluetooth/bluetooth.h>
void main(void)
{
int err;
printk("BLE示例程序启动\n");
/* 初始化蓝牙协议栈 */
err = bt_enable(NULL);
if (err) {
printk("蓝牙初始化失败 (err %d)\n", err);
return;
}
printk("蓝牙初始化成功\n");
/* 开始广播 */
err = bt_le_adv_start(BT_LE_ADV_CONN, NULL, 0, NULL, 0);
if (err) {
printk("广播启动失败 (err %d)\n", err);
return;
}
printk("广播已启动,设备名称: MyFirstBLE\n");
/* 程序不能退出,否则蓝牙会停止 */
while (1) {
k_sleep(K_SECONDS(1));
}
}
这段代码的结构其实很清晰,我拆开给你讲:
- 头文件包含:
bluetooth.h是蓝牙协议栈的主头文件,所有蓝牙API都在里面。 - bt_enable(NULL):这是蓝牙协议栈的初始化函数。参数是回调函数指针,这里传NULL表示不需要回调通知。我建议你初期都传NULL,等后面需要处理连接事件时再改。
- bt_le_adv_start():启动广播。第一个参数
BT_LE_ADV_CONN表示可连接广播。说白了,就是告诉周围的设备:“我在这里,快来连我”。 - while(1) 循环:这个很重要。main函数不能返回,否则整个程序就退出了,蓝牙也会停止。我见过有人忘了加这个循环,程序跑完就结束了,蓝牙根本没工作。
bt_enable() 前后加打印信息。如果蓝牙初始化失败,90%的原因是硬件问题——比如模块没上电、天线没接好。别急着怀疑代码,先检查硬件。
4. CMakeLists.txt:告诉编译器怎么编译
这个文件很简单,就几行:
cmake_minimum_required(VERSION 3.20)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(my_first_ble)
target_sources(app PRIVATE src/main.c)
嗯,这里要注意:find_package(Zephyr REQUIRED) 这一行,必须确保环境变量 ZEPHYR_BASE 已经设置。如果你是用 west 初始化的项目,这个变量会自动设置。否则,你需要手动 source zephyr-env.sh。
5. 编译与烧录:让代码跑起来
编译命令很简单:
cd ~/zephyr_project
west build -b nrf52840dk_nrf52840 apps/my_first_ble
这里 -b 参数指定开发板。我用的nRF52840 DK,你可以换成自己的板子,比如 nrf52dk_nrf52832 或 qemu_cortex_m3(如果没有硬件,可以用QEMU模拟)。
编译成功后,烧录命令:
west flash
如果你用的是JLink调试器,它会自动识别。如果是其他调试器,可能需要加参数,比如 --runner pyocd。
6. 验证结果:用手机看看
烧录成功后,打开手机的蓝牙扫描。你应该能看到一个叫 MyFirstBLE 的设备。点击连接,如果一切正常,手机会显示“已连接”。
如果你没有手机,也可以用nRF Connect桌面版。我个人更喜欢用手机,方便。
如果扫描不到设备,检查以下几点:
- 开发板是否上电?LED灯亮了吗?
- 串口是否有打印信息?如果有“蓝牙初始化成功”和“广播已启动”,说明代码没问题。
- 天线是否接好?nRF52840 DK有板载天线,但有些模块需要外接天线。
好,这一章就到这里。下一章,我们会深入广播数据的结构,教你如何自定义广播包,让设备看起来更专业。