Question

I'm receiving data from device using serial port. The communication works fine, but there is a problem with reading data. I'm working on Linux (Ubuntu).

Here's my code:

int OpenPort(char *PortName, int *FileDesc) {
    *FileDesc = open (PortName, O_RDWR | O_NOCTTY | O_SYNC);
    if (fd < 0) {
            perror("fakap");
            return (P_OPEN_ERROR);
    }
    else return(P_OPEN_SUCCESS);

};

int SetPortAtributes (int fd, int speed, int parity) {
        struct termios tty;
        memset (&tty, 0, sizeof tty);
        if (tcgetattr (fd, &tty) != 0)
        {
                perror("error %d from tcgetattr");
                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 | IGNPAR);,

        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_iflag &= ~(ISTRIP);
        tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
                                        // enable reading
        tty.c_cflag &= ~(PARENB | PARODD | HUPCL);      // shut off parity
        tty.c_cflag |= parity;
        tty.c_cflag &= ~CSTOPB;
        tty.c_cflag &= ~CRTSCTS;
        tty.c_lflag = 0;
        if (tcsetattr (fd, TCSANOW, &tty) != 0)
        {
                perror("error %d from tcsetattr");
                return -1;
        }
        return 0;
}

Read section:

void PortRead(int *FileDesc) {

    memset(&recBuff[0], 0, sizeof(recBuff)); //clear buff

    int n = read (*FileDesc, recBuff, sizeof(recBuff));  // read
    printf("n: %d \n", n);
    int i = 0;
    for(i = 0;i<n;i++) {
        recData.buf[i].b_int = recBuff[i]; // put rec buff to ANS_u type variable
    }
};

Everything works fine until I receive message larger then 8 bytes. read() doesn't read more than 8 bytes so I have to use read() second time to read to read all data. Everything works fine when I'm using GtkTerm but, there's a problem during C implementation.

Was it helpful?

Solution 3

It may happen for example because fewer bytes are actually available right now (maybe because we were close to end-of-file, or because we are reading from a pipe, or from a terminal), or because read() was interrupted by a signal.

Repeat the read for as long as it has data available.

Also, since the other end is a microcontroller which might be slower than your workstation by a large margin, perhaps the data simply isn't available yet when you do the read(). That's another reason to try again, of course.

So looks like you can try

int n = 0, offset = 0, bytes_expected = 40;
do 
{
    n = read (*FileDesc, recBuff+offset, sizeof(recBuff));
    offset += num;

} while (offset < bytes_expected);

OTHER TIPS

so I have to use read() second time to read to read all data.

You must be prepared to call read() a second, third, fourth, etc time in any case. Always. Just because you know that the other side has sent say 16 bytes, you cannot assume that all 16 bytes will come out of read() in one operation. It might come as 8+8, 16*1, 3+3+10, or any other combination summing up to 16 (although most of those combinations are extremely unlikely).

From the manual page on read(2):

RETURN VALUE

On success, the number of bytes read is returned ... It is not an error if this number is smaller than the number of bytes requested


You should also be prepared to handle EINTR like already commented.


In function OpenPort the result from open is assigned to *FileDesc but some other fd variable is checked, that should be fixed as well.

I'm not sure, but it looks like the 'recBuff' is a pointer to the intput buffer.

int n = read (*FileDesc, recBuff, sizeof(recBuff));  // read

If this is true, then sizeof(recBuff) equal to 8. (The pointer size is 8). It is understandable that a maximum 8 bytes are willing to read.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top