Skip to content

概述

BLE(Bluetooth Low Energy,低功耗蓝牙,蓝牙技术里专为省电设计的版本:功耗低、连接快、只传小数据)是物联网设备最常用的近距离无线通信方式。Ai-WB2 模组内置 BLE 4.2 蓝牙协议栈,可同时与 Wi-Fi 工作:Wi-Fi 负责大流量联网,BLE 负责轻量连接。本页是 BLE 系列的概念篇,先讲清楚 BLE 世界里的「角色」和「规矩」,为后面的动手教程打基础;本系列共 5 篇,从本页开始,依次为 iBeacon 广播 → BLE 主机 → BLE 从机 → blufi 配网

用大白话讲:BLE 就像一个小巧省电的「信使」。普通蓝牙像大功率广播站,费电、能传大文件;BLE 像低声细语的信使,省电、只传小数据。通信过程像「交朋友」:一方先广播(像大喇叭喊话:「我在这里!」),另一方扫描听到后过来连接,连上之后双方按约定的规矩(GATT)互相递纸条。你的手环、耳机、遥控器用的都是这套流程。

本教程基于安信可官方 SDKAi-Thinker-Open/Ai-Thinker-WB2,版本 release_bl_iot_sdk_1.6.40),本系列全部示例来自官方 applications/bluetooth/ 目录,代码可在本地 SDK 中直接找到。

🎯本页目标建立 BLE 的整体概念框架:角色分工、广播与扫描、GATT 服务与特征值、UUID 与 MAC 地址,为后续动手教程打基础。
🧰前置条件① Ai-WB2 开发板一块(后续动手篇使用)② 已按 [SDK 安装](../sdk/sdk_intro) 完成开发环境搭建。
🔗相关章节本系列动手篇:[iBeacon 广播](./ibeacon)、[BLE 主机](./ble_master)、[BLE 从机](./ble_slave)、[blufi 配网](./blufi)。

认识 BLE:低功耗蓝牙
  1. BLE(Bluetooth Low Energy,低功耗蓝牙)是蓝牙技术里专为省电设计的版本:连接快、功耗低、只传小数据。你的手机、手环、耳机用的就是它。
  2. 与普通「经典蓝牙」(传音频/文件,费电)相比,BLE 就像「低声细语的信使」:跑腿少、耗电小,特别适合传感器、遥控器这类用电池的小设备。

💡 Ai-WB2 的 Wi-Fi 和 BLE 可以同时工作、互不干扰:Wi-Fi 负责大流量联网,BLE 负责轻量连接(比如下面的配网)。

认识角色分工:主机与从机

BLE 世界里有两个角色,一台设备只能担任其中一个:

  • 主机(Master):主动的一方,负责扫描(寻找)别人并发起连接——就像拿着手机「找朋友」的你。
  • 从机(Slave):被动的一方,一直广播等别人来连接——就像站在路边举着「欢迎光临」招牌的店员。
角色 大白话 谁当它
主机 Master 主动扫描连接的「手机」 手机、电脑
从机 Slave 被动等待连接的「手环」 手环、传感器、Ai-WB2

💡 同一块 Ai-WB2 可以烧不同固件扮演不同角色:BLE 主机 教程让它当主机,BLE 从机 教程让它当从机。

认识广播与扫描
  1. 广播(Advertising):从机间隔一定时间向外发送一小包数据(含设备名、MAC 地址、自定义内容),就像大喇叭喊话:「我在这里,我是 XX!」。广播不建立连接,谁都能听到。
  2. 扫描(Scanning):主机打开「耳朵」听周围谁在喊话,拿到广播内容后决定要不要过来连接。

💡 iBeacon(苹果推出的蓝牙信标方案)就只广播不连接,像路边广告牌——路人看得到内容,但不用和它「握手」。本系列 iBeacon 教程 会亲手实现它。

认识 GATT:服务与特征值
  1. GATT(Generic Attribute Profile)是蓝牙设备之间通信的「规矩」:规定数据怎么组织、怎么读写。BLE 设备连上后,就按这套规矩交换数据。
  2. GATT 里的数据按层级组织,像「App 里的应用 → 按钮」:
    • 服务 Service:一个功能模块(如「心率服务」「电池服务」),相当于手机里的一个 App。
    • 特征值 Characteristic:服务里的具体开关或数据(如「心率数值」「电量百分比」),相当于 App 里的一个按钮或文本框。
  3. 和某台设备通信的步骤就是:找到它有哪些服务 → 找到服务里的特征值 → 读写特征值。就像先打开 App,再点里面的按钮。

💡 本系列 BLE 从机 教程会注册一个自定义服务,用手机 App 读写它的特征值,体会这套「规矩」。

认识 UUID 与 MAC 地址
  1. UUID(Universally Unique Identifier,通用唯一标识符):蓝牙世界的「身份证号」,16 字节,写作 B9407F30-F5F8-466E-AFF9-25556B57FE6D 这种格式,用来唯一标识某个服务或特征值。
  2. MAC 地址:每台蓝牙设备的「门牌号」(6 字节,如 88:88:88:88:88:88),主机靠它找到并连接特定设备。
名词 大白话 干什么用
UUID 身份证号 标识服务/特征值,告诉别人「这个数据是什么」
MAC 地址 门牌号 标识设备,告诉别人「我是哪台设备」
认识本系列动手路线

概念就位,接下来 4 篇全部动手(顺序即侧边栏顺序):

  • iBeacon 广播:让开发板化身「路边广告牌」,只广播不连接
  • BLE 主机:开发板当「手机」,主动扫描连接从机并双向透传数据
  • BLE 从机:开发板当「手环」,提供透传服务,等手机/主机来连接
  • blufi 配网:用手机 App 通过蓝牙给开发板「录入」Wi-Fi 账号密码(配网,把 Wi-Fi 账号密码发给设备的过程,像给门锁录入指纹)

📜 想看「一个 BLE 程序长什么样」?文末 完整代码 预览了官方 iBeacon 示例的入口代码,逐行讲解见 iBeacon 教程


本文 API 汇总

本页为概念篇,未运行任何代码;下面预览本系列动手教程即将用到的核心 BLE API(签名与官方 SDK 头文件一致,详细讲解见各篇):

bl_sys_init

初始化系统时钟、外设等基础资源,使用 BLE 前必须先调用(官方示例 main() 的第一件事)。

返回值:成功返回 0;失败返回负值错误码

ble_controller_init(task_priority)

初始化 BLE 协议栈(蓝牙通信的「大脑」),是 BLE 代码的第一步。

参数

  • task_priority:协议栈任务优先级(uint8_t),官方示例传 configMAX_PRIORITIES - 1(最高优先级)

返回值:无

bt_enable(cb)

打开蓝牙协议栈,相当于手机「打开蓝牙开关」。

参数

  • cb:协议栈就绪回调(bt_ready_cb_t),形如 void cb(int err),不需要可传 NULL

返回值:成功返回 0;失败返回负值错误码

bt_set_name(name)

设置蓝牙设备名称,手机搜索列表里显示的就是它。

参数

  • name:设备名字符串,必填(如 "MY_IBEACON"

返回值:成功返回 0;失败返回负值错误码

bt_le_adv_start(param, ad, ad_len, sd, sd_len)

开始 BLE 广播(「大喇叭喊话」),广播数据由 ad 数组指定。

参数

  • param:广播参数结构体指针(bt_le_adv_param_t),含广播间隔、可连接选项等
  • ad:广播数据数组(bt_data_t),必填
  • ad_len:广播数据条数
  • sd:扫描应答数据数组,不需要传 NULL
  • sd_len:扫描应答数据条数,传 0

返回值:成功返回 0;失败返回负值错误码


完整代码

本页为概念介绍页,本身没有示例工程;这里预览官方 iBeacon 示例工程main.c 入口代码,与官方示例(applications/bluetooth/ble_ibeacon/ble_ibeacon/main.c)完全一致,让你对「一个 BLE 程序长什么样」有直观印象,逐行讲解见 iBeacon 教程

📜 点击展开 iBeacon 示例 main.c 完整代码(预览)
c
/*
 * Copyright (c) 2020 Bouffalolab.
 *
 * This file is part of
 *     *** Bouffalolab Software Dev Kit ***
 *      (see www.bouffalolab.com).
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *   1. Redistributions of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 *   2. Redistributions in binary form must reproduce the above copyright notice,
 *      this list of conditions and the following disclaimer in the documentation
 *      and/or other materials provided with the distribution.
 *   3. Neither the name of Bouffalo Lab nor the names of its contributors
 *      may be used to endorse or promote products derived from this software
 *      without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
#include <stdio.h>
#include <string.h>
#include <FreeRTOS.h>
#include <task.h>
#include <blog.h>
#include <stdio.h>
#include <cli.h>
#include <blog.h>
#include <bl_uart.h>
#include <bl_sys.h>
#include "hci_driver.h"
#include "ble_lib_api.h"
#include "bluetooth.h"
#include "gatt.h"
#include "uuid.h"
#include <hosal_uart.h>
#define PRIORITIE_OFFSET    4
/*set ibeacon name*/
#define IBEACON_NAME "MY_IBEACON"

/*ibeacon data*/
char my_ibeacon[]=
{
    0x4C, 0x00, //公司的标志 (0x004C == Apple)
	0x02, 0x15, //iBeacon advertisement indicator
	0xB9, 0x40, 0x7F, 0x30, 0xF5, 0xF8, 0x46, 0x6E, 0xAF, 0xF9, 0x25, 0x55, 0x6B, 0x57, 0xFE, 0x6D, // iBeacon proximity uuid
	0x00, 0x01, // major 
	0x00, 0x01, // minor 
	0xc5 //power
};

static struct bt_data ibeacon_data[2] = 
{
	BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
    BT_DATA(BT_DATA_MANUFACTURER_DATA, my_ibeacon, sizeof(my_ibeacon)),//
};

/*start ble advertise*/
void ble_start_advertise(void)
{
    struct bt_le_adv_param param;
    param.id = BT_ID_DEFAULT;
    param.interval_min = BT_GAP_ADV_FAST_INT_MIN_2;
    param.interval_max = BT_GAP_ADV_FAST_INT_MAX_2;
    //param.options =  BT_LE_ADV_OPT_USE_NAME | BT_LE_ADV_OPT_ONE_TIME;
    param.options = BT_LE_ADV_OPT_CONNECTABLE | BT_LE_ADV_OPT_USE_NAME | BT_LE_ADV_OPT_ONE_TIME;
    /*Get mode, 0:General discoverable,  1:non discoverable, 2:limit discoverable*/
    bt_le_adv_start(&param,ibeacon_data, ARRAY_SIZE(ibeacon_data),NULL,0);
    bt_set_name(IBEACON_NAME);
}

/*BLE ibeacon init*/
void ble_ibeacon_init(void)
{               
    printf("ble_controller_init\r\n");                                         
    ble_controller_init(configMAX_PRIORITIES - 1); //ble协议栈初始化
    printf("hci_driver_init\r\n");
    hci_driver_init();//初始化驱动
    printf("bt_enable\r\n");
    bt_enable(NULL);
    ble_start_advertise();//开启广播
}

static void app_init_thread(void *param)
{
    vTaskDelay(10 / portTICK_RATE_MS);
    ble_ibeacon_init();
    vTaskDelete(NULL);
}

static void app_init_entry(void)
{
    if(xTaskCreate(app_init_thread, ((const char*)"app_init"), 1024*6, NULL, tskIDLE_PRIORITY + 3 + PRIORITIE_OFFSET, NULL) != pdPASS)
    printf("\n\r%s xTaskCreate(init_thread) failed", __FUNCTION__);
}

static void ble_loop_proc(void *pvParameters)
{
    app_init_entry();
    vTaskDelete(NULL);
}

void main(void)
{
    bl_uart_init(0, 16, 7, 255, 255, 115200);//set uart baud 115200
    printf("AXK BLE IBEACON\r\n");//log
    bl_sys_init(); //if use ble,must init
    xTaskCreate(ble_loop_proc,  (char*)"ibeacon", 1024, NULL, 15, NULL);
}

常见问题与踩坑提示

⚠️ BLE 和普通蓝牙有什么区别
原因:两者虽然都叫蓝牙,但用途不同
解决:BLE(低功耗蓝牙)省电、连接快、只传小数据,适合传感器/手环;经典蓝牙耗电大,适合音频、文件传输。Ai-WB2 内置的是 BLE 4.2

⚠️ 手机搜不到开发板广播的设备
原因:广播没开启、距离太远,或手机蓝牙/定位权限没开
解决:确认程序调用了 bt_le_adv_start();Android 手机搜索 BLE 设备需要开启「定位权限」;把手机靠近开发板(0.5~5 米内)再扫

⚠️ BLE 传数据快吗?一次能传多少
原因:BLE 为省电牺牲了速率
解决:BLE 4.2 理论速率约 1Mbps,单次「通知」通常几十字节,适合传感器读数、遥控指令这类小数据;传大文件请用 Wi-Fi

⚠️ 我的设备该当主机还是从机
原因:角色取决于「谁主动」
解决:需要主动连接别人(如手机 App 连手环)就当主机;需要一直广播等别人来连(如手环、传感器、电子价签)就当从机

⚠️ 配网是什么?为什么要用蓝牙配网
原因:设备没有屏幕和键盘,输不了 Wi-Fi 密码
解决配网就是把 Wi-Fi 账号密码发给设备的过程,像给门锁录入指纹。用 BLE 配网不用额外硬件,手机 App 直接连上设备把密码「递」过去,本系列 blufi 配网 教程就是干这个的

运行自检

本页为概念篇,无需编译运行代码。能用自己的话讲清「主机/从机、广播、GATT(服务/特征值)、UUID、MAC 地址」五个概念,并能说出本系列 4 篇动手教程分别做什么,即为通过。

遇到问题?

如有其他问题,请到统一的提问与讨论区:Ai-Thinker Discussions

Released under the MIT License. Build Time 2026-09-11 14:52:23