📺 B站视频讲解(Bilibili):https://www.bilibili.com/video/BV1k1C9BYEAB/
📘 《Yocto项目实战教程》京东购买链接:Yocto项目实战教程
基于 Yocto 的蓝牙 Peripheral 设备实战:初始化、连接与数据传输全流程解析
本文以 Rockchip 平台 + Yocto 系统 为背景,结合你当前使用的蓝牙设备,从 Peripheral(从设备)视角,完整讲清楚:
- 蓝牙 Peripheral 在系统中的角色定位
- 如何在 Yocto 中配置蓝牙的初始信息
- Peripheral 如何被 Central 发现并建立连接
- 连接建立后如何进行数据传输
- 实战中真正重要的协议与接口
- 推荐的资料与调试方法
全文以 工程实战为主线,不做无关扩展,目标是:你看完就能在自己的板子上跑起来,并知道每一步在干什么。

一、从工程视角重新理解蓝牙角色模型
在任何蓝牙系统中,首先必须明确 角色(Role),否则后续配置一定会混乱。
1. Central 与 Peripheral 的工程含义
| 角色 | 常见设备 | 工程职责 |
|---|---|---|
| Central | 手机、PC、工控主机 | 发起扫描、建立连接、读取/写入数据 |
| Peripheral | 传感器、嵌入式板卡 | 广播自身信息、等待连接、提供数据服务 |
👉 你当前的 Rockchip + Yocto 设备,典型就是 Peripheral。
也就是说:
-
你的设备 不主动扫描别人
-
而是:
- 周期性广播(Advertising)
- 等待 Central 连接
- 提供可被访问的数据接口
这决定了我们后面所有配置的方向。
二、蓝牙 Peripheral 的整体软件架构(Yocto + Rockchip)
在 Yocto 系统中,一个典型的蓝牙 Peripheral 软件栈如下:
应用层(你的程序)
└── 使用 D-Bus / socket / GATT 接口
BlueZ(bluetoothd)
├── GAP(设备发现 / 连接管理)
├── GATT Server(数据服务)
└── 安全 / 配对策略
Linux Kernel
└── HCI 驱动(UART / USB)
蓝牙控制器(BT 芯片)
核心结论:
在 Yocto 中做蓝牙 Peripheral,99% 的工作都在 user space(BlueZ + 应用),不是内核驱动。
三、第一步:在 Yocto 中配置 Peripheral 的“初始信息”
所谓“初始信息”,从 Peripheral 角度,核心只有四类:
- 设备名(Central 扫描时看到的名字)
- 是否自动上电(power on)
- 是否可被发现(discoverable)
- 支持的蓝牙模式(BLE / BR-EDR)
3.1 BlueZ 的核心配置文件:main.conf
路径:
/etc/bluetooth/main.conf
这是 Peripheral 行为的根配置文件。
3.2 一个适合 Rockchip Peripheral 的实战配置示例
[General]
Name = RK-Peripheral
Class = 0x000100
DiscoverableTimeout = 0
PairableTimeout = 0
ControllerMode = dual
AutoEnable = true
[Policy]
AutoEnable = true
配置项逐条解释(工程意义)
-
Name- Central 扫描时看到的设备名
- 等同于“蓝牙对外身份”
-
DiscoverableTimeout = 0- 永久可发现
- 对嵌入式 Peripheral 非常重要
-
ControllerMode = dual- 同时支持 BLE + 经典蓝牙
-
AutoEnable = true- bluetoothd 启动即打开控制器
👉 这一份配置,已经定义了 Peripheral 的“开机形态”。
四、第二步:确保 Peripheral 在系统启动后处于“可连接状态”
仅有 main.conf 在工程上往往不够稳妥,实际项目中,一定会再加一层 systemd 兜底。
4.1 为什么要加 systemd 初始化服务?
因为在 Rockchip 平台上:
- 蓝牙固件加载
- UART 设备就绪
- bluetoothd 启动顺序
存在时序不确定性。
4.2 一个工程常用的 Peripheral 初始化服务
[Unit]
Description=Bluetooth Peripheral Init
After=bluetooth.service
[Service]
Type=oneshot
ExecStart=/usr/bin/bluetoothctl power on
ExecStart=/usr/bin/bluetoothctl discoverable on
ExecStart=/usr/bin/bluetoothctl pairable on
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
这一步的效果是:
无论系统怎么启动,最终你的设备一定是一个“可发现、可连接的 Peripheral”。
五、第三步:Peripheral 是如何被 Central 发现的?(GAP)
5.1 广播(Advertising)在做什么?
当 Peripheral 没有连接时,会周期性发送广播包,内容包括:
- 设备地址(MAC)
- 设备名(Name)
- 支持的服务 UUID(可选)
Central 做的事情很简单:
扫描 → 显示 → 用户选择 → 发起连接
5.2 用手机验证 Peripheral 是否正确工作
这是最基础、也是最重要的一步。
- Android / iOS 打开蓝牙
- 搜索设备
- 是否能看到:
RK-Peripheral
如果这一步失败:
- 问题一定在 初始化 / 广播阶段
- 不要继续往下查
六、第四步:Peripheral 与 Central 的连接建立过程
连接建立由 Central 主动发起,Peripheral 只是被动响应。
6.1 连接阶段发生了什么?
- Central 发送 Connection Request
- Peripheral 接受连接
- 双方进入 Connected 状态
- 建立 L2CAP 信道
你在系统中能看到的典型现象:
bluetoothctl
> devices
> info XX:XX:XX:XX:XX:XX
状态从:
Connected: no
变为:
Connected: yes
七、真正的数据传输核心:GATT(重点)
如果你只记住一个协议,那一定是 GATT。
7.1 为什么 GATT 是 Peripheral 的核心?
因为:
- Peripheral ≠ socket server
- Peripheral 提供的是 属性(Attribute)
Central 做的事情只有三种:
- Read(读)
- Write(写)
- Notify / Indicate(订阅)
7.2 GATT 的层级结构(非常重要)
GATT Server(在 Peripheral 上)
└── Service(服务)
└── Characteristic(特征)
├── Value
└── Properties(读/写/通知)
你要传输的数据,最终都体现在 Characteristic 的 value 上。
八、实战:在 Yocto 设备上实现一个最小 GATT Server
下面给你一个 工程可用、逻辑清晰的最小示例。
8.1 使用 BlueZ 的 D-Bus GATT 接口(推荐方式)
BlueZ 官方推荐:
- Peripheral → 实现 GATT Server
- 通过 D-Bus 向 bluetoothd 注册
8.2 示例:一个自定义数据 Service
1️⃣ 定义 Service UUID
12345678-1234-5678-1234-56789abcdef0
2️⃣ 定义 Characteristic
87654321-4321-6789-4321-fedcba987654
属性:
- Read
- Write
- Notify
8.3 Python 示例(清晰、适合 Yocto)
class DataCharacteristic(Characteristic):
def __init__(self, bus, index, service):
super().__init__(bus, index,
'87654321-4321-6789-4321-fedcba987654',
['read', 'write', 'notify'], service)
self.value = [0x00]
def ReadValue(self, options):
return self.value
def WriteValue(self, value, options):
self.value = value
print("Received data:", value)
def notify_data(self, data):
self.value = data
self.PropertiesChanged(GATT_CHRC_IFACE,
{'Value': self.value}, [])
8.4 数据流向说明(非常关键)
- Central 写数据 →
WriteValue() - Peripheral 主动推送 →
notify_data() - Central 订阅后即可实时接收
👉 这就是蓝牙 Peripheral 数据传输的本质。
九、协议重点总结(只保留工程必要部分)
| 协议 | 是否必须 | 工程作用 |
|---|---|---|
| GAP | ✅ | 发现 / 连接管理 |
| GATT | ✅ | 数据模型与传输 |
| ATT | ⭕ | GATT 底层实现 |
| SMP | ⚠️ | 配对 / 加密(可选) |
| L2CAP | ⭕ | 底层信道 |
记住一句话:
Peripheral 工程开发,90% 的精力都在 GATT 设计上。
十、调试与验证(非常实用)
10.1 在 Peripheral 端
bluetoothctl
show
info
10.2 在 Central 端
- nRF Connect(Android / iOS)
- 查看 Service / Characteristic
- 读 / 写 / 订阅数据
这是 验证 GATT Server 是否正确的最佳工具。
十一、推荐参考资料(不多,但够用)
-
BlueZ 官方文档(GATT):
-
Bluetooth Core Specification(只查 GATT / GAP):
- Volume 3, Part G
-
BlueZ 示例代码:
test/example-gatt-server
十二、工程级总结
在 Yocto + Rockchip 平台上实现蓝牙 Peripheral,本质是:
- 用 BlueZ 定义好设备的“对外形态”(Name / Discoverable)
- 通过 systemd 保证启动稳定
- 使用 GATT Server 向 Central 提供数据接口
- 所有数据交互,最终都映射到 Characteristic 上
📺 B站视频讲解(Bilibili):https://www.bilibili.com/video/BV1k1C9BYEAB/
📘 《Yocto项目实战教程》京东购买链接:Yocto项目实战教程
860

被折叠的 条评论
为什么被折叠?



