我试图使用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=?\r\n";
        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: %s\n", buffer);
        }

        usleep(500000);
    }
}

但当我阅读回复时,它总是包含我发送的字符串。
我在使用screen时没有遇到这个问题。
使用Linux从C语言的UART中读取数据的最佳方式是什么?
多路复用方式(使用select)会导致问题吗?
编辑
为完整起见,输出为:
Reply is: at+gmi=?

OK

而且,有时我什么也不看。

最佳答案

但当我阅读回复时,它总是包含我发送的字符串。
由于termios配置删除了本地echo属性,并且发送的是AT modem命令,因此应尝试发送ATE0命令以禁用调制解调器的回声。
我在使用屏幕时没有遇到这个问题。
此观察结果确认已连接的调制解调器已启用回声。
在您键入时,AT命令会被(调制解调器)回显,但在这种情况下,您不反对接收到的数据(因为您想查看键入的内容)。
如果调制解调器没有启用回音,那么您将抱怨您在屏幕中键入的内容不可见。
当使用终端仿真器程序(如屏幕)时,需要使用IOW echo,但当通过程序发送数据时,需要禁用echo。
使用Linux从C语言的UART中读取数据的最佳方式是什么?
(从技术上讲,您不是从“UART”读取数据,而是从完全缓冲所有输入和输出的串行终端读取数据。)
符合POSIX标准的代码,如Setting Terminal Modes Properly
比你现在拥有的要好得多。
我很惊讶它居然能工作(比如CREAD没有启用)。
多路复用方式(使用select)会导致问题吗?
不是回声“问题”。
程序不执行任何需要使用select()和非阻塞模式的操作。
而且,有时我什么也不看。
当您编写不符合POSIX的代码时,您不应该期望可靠的程序行为。

关于linux - UART回复是否包含先前的命令?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53831329/

10-12 18:10