第4章 WiFi基础:Station模式、AP模式、WiFi扫描与连接流程

说到WiFi,很多刚入行的朋友容易把概念搞混。其实WiFi的工作模式没那么玄乎,说白了就两种:一种是去连别人,一种是让别人来连你。嗯,这就是我们今天要聊的Station模式和AP模式。

4.1 Station模式——咱们的设备去连路由器

Station模式,也叫STA模式。这是最常用的模式。我们的扫地机器人连上家里的路由器,用的就是STA模式。

我刚开始做WiFi项目时,总觉得STA模式就是配个SSID和密码就完事了。后来踩了不少坑才发现,事情没那么简单。

核心要点:STA模式下,设备作为客户端,主动连接一个已有的WiFi热点(AP)。连接成功后,设备会获得一个IP地址,然后就能上网了。

在ESP32上,初始化STA模式的代码大概长这样:

#include "esp_wifi.h"
#include "esp_event.h"

void wifi_init_sta(void)
{
    // 初始化网络接口
    esp_netif_init();
    esp_event_loop_create_default();
    esp_netif_create_default_wifi_sta();

    // 初始化WiFi
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    esp_wifi_init(&cfg);

    // 配置STA模式
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = "MyHomeWiFi",
            .password = "password123"
        },
    };
    esp_wifi_set_mode(WIFI_MODE_STA);
    esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
    esp_wifi_start();
}

你看,代码本身不复杂。但实际项目中,我遇到过一个问题:WiFi连接成功后,设备突然断连了。排查了半天,发现是路由器开启了MAC地址过滤,而我的设备MAC地址没在白名单里。嗯,这种坑防不胜防。

4.2 AP模式——让设备变成一个小热点

AP模式,就是让我们的设备自己变成一个热点。其他设备(比如手机)可以连上来。

你想想看,扫地机器人第一次配网时,手机怎么知道该连哪个WiFi?其实就是机器人先开启AP模式,手机连上这个热点,然后通过手机把家里的WiFi信息告诉机器人。这就是所谓的智能配网

我的经验:AP模式下,热点名称(SSID)最好带上设备标识,比如"RoboCleaner_XXXX"。这样用户在手机上一眼就能认出自己的设备。我曾经见过一个产品,所有设备的热点名都一样,结果用户配网时连错了邻居家的设备……

AP模式的代码示例:

void wifi_init_ap(void)
{
    esp_netif_init();
    esp_event_loop_create_default();
    esp_netif_create_default_wifi_ap();

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    esp_wifi_init(&cfg);

    wifi_config_t wifi_config = {
        .ap = {
            .ssid = "RoboCleaner_AP",
            .ssid_len = strlen("RoboCleaner_AP"),
            .password = "12345678",
            .max_connection = 4,
            .authmode = WIFI_AUTH_WPA_WPA2_PSK
        },
    };
    esp_wifi_set_mode(WIFI_MODE_AP);
    esp_wifi_set_config(WIFI_IF_AP, &wifi_config);
    esp_wifi_start();
}

这里有个细节:AP模式下,密码长度不能少于8位。这是WiFi协议规定的。我见过有人设了个6位密码,结果死活连不上,还以为是代码写错了。

4.3 WiFi扫描——先看看周围有哪些热点

WiFi扫描,就是让设备去"听"一下周围有哪些WiFi信号。这个功能在配网时特别有用——手机把扫描到的热点列表发给用户,用户从中选择自家的WiFi。

扫描分为两种:

扫描类型 说明 耗时
主动扫描 设备主动发送探测请求帧,AP收到后会回复 较快,约1-3秒
被动扫描 设备监听AP定期发送的信标帧 较慢,约3-10秒

实际项目中,我一般用主动扫描。速度快,用户体验好。但要注意:主动扫描会发送广播帧,有些路由器会把它当成攻击行为。我之前就遇到过,某品牌路由器直接把我的设备拉黑了……

扫描的代码实现:

void wifi_scan(void)
{
    uint16_t ap_count = 0;
    wifi_ap_record_t ap_info[20];

    esp_wifi_scan_start(NULL, true);  // true表示阻塞等待扫描完成
    esp_wifi_scan_get_ap_records(&ap_count, ap_info);

    for (int i = 0; i < ap_count; i++) {
        printf("SSID: %s, RSSI: %d, Channel: %d\n",
               ap_info[i].ssid,
               ap_info[i].rssi,
               ap_info[i].primary);
    }
}

注意:扫描时设备会短暂断开当前WiFi连接。如果你的设备正在传输数据,最好先暂停传输,等扫描完成后再恢复。我曾经因为这个原因,导致扫地机器人一边扫地图一边断网,结果地图数据丢了半张……

4.4 连接流程——从扫描到连上的完整步骤

好了,我们把前面几个知识点串起来。一个完整的WiFi连接流程是这样的:

  1. 初始化WiFi:设置模式(STA/AP/混合模式)
  2. 扫描热点:获取周围AP列表
  3. 选择目标:根据SSID匹配要连接的热点
  4. 配置认证:填入SSID和密码
  5. 发起连接:调用连接API
  6. 等待事件:监听连接成功或失败的回调
  7. 获取IP:连接成功后,通过DHCP获取IP地址

在ESP32上,连接事件的处理是这样的:

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_CONNECTED) {
        printf("WiFi连接成功!\n");
    }
    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;
        printf("获取到IP: " IPSTR "\n", IP2STR(&event->ip_info.ip));
    }
    else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        printf("WiFi断开了,尝试重连...\n");
        esp_wifi_connect();  // 自动重连
    }
}

这里有个关键点:连接失败后一定要做重连处理。WiFi信号不稳定是常态,扫地机器人可能在墙角、床底等信号差的地方工作。我习惯在断连事件里加一个重试计数器,连续失败5次就放弃,避免无限重试浪费电量。

避坑指南:我曾经遇到过一个问题——设备连上WiFi后,IP地址获取失败。查了半天,发现是DHCP服务器响应太慢,而我的代码在连接成功后立即开始发送数据,结果数据包全丢了。解决方案是:等GOT_IP事件触发后再开始通信。

4.5 混合模式——既要连网又要被连

有些场景下,设备需要同时工作在STA和AP模式。比如扫地机器人正常工作时连家里的WiFi(STA模式),同时开启一个AP模式用于调试或紧急配网。

这种模式叫混合模式(WIFI_MODE_APSTA)。代码上就是把前面两个配置合在一起:

esp_wifi_set_mode(WIFI_MODE_APSTA);

// 分别配置AP和STA
wifi_config_t ap_config = { /* ... */ };
wifi_config_t sta_config = { /* ... */ };

esp_wifi_set_config(WIFI_IF_AP, &ap_config);
esp_wifi_set_config(WIFI_IF_STA, &sta_config);
esp_wifi_start();

注意:混合模式下,AP和STA通常使用同一个WiFi射频。这意味着它们共享天线和信道。如果STA连接的信道是6,AP也只能用信道6。我见过有人强行把AP设成信道11,结果STA连不上网了……

好了,这一章的内容就这些。WiFi基础其实不难,但细节很多。下一章我们会聊WiFi配网方式,到时候会用到今天讲的这些知识。记住一句话:WiFi连接的本质,就是让两个设备在同一个信道上,用同一个协议说话