我将数据字节从linux发送到串口RS232的窗口然后一切正常,只有我必须处理来自linux的0xa发送,因为Windows将其读取为0xd + 0xa。 但是当我从windows发送数据字节到linux时,一些字节被替换为 - windows发送 - 0xd linux接收0xa windows发送 - 0x11 linux接收整数8200的垃圾tyte值
请解释当我将数据从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 write serial -
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时可以替换哪个字节
答案 0 :(得分:3)
如果您在Windows上使用ReadFile
和WrietFile
,在Linux中使用read
和write
,那么行结尾应该无关紧要,其他比“你必须在收到它后在某个时候翻译它。”
这看起来不对:
while(read(_fd_port_no,buffer+_buffer_len,sizeof(buffer))>0)
{
_buffer_len = _buffer_len+sizeof(buffer);
}
您应该考虑read
返回的读取大小。
如果sizeof(buffer)
是您正在阅读的实际缓冲区,则添加+_buffer_len
,当_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应该是安全的。
答案 1 :(得分:1)
我认为你必须在从串口读取磁通之前进行冲洗
tcflush(_fd_port_no TCIFLUSH);
furthemore您是否尝试使用指挥官在控制台上看到助焊剂 猫< dev / ttyS0?
答案 2 :(得分: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()
,这将禁用对输入和输出字符的所有特殊处理。
答案 3 :(得分:1)
全部谢谢
此更改解决了我的问题
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);