ESP-IDF无法连接WiFi站点问题求助(硬件验证正常)
问题:ESP-IDF WiFi STA模式连接失败,事件处理函数无响应
使用ESP-IDF开发时,WiFi站点(STA)连接失败,试过官方网络示例、ChatGPT生成代码、IDF GitHub示例均无效,但硬件正常(Arduino IDE代码可正常连接)。事件处理函数内的所有printf语句均无输出,怀疑事件注册或代码逻辑存在问题。
事件处理函数代码
/* FreeRTOS event group to signal when we are connected*/ static EventGroupHandle_t s_wifi_event_group; /* The event group allows multiple bits for each event, but we only care about two events: * - we are connected to the AP with an IP * - we failed to connect after the maximum amount of retries */ #define WIFI_CONNECTED_BIT BIT0 #define WIFI_FAIL_BIT BIT1 static int s_retry_num = 0; static void wifi_event_handler(void* arg, esp_event_base_t event_base, int32_t event_id, void* event_data) { if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { esp_wifi_connect(); } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { if (s_retry_num < WIFI_ESP_MAXIMUM_RETRY) { esp_wifi_connect(); s_retry_num++; #ifdef VERBOSE printf("Retry to connect to the AP"); #endif } else { xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT); } #ifdef VERBOSE printf("Connect to the AP fail"); #endif } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data; #ifdef VERBOSE printf("Got ip:" IPSTR, IP2STR(&event->ip_info.ip)); #endif s_retry_num = 0; xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); } }
连接函数代码
int wifi_connect(uint8_t* ssid, uint8_t* password) { nvs_flash_init(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); esp_wifi_init(&cfg); s_wifi_event_group = xEventGroupCreate(); static wifi_config_t wifi_config = { .sta = { .ssid = "", .password = "", }, }; strcpy((char*)wifi_config.sta.ssid, (const char*)ssid); // copy chars from hardcoded configs to struct strcpy((char*)wifi_config.sta.password, (const char*)password); #ifdef VERBOSE printf("SSID: %s\n", wifi_config.sta.ssid); printf("Password: %s\n", wifi_config.sta.password); #endif esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, wifi_event_handler, NULL); esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, wifi_event_handler, NULL); esp_wifi_set_mode(WIFI_MODE_STA); esp_wifi_set_config(ESP_IF_WIFI_STA, &wifi_config); esp_wifi_start(); esp_wifi_connect(); #ifdef VERBOSE printf("Connecting to %s\n", ssid); #endif EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT | WIFI_FAIL_BIT, pdFALSE, pdFALSE, WIFI_ESP_CONN_TIMEOUT); esp_event_handler_unregister(IP_EVENT, IP_EVENT_STA_GOT_IP, wifi_event_handler); esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, wifi_event_handler); if (bits & WIFI_CONNECTED_BIT) { #ifdef VERBOSE printf("Connected to ssid:%s, password:%s\n", ssid, password); #endif return 0; } else if (bits & WIFI_FAIL_BIT) { #ifdef VERBOSE printf("Failed to connect to ssid:%s, password:%s\n", ssid, password); #endif return 1; } else { #ifdef VERBOSE printf("Error connecting. Reset 0x00\n"); #endif return -1; } }
日志输出
SSID: JM_limpia_el_baño Password: LaTienesEnElRouter Connecting to JM_limpia_el_baño Error connecting. Reset 0x00 Function return: 2;
排查建议
- 缺少事件循环初始化:ESP-IDF v4.x及以上版本必须先调用
esp_event_loop_create_default()初始化系统事件循环,否则事件无法分发,事件处理函数不会执行。需在nvs_flash_init()之后添加该调用,并处理返回错误。 - 检查宏定义有效性:确认
WIFI_ESP_MAXIMUM_RETRY和WIFI_ESP_CONN_TIMEOUT已正确定义,若未定义会导致重试逻辑失效或超时参数异常,最终触发超时返回。 - 完善NVS初始化错误处理:
nvs_flash_init()可能返回ESP_ERR_NVS_NO_FREE_PAGES或ESP_ERR_NVS_NEW_VERSION_FOUND错误,需添加擦除NVS后重试的逻辑,避免NVS初始化失败阻断WiFi功能。示例代码: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_wifi_start()会自动触发WIFI_EVENT_STA_START事件,事件处理函数内已调用esp_wifi_connect(),当前代码中esp_wifi_start()后手动调用的esp_wifi_connect()属于重复操作,可能导致逻辑冲突,建议删除。 - 特殊字符编码检查:SSID包含西班牙语特殊字符(ñ、ó),需确保传入的SSID字符串编码为UTF-8,且
strcpy操作未因编码问题导致字符串截断,可改用memcpy并指定长度,或直接初始化wifi_config.sta.ssid数组。 - 替换printf为ESP系统日志:使用
ESP_LOGI、ESP_LOGW等ESP-IDF日志函数替代printf,在menuconfig中开启WiFi组件的详细日志级别,可获取系统层面的WiFi错误信息,更容易定位问题。 - 验证事件注册时机:确保事件注册在
esp_wifi_init()之后、esp_wifi_start()之前,当前代码顺序正确,但需配合事件循环初始化才能生效。
内容的提问来源于stack exchange,提问作者ABC
相关产品推荐
相关产品推荐

