Seeed Studio XIAO nRF54L15 Sense BLE 使用指南
nRF Connect SDK
本蓝牙广播教程基于官方示例代码,经过修改后可在 Nordic Connect SDK 上运行。结合我们的开发板和官方文档,您可以深入了解更多蓝牙应用。
当手机未连接到 XIAO nRF54L15 时,板载指示灯将保持常亮。一旦手机成功连接,指示灯将开始闪烁,表示已建立连接。

手机连接 XIAO nRF54L15
BLE 广播软件安装
对于此示例,您需要在手机上下载官方蓝牙测试应用 nRF Connect。

将程序烧录到 XIAO nRF52840 Sense 开发板后,您可以打开 nRF Connect 应用的主页面与其交互。
-
步骤 1:在 nRF Connect 应用中,点击右上角的扫描按钮开始扫描蓝牙设备。
-
步骤 2:接下来,在"名称"字段中输入您的 XIAO nRF52840 Sense 设备名称。这将帮助您过滤并快速定位您的设备。
-
步骤 3:在扫描结果区域中,找到您的 XIAO nRF52840 Sense 设备并点击旁边的"连接"按钮。
连接成功后,您将进入设备详情页面。在此页面上,您可以观察不同时间段内的蓝牙信号强度 (RSSI) 分布,这有助于您了解设备连接的稳定性。
![]() | ![]() |
添加 XIAO nRF54L15 开发板
要将 XIAO nRF52840 Sense 开发板添加到 NCS (nRF Connect SDK),您可以参考 Seeed Studio Wiki 上的"入门指南"。该指南将提供详细的操作说明。
BLE 广播代码
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/gap.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/sys/printk.h>
#include <zephyr/drivers/gpio.h>
#include <zephyr/dt-bindings/gpio/nordic-nrf-gpio.h>
LOG_MODULE_REGISTER(BLE_LowPower, LOG_LEVEL_INF);
#define DEVICE_NAME CONFIG_BT_DEVICE_NAME
#define DEVICE_NAME_LEN (sizeof(DEVICE_NAME) - 1)
static const struct gpio_dt_spec led0 = GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios);
static const struct bt_data ad[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR),
BT_DATA(BT_DATA_NAME_COMPLETE, DEVICE_NAME, DEVICE_NAME_LEN),
};
static unsigned char url_data[] = {
0x17,
'/', '/', 'a', 'c', 'a', 'd', 'e', 'm', 'y', '.',
'n', 'o', 'r', 'd', 'i', 'c', 's', 'e', 'm', 'i', '.',
'c', 'o', 'm'
};
static const struct bt_data sd[] = {
BT_DATA(BT_DATA_URI, url_data, sizeof(url_data)),
};
static bool device_connected = false;
static void connected(struct bt_conn *conn, uint8_t err)
{
if (err) {
LOG_ERR("连接失败 (err 0x%02x)\n", err);
} else {
LOG_INF("设备已连接\n");
device_connected = true;
}
}
static void disconnected(struct bt_conn *conn, uint8_t reason)
{
LOG_INF("设备已断开连接 (reason 0x%02x)\n", reason);
device_connected = false;
int err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
if (err) {
LOG_ERR("重新启动广播失败 (err %d)\n", err);
} else {
LOG_INF("广播成功重新启动 (可连接)\n");
}
}
BT_CONN_CB_DEFINE(conn_callbacks) = {
.connected = connected,
.disconnected = disconnected,
};
int main(void)
{
int err;
if (!gpio_is_ready_dt(&led0)) {
LOG_ERR("错误: LED设备 %s 未就绪\n", led0.port->name);
return -1;
}
err = gpio_pin_configure_dt(&led0, GPIO_OUTPUT_INACTIVE);
if (err) {
LOG_ERR("错误: 配置LED引脚 %d 失败 (err %d)\n", led0.pin, err);
return -1;
}
LOG_INF("LED已配置,初始状态为关闭。");
err = bt_enable(NULL);
if (err) {
LOG_ERR("蓝牙初始化失败 (err %d)\n", err);
return -1;
}
LOG_INF("蓝牙已初始化\n");
err = bt_le_adv_start(BT_LE_ADV_CONN, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
if (err) {
LOG_ERR("广播启动失败 (err %d)\n", err);
return -1;
}
LOG_INF("广播成功启动 (可连接)\n");
while (1) {
if (device_connected) {
gpio_pin_toggle_dt(&led0);
k_sleep(K_MSEC(500));
} else {
gpio_pin_set_dt(&led0, 0);
k_sleep(K_MSEC(1000));
}
}
return 0;
}
PlatformIO
这个蓝牙无线电示例程序专门为在 PlatformIO 平台上开发而设计。选择 PlatformIO 的主要优势在于它提供了一个集成开发环境,大大简化了嵌入式项目的设置、编译和烧录过程,使得即使是初学者也能更轻松、更快速地开始开发蓝牙应用程序。
BLE 广播代码
#include <stdio.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <zephyr/bluetooth/hci.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/bluetooth/gatt.h>
#define BT_UUID_ONOFF_VAL BT_UUID_128_ENCODE(0x8e7f1a23, 0x4b2c, 0x11ee, 0xbe56, 0x0242ac120002)
#define BT_UUID_ONOFF BT_UUID_DECLARE_128(BT_UUID_ONOFF_VAL)
#define BT_UUID_ONOFF_ACTION_VAL \
BT_UUID_128_ENCODE(0x8e7f1a24, 0x4b2c, 0x11ee, 0xbe56, 0x0242ac120002)
#define BT_UUID_ONOFF_ACTION BT_UUID_DECLARE_128(BT_UUID_ONOFF_ACTION_VAL)
#define BT_UUID_ONOFF_READ_VAL \
BT_UUID_128_ENCODE(0x8e7f1a25, 0x4b2c, 0x11ee, 0xbe56, 0x0242ac120003)
#define BT_UUID_ONOFF_READ BT_UUID_DECLARE_128(BT_UUID_ONOFF_READ_VAL)
static uint8_t onoff_flag = 0;
static const struct bt_data ad[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1),
};
static const struct bt_data sd[] = {
BT_DATA_BYTES(BT_DATA_UUID128_ALL, BT_UUID_ONOFF_VAL),
};
static ssize_t read_onoff_val(struct bt_conn *conn, const struct bt_gatt_attr *attr,
void *buf, uint16_t len, uint16_t offset)
{
const uint8_t *value = attr->user_data;
return bt_gatt_attr_read(conn, attr, buf, len, offset, value, sizeof(*value));
}
static ssize_t write_onoff_val(struct bt_conn *conn, const struct bt_gatt_attr *attr,
const void *buf, uint16_t len, uint16_t offset, uint8_t flags)
{
uint8_t val;
if (len != 1U) {
return BT_GATT_ERR(BT_ATT_ERR_INVALID_ATTRIBUTE_LEN);
}
if (offset != 0) {
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
}
val = *((uint8_t *)buf);
if (val == 0x00U) {
printf("写入: 0\n");
onoff_flag = 0;
} else if (val == 0x01U) {
printf("写入: 1\n");
onoff_flag = 1;
} else {
return BT_GATT_ERR(BT_ATT_ERR_VALUE_NOT_ALLOWED);
}
return len;
}
BT_GATT_SERVICE_DEFINE(lbs_svc,
BT_GATT_PRIMARY_SERVICE(BT_UUID_ONOFF),
BT_GATT_CHARACTERISTIC(BT_UUID_ONOFF_ACTION, BT_GATT_CHRC_WRITE,
BT_GATT_PERM_WRITE, NULL, write_onoff_val, NULL),
BT_GATT_CHARACTERISTIC(BT_UUID_ONOFF_READ, BT_GATT_CHRC_READ,
BT_GATT_PERM_READ, read_onoff_val, NULL, &onoff_flag),
);
static void connected(struct bt_conn *conn, uint8_t err)
{
if (err != 0U) {
printf("连接失败 (%02x, %s)\n", err, bt_hci_err_to_str(err));
return;
}
printf("已连接\n");
}
static void disconnected(struct bt_conn *conn, uint8_t reason)
{
printf("已断开连接 (%02x, %s)\n", reason, bt_hci_err_to_str(reason));
}
BT_CONN_CB_DEFINE(conn_callbacks) = {
.connected = connected,
.disconnected = disconnected,
};
int main(void)
{
int err;
err = bt_enable(NULL);
if (err < 0) {
printf("蓝牙启用失败 (err %d)", err);
return err;
}
err = bt_le_adv_start(BT_LE_ADV_CONN_FAST_1, ad, ARRAY_SIZE(ad), sd, ARRAY_SIZE(sd));
if (err < 0) {
printf("广播启动失败 (err %d)", err);
return err;
}
printf("蓝牙已启用");
return 0;
}
技术支持与产品讨论
感谢您选择我们的产品!我们在这里为您提供不同的支持,以确保您使用我们产品的体验尽可能顺畅。我们提供多种沟通渠道,以满足不同的偏好和需求。