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

Raspberry Pi 4使用C语言与SIM7600X调制解调器通信不稳定问题求助

问题根因

你的代码存在4个核心问题,导致和调制解调器通信异常:

  • 未配置串口通信参数:/dev/ttyUSB这类TTY设备需要手动配置波特率、数据位、校验位、停止位、流控等参数,Minicom/Cutecom启动时会自动设置匹配调制解调器的参数,你的代码直接打开设备未做配置,参数不匹配导致数据收发截断,这就是你输出中反复出现AT+CS错误的原因,完整的AT+CSQ命令被截断成了AT+CS,调制解调器无法识别返回ERROR。
  • AT命令结束符不符合规范:3GPP标准定义AT命令必须以\r(回车符,ASCII 0x0D)作为命令结束标志,你使用的\n不符合要求,会导致调制解调器命令解析异常。
  • I/O缓冲未刷新:C标准库的FILE*流默认开启缓冲,你调用fputs写入命令后,数据可能残留在进程缓冲中没有真正发送到串口,需要调用fflush强制刷新。
  • 读取逻辑错误:fgets的返回值是char*类型,读取成功返回缓冲区指针,出错或读取到EOF时返回NULL,你写的if (line >= 0)属于完全错误的指针判断逻辑,会导致循环逻辑异常,无法正常退出。

修正后的代码示例

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>

int main()
{
    FILE *modem;
    struct termios tty;
    int exitflag=0;
    char buf[256];
    char *line;
    int res;
    
    // 打开串口设备
    modem = fopen("/dev/ttyUSB2", "r+b");
    if (modem == NULL) {
        fprintf(stderr, "Unable to open modem\n");
        return(-1);
    }
    int fd = fileno(modem);

    // 配置串口参数:115200波特率,8N1,无流控
    if(tcgetattr(fd, &tty) != 0) {
        fprintf(stderr, "Failed to get termios attributes\n");
        fclose(modem);
        return -1;
    }
    cfsetispeed(&tty, B115200);
    cfsetospeed(&tty, B115200);
    tty.c_cflag &= ~PARENB; // 无校验
    tty.c_cflag &= ~CSTOPB; // 1停止位
    tty.c_cflag &= ~CSIZE;
    tty.c_cflag |= CS8; // 8数据位
    tty.c_cflag &= ~CRTSCTS; // 关闭硬件流控
    tty.c_cflag |= CREAD | CLOCAL; // 开启接收,忽略调制解调器控制线
    tty.c_iflag &= ~(IXON | IXOFF | IXANY); // 关闭软件流控
    tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // 原始模式,关闭回显、规范模式
    tty.c_oflag &= ~OPOST; // 关闭输出处理
    tty.c_cc[VMIN] = 1;
    tty.c_cc[VTIME] = 5; // 读取超时500ms
    if(tcsetattr(fd, TCSANOW, &tty) != 0) {
        fprintf(stderr, "Failed to set termios attributes\n");
        fclose(modem);
        return -1;
    }

    // 发送AT+CSQ命令,以\r结尾
    res = fputs("AT+CSQ\r", modem);
    if (res < 0) 
    {
        fprintf(stderr, "failed to send to modem (res = %d)\n",res);
        fclose(modem);
        return(-1);
    }
    fflush(modem); // 刷新输出缓冲,确保命令发送到串口

    exitflag=0;
    while (exitflag==0)
    {
        line = fgets(buf, sizeof(buf), modem);
        if (line != NULL)
        {
            fprintf(stderr,"%s",buf);
            // 读到OK或者ERROR就退出循环
            if (strstr(buf, "OK") != NULL || strstr(buf, "ERROR") != NULL) {
                exitflag = 1;
            }
        }
        else
        {
            exitflag=1;
            fprintf(stderr,"read timeout or error\n");
        }
    }
    fclose(modem);
    return(0);
}

额外优化建议

  • 可以先发送ATE0\r命令关闭调制解调器的命令回显,这样输出中就不会重复打印你发送的AT命令,只保留调制解调器的返回结果。
  • 每次发送命令后建议等待100~200ms再读取返回,避免调制解调器处理未完成。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 20:15:00