tags: [source-summary] type: source source: "尚硅谷嵌入式技术之STM32单片机(高级篇)V2.0.1 — BLE章节 + 配套代码12" author: "尚硅谷研究院" date: 2026-07-15
用生活理解:BLE 就像一台"静音待机"的对讲机——平时完全关闭喇叭省电(休眠),每隔几秒悄悄喊一声"我在这呢"(广播)。当有人听到广播后说"跟我连个线吧"(连接请求),通信就建立起来了。连上之后也不是一直说,而是每隔 30ms 说一句(连接间隔),不说话时极低功耗。
| 特性 | 经典蓝牙 (BR/EDR) | BLE (Bluetooth Low Energy) |
|---|---|---|
| 功耗 | ~1W(持续发送) | ~0.01W(广播时 5~10mA,休眠时 μA 级) |
| 峰值速率 | 1~3 Mbps | 125Kbps~2Mbps |
| 连接延迟 | ~100ms | ~3ms |
| 数据包 | 长包(可达 339 字节) | 短包(最大 251 字节 ATT MTU) |
| 信道 | 79 个 1MHz 信道 | 40 个 2MHz 信道(3 个广播 + 37 个数据) |
| 语音 | 支持(SCO 链路) | 不支持(需通过协议栈上层实现) |
| 主要应用 | 音频流、文件传输 | IoT、传感器、可穿戴设备 |
BLE 和经典蓝牙工作在相同 2.4GHz ISM 频段,但调制方式和信道划分不同,互不兼容。
Application(应用层)
↓
GAP (Generic Access Profile) — 广播、扫描、连接、角色
GATT (Generic Attribute Profile) — 数据读写、服务/特征值结构
↓
ATT (Attribute Protocol) — 属性读/写/通知/指示
L2CAP (Logical Link Control and Adaptation Protocol) — 数据分包/重组
↓
HCI (Host Controller Interface) — 主机与控制器通信接口
↓
Link Layer (链路层) — 广播/数据信道管理、加密
Physical Layer (物理层) — 2.4GHz GFSK 调制
| GAP 角色 | 行为 | 典型设备 |
|---|---|---|
| Broadcaster | 只发广播(不能连) | 信标(Beacon) |
| Observer | 只扫描广播(不连) | 扫描仪 |
| Peripheral | 广播 + 接受连接 | 传感器节点 |
| Central | 扫描 + 发起连接 | 手机、网关 |
典型连接流程:
Peripheral 广播 → Central 扫描到 → Central 发起连接请求
→ 连接建立 → 双方按连接间隔周期性交互数据 → 一方断开
BLE 的数据按以下层级组织:
Service (服务) 如 "心率服务" UUID: 0x180D
├── Characteristic 如 "心率测量" UUID: 0x2A37
│ ├── Properties read / write / notify / indicate
│ ├── Value 实际数据(心率值)
│ └── Descriptor 配置描述(如 CCCD 使能 notify)
└── Characteristic
├── ...
UUID(唯一标识符):
GATT 角色:
STM32 通过串口连接 BLE 透传模块(支持 AT 指令),实现 BLE 数据收发。
项目路径:stm32/12_ble_server_hal
// BLE 模块初始化(Peripheral 模式 + 广播)
void BLE_Init(void)
{
// 1. 设置为 Peripheral(从机)模式
AT_SendCmd("AT+BLEINIT=2\r\n", "OK", 2000);
// AT+BLEINIT: 0=关闭BLE, 1=Central, 2=Peripheral
// 2. 设置设备名称(广播时显示)
AT_SendCmd("AT+BLENAME=\"STM32_BLE_Device\"\r\n", "OK", 1000);
// 3. 设置广播间隔(单位 0.625ms,默认 100 = 62.5ms)
AT_SendCmd("AT+BADVINT=100\r\n", "OK", 1000);
// 值越小 → 被发现越快 → 功耗越高
// 4. 设置广播数据(自定义数据)
AT_SendCmd("AT+BLEADVDATA=\"020106\"\r\n", "OK", 1000);
// 02=长度, 01=标志类型, 06=LE General Discoverable + BR/EDR Not Support
// 5. 启动广播
AT_SendCmd("AT+BLEADVSTART\r\n", "OK", 2000);
printf("BLE 广播中...\r\n");
}
// 发送数据(通过 GATT 通知)
void BLE_SendData(uint8_t *data, uint16_t len)
{
char cmd[64];
// 格式: AT+BLESEND=conn_id,len\r\n
// 之后发送 len 字节的数据
sprintf(cmd, "AT+BLESEND=0,%d\r\n", len);
AT_SendCmd(cmd, ">", 3000);
// 发送实际数据
HAL_UART_Transmit(&huart2, data, len, 1000);
}
// BLE 数据接收(串口主动上报)
// 当手机发送数据给 STM32 时,BLE 模块通过串口上报:
// +BLEDATA: conn_id,len,data
void BLE_ProcessRxData(uint8_t *buffer, uint16_t len)
{
if (strstr((char *)buffer, "+BLEDATA:"))
{
// 解析数据并处理
char *data_ptr = strstr((char *)buffer, ",");
if (data_ptr)
{
data_ptr = strstr(data_ptr + 1, ",");
if (data_ptr)
{
data_ptr++; // 跳过逗号,指向实际数据
printf("Received BLE: %s\r\n", data_ptr);
}
}
}
}
| BLE 操作 | AT 指令 | 说明 |
|---|---|---|
| 初始化(Peripheral) | AT+BLEINIT=2 |
2=从机模式 |
| 初始化(Central) | AT+BLEINIT=1 |
1=主机模式 |
| 设置名称 | AT+BLENAME="name" |
最长 29 字节 |
| 设置广播间隔 | AT+BADVINT=N |
N×0.625ms,默认 100 (62.5ms) |
| 设置广播数据 | AT+BLEADVDATA="hex" |
16 进制字符串 |
| 开始广播 | AT+BLEADVSTART |
Peripheral 模式 |
| 停止广播 | AT+BLEADVSTOP |
— |
| 发送数据 | AT+BLESEND=conn,len → 数据 |
— |
| 查询连接状态 | AT+BLECONN? |
返回当前连接 |
| 断开连接 | AT+BLEDISCONN=n |
n=连接 ID |
| 扫描设备 | AT+BLESCAN=0 |
0=被动扫描 |
AT+BLEADVSTART