08_ESP32 Wi-Fi 基础用法

08_ESP32 Wi-Fi 基础用法

ESP32 系列芯片内置了强大的无线连接功能。多数 ESP32 芯片集成了 Wi-Fi,这使其非常适用于物联网(IoT)项目。(部分型号为满足成本或特定应用场景的需求,未集成 Wi-Fi 功能。各型号具体的支持情况可查阅官方的 [ESP32 产品概览](https://products.espressif.com/static/Espressif SoC Product Portfolio.pdf) 文档。)

ESP32 可以工作在多种 Wi-Fi 模式下:

  • STA 模式(Station):ESP32 作为客户端连接到路由器或热点。
  • AP 模式(Access Point):ESP32 创建热点,其他设备可以连接到它。
  • AP+STA 模式:同时作为客户端连接网络,并为其他设备提供热点。

示例 1:扫描 Wi-Fi

这个示例展示如何扫描周围的 Wi-Fi 网络并显示其详细信息,包括网络名称、信号强度、信道和加密类型。

// 引入 ESP32 的 WiFi 库,用来操作 WiFi
#include "WiFi.h"

// ==================== 初始化函数,只运行一次 ====================
void setup() {
  // 初始化串口,波特率 115200,用于在电脑上看打印信息
  Serial.begin(115200);

  // 设置 ESP32 的 WiFi 工作模式:STA 模式(站点模式 = 连接别人的WiFi)
  WiFi.mode(WIFI_STA);
  
  // 断开之前可能存在的 WiFi 连接,保证干净扫描
  WiFi.disconnect();
  
  // 等待 100ms,让 WiFi 模块稳定
  delay(100);

  // 串口打印:初始化完成
  Serial.println("Setup done");
}

// ==================== 循环函数,一直重复运行 ====================
void loop() {
  // 提示:开始扫描 WiFi
  Serial.println("Scan start");

  // 启动 WiFi 扫描,并返回扫描到的 WiFi 个数
  int n = WiFi.scanNetworks();
  
  // 提示:扫描结束
  Serial.println("Scan done");

  // ==================== 判断有没有扫描到 WiFi ====================
  if (n == 0) {
    // 如果 n=0,表示一个 WiFi 都没找到
    Serial.println("no networks found");
  } else {
    // 找到 WiFi,打印数量
    Serial.print(n);
    Serial.println(" networks found");
    
    // 打印表头,让输出格式整齐好看
    Serial.println("Nr | SSID                             | RSSI | CH | Encryption");

    // ==================== 循环打印每一个 WiFi 的信息 ====================
    for (int i = 0; i < n; ++i) {
      // 打印序号
      Serial.printf("%2d", i + 1);
      Serial.print(" | ");
      
      // 打印 WiFi 名称(SSID),左对齐,固定宽度
      Serial.printf("%-32.32s", WiFi.SSID(i).c_str());
      Serial.print(" | ");
      
      // 打印信号强度(单位为 dBm,该值为负数,越接近 0 表示信号越强)
      Serial.printf("%4ld", WiFi.RSSI(i));
      Serial.print(" | ");
      
      // 打印 WiFi 信道
      Serial.printf("%2ld", WiFi.channel(i));
      Serial.print(" | ");

      // ==================== 判断 WiFi 加密方式 ====================
      switch (WiFi.encryptionType(i)) {
        case WIFI_AUTH_OPEN:              Serial.print("open");          break; // 无密码
        case WIFI_AUTH_WEP:               Serial.print("WEP");           break; // WEP 加密
        case WIFI_AUTH_WPA_PSK:           Serial.print("WPA");           break; // WPA
        case WIFI_AUTH_WPA2_PSK:          Serial.print("WPA2");          break; // WPA2(最常见)
        case WIFI_AUTH_WPA_WPA2_PSK:      Serial.print("WPA+WPA2");      break; // WPA+WPA2 混合
        case WIFI_AUTH_WPA2_ENTERPRISE:   Serial.print("WPA2-EAP");      break; // 企业版 WPA2
        case WIFI_AUTH_WPA3_PSK:          Serial.print("WPA3");          break; // WPA3
        case WIFI_AUTH_WPA2_WPA3_PSK:     Serial.print("WPA2+WPA3");     break; // WPA2+WPA3
        case WIFI_AUTH_WAPI_PSK:          Serial.print("WAPI");          break; // WAPI
        default:                          Serial.print("unknown");              // 未知加密
      }
      
      // 换行,准备打印下一个 WiFi
      Serial.println();
      
      // 稍微延时,让串口输出稳定
      delay(10);
    }
  }

  // 空一行,格式更清晰
  Serial.println("");

  // 删除本次扫描结果,释放内存
  WiFi.scanDelete();

  // 等待 5 秒,再进行下一次扫描
  delay(5000);
}
  • WiFi.mode(WIFI_STA);:设置 ESP32 的 Wi-Fi 工作模式为站点(Station)模式。
  • WiFi.disconnect():断开之前可能存在的连接,确保处于未连接状态。
  • WiFi.scanNetworks():执行一次同步扫描,探测周围的 Wi-Fi 网络。该函数为阻塞式,扫描完成后会返回发现的网络数量。
  • WiFi.SSID(i):获取索引为 i 的网络的 SSID(网络名称),返回 String 类型。
  • WiFi.RSSI(i):获取索引为 i 的网络的 RSSI(接收信号强度指示)。单位为 dBm,该值为负数,越接近 0 表示信号越强。
  • WiFi.channel(i):获取索引为 i 的网络所在的 Wi-Fi 信道。
  • WiFi.encryptionType(i): 获取索引为 i 的网络的加密类型。
  • WiFi.scanDelete():删除扫描结果以释放内存,是良好的编程习惯。
image-20260520162915445

示例 2:连接指定 Wi-Fi (STA 模式)

ESP32 连接到指定的 Wi-Fi 网络,获取 IP 地址并保持连接。

// 引入 ESP32 的 WiFi 库,用于连接和管理无线网络
#include <WiFi.h>

// ==================== WiFi 配置 ====================
// 定义要连接的 WiFi 名称
const char *ssid = "aaaa";            
// 定义要连接的 WiFi 密码
const char *password = "1234567890";  

// ==================== 初始化函数,只运行一次 ====================
void setup() {
  // 初始化串口通信,波特率 115200,用于在电脑上查看连接信息
  Serial.begin(115200);

  // 延时 10 毫秒,让系统稳定一下
  delay(10);

  // 串口打印:正在连接 WiFi,并显示 WiFi 名称
  Serial.print("Connecting to ");
  Serial.println(ssid);

  // 设置 ESP32 为 STA 模式(客户端模式,用来连接路由器)
  WiFi.mode(WIFI_STA);
  
  // 开始连接指定名称和密码的 WiFi
  WiFi.begin(ssid, password);

  // ==================== 等待 WiFi 连接成功 ====================
  // 如果 WiFi 没有连接成功,就一直循环打印点 ...
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);        // 延时 500 毫秒
    Serial.print("."); // 串口打印一个点,表示正在连接中
  }

  // 到这里说明 WiFi 已经连接成功!
  Serial.println("");
  Serial.println("WiFi connected.");  // 打印:WiFi 已连接
  Serial.println("IP address: ");     // 打印:IP 地址
  Serial.println(WiFi.localIP());     // 打印 ESP32 获取到的 IP 地址
}

// ==================== 循环函数,一直重复运行 ====================
void loop() {
  // 这里空着,因为只需要开机自动连接一次 WiFi
}
  • WiFi.begin(ssid, password);:启动连接过程。这是一个异步函数,它会立即返回,而连接在后台进行。

  • WiFi.status():返回当前的 Wi-Fi 连接状态。

    WL_CONNECTED表示已成功连接。while循环通过轮询此状态来等待连接完成。常见的 Wi-Fi 状态值:

    • WL_IDLE_STATUS:Wi-Fi 处于空闲状态
    • WL_NO_SSID_AVAIL:找不到指定的网络名称
    • WL_CONNECTED:已成功连接
    • WL_CONNECT_FAILED:连接失败
    • WL_CONNECTION_LOST:连接丢失
  • WiFi.localIP():获取 ESP32 在连接成功后由 DHCP 服务器分配到的 IP 地址。类型为 IPAddress。

image-20260520164252895

示例 3:管理多个 Wi-Fi (WiFiMulti)

预设多个 Wi-Fi 网络信息,ESP32 自动连接到信号最强的可用网络。

// 引入ESP32 WiFi库,用于WiFi连接和通信
#include <WiFi.h>
// 引入WiFiMulti库,用于自动连接多个已知WiFi(哪个信号好连哪个)
#include <WiFiMulti.h>

// 创建一个WiFiMulti对象,用来管理多个WiFi账号
WiFiMulti wifiMulti;

// ==================== 初始化函数,只执行1次 ====================
void setup() {
  // 初始化串口,波特率115200,用于在电脑上查看信息
  Serial.begin(115200);
  // 等待10ms,让系统稳定
  delay(10);

  // ==================== 添加待选的WiFi账号和密码 ====================
  // 可以添加很多个,ESP32会自动选择能连上的
  wifiMulti.addAP("aaaa", "1234567890");
  wifiMulti.addAP("123", "feilimao123");
  //wifiMulti.addAP("ssid_from_AP_3", "your_password_for_AP_3");

  // 串口提示:正在连接WiFi
  Serial.println("Connecting Wifi...");

  // ==================== 自动搜索并连接添加过的WiFi ====================
  // 如果连接成功
  if (wifiMulti.run() == WL_CONNECTED) {
    Serial.println("");
    Serial.println("WiFi connected");       // 提示:WiFi已连接
    Serial.print("SSID: ");                 // 打印当前连接的WiFi名称
    Serial.println(WiFi.SSID());
    Serial.print("IP address: ");           // 打印ESP32的IP地址
    Serial.println(WiFi.localIP());
  }
}

// ==================== 循环函数,一直重复运行 ====================
void loop() {
  // 检查WiFi是否还连着
  // 如果断开,就打印提示,然后自动尝试重连
  if (wifiMulti.run() != WL_CONNECTED) {
    Serial.println("WiFi not connected!");
    delay(1000);  // 延时1秒再重试
  }
}
  • WiFiMulti wifiMulti;:创建一个 WiFiMulti 对象实例,用于管理多个 Wi-Fi 网络。
  • wifiMulti.addAP("ssid", "password");:向 WiFiMulti 实例中添加一个候选 Wi-Fi 网络的凭据。可以多次调用以添加多个网络。
  • wifiMulti.run():核心函数。它会扫描、选择信号最强的可用网络并尝试连接。返回当前的连接状态,类似 WiFi.status()。在 loop 中持续调用可实现断线自动重连。

配置好至少一个可用的 Wi-Fi 信息后上传代码。ESP32 会连接到列表中信号最强的网络,并打印出 IP 地址。如果当前连接断开,它会自动尝试重连到列表中的其他可用网络。

image-20260520165241741

示例 4:创建 Wi-Fi 热点 (AP 模式)

ESP32 创建一个 Wi-Fi 热点,其他设备可以连接到它。设备的连接和断开时,串口监视器显示设备的信息。本示例使用事件回调来监视客户端的连接和断开。

// 引入 ESP32 WiFi 库,用来开启热点、连接WiFi
#include <WiFi.h>

// ==================== 热点配置 ====================
// 自定义 ESP32 发出的 WiFi 热点名称
const char *ssid = "ESP32-S3-TEST";
// 自定义 WiFi 密码(必须至少 8 位,否则无法创建)
const char *password = "12345678";

// ==================== 初始化函数,只运行一次 ====================
void setup() {
  // 初始化串口,波特率 115200,用于查看日志
  Serial.begin(115200);
  Serial.println();
  Serial.println("Configuring access point...");  // 提示:正在配置热点

  // ==================== 注册 WiFi 事件监听 ====================
  // 当有设备连接上 ESP32 热点时,调用 WiFiStationConnected 函数
  WiFi.onEvent(WiFiStationConnected, WiFiEvent_t::ARDUINO_EVENT_WIFI_AP_STACONNECTED);
  // 当设备获取到 IP 地址时,调用 WiFiStationGotIP 函数
  WiFi.onEvent(WiFiStationGotIP, WiFiEvent_t::ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED);
  // 当设备断开热点时,调用 WiFiStationDisconnected 函数
  WiFi.onEvent(WiFiStationDisconnected, WiFiEvent_t::ARDUINO_EVENT_WIFI_AP_STADISCONNECTED);

  // ==================== 启动 ESP32 热点 ====================
  // 如果热点启动失败
  if (!WiFi.softAP(ssid, password)) {
    Serial.println("Soft AP creation failed.");  // 打印失败信息
    while (1);  // 死循环,停止程序
  }

  // 获取 ESP32 热点的 IP 地址(默认:192.168.4.1)
  IPAddress myIP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(myIP);  // 打印热点IP
}

// 循环函数,这里不需要做任何事
void loop() {
}

// ==================== 事件1:有设备连接上热点 ====================
void WiFiStationConnected(WiFiEvent_t event, WiFiEventInfo_t info) {
  Serial.print("Device connected, MAC: ");      // 打印:设备已连接
  // 打印设备的 MAC 地址
  Serial.println(macToString(info.wifi_ap_staconnected.mac));
}

// ==================== 事件2:设备成功获取到IP ====================
void WiFiStationGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
  Serial.print("Device IP address: ");          // 打印:设备IP地址
  // 打印分配给设备的IP
  Serial.println(IPAddress(info.got_ip.ip_info.ip.addr));
}

// ==================== 事件3:设备断开了热点 ====================
void WiFiStationDisconnected(WiFiEvent_t event, WiFiEventInfo_t info) {
  Serial.print("Device disconnected, MAC: ");  // 打印:设备断开
  // 打印断开设备的MAC地址
  Serial.println(macToString(info.wifi_ap_stadisconnected.mac));
}

// ==================== 辅助函数:把MAC地址转成字符串方便打印 ====================
String macToString(const uint8_t *mac) {
  char buf[18];
  snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
           mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  return String(buf);
}
  • WiFi.onEvent(callback, event):注册 Wi-Fi 事件回调函数。当指定的事件发生时,系统会自动调用相应的回调函数。这是一种事件驱动的编程模式,无需主动轮询状态。
  • 事件类型说明:
    • ARDUINO_EVENT_WIFI_AP_STACONNECTED:有设备连接到 ESP32 热点时触发
    • ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED:连接的设备获取到 IP 地址时触发
    • ARDUINO_EVENT_WIFI_AP_STADISCONNECTED:设备从 ESP32 热点断开时触发
    • 其他事件,参考 Wi-Fi 事件示例
  • WiFi.softAP(ssid, password):创建一个 Wi-Fi 热点。第一个参数是热点名称,第二个参数是密码(至少 8 位)。返回布尔值表示创建是否成功。
  • WiFi.softAPIP():获取 ESP32 作为热点时的 IP 地址,通常默认为 192.168.4.1。
  • WiFiEventInfo_t info:包含事件相关信息的结构体,不同事件类型包含不同的信息字段。
  • macToString():辅助函数,将 6 字节的 MAC 地址数组转换为可读的字符串格式(如 "aa:bb:cc:dd:ee:ff")。

程序运行后,ESP32 会创建一个名为 "ESP32S3-TEST" 的 Wi-Fi 热点。串口监视器会首先打印出 AP 的 IP 地址。当有设备连接或断开此热点时,相应的事件信息会被打印出来:

image-20260520165513732

示例 5:配置静态 IP

在特定应用场景下,为 ESP32 设置一个固定的 IP 地址(而非通过 DHCP 动态获取)是一种常见需求,便于设备被稳定访问。

STA 模式:配置静态 IP

// 引入 ESP32 WiFi 库,用于连接无线网络
#include <WiFi.h>

// ==================== WiFi 账号密码 ====================
const char *ssid = "aaaa";            // 你要连接的 WiFi 名称
const char *password = "1234567890";  // WiFi 密码(至少8位)

// ==================== 静态 IP 设置(重点!) ====================
// 静态IP = 固定IP,ESP32每次开机都用这个IP,不会变
IPAddress ip(192, 168, 137, 100);     // ESP32 的固定 IP 地址
IPAddress gateway(192, 168, 137, 1);  // 路由器网关(一般是路由器IP)
IPAddress subnet(255, 255, 255, 0);   // 子网掩码(几乎都是这个)

// ==================== 初始化函数,只运行一次 ====================
void setup() {
  // 初始化串口,波特率 115200,用于查看连接信息
  Serial.begin(115200);

  // 等待 10ms,让系统稳定
  delay(10);

  // 设置 ESP32 为 STA 模式(客户端模式,连接路由器)
  WiFi.mode(WIFI_STA);

  // ==================== 关键:设置静态 IP ====================
  // 必须在 WiFi.begin() 之前设置
  // 让 ESP32 强制使用上面定义的固定IP,不自动获取
  WiFi.config(ip, gateway, subnet);

  // 串口打印:正在连接哪个 WiFi
  Serial.print("Connecting to ");
  Serial.println(ssid);

  // 开始连接 WiFi
  WiFi.begin(ssid, password);

  // ==================== 等待连接成功 ====================
  // 如果没连上,就一直循环打印点 ...
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);        // 延时 500ms
    Serial.print("."); // 打印一个点,表示正在连接
  }

  // 连接成功!
  Serial.println("");
  Serial.println("WiFi connected.");       // 提示:WiFi 已连接
  Serial.println("IP address: ");          // 提示:IP 地址
  Serial.println(WiFi.localIP());          // 打印 ESP32 的 IP(就是你设置的静态IP)
}

// 循环函数,这里空着,只需要开机连一次 WiFi
void loop() {
}

代码解释

  • IPAddress(a, b, c, d):创建一个 IPAddress 对象来表示 IP 地址。
  • WiFi.config(local_IP, gateway, subnet):在 WiFi.begin() 之前调用,用于配置静态 IP。如果配置失败,会返回 false

请确保你设置的 IP 地址、网关和子网掩码与你所在的局域网环境相匹配,且该 IP 未被其他设备占用。

AP 模式:配置静态 IP

// 引入ESP32 WiFi库,用于创建WiFi热点
#include <WiFi.h>

// ==================== 热点配置 ====================
const char *ssid = "ESP32S3-TEST";  // ESP32发出的热点名称
const char *password = "12345678";  // 热点密码(必须≥8位)

// ==================== 热点静态IP设置(自定义IP) ====================
IPAddress ip(192, 168, 5, 1);        // 热点自身的固定IP地址
IPAddress gateway(192, 168, 5, 1);   // 网关(和热点IP一致)
IPAddress subnet(255, 255, 255, 0);  // 子网掩码(默认即可)

// ==================== 初始化函数,只运行1次 ====================
void setup() {

  // 初始化串口,波特率115200,用于查看连接日志
  Serial.begin(115200);
  Serial.println();
  Serial.println("Configuring access point...");  // 提示:正在创建热点

  // ==================== 注册WiFi事件监听 ====================
  // 监听:有设备连接上热点
  WiFi.onEvent(WiFiStationConnected, WiFiEvent_t::ARDUINO_EVENT_WIFI_AP_STACONNECTED);
  // 监听:设备获取到IP地址
  WiFi.onEvent(WiFiStationGotIP, WiFiEvent_t::ARDUINO_EVENT_WIFI_AP_STAIPASSIGNED);
  // 监听:设备断开热点
  WiFi.onEvent(WiFiStationDisconnected, WiFiEvent_t::ARDUINO_EVENT_WIFI_AP_STADISCONNECTED);

  // ==================== 关键:设置热点静态IP ====================
  // 必须在创建热点 softAP() 之前调用
  // 让热点固定IP:192.168.5.1,不再使用默认的192.168.4.1
  WiFi.softAPConfig(ip, gateway, subnet);

  // ==================== 创建WiFi热点 ====================
  if (!WiFi.softAP(ssid, password)) {  // 如果热点创建失败
    Serial.println("Soft AP creation failed.");
    while (1);  // 程序卡死,停止运行
  }

  // 打印热点的IP地址(你设置的 192.168.5.1)
  Serial.print("AP IP address: ");
  Serial.println(WiFi.softAPIP());
}

// 循环函数,空着即可
void loop() {
}

// ==================== 事件1:有设备连接上热点 ====================
void WiFiStationConnected(WiFiEvent_t event, WiFiEventInfo_t info) {
  Serial.print("Device connected, MAC: ");  // 打印设备已连接
  // 打印连接设备的MAC地址
  Serial.println(macToString(info.wifi_ap_staconnected.mac));
}

// ==================== 事件2:设备成功获取IP ====================
void WiFiStationGotIP(WiFiEvent_t event, WiFiEventInfo_t info) {
  Serial.print("Device IP address: ");  // 打印设备IP
  // 打印手机/电脑获取到的IP地址(如 192.168.5.2)
  Serial.println(IPAddress(info.got_ip.ip_info.ip.addr));
}

// ==================== 事件3:设备断开热点 ====================
void WiFiStationDisconnected(WiFiEvent_t event, WiFiEventInfo_t info) {
  Serial.print("Device disconnected, MAC: ");  // 打印设备断开
  // 打印断开设备的MAC地址
  Serial.println(macToString(info.wifi_ap_stadisconnected.mac));
}

// ==================== 辅助函数:MAC地址转字符串 ====================
String macToString(const uint8_t *mac) {
  char buf[18];
  snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
           mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  return String(buf);
}

代码解释

  • WiFi.softAPConfig(local_IP, gateway, subnet):在 WiFi.softAP() 之前调用,为 ESP32 的 AP 模式设置自定义的 IP 地址、网关和子网掩码。
posted @ 2026-05-20 17:11  Q&25  阅读(8)  评论(0)    收藏  举报