本页内容 创建服务并广播记录每次连接的编号把手机数据交给 SDK实现 SDK 的发送函数显示配对码并验证
SDK / FreeRTOS

蓝牙连接

创建服务、收发数据并完成配对。

你的蓝牙驱动负责收发字节,SDK 负责解析和认证。下面按“广播 → 连接 → 收发 → 配对”的顺序接入。

创建服务并广播

在开发板上创建一个 GATT 服务,也就是供手机读写的蓝牙服务:

对象 UUID 属性
主服务 6d4d0001-5239-4f5e-9ca0-941181196587 Primary
RX:手机发给开发板 6d4d0002-5239-4f5e-9ca0-941181196587 Write With Response
TX:开发板发给手机 6d4d0003-5239-4f5e-9ca0-941181196587 Notify + CCCD

SDK 创建成功后取得广播数据,交给蓝牙栈的原始广播接口:

uint8_t advertising[31];
moto_result rc = moto_terminal_advertising(terminal, advertising);
// rc == MOTO_OK 时,发送完整的 31 字节。

这 31 字节已包含 Flags,不再追加。设备名称放在扫描响应里。手机应能在 APP 添加设备页面发现开发板。

记录每次连接的编号

手机连上时调用:

uint64_t connection = 0;
moto_result rc = moto_terminal_connected(terminal, &connection);
// 成功后,把 connection 保存到这条蓝牙连接的上下文中。

connection 是 SDK 为本次连接生成的编号。后续收包、断连都带上它;重连时重新申请,不能拿蓝牙栈自己的句柄代替。

该连接断开时调用:

moto_terminal_disconnected(terminal, connection);

先成功启动 SDK,再允许手机连接。标准 FreeRTOS 接口一次处理一个手机连接。

把手机数据交给 SDK

在 RX 特征值的收包回调里调用:

moto_result rc = moto_terminal_receive(
    terminal, connection, received_bytes, received_size);

每次提交 1–512 字节,大于 512 字节时按顺序分段。

返回值 下一步
MOTO_OK SDK 已复制整段数据,继续下一段
MOTO_FULL SDK 暂时放不下,保存这一段,稍后重试;后续段先等待
MOTO_STATE 当前连接已失效,停止提交它的数据

不能丢掉一段后继续发送;缓存也放不下时断开连接。以上接口从任务调用,不在硬件中断中直接调用。

实现 SDK 的发送函数

SDK 有数据要发给手机时,会调用你填写的 ble_send:

int ble_send(void *user, uint64_t connection,
             const uint8_t *bytes, size_t size);

先把数据复制到自己的发送队列,再返回实际接收的字节数。队列暂满或手机尚未订阅 TX 通知时返回 0;连接不可用时返回负数。SDK 会重试剩余字节。

真正发送时按蓝牙栈允许的单包长度(ATT MTU)分段。不要只保存 bytes 指针,它在函数返回后可能失效。

ble_close 只需通知蓝牙栈关闭指定连接,无需等待关闭完成。

显示配对码并验证

收到的事件 仪表处理
MOTO_EVENT_PAIRING_PIN 将 e.value 显示成四位数字,例如 0042;e.target 是有效秒数
MOTO_EVENT_PAIRING_CLEARED 清除配对码
MOTO_EVENT_AUTHENTICATED 已绑定用户认证通过
MOTO_EVENT_CLOSED 清除临时界面和待处理的旧连接工作

MOTO_EVENT_READY 仅表示加密通道建立,还不是用户认证成功。配对码不写入日志或存储。

最后测试:首次配对、输错 PIN、断开后重连、开发板重启。重启后应保留绑定,不要求用户每次重新配对。