UART回复包括上一个命令



我正在尝试使用C程序中的Linux环境中的UART设备阅读,但是我经历了使用屏幕与UART通信的不同结果。

我用来测试UART通信的C代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <libgen.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <getopt.h>
#include <stdbool.h>
#include <sys/stat.h>
#include <termios.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/select.h>
#include <signal.h>
#include <ctype.h>
bool loop;
void sigHandler(int32_t sig)
{   
    if(sig == SIGINT)
    {
        printf("Catched SIGINT");
        loop = false;
    }
}
int main(int argc, char *argv[])
{
    char *devname = argv[1];
    int fd = -1;
    int nread = -1;
    int nwrite = -1;
    int ret;
    struct termios t_new = {0};
    struct termios t_old = {0};

    signal(SIGINT, sigHandler);

    fd = open(devname, O_RDWR | O_NOCTTY |O_NONBLOCK);
    if(fd > 0)
    {   
        printf("TTY open ! Configuring TTY"); 
    }
    else
    {
        fd = -1;
        return 1;
    }
    ret = tcgetattr(fd, &t_old);
    if(ret < 0)
    {
        perror("tcgetattr ");
        close(fd);
        fd = -1;
        return 1;
    }
    t_new = t_old;
    t_new.c_cflag = (B9600 | CS8 | CREAD );
    t_new.c_oflag = 0;
    t_new.c_iflag = 0;
    t_new.c_lflag = 0;
    ret = tcsetattr(fd, TCSANOW, &t_new);
    loop = true;
    while(loop)
    {
        char s[] = "at+gmi=?rn";
        nwrite = write(fd, s, strlen(s));
        if(nwrite == strlen(s))
        {
            fd_set rfd;
            struct timeval tm = {.tv_sec = 0, .tv_usec = 500000};
            FD_ZERO(&rfd);
            FD_SET(fd, &rfd);
            char buffer[64] = {0};
            if(select(fd + 1, &rfd, NULL, NULL, &tm) > 0)
                nread = read(fd, buffer, sizeof(buffer));
            if(nread > 0)
                printf("Reply is: %sn", buffer);
        }
        usleep(500000);
    }
}

但是,当我阅读答复时,它总是包括我发送的字符串。我没有使用screen遇到这个问题。

使用Linux从C中的UART读取的最佳方法是什么?多路复用的方式(使用select)会引起问题吗?

编辑为了完整性,输出为:

Reply is: at+gmi=?
OK

另外,有时我什么都没看。

但是,当我阅读答复时,它总是包括我发送的字符串。

由于您的Termios配置破坏了本地echo属性,并且您正在发送AT Modem命令,因此您应该尝试发送ATE0命令以通过调制解调器禁用Echo。

我没有使用屏幕遇到这个问题。

此观察结果证实了连接的调制解调器已启用其回声。

键入时(由调制解调器)呼应了AT命令,但是在这种情况下,您不反对此收到的数据(因为您想查看您键入的内容)。
如果调制解调器未启用回声,那么您将抱怨您在屏幕中键入的内容不可见。

使用终端仿真程序(例如屏幕)时,需要回声,但是在通过程序发送数据时需要禁用回声。

使用Linux从C中的UART读取的最佳方法是什么?

(从技术上讲,您不是从A " UART"读取的,而是从完全缓冲所有输入和输出的串行终端。)
正确设置终端模式中所述符合POSIX标准的代码POSIX操作系统的串行编程指南将比您现在拥有的要好得多。
令我惊讶的是它完全有效(例如,不启用cread)。

多路复用的方式(使用选择)会引起问题吗?

不是回声"问题"。
您的程序不执行任何需要使用 select()和非块模式的事情。

另外,有时我什么都没看。

编写不符合POSIX的代码时,您不应期望可靠的程序行为。

最新更新