3. WiFi 6 特性检测与报告
任务目标
在 ESP32-S3 上检测当前 Wi-Fi 连接协商的协议版本,判断是否为 WiFi 6(802.11ax),并通过串口输出检测报告。本案例聚焦于利用 ESP-IDF 的事件回调机制获取 AP 侧实际协商的协议模式,不涉及吞吐量或信号质量测量。
环境依赖
- 硬件:ESP32-S3-DevKitC 开发板(或兼容模组)
- 软件:ESP-IDF v5.2 及以上版本(需启用 802.11ax 支持)
- 路由器:支持 WiFi 6(802.11ax)且已开启该模式
实现原理
ESP-IDF 在 WIFI_EVENT_STA_CONNECTED 事件中通过 wifi_event_sta_connected_t 结构体提供 phy_mode 字段,该字段直接反映与 AP 协商成功的物理层协议模式。通过比较该枚举值与 WIFI_PHY_MODE_11AX 即可判定是否为 WiFi 6 连接。此方法比主动探测更可靠,因为它是芯片与 AP 完成握手后的真实协商结果。
完整代码
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
static const char *TAG = "wifi6_detect";
static EventGroupHandle_t s_wifi_event_group;
#define WIFI_CONNECTED_BIT BIT0
// 将 PHY 模式枚举转换为可读字符串
static const char* phy_mode_to_str(wifi_phy_mode_t mode) {
switch(mode) {
case WIFI_PHY_MODE_11B: return "802.11b";
case WIFI_PHY_MODE_11G: return "802.11g";
case WIFI_PHY_MODE_11N: return "802.11n (WiFi 4)";
case WIFI_PHY_MODE_LR: return "LR mode";
case WIFI_PHY_MODE_11A: return "802.11a";
case WIFI_PHY_MODE_11AC: return "802.11ac (WiFi 5)";
case WIFI_PHY_MODE_11AX: return "802.11ax (WiFi 6)";
default: return "UNKNOWN";
}
}
static void 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) {
esp_wifi_connect();
ESP_LOGI(TAG, "重连中...");
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
}
}
// 连接事件中提取 PHY 模式并报告
static void wifi_connected_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data) {
wifi_event_sta_connected_t* data = (wifi_event_sta_connected_t*)event_data;
ESP_LOGI(TAG, "已连接 AP: %s, 信道: %d",
(char*)data->ssid, data->channel);
ESP_LOGI(TAG, "协商 PHY 模式: %s", phy_mode_to_str(data->phy_mode));
if (data->phy_mode == WIFI_PHY_MODE_11AX) {
ESP_LOGI(TAG, ">>> 检测结果: 当前连接支持 WiFi 6 (802.11ax)");
} else {
ESP_LOGI(TAG, ">>> 检测结果: 当前连接不支持 WiFi 6");
}
}
void app_main(void) {
ESP_ERROR_CHECK(nvs_flash_init());
s_wifi_event_group = xEventGroupCreate();
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_create_default_wifi_sta();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
// 注册事件回调
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID,
&event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP,
&event_handler, NULL));
// 关键:单独注册连接事件以获取 phy_mode
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, WIFI_EVENT_STA_CONNECTED,
&wifi_connected_handler, NULL));
wifi_config_t wifi_config = {0};
strcpy((char*)wifi_config.sta.ssid, CONFIG_ESP_WIFI_SSID);
strcpy((char*)wifi_config.sta.password, CONFIG_ESP_WIFI_PASSWORD);
wifi_config.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK;
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());
// 等待连接成功(带超时)
EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
WIFI_CONNECTED_BIT, pdFALSE, pdTRUE, pdMS_TO_TICKS(15000));
if (bits & WIFI_CONNECTED_BIT) {
ESP_LOGI(TAG, "WiFi 连接成功,PHY 模式报告完成");
} else {
ESP_LOGE(TAG, "连接超时,请检查 SSID/密码");
}
}
运行配置
使用 menuconfig 配置 Wi-Fi 凭据:
idf.py menuconfig
# 进入 Example Connection Configuration
# 设置 WiFi SSID 和 Password
# 保存退出
编译并烧录:
idf.py build flash monitor
验证方法
观察串口监视器输出,判定标准如下:
- 通过条件:日志中出现
协商 PHY 模式: 802.11ax (WiFi 6)且检测结果为支持 WiFi 6。若路由器为 WiFi 5 或更早标准,应显示对应模式且报告不支持。 - 功能验证:分别连接 WiFi 6 路由器(2.4GHz/5GHz 均开启 ax 模式)和旧标准路由器,对比输出差异。
- 注意事项:部分路由器默认开启“WiFi 6 兼容模式”,此时可能协商为 802.11ax;若路由器关闭 ax 功能,则 ESP32-S3 会回退到 802.11n/ac,属正常现象。
常见问题
- 编译错误:若提示
phy_mode字段不存在,请确认 IDF 版本 ≥ v5.2 且未禁用 802.11ax 支持。 - 始终显示 802.11n:检查路由器管理界面是否启用了“WiFi 6/802.11ax”模式,部分路由器需在 5GHz 频段单独开启。
- 连接不稳定:若路由器开启 WPA3 且 ESP32-S3 固件不支持,可能导致连接失败,建议先使用 WPA2 测试。