I need to communicate over my serial Port. I have written a c code to open the devices for tx & rx and configure the settings, write and read the data. First time when I execute the code, I'm able to read and write data. But when I try it second time, I'm unable to receive or transmit data. Can sometime help me to know what the reason for that will be. I have closed the files that are opened.
#include<stdio.h>
#include<fcntl.h>
#include<termios.h>
#include<unistd.h>
#include<string.h>
#define buff_size 256
int main()
{
int tx_fd,rx_fd;
struct termios option1,option2;
int byte_write,byte_read;
char buffer[buff_size];
printf("test\n");
tx_fd = open("/dev/ttyUSB2",O_RDWR);
printf("tx port is opened\n");
if(tx_fd < 0)
{
perror("error opening transmitter uart port");
return 1;
}
rx_fd = open("/dev/ttyUSB0",O_RDWR);
printf("rx port opened\n");
if(rx_fd < 0)
{
perror("error opening receiver uart port");
close(tx_fd);
return 1;
}
//configuration setting
////baud rate oof input and output is set to 9600;
cfsetospeed(&option2,B9600);
cfsetispeed(&option1,B9600);
////
option1.c_cflag = CS8;
option2.c_cflag = CS8;
option1.c_cflag &= ~PARENB;
option2.c_cflag &= ~PARENB;
option1.c_cflag &= ~CSTOPB;
tcflush(tx_fd,TCIFLUSH);
tcflush(rx_fd,TCOFLUSH);
// Apply receiver (RX) settings
if (tcsetattr(rx_fd, TCSANOW, &option2) < 0) {
perror("Error setting receiver attributes");
close(tx_fd);
close(rx_fd);
return 1; // Handle the error and exit
}
tcsetattr(tx_fd,TCSANOW,&option1);
tcsetattr(rx_fd,TCSANOW,&option2);
char data[] = "hello! \n";
byte_write = write(tx_fd,data,sizeof(data));
printf("write %d bytes to receiver\n",byte_write);
if(byte_write < 0)
{
perror("Error in writing data\n");
close(tx_fd);
close(rx_fd);
return 1;
}
usleep(10000);
byte_read = read(rx_fd,buffer,sizeof(buffer));
if(byte_read < 0)
{
perror("error in reading data\n");
close(tx_fd);
close(rx_fd);
return 1;
}
buffer[byte_read] = '\0';
printf("read %d bytes from transmitter\n",byte_read);
printf("Received: %s \n",buffer);
if( close(rx_fd) < 0)
{ perror("there is a error in closing rx");
}
if( close(tx_fd) < 0)
{
perror("there is a error in closing tx");
}
return 0;
}
this is the code that I have tried. I found that I'm having an issue with a particular serial port to open the file while executing for the second time. But still can't understand what the issue is. The code stands in a place where it can't be open, but the error message is also not executed.
If the
open()call is blocked when the executable is run the second time, it is probably because theCLOCALflag was cleared in thestruct termiosc_cflagmember when the executable was run the first time. That causes a blockingopen()call to wait for the Carrier Detect (a.k.a. CD, Data Carrier Detect, DCD) signal to be asserted on the serial line.open()can be called in nonblocking mode by setting theO_NONBLOCKflag in the second parameter. That will makeopen()return immediately without waiting for the CD signal, allowing you to change the termios settings. However, the read and write operations will also be in nonblocking mode. To restore blocking mode, you can use thefcntl()F_SETFLcommand to clear theO_NONBLOCKflag after opening:The nonblocking open with blocking restored after the open could be factored out into a function that can also be used to open the other TTY:
That could be called like this:
You should also either fully initialize the
struct termiosobjects passed totcsetattr(), or usetcgetattr()to read the existing settings into thestruct termiosobjects before modifying the settings. Your current code only initializes thec_cflagmembers ofoption1andoption2. The other members contain indeterminate values, which will either cause thetcsetattr()calls to return an error, or indeterminate termios settings to be applied to the TTY, or some other undefined behavior to occur.