I wrote this a long time ago (from years 1985-1992, with just a few tweaks since then), and just copy and paste the bits needed into each project.

You must call cfmakeraw on a tty obtained from tcgetattr. You cannot zero-out a struct termios, configure it, and then set the tty with tcsetattr. If you use the zero-out method, then you will experience unexplained intermittent failures, especially on the BSDs and OS X. "Unexplained intermittent failures" include hanging in read(3).

#include <errno.h>
#include <fcntl.h> 
#include <string.h>
#include <termios.h>
#include <unistd.h>

int
set_interface_attribs (int fd, int speed, int parity)
{
        struct termios tty;
        if (tcgetattr (fd, &tty) != 0)
        {
                error_message ("error %d from tcgetattr", errno);
                return -1;
        }

        cfsetospeed (&tty, speed);
        cfsetispeed (&tty, speed);

        tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;     // 8-bit chars
        // disable IGNBRK for mismatched speed tests; otherwise receive break
        // as \000 chars
        tty.c_iflag &= ~IGNBRK;         // disable break processing
        tty.c_lflag = 0;                // no signaling chars, no echo,
                                        // no canonical processing
        tty.c_oflag = 0;                // no remapping, no delays
        tty.c_cc[VMIN]  = 0;            // read doesn't block
        tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

        tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl

        tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
                                        // enable reading
        tty.c_cflag &= ~(PARENB | PARODD);      // shut off parity
        tty.c_cflag |= parity;
        tty.c_cflag &= ~CSTOPB;
        tty.c_cflag &= ~CRTSCTS;

        if (tcsetattr (fd, TCSANOW, &tty) != 0)
        {
                error_message ("error %d from tcsetattr", errno);
                return -1;
        }
        return 0;
}

void
set_blocking (int fd, int should_block)
{
        struct termios tty;
        memset (&tty, 0, sizeof tty);
        if (tcgetattr (fd, &tty) != 0)
        {
                error_message ("error %d from tggetattr", errno);
                return;
        }

        tty.c_cc[VMIN]  = should_block ? 1 : 0;
        tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

        if (tcsetattr (fd, TCSANOW, &tty) != 0)
                error_message ("error %d setting term attributes", errno);
}


...
char *portname = "/dev/ttyUSB1"
 ...
int fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC);
if (fd < 0)
{
        error_message ("error %d opening %s: %s", errno, portname, strerror (errno));
        return;
}

set_interface_attribs (fd, B115200, 0);  // set speed to 115,200 bps, 8n1 (no parity)
set_blocking (fd, 0);                // set no blocking

write (fd, "hello!\n", 7);           // send 7 character greeting

usleep ((7 + 25) * 100);             // sleep enough to transmit the 7 plus
                                     // receive 25:  approx 100 uS per char transmit
char buf [100];
int n = read (fd, buf, sizeof buf);  // read up to 100 characters if ready to read

The values for speed are B115200, B230400, B9600, B19200, B38400, B57600, B1200, B2400, B4800, etc. The values for parity are 0 (meaning no parity), PARENB|PARODD (enable parity and use odd), PARENB (enable parity and use even), PARENB|PARODD|CMSPAR (mark parity), and PARENB|CMSPAR (space parity).

"Blocking" sets whether a read() on the port waits for the specified number of characters to arrive. Setting no blocking means that a read() returns however many characters are available without waiting for more, up to the buffer limit.


Addendum:

CMSPAR is needed only for choosing mark and space parity, which is uncommon. For most applications, it can be omitted. My header file /usr/include/bits/termios.h enables definition of CMSPAR only if the preprocessor symbol __USE_MISC is defined. That definition occurs (in features.h) with

#if defined _BSD_SOURCE || defined _SVID_SOURCE
 #define __USE_MISC     1
#endif

The introductory comments of <features.h> says:

/* These are defined by the user (or the compiler)
   to specify the desired environment:

...
   _BSD_SOURCE          ISO C, POSIX, and 4.3BSD things.
   _SVID_SOURCE         ISO C, POSIX, and SVID things.
...
 */
Answer from wallyk on Stack Overflow
Top answer
1 of 2
289

I wrote this a long time ago (from years 1985-1992, with just a few tweaks since then), and just copy and paste the bits needed into each project.

You must call cfmakeraw on a tty obtained from tcgetattr. You cannot zero-out a struct termios, configure it, and then set the tty with tcsetattr. If you use the zero-out method, then you will experience unexplained intermittent failures, especially on the BSDs and OS X. "Unexplained intermittent failures" include hanging in read(3).

#include <errno.h>
#include <fcntl.h> 
#include <string.h>
#include <termios.h>
#include <unistd.h>

int
set_interface_attribs (int fd, int speed, int parity)
{
        struct termios tty;
        if (tcgetattr (fd, &tty) != 0)
        {
                error_message ("error %d from tcgetattr", errno);
                return -1;
        }

        cfsetospeed (&tty, speed);
        cfsetispeed (&tty, speed);

        tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;     // 8-bit chars
        // disable IGNBRK for mismatched speed tests; otherwise receive break
        // as \000 chars
        tty.c_iflag &= ~IGNBRK;         // disable break processing
        tty.c_lflag = 0;                // no signaling chars, no echo,
                                        // no canonical processing
        tty.c_oflag = 0;                // no remapping, no delays
        tty.c_cc[VMIN]  = 0;            // read doesn't block
        tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

        tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl

        tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
                                        // enable reading
        tty.c_cflag &= ~(PARENB | PARODD);      // shut off parity
        tty.c_cflag |= parity;
        tty.c_cflag &= ~CSTOPB;
        tty.c_cflag &= ~CRTSCTS;

        if (tcsetattr (fd, TCSANOW, &tty) != 0)
        {
                error_message ("error %d from tcsetattr", errno);
                return -1;
        }
        return 0;
}

void
set_blocking (int fd, int should_block)
{
        struct termios tty;
        memset (&tty, 0, sizeof tty);
        if (tcgetattr (fd, &tty) != 0)
        {
                error_message ("error %d from tggetattr", errno);
                return;
        }

        tty.c_cc[VMIN]  = should_block ? 1 : 0;
        tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

        if (tcsetattr (fd, TCSANOW, &tty) != 0)
                error_message ("error %d setting term attributes", errno);
}


...
char *portname = "/dev/ttyUSB1"
 ...
int fd = open (portname, O_RDWR | O_NOCTTY | O_SYNC);
if (fd < 0)
{
        error_message ("error %d opening %s: %s", errno, portname, strerror (errno));
        return;
}

set_interface_attribs (fd, B115200, 0);  // set speed to 115,200 bps, 8n1 (no parity)
set_blocking (fd, 0);                // set no blocking

write (fd, "hello!\n", 7);           // send 7 character greeting

usleep ((7 + 25) * 100);             // sleep enough to transmit the 7 plus
                                     // receive 25:  approx 100 uS per char transmit
char buf [100];
int n = read (fd, buf, sizeof buf);  // read up to 100 characters if ready to read

The values for speed are B115200, B230400, B9600, B19200, B38400, B57600, B1200, B2400, B4800, etc. The values for parity are 0 (meaning no parity), PARENB|PARODD (enable parity and use odd), PARENB (enable parity and use even), PARENB|PARODD|CMSPAR (mark parity), and PARENB|CMSPAR (space parity).

"Blocking" sets whether a read() on the port waits for the specified number of characters to arrive. Setting no blocking means that a read() returns however many characters are available without waiting for more, up to the buffer limit.


Addendum:

CMSPAR is needed only for choosing mark and space parity, which is uncommon. For most applications, it can be omitted. My header file /usr/include/bits/termios.h enables definition of CMSPAR only if the preprocessor symbol __USE_MISC is defined. That definition occurs (in features.h) with

#if defined _BSD_SOURCE || defined _SVID_SOURCE
 #define __USE_MISC     1
#endif

The introductory comments of <features.h> says:

/* These are defined by the user (or the compiler)
   to specify the desired environment:

...
   _BSD_SOURCE          ISO C, POSIX, and 4.3BSD things.
   _SVID_SOURCE         ISO C, POSIX, and SVID things.
...
 */
2 of 2
68

For demo code that conforms to POSIX standard as described in Setting Terminal Modes Properly and Serial Programming Guide for POSIX Operating Systems, the following is offered.
This code should execute correctly using Linux on x86 as well as ARM (or even CRIS) processors.
It's essentially derived from the other answer, but inaccurate and misleading comments have been corrected.

This demo program opens and initializes a serial terminal at 115200 baud for non-canonical mode that is as portable as possible.
The program transmits a hardcoded text string to the other terminal, and delays while the output is performed.
The program then enters an infinite loop to receive and display data from the serial terminal.
By default the received data is displayed as hexadecimal byte values.

To make the program treat the received data as ASCII codes, compile the program with the symbol DISPLAY_STRING, e.g.

 cc -DDISPLAY_STRING demo.c

If the received data is ASCII text (rather than binary data) and you want to read it as lines terminated by the newline character, then see this answer for a sample program.


#define TERMINAL    "/dev/ttyUSB0"

#include <errno.h>
#include <fcntl.h> 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>

int set_interface_attribs(int fd, int speed)
{
    struct termios tty;

    if (tcgetattr(fd, &tty) < 0) {
        printf("Error from tcgetattr: %s\n", strerror(errno));
        return -1;
    }

    cfsetospeed(&tty, (speed_t)speed);
    cfsetispeed(&tty, (speed_t)speed);

    tty.c_cflag |= (CLOCAL | CREAD);    /* ignore modem controls */
    tty.c_cflag &= ~CSIZE;
    tty.c_cflag |= CS8;         /* 8-bit characters */
    tty.c_cflag &= ~PARENB;     /* no parity bit */
    tty.c_cflag &= ~CSTOPB;     /* only need 1 stop bit */
    tty.c_cflag &= ~CRTSCTS;    /* no hardware flowcontrol */

    /* setup for non-canonical mode */
    tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
    tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
    tty.c_oflag &= ~OPOST;

    /* fetch bytes as they become available */
    tty.c_cc[VMIN] = 1;
    tty.c_cc[VTIME] = 1;

    if (tcsetattr(fd, TCSANOW, &tty) != 0) {
        printf("Error from tcsetattr: %s\n", strerror(errno));
        return -1;
    }
    return 0;
}

void set_mincount(int fd, int mcount)
{
    struct termios tty;

    if (tcgetattr(fd, &tty) < 0) {
        printf("Error tcgetattr: %s\n", strerror(errno));
        return;
    }

    tty.c_cc[VMIN] = mcount ? 1 : 0;
    tty.c_cc[VTIME] = 5;        /* half second timer */

    if (tcsetattr(fd, TCSANOW, &tty) < 0)
        printf("Error tcsetattr: %s\n", strerror(errno));
}


int main()
{
    char *portname = TERMINAL;
    int fd;
    int wlen;
    char *xstr = "Hello!\n";
    int xlen = strlen(xstr);

    fd = open(portname, O_RDWR | O_NOCTTY | O_SYNC);
    if (fd < 0) {
        printf("Error opening %s: %s\n", portname, strerror(errno));
        return -1;
    }
    /*baudrate 115200, 8 bits, no parity, 1 stop bit */
    set_interface_attribs(fd, B115200);
    //set_mincount(fd, 0);                /* set to pure timed read */

    /* simple output */
    wlen = write(fd, xstr, xlen);
    if (wlen != xlen) {
        printf("Error from write: %d, %d\n", wlen, errno);
    }
    tcdrain(fd);    /* delay for output */


    /* simple noncanonical input */
    do {
        unsigned char buf[80];
        int rdlen;

        rdlen = read(fd, buf, sizeof(buf) - 1);
        if (rdlen > 0) {
#ifdef DISPLAY_STRING
            buf[rdlen] = 0;
            printf("Read %d: \"%s\"\n", rdlen, buf);
#else /* display hex */
            unsigned char   *p;
            printf("Read %d:", rdlen);
            for (p = buf; rdlen-- > 0; p++)
                printf(" 0x%x", *p);
            printf("\n");
#endif
        } else if (rdlen < 0) {
            printf("Error from read: %d: %s\n", rdlen, strerror(errno));
        } else {  /* rdlen == 0 */
            printf("Timeout from read\n");
        }               
        /* repeat read to get full message */
    } while (1);
}

For an example of an efficient program that provides buffering of received data yet allows byte-by-byte handing of the input, then see this answer.


🌐
Raspberry Pi Forums
forums.raspberrypi.com › board index › programming › c/c++
Reading serial port in C: timing and performances - Raspberry Pi Forums
You will probably want to read more than a character at a time but the idea is the same. ... #include <stdio.h> #include <unistd.h> #include <fcntl.h> #include <termios.h> #include <errno.h> #include <string.h> #include <sys/ioctl.h> int main() { int sfd = open("/dev/ttyAMA1",O_RDWR|O_NOCTTY); if (sfd == -1) { printf("Error opening serial port: %s\n",strerror(errno)); return -1; } struct termios options; if (tcgetattr(sfd,&options) < 0) { printf("Error getting attributes: %s\n",strerror(errno)); return -1; } cfmakeraw(&options); cfsetspeed(&options,B500000); // 500000 baud options.c_cflag &= ~
Discussions

c - Reading from a serial port - Code Review Stack Exchange
I'm receiving data from a serial port in C, using Serial Programming Guide for POSIX Operating Systems as a guide. The data I receive should be always 10 bytes in length but I want to be sure that... More on codereview.stackexchange.com
🌐 codereview.stackexchange.com
January 23, 2014
Reading serial port with c programming
Here is the deal! I need to read (read only, not write) the data from the serial usb port using a c program. I have no idea how to do this but I would like it to be vary simple. Get the data... store it in a variable so I can play with the content and do this over and over again. More on forum.arduino.cc
🌐 forum.arduino.cc
0
0
February 22, 2011
Serial Port Programming on Linux using C language and System calls
Or you could just read the 1998 Serial Programming HOWTO More on reddit.com
🌐 r/linux
9
187
June 18, 2025
c - Read from serial port in Windows - Stack Overflow
serial port does not exist some other error occured. Inform user. error getting state error setting serial port state error setting port state error reading from input buffer -------------------------------- Process exited after 0.4768 seconds with return value 0 Press any key to continue . More on stackoverflow.com
🌐 stackoverflow.com
🌐
mbedded.ninja
blog.mbedded.ninja › programming › operating-systems › linux › linux-serial-ports-using-c-cpp
Linux Serial Ports Using C/C++ | mbedded.ninja
3 weeks ago - I have never used a serial port that didn’t use 8 (but they do exist). You must clear all of the size bits before setting any of them with &= ~CSIZE. tty.c_cflag &= ~CSIZE; // Clear all the size bits, then use one of the statements below ... If the CRTSCTS field is set, hardware RTS/CTS flow control is enabled. This is when there are two extra wires between the end points, used to signal when data is ready to be sent/received.
🌐
GitHub
gist.github.com › c6e56759e7c30e5497b1
serial port read by c · GitHub
serial port read by c. GitHub Gist: instantly share code, notes, and snippets.
🌐
Pololu
pololu.com › support › jrk g2 motor controller user’s guide › 15. writing pc software to control the jrk
Pololu - 15.6. Example serial code for Windows in C
It demonstrates how to set the ... how to read variables using a “Get variables” command. For a very similar example that works on Linux and macOS, see Section 15.5. The Jrk’s input mode should be set to “Serial / I2C / USB”, or else the “Set target” command will not work. Also, you will need to change the const char * device line in the code that specifies what serial port to connect ...
🌐
Lucidar
lucidar.me › en › serialib › read-and-write-strings-on-serial-port-in-c-cpp
How to read and write strings on serial port in C/C++ |
April 25, 2025 - The string is expected to be a Null-terminated string. Note that the null character does not belong to the string, so it is not sent to the serial device. ... int serialib::readString ( char *receivedString, char finalChar, unsigned int maxNbBytes, const unsigned int timeOut_ms=0);
🌐
Cprogramming
cboard.cprogramming.com › c-programming › 81984-reading-writing-serial-port.html
Reading and writing to a serial port
August 17, 2006 - The write() seems to be doing fine, and I would expect that I would be able to read the 4 bytes that I just sent with the write(), but no. I don't really know what this means or what to do about it. I'm pretty stuck. I've shut down minicom, and rebooted the system so I know (I think) that minicom doesn't have any hold on the port. Any suggestions would be much apprecated. Thanks, Bill ... > void main() main returns an int - see the FAQ > char *buf; 1.
Find elsewhere
Top answer
1 of 5
9

The code you posted contains no error-recovery at all. It's a bit off-topic on this site to ask how to implement a new feature (error-recovery); but I'll try.

It's not clear what your communication protocol looks like. It might be:

  1. A continuous stream of bytes, to be split into packets of 10
  2. 10-byte packets, with a measurable delay between packets, no reply expected
  3. 10-byte packets, after which silence until there is a reply, perhaps with a retry if there no reply

I'll assume it isn't 1. because that has little opportunity for error-recovery: if a byte were ever lost then you wouldn't know where the boundary is between "packets", if it's a continuous stream of bytes, unless you use 'framing' and 'escape sequences' in the data.

So I'll assume that it's 2. or 3.. In either case, what's important is:

  • There are 10 bytes received (probably received quickly with little or no delay between bytes)
  • There is then a delay (no bytes received) after those 10 bytes.

Setting Read Timeouts looks interesting. It may be your best algorithm: set VMIN to say that you want to receive no more or less than exactly 10 bytes when you read.

However that may have a problem:

However, the timeout only applies to the first character read, so if for some reason the driver misses one character inside the N byte packet then the read call could block forever waiting for additional input characters.

You don't say why you want error-recovery after losing a character: perhaps you sometimes get overruns in the driver, or bit parity errors from the serial port?

"Setting Input Parity Options" talks about handling the parity errors:

  1. Replace/mark the byte with an error byte

    If you do this then you can be more sure that you will get 10 bytes; but you can only do it if the protocol allows you to recognize an illegal byte value.

  2. Or remove the error byte

    If you do this then you must be able to recover from getting 9 bytes sometimes.

The data I receive should be always 10 bytes in length but I want to be sure that, if there is any error (more or less bytes received), reading will clear buffer before the next data arrive, so that there is always proper data in the buffer to be processed.

Reading should empty the buffer, if your sizeof(tmp_buffer) is bigger is the number of bytes queued in the driver. However:

  • It depends on the read mode (e.g. a read may block forever instead of clearing the buffer, if VMIN is set to non-zero)
  • If there are, somehow, very many received bytes enqueued in the driver, then you may have to read repeatedly until the driver is empty.
  • Immediately after you read, there may be more bytes in the driver: for example if the serial port is flow-controlled, reading from the driver allows the device to send again / send more.

Whether you can clear the buffer "before the next data arrive" is difficult to say: I don't know when the next data is supposed to arrive.

Depending on how you handle parity errors, maybe bytes are never lost. If bytes are sometimes lost then you may want to implement logic like:

read_10_bytes:
  read (waiting forever) until some bytes are returned
  if 10 bytes were read then return
  if less than 10 bytes were read, then:
    set an expiry timer
    loop doing the following
  read more bytes
  if you read 10 bytes before the timer expires, then clear the timer and return
  if the timer expires before you read 10 bytes, then discard the bad bytes and return

Instead of actually setting a timer, above, perhaps loop doing a blocking-read-with-timeout (which either reads the bytes, or expires).

As well as handling too few bytes (above), you could modify the above to check for receiving more than 10 bytes: after you receive 10 bytes, do another blocking-read-with-small-timeout to verify that there are no more bytes to receive. If there are extra bytes, then read them all before returning to the 'waiting-for-next-10-bytes' state (otherwise, these extra bytes will mess up your next 10-byte packet).


I think there's an obvious bug in the code. After you read 16 bytes, you completely clear your serial_buffer by zeroing si_processed, and you then think "success!" after each next 10 bytes you read.

Instead you should:

  • If you read too much data, don't discard the extra bytes: instead use memmove to move them to the beginning of the buffer (assuming they're the start of the next packet), and then read the subsequent bytes into the vacant space after them.

Something like:

// after reading and processing a 10-byte packet
if (si_processed > 10) // already have the start of the next packet
{
     // move start of next packet to start of buffer
     memmove(serial_buffer, serial_buffer+10, si_processed - 10);
     // not 0: remember how many start bytes we already have
     si_processed -= 10;
}
  • After you read any bytes, verify whether the start byte is your 0xA5 value, and discard the bytes if not.

Something like:

if (si_processed > 0) // have some bytes
{
    int i;
    for (i = 0; i < si_processed; ++i)
        if (serial_buffer[i] == 0xA5) // found start of packet
            break;
    if (i > 0)
    {
        // start of packet is not start of buffer
        // so discard bad bytes at the start of the buffer
        memmove(serial_buffer, serial_buffer+i, si_processed - i);
        si_processed -= i;
    }
}
2 of 5
4

You shouldn't need to call usleep() to throttle the loop. If you need usleep() prevent the loop from consuming 100% of the CPU, then something is wrong, since select() is supposed to be the gatekeeper that lets the loop continue when input is available to be processed. Perhaps you are failing to drain the socket or serial port completely in your input handlers, so that select() always returns immediately.

🌐
Arduino Forum
forum.arduino.cc › projects › interfacing w/ software on the computer
Reading serial port with c programming - Interfacing w/ Software on the Computer - Arduino Forum
February 22, 2011 - Here is the deal! I need to read (read only, not write) the data from the serial usb port using a c program. I have no idea how to do this but I would like it to be vary simple. Get the data... store it in a variable so…
🌐
Reddit
reddit.com › r/linux › serial port programming on linux using c language and system calls
r/linux on Reddit: Serial Port Programming on Linux using C language and System calls
June 18, 2025 -

I have written a detailed post on programming the Linux serial port using C to communicate with external embedded computers like Arduino.

Code along with the article can be found here.

🌐
Unilim
unilim.fr › pages_perso › vahid.meghdadi-neyshabouri › port_serie.html
serial port C
// Here we read byte by byte and we end the loop when we receive a 0 caracter i=0; do { if (ReadFile(hDevID, &readbuf, 1, (LPDWORD)&nbbytes, NULL)) // 1 is the number // of bytes that we read { if (nbbytes == 0) { printf("ReadFile() timed out\n"); return -1; } } else { printf("ReadFile() failed\n"); return -1; } readbytes += nbbytes; // here nbbytes is alwayes equal to 1 printf("%c",readbuf); // print the read caracters on the screen buffer[i++]=readbuf; // save the string in a buffer } while(readbuf != 10); // read until the a specian caracter arrives buffer[i]=0; printf("%s",buffer); //------------------------------------------------------------------------------------------------------ // Step 6 : Closing the serial port //------------------------------------------------------------------------------------------------------ // Close the COM4 serial port.
🌐
Experts Exchange
experts-exchange.com › questions › 29157573 › Read-and-Write-on-Serial-Port-under-Ubuntu-and-C-C.html
Solved: Read and Write on Serial Port under Ubuntu and C/C++ | Experts Exchange
September 9, 2019 - You are reading a character at a time, use found line feed marker, when you see \r Then your reading loop shoukd check whether line feed (chr(10)) was seen and the current character is cr chr(13) \n IMHO, it is easier to trim the string by one charcter, versus buffering two characters before add them in.
🌐
Reddit
reddit.com › r/learnprogramming › [c++] serial port read and write
r/learnprogramming on Reddit: [C++] Serial Port Read and Write
February 15, 2013 -

Well, actually, I already have the write down, just having trouble reading data.

Here is my code:

int main()
{

hexConvert data[10000];

fd1=open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);

if (fd1 == -1 )
{

	perror("open_port: Unable to open /dev/ttyS0 – ");
}

else

{

fcntl(fd1, F_SETFL,0);

printf("Port 1 has been sucessfully opened and %d is the file description\n",fd1);

}

for(int i = 0; i < 1; i++)
{
wr=write(fd1,"t",4);
}

hexConvert h;
long l;
for(int i = 0; i < 100; i++)
{
	rd = read(fd1,buff,4);

	data[i].msb = buff[0];
	
	printf("0 = %c", data[i].msb);
}

close(fd1);

return 1;

}

Okay, so two big questions here: I fully understand th UART interface at a bit banging/harware level, but am having trouble finding info about the C++ accessors. The line:

fd1=open("/dev/ttyUSB0", O_RDWR | O_NOCTTY | O_NDELAY);

What do those flags mean? I assume they have to do with the operation mode (half duplex,8 bits or 9 bits ect). Is this correct?

Also, where in the code is the baud rate specifier? I assume it knows it cause its able to send correct signals to an embedded system.

Finally, as you may be able to tell, I have no clue how to read data coming back from my embedded system. I know that data is being sent, one byte at a time over the same interface. Specifically, what does the third parameter in:

rd = read(fd1, buff, 8)

mean? Also, where is the data read stored? My program never prints out any data, it seems to get hung up on the read() command.

Thanks in advance for the help!!!

Top answer
1 of 2
2
What do those flags mean? I assume they have to do with the operation mode (half duplex,8 bits or 9 bits ect). Is this correct? No. Read the documentation for your system, e.g. manpages. This kind of thing is system-specific, and you didn't specify what system you're using, so I'll have to assume Linux. Here's the open(2) manpage for Linux . Also, where in the code is the baud rate specifier? I assume it knows it cause its able to send correct signals to an embedded system. It's not set anywhere. If it works, it's only by accident (i.e. the default values were correct.) The ioctl() syscall (documented in the ioctl(2) manpage ) is used to get or set parameters of a file descriptor. This is how many low level APIs communicate with the kernel for things that cannot be represented as simple reads or writes of a file descriptor. On Linux the ioctl_list(2) manpage lists all of the available ioctl values, and you can see that it is far-ranging: networking, filesystems, sound, various hardware, etc. Some ranges have a dedicated sub-manpage, such as tty_ioctl(4) . In this case of the terminal-related ioctls, there is also a higher level abstraction called termios which is documented by the termios(3) manpage. This API is meant to be more portable than doing raw ioctls, which may vary across systems. POSIX documents the termios API and gives a decent overview. I have no clue how to read data coming back from my embedded system. I know that data is being sent, one byte at a time over the same interface. Specifically, what does the third parameter in: rd = read(fd1, buff, 8) mean? Also, where is the data read stored? My program never prints out any data, it seems to get hung up on the read() command. Again, consult the documentation: read(2) . The first parameter is the file descriptor, the second is a pointer to the location where the data will be stored, and the third is the size. You are requesting that this function reads 8 bytes into the location pointed to by buff. Since you omitted that part of the program (don't do that) I have no idea what buff is and I can't help you further. You opened the fd in non-blocking mode (because of the O_NDELAY flag) but you then cleared that flag by calling fcntl() with F_SETFL (set flags) with a third argument of 0, which means all the flags are cleared and the descriptor is back to blocking mode. (Why on earth would you do this?) Blocking mode means that the operating system waits to fulfill the request; if you ask it to read 8 bytes but only 1 byte is available, it will block (wait) until more bytes arrive in an attempt to satisfy your request to read 8. (The request cannot always be fulfilled, due to things like interrupted syscalls, so you must always check the return value to see how many were actually read; this is missing from your code.) I have no idea what kind of data your device is sending, but if it's sending a single byte and then waiting for your program to respond, then this has no chance of ever working as this is a deadlock. Also, this line is very very wrong: wr=write(fd1,"t",4); You are asking the system to write 4 bytes, but the buffer that you pass only contains two bytes (the character 't' followed by the NUL byte) so this is reading two more random bytes after that. This is undefined behavior, and very dangerous.
2 of 2
1
Macro: int O_NOCTTY If the named file is a terminal device, don't make it the controlling terminal for the process. See section 27. Job Control, for information about what it means to be the controlling terminal. If O_NDELAY or O_NONBLOCK is set: The open will return without waiting for the device to be ready or available; subsequent behavior of the device is device specific. If O_NDELAY and O_NONBLOCK are clear: The open will block until the device is ready or available. The manpages are great.
🌐
FreeBSD
forums.freebsd.org › development › userland programming and scripting
C - Sample code for reading from a serial port | The FreeBSD Forums
June 9, 2018 - Emphasizes that posix serial IO is not just open uart, write a byte, read a byte, and close....but that there are other important considerations: cooked vs raw, word length and parity, importance of non-blocking reads, etc. ... I was never able to get my head around uart programming or even 'c' in general. All I was hoping to do is find why some 'c' code works with Linux (Debian) but the same code does not work with FreeBSD. The code is here. It is supposed to send data using xmodem to the serial port but in FreeBSD it simply seems to stay in a wait state.
🌐
Stack Overflow
stackoverflow.com › questions › 45401449 › how-to-read-data-from-a-serial-port-and-write-it-to-a-file
c - How to read data from a serial port and write it to a file - Stack Overflow
July 30, 2017 - I can post the code that opens the serial port and log file if its necessary but I don't want to clutter my questions. I currently have a while loop which reads data from the serial port into a 32 element char array and then writes it to the file.
🌐
Pololu
pololu.com › support › jrk g2 motor controller user’s guide › 15. writing pc software to control the jrk
Pololu - 15.5. Example serial code for Linux and macOS in C
It demonstrates how to set the ... how to read variables using a “Get variables” command. For a very similar example that only works on Windows, see Section 15.6. The Jrk’s input mode should be set to “Serial / I2C / USB”, or else the “Set target” command will not work. Also, you might need to change the const char * device line in the code that specifies what serial port to connect ...
🌐
Arduino Forum
forum.arduino.cc › projects › interfacing w/ software on the computer
Reading serial data from the Arduino in C - Interfacing w/ Software on the Computer - Arduino Forum
March 22, 2011 - I'm trying to read serial data ... FILE *serialPort; system( "MODE COM4: BAUD=9600 PARITY=n DATA=8 STOP=1" ); serialPort = fopen("COM4:", "r" ); if (serialPort == NULL) { printf ("Error: unable to open serial port COM4\n"); ...
🌐
Google Groups
groups.google.com › g › beagleboard › c › vbRrGiqZyfs
UART, serial port read C/C++
I think Simon's post will get you on the right track. You are sending a command over the UART and expecting a response back, you pretty much have to block or read in a loop to give the external device time to reply. I open the port (O_RDWR | O_NOCTTY | O_NDELAY) and use