Serial Port Programming in Linux

Configure Serial Port

Configuration of the serial port under Linux takes place through the use the termios struct, and consists of four steps :
  • Create the struct and initialize it to the current port settings.
  • Set the speed attribute of the struct to the de-sired port speed using the functions cfsetispeed()and cfsetospeed(). While these functions allow different reading and writing speed, most hardware and system implementations do not allow these speeds to be different.
  • Sets the timeouts of the port.
  • Apply the settings to the serial port.
    While opening the serial port is generally easier in Linux than it is in Windows, configuring it is harder as there is more bit-masking involved to change a single option. While there are convenient functions that can be used to set the speed of the port, other options, like parity and number of stop bits, are set using the c cflag member of the termios struct, and require bitwise operations to set the various settings.
Linux is also only capable of setting the read time- out values. This is set using the c cc member of the termios struct which is actually an array indexed by defined values. Please see the code below for an example. Souce Code

// create the struct
struct termios options;

// get the current settings of the
// serial port
tcgetattr(fd, &options);

// set the read and write speed to
// 19200 BAUD
// All speeds can be prefixed with B
// as a settings.
cfsetispeed(&options, B19200);
cfsetospeed(&options, B19200);

// now to set the other settings
// here we will have two examples.
// The first will be no parity,
// the second will be odd parity.
// Both will assume 8-bit words

*     no parity example

// PARENB is enable parity bit
// so this disables the parity bit
options.c_cflag &= ~PARENB

// CSTOPB means 2 stop bits
// otherwise (in this case)
// only one stop bit
options.c_cflag &= ~CSTOPB

// CSIZE is a mask for all the
// data size bits, so anding
// with the negation clears out
// the current data size setting
options.c_cflag &= ~CSIZE;

// CS8 means 8-bits per work
options.c_cflag |= CS8;

*    odd parity example

// enable parity with PARENB
options.c_cflag |= PARENB

// PARAODD enables odd parity
// and with ~PARAODD for even parity
options.c_cflag |= PARODD

// Only one stop bit
options.c_cflag &= ~CSTOPB

// clear out the current word size
options.c_cflag &= ~CSIZE;

// we only have 7-bit words here
// because one bit is taken up
// by the parity bit
options.c_cflag |= CS7;

// Set the timeouts
// VMIN is the minimum amount
// of characters to read.
options.c_cc[VMIN] = 0;

// The amount of time to wait
// for the amount of data
// specified by VMIN in tenths
// of a second.
optiont.c_cc[VTIME] = 1;

// CLOCAL means don't allow
// control of the port to be changed
// CREAD says to enable the receiver
options.c_cflag |= (CLOCAL | CREAD);

// apply the settings to the serial port
// TCSNOW means apply the changes now
// other valid options include:
//    TCSADRAIN - wait until every
//        thing has been transmitted
//    TCSAFLUSH - flush buffers
//        and apply changes
if(tcsetattr(fd, TCSANOW, &options)!= 0) {

   // error code goes here


Opening the Serial Port

int fd = open(                               
         // the name of the serial port                     
         // as a c-string (char *)
         // eg. /dev/ttys0
         // configuration options
         // O_RDWR - we need read
         //     and write access
         // O_CTTY - prevent other
         //     input (like keyboard)      
         //     from affecting what we read
         // O_NDELAY - We don't care if     
         //     the other side is           
         //     connected (some devices
         //     don't explicitly connect)     
         O_RDWR | O_NOCTTY | O_NDELAY         
if(fd == -1) {
    // error code goes here

Reading and Writing Serial Port in Linux

      Reading from the Serial Port                        
// fd is the file descriptor to the
//      serial port
// buf is a pointer the array we want to
//      read data into
// bufSize is the amount of data that we
//      want to read in
int wordsRead = read(fd, buf, bufSize);


      Writing to the Serial Port

// write data to the serial port
// fd is the file descriptor of
//      the serial port
// buf is a pointer to the data that
//      we want to write to the serial
//      port
// bufSize is the amount of data that we
//      want to write
int wordsWritten = write(fd, buf, bufSize);

Closing Serial Port in Linux

// close the serial port
if(close(fd) == -1) {
   // error code goes here
Sample Source Code [com-linux.c]
(credit to Mark Zehner / Peter Baumann)