Skip to main content

Seeed Studio XIAO nRF54L15 Sense BLE 使用指南

nRF Connect SDK

本蓝牙广播教程基于官方示例代码,经过修改后可在 Nordic Connect SDK 上运行。结合我们的开发板和官方文档,您可以深入了解更多蓝牙应用

当手机未连接到 XIAO nRF54L15 时,板载指示灯将保持常亮。一旦手机成功连接,指示灯将开始闪烁,表示已建立连接。

XIAO nRF54L15 Ultra-low Power Consumption in System Off Mode

手机连接 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;
}

技术支持与产品讨论

感谢您选择我们的产品!我们在这里为您提供不同的支持,以确保您使用我们产品的体验尽可能顺畅。我们提供多种沟通渠道,以满足不同的偏好和需求。

Loading Comments...