Link to home
Start Free TrialLog in
Avatar of k6t
k6t

asked on

serisal programming in linux

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];
 fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY );
 if (fd <0) {perror(MODEMDEVICE); exit(-1); }
 tcgetattr(fd,&oldtio);
 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);
 tcsetattr(fd,TCSANOW,&newtio);
 while (STOP==FALSE)
 {
      res = read(fd,buf,255);
      buf[res]='\0';         
       printf(":%s:%d\n", buf, res);
    if (buf[0]=='z') STOP=TRUE;
 }
 tcsetattr(fd,TCSANOW,&oldtio);
 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.
Avatar of Infinity08
Infinity08
Flag of Belgium image

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;
      }
      *buf_ptr='\0';
SOLUTION
Avatar of mokule
mokule
Flag of Poland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
>>>> Other possibility is to send byte count
Sorry I missed your comment or I would have made a reference.
I'd suggest to take a look at http://www.tldp.org/HOWTO/Serial-Programming-HOWTO/ for more information and code examples.
Avatar of k6t
k6t

ASKER

char *buf_ptr = buf
      while ((res = read(fd,buf_ptr,255)) > 0) {
        buf_ptr += res;
      }
      *buf_ptr='\0';

with your code, my program will block. because res > 0. then the while control no break.
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.
Avatar of k6t

ASKER

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.
ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Several things to recommend:

Replace
   bzero(&newtio, sizeof(newtio));
with
  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

Then:

   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')
            break;
      }
      else {
         // You can do something or break from while loop
     }
   }

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


I hope this will work.
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.

Sean
EE Cleanup Volunteer
I'd like to point out the pointer to http://www.tldp.org/HOWTO/Serial-Programming-HOWTO/ also...
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.

Sean
EE Cleanup Volunteer