【问题标题】:Writing binary data over serial in windows在Windows中通过串行写入二进制数据
【发布时间】:2013-10-03 18:32:25
【问题描述】:

我需要通过串行端口发送二进制数据,在此过程中没有任何字节被重新解释为控制字符。我目前正在按如下方式设置我的串口:

#include <windows.h>

// open serial port
HANDLE hSerial;
hSerial = CreateFile ("COM1", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

// get serial parameters
DCB dcbSerialParams = {0};
dcbSerialParams.DCBlength = sizeof (dcbSerialParams);
if (!GetCommState(hSerial, &dcbSerialParams)) {
    cout << "error getting state\n";
    exit(0);
}

// set serial params
dcbSerialParams.BaudRate = CBR_115200;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity   = NOPARITY;
if (!SetCommState (hSerial, &dcbSerialParams)) {
    cout << "error setting parameters\n";
    exit(0);
}

// set time outs
COMMTIMEOUTS timeouts = {0};
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 10;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 10;
timeouts.WriteTotalTimeoutMultiplier = 10;
if (!SetCommTimeouts (hSerial, &timeouts)) {
    cout << "problem setting timeout values\n";
    exit(0);
} else cout << "timeouts set\n";

当我发出 ReadFile 命令时,我可以毫无问题地获取和显示从 0 到 255 的字节。但我对 WriteFile 没有这样的运气。有没有办法明确设置二进制写入模式?

编辑

好的,这里有更多信息。我有一台windows机器和一台linux单板机通过串口连接,上面windows端的代码后面是:

unsigned char temp = 0;

bool keepReading = true;
while (keepReading) {
    DWORD dwBytesRead = 0;
    ReadFile (hSerial, &temp, 1, &dwBytesRead, NULL);
    if (1 == dwBytesRead) cout << (unsigned int) temp << " ";
    if (255 == temp) keepReading = false;
}
cout << endl;

bool keepWriting = true;
char send = 0;
while (keepWriting) {
    DWORD dwBytesWritten = 0;
    WriteFile (hSerial, &send, 1, &dwBytesWritten, NULL);
    send++;
    if (256 == send) keepWriting = false;
}

我在 linux 端的代码如下所示:

int fd = open("/dev/ttymxc0", O_RDWR | O_NOCTTY);
struct termios options;
bzero (options, sizeof(options));
options.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
options.c_iflat = IGNPAR;
options.c_oflag = 0;
options.c_lflag = ICANON;
options.c_cc[VMIN] = 1;
options.c_CC[VTIME] = 0;
tcflush (fd, TCIFLUSH);
tcsetattr (fd, ICSANOW, &options);

bool keepWriting = true;
char send = 0;
while (keepWriting) {
    write (fd, &send, 1);
    send++;
    if (256 == send) keepWriting = false;
}

bool keepReading = true;
while (keepReading) {
    char temp = 0;
    int n = read (fd, &temp, 1);
    if (-1 == n) {
        perror ("Read error");
        keepReading = false;
    } else if (1 == n) {
        cout << temp << " ";
    }
    if (256 == temp) keepReading = false;

}
cout << endl;

close(fd);

我在两台机器上都启动了代码,第一组 while 循环运行良好。 Windows 端的终端显示 0 到 255。然后它就坐在那里。如果我输出在 linux 端为第二组 while 循环读取的字节数,它会不断给我 0 个字节。这通常表明端口已关闭,但我只是通过它发送了一堆信息,那怎么会呢?

【问题讨论】:

  • 您可以发布您为WriteFile 尝试过的内容吗?调用WriteFileReadFile 应该没有什么不同。
  • “没有这样的运气”不是一个合适的问题描述。没有“二进制写入模式”,它始终是二进制的。您可能必须在电线的另一端寻找问题。
  • 您应该确保DCB::fOutXDCB::fInX 都设置为0。

标签: c++ winapi serial-port


【解决方案1】:

我认为可能发生的情况是 Linux 正在检测中断并重置端口,或者设置了规范模式的事实将其搞砸了。除了您已有的设置之外,请尝试以下设置:

    options.c_iflag |= IGNBRK;
    options.c_iflag &= ~BRKINT;
    options.c_iflag &= ~ICRNL;
    options.c_oflag = 0;
    options.c_lflag = 0;

【讨论】:

  • 这似乎没有什么不同。不过,我的想法是一样的,有些字节被解释为控制字符。不过,我发送哪些字节似乎并不重要。
【解决方案2】:

正如 Jonathan Potter 所提到的,您很可能没有关闭 XON/XOFF 流控制。在调用SetCommState之前添加这些行:

dcbSerialParams.fOutX = 0;
dcbSerialParams.fInX  = 0;

您可能需要设置的其他一些字段:

dcbSerialParams.fNull = 0;
dcbSerialParams.fDtrControl = DTR_CONTROL_DISABLE;
dcbSerialParams.fRtsControl = RTS_CONTROL_DISABLE;

【讨论】:

  • 我试过了,结果没有变化。我一直在考虑的一件事是:可以通过串行端口登录,实际上这就是您首先设置板的方式。从 Windows 发送的字节是否可以被终端而不是我的程序捕获?
【解决方案3】:

好吧,所以我想通了,而是同事想通了。在 linux 端,在文件 /etc/inittab 中我必须注释掉这一行:

T0:23:respawn:/sbin/getty -L ttymxc0 115200 vt100

这是以一种使其无法用于接收字节的方式获取串行端口。我现在看到了预期的输出。

【讨论】:

    猜你喜欢
    • 2012-07-23
    • 1970-01-01
    • 2016-01-15
    • 1970-01-01
    • 2018-09-04
    • 1970-01-01
    • 2017-06-03
    • 2012-05-14
    • 2015-07-02
    相关资源
    最近更新 更多