STM32+ESP8266串口WiFi模块实战:AT指令配置与TCP透传全攻略

发布时间:2026/10/17 1:30:12
STM32+ESP8266串口WiFi模块实战:AT指令配置与TCP透传全攻略 做物联网项目的时候最常打交道的组合就是STM32开发板配一颗ESP8266串口WiFi模块。战舰开发板加ATK_ESP8266这套搭配我用过很多次从最开始对着手册敲AT命令都经常没反应到后来把WiFi连接、TCP透传、远程数据下发全部串通中间踩了不少坑。这篇文章就把整个配置过程重新梳理一遍从硬件接线、AT指令集、三种工作模式的实操配置到STM32代码怎么集成以及那些文档里不会写的排查经验尽量一次讲透。如果你正在用战舰开发板做联网类的小项目手上也有这颗ATK_ESP8266模块或者只是想搞明白串口WiFi到底怎么玩这篇内容应该能帮你少走不少弯路。1. 项目整体思路与硬件准备1.1 战舰开发板与ATK_ESP8266的接线关系战舰开发板是一块以STM32F103ZET6为主控的高端开发板板载资源很多其中一个很贴心的设计就是预留了ATK-ESP8266模块的专用接口。这个接口通常是6个针脚顺着丝印插上去就行不需要额外飞线默认对接的是USART2的串口也就是PA2TX和PA3RX。我第一次用时没仔细看原理图想着模块是串口驱动直接接USART1PA9/PA10结果在代码里绕了一大圈后面查资料才发现板子上的接口对应的其实是USART2才算把路子走正。如果你手里的模块是散装的没有专用座子那就按表接线ATK-ESP8266引脚开发板连接位置说明VCC3.3V模块电源必须3.3VGNDGND共地TXDUSART2_RXPA3模块的发送接开发板的接收交叉连接RXDUSART2_TXPA2模块的接收接开发板的发送交叉连接RST可接GPIO或悬空低电平复位悬空正常工作时即可IO_0悬空默认运行模式拉低时进入固件下载模式正常上电必须保证它是高电平或悬空这里最容易错的就是TXD和RXD的交叉关系。我见过不少新手把板子的TXD直接接到模块的TXD结果怎么发AT指令都没反应。串口设备的TX必须接对端RX这是第一课。1.2 供电规划与电平匹配经验ESP8266这颗芯片对供电比较敏感虽然标称工作电压是3.0V到3.6V开发板的3.3V输出看似能满足但真正跑起来有个问题——模块在WiFi发射瞬间的电流峰值可以拉到300mA甚至更高。战舰开发板板载的3.3V稳压器通常能提供几百毫安的电流短时间的峰值一般也能扛住但如果你发现模块连接WiFi的时候反复重启、或者AT指令返回一堆乱码首先别怀疑代码先怀疑是不是供电不足。解决的办法很简单从USB转TTL工具或者外部稳压模块单独取一路3.3V给ATK-ESP8266供电同时把开发板的地和模块的GND连在一起保持共地。电平方面不用担心STM32的IO口和ESP8266都是3.3V电平可以直接互连不需要额外的电平转换模块。如果哪天你换了一颗5V供电的模块才需要考虑分压或者加电平转换芯片。另外模块的天线最好远离开发板上的排针和金属结构件天线周围不要走线否则信号强度会下降得很明显实地测试中我遇到过同一个位置WiFi信号从-60dBm掉到-75dBm的情况就是因为天线旁边压了一根杜邦线。2. 固件与AT指令集要点2.1 确认固件版本与默认串口参数ATK-ESP8266出厂默认刷的是AT指令固件也就是说它出厂就带了一套“串口透传到网络”的解释程序。我们在STM32端要做的就是通过串口发送ASCII格式的AT指令让这个模块自己完成连接路由器、建立TCP连接等动作。上电后模块默认的串口波特率一般是115200数据位8位无校验1位停止位也就是常说的115200 8N1。但这里有个坑如果不是原装模块或者模块被刷过其他固件波特率可能会是9600甚至74880芯片内部启动打印时用的波特率。所以拿到模块第一件事是用串口调试助手挨个波特率扫一遍最稳的办法是发裸指令AT看哪个波特率下能收到OK。模块上电后不是立刻能接收指令的因为内部固件要启动这个过程大约需要2到3秒。上电后立刻疯狂发送AT大概率是没响应的。正确做法是等一到两秒先发一个AT看到返回OK再做下一步。我见过太多人卡在这一步以为模块坏了其实只是没给它启动的时间。还可以通过ATGMR指令查询固件版本。不同版本的AT固件在新版本中又加入了带_DEF后缀的指令。比如老版本直接ATCWMODE1设置工作模式新版本如果希望断电后保留设置需要用ATCWMODE_DEF1。这一点后面会在配置流程里再次提到。2.2 常用指令与返回值速查ESP8266的AT指令看起来复杂真正常用的其实就那么十几条按功能可以分成三类基础命令AT测试模块是否在线返回OKATRST软复位模块ATGMR查询固件版本ATE0关闭回显避免串口数据里混入发送的指令本身WiFi配置命令ATCWMODE1/2/3设置工作模式1是STA连路由器2是AP自己开热点3是双模式ATCWJAPSSID,password让模块以STA模式连接一个WiFi网络ATCWSAPSSID,password,通道号,加密方式配置AP热点ATCIFSR查询模块获取到的IP地址网络连接与数据传输命令ATCIPSTARTTCP,目标IP,端口建立TCP连接ATCIPCLOSE关闭连接ATCIPSEND长度发送指定长度的数据ATCIPMODE1开启透传模式ATCIPMODE0关闭透传模式回到点名发送模式需要特别注意所有AT指令必须以回车换行结尾即“\r\n”不是单独的“\n”也不是单纯回车。在串口调试助手里这是“发送新行”选项在STM32代码里就要手动加上“\r\n”。如果少了\r模块响应会非常奇怪或者干脆不响应。2.3 指令执行时序不要急着发下一条很多人的配置脚本写得很漂亮但执行起来就是失败原因大多是忽略了指令之间的时间关系。ESP8266的执行是串行化的上一条指令没有执行完下一条指令进来会直接返回BUSY或者ERROR。比如刚发完ATCWMODE1立刻发ATCWJAP模块还没切换好AP模式连接路由器的指令就会失败。我习惯的做法是每条指令后等待固定的足够长的时间再用AT指令返回的内容去做判断发现遇到STATUS:2这种中间状态就继续等待直到出现GET IP再放开下一步。简单说写脚本的时候要“等返回”而不是“盲延时”。3. 三种核心工作模式的配置实操3.1 第一步先用串口助手把模块打通不管最终是把模块接到STM32还是其他主控上调试的第一步永远是先把模块从开发板上拿下来或者不接主控用USB转TTL工具直接连电脑在串口调试助手环境里把模块调通。这一步的目的是剥离主控代码的干扰先确认模块本身没问题。具体操作USB转TTL的TXD接模块RXDRXD接模块TXDGND接GND3.3V供电。打开串口助手选择115200波特率勾选“发送新行”发送AT应该能看到模块回复OK。接着发送ATCWLAP模块会扫描当前环境里的WiFi并返回可见网络列表。如果这里能正常列出附近的SSID说明模块射频部分和串口通信都正常后续操作就可以放心进行了。这一步价值很大。上面的步骤走通了后面所有问题都会被限定在主控代码层面。3.2 STA模式让模块连接家里的路由器绝大多数物联网设备都需要连到已有路由器这就是STAStation模式。配置步骤如下设置模式 ATCWMODE1 返回OK连接路由器 ATCWJAP你的SSID,你的密码 这一步执行时间会长一些常见会等待几秒钟。成功后返回WIFI CONNECTED接下来还会返回WIFI GOT IP。出现WIFI GOT IP才能确认模块在路由器侧拿到了IP如果只出现WIFI CONNECTED而没有GOT IP说明连接其实是不完整的可能是DHCP出了问题也可能是路由器的加密方式不匹配。查询IP ATCIFSR 返回类似192.168.1.102这样的地址记下它后面PC端或者手机端连它的时候就靠这个IP。在实际使用中ATCWJAP这条指令的失败率是最高的原因通常是三个密码里带了特殊字符没有转义、连了5G频段ESP8266只支持2.4G、或者路由器开启了MAC地址过滤。排查顺序也是从这三个角度入手。3.3 AP模式让模块自己当热点有时现场根本没有路由器比如做野外数据采集手机直接连模块反而更方便。AP模式适合这种场景。配置命令 ATCWMODE2 ATCWSAPMyAP,12345678,1,3CWSAP的参数依次是SSID、密码、信道、加密方式加密方式填3代表WPA2-PSK这是目前兼容性最好的选择。配置成功后用手机搜索MyAP这个WiFi输入密码连接然后手机浏览器访问192.168.4.1就能和模块建立TCP/UDP通信了模块的默认IP通常固定是192.168.4.1。AP模式下模块相当于一个路由器所以同一局域网内的其他设备也可以直接访问这个IP在没有外网的环境里做联调非常方便。3.4 TCP通信与透传从指令模式到数据流模式做物联网项目时模块最终任务是跟服务器或手机App建立TCP连接并交换数据。先看非透传方式的TCP通信ATCIPSTARTTCP,192.168.1.100,8080 返回CONNECT OK表示建立连接成功。发送固定长度的数据 ATCIPSEND5 此时模块返回一个大于号“”然后输入hello模块发完数据后返回SEND OK。这种方式的问题在于每发一次数据都挨了两条AT指令的开销“ATCIPSEND5”和“”对于频繁上报数据的场景太啰嗦了。这时就要用透传模式。进入透传 ATCIPMODE1 ATCIPSEND 模块返回“”后所有通过串口输入的数据都会被直接打包发送到已建立的TCP连接上不再有AT指令纠缠就像串口线直接网线了一样。要退出透传不能发“ATCIPCLOSE”正确做法是直接发送不带回车换行的“”而且前后最好留1秒不发数据模块才会识别那是退出序列然后返回OK。我从串口助手直接点“”经常会失败最后还是写代码或者手动输入“”后不加回车才稳定退出。这里有一个工程上的建议如果项目的数据上有明确的数据帧格式比如一个指令帧头和CRC校验透传模式体验极佳。如果数据内容比较随机、不好靠协议切分还是建议用指令模式虽然效率低一点但不容易把“”这样的内容发送到网络端。4. STM32代码集成与调用4.1 USART2初始化与串口驱动代码接线确认没问题后STM32端的开发就是按照标准串口流程来。因为战舰开发板上的模块接口接的是USART2所以先初始化USART2为波特率1152008N1。同时打开中断让接收数据能及时被处理。下面是基于标准外设库的USART2初始化代码框架核心是GPIO和USART的配置void ESP8266_UART_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; USART_InitTypeDef USART_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); // PA2 TXPA3 RX GPIO_InitStructure.GPIO_Pin GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; GPIO_Init(GPIOA, GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, GPIO_InitStructure); USART_InitStructure.USART_BaudRate 115200; USART_InitStructure.USART_WordLength USART_WordLength_8b; USART_InitStructure.USART_StopBits USART_StopBits_1; USART_InitStructure.USART_Parity USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode USART_Mode_Rx | USART_Mode_Tx; USART_Init(USART2, USART_InitStructure); USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); NVIC_InitStructure.NVIC_IRQChannel USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority 1; NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; NVIC_Init(NVIC_InitStructure); USART_Cmd(USART2, ENABLE); }注意PA2是TX功能脚必须设置成复用推挽输出PA3是RX设置成浮空输入。这里的GPIO模式是标准库时代的写法如果用的是HAL库对应的模式是GPIO_MODE_AF_PP和GPIO_MODE_INPUT。中断处理函数中要做的事情很简单把收到的字节放进一个环形缓冲区供上层逻辑读取。这里特别注意不要在中断里做重活解析AT响应和等待超时都放在主循环里做。4.2 发送AT指令与响应解析ESP8266的AT指令交互逻辑非常直接发一条命令等一段时间检查返回的字符串里是否包含预期内容。核心函数就两个一个是发送字符串一个是等待期望内容。发送字符串直接用串口逐字节发送即可void ESP8266_SendCmd(char *cmd) { while (*cmd) { USART_SendData(USART2, *cmd); while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) RESET); } }等待响应并判断是否包含期望字符串uint8_t ESP8266_WaitResponse(char *expect, uint16_t timeout) { uint16_t i 0; uint32_t start 0; // 将接收缓冲区清空 clearRxBuffer(); while (1) { if (receiveBufferLen 0) { // 在缓冲区中查找expect if (strstr(receiveBuffer, expect) ! NULL) { return SUCCESS; } } if (i timeout) { return TIMEOUT; } delay_ms(1); } }实际工程里我通常会把这两个函数包一层做成一个带超时的完整指令执行接口uint8_t ESP8266_AT_Cmd(char *cmd, char *expect, uint16_t timeout) { clearRxBuffer(); ESP8266_SendCmd(cmd); return ESP8266_WaitResponse(expect, timeout); }使用时的典型流程是上电延时2秒发AT等OK发ATCWMODE1等OK发ATCWJAP等WIFI GOT IP发ATCIPSTART等CONNECT OK发ATCIPMODE1等OK发ATCIPSEND等“”之后直接开始用USART2发送业务数据这一套流程写下来一个可用的TCP透传通道就跑起来了。我建议把这些步骤封装成一个初始化函数不要在主循环里重复调用否则指令之间的时序很难控制。4.3 一个实际例子温湿度数据远程上报以常见的DHT11温湿度传感器为例STM32读取到温湿度后通过透传方式把JSON格式的数据发送到服务器char buffer[64]; sprintf(buffer, {\temp\:%d.%d,\hum\:%d.%d}\r\n, temp / 10, temp % 10, hum / 10, hum % 10); ESP8266_SendCmd(buffer);这行代码执行完数据就从串口、模WiFi、路由器一路到达服务器端了。在透传模式下不需要关心TCP分包这种事因为ESP8266固件底层会做数据打包和发送只要不是长时间不发数据、然后一次性发几KB一般不会出问题。这里有一个非常实用的建议在透传模式下不要用STM32的printf同时往同一个USART2输出调试信息和业务数据否则调试信息会被当成网络数据包发到服务器。我自己的项目里调试串口一律用USART1业务数据专用USART2两边彻底隔离排查问题就轻松多了。5. 常见问题排查与经验总结5.1 典型故障速查表现象原因解决方法发送AT无任何返回波特率不对依次尝试115200、9600、74880发送AT返回乱码波特率不匹配或供电不稳校准波特率检查供电电压返回ERROR但不清楚原因指令格式错误、缺少\r\n确认每条指令带\r\n确认参数格式ATCWJAP连接不上5G频段、密码特殊字符、MAC过滤换2.4G网络换纯数字密码测试模块反复重启供电不足外部3.3V供电共地透传模式下无法退出缺少发送时序不发\r\n手动发送前后停1秒网络数据丢包天线靠近干扰源调整天线位置远离金属和排针代码中模块无响应用了USART1而接口在USART2核对原理图确认串口号和引脚5.2 排查思路的先后顺序项目出了问题很多人喜欢一头扎进代码里改这改那。我建议按下面顺序排查效率最高第一硬件供电。用万用表量模块VCC和GND之间电压正常运行应该稳定在3.3V左右WiFi发射瞬间电压跌落不能超过0.1V太多。这一步能排除80%的奇怪问题。第二串口通信。把模块从开发板上断开用USB转TTL接电脑串口助手测试发AT看能不能收到OK。如果这里都不过代码层面完全不用看。第三AT指令交互。确认模块可以响应AT后按3.2节步骤操作一遍看模块在串口助手上能不能成功连上路由器并拿到IP。如果这个工作模式配置不过关写再多代码也是白费。第四再回到STM32代码。这时候我们要怀疑的就是自己的串口初始化、缓冲区、时序逻辑了。5.3 关于配置保存与掉电恢复最后说一个很多资料都忽略的细节就是模块的配置持久化。默认情况下ATCWMODE、ATCWJAP这些指令设置的模式只在当前上电周期有效断电后模块会恢复成出厂状态。如果项目每次上电都要重新执行一遍完整配置流程不仅费时间而且增加了出错的概率。解决方法是使用带_DEF后缀的指令比如ATCWJAP_DEF、ATCWMODE_DEF、ATCWSAP_DEF。这些指令会把配置写入模块内部Flash断电再上电仍然维持下次启动时模块会自己尝试连接之前保存的WiFi。实测下来保存成功后重新上电大约4到5秒就能连上路由器并拿到IP这比每次上电都跑一遍配置流程要可靠得多。不过要注意配置持久化后模块上电启动时间会比默认长一点因为在启动阶段模块自动尝试连接保存的网络。如果连不上会反复重试可能持续几十秒期间AT指令响应变慢。在调试中如果碰到这种情况不要以为模块卡死了耐心等待或者发送ATRST复位。5.4 我现在习惯的做法写了这么多如果让我只总结一条经验那就是先把模块当成独立器件调通再让它和主控代码产生关系。ATK-ESP8266这个模块本身很稳定大部分莫名其妙的问题都出在供电、串口对接和指令时序上。我一般会在板上预留一个短接开关或者跳帽方便随时把USART2的RX/TX切换到USB转TTL这样既能快速验证模块又不用反复拔线。还有一个小技巧是把整套AT指令配置流程用脚本固化下来。不管是写一个Python脚本用串口控制还是直接在STM32里做好状态机都比你每次开串口助手手动敲指令来得高效。尤其是当你要同时配置好几块模块的时候手工操作很容易漏掉状态判断脚本虽然丑但至少每个步骤都留了超时和错误检查出错时还能定位是第几步。做过的几个项目里这颗模块扮演的角色一直是“可靠的数据搬运工”。它不负责算力也不负责协议栈的复杂逻辑但只要你按照“供电稳定、串口正确、时序合理”这三条原则去对待它它就能七乘二十四小时稳定地帮你把下位机的数据送到你想送的地方。希望在读这篇文章的你也能少踩几个我当年踩过的坑把这个经典组合玩得顺手。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询