Reputation: 34568
I want to use RS232 port on the board to communicate with a PC. I understand that I can use "dev/ttyS0" for that purpose.
I can open and write data to PC by using write() function. But the problem is I can't read from "dev/ttyS0". Every time I use read function, I get "Resource temporarily unavailable". Can u guys tell me how to solve this problem?
Here is my code:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
int main()
{
int n = 0, fd = 0, bytes = 0;
char ch = 0;
char buffer[10], *bufPtr;
int nBytes = 0, tries = 0, x = 0;
struct termios term;
fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY | O_NDELAY);
if (fd == -1)
{
perror("open");
return;
}
else
{
fcntl(fd, F_SETFL, 0);
perror("Port");
}
if (n = tcgetattr(fd, &term) == -1)
{
perror("tcgetattr");
return;
}
if (n = cfsetispeed(&term, B115200) == -1)
{
perror("cfsetispeed");
return;
}
if (n = cfsetospeed(&term, B115200) == -1)
{
perror("cfsetospeed");
return;
}
term.c_cflag |= (CLOCAL | CREAD);
term.c_cflag &= ~PARENB;
term.c_cflag &= ~CSTOPB;
term.c_cflag &= ~CSIZE;
term.c_cflag |= CS8;
term.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
term.c_iflag &= ~(IXON | IXOFF | IXANY);
term.c_cflag &= ~CRTSCTS;
term.c_oflag &= ~OPOST;
if (n = tcsetattr(fd, TCSANOW, &term) == -1)
{
perror("tcsetattr");
return;
}
write(fd,"LINUX",5);
perror("write");
fcntl(fd, F_SETFL, FNDELAY);
perror("fcntl");
bytes = read(fd, buffer, sizeof(buffer));
perror("read");
printf("Bytes : %d and data: %s\n", bytes, buffer);
}
Upvotes: 0
Views: 1255
Reputation: 16213
What is your test? Are you shortcutting pin 2 and 3 of your RS232 DB9 connector?
Otherwise read
will always return -1 if there are no data to be read.
This is what your code is supposed to do using O_NDELAY
flag opening the serial line.
To avoid to read if there are no data to be read, you could use select In your case:
struct timeval tv;
fd_set rset;
int retV;
int timeout = 5000; // 5 seconds
tv.tv_usec = (timeout * 1000) % 1000000;
tv.tv_sec = timeout / 1000;
FD_ZERO ( &rset );
FD_SET ( fd, &rset );
retV = select ( fd+1, &rset, NULL, NULL, &tv );
if( retV == 0 )
{
// timeout stuff
}
else if( retV < 0 )
{
// Error stuff. Read errno to see what happened
}
else
{
// read data
}
EDIT
Remove fcntl(fd, F_SETFL, FNDELAY);
If you want a normal blocking read, unset that flag.
In your code you are also assuming that read
will return all sent chars but is not true. read
will return chars that are available to be read. This means that if you send "LINUX" a 5 times read could be requested to read all 5 chars sent.
Last thing
printf("Bytes : %d and data: %s\n", bytes, buffer);
is Undefined Behavior because of buffer
is not a NULL
terminated string. You could solve it looping on received chars and print it with %c format, or NULL
terminating your buffer with:
if (bytes > 0)
buffer[bytes] = '\0';
or
char stringToSend[] = "LINUX";
size_t len = strlen(stringToSend) +1 ;
write(fd,"LINUX", len);
perror("write");
size_t receivedBytes = 0;
bytes = 0;
while (receivedBytes<len)
{
bytes = read(fd, &buffer[receivedBytes], sizeof(buffer)-1);
perror("read");
if (bytes > 0)
receivedBytes += bytes;
}
printf("Bytes : %d and data: %s\n", receivedBytes, buffer);
Upvotes: 3