serisal programming in linux

Posted on 2007-04-03
Last Modified: 2013-11-13
I have a program that use to tranfer data by serial port:
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#define BAUDRATE B19200            
#define MODEMDEVICE "/dev/ttyS0"
#define _POSIX_SOURCE 1
#define FALSE 0
#define TRUE 1

volatile int STOP=FALSE;

int main(int agrs, char* agvs)
 int fd, res;
 struct termios oldtio,newtio;
 char buf[255];
 if (fd <0) {perror(MODEMDEVICE); exit(-1); }
 bzero(&newtio, sizeof(newtio));
 newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;
 newtio.c_iflag = IGNPAR | ICRNL;
 newtio.c_oflag = 0;
 newtio.c_lflag = 0;
 newtio.c_cc[VINTR]    = 0;  
 newtio.c_cc[VQUIT]    = 0;
 newtio.c_cc[VERASE]   = 0;
 newtio.c_cc[VKILL]    = 0;
 newtio.c_cc[VEOF]     = 4;
 newtio.c_cc[VTIME]    = 1;
 newtio.c_cc[VMIN]     = 1;
 newtio.c_cc[VSWTC]    = 0;
 newtio.c_cc[VSTART]   = 0;
 newtio.c_cc[VSTOP]    = 0;
 newtio.c_cc[VSUSP]    = 0;
 newtio.c_cc[VEOL]     = 0;
 newtio.c_cc[VREPRINT] = 0;
 newtio.c_cc[VDISCARD] = 0;
 newtio.c_cc[VWERASE]  = 0;
 newtio.c_cc[VLNEXT]   = 0;
 newtio.c_cc[VEOL2]    = 0;
 tcflush(fd, TCIFLUSH);
 while (STOP==FALSE)
      res = read(fd,buf,255);
       printf(":%s:%d\n", buf, res);
    if (buf[0]=='z') STOP=TRUE;
 return 0;

I begin running my program, I get a problem:
while I receive string "0123456789" from another PC(this PC use Terminal v19b with baudrate 19200, 8N1 to sent). sometimes, I received "01234567" on buffer instead of "0123456789". how to receive complete data from buffer (I dont' know length of data sent). pleas help me.
Question by:k6t
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 3
  • 2
  • 2
  • +4
LVL 53

Expert Comment

ID: 18842001
I assume that you just have to do another read, something like this :

      char *buf_ptr = buf
      while ((res = read(fd,buf_ptr,255)) > 0) {
        buf_ptr += res;
LVL 17

Assisted Solution

mokule earned 166 total points
ID: 18842293
Good practice is to use some even simplest frame for transmission.
For example start mark byte at the beggining and end mark byte at the end.
These marks should be chosen such that thay cannot occur in Your data.
Other possibility is to send byte count at the beggining.

Otherwise You never know if You received everything.
LVL 39

Assisted Solution

itsmeandnobodyelse earned 166 total points
ID: 18842375
>>>> I dont' know length of data sent
If you are responsible for sending and receiving, you might change sending so that they pass the length of the message first.

struct Message
    int lenMsg;
    char szMsg[1020];
    Message(const char* pszMsg)
       : lenMsg{strlen(pszMsg+1)) { strcpy(szMsg, pszMsg); }
     const char* buffer() { return (const char*)this; }
     int msglen() { return lenMsg + sizeof(int); }

     Message msg("12345678);
     send(fd, msg.buffer(), msg.msglen());

     int msglen = 0;
     int nread = 0;
     char* p =  (char*)&msglen;
     while ((nread += read(fd, p, sizeof(int) - nread)) < sizeof(int))
           p =  ((char*)&msglen) + nread;
     if (msglen > 0)
          char* pszMsg = new char[msglen];
          p = pszMsg;
          nread = 0;
          while ((nread += read(fd, p, msglen - nread)) < msglen)
               p = pszMsg + nread;

Of course you could implement the receiver's side by using struct Message as well. Then the read loops would be made by a member function of struct Message.

Regards, Alex

The Ultimate Checklist to Optimize Your Website

Websites are getting bigger and complicated by the day. Video, images, custom fonts are all great for showcasing your product/service. But the price to pay in terms of reduced page load times and ultimately, decreased sales, can lead to some difficult decisions about what to cut.

LVL 39

Expert Comment

ID: 18842380
>>>> Other possibility is to send byte count
Sorry I missed your comment or I would have made a reference.
LVL 86

Expert Comment

ID: 18843798
I'd suggest to take a look at for more information and code examples.

Author Comment

ID: 18848300
char *buf_ptr = buf
      while ((res = read(fd,buf_ptr,255)) > 0) {
        buf_ptr += res;

with your code, my program will block. because res > 0. then the while control no break.
LVL 53

Expert Comment

ID: 18848833
Well, it's a very crude solution, and has to be refined, but read() will return a value > 0 for as long as there is data to receive. If there is no data to be received, it will either return 0 or <0.

However, as mokule suggested, I would send the length of the data in some way, so the receiver knows how much he has t o receive.

Author Comment

ID: 18862732
thanks you. but, in my practical, I don't know length of data. In theorical read() function will return a value > 0 for as long as there is data to receive. If there is no data to be received, it will either return 0 or <0. if you don't set 0_NDELAY or same thing by  fcntl(fd, F_SETFL, FNDELAY) function, read() will block until look for data on buffer.
LVL 53

Accepted Solution

Infinity08 earned 168 total points
ID: 18863033
>> I don't know length of data

The sender knows how much data it's sending, and can give that information to the receiver ...

Expert Comment

ID: 19444424
Several things to recommend:

   bzero(&newtio, sizeof(newtio));
  memcpy (&newtio, &oldtio, sizeof(newtio));

This will copy serial port configuration to a new structure. Then you just change several parameters:

   newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;
   newtio.c_iflag = IGNPAR | IGNBRK;     // Ignore bad parity bytes and break chars
   newtio.c_oflag = 0;   // raw sending
   newtio.c_lflag = 0;    // no echo, noncanonical ...

And crucial thing:

   newtio.c_cc[VTIME] = 5;         // Timeout is 0.5s
   newtio.c_cc[VMIN]  = 0;         // Wait for a byte until timeout


   tcflush (fd, TCIOFLUSH);                                     // Clean the line
   tcsetattr (fd, TCSANOW, &newtio);              // Activate new port configuration

   memset (buf, 0, sizeof(buf));
   while (TRUE) {
      res = read (fd, buf, 255);
      if (res > 0) {
         buf[res] = 0;
         printf ("%s", buf);
         if (buf[0] == 'z')
      else {
         // You can do something or break from while loop

    tcflush (fd, TCIOFLUSH);                                  
    tcsetattr (fd, TCSANOW, &oldtio);
    close (fd);

I hope this will work.

Expert Comment

ID: 21466814
No comment has been added to this question in more than 21 days, so it is now classified as abandoned.

I will leave the following recommendation for this question in the Cleanup Zone:
      Split: mokule {http:#18842293} & itsmeandnobodyelse {http:#18842375} & Infinity08 {http:#18863033}

Any objections should be posted here in the next 4 days. After that time, the question will be closed.

EE Cleanup Volunteer
LVL 86

Expert Comment

ID: 21467538
I'd like to point out the pointer to also...

Expert Comment

ID: 21467602
It looks, from the code samples, as though the Asker pulled source code from that site (or one with very similar source) and edited it to suit his needs (the code he provided is almost exactly the same as some of the source code from the link you provided, with minor changes). I assumed he had done a little research first before asking this question, or at least did not want to do the research in the first place, and while I may be wrong, it looks as though he ignored your above comment.

That's just my personal opinion, but I'll alert the moderator who reviews this to take extra note of your comments.

EE Cleanup Volunteer

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Since upgrading to Office 2013 or higher installing the Smart Indenter addin will fail. This article will explain how to install it so it will work regardless of the Office version installed.
In this post we will learn how to connect and configure Android Device (Smartphone etc.) with Android Studio. After that we will run a simple Hello World Program.
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …
Introduction to Processes

691 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question