Reading Serial Port Blocks for Unknown Reason

Why cannot I read data from a serial port?

I'm not sure what has happened but the following settings finally worked. I will share it with you as I got a lot of help here on Stackoverflow:

serial = open(name.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
fcntl(serial, F_SETFL,0);

tcgetattr(serial, &options);
options.c_ispeed = _baudRate;
options.c_ospeed = _baudRate;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;
options.c_cflag &= ~PARENB;
options.c_iflag &= ~(INPCK|PARMRK|ISTRIP);
options.c_cflag &= ~CSTOPB;

options.c_cflag |= CREAD |CLOCAL ;
options.c_cc[VMIN]=0;
options.c_cc[VTIME]=10;

options.c_cflag &= ~CRTSCTS; // turn off hardware flow control
options.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off sowftware flow control
options.c_lflag &= ~ICANON;
options.c_lflag &= ~ISIG;
options.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); // Disable any special handling of received bytes
options.c_oflag &= ~OPOST; // Prevent special interpretation of output bytes (e.g. newline chars)
options.c_oflag &= ~ONLCR; // Prevent conversion of newline to carriage return/line feed

tcflush(serial, TCIFLUSH);
tcsetattr(serial, TCSANOW, &options);

Can't get C to write and read serial port

First,

if (buff=msg)

is assignment, not comparison :) The latter is ==.

Second,

if (buff == msg)

is actually pointer comparison, not string comparison. For string comparison, see strcmp() from C standard library.

Third,

char *buff;
...
rd=read(fd,buff,sizeof(msg));

buff is left uninitialized - there's no memory allocated for it, so you're happy enough it doesn't crash at all.

Well, there is more to check, but listed above is already enough to prevent the program from functioning correctly.

As an advice: try to put a debugging printf below the read line to see what is actually read from the port. And remember, the data read from the port is not guaranteed to be zero-terminated (see zero-terminated strings for reference), so you have to watch for this also (either add a zero after the actual data, or somehow limit string operations on the buffer, like using strncmp() instead of strcmp()).

C++ Serial port reading issue: does ioctl(FIONREAD) set a wrong value?

This code worked a few days ago but now it isn't anymore.

Fickle program behavior usually indicates improper or incomplete initialization.

Your termios initialization only configures the baudrate and character framing, and everything else is left to chance.

See Setting Terminal Modes Properly
and Serial Programming Guide for POSIX Operating Systems.


Your revised code still has not properly resolved this issue.

The code never initializes the termios structure options by calling the tcgetattr() function.

For sample code see my answer to How to open, read, and write from serial port in C?



options.c_lflag = 0;

That is not considered the proper way of assigning a termios element.



options.c_cc[VMIN]     = 1;

Non-canonical mode requires definition of both the VMIN and VTIME entries.

Your code uses whatever garbage value that exists at the location for VTIME.

See Linux Blocking vs. non Blocking Serial Read.



FIONREAD which doesn't write the correct number to the bytes_available-var (anymore).

Negative descriptions, i.e. what does not occur, are not as helpful or specific as descriptions of what does occur.

So what kind of values are you getting back?

Why do you think it is "wrong"?

More importantly, why aren't you checking the return value from each syscall, especially this ioctl() that you think is giving you problems?

Most likely is that the ioctl() failed, did not update your bytes_available variable, and returned an error code.

Instead of first checking for a good return, your code unconditionally uses the returned argument.


Another answer that critiques your code is misleading. Flow control can be disabled. Your code is broken because it doesn't do proper initialization and is not checking for error returns, not because the comm link is "deadlocked".


In your revised code:

    bytes_read = read(serial, buf, datalength-bytes_in_msg);
usleep(1000);

A sleep or delay before and/or after a blocking read is superfluous.

write() to serial port fails when called twice

I think that your send buffer is getting full and you are using a non-blocking socket which means that instead of waiting for the buffer to clear like in a blocking socket, the process just returns the "Resource temporarily unavailable error". See this thread for more info: What can cause a “Resource temporarily unavailable” on sock send() command



Related Topics



Leave a reply



Submit