WiFi模块是嵌入式设备接入网络最常用的方案之一,比如ESP8266、ESP32这类芯片,成本低、生态成熟,几乎成了物联网项目的标配。不过拿到模块之后的第一件事,往往就是让它能扫描到周边的WiFi、连接上路由器,或者自己变成一个热点供手机连接。这篇文章就把这三个核心功能逐一拆解,配合可直接运行的代码,帮你把无线链路跑通。

一、STA模式:扫描周边WiFi网络
WiFi模块一般有两种工作模式:STA和AP。STA(Station)模式下,模块作为一个客户端,像手机一样去连接已有的路由器;AP(Access Point)模式下,模块自己发出热点,让别人来连它。扫描功能属于STA模式的基础操作,只有先拿到周边网络的SSID列表,后续的连接才有依据。
如果你用的是刷了AT固件的ESP8266模块,扫描只需要一条指令:
AT+CWLAP +CWLAP:(3,"HomeWiFi",-52,"a1:b2:c3:d4:e5:f6",6) +CWLAP:(4,"Office_5G",-71,"11:22:33:44:55:66",11) OK
返回结果里第一个数字是加密方式,比如3代表WPA2_PSK,4代表WPA_WPA2_PSK;后面依次是SSID、信号强度(RSSI,数值越接近0信号越好)、MAC地址和信道。信号强度这一项很实用,做设备配网或者位置相关的应用时,可以通过多轮扫描的RSSI变化做粗略判断。
如果用Arduino框架或者ESP-IDF写代码,直接调用扫描API即可。以Arduino为例:
#include "ESP8266WiFi.h"
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
// 同步扫描,阻塞直到完成,返回网络数量
int n = WiFi.scanNetworks();
Serial.printf("发现 %d 个网络\n", n);
for (int i = 0; i < n; i++) {
Serial.printf("%d: %s (%d dBm) %s\n", i + 1,
WiFi.SSID(i).c_str(),
WiFi.RSSI(i),
WiFi.encryptionType(i) == ENC_TYPE_NONE ? "开放" : "加密");
}
}
需要注意的是,scanNetworks是阻塞式调用,扫描一次大约需要2到3秒。如果项目对主循环的实时性有要求,应该改用scanNetworksAsync异步接口,扫描完成后通过回调函数获取结果,扫描期间CPU可以继续处理其他任务。另外扫描动作会暂时离开当前信道,如果设备已经连上了路由器并且有TCP长连接在跑,扫描可能导致短暂丢包,这一点在写代码时要提前考虑。
二、连接路由器与断线重连
扫描到目标网络之后,连接过程就是把SSID和密码交给模块。AT固件方式下的指令序列如下:
AT+CWMODE=1 AT+CWJAP="HomeWiFi","your_password" WIFI CONNECTED WIFI GOT IP OK
AT+CWMODE=1把模块设为纯STA模式,AT+CWJAP执行连接。看到WIFI GOT IP说明模块已经从路由器拿到了IP地址,此时可以用AT+CIFSR查询本机IP,确认联网成功。
代码方式下,Arduino的连接逻辑非常简洁:
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin("HomeWiFi", "your_password");
Serial.print("连接中");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.printf("\n连接成功,IP地址: %s\n", WiFi.localIP().toString().c_str());
}
void loop() {
// 检测连接状态,掉线自动重连
if (WiFi.status() != WL_CONNECTED) {
WiFi.reconnect();
}
delay(1000);
}
连接失败时不要急着怀疑代码,先按顺序排查几个常见原因:密码错误是最普遍的,模块一般会在3到20秒后返回连接失败;其次是路由器开启了2.4G与5G双频合一,部分老固件的模块不支持5G频段,需要确认连的是2.4G热点;再就是路由器设置了MAC地址过滤或者隐藏了SSID,隐藏SSID时需要在连接指令中显式指定。信号太弱也会导致反复断连,如果RSSI低于-85 dBm,建议先改善天线位置再调试软件层面的重连逻辑。
断线重连建议不要简单地在循环里高频调用begin,频繁的连接请求可能被路由器限流。更稳妥的做法是检测到掉线后等待几秒再重试,并做好指数退避,重连间隔从5秒逐步拉长到60秒,避免网络波动时设备反复冲击路由器。
三、AP模式:创建自己的热点
AP模式适合设备还没有联网、需要用户先通过手机完成配网的场景,比如智能插座首次使用时发出的那个配置热点。切换到AP模式并创建热点的AT指令如下:
AT+CWMODE=2 AT+CWSAP="MyDevice_1234","12345678",5,3 OK
AT+CWSAP的四个参数分别是SSID、密码、信道和加密方式。密码至少8位,否则会报错。设置完成后手机就能搜到这个热点,连接后模块默认网关一般是192.168.4.1,可以通过这个地址访问模块上运行的配置页面。
代码方式创建热点同样简单:
#include "ESP8266WiFi.h"
void setup() {
Serial.begin(115200);
WiFi.mode(WIFI_AP);
bool ok = WiFi.softAP("MyDevice_1234", "12345678", 5, 0, 4);
// 参数依次为:SSID、密码、信道、是否隐藏SSID、最大连接数
if (ok) {
Serial.printf("热点已创建,IP: %s\n", WiFi.softAPIP().toString().c_str());
}
}
最后一个参数是最大接入数,ESP8266在AP模式下最多支持4个客户端同时连接,ESP32可以更多。如果希望不设密码的开放热点,把密码参数传null即可,但开放热点存在被蹭网和流量劫持的风险,正式产品不建议这样做。
四、AP与STA共存的混合模式
实际项目里最常用的其实是AP_STA混合模式:设备一边连着家里的路由器上传数据,一边保留自己的热点供调试或配网使用。设置方法是把模式参数改为3:
AT+CWMODE=3 AT+CWJAP="HomeWiFi","your_password"
WiFi.mode(WIFI_AP_STA);
WiFi.softAP("MyDevice_1234", "12345678");
WiFi.begin("HomeWiFi", "your_password");
混合模式下要注意信道冲突问题:AP和STA共用一个射频,模块会优先跟随STA连接的路由器信道,AP热点的信道会被自动对齐。如果路由器工作在信道11,而你创建AP时指定的信道是6,实际发出的热点会在11信道上。因此混合模式下手动指定AP信道意义不大,交给模块自动处理即可。
另外,双模式同时运行会增加功耗和内存占用,ESP8266内存较小,同时跑AP、STA和多个TCP连接时可能出现内存不足的情况,如果遇到莫名其妙的复位,可以检查一下剩余堆内存,必要时减少连接数或换用ESP32。
五、调试阶段的几个实用建议
调试WiFi问题时,串口日志是最好的朋友。建议在关键节点打印状态码和RSSI,而不是只打印成功或失败,这样能快速定位是密码错误、信号问题还是路由器拒绝连接。其次,AT固件调试时注意串口波特率要和固件配置一致,默认115200,乱码基本都是波特率不匹配造成的。
供电也是容易被忽略的坑。WiFi模块在发射瞬间电流可达300 mA以上,如果用USB转TTL直接供电,很多转接板只能提供100 mA左右,会出现模块反复重启、连接时掉线的现象。调试时最好用独立的3.3V电源,并在模块电源引脚附近加一个470 μF左右的电容来吸收电流尖峰。把供电、天线、固件这几点确认无误后,扫描、连接、热点这三步功能基本都能一次跑通,后续就可以在此基础上搭建TCP通信、MQTT上报等上层应用了。