下面给出一个最简化、可编译运行的示例代码,演示如何在 ESP-IDF 环境下正确初始化 NVS,然后初始化 BLE 控制器和 Bluedroid 协议栈。该示例不会包含完整的 GATT 服务/特征注册逻辑,仅用于演示如何消除 “NVS not initialized” 相关错误并顺利启动 BLE。如果你需要进一步实现 GATT Server 或 Client,可在此基础上添加相应的功能代码。
注意:请先确保你的分区表中有名为
nvs
的分区,并且大小足够。官方默认的partitions_singleapp.csv
通常会包含这一分区。如果使用自定义分区表,请自行检查。
示例代码
#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_bt_main.h"
#include "esp_gap_ble_api.h"
#include "esp_gatts_api.h"
#include "esp_gatt_common_api.h"
static const char *TAG = "BLE_INIT_EXAMPLE";
void app_main(void)
{
// 1. 初始化 NVS
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_LOGW(TAG, "NVS 分区出现问题,正在擦除并重新初始化...");
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);
ESP_LOGI(TAG, "NVS 初始化成功");
// 2. 初始化蓝牙控制器
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
ret = esp_bt_controller_init(&bt_cfg);
if (ret) {
ESP_LOGE(TAG, "初始化蓝牙控制器失败: %s", esp_err_to_name(ret));
return;
}
ret = esp_bt_controller_enable(ESP_BT_MODE_BLE);
if (ret) {
ESP_LOGE(TAG, "使能蓝牙控制器失败: %s", esp_err_to_name(ret));
return;
}
ESP_LOGI(TAG, "蓝牙控制器初始化并使能成功");
// 3. 初始化 Bluedroid
ret = esp_bluedroid_init();
if (ret) {
ESP_LOGE(TAG, "Bluedroid 初始化失败: %s", esp_err_to_name(ret));
return;
}
ret = esp_bluedroid_enable();
if (ret) {
ESP_LOGE(TAG, "Bluedroid 使能失败: %s", esp_err_to_name(ret));
return;
}
ESP_LOGI(TAG, "Bluedroid 初始化并使能成功");
// 后续可以在这里进行 GATT Server/Client 的初始化和配置
// 比如:esp_ble_gatts_register_callback()、esp_ble_gap_start_advertising() 等
ESP_LOGI(TAG, "BLE 初始化完成,后续可添加自定义 BLE 功能");
}
代码说明
-
NVS 初始化
- 使用
nvs_flash_init()
初始化 NVS。如果返回ESP_ERR_NVS_NO_FREE_PAGES
或ESP_ERR_NVS_NEW_VERSION_FOUND
,说明 NVS 分区空间不足或版本不兼容,需要先擦除再重新初始化。 - 这一步必须在使用蓝牙前完成,否则会报 “NVS not initialized” 错误。
- 使用
-
蓝牙控制器初始化
- 通过
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
获取默认配置,然后调用esp_bt_controller_init(&bt_cfg)
完成控制器初始化。 - 调用
esp_bt_controller_enable(ESP_BT_MODE_BLE)
使能 BLE 功能(如果需要经典蓝牙,可改为ESP_BT_MODE_CLASSIC_BT
或ESP_BT_MODE_BTDM
)。
- 通过
-
Bluedroid 协议栈初始化
- 调用
esp_bluedroid_init()
初始化协议栈,随后调用esp_bluedroid_enable()
使能。 - 如果需要 GATT 功能,还可以调用
esp_ble_gatts_register_callback()
、esp_ble_gap_register_callback()
等函数来注册相应回调,并在其中配置服务、特征、广播等。
- 调用
编译时,请确保使用了合适版本的 ESP-IDF,并正确配置了串口下载端口、波特率等。执行
idf.py build && idf.py flash && idf.py monitor
即可烧写并监控日志输出。
通过以上代码,你就可以在 ESP32 上完成基础的 NVS 和 BLE 初始化,避免日志中出现 “BT OSI: config save: NVS not initialized” 的错误提示。后续若需实现更多 BLE 功能,可以在注释处继续扩展。