简介:面向使用正点原子开发板学习ESP8266 Wi-Fi联网的嵌入式开发者与物联网入门者,这套资料围绕模块硬件集成、AT指令控制、固件烧写和MCU程序移植展开,可解决从接线、联网到二次开发的具体问题。压缩包共57个文件、约127.67MB,以rar源码与工具包、pdf原理图/用户手册/数据手册、exe与bat驱动安装脚本为主,另含html入口、apk手机调试工具及少量图片说明,便于按硬件、软件、文档分类查阅。已有1759人学习下载。内容覆盖多款STM32开发板的测试实验源码、串口与网络调试助手、ESP8266 AT指令示例、固件烧写说明及手机端配网工具,既适合作为课堂实验与项目搭建的参考,也方便开发者对照原理图和手册排查通信、联网与升级中的常见问题。
1. 这块 ESP8266 的真正门槛不在联网,而在供电和固件
很多人拿到 ESP8266 WIFI 模块资料包,第一反应是翻出一份 AT 指令表,照着敲AT+CWJAP填上 SSID 和密码,以为这就完事了。真到板子上一跑,串口回来的常常是一串乱码,或者连上两三分钟就掉线。问题几乎不出在指令本身,而是 3.3V 电源给不出峰值电流、串口波特率对不上、固件里跑的其实不是 AT 指令集这三件事。这份资料包的价值不在教你背指令,而是把 AT 固件、SDK 源码、烧录工具、原理图和例程凑到一起,让「能连上」到「连得住」中间那段没人写的路有据可查。手上有串口模块和一块主控板、正要接 WIFI 需求的人,从这里开始最省时间。
2. 先定路线再上电:AT 透传和 SDK 开发的分水岭
同是 ESP8266,用 AT 固件当无线串口,和用 SDK 自己写固件,是两条几乎不重叠的路。选错了不是慢一点,而是资料包里一半的文件你都用不上,还会被互相矛盾的教程带着来回折腾。这一章先把判据讲清楚,再把手头的模块点亮到能回一个OK。
2.1 AT 固件与 SDK 的边界,用三个问题判断
第一个问题:你的板子上有没有一颗已经在跑业务逻辑的主控。如果有,ESP8266 就只是一个外设,走 AT 路线,主控通过串口发字符串,模块负责射频和协议栈,出问题时职责边界很干净——网络不通找模块,业务不对找主控。第二个问题:整机成本和小型化卡到哪一步。如果只做一颗温湿度上报节点,多一颗主控就多一份 BOM 和一份功耗,这时候把业务直接写进 ESP8266 的 SDK 工程里更划算。第三个问题:能不能接受调试手段的降级。AT 路线用串口助手就能看全过程,SDK 路线要面对 Makefile、链接地址、内存分布,出问题只能靠串口日志和rst cause反推。
| 维度 | AT 固件路线 | SDK 路线 |
|---|---|---|
| 前期上手 | 半天能通 | 两三天才能点亮 |
| 硬件成本 | 主控 + 模块 | 单模块 |
| 功能上限 | 受指令集限制,复杂逻辑要主控配合 | 可自定义协议、OTA、本地控制 |
| 调试手段 | 串口收发即所见 | 日志 + 地址表 + 内存排查 |
| 适合场景 | 主控已存在、快速联网改造 | 小体积节点、量产成本敏感 |
我一般建议:项目里已经有 MCU 的,别犹豫,直接 AT;只有一块裸模块、又想做成品的小项目,才进 SDK。资料包里两条路的材料都给了,但不要同时开工。
2.2 上电前的接线自检:六个引脚决定它能不能启动
ESP8266 上电先看启动脚状态,脚位错了,串口只会一直吐乱码或者干脆没反应,你会误以为是模块坏了。常见做法是把下面这张表对着原理图核一遍再插电。
| 引脚 | 运行模式 | 下载模式 | 说明 |
|---|---|---|---|
| VCC | 3.3V | 3.3V | 峰值电流按 500mA 留余量 |
| GND | 共地 | 共地 | 必须和 USB-TTL 共地 |
| EN / CH_PD | 高 | 高 | 悬空必挂,10k 上拉到 3.3V |
| GPIO0 | 高 | 低 | 拉低才进烧录 |
| GPIO2 | 高 | 高 | 上电瞬间不能为低 |
| GPIO15 | 低 | 低 | 10k 下拉到地 |
| RST | 高 | 高 | 复位低有效 |
供电是翻车率最高的一环。USB-TTL 小板上标着 3.3V 的那根针,多数只能给出一百多毫安的余量,模块一发射就掉压重启,表现是「连上就断」。正确做法是单独给 3.3V,模块电源脚旁边并 100uF 电解加 0.1uF 瓷片,走线尽量短。另外 ESP8266 的 IO 不是 5V 兼容,主控如果是 5V 电平,串口线上要加电平转换,别抱着「试一下说不定能行」的心态。
2.3 用一段 Python 脚本把 AT 握手跑通
接好线之后先别急着写业务,用最少的代码确认「模块活着、波特率对、固件是 AT」。下面这段脚本把回显关掉、读版本、设工作模式一次做完。
import serial, time # 115200 是 AT 固件最常见的出厂波特率,8N1,无硬件流控 ser = serial.Serial("COM3", 115200, timeout=1) ser.dtr = False # 部分 USB-TTL 的 DTR/RTS 会拉住 EN 和 GPIO0,先释放 ser.rts = False def at(cmd, wait=1.0): ser.reset_input_buffer() # 清掉上一次的残留,避免读到旧响应 ser.write((cmd + "\r\n").encode()) time.sleep(wait) # 入网类指令要给足时间,普通指令 0.3s 够 return ser.read(ser.in_waiting or 1).decode(errors="ignore") print(at("AT")) # 期望回 OK,没回就是线或波特率的问题 print(at("ATE0")) # 关回显,之后读到的都是纯响应,好解析 print(at("AT+GMR")) # 固件版本,先记下来,后面查资料要对得上 print(at("AT+CWMODE=1")) # 1=Station 2=AP 3=AP+Station,先设成站点模式参数说明:timeout控制单次读取等待,设太小会在入网时读到半截字符串;wait是每条指令后的固定延时,AT+CWJAP这类要连路由的指令建议给到 8 秒以上;\r\n不能省,AT 固件以回车换行作为帧结束;ATE0这一句看似可有可无,但开着回显时你的响应里会混进自己发出去的指令,后面写解析逻辑会额外多出一堆判断。
如果这里回的是busy p...或者一串ets Jan 8 2013,rst cause:2,说明模块在反复重启,先回去查供电和 EN 脚,不要怀疑指令。如果完全无响应,把波特率换成 74880 再听一次——那是芯片启动日志的波特率,能听到日志说明模块是好的,只是固件不是 AT 或者波特率被改过。
3. 打通一条完整链路:入网、建连、透传的指令序列
握手通过只是证明模块能说话,真正要交付的是「数据从主控发出去、从服务器回来」这条通路。这一章按入网、建连、透传三段拆开,每段给出可以直接抄的指令序列和失败时的判断依据,顺带把掉线重连这件事写清楚。
3.1 入网四步:模式、扫描、连接、查 IP
顺序不能乱,CWMODE没设成 1 就去CWJAP,返回的会是ERROR,很多人在这里以为是密码错了。
# 1. 设为 Station 模式 AT+CWMODE=1 # 2. 扫一眼周围热点,确认 SSID 拼写和信号强度 AT+CWLAP # 3. 连接路由,注意 SSID 和密码都要带双引号,逗号是英文逗号 AT+CWJAP="your_ssid","your_password" # 4. 拿到 IP 才算真正入网 AT+CIFSRAT+CWJAP成功回WIFI CONNECTED再回WIFI GOT IP,最后才是OK。只回WIFI CONNECTED没有GOT IP,说明链路层通了但 DHCP 没拿到地址,先看路由的地址池是不是满了,或者安全类型是不是只支持 WPA2。AT+CIFSR返回的STAIP就是模块地址,后面组网测试要拿它对着看。这一组指令的失败重试不要写死循环,模块连续三次连不上同一个 SSID 会进入保护状态,正确做法是AT+RST之后再重来,间隔放到 5 秒以上。
3.2 单连接与多连接:CIPMUX必须先定
AT+CIPMUX=0是单连接,CIPSTART只带协议、地址、端口三个参数;AT+CIPMUX=1是多连接,CIPSTART的第一个参数是连接号 id。这两种模式的参数格式不一样,混用必然ERROR,而且报错信息不会告诉你哪里错了。
AT+CIPMUX=0 # 单连接,多数透传场景够用 AT+CIPSTART="TCP","192.168.1.100",8080 # 单连接写法 AT+CIPMODE=1 # 开启透传 AT+CIPSEND # 回一个 > 之后,后面发的都是数据 # 退出透传:先静默 1 秒以上,发三个加号,不要带回车 ++++++这个退出序列是个经典坑:前后各要至少 1 秒的静默,中间不能夹任何其他字节,也不能加回车换行。很多人习惯性在串口助手里勾了「发送新行」,结果+++变成了数据本身的一部分,被原样发给了服务器,模块则一直卡在透传里出不来。判断依据很直接:发完+++大约一秒后应该收到OK,没收到就是时序不对。
如果是服务器主动下发指令、模块定时上报这种一问一答的场景,别用透传,用普通模式更可控:AT+CIPSEND=<长度>,等模块回>,再发正好这么多字节。长度算错(比如中文按字符数而不是字节数)会直接SEND FAIL。
3.3 掉线重连:把CLOSED当成常态处理
现场环境里 TCP 连接被中间设备回收是常态,代码里把CLOSED当异常才是异常。我一般写成「状态机 + 有限重试」:心跳发出去 3 次没回SEND OK,主动AT+CIPCLOSE,再CIPSTART;连续 5 次重建失败,直接AT+RST从头走一遍入网流程。
def ensure_link(): r = at("AT+CIPSTATUS", 0.5) if "STATUS:4" in r or "STATUS:5" in r: # 4=断开 5=未入网 at("AT+CIPCLOSE", 0.5) at('AT+CIPSTART="TCP","192.168.1.100",8080', 5) return "reconnect" return "ok"这段的关键不是重连本身,而是CIPSTATUS的状态码比字符串匹配可靠得多,别去 grepCLOSED关键字,透传模式下那条提示未必会打出来。另外心跳间隔别小于 30 秒,太频繁会被服务器侧当成异常流量断掉;也不建议超过 120 秒,中间设备普遍在两分钟左右回收空闲连接。
4. 走 SDK 路线:工程结构、编译开关与烧录地址表
AT 路线卡住的大多是接线和时序,SDK 路线卡住的几乎全是地址。编译出一堆 bin 文件只是第一步,把哪个 bin 烧到哪个偏移,错一个字节就是无限重启,而串口只会给你一句rst cause:4。这一章把工程结构、Makefile 里真正会改到的四个开关和一张地址表摊开说。
4.1 工程目录:真正要动的只有三类文件
资料包里的 SDK 工程一般长这样:app/放用户业务,user/放user_init.c和几个回调,include/放头文件,driver/放串口、GPIO 这类底层,根目录一个Makefile加一个gen_misc.sh之类的编译脚本。第一次上手不要把整个目录通读一遍,只看三处:user/user_main.c里的user_init(),这是入口;Makefile顶部的几个BOOT=、SPI_SPEED=、SPI_MODE=、SPI_SIZE_MAP=;以及include/user_config.h里跟串口打印相关的宏。
user_init()里我一般先干三件事:把串口波特率设成 115200 并打开打印、把 station 参数用代码写死(避免调试期还要靠 AT 配网)、注册一个定时器先闪灯。闪灯能跑起来,说明编译链、烧录地址、启动流程全对,这时候再接 WIFI 逻辑,出问题能立刻分层。
4.2 Makefile 的四个开关与烧录地址
SPI_SIZE_MAP是最容易错的一个,它决定 flash 容量,也决定esp_init_data_default.bin烧到哪里。改错了,模块会一直重启或者射频参数读不出来。
| SPI_SIZE_MAP | flash 容量 | init_data 偏移 |
|---|---|---|
| 0 | 512KB | 0x7C000 |
| 2 | 1MB | 0xFC000 |
| 4 | 2MB | 0x1FC000 |
| 5 | 2MB | 0x1FC000 |
| 6 | 4MB | 0x3FC000 |
编译和烧录按顺序来,命令行参数和 Makefile 里的开关必须保持一致,否则编出来的 bin 和烧录地址对不上:
# 编译:BOOT=new 表示新启动模式,APP=1 编用户1区,参数与 Makefile 保持一致 make COMPILE=gcc BOOT=new APP=1 SPI_SPEED=40 SPI_MODE=DIO SPI_SIZE_MAP=6 # 烧录:文件名以 bin 目录下实际生成的为准,地址一个都不能猜 esptool.py --port COM3 --baud 460800 write_flash \ --flash_mode dio --flash_size 4MB \ 0x00000 boot.bin \ 0x01000 user1.bin \ 0x3FC000 esp_init_data_default.bin \ 0x3FE000 blank.bin参数说明:SPI_SPEED=40是 40MHz,SPI_MODE=DIO是双线模式,两者要和烧录命令里的--flash_mode、--flash_size严格一致;0x00000永远是启动区,0x01000是用户区起点,esp_init_data_default.bin必须落在上表对应的偏移;blank.bin用来初始化射频参数区,不烧也能跑,但信号强度和功耗会不正常。烧录波特率给到 460800 能快不少,如果报同步失败,降到 115200 重来。
4.3 串口日志怎么读:rst cause是唯一的黑匣子
SDK 出问题没有断点,只有串口。启动日志里那行rst cause:N基本能定方向:1是上电复位,2是外部复位,4是软件看门狗,6是硬件看门狗。上电就无限rst cause:1,先查供电;跑着跑着变成4,多半是某个任务里死循环或者阻塞太久没喂狗,把耗时操作拆成状态机基本能解决。
启动日志的波特率是 74880,业务打印的波特率是你自己设的 115200,两者不一样。所以「上电那一段是乱码,后面就正常了」是正常现象,不是故障。真要看清楚启动信息,把串口助手切到 74880 抓一次,能拿到 flash 容量、启动模式、固件头部校验结果,比猜快得多。
5. 避坑与排查:五个把新手挡在门外的现场现象
下面五条是我在实际调试里反复遇到的,几乎覆盖了九成「模块好像坏了」的报修。写法统一按现象、原因、解决来,遇到对应症状直接对号入座。
现象一:串口一直吐ets Jan 8 2013,rst cause:1,间隔几百毫秒一次。原因:供电带不动。模块发射瞬间电流冲到三百多毫安,USB-TTL 的 3.3V 直接掉压,芯片欠压复位,看起来就像在不停重启。 解决:换独立 3.3V 电源,模块电源脚并 100uF 加 0.1uF,走线缩短;用万用表量发射瞬间的电压,掉到 3.0V 以下就是它。
现象二:发AT完全没反应,换 74880 能听到启动日志。原因:跑的不是 AT 固件,或者波特率被前一个工程改掉了;还有一种可能是 GPIO0 被拉低,芯片每次上电都停在下载模式等烧录。 解决:先确认 GPIO0 上电为高,再重新烧一遍 AT 固件;如果手上没有固件文件,就干脆走 SDK 路线,别在半路纠结。
现象三:AT+CWJAP一直回FAIL,但手机能连上同一个热点。原因:SSID 里有中文或空格、安全类型是 WPA3、路由开了 MAC 过滤,或者模块还停在上一次的连接状态里没释放。 解决:先用AT+CWLAP看能不能扫到目标 SSID,扫不到是信道或天线问题;扫得到就AT+RST重启后再连,密码里带特殊字符的先改成纯字母数字试一次。
现象四:进了透传之后退不出来,服务器那边收到一堆乱码。原因:串口助手勾了「发送新行」,+++变成了带回车的数据帧;或者三个加号之间间隔太久,没被识别成转义序列。 解决:关掉自动换行,前后各留 1 秒静默,一次性发完+++。如果已经卡死,只能AT+RST硬复位,透传模式本身没有其他退出方式。
现象五:SDK 工程烧完就无限重启,日志里rst cause:2反复出现。原因:烧录地址和SPI_SIZE_MAP不匹配,尤其是esp_init_data_default.bin偏移写错,射频参数读出来是非法值。 解决:对着第 4 章那张表重新核一遍地址,把 flash 整片擦除后按0x00000 / 0x01000 / init_data / blank的顺序重烧,别只覆盖用户区。
6. 把「能连上」变成「连得住」:一轮 24 小时压测的做法
演示桌上连一次成功,说明不了任何问题。真正决定这个模块能不能进项目的,是它在弱信号、路由重启、服务器主动断开这些情况下的表现。我的习惯是上线前跑一轮 24 小时压测,用一个脚本每 10 秒发一包带序号的心跳,同时记录四类数据:首次入网耗时、掉线次数、重连成功耗时、以及AT+CIPSTATUS里读到的 RSSI。
| 指标 | 采集方式 | 及格线 |
|---|---|---|
| 首次入网耗时 | 上电到GOT IP的时间戳差 | 稳定在 8 秒内 |
| 24 小时掉线次数 | 统计CLOSED到重建成功的次数 | 不超过 3 次 |
| 重连成功耗时 | 断线到再次SEND OK | 20 秒内恢复 |
| 空闲 RSSI | 定时读信号强度 | 高于 -75dBm |
| 心跳丢失率 | 发出的序号对端未收到比例 | 低于 1% |
压测过程中故意做两件事:中途把路由断电 30 秒再上电,看模块能不能自己爬回来;以及在数据发送过程中拔掉天线附近遮挡,制造一次信号跌落。这两下之后还能自愈的,才敢往现场发。另外一个容易被忽略的点是功耗——如果设备是电池供电,把AT+CWJAP的重连间隔从 5 秒放宽到 30 秒,再配合AT+SLEEP=1的浅睡眠,整体续航差别能有几倍,代价是响应变慢,这笔账要在需求阶段就算清楚。
还有一个只有长期跑才看得出来的现象:模块连续工作几天后,AT+CIFSR拿到的还是旧 IP,CIPSTART却一直失败。原因是路由侧租约到期而模块没重新走 DHCP,这时候别在应用层死重试,直接AT+RST从头入网最快。我后来干脆在脚本里加了一条规则:连续 5 次重建失败就整机复位,把这个不确定性交给最可靠的那条路。
从那以后我每次拿到新模块,第一件事不是写业务,而是先跑一遍这个压测脚本,让它自己在边上跑一天,第二天再看数据说话。上面这些参数没有一条是我从文档里抄来的,全是被掉线、被重启、被+++卡死之后一条条试出来的。希望帮到你。
本文还有配套的精品资源,点击获取