3

我正在通过串行 RS232 将数据字节从 linux 发送到 windows,然后一切正常,只有我必须处理从 linux 发送的 0xa,因为 windows 将其读取为 0xd + 0xa。但是当我从 windows 向 linux 发送数据字节时,一些字节被替换为 - windows 发送 - 0xd linux 接收 0xa windows 发送 - 0x11 linux 接收垃圾类型值整数 8200

请解释当我从 Windows 向 Linux 发送数据时出了什么问题。提前致谢

Windows 串口初始化

char *pcCommPort = "COM1";
    hCom = CreateFile( TEXT("COM1"),
                       GENERIC_READ | GENERIC_WRITE,
                       0,    // must be opened with exclusive-access
                       NULL, // no security attributes
                       OPEN_EXISTING, // must use OPEN_EXISTING
                       0,    // not overlapped I/O
                       NULL  // hTemplate must be NULL for comm devices
                       );
fSuccess = GetCommState(hCom, &dcb);
 FillMemory(&dcb, sizeof(dcb),0);


    dcb.DCBlength = sizeof(dcb);
    dcb.BaudRate = CBR_115200;     // set the baud rate
    dcb.ByteSize = 8;             // data size, xmit, and rcv
    dcb.Parity = NOPARITY;        // no parity bit
    dcb.StopBits = ONESTOPBIT;    // one stop bit
    dcb.fOutxCtsFlow = false;

    fSuccess = SetCommState(hCom, &dcb);
 buff_success = SetupComm(hCom, 1024, 1024);
COMMTIMEOUTS cmt;
    // ReadIntervalTimeout in ms
    cmt.ReadIntervalTimeout = 1000;
    cmt.ReadTotalTimeoutMultiplier = 1000;
    cmt.ReadTotalTimeoutConstant=1000;
    timeout_flag = SetCommTimeouts(hCom, &cmt);

windows写串口-

WriteFile(hCom, buffer, len, &write, NULL);

Linux串行初始化-

_fd_port_no = open("//dev//ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
tcgetattr(_fd_port_no, &options);
        cfsetispeed(&options, B115200);
        cfsetospeed(&options, B115200);
        options.c_cflag |= (CS8);
        options.c_cflag|=(CLOCAL|CREAD);
        options.c_cflag &=~PARENB;
        options.c_cflag &= ~CSTOPB;
        options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
        options.c_iflag |= (IXON | IXOFF | IXANY);
        options.c_cflag &= ~ CRTSCTS;
        tcsetattr(_fd_port_no, TCSANOW, &options);

读取串行linux-

while(read(_fd_port_no,buffer+_buffer_len,sizeof(buffer))>0)
    {
        _buffer_len = _buffer_len+sizeof(buffer);

    }

是的,正如我从 Linux 告诉 Windows 仅检测到 NL/CR 问题,但我通过字节替换解决了它,但是您对从 Windows 发送到 Linux 的 serila 数据有任何想法(字节替换策略)。实际上我必须通过串行发送 200 字节块中的 200 KB 文件,以便如果从 Windows 发送到 Linux 可以替换哪个字节

4

4 回答 4

3

如果你在 Windows 和Linux上使用ReadFileand ,那么行尾是什么并不重要,除了“你必须在收到它后的某个时候翻译它。WrietFilereadwrite

这看起来不对:

while(read(_fd_port_no,buffer+_buffer_len,sizeof(buffer))>0)
{
    _buffer_len = _buffer_len+sizeof(buffer);

}

您应该考虑返回的读取大小read

如果sizeof(buffer)是您正在读取的实际缓冲区,则添加+_buffer_len, when_buffer_len >= sizeof(buffer)将写入缓冲区之外。

也有点担心这个:

    options.c_iflag |= (IXON | IXOFF | IXANY);
    options.c_cflag &= ~ CRTSCTS;

你确定你想要一个 XOFF/CTRL-S (0x13) 来停止流动吗?通常这意味着不允许包含 CTRL-S 的数据 - 这在发送文本数据时可能不是问题,但如果您需要发送二进制数据,它肯定会。IXOFF 也意味着另一端必须响应 XOFF 和 XON (CTRL-Q, 0x11) 来停止/启动数据流。通常,我们不希望在现代系统中这样做......

如果两端之间的接线正确,使用 RTS/CTS 应该是安全的。

于 2013-07-13T09:49:55.437 回答
1

Thanks all

This Change Solved my problem

fd_port_no = open("//dev//ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
tcgetattr(_fd_port_no, &options);
        cfsetispeed(&options, B115200);
        cfsetospeed(&options, B115200);
        options.c_cflag |= (CS8);
        options.c_cflag|=(CLOCAL|CREAD);
        options.c_cflag &=~PARENB;
        options.c_cflag &= ~CSTOPB;
        options.c_cflag &= ~ CRTSCTS;
        options.c_iflag |= (IXON | IXOFF | IXANY);
        options.c_lflag &= ~(ICANON | ISIG | ECHO | ECHONL | ECHOE | ECHOK);
        options.c_cflag &= ~ OPOST;
        tcsetattr(_fd_port_no, TCSANOW, &options);
于 2013-12-06T09:46:23.587 回答
1

我认为您必须先冲洗,然后才能从串行端口读取通量

tcflush(_fd_port_no TCIFLUSH);

此外,您是否尝试过使用 commande
cat < dev/ttyS0 的控制台查看通量?

于 2013-07-15T07:07:21.633 回答
1

为避免行尾转换,您可能需要添加:

options.c_iflag &= ~IGNCR;  // turn off ignore \r 
options.c_iflag &= ~INLCR;  // turn off translate \n to \r 
options.c_iflag &= ~ICRNL;  // turn off translate \r to \n

options.c_oflag &= ~ONLCR;  // turn off map \n  to \r\n
options.c_oflag &= ~OCRNL;  // turn off map \r to \n 
options.c_oflag &= ~OPOST;  // turn off implementation defined output processing

此外,以下行:

options.c_iflag |= (IXON | IXOFF | IXANY);

将启用 XON/XOFF 处理,因此 tty 驱动程序会将 Ctrl-S (XOFF) 和 Ctrl-Q (XON) 字符处理为流控制(这可能是您在发送 0x11 时看到一些意外的原因,即 Ctrl-Q)。我希望您想要关闭这些位:

options.c_iflag &= ~(IXON | IXOFF | IXANY);

事实上,我认为您可能想在调用cfmakeraw()后调用tcgetattr()它应该禁用对输入和输出字符的所有特殊处理。

于 2013-07-15T08:26:52.847 回答