基于Arduino平台和ESP-IDF平台ESP8684 (ESP32C2) 蓝牙通讯协议开发详解
·
ESP8684 (ESP32C2) 蓝牙通讯协议开发详解
技术文章大纲:基于Arduino与ESP-IDF平台的ESP8684(ESP32-C2)蓝牙通信协议开发详解
一、引言
ESP8684是乐鑫推出的一款低功耗Wi-Fi+蓝牙双模SoC,基于ESP8684芯片设计,集成了完整的Wi-Fi 4和蓝牙5.0 BR/EDR + BLE功能。本文将详细介绍如何基于ESP32C2芯片上使用Arduino和ESP-IDF开发框架进行蓝牙通信协议的开发,包括经典蓝牙(BR/EDR)和低功耗蓝牙(BLE)两种模式。
二、ESP8684 (ESP32C2) 平台概述
2.1 芯片特点
- 内核:RISC-V 32位单核处理器,主频最高120MHz
- 蓝牙功能:
- 支持蓝牙5.0 BR/EDR (经典蓝牙)
- 支持蓝牙5.0 BLE (低功耗蓝牙)
- 支持BLE 2Mbps高速模式
- 支持长距离模式(LE Coded PHY)
硬件与平台概述
- ESP8684(ESP32-C2)芯片特性
低功耗Wi-Fi/蓝牙双模SoC,支持BLE 5.0,32位RISC-V内核,外设资源(GPIO、ADC等)。 - 开发平台对比
Arduino平台:快速原型开发,库支持丰富;ESP-IDF平台:官方底层控制,灵活性高。
开发环境搭建
- Arduino平台配置
安装ESP32-Arduino核心板支持包,配置开发板管理器,选择ESP32-C2开发板。 - ESP-IDF平台配置
安装工具链(Windows/Linux/macOS),配置VS Code插件,创建项目模板。
蓝牙协议栈基础
- BLE协议架构
GAP(通用访问协议)角色(Central/Peripheral),GATT(属性协议)服务与特征。 - 关键概念
UUID、广播数据、连接参数、MTU协商。
Arduino平台蓝牙开发实践
- BLE外设模式实现
使用NimBLE库创建服务与特征,示例代码:数据发送与接收回调。 - BLE中心设备模式实现
扫描周边设备,连接并读写特征值,处理通知(Notify/Indicate)。
ESP-IDF平台蓝牙开发实践
- 基于Bluetooth Controller的底层配置
初始化蓝牙控制器,设置PHY层参数(1M/2M/Coded PHY)。 - GATT服务端开发
注册自定义服务,实现特征权限(读/写/通知),事件回调处理。 - 低功耗优化
调整连接间隔(Connection Interval),休眠模式配置(Light/Deep Sleep)。
双平台功能对比与性能测试
- 开发效率对比
Arduino库封装程度高,ESP-IDF提供更细粒度控制。 - 功耗与吞吐量测试
实测广播模式/连接状态下的电流消耗,数据传输速率(Throughput)。
常见问题与调试技巧
- 连接稳定性问题
干扰排查(信道选择),电源噪声抑制。 - 日志分析工具
Arduino串口调试,ESP-IDF的idf.py monitor与Wireshark抓包。
进阶应用方向
- 蓝牙Mesh组网
ESP-IDF的mesh协议栈配置,节点角色(Provisioner/Node)。 - 安全机制
配对加密(LE Secure Connections),防重放攻击(Replay Protection)。
参考资料
- 官方文档:Espressif ESP-IDF编程指南、Arduino-ESP32库文档。
- 开源项目:ESP32-BLE示例仓库、社区案例(GitHub)。
注:实际开发需结合具体硬件型号(如ESP32-C3与ESP32-C2差异)调整代码实现。
- 内存:320KB SRAM,内置4MB Flash
- 电源管理:支持多种低功耗模式,功耗低至1μA
2.2 蓝牙架构
ESP32C2的蓝牙子系统采用了分层架构:
- 控制器层:负责物理层(PHY)和链路层(LL)的实现
- 主机层:实现蓝牙核心协议栈,包括L2CAP、SDP、GAP、GATT等
- 应用层:用户开发的应用程序,通过API与主机层交互
三、Arduino平台蓝牙开发
3.1 开发环境搭建
-
安装Arduino IDE:下载并安装最新版本的Arduino IDE
-
添加ESP32开发板支持:
- 打开Arduino IDE,进入"文件"->“首选项”
- 在"附加开发板管理器网址"中添加:
https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json - 点击"工具"->“开发板”->“开发板管理器”
- 搜索"esp32",安装"ESP32 Arduino"开发板包
-
选择开发板:
- 点击"工具"->“开发板”->“ESP32 Arduino”
- 选择"ESP32C2 Dev Module"
- 配置端口、上传速度等参数
3.2 经典蓝牙(BR/EDR)开发
3.2.1 基本概念
经典蓝牙主要用于传输音频、文件等大数据量应用,支持SPP(串行端口协议)、A2DP(音频传输)、HFP(免提协议)等 profile。
3.2.2 SPP服务示例
以下是一个简单的SPP服务示例,实现蓝牙串口通信:
#include <BluetoothSerial.h>
BluetoothSerial SerialBT;
void setup() {
Serial.begin(115200);
SerialBT.begin("ESP8684_SPP"); // 设置蓝牙设备名称
Serial.println("蓝牙串口服务已启动,等待连接...");
}
void loop() {
if (Serial.available()) {
SerialBT.write(Serial.read());
}
if (SerialBT.available()) {
Serial.write(SerialBT.read());
}
delay(20);
}
3.2.3 代码解析
- 包含
BluetoothSerial.h库,提供经典蓝牙功能 BluetoothSerial SerialBT创建蓝牙串口对象SerialBT.begin("ESP8684_SPP")初始化蓝牙服务,设置设备名称- 通过
Serial和SerialBT之间的数据转发实现串口透传功能
3.3 BLE开发
3.3.1 基本概念
BLE(Bluetooth Low Energy)低功耗蓝牙,主要用于低功耗、小数据量的应用场景,采用GATT(通用属性协议)架构。
BLE的核心概念:
- Service(服务):包含多个Characteristic的集合
- Characteristic(特征):包含一个值和多个描述符
- Descriptor(描述符):提供Characteristic的额外信息
3.3.2 BLE服务器示例
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
// 定义服务和特征UUID
#define SERVICE_UUID "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"
BLEServer *pServer = NULL;
BLECharacteristic *pCharacteristic = NULL;
bool deviceConnected = false;
uint32_t value = 0;
class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
Serial.println("设备已连接");
};
void onDisconnect(BLEServer* pServer) {
deviceConnected = false;
Serial.println("设备已断开连接");
// 重启广告以便重新连接
BLEAdvertising *pAdvertising = pServer->getAdvertising();
pAdvertising->start();
}
};
class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string value = pCharacteristic->getValue();
if (value.length() > 0) {
Serial.println("收到数据:");
for (int i = 0; i < value.length(); i++) {
Serial.print(value[i]);
}
Serial.println();
}
}
};
void setup() {
Serial.begin(115200);
Serial.println("初始化BLE服务...");
// 创建BLE设备
BLEDevice::init("ESP8684_BLE");
// 创建BLE服务器
pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());
// 创建BLE服务
BLEService *pService = pServer->createService(SERVICE_UUID);
// 创建BLE特征
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_READ |
BLECharacteristic::PROPERTY_WRITE |
BLECharacteristic::PROPERTY_NOTIFY |
BLECharacteristic::PROPERTY_INDICATE
);
// 添加描述符
pCharacteristic->addDescriptor(new BLE2902());
pCharacteristic->setCallbacks(new MyCallbacks());
// 设置初始值
pCharacteristic->setValue("Hello BLE");
// 启动服务
pService->start();
// 启动广告
BLEAdvertising *pAdvertising = BLEDevice::getAdvertising();
pAdvertising->addServiceUUID(SERVICE_UUID);
pAdvertising->setScanResponse(true);
pAdvertising->setMinPreferred(0x06); // 功率级别
pAdvertising->setMinPreferred(0x12);
BLEDevice::startAdvertising();
Serial.println("BLE服务已启动,等待连接...");
}
void loop() {
if (deviceConnected) {
// 更新特征值并发送通知
pCharacteristic->setValue((uint8_t*)&value, 4);
pCharacteristic->notify();
value++;
delay(1000);
}
}
3.3.3 代码解析
- 包含BLE相关库文件
- 定义服务和特征UUID
- 创建BLE服务器并设置连接回调
- 创建可读写并支持通知的特征
- 实现数据接收和发送逻辑
四、ESP-IDF平台蓝牙开发
4.1 经典蓝牙开发
4.1.1 配置menuconfig
idf.py menuconfig
在menuconfig中配置:
Component config->Bluetooth-> 启用Classic BluetoothComponent config->Bluetooth Serial Port Profile (SPP)-> 启用SPP服务
4.1.2 示例代码
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "bt.h"
#include "bta_api.h"
#include "esp_spp_api.h"
static const char TAG[] = "ESP_SPP_EXAMPLE";
#define SPP_SERVER_NAME "ESP8684 SPP Server"
#define EXAMPLE_DEVICE_NAME "ESP8684_BT"
static void esp_spp_cb(esp_spp_cb_event_t event, esp_spp_cb_param_t *param)
{
switch (event) {
case ESP_SPP_INIT_EVT:
ESP_LOGI(TAG, "ESP_SPP_INIT_EVT");
esp_spp_start_srv(ESP_SPP_SEC_AUTHENTICATE, ESP_SPP_ROLE_SLAVE, 0, SPP_SERVER_NAME);
break;
case ESP_SPP_OPEN_EVT:
ESP_LOGI(TAG, "ESP_SPP_OPEN_EVT");
break;
case ESP_SPP_DATA_IND_EVT:
ESP_LOGI(TAG, "ESP_SPP_DATA_IND_EVT len=%d handle=%d",
param->data_ind.len, param->data_ind.handle);
esp_log_buffer_hex(TAG, param->data_ind.data, param->data_ind.len);
// 回显收到的数据
esp_spp_write(param->data_ind.handle, param->data_ind.len, param->data_ind.data);
break;
case ESP_SPP_CLOSE_EVT:
ESP_LOGI(TAG, "ESP_SPP_CLOSE_EVT");
break;
default:
break;
}
}
void app_main(void)
{
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
ESP_LOGI(TAG, "BT Init");
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
if ((ret = esp_bt_controller_init(&bt_cfg)) != ESP_OK) {
ESP_LOGE(TAG, "%s initialize controller failed: %s", __func__, esp_err_to_name(ret));
return;
}
if ((ret = esp_bt_controller_enable(ESP_BT_MODE_CLASSIC_BT)) != ESP_OK) {
ESP_LOGE(TAG, "%s enable controller failed: %s", __func__, esp_err_to_name(ret));
return;
}
if ((ret = esp_bluedroid_init()) != ESP_OK) {
ESP_LOGE(TAG, "%s initialize bluedroid failed: %s", __func__, esp_err_to_name(ret));
return;
}
if ((ret = esp_bluedroid_enable()) != ESP_OK) {
ESP_LOGE(TAG, "%s enable bluedroid failed: %s", __func__, esp_err_to_name(ret));
return;
}
if ((ret = esp_spp_register_callback(esp_spp_cb)) != ESP_OK) {
ESP_LOGE(TAG, "%s spp register failed: %s", __func__, esp_err_to_name(ret));
return;
}
if ((ret = esp_spp_init(ESP_SPP_MODE_CB)) != ESP_OK) {
ESP_LOGE(TAG, "%s spp init failed: %s", __func__, esp_err_to_name(ret));
return;
}
esp_bt_dev_set_device_name(EXAMPLE_DEVICE_NAME);
esp_bt_gap_set_scan_mode(ESP_BT_CONNECTABLE, ESP_BT_GENERAL_DISCOVERABLE);
}
4.1.3 代码解析
- 初始化NVS Flash
- 配置和启用蓝牙控制器
- 初始化和启用Bluedroid协议栈
- 注册SPP回调函数
- 启动SPP服务器
- 实现数据接收和回显功能
4.2 BLE开发
4.2.1 配置menuconfig
idf.py menuconfig
在menuconfig中配置:
Component config->Bluetooth-> 启用Bluetooth和BLEComponent config->Bluetooth->BLE-> 启用所需的BLE功能
4.2.2 BLE服务器示例
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_bt.h"
#include "esp_gap_ble_api.h"
#include "esp_gatts_api.h"
#include "esp_bt_main.h"
#include "esp_gatt_common_api.h"
static const char TAG[] = "ESP_BLE_EXAMPLE";
#define GATTS_SERVICE_UUID_TEST 0x00FF
#define GATTS_CHAR_UUID_TEST 0xFF01
#define GATTS_DESCR_UUID_TEST 0x3333
#define GATTS_NUM_HANDLE_TEST 4
#define TEST_DEVICE_NAME "ESP8684_BLE"
#define TEST_MANUFACTURER_DATA_LEN 17
static uint8_t manufacturer_data[TEST_MANUFACTURER_DATA_LEN] = {
0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89,
0x9a, 0xab, 0xbc, 0xcd, 0xde, 0xef, 0xf0, 0x0f,
0x10
};
static uint16_t handle_table[GATTS_NUM_HANDLE_TEST] = {0};
static esp_gatt_if_t gatt_if = ESP_GATT_IF_NONE;
static esp_gatts_attr_db_t gatt_db[GATTS_NUM_HANDLE_TEST] = {
// 服务声明
[0] = {
.attr_control = ESP_GATT_AUTO_RSP,
.att_desc = {
.uuid_length = ESP_UUID_LEN_16,
.uuid_p = (uint8_t *)&primary_service_uuid,
.perm = 0,
.max_length = sizeof(uint16_t),
.length = sizeof(uint16_t),
.value = (uint8_t *)&GATTS_SERVICE_UUID_TEST,
},
},
// 特征声明
[1] = {
.attr_control = ESP_GATT_AUTO_RSP,
.att_desc = {
.uuid_length = ESP_UUID_LEN_16,
.uuid_p = (uint8_t *)&character_declaration_uuid,
.perm = 0,
.max_length = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY,
.length = ESP_GATT_CHAR_PROP_BIT_READ | ESP_GATT_CHAR_PROP_BIT_WRITE | ESP_GATT_CHAR_PROP_BIT_NOTIFY,
.value = NULL,
},
},
// 特征值
[2] = {
.attr_control = ESP_GATT_AUTO_RSP,
.att_desc = {
.uuid_length = ESP_UUID_LEN_16,
.uuid_p = (uint8_t *)&GATTS_CHAR_UUID_TEST,
.perm = ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED,
.max_length = 4,
.length = 4,
.value = (uint8_t *)"test",
},
},
// 描述符
[3] = {
.attr_control = ESP_GATT_AUTO_RSP,
.att_desc = {
.uuid_length = ESP_UUID_LEN_16,
.uuid_p = (uint8_t *)&character_client_config_uuid,
.perm = ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE,
.max_length = sizeof(uint16_t),
.length = sizeof(uint16_t),
.value = (uint8_t *)&gatts_demo_char2_desc,
},
},
};
static void gatts_event_handler(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, esp_ble_gatts_cb_param_t *param)
{
switch (event) {
case ESP_GATTS_REG_EVT:
ESP_LOGI(TAG, "REG_EVT, status %d, app_id %d, gatts_if %d",
param->reg.status, param->reg.app_id, gatts_if);
gatt_if = gatts_if;
// 创建服务
esp_gatts_create_service(gatts_if, &gatt_db[0].att_desc.uuid, GATTS_NUM_HANDLE_TEST);
break;
case ESP_GATTS_READ_EVT:
ESP_LOGI(TAG, "READ_EVT, conn_id %d, trans_id %d, handle %d",
param->read.conn_id, param->read.trans_id, param->read.handle);
break;
case ESP_GATTS_WRITE_EVT:
ESP_LOGI(TAG, "WRITE_EVT, conn_id %d, trans_id %d, handle %d",
param->write.conn_id, param->write.trans_id, param->write.handle);
if (!param->write.is_prep) {
ESP_LOGI(TAG, "GATT_WRITE_EVT, value len %d, value:", param->write.len);
esp_log_buffer_hex(TAG, param->write.value, param->write.len);
}
break;
case ESP_GATTS_EXEC_WRITE_EVT:
ESP_LOGI(TAG, "EXEC_WRITE_EVT, conn_id %d, trans_id %d, flags %d",
param->exec_write.conn_id, param->exec_write.trans_id, param->exec_write.flags);
break;
case ESP_GATTS_MTU_EVT:
ESP_LOGI(TAG, "MTU_EVT, conn_id %d, mtu %d", param->mtu.conn_id, param->mtu.mtu);
break;
case ESP_GATTS_CONF_EVT:
ESP_LOGI(TAG, "CONF_EVT, status %d, handle %d", param->conf.status, param->conf.handle);
break;
case ESP_GATTS_START_EVT:
ESP_LOGI(TAG, "START_EVT, status %d", param->start.status);
// 开始广告
esp_ble_gap_config_adv_data(&adv_data);
break;
case ESP_GATTS_CONNECT_EVT:
ESP_LOGI(TAG, "CONNECT_EVT, conn_id %d", param->connect.conn_id);
break;
case ESP_GATTS_DISCONNECT_EVT:
ESP_LOGI(TAG, "DISCONNECT_EVT, reason %d", param->disconnect.reason);
// 断开连接后重新开始广告
esp_ble_gap_config_adv_data(&adv_data);
break;
default:
break;
}
}
static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *param)
{
switch (event) {
case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT:
// 广告数据设置完成,开始广告
esp_ble_gap_start_advertising();
break;
default:
break;
}
}
void app_main(void)
{
esp_err_t ret;
// 初始化NVS
ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
// 初始化蓝牙
ret = esp_bt_controller_init(&bt_cfg);
if (ret) {
ESP_LOGE(TAG, "bt controller init failed: %s", esp_err_to_name(ret));
return;
}
ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);
if (ret) {
ESP_LOGE(TAG, "bt controller enable failed: %s", esp_err_to_name(ret));
return;
}
ret = esp_bluedroid_init();
if (ret) {
ESP_LOGE(TAG, "bluedroid init failed: %s", esp_err_to_name(ret));
return;
}
ret = esp_bluedroid_enable();
if (ret) {
ESP_LOGE(TAG, "bluedroid enable failed: %s", esp_err_to_name(ret));
return;
}
// 注册GAP回调
esp_ble_gap_register_callback(gap_event_handler);
// 注册GATTS回调
esp_ble_gatts_register_callback(gatts_event_handler);
// 注册应用
esp_ble_gatts_app_register(0);
// 设置设备名称
esp_ble_gap_set_device_name(TEST_DEVICE_NAME);
// 配置广告数据
esp_ble_adv_data_t adv_data;
memset(&adv_data, 0, sizeof(adv_data));
adv_data.set_scan_rsp = false;
adv_data.include_name = true;
adv_data.include_txpower = true;
adv_data.min_interval = 0x0006; // 100ms
adv_data.max_interval = 0x0010; // 200ms
adv_data.manufacturer_len = TEST_MANUFACTURER_DATA_LEN;
adv_data.p_manufacturer_data = manufacturer_data;
adv_data.service_data_len = 0;
adv_data.p_service_data = NULL;
adv_data.service_uuid_len = 0;
adv_data.p_service_uuid = NULL;
adv_data.flag = (ESP_BLE_ADV_FLAG_GEN_DISC | ESP_BLE_ADV_FLAG_BREDR_NOT_SPT);
esp_ble_gap_config_adv_data(&adv_data);
}
4.2.3 代码解析
- 初始化BLE栈和服务
- 定义GATT服务、特征和描述符
- 实现GATTS事件处理
- 配置广告数据和设备名称
- 实现BLE连接管理
五、蓝牙通信调试
5.1 Arduino平台调试
- 使用串口监视器查看调试信息
- 使用手机APP(如"Serial Bluetooth Terminal"或"nRF Connect")测试蓝牙连接
5.2 ESP-IDF平台调试
- 使用
idf.py monitor查看调试日志 - 配置不同级别的日志输出:
esp_log_level_set("*", ESP_LOG_DEBUG) - 使用Wireshark配合BLE抓包器分析蓝牙通信数据包
六、总结与进阶
6.1 总结
- ESP8684(ESP32C2)支持经典蓝牙和BLE两种模式
- Arduino平台适合快速开发和原型验证
- ESP-IDF平台提供更底层的控制和更高的性能
- 蓝牙应用开发需要理解服务、特征等核心概念
七、参考资料
- ESP32C2官方文档:
https://docs.espressif.com/projects/esp-idf/en/latest/esp32c2/index.html - Arduino ESP32文档:
https://docs.espressif.com/projects/arduino-esp32/en/latest/ - 蓝牙核心规范:
https://www.bluetooth.com/specifications/bluetooth-core-specification/ - ESP-IDF蓝牙API文档:
https://docs.espressif.com/projects/esp-idf/en/latest/esp32c2/api-reference/bluetooth/index.html
本文详细介绍了ESP8684(ESP32C2)平台上的蓝牙通信协议开发,涵盖了Arduino和ESP-IDF两种开发框架,以及经典蓝牙和BLE两种通信模式。
更多推荐



所有评论(0)