Serial Port Programming: tcflush – TCIFLUSH,TCOFLUSH example

termios

The termios module provides a POSIX-style interface for controlling the behavior of TTYs and other serial communication devices on UNIX systems. All the functions operate on integer file descriptors such as those returned by the os.open() function or the fileno() method of a file object. In addition, the module relies on a large collection of constants that are also defined in this module.

tcflush flushes/discards:

  • data which is written but not transmitted and/or
  • data which is received but not read by user

The exact operation depends on the ‘queue_selector’ argument.

#include <termios.h>
int tcflush(int fildes, int queue_selector);

Possible values of queue_selector are:

  • TCIFLUSH – Flushes/Discards received data, but not read.
  • TCOFLUSH – Flushes/Discards written data, but not transmitted.
  • TCIOFLUSH – Flushes/Discards both.

For example, the following example flushes pending input data:

int rc;
rc = tcflush(fd,TCIFLUSH);

Let’s write a sample code to check what happens when we:

  1. Loop until there are bytes in input buffer using ‘FIONREAD’ ioctl.
  2. Call tcflush with queue selector ‘TCIFLUSH’.
  3. Check how many bytes are present in input buffer with ‘FIONREAD’ ioctl.

Need two USB to serial/serial devices connected (TX-RX/RX-TX)

Code:

#include <stdio.h>
#include <sys/types.h>
#include <termios.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/ioctl.h>

#define MAX_BYTES_TO_READ 50
#define SERIAL_DEVICE "/dev/ttyUSB0"

int main()
{
 struct termios serial_port_settings;
 int fd;
 int retval;
 char buf[256];
 int bytes_available;
 int i;

 fd = open(SERIAL_DEVICE, O_RDWR);
 if (fd < 0) {
  perror("Failed to open SERIAL_DEVICE");
  exit(1);
 }
 
 retval = tcgetattr(fd, &serial_port_settings);
 if (retval < 0) {
  perror("Failed to get termios structure");
  exit(2);
 }

 //setting baud rate to B38400
 retval = cfsetospeed(&serial_port_settings, B38400);
 if (retval < 0) {
  perror("Failed to set 38400 output baud rate");
  exit(3);
 }
 retval = cfsetispeed(&serial_port_settings, B38400);
 if (retval < 0) {
  perror("Failed to set 38400 input baud rate");
  exit(4);
 }
 serial_port_settings.c_lflag &= ~(ICANON);
 serial_port_settings.c_lflag &= ~(ECHO | ECHOE);
 retval = tcsetattr(fd, TCSANOW, &serial_port_settings);
 if (retval < 0) {
  perror("Failed to set serial attributes");
  exit(5);
 }
 printf("Successfully set the baud rate\n");
 while (1) {
  retval = ioctl(fd, FIONREAD, &bytes_available);
  if (retval < 0) {
   perror("FIONREAD ioctl failed\n");
   exit(6);
  }
  usleep(50*1000L);
  if (bytes_available > 0)
   break;
 }
 printf("tcflush: Bytes available in the input buffer before TCIFLUSH:%d\n",
   bytes_available);
 tcflush(fd, TCIFLUSH);
 retval = ioctl(fd, FIONREAD, &bytes_available);
 if (retval < 0) {
  perror("FIONREAD ioctl failed\n");
  exit(7);
 }
 printf("tcflush:Bytes available in the input buffer after TCIFLUSH:%d\n",
   bytes_available);
 close(fd);
 return 0;
}

Output:

Same behavior will happen when we call write on the serial port with large number of bytes, and in the next statement call tcflush with queue selector ‘TCOFLUSH’ not all data will be received by the other serial port.

Receive Code: (fionread)

Consider the example shown below:

#include <stdio.h>
#include <sys/types.h>
#include <termios.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/ioctl.h>

#define SERIAL_DEVICE "/dev/ttyUSB0"

int main()
{
 struct termios serial_port_settings;
 int fd;
 int retval;
 char buf[256];
 int i;
 int bytes_available;

 fd = open(SERIAL_DEVICE, O_RDWR);
 if (fd < 0) {
  perror("Failed to open SERIAL_DEVICE");
  exit(1);
 }
 
 retval = tcgetattr(fd, &serial_port_settings);
 if (retval < 0) {
  perror("Failed to get termios structure");
  exit(2);
 }

 //setting baud rate to B38400
 retval = cfsetospeed(&serial_port_settings, B38400);
 if (retval < 0) {
  perror("Failed to set 38400 output baud rate");
  exit(3);
 }
 retval = cfsetispeed(&serial_port_settings, B38400);
 if (retval < 0) {
  perror("Failed to set 38400 input baud rate");
  exit(4);
 }
 serial_port_settings.c_lflag &= ~(ICANON);
 serial_port_settings.c_lflag &= ~(ECHO | ECHOE);
 retval = tcsetattr(fd, TCSANOW, &serial_port_settings);
 if (retval < 0) {
  perror("Failed to set serial attributes");
  exit(5);
 }
 printf("/dev/ttyUSB0:Successfully set the baud rate\n");
 while (1) {
  retval = ioctl(fd, FIONREAD, &bytes_available);
  if (retval < 0) {
   perror("FIONREAD ioctl failed\n");
   exit(6);
  }
  sleep(5);
  if (bytes_available > 0)
   break;
 }
 printf("/dev/ttyUSB0:Bytes in input buffer:%d\n", bytes_available);
 close(fd);
 return 0;
}

TransmitCode:(tcflush_output)

Consider the example shown below:

#include <stdio.h>
#include <sys/types.h>
#include <termios.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>

#define SERIAL_DEVICE "/dev/ttyUSB1"

int main()
{
 struct termios serial_port_settings;
 int fd;
 int retval;
 char *buf = NULL;
 int bufsize = 0;

 fd = open(SERIAL_DEVICE, O_RDWR);
 if (fd < 0) {
  perror("Failed to open SERIAL_DEVICE");
  exit(1);
 }
 
 retval = tcgetattr(fd, &serial_port_settings);
 if (retval < 0) {
  perror("Failed to get termios structure");
  exit(2);
 }

 //setting baud rate to B38400
 retval = cfsetospeed(&serial_port_settings, B38400);
 if (retval < 0) {
  perror("Failed to set 38400 output baud rate");
  exit(3);
 }
 retval = cfsetispeed(&serial_port_settings, B38400);
 if (retval < 0) {
  perror("Failed to set 38400 input baud rate");
  exit(4);
 }
 serial_port_settings.c_lflag |= ICANON; 
 serial_port_settings.c_oflag |= OCRNL;
 serial_port_settings.c_oflag |= OLCUC;
 retval = tcsetattr(fd, TCSANOW, &serial_port_settings);
 if (retval < 0) {
  perror("Failed to set serial attributes");
  exit(5);
 }
 printf("/dev/ttyUSB1:Successfully set the baud rate\n");
loop: 
 printf("/dev/ttyUSB1:Enter size of the buffer:");
 scanf("%d", &bufsize);
 if (bufsize <= 0) {
  printf("Buffer size should be greater > 0\n");
  goto loop;
 }
 buf = malloc(bufsize);
 if (!buf) {
  perror("Failed to allocate buffer\n");
  exit(6);
 }
 memset(buf, 'A', bufsize);
 buf[bufsize-2] = '\n';
 buf[bufsize-1] = '\0';
 retval = write(fd, buf, bufsize);
 if (retval < 0) {
  perror("write on SERIAL_DEVICE failed");
  exit(7);
 }
 tcflush(fd, TCOFLUSH);
 printf("/dev/ttyUSB1: Flushing output buffer\n");
 free(buf);
 close(fd);
 return 0;
}

Output:

Related Post