c - C LINUX中串口读取不一致

标签 c linux serial-port termios

我在使用 Linux 和 C 读取串行端口时遇到了不一致的问题。

我用来配置串口的代码是这样的:

serial = open("/dev/ttymxc1", O_RDWR | O_NOCTTY | O_SYNC);      //Open in non blocking read/write mode
    if (serial == -1)
    {
        //ERROR - CAN'T OPEN SERIAL PORT
        printf("Error - Unable to open UART.  Ensure it is not in use by another application\n");
    }

    struct termios tty;
    memset (&tty, 0, sizeof tty);
    if (tcgetattr (serial, &tty) != 0)
    {
        printf("error from tcgetattr");
        return -1;
    }

    cfsetospeed (&tty, B115200);

    tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;     // 8-bit chars
    // disable IGNBRK for mismatched speed tests; otherwise receive break
    // as \000 chars
    //tty.c_iflag &= ~IGNBRK;         // disable break processing
    tty.c_lflag = 0;                // no signaling chars, no echo,
                                            // no canonical processing
    tty.c_oflag = 0;                // no remapping, no delays
    tty.c_cc[VMIN]  = 0;            // read doesn't block
    tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

    tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl

    tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
                                            // enable reading
    tty.c_cflag &= ~(PARENB | PARODD);      // shut off parity
    tty.c_cflag |= 0;
    tty.c_cflag &= ~CSTOPB;
    tty.c_cflag &= ~CRTSCTS;

    if (tcsetattr (serial, TCSANOW, &tty) != 0)
    {
        printf("error from tcsetattr");
        return -1;
    }

然后我使用以下代码轮询 UART(来自配置串口的同一线程):

while(1)
{
    if (serial != -1)
    {
        //memset(rx, 0, sizeof(rx));
        int rx_length = read(serial, &rx, MAX_TXRX_BUF);        //Filestream, buffer to store in, number of bytes to read (max)
        if(rx_length > 0){
            //Bytes received
            //rx[rx_length] = '\0';

            printf("1) %i bytes read : %s\n", rx_length, rx);
            //forward_data(rx, rx_length);
            printf("2) %i bytes read : %s\n", rx_length, rx);
            //tcflush(serial, TCIOFLUSH);
        }
        // else: NO DATA
    }
    else{
        fprintf(stderr, "TEST: %s SERIAL FAIL\n", __func__);
        releaseUart();
    }

}

问题是这个打印:

printf("1) %i bytes read : %s\n", rx_length, rx);

始终工作并打印从串口读取的正确数据。 而第二次打印:

printf("2) %i bytes read : %s\n", rx_length, rx);

紧接在第一个下方,有时可以工作,而其他项目只是打印一个未知字符。

下面我向您展示了输出,但在它工作的情况下以及在它不工作的情况下:

正确:

1) 2 bytes read : gv
2) 2 bytes read gv

错误:

1) 2 bytes read : gv
2) 2 bytes read: �

为什么即使两个打印件一个在另一个下面,有时我在打印 SAME 缓冲区时也会遇到这种不一致?

非常感谢您的帮助。

最好的问候, 马可

最佳答案

我无法解释为什么输出在第一个 printf 和第二个之间发生变化。但是,read 不会以 NUL 终止其缓冲区,这意味着,在您执行之后

int rx_length = read(serial, &rx, MAX_TXRX_BUF);

rx 中有一个有效的C 字符串。你需要做这样的事情:

char rx[MAX_TXRX_BUF + 1]; // extra space for terminator
ssize_t rx_length = read(serial, rx, MAX_TXRX_BUF);
if (rx_length >= 0) {
    rx[rx_length] = '\0';
    // use rx here
    // if rx_length == 0, handle EOF
} else {
    // read error
}

即使我不知道为什么输出会改变,我预测如果你把你的两个 printf 语句放在我有 //use rx here 的地方,它们将会总是打印同样的东西。

注意获取整个数组的地址,就像您对 &rx 所做的那样,几乎总是错误的。在大多数情况下,为了在 C 中引用数组,您真正需要的是第一个元素的地址,这就是您仅使用 rx 获得的地址。 (由于过于乏味和切题的原因无法进入这里,read 并不关心你提供了两个中的哪一个,但在其他情况下它可能会导致细微的错误。因此,C 中的最佳实践即使在无关紧要的情况下也使用第一个元素的地址;保留 &rx 用于您确实特别需要整个数组地址的极少数情况。)

关于c - C LINUX中串口读取不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54427480/

相关文章:

c - main 函数和之后的变量

c - 已接受来自 00 :00:00:00:00:00; after connect 的连接

java - 通过定义正则表达式过滤日志文件

c - UDP 套接字 - 服务器未收到任何数据

java - DynamicTimeSeriesCollection 和串行通信

python - 使用正则表达式解析文件并进行修改

C 递归函数不会返回 true

Java SocketChannel 没有在 linux 环境下抛出 IOException

c++ - HELLO WORLD 的 COM Serial Port echo 中的奇怪字符

serial-port - 串行端口握手。硬件和无握手之间有什么区别?