You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 14:47:32