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?
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.
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.
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.
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.
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;
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With