简体   繁体   English

linux串口read()错误数据

[英]linux serial port read() wrong data

I am writing a small program to communicate with a AVR MCU, on PC side I used posix write() and read() to access the serial port, I connected the serial port's RX and TX pins to test if it can properly send and receive data, in theory everything sent out should end up exactly the same in the receive buffer, it is the case when the message being sent is short and sending frequency is low, read() returns the same message as sent out, but when the message gets longer and sent more frequently, read() returns the wrong data, the characters seem to be in the wrong order, my guess is read() or write() is not in block mode, so when old transfer hasn't finish yet, new transfer(write()?) arrived, interrupts the old transfer and changed the TX buffer. 我正在编写一个用于与AVR MCU通信的小程序,在PC端,我使用posix write()和read()访问串行端口,我连接了串行端口的RX和TX引脚以测试其是否可以正确发送和接收数据,从理论上讲,所有发送出去的消息在接收缓冲区中的结局都应该完全相同,在这种情况下,正在发送的消息很短并且发送频率很低,read()返回的消息与发送的消息相同,但是当消息发送时变得更长并更频繁地发送,read()返回错误的数据,字符似乎顺序错误,我的猜测是read()或write()不在块模式下,因此当旧传输尚未完成时,新的传输(write()?)到达,中断旧的传输并更改了TX缓冲区。

I am a newbie in Linux programing, please anybody help me on this, it's killing me ... any help is greatly appreciated. 我是Linux编程的新手,请任何人帮助我,这使我丧命...任何帮助都将不胜感激。

Edit: I noticed in the write() man page: A successful return from write() does not make any guarantee that data has been committed to disk. 编辑:我在write()手册页中注意到:从write()成功返回并不能保证数据已提交到磁盘。 In fact, on some buggy implementations, it does not even guarantee that space has successfully been reserved for the data. 实际上,在某些错误的实现中,它甚至不能保证已经为数据成功保留了空间。 The only way to be sure is to call fsync(2) after you are done writing all your data. 唯一确定的方法是在完成所有数据写入后调用fsync(2)。

I tried the fsync() function, still getting the same wrong result. 我尝试了fsync()函数,仍然得到相同的错误结果。

Here is the code: 这是代码:

#include <stdio.h>
#include <stdio.h>   /* Standard input/output definitions */
#include <string.h>  /* String function definitions */
#include <unistd.h>  /* UNIX standard function definitions */
#include <fcntl.h>   /* File control definitions */
#include <errno.h>   /* Error number definitions */
#include <termios.h> /* POSIX terminal control definitions */

int main(void) {

    int fd;
//  fd = open("/dev/tty.usbmodem1a21", O_RDWR | O_NOCTTY | O_NDELAY);
    fd = open("/dev/tty.usbmodem1a21", O_RDWR | O_NOCTTY);
    if (fd == -1) {
        //Could not open the port.
        perror("open_port: Unable to open port ");
    }
        else
        fcntl(fd, F_SETFL, 0);

    char s[] = "Hello, this is a test of the serial port access";

    int cnt;
    unsigned char in[100];
    for(cnt=0; cnt<10; cnt++) {
        int n = write(fd, s, sizeof(s));
        if (n < 0)
            fputs("write() failed!\n", stderr);

        usleep(50000);  // works fine with delay

        read(fd, in, 100);


            printf("%s\n", in);
    }

    return 0;
}

在write()和read()之间使用sleep()在write()和read()之间没有sleep()

Eric 埃里克

Start by using the return value from read() . 首先使用read()的返回值。 Remember: read does not yield nul-terminated strings. 切记:read 不会产生以nul结尾的字符串。

n=read(fd, in, 100);

        printf("%*.*s\n", n,n, in);

(1) Always check return codes. (1)务必检查返回码。 (2) If you try to printf a string that hasn't been null terminated you are going to end up printing any junk that is in memory (or worse). (2)如果您尝试打印未终止为null的字符串,则最终将打印出内存中(或更糟)的所有垃圾。

My guess is that your real problem is that read/write are NOT guaranteed to write the number of bytes you specify. 我的猜测是,您真正的问题是不能保证读/写操作可以写入您指定的字节数。 The number that they actually read/write is in the return code. 他们实际读/写的数字在返回码中。 So as the fd buffer fills up you could be writing 1 byte and then trying to print a non-null string of that 1 byte and everything after it. 因此,当fd缓冲区填满时,您可能正在写入1个字节,然后尝试打印该1个字节的非空字符串及其后的所有内容。

Try something like this and see if things change. 尝试这样的事情,看看情况是否会改变。

int cnt;
unsigned char in[100];

for(cnt=0; cnt<10; cnt++) 
{
    int n = write(fd, s, sizeof(s));

    if (n < 0)
    {
        perror("write");
        exit(EXIT_FAILURE);
    }

    n = read(fd, in, 100);

    if (n < 0)
    {
        perror("read");
        exit(EXIT_FAILURE);
    }

    in[n] = '\0';

    printf("%s\n", in);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM