Skip to content

LV030-ATK-MW8266D联调与排错 ​

驱动写完只是开始。模块不上报、上报了但判不出帧、判出帧了却内容不对——这三类现象看起来都是"没有应答",实际定位手段完全不同。这一篇讲联调环境怎么搭、日志该长什么样,以及怎么用几个状态量把故障范围从"整个链路"缩小到"某一行代码"。

一、测试环境准备 ​

(1)PC 与模块连同一个 2.4 GHz 热点。ESP8266 不支持 5 GHz,这一步没做对,后面所有步骤都会莫名失败。

(2)在 PC 上开网络调试助手,建 TCP Server,端口 8080,记下 PC 的局域网 IP(ipconfig),填进 DEMO_TCP_SERVER_IP。

(3)串口助手连调试口,115200 8N1,用于看日志。

(4)先关掉 PC 防火墙,或为 8080 放行。

(5)把模块 IP、PC IP、服务器端口写在纸面上再开始,这三者任何一个记错都会表现为"连接超时"。

更省事的做法是保留一个 at <指令> 调试命令,不改代码就能逐条试指令,见LV025-ATK-MW8266D驱动实现里 API 一览的自测层部分。

二、预期日志 ​

初始化阶段(atk_mw8266d_init() 内部的 AT 测试成功会打印一行):

text
ATK-MW8266D_EOK
Joining to AP...
IP: 192.168.1.123

进入透传后,按键或周期发送的数据应当原样出现在网络调试助手的接收区;服务器下发的数据则出现在串口助手里:

text
AT test success!
Enter unvarnished!
This ATK-MW8266D TCP Connect Test.

日志的价值在于"基线":先确认正常时打印什么,故障时才知道哪一行消失了。AT test success! 没出现,说明卡在 AT 探测;出现了但 Joining to AP... 之后没有 IP,说明卡在联网——两个阶段要查的原因完全不同。

三、先看状态,再猜原因 ​

原始代码在自测失败时只打印"失败了",这没有信息量。改成把 USART3 的收发状态一并打出来:

c
// Drivers/BSP/ATK_MW8266D/atk_mw8266d_test.c
static void atk_print_uart_state(void)
{
    printf(ATK_TEST_TAG "  uart: rx_err=%u rx_st=%u rx_type=%u buf=%u/%u SR=%04X CR1=%04X\r\n",
           (unsigned int)atk_mw8266d_uart_rx_error_count(),
           (unsigned int)huart3.RxState,
           (unsigned int)huart3.ReceptionType,
           (unsigned int)(huart3.RxXferSize - huart3.RxXferCount),
           (unsigned int)huart3.RxXferSize,
           (unsigned int)huart3.Instance->SR,
           (unsigned int)huart3.Instance->CR1);
}

各字段的判读方式:

字段含义判读
buf=n/size已进缓冲但还没等到空闲中断的字节数大于 0 说明数据到了、IDLE 没上报;恒为 0 说明一个字节都没收到(模块没应答,或本地没发出去)
rx_err溢出、上一帧未取走就被覆盖等错误累计非 0 多半是电气/接线问题,或上一帧没被 rx_restart() 取走
rx_stHAL 的 RxStateBUSY 说明还在收;如果一直停不到 READY 而 buf 也在涨,就是 HAL 与自管逻辑打架
rx_typeHAL 的 ReceptionType决定 buf 是按哪个字段算的,换过接收方式时要对着看
SR状态寄存器快照看 RXNE(0x0020)、IDLE(0x0010)、ORE(0x0008)、FE/NE(0x0002/0x0004)哪一位亮着
CR1控制寄存器快照看 RXNEIE(0x0020)、IDLEIE(0x0010)、TE/RE(0x0008/0x0004)是否真的使能

buf 那一栏是最有价值的一个数:它把"模块没回"和"回了但没上报"这两件事直接分开——前者查硬件,后者查中断。后面那个故障复盘就是靠这个数字定位的,见at 命令全部返回 ERROR 的排查记录。

四、常见故障 ​

现象最可能的原因处理
init failed,10 次 AT 全无应答P8 跳线帽没短接 / TX-RX 没交叉 / PA4 一直低 / 波特率不符按接线与工程配置里的核对表逐条检查
偶发 init failed,重上电就好供电不足(峰值 200 mA)或复位后等待不足换稳的 3.3 V,把 500 ms 加到 800 ms
AT 有回应但 AT+RESTORE 超时模块重启较慢,3 s 不够把超时加到 5000 ms
join_ap 失败SSID 是 5 GHz / 密码错 / 信号弱 / MAC 过滤用手机热点验证;查 +CWJAP:<error code>(1 超时 2 密码错 3 找不到 AP 4 连接失败)
get_ip() 拿到乱码或空串没先 ATE0,第一对引号是回显的指令本身在 get_ip() 之前 ate_config(0)
connect tcp server 返回 ERROR服务器没启动 / 端口被占 / 不在同网段先用 PC 的 telnet 或第二个调试助手连一次
透传发数据,服务器收不到CIPSEND 没返回 >(没真正进入透传)/ 连接已断打印 enter_unvarnished() 的返回值;查模块是否打印 CLOSED
退出透传后 AT 无响应+++ 前后静默不足 1 s退出后 HAL_Delay(1000) 再发 AT
接收数据明显被截断帧缓冲深度上限(原厂 127、本工程 255 字节可用)加大 ATK_MW8266D_UART_RX_BUF_SIZE 或改环形缓冲
程序卡在某处不返回send_at_cmd 阻塞(最长 10 s)正常现象;需要并发就把 WIFI 流程挪到独立任务
慢指令一律返回超时等待窗口比指令本身还短(AT+CWJAP 官方建议 15 s)把窗口提到 15 s,快指令仍会提前返回
长 AT 指令被截断或判非法命令行缓冲只有 16 字节,且尾随空格被一起发给模块单行上限提到 64 字节;行尾空白裁掉再解析

五、已知限制 ​

(1)帧缓冲只有几百字节(原厂 128、本工程 256)。长应答(AT+CWLAP)与大数据块透传都会被截断,本驱动不适合这两类场景。

(2)全程阻塞式。send_at_cmd() 靠 HAL_Delay(1) 轮询,join_ap() 最坏 10 s,HAL_UART_Transmit 也是阻塞发送。裸机主循环里能接受,放进 RTOS 要注意任务栈与看门狗。

(3)get_ip() 依赖 ATE0。它用"第一个引号对"取 IP,回显开着时取到的是指令本身。这是实现上的取巧,不是协议保证。

(4)没有断线检测与重连。连接断开后模块只打印 CLOSED,驱动不解析、不上报,应用层无法感知。需要的话得自己增加 CLOSED/WIFI DISCONNECT 关键字检测。

(5)只封装了单连接 TCP 客户端 + 透传。多连接(CIPMUX=1)、TCP 服务器(CIPSERVER)、UDP、SSL 都没有封装,需要按同一模式自行扩展——send_at_cmd() 就是扩展的支点。

(6)透传下发无协议分帧。接收边界只靠总线空闲(约 20 ms 间隔)判定,没有长度、没有校验。要保证完整性,必须在应用层自己加帧头与 CRC。

(7)ret += ... 的累加判断只能回答"有没有失败"。建议移植时改为逐条判断并打印步骤名。