I am working on a project in which I need to read and write data from a serial port, and this should be non-blocking for reasons that I will not go into. The select () function is similar to what I want to use, but I'm struggling with getting a working implementation.
In open_port (), I define the settings for the port and that it does not block. In otherselect (), I assign an open_port () handle and try to read. I also have a 1 second sleep call at the end of the function to try to avoid reading too fast for the hardware.
When I start, I get a message that prints every second, for the "lack of data" before sending the message, and after sending the message it displays it, but usually it consists of pieces with binary characters along with it. For example, when sending the word βbufferβ, it will print βfferβ followed by a binary character.
I have almost no experience with termios or select, so any suggestions would be appreciated.
#include <iostream> #include "stdio.h" #include "termios.h" #include "errno.h" #include "fcntl.h" #include "string.h" #include "time.h" #include "sys/select.h" using namespace std; int open_port(){ struct termios oldtio,newtio; int serial_fd; if ((serial_fd = open("/dev/ttyS0", O_RDWR | O_EXCL | O_NDELAY)) == -1) { cout << "unable to open" << endl; return -1; } if (tcgetattr(serial_fd, &oldtio) == -1) { cout << "tcgetattr failed" << endl; return -1; } cfmakeraw(&newtio); // Clean all settings newtio.c_cflag = (newtio.c_cflag & ~CSIZE) | CS8 | B115200; // 8 databits newtio.c_cflag |= (CLOCAL | CREAD); newtio.c_cflag &= ~(PARENB | PARODD); // No parity newtio.c_cflag &= ~CRTSCTS; // No hardware handshake newtio.c_cflag &= ~CSTOPB; // 1 stopbit newtio.c_iflag = IGNBRK; newtio.c_iflag &= ~(IXON | IXOFF | IXANY); // No software handshake newtio.c_lflag = 0; newtio.c_oflag = 0; newtio.c_cc[VTIME] = 1; newtio.c_cc[VMIN] = 60; if (tcsetattr(serial_fd, TCSANOW, &newtio) == -1) { cout << "tcsetattr failed" << endl; return -1; } tcflush(serial_fd, TCIOFLUSH); // Clear IO buffer return serial_fd; } void otherselect(){ fd_set readfs; timeval tv; tv.tv_sec = 1; tv.tv_usec = 0; char * buffer = new char[15]; int _fd = open_port(); FD_ZERO(&readfs); FD_SET(_fd, &readfs); select(_fd+1, &readfs, NULL, NULL, &tv /* no timeout */); if (FD_ISSET(_fd, &readfs)) { int r = read(_fd, buffer, 15); if(r == -1){ cout << strerror(errno) << endl; } cout << buffer << endl; } else{ cout << "data not available" << endl; } close(_fd); sleep(1); } int main() { while(1){ otherselect(); } }
c ++ linux select serial-port
Kevin corder
source share