1、实验简介

本实验参考网址:https://gitee.com/Lockzhiner-Electronics/lz3863/tree/master/apps/e4_sle_uart_client

准备事项:

  • 小智派-LZ3863开发板
  • USB烧录线
  • Windows电脑

其中,小智派-LZ3863开发板是福州市凌睿智捷电子有限公司研发的一款基于海思WS63(Hi3863)芯片、高度集成2.4GHz Wi-Fi6、BLE(低功耗蓝牙)和SLE(星闪低功耗接入技术,简称SLE)、专用于短距离数据传输的新兴无线通信技术模块。

在这里插入图片描述
在这里插入图片描述

1.1、实验目的

本实验旨在帮助学习者掌握 OpenHarmony 轻量系统中 SLE(Smart Link Extension,星闪)UART 透传服务端 的实现方法。通过本实验,你将学会:

  1. 理解 SLE SSAP Server(服务访问协议服务端)UART 串口 协同工作的透传机制;
  2. 在开发板上实现 SLE UART 透传服务端,完成 SSAP 服务注册、广播启动与双向数据转发;
  3. 使用 消息队列 解耦 UART 中断回调与 SLE 发送任务,掌握异步数据转发设计;
  4. 掌握 UART 中断接收、SSAP Notify 发送与 Write 接收的完整处理流程;
  5. 完成案例代码的编译、烧录,并与 e4_sle_uart_client 客户端案例进行双板 UART 透传联调。

1.2、实验内容

本案例在 LZ3863-星闪开发板上实现 SLE UART 透传服务端 功能:初始化星闪协议栈并注册 UART 服务,启动可连接广播;连接建立后,将 UART 串口接收的数据通过 SSAP Notify 转发给客户端,同时将客户端写入的数据打印到串口终端。

项目 说明
应用层源文件 sle_server_app.c(UART 收发任务与入口)
协议栈封装 sle_server_lib.c / sle_server_lib.h(SSAP 服务、广播、回调)
广播设备名称 sle_uart_server
设备 MAC 地址 78:70:60:88:96:46
UART 总线 CONFIG_SLE_UART_BUS = 0(UART0)
应用 UUID {0x12, 0x34}
服务 UUID 0x2222
属性 UUID 0x2323(读 / 写 / Notify,服务端 → 客户端)
数据转发方式 UART 接收 → 消息队列 → SSAP Notify;SSAP Write → 串口打印
接收缓冲区 g_sle_rx_data[256]
MTU 大小 520SLE_MTU_SIZE_DEFAULT
初始化入口 APP_FEATURE_INIT(sle_server_app)

典型联调拓扑:

┌─────────────────────────┐    SLE 连接     ┌─────────────────────────┐
│  开发板 A(本案例)        │ ◄────────────► │  开发板 B(e4 客户端)    │
│  e3_sle_uart_server     │  SSAP Notify   │  e4_sle_uart_client     │
│  (Server)              │  SSAP Write    │  (Client)              │
│  广播: sle_uart_server  │                │  扫描并连接服务端         │
│  UART0 ←→ 串口助手       │                │  UART0 ←→ 串口助手       │
│  串口输入 → SLE 转发     │                │  串口输入 → SLE 转发     │
│  SLE 数据 → 串口打印     │                │  SLE 数据 → 串口打印     │
└─────────────────────────┘                 └─────────────────────────┘

说明:本案例为 SLE UART 透传服务端,需配合 e4_sle_uart_client 客户端案例完成双板透传联调。建议先烧录并启动服务端开发板,确认广播就绪后再启动客户端开发板。

e1_sle_connect_server 基础连接案例的区别在于:本案例不再周期性发送固定字符串,而是 由 UART 串口输入驱动数据转发,实现真正的无线串口透传功能。

1.3、实验环境

项目 说明
硬件 两块 LZ3863-星闪开发板(服务端 + 客户端)、USB 数据线
软件 OpenHarmony v5.1.0 源码、hb 编译工具
联调案例 e4_sle_uart_client(客户端,烧录至第二块开发板)
调试工具 串口助手(波特率 115200,8N1)
案例路径 applications/sample/wifi-iot/app/e3_sle_uart_server/

注意:完整 UART 透传实验需要 两块开发板,分别烧录服务端固件(本案例)和客户端固件(e4_sle_uart_client),并分别通过 USB 连接 PC 串口助手。


2、基础知识

2.1、SLE UART 透传概述

SLE UART 透传 是一种将串口数据通过 SLE 无线链路透明传输的通信模式,广泛应用于物联网网关、无线串口模块等场景。其核心思想是:

方向 数据路径 本案例实现
串口 → SLE UART 接收数据,通过 SSAP Notify 发送给客户端 sle_uart_read_int_handler → 消息队列 → sle_server_send_report_by_handle()
SLE → 串口 客户端 Write 数据,服务端接收后输出到串口 ssaps_write_request_callbacksg_sle_rx_datasle_uart_tx_server 打印

2.2、SLE 协议栈概述

SLE(Smart Link Extension,星闪) 是面向物联网场景的短距离无线通信技术,具备低功耗、低延迟、高吞吐量等优势。SLE 协议栈从下到上可分为:

层次 英文名称 主要功能
物理层 PHY 射频收发
链路层 LL 连接建立、数据包封装
主机控制器接口 HCI 控制器与主机间通信
服务访问协议 SSAP 服务/属性读写、句柄管理
设备发现 Announce/Seek 广播、扫描、连接
连接管理 Connection Manager 连接状态、配对管理

本案例主要涉及 设备发现(Announce)SSAP Server(服务与属性) 两层。

2.3、设备发现:广播与连接

SLE 设备通过 Announce(广播)Seek(扫描) 完成发现与连接。本案例服务端采用 可连接可扫描广播(Connectable Scanable) 模式:

服务端启动
    ↓
注册 SSAP 服务与属性
    ↓
配置广播数据(发现等级 + 接入模式 + 本地名称)
    ↓
SleStartAnnounce()  →  开始广播,等待客户端扫描连接
    ↓
客户端发起连接  →  OH_SLE_ACB_STATE_CONNECTED
    ↓
连接断开  →  重新广播

本案例广播参数:

参数 说明
广播模式 SLE_ANNOUNCE_MODE_CONNECTABLE_SCANABLE 可连接、可扫描
广播间隔 min=0xC8, max=0xC8 单位 125 μs,约 25 ms
广播信道 默认全信道 SLE_ADV_CHANNEL_MAP_DEFAULT
广播功率 10 dBm SLE_ADV_TX_POWER
广播句柄 1 SLE_ADV_HANDLE_DEFAULT
连接间隔 0x64 单位 125 μs,约 12.5 ms

2.4、SSAP:服务与属性

SSAP 采用 Client/Server 模型。本案例实现了一个 SLE UART 透传服务,结构如下:

Service: 0x2222 (SLE UART Service)
    └── Property: 0x2323
            权限: Read | Write
            操作指示: Read | Write
            描述符: Client Configuration (0x2902)
            用途: 双向数据收发(Notify 发送 + Write 接收)
角色 数据方向 本案例实现方式
服务端 → 客户端 Property Notify UART 数据 → sle_server_send_report_by_handle()
客户端 → 服务端 Property Write ssaps_write_request_callbacks() → 写入 g_sle_rx_data

2.5、UART 中断回调与消息队列

本案例采用 中断回调 + 消息队列 架构处理 UART 数据,避免在中断上下文中执行耗时的 SLE 发送操作:

UART 硬件接收数据
    ↓
触发接收中断 → sle_uart_read_int_handler()
    ↓
动态分配内存,拷贝 UART 数据
    ↓
写入消息队列(osal_msg_queue_write_copy)
    ↓
sle_uart_rx_server 任务阻塞读取队列
    ↓
sle_server_send_report_by_handle() → SSAP Notify 发送
    ↓
释放动态内存(osal_vfree)

消息队列的优势:

对比项 直接在中断中发送 SLE 消息队列异步转发
中断耗时 中断中执行 SLE 协议栈操作,可能超时 中断仅做数据拷贝和入队,耗时极短
数据安全 中断缓冲区可能被覆盖 动态分配独立缓冲区,数据完整
任务解耦 UART 中断与 SLE 发送紧耦合 收发任务独立调度,互不阻塞

UART 接收触发条件:

参数 说明
触发条件 UART_RX_CONDITION_FULL_OR_IDLE 接收缓冲区满或空闲时触发
超时阈值 1 空闲超时参数

2.6、SLE 事件回调机制

SLE 协议栈通过回调函数异步通知应用层状态变化。本案例注册了设备发现、连接管理与 SSAP Server 三类回调:

设备发现回调:

回调函数 触发时机 处理逻辑
sle_enable_cbk SLE 协议栈启用完成 延时 1s 后注册服务并启动广播
sle_announce_enable_cbk 广播启动成功 打印日志
sle_announce_disable_cbk 广播停止 打印日志
SleAnnounceTerminalCbk 广播终止 打印日志

连接管理回调:

回调函数 触发时机 处理逻辑
sle_connect_state_changed_cbk 连接状态变化 保存连接句柄;连接时设置 MTU;断开时重新广播
sle_pair_complete_cbk 配对完成 保存配对句柄

SSAP Server 回调:

回调函数 触发时机 处理逻辑
ssaps_add_service_cbk 服务添加完成 打印服务 UUID
ssaps_add_property_cbk 属性添加完成 打印属性 UUID
ssaps_add_descriptor_cbk 描述符添加完成 打印描述符 UUID
ssaps_start_service_cbk 服务启动完成 打印日志
ssaps_mtu_changed_cbk MTU 协商完成 保存配对句柄
ssaps_write_request_callbacks 收到客户端写请求 将数据拷贝至 g_sle_rx_data,置位 g_sle_new_data_ready
ssaps_read_request_callbacks 收到客户端读请求 预留读请求处理

2.7、软件调用层次

本案例的软件调用层次如下:

应用层(sle_server_app.c)
    ├── sle_server_app()              ← APP_FEATURE_INIT 注册入口
    ├── sle_uart_rx_server()          ← UART 转发任务:读队列 → SLE Notify 发送
    ├── sle_uart_tx_server()          ← SLE 接收任务:打印客户端写入的数据
    └── sle_uart_read_int_handler()   ← UART 中断回调:数据入队
            │
封装层(sle_server_lib.c)
    ├── sle_server_init()             ← 初始化:注册回调、启用 SLE
    ├── sle_enable_server_cbk()       ← SLE 启用后:添加服务、启动广播
    ├── sle_server_add()              ← 注册 SSAP Server、添加服务/属性
    ├── sle_server_adv_init()         ← 配置广播参数与数据
    └── sle_server_send_report_by_handle() ← SSAP Notify 发送
            │
协议栈 / 驱动层
    ├── SleAnnounceSeek*()            ← 广播与设备发现
    ├── SleConnection*()              ← 连接与配对管理
    ├── Ssaps*()                      ← SSAP Server 服务/属性管理
    ├── EnableSle()                   ← 启用 SLE 协议栈
    └── uapi_uart_register_rx_callback() ← UART 接收中断注册

2.8、核心 API 介绍

2.8.1、头文件
#include "sle_server_lib.h"
#include "cmsis_os2.h"
#include "ohos_init.h"
#include "uart.h"
2.8.2、应用层 API
API 名称 功能说明
sle_server_init() 初始化 SLE 服务端:注册回调、启用 SLE 协议栈
sle_server_send_report_by_handle(data, len) 通过 SSAP Notify 向已连接客户端发送数据
uapi_uart_register_rx_callback(bus, condition, timeout, handler) 注册 UART 接收中断回调
osal_msg_queue_create() / osal_msg_queue_write_copy() / osal_msg_queue_read_copy() 消息队列创建、写入与读取
osal_vmalloc() / osal_vfree() 动态内存分配与释放
osThreadNew(func, arg, &attr) 创建 RTOS 线程
osDelay(ticks) 线程延时
APP_FEATURE_INIT(func) 注册应用特性初始化入口,系统启动后自动执行
2.8.3、协议栈 API(sle_server_lib.c 内部调用)
API 名称 功能说明
EnableSle() 启用 SLE 协议栈
SleSetLocalAddr() 设置 SLE 设备 MAC 地址
SleSetAnnounceParam() / SleSetAnnounceData() 配置广播参数与广播数据
SleStartAnnounce() 启动广播
SsapsRegisterServer() 注册 SSAP Server
SsapsAddServiceSync() 添加 SSAP 服务
SsapsAddPropertySync() 添加属性
SsapsAddDescriptorSync() 添加描述符
SsapsStartService() 启动 SSAP 服务
SsapsNotifyIndicate() 发送 Notify/Indicate 通知
SleConnectionRegisterCallbacks() 注册连接状态回调

3、程序设计

3.1、程序架构

本案例目录结构

e3_sle_uart_server/
├── sle_server_app.c      # 应用层:UART 收发任务、消息队列与入口
├── sle_server_lib.c      # 协议栈封装:SSAP 服务、广播、回调
├── sle_server_lib.h      # 头文件:UUID 宏定义与 API 声明
├── BUILD.gn              # GN 编译配置
├── README_zh.md          # 案例简要说明
└── 实验手册.md            # 本实验手册

程序执行流程:

系统启动
    │
    ▼
sle_server_app()                    ← APP_FEATURE_INIT 注册,自动执行
    │
    ├── osal_msg_queue_create()     ← 创建消息队列
    │
    ├── osThreadNew(sle_uart_rx_server)  ← 创建 UART 转发任务
    └── osThreadNew(sle_uart_tx_server)  ← 创建 SLE 接收打印任务
            │
            ▼
    ┌───────────────────────────────────────────────┐
    │  sle_uart_rx_server(UART 转发任务)            │
    │  sle_server_init() → 注册 SLE 服务、启动广播   │
    │  uapi_uart_register_rx_callback() → 注册 UART │
    │  阻塞读取消息队列 → Notify 发送 UART 数据       │
    └───────────────────────────────────────────────┘
    ┌───────────────────────────────────────────────┐
    │  sle_uart_tx_server(SLE 接收打印任务)         │
    │  轮询 g_sle_new_data_ready → 打印接收数据       │
    └───────────────────────────────────────────────┘

3.2、源文件说明

文件 说明
sle_server_app.c 应用层主程序,实现 UART 中断回调、消息队列、UART 转发任务与 SLE 接收打印任务
sle_server_lib.c SLE 协议栈封装,实现 SSAP 服务注册、广播配置、连接与 SSAP 回调处理
sle_server_lib.h UUID 宏定义、广播参数、全局变量声明与 API 接口
BUILD.gn 编译配置,生成 sle_uart 静态库

3.3、关键代码分析

(1)宏定义与消息队列数据结构
#define CONFIG_SLE_UART_BUS 0

typedef struct
{
    uint8_t *value;     /* 数据缓冲区指针 */
    uint16_t value_len; /* 数据长度 */
} msg_data_t;

CONFIG_SLE_UART_BUS 指定 UART0 作为透传串口;msg_data_t 作为消息队列的数据载体,封装动态分配的 UART 数据缓冲区及其长度。

(2)UART 接收中断回调 — sle_uart_read_int_handler

UART 串口接收到数据后触发中断,回调函数将数据封装并写入消息队列:

static void sle_uart_read_int_handler(const void *buffer, uint16_t length, bool error)
{
    printf("sle_uart_read_int_handler server.\r\n");
    unused(error);
    msg_data_t msg_data = {0};
    void *buffer_cpy = osal_vmalloc(length);
    if (memcpy_s(buffer_cpy, length, buffer, length) != EOK)
    {
        osal_vfree(buffer_cpy);
        return;
    }
    msg_data.value = (uint8_t *)buffer_cpy;
    msg_data.value_len = length;
    osal_msg_queue_write_copy(mouse_msg_queue, (void *)&msg_data, msg_rev_size, 0);
}

中断回调中仅完成内存拷贝和入队操作,不执行 SLE 发送,保证中断响应迅速。

(3)UART 转发任务 — sle_uart_rx_server

该任务负责 SLE 初始化、UART 回调注册,以及从消息队列读取数据并通过 SLE Notify 转发:

void sle_uart_rx_server(void *arg)
{
    unused(arg);
    sle_server_init();
    errcode_t ret = uapi_uart_register_rx_callback(CONFIG_SLE_UART_BUS,
        UART_RX_CONDITION_FULL_OR_IDLE, 1, sle_uart_read_int_handler);
    if (ret != ERRCODE_SUCC)
    {
        printf("Register uart callback fail.");
        return;
    }
    while (1)
    {
        msg_data_t msg_data = {0};
        int msg_ret = osal_msg_queue_read_copy(mouse_msg_queue, &msg_data,
                                               &msg_rev_size, OSAL_WAIT_FOREVER);
        if (msg_ret != OSAL_SUCCESS)
        {
            if (msg_data.value != NULL)
                osal_vfree(msg_data.value);
            continue;
        }
        if (msg_data.value != NULL)
        {
            sle_server_send_report_by_handle(msg_data.value, msg_data.value_len);
            osal_vfree(msg_data.value);
        }
    }
}

任务以 OSAL_WAIT_FOREVER 阻塞等待消息队列数据,收到数据后立即通过 sle_server_send_report_by_handle() 转发,并释放动态内存。

(4)SLE 接收打印任务 — sle_uart_tx_server

该任务轮询全局标志位,检测客户端通过 SSAP Write 发送的新数据并打印到串口:

void sle_uart_tx_server(void *arg)
{
    unused(arg);
    while (1)
    {
        if (g_sle_new_data_ready == true)
        {
            printf("sle rev date:%s", g_sle_rx_data);
            g_sle_new_data_ready = false;
        }
        osDelay(1);
    }
}

标志位 g_sle_new_data_ready 由 SSAP 写请求回调 ssaps_write_request_callbacks 在收到客户端数据时置位。

(5)程序入口 — sle_server_app
static void sle_server_app(void)
{
    int msg_ret = osal_msg_queue_create("task_msg", msg_rev_size,
                                        &mouse_msg_queue, 0, msg_rev_size);
    if (msg_ret != OSAL_SUCCESS)
    {
        printf("msg queue create fail.");
        return;
    }

    osThreadAttr_t rx_attr = {0};
    rx_attr.name = "sle_uart_rx_server";
    rx_attr.stack_size = 8192;
    rx_attr.priority = osPriorityNormal;
    osal_kthread_lock();
    osThreadNew(sle_uart_rx_server, NULL, &rx_attr);
    osal_kthread_unlock();

    osThreadAttr_t tx_attr = {0};
    tx_attr.name = "sle_uart_tx_server";
    tx_attr.stack_size = 8192;
    tx_attr.priority = osPriorityNormal;
    osal_kthread_lock();
    osThreadNew(sle_uart_tx_server, NULL, &tx_attr);
    osal_kthread_unlock();
}

APP_FEATURE_INIT(sle_server_app);

系统启动后自动调用 sle_server_app():先创建消息队列,再创建 UART 转发任务和 SLE 接收打印任务。SLE 初始化在 sle_uart_rx_server 任务中执行。

(6)服务端初始化 — sle_server_init
errcode_t sle_server_init()
{
    sle_announce_register_cbks();   /* 注册广播回调 */
    sle_conn_register_cbks();         /* 注册连接回调 */
    sle_ssaps_register_cbks(ssaps_read_request_callbacks,
                            ssaps_write_request_callbacks);  /* 注册 SSAP 回调 */
    EnableSle();                    /* 启用 SLE */
    return ERRCODE_SLE_SUCCESS;
}

EnableSle() 成功后触发 sle_enable_cbk 回调,延时 1 秒后执行 sle_enable_server_cbk(),完成服务注册与广播启动。

(7)SSAP Notify 发送 — sle_server_send_report_by_handle
errcode_t sle_server_send_report_by_handle(const uint8_t *data, uint8_t len)
{
    SsapsNtfInd param = {0};
    param.handle = g_propertyHandle;
    param.type = SSAP_PROPERTY_TYPE_VALUE;
    param.value = g_receiveBuf;
    param.valueLen = len + 1;
    memcpy_s(param.value, param.valueLen, data, len);
    return SsapsNotifyIndicate(g_serverId, g_sleConnHdl, &param);
}

Notify 发送依赖属性句柄(在 ssaps_add_property_cbk 中保存至 g_propertyHandle)和当前连接句柄(在 sle_connect_state_changed_cbk 中保存至 g_sleConnHdl)。

(8)SSAP Write 接收 — ssaps_write_request_callbacks
void ssaps_write_request_callbacks(uint8_t serverId, uint16_t connId,
                                   ssaps_req_write_cb_t *write_cb_para,
                                   errcode_t status)
{
    write_cb_para->value[write_cb_para->length - 1] = '\0';
    memcpy(g_sle_rx_data, write_cb_para->value, write_cb_para->length);
    g_sle_new_data_ready = true;
    printf(" client_send_data: %s\r\n", write_cb_para->value);
}

客户端 Write 数据到达后,协议栈回调将数据拷贝至全局缓冲区并置位标志,sle_uart_tx_server 任务检测到标志后打印到串口。

(9)BUILD.gn — 编译配置
static_library("sle_uart") {
  sources = [
    "sle_server_app.c",
    "sle_server_lib.c",
  ]
  defines = [
    "CONFIG_UART_SUPPORT_TX",
    "CONFIG_UART_SUPPORT_RX",
  ]
  // ...
}

编译宏 CONFIG_UART_SUPPORT_TXCONFIG_UART_SUPPORT_RX 启用 UART 收发功能支持。

3.4、程序执行流程

e4 客户端 SSAP Server sle_server_lib 消息队列 sle_server_app UART0 PC 串口助手 e4 客户端 SSAP Server sle_server_lib 消息队列 sle_server_app UART0 PC 串口助手 广播 sle_uart_server,等待连接 osal_msg_queue_create() 创建 sle_uart_rx_server / sle_uart_tx_server sle_server_init() SsapsRegisterServer() + sle_server_add() 服务启动 → SleStartAnnounce() uapi_uart_register_rx_callback() 扫描并连接服务端 connect_state_changed_cbk (CONNECTED) 发送串口数据 sle_uart_read_int_handler() osal_msg_queue_write_copy() sle_server_send_report_by_handle() SsapsNotifyIndicate() Notify 转发数据 串口打印接收数据 客户端串口发送数据 Write Property write_request_callbacks → g_sle_rx_data sle_uart_tx_server 打印接收数据

4、编译步骤

本实验编译服务端固件并烧录至 开发板 A;客户端固件请参考 e4_sle_uart_client 案例编译烧录至 开发板 B。以下步骤只需在首次编译时完成 4.1~4.3 的配置注册。

4.1、确认案例目录

确认案例已位于 OpenHarmony 源码目录下:

applications/sample/wifi-iot/app/e3_sle_uart_server/
├── sle_server_app.c
├── sle_server_lib.c
├── sle_server_lib.h
├── BUILD.gn
└── 实验手册.md

若从外部复制,请将 e3_sle_uart_server 目录放到上述 app/ 路径下。

4.2、修改 BUILD.gn(注册编译组件)

编辑 applications/sample/wifi-iot/app/BUILD.gn,在 features 列表中添加本案例:

lite_component("app") {
  features = [
    "startup",
    "e3_sle_uart_server:sle_uart",   // 添加此行
  ]
}

4.3、修改 SDK 配置文件

步骤 1:编辑 device/soc/hisilicon/ws63v100/sdk/build/config/target_config/ws63/config.py

找到 'ws63-liteos-app' 配置段,在其 'ram_component' 列表中添加:

"sle_uart"

步骤 2:编辑 device/soc/hisilicon/ws63v100/sdk/libs_url/ws63/cmake/ohos.cmake

找到 "ws63-liteos-app" 对应的 set(COMPONENT_LIST 部分,添加:

"sle_uart"

4.4、编译固件

在 OpenHarmony 源码根目录下执行编译:

rm -rf out
hb set -root .
# 通过上下方向键选择 ws63 对应的编译分支(如 nearlink_txnl63 / nearlink_dk_3863)
hb build -f

编译成功后,将固件烧录到 开发板 A(作为 SLE UART 透传服务端)。

4.5、编译客户端固件(开发板 B)

按照 e4_sle_uart_client 案例的 README 或实验手册,完成客户端的 BUILD.gn 与 SDK 配置注册(组件名同样为 sle_uart,但需将 features 指向 e4_sle_uart_client:sle_uart),编译后将固件烧录到 开发板 B

注意:服务端与客户端不能同时编译到同一块开发板固件中。编译客户端时,需将 features 中的 e3_sle_uart_server:sle_uart 替换为 e4_sle_uart_client:sle_uart

4.6、烧录固件

使用开发板配套的烧录工具,将编译生成的固件分别烧写到两块 LZ3863-星闪开发板。具体烧录步骤请参考开发板用户手册。


5、运行结果

5.1、硬件准备

  1. 开发板 A(服务端固件,本案例)上电或复位,等待 SLE 广播启动;
  2. 开发板 B(客户端固件 e4_sle_uart_client)上电或复位,开始扫描并连接服务端;
  3. 两块开发板分别通过 USB 连接 PC,各打开一个串口助手窗口(波特率 115200,8N1)。

建议:先启动服务端开发板,确认广播启动日志输出后,再启动客户端开发板,以提高首次连接成功率。

5.2、串口配置

参数
波特率 115200
数据位 8
停止位 1
校验位
流控

5.3、服务端预期输出(开发板 A)

烧录服务端固件并复位后,串口助手可观察到 SLE 初始化与服务注册过程:

[sle server] init ok
[sle server] sle enable callback status:0
[sle server] sle add service in
[sle server] add service cbk callback server_id:0, handle:xx, status:0
[sle server] uuid: 22 22.
[sle server] add property cbk callback server_id:0, service_handle:xx, handle:xx, status:0
[sle server] uuid: 23 23.
[sle server] sle add service, server_id:0, service_handle:xx, property_handle:xx
[sle server] set announce data success.
[sle server] sle announce enable callback id:01, state:0

表示 SSAP UART 服务注册成功,广播已启动,设备名 sle_uart_server 可被客户端扫描发现。

客户端连接成功后,服务端还会输出:

[sle server] connect state changed callback conn_id:0x01, conn_state:0x2, ...
[sle server] pair complete conn_id:01, status:0

conn_state:0x2 表示 SLE 连接已建立(OH_SLE_ACB_STATE_CONNECTED)。

5.4、UART 透传验证

连接建立后,可通过以下两个场景验证双向 UART 透传功能:

验证场景 1:服务端 UART → 客户端
  1. 开发板 A 的串口助手发送窗口输入数据,例如 SLE UART server test
  2. 服务端串口打印中断回调日志:
sle_uart_read_int_handler server.
  1. 客户端 开发板 B 的串口助手应打印接收到的透传数据:
sle rev date:SLE UART server test
验证场景 2:客户端 UART → 服务端
  1. 开发板 B 的串口助手发送窗口输入数据,例如 data from SLE client
  2. 服务端 开发板 A 的串口助手应打印:
 client_send_data: data from SLE client
sle rev date:data from SLE client

完整日志示例:

sle_uart_read_int_handler server.
 client_send_data: data from SLE client
sle rev date:data from SLE client
sle_uart_read_int_handler server.

5.5、客户端预期输出(开发板 B)

烧录 e4_sle_uart_client 固件并复位后,串口助手可观察到扫描、连接与数据收发过程:

[sle uart client] sle uart scan data :sle_uart_server
[sle uart client] SLE_ACB_STATE_CONNECTED
[sle uart client] exchange mtu, mtu size: 520, version: 1.
[sle uart client] find structure cbk client: 0 conn_id:1 status: 0
[sle uart client] sle_client_sample_find_property_cbk, client id: 0, conn id: 1, ...

其中:

  • sle uart scan data :sle_uart_server 表示扫描到目标服务端;
  • SLE_ACB_STATE_CONNECTED 表示已成功连接服务端;
  • exchange mtu / find structure 表示 SSAP 服务发现完成。

5.6、双向透传验证汇总

方向 操作 发送端串口输出 接收端串口输出
服务端 → 客户端 开发板 A 串口发送 SLE UART server test sle_uart_read_int_handler server. 开发板 B:sle rev date:SLE UART server test
客户端 → 服务端 开发板 B 串口发送 data from SLE client sle_uart_read_int_handler server. 开发板 A:sle rev date:data from SLE client

5.7、结果分析

现象 说明
服务端输出 set announce data success / announce enable callback SSAP 服务就绪,广播已成功启动
服务端输出 connect state changed ... conn_state:0x2 客户端已成功连接
服务端输出 sle_uart_read_int_handler server. UART 中断回调正常触发,数据已入队
客户端输出 sle rev date:... SSAP Notify 接收正常,UART → SLE 透传成功
服务端输出 client_send_data / sle rev date 客户端 Write 数据接收正常,SLE → UART 透传成功
客户端长时间无连接日志 服务端未启动或广播未就绪,检查服务端日志
连接成功但 UART 数据未转发 SSAP 服务发现未完成或 Notify 未启用,检查 UUID 是否匹配

5.8、常见问题排查

问题 可能原因 解决方法
客户端扫描不到服务端 服务端未启动或广播失败 确认服务端输出 announce enable callback;先启动服务端
连接后立即断开 信号干扰或协议栈未就绪 两块板靠近放置;确认服务端 sle_enable_cbk 延时 1s 已执行
串口发送无 sle_uart_read_int_handler 日志 UART 回调未注册或串口参数错误 确认波特率 115200;检查 CONFIG_SLE_UART_BUS 配置
服务端有中断日志但客户端无数据 SLE 未连接或 Notify 未生效 确认连接已建立;检查 MTU 与服务发现是否完成
服务端无 sle rev date 输出 客户端未写入或属性 UUID 不匹配 确认客户端已连接并完成服务发现
编译报错找不到 sle_uart BUILD.gn 或 config.py 未正确修改 逐步核对 4.2、4.3 节的配置项
两块板烧录了相同固件 未区分服务端/客户端固件 分别编译烧录 e3(服务端)和 e4(客户端)

6、实验扩展

完成基本实验后,可尝试以下扩展练习:

  1. 修改设备名称:更改 g_sleLocalName 数组,同时修改客户端 SLE_SERVER_NAME 宏,观察扫描连接结果的变化;
  2. 修改 UART 总线:调整 CONFIG_SLE_UART_BUS 宏,了解不同 UART 端口的透传配置;
  3. 增加连接状态判断:在 sle_uart_read_int_handler 中增加 SLE 连接状态检查,仅在已连接时入队转发;
  4. 调整消息队列深度:修改 osal_msg_queue_create 参数,测试高频率串口输入下的数据转发稳定性;
  5. 断开重连测试:断开 SLE 连接后观察服务端是否自动重新广播并成功重连,验证透传功能恢复;
  6. 结合后续案例:在 SLE UART 透传基础上,配合其他星闪或网络通信案例实现更复杂的物联网网关应用。
Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐