Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reading from serial port fails

I have the following C program:

#include <fcntl.h>
#include <termios.h>
#include <stdio.h>

int main()
{
    int fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NONBLOCK);
    if(fd < 0)
    {
        perror("Could not open device");
    }
    printf("Device opened\n");

    struct termios options;
    tcgetattr(fd, &options);
    cfmakeraw(&options);
    cfsetispeed(&options, B19200);
    cfsetospeed(&options, B19200);
    tcsetattr(fd, TCSANOW, &options);

    char txpacket[] = {0x23, 0x06, 0x00, 0x00, 0xdd, 0xf9};
    ssize_t written = write(fd, txpacket, sizeof(txpacket));
    printf("Written %d bytes\n", written);

    printf("Starting to wait for target to respond\n");
    while(1)
    {
        fd_set readset;
        FD_ZERO(&readset);
        FD_SET(fd, &readset);
        int nCount = select(fd + 1, &readset, NULL, NULL, NULL);
        if(nCount > 0)
        {
            if(FD_ISSET(fd, &readset))
            {
                int i;
                char buffer[128];
                ssize_t bytesread = read(fd, buffer, sizeof(buffer));
                printf("Received %d bytes\n", bytesread);
                for(i = 0; i < bytesread; i++)
                {
                    printf("  %02x", buffer[i]);
                }
            }
        }
    }
}

This program opens the serial device /dev/ttyS0, writes a sequence of data to it and starts listening for a response. I get the following output:

Device opened
Written 6 bytes
Starting to wait for target to respond
Received 0 bytes
Received 0 bytes
Received 0 bytes
Received 0 bytes
Received 0 bytes
Received 0 bytes
...

And the application consumes 100% CPU. I'm not able to receive any data, even though the target hardware actually transmits it.

What is wrong?

like image 424
anorm Avatar asked Nov 18 '09 09:11

anorm


People also ask

Can a serial port read and write at the same time?

Reading and writing to the serial port "at the same time" from different threads is a standard way to handle serial port communications: one thread handles reading, and one handles writing. Acceptable.

How do I check if a serial port is open?

To test if the computer COM port is functioning correctly, you can do a simple loopback test. (In a loopback test, a signal is sent from a device and returned, or looped back, to the device.) For this test, connect a serial cable to the COM port that you want to test. Then short pin 2 and pin 3 of the cable together.

What is serial port buffer?

The input buffer is computer memory allocated by the serial port object to store data that is to be read from the device. When reading data from your device, the data flow follows these two steps: The data read from the device is stored in the input buffer.


2 Answers

read() returning 0 indicates the end-of-file condition. You should check for that and break out of the loop if it occurs.

As to what's causing that - end-of-file on a serial port indicates it has detected a hangup, meaning that the DCD line has been dropped.

You can set the CLOCAL flag in options.c_cflag to ignore the modem control lines, if your device doesn't set them properly.

like image 121
caf Avatar answered Sep 21 '22 11:09

caf


You should try without the O_NONBLOCK flag. in raw mode, if the settings of c_cc[VMIN] and c_cc[VTIME] is 0, the serial port behave like this (according to man cfmakeraw) :

If data is available, read returns immediately, with the lesser of the number of bytes available, or the number of bytes requested. If no data is available, read returns 0

So what you should try is :

options->c_cc[VMIN]=1;
like image 22
shodanex Avatar answered Sep 19 '22 11:09

shodanex