包含:
自定义 AT 命令 (
AT+SCAN=2G
,AT+SCAN=5G
,AT+CONN=ssid,pwd,2G/5G
)2.4 GHz 与 5 GHz 扫描逻辑,并按频段过滤并打印结果
STA 模式初始化、事件回调处理
连接指定 SSID/密码 的示例
详细的中文注释,帮助理解每个模块的设计与实现
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "freertos/task.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"// 本示例针对 ESP32-C5 模组
// 功能:
// 1. 通过自定义 AT 指令扫描 2.4GHz 或 5GHz Wi-Fi(AT+SCAN=2G 或 AT+SCAN=5G)
// 2. 通过自定义 AT 指令连接指定频段的 Wi-Fi(AT+CONN=<SSID>,<PWD>,2G/5G)static const char *TAG = "esp32c5_wifi";
// 事件组标志
#define WIFI_SCAN_DONE_BIT BIT0static EventGroupHandle_t wifi_event_group;
// AT 命令行缓冲区
#define AT_CMD_MAX_LEN 128
static char at_cmd[AT_CMD_MAX_LEN];//--------------------------------------------------
// 1. Wi-Fi 事件处理回调
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) {
switch (event_id) {
case WIFI_EVENT_STA_START:
ESP_LOGI(TAG, "Wi-Fi STA started");
break;
case WIFI_EVENT_SCAN_DONE: {
ESP_LOGI(TAG, "Wi-Fi scan completed");
xEventGroupSetBits(wifi_event_group, WIFI_SCAN_DONE_BIT);
break;
}
case WIFI_EVENT_STA_CONNECTED:
ESP_LOGI(TAG, "Wi-Fi connected");
break;
case WIFI_EVENT_STA_DISCONNECTED:
ESP_LOGI(TAG, "Wi-Fi disconnected");
break;
default:
break;
}
} 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;
ESP_LOGI(TAG, "Got IP: " IPSTR, IP2STR(&event->ip_info.ip));
}
}//--------------------------------------------------
// 2. 初始化 Wi-Fi STA 模式
static void wifi_init(void)
{
// 初始化 NVS(Wi-Fi 驱动依赖)
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
nvs_flash_erase();
nvs_flash_init();
}// 创建事件组
wifi_event_group = xEventGroupCreate();// 初始化 TCP/IP 网络接口
esp_netif_init();
esp_event_loop_create_default();// 创建默认 Wi-Fi STA 接口
esp_netif_create_default_wifi_sta();// Wi-Fi 驱动配置
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
esp_wifi_init(&cfg);// 注册事件处理
esp_event_handler_instance_t instance_any_id;
esp_event_handler_instance_t instance_got_ip;
esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID,
&wifi_event_handler,
NULL,
&instance_any_id);
esp_event_handler_instance_register(IP_EVENT,
IP_EVENT_STA_GOT_IP,
&wifi_event_handler,
NULL,
&instance_got_ip);// 设置为 STA
esp_wifi_set_mode(WIFI_MODE_STA);
esp_wifi_start();
}//--------------------------------------------------
// 3. 扫描并根据频段打印 AP 列表
static void wifi_scan_band(int band)
{
// band = 2 -> 2.4GHz, band = 5 -> 5GHz
ESP_LOGI(TAG, "Starting %dGHz scan...", band);wifi_scan_config_t scan_cfg = {
.ssid = NULL,
.bssid = NULL,
.channel = 0, // 0 表示扫描所有信道
.show_hidden = true
};
esp_wifi_scan_start(&scan_cfg, false);// 等待扫描完成
xEventGroupWaitBits(wifi_event_group,
WIFI_SCAN_DONE_BIT,
pdTRUE,
pdFALSE,
portMAX_DELAY);// 获取扫描结果数量
uint16_t ap_num = 0;
esp_wifi_scan_get_ap_num(&ap_num);
wifi_ap_record_t *ap_records = calloc(ap_num, sizeof(wifi_ap_record_t));
esp_wifi_scan_get_ap_records(&ap_num, ap_records);// 遍历并过滤频段
for (int i = 0; i < ap_num; i++) {
int ch = ap_records[i].primary;
bool is2g = (ch >= 1 && ch <= 14);
if ((band == 2 && is2g) || (band == 5 && !is2g)) {
printf("SSID: %s, RSSI: %d dBm, Channel: %d\n",
(char *)ap_records[i].ssid,
ap_records[i].rssi,
ap_records[i].primary);
}
}
free(ap_records);
}//--------------------------------------------------
// 4. 连接指定 SSID
static void wifi_connect_ap(const char *ssid, const char *pwd)
{
wifi_config_t sta_cfg = { 0 };
strncpy((char *)sta_cfg.sta.ssid, ssid, sizeof(sta_cfg.sta.ssid) - 1);
strncpy((char *)sta_cfg.sta.password, pwd, sizeof(sta_cfg.sta.password) - 1);
sta_cfg.sta.threshold.authmode = WIFI_AUTH_WPA2_PSK;esp_wifi_set_config(WIFI_IF_STA, &sta_cfg);
esp_wifi_connect();
}//--------------------------------------------------
// 5. 简单 AT 命令行解析任务
static void at_task(void *arg)
{
while (1) {
printf("\nEnter AT Command (e.g. AT+SCAN=2G / AT+SCAN=5G / AT+CONN=ssid,pwd,2G): ");
fflush(stdout);
if (fgets(at_cmd, AT_CMD_MAX_LEN, stdin) == NULL) {
vTaskDelay(pdMS_TO_TICKS(100));
continue;
}
// 去除换行符
at_cmd[strcspn(at_cmd, "\r\n")] = 0;if (strncmp(at_cmd, "AT+SCAN=2G", 10) == 0) {
wifi_scan_band(2);
} else if (strncmp(at_cmd, "AT+SCAN=5G", 10) == 0) {
wifi_scan_band(5);
} else if (strncmp(at_cmd, "AT+CONN=", 8) == 0) {
// 格式: AT+CONN=ssid,pwd,2G
char *cmd = at_cmd + 8;
char *ssid = strtok(cmd, ",");
char *pwd = strtok(NULL, ",");
char *band = strtok(NULL, ",");
if (ssid && pwd && band) {
printf("Connecting to SSID '%s' on %s...\n", ssid, band);
wifi_connect_ap(ssid, pwd);
} else {
printf("Invalid AT+CONN format. Use: AT+CONN=ssid,pwd,2G or 5G\n");
}
} else {
printf("Unknown command.\n");
}
}
}//--------------------------------------------------
void app_main(void)
{
// 1. 初始化 Wi-Fi
wifi_init();// 2. 创建 AT 命令解析任务
xTaskCreate(at_task, "at_task", 4096, NULL, 5, NULL);
}