上电工作一段时间后,ble广播没有了,但是iic读卡的功能还正常,串口输出也正常,试过手动接en复位,但是ble广播没有回复

1. 先确认:是真的"广播没发",还是"被连接后不再广播"

BLE 外设如果是 connectable advertising ,一旦被手机、网关或测试工具连接,普通扫描软件就看不到广播了。ESP-IDF NimBLE 示例里也是在连接失败、断开连接后才重新启动广播;断开事件里需要显式 start_advertising()

建议先做两个实验:

复制代码
复制代码
// NimBLE: 所有 GAP 事件都打出来
case BLE_GAP_EVENT_CONNECT:
    ESP_LOGI(TAG, "connect status=%d", event->connect.status);
    if (event->connect.status != 0) start_advertising();
    break;

case BLE_GAP_EVENT_DISCONNECT:
    ESP_LOGI(TAG, "disconnect reason=%d", event->disconnect.reason);
    start_advertising();
    break;

case BLE_GAP_EVENT_ADV_COMPLETE:
    ESP_LOGW(TAG, "adv complete reason=%d", event->adv_complete.reason);
    start_advertising();
    break;

如果你用的是 NimBLE,启动广播建议先确认用的是无限广播:

复制代码
复制代码
rc = ble_gap_adv_start(own_addr_type, NULL, BLE_HS_FOREVER,
                       &adv_params, gap_event_handler, NULL);
ESP_LOGI(TAG, "ble_gap_adv_start rc=%d", rc);

官方示例也是用 BLE_HS_FOREVER 启动持续广播,并且 ble_gap_adv_start() 返回 0 才表示广播真正启动成功。

2. 每个 BLE API 的返回值和 GAP 回调状态都要打印

很多项目只打印"advertising started",但没有打印实际返回码,导致 BLE 已经失败却看起来程序正常。重点打印这些点:

复制代码
复制代码
ESP_LOGI(TAG, "nvs init ret=%s", esp_err_to_name(ret));
ESP_LOGI(TAG, "bt controller init ret=%s", esp_err_to_name(ret));
ESP_LOGI(TAG, "bt controller enable ret=%s", esp_err_to_name(ret));
ESP_LOGI(TAG, "nimble init ret=%d", rc);
ESP_LOGI(TAG, "adv set fields ret=%d", rc);
ESP_LOGI(TAG, "adv start ret=%d", rc);

还要检查广播包长度。传统广播包和扫描响应包每个最大 31 字节;超了以后启动广播会失败。

如果你用 Bluedroid,不是 NimBLE,要把这些事件都打出来:

复制代码
复制代码
ESP_GAP_BLE_ADV_START_COMPLETE_EVT
ESP_GAP_BLE_ADV_STOP_COMPLETE_EVT
ESP_GAP_BLE_ADV_TERMINATED_EVT
ESP_GATTS_CONNECT_EVT
ESP_GATTS_DISCONNECT_EVT

ESP-IDF 的 GAP API 里有广播 start/stop complete 事件和状态字段,应该用这些事件判断广播是否真的成功或被停止。

3. 检查是否进入了 light sleep / deep sleep / modem sleep

ESP32-C3 如果进了 light sleep 或 deep sleep,无线外设会掉电,Wi-Fi/BT 连接不会保持。官方文档明确说进入 deep sleep 或 light sleep 前应用需要关闭 Wi-Fi/BT,且连接不会被保持。

排查方式很直接:

先临时关闭这些配置或代码:

复制代码
复制代码
esp_pm_configure(...)
esp_light_sleep_start()
esp_deep_sleep_start()
esp_bt_sleep_enable()

如果关闭低功耗后 BLE 广播不再消失,问题就在 PM/睡眠路径。

还要检查 BLE modem sleep 的低功耗时钟。ESP32-C3 配置里提到,BT modem sleep 会在 BLE 事件之间睡眠,并依赖低功耗时钟;内部 150 kHz RC 精度大于 BLE 通信常用的 500 ppm 要求,不适合 BLE 连接场景。

4. 检查任务优先级、堆内存、栈溢出

IIC 读卡还能工作,但 BLE 可能因为 host task 被饿死、堆碎片化、栈不足而异常。建议每 10 秒打印一次:

复制代码
复制代码
ESP_LOGI(TAG, "free_heap=%lu min_heap=%lu",
         esp_get_free_heap_size(),
         esp_get_minimum_free_heap_size());

ESP_LOGI(TAG, "task watermark=%lu",
         uxTaskGetStackHighWaterMark(NULL));

重点看:

  • IIC 读卡任务是否是高优先级死循环,没有 vTaskDelay()
  • 是否在 GAP/GATT 回调里做了耗时操作,比如 IIC 读卡、NVS 写入、大量串口打印。
  • 是否频繁动态申请释放内存,导致 BLE 栈拿不到 buffer。
  • 是否有 task watchdog、stack overflow、heap corruption 日志被你忽略了。

建议把 IIC 轮询任务优先级降到普通业务级别,BLE 回调里只投递事件到队列,不直接做复杂业务。

5. EN 复位后 BLE 还不恢复,这一点很关键

正常情况下,拉低 EN/CHIP_EN 应该让芯片复位。如果 EN 复位后串口没有完整 boot log,或者 app_main() 没有重新执行,说明 EN 复位没有真正生效。

硬件上要查:

  • EN/CHIP_EN 是否真的被拉到低电平。
  • 低电平保持时间是否足够。
  • EN 走线是否过长、受干扰。
  • EN 是否悬空。
  • 是否有推荐的 RC 延时电路。

ESP32-C3 硬件设计指南说明,CHIP_EN 高电平使能芯片、低电平复位芯片;复位低电平需要低于 0.25 × VDD,CHIP_EN 低电平复位时间最小 50 µs;并建议 CHIP_EN 不要悬空,通常使用 10 kΩ + 1 µF 的 RC 延时。如果电源上升/下降慢或不稳定,还建议预留电源监控芯片,阈值约 3.0 V。

启动时加这个:

复制代码
复制代码
ESP_LOGI(TAG, "reset reason=%d", esp_reset_reason());

ESP-IDF 提供 esp_reset_reason() 用来读取上一次复位原因。

如果 EN 复位确实进了 app_main(),但 BLE 依然不恢复,而断电重上电能恢复,优先怀疑:

  • 3.3 V 电源边界不稳定。
  • EN 复位没有让外部 Flash / 外设 / 电源域完全恢复。
  • NVS 中 PHY/BLE 相关数据异常。
  • BLE 初始化失败但代码没有打印错误。

6. 查 NVS / PHY 校准数据

BLE/Wi-Fi 射频校准数据会和 NVS/PHY 数据相关。可以做一次诊断性验证:

复制代码
复制代码
idf.py erase-flash
idf.py flash monitor

或者在诊断模式下擦除 PHY 校准数据:

复制代码
复制代码
esp_phy_erase_cal_data_in_nvs();

Espressif 文档提到,遇到 RF 校准数据相关问题时,可以擦除 NVS,或者调用 esp_phy_erase_cal_data_in_nvs() 只擦除 PHY namespace。

同时检查 nvs_flash_init() 的返回值。如果出现 ESP_ERR_NVS_NO_FREE_PAGES,官方建议擦除整个 NVS 分区后重新初始化。

7. 如果同时开了 Wi-Fi,要单独做 Wi-Fi/BLE 共存测试

ESP32-C3 的 Wi-Fi 和 BLE 共用 2.4 GHz 射频资源,共存模块会按状态动态分配时间片。官方文档说明 BLE advertising 事件也会参与动态优先级调度;某些非默认 Wi-Fi 省电参数可能影响 Bluetooth 性能。

排查方法:

  1. 先完全关闭 Wi-Fi,只保留 BLE + IIC。
  2. 如果正常,再打开 Wi-Fi 但关闭 Wi-Fi power save。
  3. 如果异常只在 Wi-Fi 开启后出现,重点查 coexist、Wi-Fi scan、配网、重连逻辑。

8. 硬件射频和电源也要测,不要只看 UART 正常

BLE 发射时电流是脉冲型的,IIC 和 UART 正常不代表 RF 供电稳定。建议用示波器测:

  • ESP32-C3 模组 3V3 引脚附近电压。
  • BLE 广播期间有没有瞬时跌落。
  • 异常发生前后 3V3 是否有毛刺。
  • EN 脚是否被干扰。
  • 40 MHz 晶振是否稳定。
  • 天线净空、匹配、电感电容是否按参考设计。
  • VDD3P3_RTC、VDDA、VDD_SPI 附近去耦是否足够。

如果是自研板,建议先拿同样固件烧到 ESP32-C3 官方开发板或成熟模组板上跑长测。若开发板不复现,硬件电源/EN/射频布局概率很高。

我建议的最短排查路径

先做这 5 步:

  1. 把所有 BLE GAP 事件、BLE API 返回值、reset reason、free heap、min heap 打印出来。
  2. BLE_HS_FOREVER,并在 DISCONNECT / ADV_COMPLETE / 连接失败时强制重启广播。
  3. 临时关闭 light sleep、deep sleep、BT modem sleep、Wi-Fi,只保留 BLE + IIC 跑长测。
  4. EN 复位时确认串口是否出现完整 boot log,并打印 esp_reset_reason()
  5. idf.py erase-flash 后重新烧录,排除 NVS/PHY 校准数据异常。

从你描述的"系统还活着,但 BLE 广播没了,EN 复位也不恢复"来看,我会优先怀疑 GAP 状态没有重启广播、低功耗/时钟配置、BLE 初始化失败未打印、EN/电源复位不完整 这四类。