Linux and Windows serial port communication
I’m sending data bytes from linux to windows via serial RS232 and then everything works fine, only I have to deal with the 0xa sent from linux because windows reads it as 0xd + 0xa.
But when I send data bytes from Windows to Linux, some bytes are replaced with –
Windows Send – 0xd Linux receives 0xa
Windows Send – 0x11 Linux receives an integer garbage type value of 8200
Please explain what went wrong when I sent data from Windows to Linux.
Thanks in advance
Windows serial port initialization
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 writes serial port –
WriteFile(hCom, buffer, len, &write, NULL);
Linux serial initialization –
_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);
Read serial port linux-
while(read(_fd_port_no,buffer+_buffer_len,sizeof(buffer))>0)
{
_buffer_len = _buffer_len+sizeof(buffer);
}
Yes, as I said, only NL/CR issues were detected from Linux to Windows, but I solved it with byte substitution,
But do you know the serila data sent from Windows to Linux (byte substitution policy).
I actually have to send a 200 KB file in a 200-byte block serially so that if sent from Windows to Linux, which byte can be replaced
Solution
If you’re using ReadFile
and WrietFile
on Windows and read
and write
on Linux, it really matters what it should be at the end of the line, except “you have to translate it sometime after receiving it.”
This doesn’t look right :
while(read(_fd_port_no,buffer+_buffer_len,sizeof(buffer))>0)
{
_buffer_len = _buffer_len+sizeof(buffer);
}
You should consider the read size returned by read
.
If sizeof(buffer) is the actual buffer you are reading into, add +_buffer_len
when _buffer_len >= sizeof(buffer)
will be written out of the buffer
.
Also a little worried about this :
options.c_iflag |= (IXON | IXOFF | IXANY);
options.c_cflag &= ~ CRTSCTS;
Are you sure you want to use XOFF/CTRL-S (0x13) to stop the stream? Usually this means that data containing CTRL-S is not allowed – this may not be a problem when sending text data, but if you need to send binary data, it definitely will. IXOFF also means that the other end must respond to XOFF and XON (CTRL-Q, 0x11) to stop/start the data flow. In general, we do not want this to happen in modern systems….
If the wiring at both ends is correct, it should be safe to use RTS/CTS.