简介:面向STM32F4嵌入式开发者,这份资源演示EC20模块TCP透传模式通讯,覆盖AT命令配置、串口交互、TCP连接建立与数据收发,适合快速上手4G模块与单片机联调的工程师或学习者。压缩包共174个文件,约4.06MB,以C源文件(48个)和头文件(46个)为主,另有uvproj工程、axf/hex编译产物及map/lst等辅助文件,便于参考或移植到自己的工程。资源对PDP上下文配置、GPRS/4G激活、CIPSTART连接、数据收发、CIPCLOSE关闭等均有说明,同时包含PWM、定时器、ADC、RCC、FLASH、CAN等驱动源码,可作为STM32F4外设开发的综合示例。目前已有1358人学习下载,适合正在调试EC20透传通信或了解AT命令交互细节的开发者。
1. 拿到这份 EC20 透传工程:STM32F4 用户最该先看的联网方案
做远程设备数据采集的时候,最常用的组合就是"STM32F4系列 + EC20 模块 + TCP透传模式"。很多第一次摸 4G 模块的开发者都会卡在同一个地方:模块明明能收到 AT 指令,可数据就是上不了服务器;要不就是进了透传模式之后再也退不出来。这份带完整源码的工程包,把 EC20 的 TCP 透传通讯流程整个串起来了,从开机注网、TCP 建连到双向数据转发,全部是可以在 STM32F4 上直接编译运行的代码。适合正在做联网网关、远程监控或者纯数据上报项目的开发者,也适合还不太确定透传模式和指令模式怎么选的初学者。下面我会按工程的实际使用顺序,从原理讲到代码,再讲几个我实际踩过的坑。
2. EC20 联网流程与透传模式选型:先搞清模块在干什么
2.1 从开机到 TCP 连接:EC20 要过四道关
很多人拿到 EC20 的第一反应是"上电就能发数据",实际上模块从冷启动到能够承载 TCP 数据,要经过四个阶段:开机、联网注册、PDP 激活、TCP 建连。前两个阶段是"模块自身状态",后两个阶段是"数据通道状态"。一个常见翻车场景是用测试板已经连通过,换到自己的板子上死活建不了 TCP 连接,最后发现是 SIM 卡槽接触不良、天线没接好导致注册不成功。
开机阶段由硬件控制,PWRKEY 拉低几百毫秒触发模块上电,模块起来后串口会主动输出一段开机信息,包括固件版本号。此时不要急着发 AT 指令,先等模块自己把射频初始化完。之后依次检查 SIM 卡状态、信号强度、网络注册。网络注册分为 CS 域和 PS 域,我们做 TCP 只看 PS 域的注册状态,对应 AT 指令返回的第二个数字是 1 或 5,而不是开机时看到的 1、2、3。
PDP(分组数据协议)激活是容易被忽略的一步,没有激活上下文就无法建立 IPO 连接。激活前要先通过 AT+CGDCONT 设置 APN。国内多数物联网卡走的是 CMNET 这类公共 APN,专用的 APN 需要向运营商申请。激活完成后模块才有公网侧的 IP 地址,接下来才能发起 TCP 连接。
2.2 透传模式 vs 指令模式:为什么数据上行为主时选透传
EC20 有两种数据通道用法。一种是指令模式,即用 AT+QISEND 发送数据、用 AT+QIRD 接收数据,模块收到网络数据时会主动上报提示。这种模式的优点是随时可以查信号、查网络状态、切换连接,缺点也很明显:每条数据都要组 AT 帧、等返回、做解析,MCU 侧的处理压力集中在协议解析上,吞吐量上不去。
透传模式则不同,模块建立 TCP 连接后,进入透传状态,单片机往串口写的每一个字节会直接变成网络数据发出去,网络侧收到的 TCP 数据也会原样从串口透传回来。对 STM32F4 来说,它的工作只剩下"串口搬运",不需要理解任何数据内容,这非常适合大流量、长连接、数据上行为主的场景,比如周期性上传传感器数据、固件 OTA 分包下发。
但透传不是万能的,如果你需要在连接过程中频繁查询信号强度 CSQ、或者动态切换服务器地址,透传模式会非常难受,因为要频繁退出和重进透传。遇到这种场景,我一般会保留指令模式,把业务数据封装成私有协议,用缓冲模式处理。这个取舍在后面的进阶章节还会再展开。
2.3 关键 AT 指令与返回参数速查表
工程里把联网流程封装成了几个函数,但底层调用的是这张指令序列。建议先把这张表看明白,再去看工程代码。
| 阶段 | 作用 | 指令 | 返回判断 |
|---|---|---|---|
| 串口探测 | 确认模块能收到 AT 指令 | AT | OK |
| 关闭回显 | 减少串口干扰 | ATE0 | OK |
| SIM 卡检测 | 检查 SIM 是否识别 | AT+CPIN? | READY |
| 信号强度 | 确认天线可用 | AT+CSQ | 第一个值大于 10 较稳 |
| 网络注册 | 确认 PS 域注册 | AT+CREG? | 返回中第二位为 1 或 5 |
| APN 配置 | 设定数据网络 | AT+CGDCONT=1,"IP","CMNET" | OK |
| PDP 激活 | 获取网络 IP | AT+CGACT=1,1 | OK |
| TCP 建连 | 连接服务器 | AT+QIOPEN=1,"TCP","x.x.x.x",8080,20000,0 | +QIOPEN: 1,0 |
| 进入透传 | 数据直通 | AT+QIMODE=1 | OK |
参数说明:AT+CSQ 返回的两个数字中,第一个是信号强度等级,范围 0~31,10 以下基本属于"能注册但容易掉线";第二个数字是误码率等级,一般不用太关注。AT+CREG? 的返回里,第二位 1 表示已注册本地网、5 表示已注册漫游网,都可以建连。AT+QIOPEN 里的三个数字依次是连接 ID、TCP 类型、远端 IP、远端端口、本地端口和连接模式,最后一个 0 表示非缓冲模式,1 表示缓冲模式。连接成果返回 +QIOPEN: 1,0 中的第一个 1 是连接 ID,第二个 0 表示成功,若是负数代表失败。
3. STM32F4 与 EC20 的硬件连接和驱动分层:先稳住电气基础
3.1 供电、电平与 SIM 卡:硬件上最容易翻车的三个位置
EC20 是 4G 模块,不是 WiFi 模块。它的瞬态功耗比很多人想象的大得多,在弱信号环境下射频发射功率拉满,峰值电流能到 2A 左右,这个电流如果用 STM32F4 板子上的 3.3V LDO 扛,电压会被瞬间拉垮导致模块重启。我一般会在模块供电入口放一颗 DC-DC 降压芯片,或者至少用能持续输出 1A 以上的降压电路,并在模块 VBAT 引脚附近并联一个大容量的铝电容加若干 100nF 陶瓷电容。工程板子上如果空间紧张,也要确保走线线宽不小于 1mm。
电平转换是第二个容易踩坑的点。EC20 的 UART 电平是 1.8V,STM32F4 的 UART 电平是 3.3V,直接连会有过压风险,尤其模块的 TX 引脚在空闲时会被上拉到 1.8V,这个电压识别不了 3.3V 为高电平,反而可能损伤模块。更好的做法是用电平转换芯片把两边的 TXD/RXD 交叉转接,或者选择已经带电平转换的底板。
SIM 卡部分要注意卡座引脚是否和模块的 SIM 接口匹配,EC20 使用的是 1.8V/3V 双电压 SIM 卡接口,如果卡座加上过长走线容易信号衰减。做好这些事情,再进入代码部分,否则后边程序跑不通往往不是代码问题,而是硬件电平不对,这在调试时经常造成误导。
3.2 驱动工程的文件结构:把协议和业务分开
这份工程值得称道的一个点是目录组织思路清楚。如果直接堆代码,后续维护会很痛苦,尤其是要换服务器 IP 或者改波特率的时候。打开工程包后,你会看到这样一套结构:
project/ ├── core/ // 系统时钟、中断相关 ├── usart/ │ ├── usart.c // 串口底层,DMA 发送接收 │ └── usart.h ├── ec20/ │ ├── ec20.c // AT 指令、联网状态机、透传控制 │ ├── ec20.h │ └── ec20_config.h // APN、服务器 IP、端口、心跳周期 ├── app/ │ ├── data_handler.c // 业务数据组装与解析 │ └── data_handler.h └── main.c // 主循环框架ec20_config.h 是我建议你第一个打开的文件。里面集中定义了所有需要按项目修改的参数,比如模块串口句柄、APN 名称、服务器地址、端口、波特率等。这样做有一个实际好处:换运营商 SIM 卡或者换服务器时,不需要到整个工程里翻 AT 指令。app 层是业务代码,比如温湿度数据怎么组帧、收到下行指令怎么处理,它只被 ec20 层的接口调用,不直接操作串口和 AT 指令。
这样的分层对 STM32F4 用户的意义在于,你想移植到其他 F4 型号时,只需要改 usart 层里对应的串口号,业务代码基本不用动。工程里用的是 HAL 库的串口,在 usart.c 里能看到具体的串口初始化结构体,可以通过修改句柄来切换 USART1、USART2 或 USART3。
3.3 串口接收框架:DMA + 空闲中断怎么配合
串口接收是 4G 模块通信最容易出 bug 的地方。很多人直接从 HAL_UART_Receive_IT 按字节收,这样做的结果是有可能每收到一个字节就被中断打断一次,在主循环里还要拼包,工作量大,还容易出现粘包。更好的做法是用 DMA + 空闲中断(HAL_UARTEx_ReceiveToIdle_DMA)来接收,这一套方法在这份工程里已经给了现成框架。
static uint8_t ec20_rx_buf[EC20_RX_BUF_SIZE]; volatile uint16_t ec20_rx_len = 0; void EC20_UartStartReceive(void) { HAL_UARTEx_ReceiveToIdle_DMA(&huart3, ec20_rx_buf, EC20_RX_BUF_SIZE); } void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) { if (huart->Instance == USART3) { ec20_rx_len = Size; // 本次 DMA 接收到的字节数 EC20_ProcessRxData(ec20_rx_buf, ec20_rx_len); memset(ec20_rx_buf, 0, EC20_RX_BUF_SIZE); HAL_UARTEx_ReceiveToIdle_DMA(&huart3, ec20_rx_buf, EC20_RX_BUF_SIZE); } }逻辑说明:HAL_UARTEx_ReceiveToIdle_DMA 打开一个 DMA 传输,当串口在某个时间点一段时间没有新数据时,硬件会产生空闲中断,HAL 库会调用这个回调函数。Size 参数是当前这一轮 DMA 接收到的字节总数,这样不需要自己拼包,一次性把一整帧数据交给业务层。把收到的数据交给 EC20_ProcessRxData 后,重新拉进 DMA 接收模式,保证下一次数据到来时缓冲区一直在监听。
参数说明:EC20_RX_BUF_SIZE 的大小直接影响可接收的单帧数据长度。如果服务器下发的指令帧可能超过 512 字节,就把它调大。这个参数的设置要和你的协议最大帧长度匹配,否则模块返回的数据会被 DMA 截断,造成解析失败。对于 K 线,接收缓冲区设置到 1024 是合理的。另外注意 Buffer 是 uint8_t 数组,不是指针,这样 DMA 才能连续搬数据。一旦初始化后这个 buf 不能随意被局部变量覆盖,所以它被定义成静态全局。回调里如果发现 ec20_rx_len 超过了缓冲长度,说明出现了严重的溢出,这种情况要在代码里做丢帧处理,而不能直接把缓冲区后半段当成有效数据。
4. 初始化、拨号、进入透传:核心代码拆解
4.1 开机与串口握手:电源时序和 AT 探测
打开 main 函数,第一个用到的函数是 EC20_PowerOn。EC20 的 PWRKEY 引脚是低电平有效,触发方式比较固定:拉低再释放。电源时序上要先保证 VBAT 电压稳定后再拉 PWRKEY,否则模块可能直接不启动。
void EC20_PowerOn(void) { HAL_GPIO_WritePin(EC20_PWRKEY_GPIO_Port, EC20_PWRKEY_Pin, GPIO_PIN_RESET); HAL_Delay(600); // 拉低 600ms HAL_GPIO_WritePin(EC20_PWRKEY_GPIO_Port, EC20_PWRKEY_Pin, GPIO_PIN_SET); HAL_Delay(3000); // 等待开机 AT 信息 }逻辑说明:PWRKEY 被拉低 600 毫秒后释放,模块开始启动。等 3 秒不是因为 AT 必须等这么久,而是为了在调试时不漏掉开机信息。质量好的习惯是后面加一个 AT 探测循环,判断模块是否真正就绪。很多工程师在这里只延时一次然后就发 AT,结果如果模块因为天线没接好重新启动,AT 命令就发早了,导致后面的初始化全部错位。
uint8_t EC20_ATDetect(void) { uint8_t retry = 0; while (retry++ < 20) { if (EC20_SendCmd("AT\r\n", "OK", 200) == EC20_OK) { return EC20_OK; } HAL_Delay(500); } return EC20_ERR; }逻辑说明:EC20_SendCmd 是工程里的核心 AT 发送函数,参数包括指令、期望返回的字符串和超时时间。这个函数的基本工作是发送字符串,然后在 DMA 接收缓冲区里查找有没有出现期望的返回关键字。循环 20 次是给模块留了 10 秒以上的时间来完成启动。对于实际联网超时,要注意 EC20_SendCmd 的第三个参数不是整套协议的 timeout,而是等待返回关键字的 timeout,如果模块信号很差,AT+QIOPEN 的应答超过 2 秒才返回,就需要把 timeout 加大。
4.2 注网、激活 PDP 与建立 TCP 连接
模块启动后就要依次走完注册、激活、建连,这一步是联网的主流程。代码里一般会封装成一个 EC20_NetOpen 函数,我把关键步骤拆开看:
uint8_t EC20_NetOpen(const char *apn, const char *ip, uint16_t port) { EC20_SendCmd("ATE0\r\n", "OK", 1000); EC20_SendCmd("AT+CPIN?\r\n", "READY", 3000); EC20_SendCmd("AT+CREG?\r\n", "0,1", 1000); // 期望第二位是 1 char cmd[128]; snprintf(cmd, sizeof(cmd), "AT+CGDCONT=1,\"IP\",\"%s\"\r\n", apn); EC20_SendCmd(cmd, "OK", 2000); EC20_SendCmd("AT+CGACT=1,1\r\n", "OK", 5000); snprintf(cmd, sizeof(cmd), "AT+QIOPEN=1,\"TCP\",\"%s\",%d,20000,0\r\n", ip, port); EC20_SendCmd(cmd, "+QIOPEN: 1,0", 5000); return EC20_OK; }逻辑说明:ATE0 把回显关掉,减少串口上的干扰帧。AT+CPIN? 等返回 READY 才继续。AT+CREG? 里的期望返回值 0,1 表示已注册本地 4G 网络;如果 SIM 卡是漫游状态,这里要改成 0,5。AT+CGDCONT 配置 APN 时,1 表示上下文 ID,后面建立连接也要用同一个 ID。AT+CGACT=1,1 激活上下文,模块会获得 IP 地址。最后 AT+QIOPEN 携带远端 IP 和端口发起 TCP 连接,本地端口设置为 20000,这个数值可以随意调整,只要不和其他连接冲突即可。
参数说明:QIOPEN 最后一个参数 0 表示非缓冲模式,1 表示缓冲模式。缓冲模式下网络数据不会立刻从串口出来,而是先存在模块内部缓存,等到缓存达到一定阈值才输出;非缓冲模式是立刻透传。这里我们需要透传,所以用 0。连接模式要和后面的 QIMODE 配合,QIMODE=1 本身也要求连接处于非缓冲模式下。
实际调试时,AT+CREG? 这一句最容易耗时,如果每次都等 3 秒,初始化时间会拉得很长。更好的做法是轮询,例如每 500ms 查一次,最多等 20 秒。已注册/漫游的状态是在变化阶段的中间态,模块可能先返回 0,2(正在注册),之后才是 0,1 或 0,5。所以不要以为一次返回 OK 就代表注册完成,一定要等写进期望的 0,1 再往下走。
4.3 进入透传与退出透传:+++ 的时序细节
TCP 连接建立后,调用 AT+QIMODE=1 进入透传模式。注意这个指令必须在 QIOPEN 成功之后发送。如果连接还没建好就发,模块会直接返回 ERROR。
uint8_t EC20_EnterTransparent(void) { return EC20_SendCmd("AT+QIMODE=1\r\n", "OK", 2000); }进入透传模式后,模块返回的 OK 是"透传模式已开启"的标记,之后串口上再有数据就会被视为业务数据。这时候主循环里就不能再调用 EC20_SendCmd 去发 AT 指令了,否则那些指令文本会被当成 TCP 数据发给服务器。
退出透传用的是 +++ 序列,这个退出序列有严格的时序要求:进入透传后,模块会监测串口数据中出现的连续三个加号字符,但前后要有一段静默时间。如果直接发 "+++",模块可能会把它当成普通数据送出去。通常做法是保持 1 秒静默,然后发送三个连续的加号字符,再等待 1 秒静默。退回到 AT 模式后,之前建立的 TCP 连接仍然存在,不会因为退出透传而断链。这个设计给业务上带来了灵活性,比如可以在运行中临时退出透传查询信号,再重新进入透传继续传数据。
void EC20_ExitTransparent(void) { HAL_Delay(1000); EC20_UartSendString("+++"); // 注意不要带 \r\n HAL_Delay(1000); }逻辑说明:这段代码中 EC20_UartSendString 是直接串口发送字节流,不做 AT 返回区分,因为此时模块处于透传模式,不会有 OK 回应。发完 +++ 后等待 1 秒,之后模块应该回到 AT 指令模式,可以用 AT 或 ATE0 再次验证。
那种在透传模式下误发 +++ 导致数据丢失的问题,多半是发送时带了回车换行,或者前后静默时间不够。谨记 ++ 三个字符是连发,中间不能有停顿,否则会触发模块每个加号的超时判定。
4.4 主循环里的双向转发
进入透传后,STM32F4 的主要任务就是转发。上行方向:把来自传感器的数据从 MCU 的串口写入 EC20 的串口;下行方向:把 EC20 网络侧收到的数据从模块串口转发到业务处理函数。这段逻辑在主循环里实现:
while (1) { if (sensor_new_data_ready) { EC20_UartSendString((char *)sensor_buf, sensor_len); sensor_new_data_ready = 0; } // EC20 下行数据已经在 DMA 空闲中断回调里处理 EC20_ProcessRxData(ec20_rx_buf, ec20_rx_len); HAL_Delay(10); }逻辑说明:主循环承担的是"推"的动作,把业务层要发送的数据推给模块串口。下行数据则采用中断方式,不需要在主循环里轮询。这里要注意 HAL_Delay(10) 会让主循环以 100Hz 的频率运行,如果传感器数据产生频率很高,需要放在中断里,而不是靠主循环轮询传感器标志位,否则会有数据延迟。
双向转发代码还有一个关键点是缓冲区管理。如果 MCU 往模块串口写入的速度太快,模块 UDP 缓冲区可能直接丢弃后续数据,或者服务器侧收包出现乱序。最常见的做法是每次发送前判断模块串口是否还有数据未发送完成,使用 HAL_UART_GetState 查询发送状态,只有当状态为就绪时才写入下一包。咱们这份工程里 EC20_UartSendString 封装的底层就是带状态检查的。
5. 避坑与排查:五个实录问题
5.1 现象:模块不回 AT 指令的 OK,或者返回乱码
原因:最典型的是串口波特率不匹配,或者模块的开机时序没有走完就发指令。我自己遇到过一块底板上有跳帽控制电平,结果默认接成 3.3V 的模块 TX,读回来的数据完全是乱的。
解决:先看硬件,用示波器抓模块串口 TX,确认上电后确实有 1.8V 电平的信号。然后检查 STM32F4 的串口外设时钟和波特率是否与模块一致。工程里默认 115200,如果你用的模块固件版本或者底板有不同波特率,必须先在 AT 测试软件里确定,再改代码里的初始化结构体。最后把 EC20_PowerOn 的延时从 3 秒加大到 5 秒,避免模块缓慢开机的场合探测失败。
5.2 现象:AT+CREG? 一直返回 0,2 或者 0,3
原因:0,2 表示正在注册网络中,0,3 表示被拒绝。如果一直卡在 2 后面或者直接 3,SIM 卡片和天线大概率有问题,网络侧没有注册上。
解决:先用手机或者其他模块确认同一张 SIM 卡在同一地点能上网。如果是专用物联网卡,APN 可能不是公共 CMNET,这样模块注册会失败。我遇到过一次工厂里信号被屏蔽,CREG 一直返回 0,2,最后换到窗边就注册成功了。所以不要把代码里 AT+CREG? 的期望值当成测试万能的,信号差的时候该加天线延长线还是要加。
5.3 现象:AT+QIOPEN 返回错误码
常见错误码包括 +QIOPEN: 1,3 和 1,4,各自表示 DNS 解析失败和连接失败。这个返回值的第二项不是 0,就代表建连不成功。多数情况下是因为 APN 没配好,导致模块拿不到公网 IP。也可能是服务器端口写错,或者远端服务器防火墙禁止了这个端口。
解决:先检查 AT+CGACT=1,1 是否返回 OK,再发命令 AT+QIOPEN 前可以用 AT+QIACT? 查看当前 PDP 上下文的状态,确认模块已经获得 IP 地址。如果服务器是公网 IP,直接用 ping 的方式确认网络可达性。调试时优先选择不加密的 TCP 端口,避免 TLS 握手引入新的变量。
5.4 现象:透传模式下数据不定时丢失,或者数据粘包
原因:这类问题本质上是串口收发的时序问题,而不是模块本身丢数据。EC20 的串口 FIFO 有限,如果 MCU 大批量写入而模块来不及发出去,就会产生溢出丢弃。粘包则是接收端把几个包合并成了一个,尤其是在 DMA 空闲中断触发的判断里,如果服务器连续下发两个小数据包,中间间隔小于一个字节,空闲中断就分不开了。
解决:上行尽量采用等长的数据包,并且每次发送后用 HAL_UART_GetState 查询模块串口状态。下行粘包需要通过应用层的帧解析来处理,比如定义帧头帧尾和长度字段。这份工程在 app 层的 data_handler.c 里预留了帧解析函数,你可以把长度字段统一成两字节,收到数据后先解析长度,不足就等下一帧再拼接。
5.5 现象:+++ 退出透传后,模块不再响应 AT 指令
原因:最典型的是 +++ 是在模块收到网络数据后立即发送的,此时模块内部还在透传缓冲区中,把 +++ 当成了业务数据。另外,如果用了回车换行结束,那模块就会把命令生成"业务数据"发送到服务器,自然没法进入 AT 模式。
解决:进入透传后,如果要退出,必须先把自己的发送端静默至少 1 秒,再裸发三个加号(注意不是 "+++\r\n"),保持静默 1 秒以上。这个静默时间最好用 HAL_Delay 控制,不能放在主循环里等待,因为主循环可能被业务任务卡住。之后再用 AT 指令探测,如果 OK 返回,说明已经退回来了。
6. 验证与进阶:服务器回环、心跳保活与缓冲模式
写完了代码、避了坑,接下来就是验证。第一次拿到这种透传工程,建议不要直接在真实业务服务器上测,也不要先用业务数据。先用一个回环测试把链路能力验证清楚。你可以在 PC 上开一个 TCP 服务端,监听某个端口,然后用 STM32F4 连接这个服务端。服务器不回复任何业务逻辑,直接把收到的数据原样返回给模块。这样就能判断整个透传链路是不是真的双向都通。
回环测试的基本步骤:
- PC 上运行 TCP Server 工具,监听端口如 8080
- 修改 ec20_config.h 里的 IP 和端口,指向本机公网 IP,如果是局域网测试要用同一网段 IP
- 进入透传模式后,STM32F4 每 2 秒发送一次 16 字节数据
- 服务器回显后,查看 F4 能否再次收到相同数据
这个测试能一次性验证:串口收、串口发、网络数据上行透传、网络数据下行透传、接收中断、缓冲区是否够用。我见过很多项目上来就用业务数据测,一失败就怀疑模块,实际上大部分问题都在自己的缓冲区或流程上。
链路通了以后,要考虑保活。TCP 长连接在运营商侧如果空闲时间太长,可能被 NAT 老化掉,服务器端几个月不重连的"僵尸连接"也经常出现。工程只在应用层常发了心跳,这类 4G 模块本身还有一个低功耗机制,如果长时间无数据,部分固件会自动进入 PSM 模式,这会导致用户感知断链。为此需要做应用层心跳,代码里默认每 30 秒会往服务器发送一个 4 字节的通用心跳帧,这个值可以根据服务器侧的超时策略调整。需注意服务器端的心跳超时时间要大于模块心跳周期,我这里倾向于配置为 60 秒,保持余量。
还有一个进阶选择值得提:把 TCP 连接配置为缓冲模式。也就是在 AT+QIOPEN 时把最后一个参数改成 1,以及 QIMODE=1 的透传模式改成 AT+QIMODE=0,这样模块接收网络数据后不会立刻从串口输出,而是先暂存在模块缓冲区里,达到一定条件再一次性输出。它的好处是减少 MCU 频繁被中断打扰,坏处是实时性下降。如果你在做的是批量上传而非交互式控制,缓冲模式比纯透传更适用,能把 F4 的 CPU 利用率让出一部分。
模块固件升级这个动作也被很多人忽略。收到了新版本固件或者某个功能有问题时,换模块固件往往比改代码都快。但升级工具需要在 AT 模式下操作,不要在透传模式下升级,升级过程中不能掉电。升级完后再检查一遍串口返回的版本号,确认是新固件。
最后说点我的个人习惯。从那次在透传模式下误发 +++ 导致数据丢失、又排查了一整天才意识到是时序问题之后,我每次给项目换 EC20 底板或者升级固件,都会强制自己走一遍这套流程:先看电源和电平,再用回环测链路,再测心跳,最后才接业务代码。这套顺序看起来慢,实际上比出一次问题再排查便宜得多。希望这份工程笔记能帮你把 EC20 的 TCP 透传链路一次跑通,少走点弯路。
本文还有配套的精品资源,点击获取