1

I am working on a "high level" C++ interface for the standard PC serial port. When I open the port, I would like to clear the input and output buffers in order not to receive or send data from previous usage of the port. To do that, I use the tcflush function. However, it does not work. How can that be? My "port opening" code can be seen below. Yes I use C++ exceptions but none are getting thrown. That indicates that tcflush returns 0 but it does not clear the buffer.

The only way I can clear the input buffer is to read bytes from it until there is none left. This usually takes a couple of seconds and I do not think of it as a solution.

Thanks in advance :-)

fd = ::open(port.c_str(), O_RDWR | O_NOCTTY);

if (fd < 0)
{
    throw OpenPortException(port);
    return;
}

// Get options
tcgetattr(fd, &options);

// Set default baud rate 9600, 1 stop bit, 8 bit data length, no parity
options.c_cflag &= ~PARENB;
options.c_cflag &= ~CSTOPB;
options.c_cflag &= ~CSIZE;
options.c_cflag |= CS8;

// Default timeout (1000 ms)
options.c_cc[VMIN] = 0;
options.c_cc[VTIME] = 10;

// Additional options
options.c_cflag |= (CLOCAL | CREAD);

this->port = port;

// Apply the settings now
if (tcsetattr(fd, TCSANOW, &options) != 0)
{
    throw PortSettingsException();
}

// Flush the port
if (tcflush(fd, TCIOFLUSH) != 0)
{
    throw IOException();
}
MPelletier
  • 16,256
  • 15
  • 86
  • 137
pvh1987
  • 621
  • 5
  • 8
  • 12
  • 1
    What is the test you are doing to see if this is working properly? – btse Feb 25 '14 at 15:20
  • I expect to see `cfsetispeed(&options, B9600); cfsetospeed(&options, B9600);` if the code does as the comment implies '// Set default baud rate 9600..." – chux - Reinstate Monica Feb 25 '14 at 15:41
  • I set the speed with the above commands in another function. I have done the testing with a microcontroller that sends characters to the serial port. If I stop the transmission after I exited my program, the input buffer will have characters in it at the next run. That is why I want to clear the buffer. – pvh1987 Feb 27 '14 at 13:41

2 Answers2

4

This is the correct way (as below):

usleep(1000);
ioctl(fd, TCFLSH, 0); // flush receive
ioctl(fd, TCFLSH, 1); // flush transmit
ioctl(fd, TCFLSH, 2); // flush both

User can choose both of the first 2 lines OR last line alone based on requirement. Please check if sleep may be required.

Sammy
  • 257
  • 2
  • 8
3

Try

ioctl(fd, TCFLUSH, dir)

with dir equal to 0 for receive, 1 for transmit, 2 for both.

  • Is there a sleep required before or after this call. Doesn't seem to be working for me (or not straightforward to find out if its working). Using Linux x86, 64 bit. – Sammy Oct 07 '17 at 22:06
  • 2
    Your answer is incomplete. Correction to your answer @user3485419 in the post. Its TCFLSH not TCFLUSH – Sammy Oct 07 '17 at 22:16