4、ESP32 Wi-Fi AP模式:SoftAP初始化、配置热点参数、STA连接管理
说实话,很多做IoT的朋友一上来就盯着MQTT协议本身,却忽略了底层的Wi-Fi连接。我见过不少项目,明明代码逻辑没问题,设备就是连不上云,最后排查下来——Wi-Fi初始化顺序错了,或者AP参数配得不对。
这一章,咱们就专门啃这块硬骨头。ESP32的SoftAP模式,说白了就是让芯片自己变成一个Wi-Fi热点。手机、电脑或者其他设备可以直接连上来,不需要经过路由器。这在设备配网、本地调试、甚至点对点通信场景下非常实用。
核心要点: SoftAP模式下,ESP32既是接入点,也是服务器。你需要自己管理IP地址、客户端连接数、以及安全认证。
4.1 SoftAP初始化流程
我个人习惯把初始化分成三步走:网络接口初始化 → 参数配置 → 启动AP。少一步都不行。
- 初始化网络接口:调用
esp_netif_init()和esp_event_loop_create_default()。这是ESP-IDF的底层基础设施,所有网络功能都依赖它。 - 创建默认AP网络接口:使用
esp_netif_create_default_wifi_ap()。这个函数会帮你把TCP/IP协议栈和Wi-Fi驱动绑定好。 - 初始化Wi-Fi驱动:
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); esp_wifi_init(&cfg);。嗯,这里要注意,WIFI_INIT_CONFIG_DEFAULT宏会帮你填好大部分参数,但如果你对内存占用有要求,可以手动调整。
// 标准初始化代码片段
esp_netif_init();
esp_event_loop_create_default();
esp_netif_t *ap_netif = esp_netif_create_default_wifi_ap();
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
esp_wifi_init(&cfg);
esp_wifi_set_mode(WIFI_MODE_AP);
esp_wifi_start();
我的经验: 曾经在一个低功耗项目里,我为了省内存,把
WIFI_INIT_CONFIG_DEFAULT 里的 static_rx_buf_num 从10改成了4。结果客户端一多就丢包。后来老老实实改回默认值,问题解决。内存省那几百字节,真不如稳定性重要。
4.2 配置热点参数
热点参数配置,核心就是填充 wifi_config_t 结构体。你想想看,一个Wi-Fi热点,最重要的无非就是:SSID(名字)、密码、信道、最大连接数。
| 参数 | 说明 | 建议值 |
|---|---|---|
ssid |
热点名称,最长32字节 | 建议带设备标识,如 ESP32_DEV_01 |
password |
密码,至少8位,最长64字节 | 开放热点可留空,但生产环境不建议 |
channel |
Wi-Fi信道,1~13 | 默认1,如果周围干扰大可以手动指定 |
max_connection |
最大允许连接的STA数量 | ESP32默认4,最多10 |
authmode |
认证模式 | 推荐 WIFI_AUTH_WPA2_PSK |
wifi_config_t wifi_config = {
.ap = {
.ssid = "ESP32_Hotspot",
.ssid_len = strlen("ESP32_Hotspot"),
.password = "12345678",
.channel = 1,
.max_connection = 4,
.authmode = WIFI_AUTH_WPA2_PSK
},
};
esp_wifi_set_config(WIFI_IF_AP, &wifi_config);
避坑指南: 我曾经遇到过一个问题——密码设置成
"1234567"(7位),结果热点死活起不来。后来查文档才发现,WPA2-PSK模式要求密码至少8位。另外,SSID如果包含中文,需要先转成UTF-8编码,否则客户端看到的会是乱码。
4.3 STA连接管理
AP模式建好了,接下来就是管理那些连上来的STA(Station,也就是客户端设备)。ESP32提供了事件回调机制,你可以监听客户端连接、断开的事件,然后做相应的处理。
我个人习惯在事件循环里注册两个关键事件:
WIFI_EVENT_AP_STACONNECTED:有设备连上来了。这时候可以获取它的MAC地址,记录到列表里。WIFI_EVENT_AP_STADISCONNECTED:设备断开了。清理资源,或者更新连接状态。
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
if (event_id == WIFI_EVENT_AP_STACONNECTED) {
wifi_event_ap_staconnected_t* event = (wifi_event_ap_staconnected_t*) event_data;
printf("设备连入,MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
event->mac[0], event->mac[1], event->mac[2],
event->mac[3], event->mac[4], event->mac[5]);
} else if (event_id == WIFI_EVENT_AP_STADISCONNECTED) {
wifi_event_ap_stadisconnected_t* event = (wifi_event_ap_stadisconnected_t*) event_data;
printf("设备断开,MAC: %02x:%02x:%02x:%02x:%02x:%02x\n",
event->mac[0], event->mac[1], event->mac[2],
event->mac[3], event->mac[4], event->mac[5]);
}
}
你还可以通过 esp_wifi_ap_get_sta_list() 主动查询当前所有连接的客户端。这个函数会返回一个 wifi_sta_list_t 结构体,里面包含了每个客户端的MAC地址和对应的接口信息。
实用技巧: 我在做智能家居网关时,会在STA连接事件里给每个新设备分配一个本地IP(通过DHCP服务器),同时启动一个超时计时器。如果设备在30秒内没有发送任何数据,就主动断开它,防止僵尸连接占满
max_connection。
4.4 知识结构总览
下面这张图,是我自己梳理的SoftAP模式核心逻辑。你可以把它当作一个快速参考。
4.5 完整示例:一个可用的SoftAP热点
把上面所有的知识点串起来,就是一个完整的SoftAP示例。我通常会把它封装成一个函数,方便在项目里直接调用。
void start_softap(void)
{
// 1. 初始化网络接口
esp_netif_init();
esp_event_loop_create_default();
esp_netif_create_default_wifi_ap();
// 2. 初始化Wi-Fi
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
esp_wifi_init(&cfg);
// 3. 注册事件回调
esp_event_handler_instance_register(WIFI_EVENT,
ESP_EVENT_ANY_ID,
&wifi_event_handler,
NULL,
NULL);
// 4. 配置AP参数
wifi_config_t wifi_config = {
.ap = {
.ssid = "ESP32_AP_DEMO",
.ssid_len = 12,
.password = "iot123456",
.max_connection = 4,
.authmode = WIFI_AUTH_WPA2_PSK
},
};
esp_wifi_set_mode(WIFI_MODE_AP);
esp_wifi_set_config(WIFI_IF_AP, &wifi_config);
// 5. 启动
esp_wifi_start();
printf("SoftAP 已启动,SSID: ESP32_AP_DEMO\n");
}
注意: 上面的代码里,我故意把
ssid_len 写成了12,和SSID字符串长度一致。如果你不设置 ssid_len,系统会自动用 strlen 计算。但如果你SSID里包含 \0 字符(虽然很少见),就一定要手动指定长度。
好了,这一章的内容就这些。SoftAP模式是ESP32网络编程的基础,搞懂了它,后面做配网、做本地控制面板都会顺手很多。你可以在自己的开发板上试试,用手机搜一下看看能不能看到 ESP32_AP_DEMO 这个热点。