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():删除扫描结果以释放内存,是良好的编程习惯。
示例 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。
示例 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 地址。如果当前连接断开,它会自动尝试重连到列表中的其他可用网络。
示例 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 地址。当有设备连接或断开此热点时,相应的事件信息会被打印出来:
示例 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 地址、网关和子网掩码。
浙公网安备 33010602011771号