You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用带可变参数的函数发送AT命令出现异常行为

串口发送AT命令的异常问题分析与解决

问题背景

通过串口发送AT命令时出现异常,执行以下代码:

while (true) {
    thread_sleep_for(5000);

    sendATCommand("AT+CIPSENDEX=0,64");
    sendATCommand("test\0");
}

预期TCP接收端仅收到test,但实际收到:

AT+CIPSENDEX=0,64
test

奇怪的是,取消sendATCommand函数中printf语句的注释后,问题消失,TCP接收端仅收到test。sendATCommand函数代码如下:

void sendATCommand(const char* command, ...) {
    char fullCommand[256] = {0};
    va_list args;
    va_start(args, command);

    vsnprintf(fullCommand, 256, command, args);
    va_end(args);

    // Uncommenting the following line magically fixes the issue:
    // printf("the command is: %s\n", fullCommand);

    strcat(fullCommand, "\r\n"); // Append carriage return and newline
    serial_port.write(fullCommand, strlen(fullCommand));
}

1. 为何TCP接收端会同时收到AT+CIPSENDEX=0,64和test?

核心原因是模块未完成AT+CIPSENDEX命令的时序处理。AT+CIPSENDEX是开启透传模式的命令,模块需要时间完成模式切换,但当前代码在发送该命令后立刻发送test,此时模块还未进入透传状态,导致AT+CIPSENDEX命令本身被错误透传出去,后续的test也跟着被一并接收。

另外sendATCommand("test\0")里的\0是多余的,vsnprintf会自动在字符串末尾添加终止符,但这不是引发问题的关键。

2. 为何添加printf语句就能解决问题?

printf的IO操作会引入短暂的延迟,这个延迟刚好让模块有足够时间完成AT+CIPSENDEX命令的执行与透传模式切换。当模块成功进入透传状态后,后续发送的test会被正确透传,而AT+CIPSENDEX命令不会被透传,因此接收端仅收到test。本质是printf带来的“意外延时”刚好弥补了模块的处理时序缺口。

3. 如何修复该问题,使TCP接收端仅收到预期的test?

必须从时序匹配的根源解决,等待模块完成AT+CIPSENDEX命令的响应后,再发送透传数据,具体方案如下:

  • 改造sendATCommand函数,使其能够等待并验证模块的响应(比如等待OK或模块特定的透传进入提示)
  • 确认模块成功进入透传状态后,再发送test数据,拒绝依赖随机延时

示例修改思路:

// 改造函数,增加等待模块响应的逻辑
bool sendATCommandWaitResp(const char* command, const char* expectedResp, ...) {
    char fullCommand[256] = {0};
    char response[256] = {0};
    va_list args;
    va_start(args, command);

    vsnprintf(fullCommand, 256, command, args);
    va_end(args);

    strcat(fullCommand, "\r\n");
    serial_port.write(fullCommand, strlen(fullCommand));

    // 等待模块返回响应,需根据实际模块手册调整等待逻辑
    serial_port.read(response, sizeof(response));
    return strstr(response, expectedResp) != NULL;
}

// 主逻辑修改
while (true) {
    thread_sleep_for(5000);

    // 等待模块确认进入透传模式(部分模块会返回"> "作为透传提示)
    if (sendATCommandWaitResp("AT+CIPSENDEX=0,64", "OK")) {
        // 确认进入透传后再发送数据
        sendATCommand("test");
    }
}

注意:部分模块进入透传模式后会返回特定提示(比如>),此时需要等待该提示而非仅OK,具体以模块的AT命令手册为准。


内容的提问来源于stack exchange,提问作者user26775248

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 19:23:12