I am trying to write to the serial port (sending a handshake) and then subsequently I try to read the serial port. When reading the port, I notice I am getting garbage reads (even if there is nothing connected to the RX line) or part of the write string I am sending to the TX line. Why am I getting part of that string? I am not supposed to be seeing that!
Here is my code:
class UART{
public:
UART();
~UART();
int open_port();
int configure_port(); // All port configurations such as parity, baud rate, hardware flow, etc
int uart_write(std::string); // Send characters to the serial port
int uart_read(std::string*, int); // Read from serial port
// Close
void close_port();
private:
int fd;
uart.cpp:
UART::UART(){
open_port();
configure_port();
}
UART::~UART(){
close_port();
}
int UART::open_port()
{
// Open ttys4
fd = open("/dev/ttyS4", O_RDWR | O_NOCTTY | O_NDELAY);
if(fd == -1) // if open is unsucessful
{
//perror("open_port: Unable to open /dev/ttyS0 - ");
printf("open_port: Unable to open /dev/ttyS4. \n");
}
else
{
fcntl(fd, F_SETFL, 0);
printf("port is open.\n");
}
return(fd);
} //open_port
// configure the port
int UART::configure_port()
{
struct termios port_settings; // structure to store the port settings in
cfsetispeed(&port_settings, B9600); // set baud rates
cfsetospeed(&port_settings, B9600);
port_settings.c_cflag &= ~PARENB; // set no parity, stop bits, data bits
port_settings.c_cflag &= ~CSTOPB;
port_settings.c_cflag &= ~CSIZE;
port_settings.c_cflag |= CS8;
port_settings.c_cflag |= CREAD | CLOCAL; // turn on READ & ignore ctrl lines
port_settings.c_cc[VTIME] = 10; // n seconds read timeout
port_settings.c_iflag &= ~(IXON | IXOFF | IXANY); // turn off s/w flow ctrl
port_settings.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); // make raw
port_settings.c_oflag &= ~OPOST; // make raw
tcsetattr(fd, TCSANOW, &port_settings); // apply the settings to the port
return(fd);
}
// Write to serial port
int UART::uart_write(string data)
{
int buffer_size = data.length();
char * data_write = new char[data.length()+1];
strcpy (data_write, data.c_str());
int n = write(fd, data_write, buffer_size); //Send data
usleep(1000);
tcdrain(fd);
printf("Wrote the bytes. \n");
/* Error Handling */
int status = 0;
if (n < 0)
{
cout << "Error Writing: " << strerror(errno) << endl;
status = 0;
}else{
status = 1;
}
delete[] data_write;
return status;
}
int UART::uart_read(string *data,int buffer_size)
{
// Buffer
char * buf = new char[buffer_size+1];
usleep(1000);
tcflush(fd, TCIOFLUSH);
// Read
/*I NEED THIS PART TO BE BLOCKING*/
int n = read( fd, buf , buffer_size );
/* Error Handling */
if (n < 0)
{
cout << "Error reading: " << strerror(errno) << endl;
}
// String received
string data_received(buf,buffer_size);
*data = data_received;
delete[] buf;
cout << "data_received: " << *data << endl;
// Did we get blank data?
if( data_received.length() == 0 )
return 0;
else
return 1;
}
main
int main()
{
UART uart_connection;
string handshake = "handshake!";
uart_connection.uart_write(handshake);
string data;
string *data_ptr = &data;
uart_connection.uart_read(data_ptr );
cout << data << endl;
}
When printing the received data, I usually get part of the sent data. So on cout << data << endl I am getting the following:
dshake
along with some weird characters after it, or if I don't write anything to the serial port then I just get random characters.
Specifically I want int n = read( fd, buf , buffer_size ); to be a blocking function, which apparently it's not happening... It just goes through and it returns a bunch of weird characters or it reads part of the string sent with write.
Please note that the code works and when I do actually send something to the RX line, I can read it just fine. However, I am finding it difficult to send large chunks of data without getting bad reads.
I believe this could all be solved if I could make the read() function a blocking function, and avoid it reading those weird characters.