從您最新的日志來看,PPP 流程已經走到啟動階段并且成功進入了 “STAGE_START_PPP”,但在 “STAGE_WAIT_IP” 階段沒有拿到 IP,約 60 s 后就報了 “Connection lost”:
I (11161) modem_board: Modem state STAGE_START_PPP, Success!
I (11361) modem_board: Modem state STAGE_WAIT_IP, Start
W (11361) modem_board: Modem event! 0
I (71361) esp-netif_lwip-ppp: Connection lost
這通常是因為沒有正確激活 PDP context(即沒有拿到運營商下發的 IP)導致 LCP 握手機制超時。排查思路和改進方案如下:
一、先檢查并手動配置 APN
在啟動 PPP 之前,務必先執行:
// 假設 dce 為 esp_modem_dce_t*,代表 DCE 操作句柄
// 1. 配置 PDP 上下文(APN),請將 "your.apn.here" 替換成真實運營商 APN
esp_modem_dte_generic_command(dce, "AT+CGDCONT=1,\"IP\",\"your.apn.here\"\r", NULL, 0);// 2. 激活 PDP 上下文(部分網絡需要顯式啟動)
esp_modem_dte_generic_command(dce, "AT+CGACT=1,1\r", NULL, 0);// 再啟動 PPP
esp_err_t err = esp_modem_dce_start_ppp(dce);
ESP_ERROR_CHECK(err);
如果不先設置或激活 PDP,運營商就不會分配 IP,PPP 會一直等到超時。
二、訂閱并打印 PPP 事件
在創建 PPP Network Interface 時,注冊 IP 事件回調,查看到底有沒有收到 IP。
// 在 app_main 或初始化函數中:
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_PPP_GOT_IP, &on_ppp_got_ip, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(PPP_EVENT, ESP_EVENT_ANY_ID, &on_ppp_event, NULL));// 回調示例:
static void on_ppp_got_ip(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {ip_event_got_ip_t* info = (ip_event_got_ip_t*) event_data;ESP_LOGI(TAG, ">>> PPP GOT IP: " IPSTR ", gw: " IPSTR,IP2STR(&info->ip_info.ip), IP2STR(&info->ip_info.gw));
}static void on_ppp_event(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) {ESP_LOGI(TAG, ">>> PPP event: %ld", event_id);
}
這樣能夠精確知道是否有 IP_EVENT_PPP_GOT_IP
事件觸發。
三、配置 LCP Keepalive(可選)
默認情況下,如果長時間沒收到對端 LCP Echo 回應,PPP 會斷開。可以調大 LCP echo 檢測閾值:
esp_modem_dce_t* dce = esp_modem_dce_get_handle(modem);
esp_modem_ppp_config_t ppp_cfg = ESP_MODEM_DEFAULT_PPP();
ppp_cfg.lcp_echo_interval_ms = 10000; // 每 10s 發送一次 LCP Echo Request
ppp_cfg.lcp_echo_failure = 5; // 連續 5 次超時再判定為掉線
esp_modem_dce_set_ppp_config(dce, &ppp_cfg);
四、完整參考代碼片段
// … 初始化 NVS、網絡、esp_netif 等 …// 1. 獲取 DCE 操作句柄
esp_modem_dce_t* dce = esp_modem_dce_get_handle(modem);// 2. 配置 APN 并激活 PDP
esp_modem_dte_generic_command(dce, "AT+CGDCONT=1,\"IP\",\"cmnet\"\r", NULL, 0);
esp_modem_dte_generic_command(dce, "AT+CGACT=1,1\r", NULL, 0);// 3. 注冊 PPP 事件
esp_event_handler_register(IP_EVENT, IP_EVENT_PPP_GOT_IP, &on_ppp_got_ip, NULL);
esp_event_handler_register(PPP_EVENT, ESP_EVENT_ANY_ID, &on_ppp_event, NULL);// 4. (可選)調整 LCP Keepalive
esp_modem_ppp_config_t ppp_cfg = ESP_MODEM_DEFAULT_PPP();
ppp_cfg.lcp_echo_interval_ms = 10000;
ppp_cfg.lcp_echo_failure = 5;
esp_modem_dce_set_ppp_config(dce, &ppp_cfg);// 5. 啟動 PPP 撥號
esp_err_t err = esp_modem_dce_start_ppp(dce);
if (err != ESP_OK) {ESP_LOGW(TAG, "PPP 啟動失敗,錯誤碼 %d,嘗試手動撥號", err);esp_modem_dte_generic_command(dce, "ATD*99#\r", NULL, 0);
}// 6. 后續在回調中觀察 IP 或斷開事件
通過以上步驟,您可以:
-
確保 APN 正確,令運營商分配 IP。
-
清晰可見 PPP 是否成功拿到 IP(IP_EVENT_PPP_GOT_IP)。
-
調整超時策略,避免保活丟失導致過早斷開。
如果仍然不能拿到 IP,請貼出 AT+CGDCONT / AT+CGACT 的執行結果,以及 PPP 回調中所有事件 ID 和日志。這樣可以進一步定位問題。