Clean up serial_port class and add MacOS support (only standard baud rates for now)
This commit is contained in:
parent
f1107fc2a5
commit
126b1b4841
2 changed files with 232 additions and 130 deletions
|
|
@ -9,43 +9,54 @@
|
|||
|
||||
#include "serial_port.h"
|
||||
|
||||
//serial_port (constructor)
|
||||
// The default constructor does not initialize the serial port
|
||||
/*---------------------------------------------------------*\
|
||||
| serial_port (constructor) |
|
||||
| The default constructor does not initialize the serial |
|
||||
| port |
|
||||
\*---------------------------------------------------------*/
|
||||
serial_port::serial_port()
|
||||
{
|
||||
//Set a default baud rate
|
||||
/*-----------------------------------------------------*\
|
||||
| Set a default baud rate |
|
||||
\*-----------------------------------------------------*/
|
||||
baud_rate = 9600;
|
||||
}
|
||||
|
||||
//serial_port (constructor)
|
||||
// When created with port information, the constructor
|
||||
// will automatically open port <name> at baud rate <baud>
|
||||
/*---------------------------------------------------------*\
|
||||
| serial_port (constructor) |
|
||||
| When created with port information, the constructor |
|
||||
| will automatically open port <name> at baud rate <baud>|
|
||||
\*---------------------------------------------------------*/
|
||||
serial_port::serial_port(const char * name, unsigned int baud)
|
||||
{
|
||||
serial_open(name, baud);
|
||||
}
|
||||
|
||||
//~serial_port (destructor)
|
||||
// Closes the port before destroying the object
|
||||
/*---------------------------------------------------------*\
|
||||
| ~serial_port (destructor) |
|
||||
| Closes the port before destroying the object |
|
||||
\*---------------------------------------------------------*/
|
||||
serial_port::~serial_port()
|
||||
{
|
||||
serial_close();
|
||||
}
|
||||
|
||||
//open
|
||||
// Opens the serial port using stored information
|
||||
// Sets the baud rate to the stored baud rate
|
||||
// 8 data bits, no parity, one stop bit
|
||||
/*---------------------------------------------------------*\
|
||||
| serial_open |
|
||||
| Opens the serial port using stored information |
|
||||
| Sets the baud rate to the stored baud rate |
|
||||
| 8 data bits, no parity, one stop bit |
|
||||
\*---------------------------------------------------------*/
|
||||
bool serial_port::serial_open()
|
||||
{
|
||||
// printf("SerialPort: Opening serial port %s at baud rate %d.\n", port_name, baud_rate);
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Windows-specific code path for serial port opening |
|
||||
\*-----------------------------------------------------*/
|
||||
#ifdef _WIN32
|
||||
file_descriptor = CreateFile(port_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
|
||||
if((int)file_descriptor < 0)
|
||||
{
|
||||
// printf("SerialPort: Port %s could not be opened: %d.\n", port_name, file_descriptor);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -73,16 +84,16 @@ bool serial_port::serial_open()
|
|||
timeouts.WriteTotalTimeoutConstant=50;
|
||||
timeouts.WriteTotalTimeoutMultiplier=10;
|
||||
SetCommTimeouts(file_descriptor, &timeouts);
|
||||
#endif
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Linux-specific code path for serial port opening |
|
||||
\*-----------------------------------------------------*/
|
||||
#ifdef __linux__
|
||||
|
||||
file_descriptor = open(port_name, O_RDWR | O_NOCTTY | O_NDELAY);
|
||||
|
||||
if(file_descriptor < 0)
|
||||
{
|
||||
// printf("SerialPort: Port %s could not be opened: %d.\n", port_name, file_descriptor);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -91,55 +102,97 @@ bool serial_port::serial_open()
|
|||
options.c_cflag &= ~CBAUD;
|
||||
options.c_cflag |= BOTHER;
|
||||
options.c_lflag &= ~ICANON;
|
||||
options.c_lflag &= ~ECHO; // Disable echo
|
||||
options.c_lflag &= ~ECHOE; // Disable erasure
|
||||
options.c_lflag &= ~ECHONL; // Disable new-line echo
|
||||
options.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP
|
||||
options.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
|
||||
options.c_lflag &= ~ECHO; // Disable echo
|
||||
options.c_lflag &= ~ECHOE; // Disable erasure
|
||||
options.c_lflag &= ~ECHONL; // Disable new-line echo
|
||||
options.c_lflag &= ~ISIG; // Disable interpretation of INTR, QUIT and SUSP
|
||||
options.c_iflag &= ~(IXON | IXOFF | IXANY); // Turn off s/w flow ctrl
|
||||
options.c_ispeed = baud_rate;
|
||||
options.c_ospeed = baud_rate;
|
||||
options.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); // Disable any special handling of received bytes
|
||||
options.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL); // Disable any special handling of received bytes
|
||||
ioctl(file_descriptor, TCSETS2, &options);
|
||||
#endif
|
||||
|
||||
//serial_struct ss;
|
||||
//int closestSpeed;
|
||||
//ioctl(file_descriptor, TIOCGSERIAL, &ss);
|
||||
//ss.flags = (ss.flags & ~ASYNC_SPD_MASK) | ASYNC_SPD_CUST | ASYNCB_LOW_LATENCY;
|
||||
//ss.custom_divisor = (ss.baud_base + (baud_rate / 2)) / baud_rate;
|
||||
//if(ss.custom_divisor == 0)
|
||||
//{
|
||||
// closestSpeed = baud_rate;
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// closestSpeed = ss.baud_base / ss.custom_divisor;
|
||||
//}
|
||||
/*-----------------------------------------------------*\
|
||||
| MacOS-specific code path for serial port opening |
|
||||
\*-----------------------------------------------------*/
|
||||
#ifdef __APPLE__
|
||||
file_descriptor = open(port_name, O_RDWR | O_NOCTTY | O_NDELAY);
|
||||
|
||||
//if((float)closestSpeed < ((float)baud_rate * (98.0f/100.0f)) || (float)closestSpeed > ((float)baud_rate * (102.0f/100.0f)))
|
||||
//{
|
||||
// printf("SerialPort: Cannot set %s to %d. Closest possible speed is %d.\n", port_name, baud_rate, closestSpeed);
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// printf("SerialPort: %s speed set to %d.\n", port_name, baud_rate);
|
||||
//}
|
||||
if(file_descriptor < 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
//fcntl(file_descriptor, F_SETFL, 0);
|
||||
#endif /* __linux__ */
|
||||
struct termios options;
|
||||
tcgetattr(file_descriptor, &options);
|
||||
switch(baud_rate)
|
||||
{
|
||||
case 9600:
|
||||
cfsetispeed(&options, B9600);
|
||||
cfsetospeed(&options, B9600);
|
||||
break;
|
||||
case 19200:
|
||||
cfsetispeed(&options, B19200);
|
||||
cfsetospeed(&options, B19200);
|
||||
break;
|
||||
case 115200:
|
||||
cfsetispeed(&options, B115200);
|
||||
cfsetospeed(&options, B115200);
|
||||
break;
|
||||
case 38400:
|
||||
cfsetispeed(&options, B38400);
|
||||
cfsetospeed(&options, B38400);
|
||||
break;
|
||||
case 57600:
|
||||
cfsetispeed(&options, B57600);
|
||||
cfsetospeed(&options, B57600);
|
||||
break;
|
||||
default:
|
||||
cfsetispeed(&options, B9600);
|
||||
cfsetospeed(&options, B9600);
|
||||
break;
|
||||
}
|
||||
|
||||
// printf("SerialPort: Serial port %s opened successfully.\n", port_name);
|
||||
/*-----------------------------------------------------*\
|
||||
| Configure other settings |
|
||||
\*-----------------------------------------------------*/
|
||||
options.c_iflag &= ~(INLCR | ICRNL);
|
||||
options.c_iflag |= IGNPAR | IGNBRK;
|
||||
options.c_oflag &= ~(OPOST | ONLCR | OCRNL);
|
||||
options.c_cflag &= ~(PARENB | PARODD | CSTOPB | CSIZE | CRTSCTS);
|
||||
options.c_cflag |= CLOCAL | CREAD | CS8;
|
||||
options.c_lflag &= ~(ICANON | ISIG | ECHO);
|
||||
options.c_cc[VTIME] = 1;
|
||||
options.c_cc[VMIN] = 0;
|
||||
|
||||
if(tcsetattr(file_descriptor, TCSANOW, &options) < 0)
|
||||
{
|
||||
close(file_descriptor);
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Return true if successful |
|
||||
\*-----------------------------------------------------*/
|
||||
return true;
|
||||
}
|
||||
|
||||
//open
|
||||
// Opens the serial port <name> without changing stored baud rate
|
||||
/*---------------------------------------------------------*\
|
||||
| serial_open |
|
||||
| Opens the serial port <name> without changing stored |
|
||||
| baud rate |
|
||||
\*---------------------------------------------------------*/
|
||||
bool serial_port::serial_open(const char * name)
|
||||
{
|
||||
return serial_open(name, baud_rate);
|
||||
}
|
||||
|
||||
//open
|
||||
// Opens the serial port <name> at baud rate <baud>
|
||||
/*---------------------------------------------------------*\
|
||||
| serial_open |
|
||||
| Opens the serial port <name> at baud rate <baud> |
|
||||
\*---------------------------------------------------------*/
|
||||
bool serial_port::serial_open(const char* name, unsigned int baud)
|
||||
{
|
||||
strcpy(port_name, name);
|
||||
|
|
@ -147,106 +200,155 @@ bool serial_port::serial_open(const char* name, unsigned int baud)
|
|||
return serial_open();
|
||||
}
|
||||
|
||||
//close
|
||||
// Closes the serial port
|
||||
/*---------------------------------------------------------*\
|
||||
| serial_close |
|
||||
| Closes the serial port |
|
||||
\*---------------------------------------------------------*/
|
||||
void serial_port::serial_close()
|
||||
{
|
||||
// printf("SerialPort: Closing port %s.\n", port_name);
|
||||
/*-----------------------------------------------------*\
|
||||
| Windows-specific code path for serial close |
|
||||
\*-----------------------------------------------------*/
|
||||
#ifdef _WIN32
|
||||
|
||||
#endif /* _WIN32 */
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Linux-specific code path for serial close |
|
||||
\*-----------------------------------------------------*/
|
||||
#ifdef __linux__
|
||||
|
||||
close(file_descriptor);
|
||||
#endif
|
||||
|
||||
#endif /* __linux__ */
|
||||
/*-----------------------------------------------------*\
|
||||
| MacOS-specific code path for serial close |
|
||||
\*-----------------------------------------------------*/
|
||||
#ifdef __APPLE__
|
||||
close(file_descriptor);
|
||||
#endif
|
||||
}
|
||||
|
||||
// read
|
||||
// Reads <length> bytes from the serial port into <buffer>
|
||||
// Returns the number of bytes actually read
|
||||
// If less than <length> bytes are available, it will read all
|
||||
// available bytes
|
||||
/*---------------------------------------------------------*\
|
||||
| serial_read |
|
||||
| Reads <length> bytes from the serial port into <buffer>|
|
||||
| Returns the number of bytes actually read |
|
||||
| If less than <length> bytes are available, it will read|
|
||||
| all available bytes |
|
||||
\*---------------------------------------------------------*/
|
||||
int serial_port::serial_read(char * buffer, int length)
|
||||
{
|
||||
/*-----------------------------------------------------*\
|
||||
| Windows-specific code path for serial read |
|
||||
\*-----------------------------------------------------*/
|
||||
#ifdef _WIN32
|
||||
|
||||
DWORD bytesread;
|
||||
ReadFile(file_descriptor, buffer, length, &bytesread, NULL);
|
||||
return bytesread;
|
||||
#endif
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Linux-specific code path for serial read |
|
||||
\*-----------------------------------------------------*/
|
||||
#ifdef __linux__
|
||||
|
||||
int bytesread;
|
||||
bytesread = read(file_descriptor, buffer, length);
|
||||
return bytesread;
|
||||
#endif
|
||||
|
||||
#endif /* __linux__ */
|
||||
/*-----------------------------------------------------*\
|
||||
| MacOS-specific code path for serial read |
|
||||
\*-----------------------------------------------------*/
|
||||
#ifdef __APPLE__
|
||||
int bytesread;
|
||||
bytesread = read(file_descriptor, buffer, length);
|
||||
return bytesread;
|
||||
#endif
|
||||
|
||||
//printf("SerialPort: Read %d bytes on port %s.\n", bytesread, port_name);
|
||||
/*-----------------------------------------------------*\
|
||||
| Return 0 on unsupported platforms |
|
||||
\*-----------------------------------------------------*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
//write
|
||||
// Writes <length> bytes to the serial port from <buffer>
|
||||
// Returns the number of bytes actually written
|
||||
// Does not check for null-termination, so if <length> is
|
||||
// greater than the number of bytes in <buffer>, it will read
|
||||
// past <buffer> and may cause a segfault
|
||||
/*---------------------------------------------------------*\
|
||||
| serial_write |
|
||||
| Writes <length> bytes to the serial port from <buffer> |
|
||||
| Returns the number of bytes actually written |
|
||||
| Does not check for null-termination, so if <length> is |
|
||||
| greater than the number of bytes in <buffer>, it will |
|
||||
| read past <buffer> and may cause a segfault |
|
||||
\*---------------------------------------------------------*/
|
||||
int serial_port::serial_write(char * buffer, int length)
|
||||
{
|
||||
/*-----------------------------------------------------*\
|
||||
| Windows-specific code path for serial write |
|
||||
\*-----------------------------------------------------*/
|
||||
#ifdef _WIN32
|
||||
|
||||
DWORD byteswritten;
|
||||
WriteFile(file_descriptor, buffer, length, &byteswritten, NULL);
|
||||
return byteswritten;
|
||||
#endif
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
/*-----------------------------------------------------*\
|
||||
| Linux-specific code path for serial write |
|
||||
\*-----------------------------------------------------*/
|
||||
#ifdef __linux__
|
||||
|
||||
int byteswritten;
|
||||
tcdrain(file_descriptor);
|
||||
byteswritten = write(file_descriptor, buffer, length);
|
||||
tcdrain(file_descriptor);
|
||||
return byteswritten;
|
||||
#endif
|
||||
|
||||
#endif /* __linux__ */
|
||||
/*-----------------------------------------------------*\
|
||||
| MacOS-specific code path for serial write |
|
||||
\*-----------------------------------------------------*/
|
||||
#ifdef __APPLE__
|
||||
int byteswritten;
|
||||
tcdrain(file_descriptor);
|
||||
byteswritten = write(file_descriptor, buffer, length);
|
||||
tcdrain(file_descriptor);
|
||||
return byteswritten;
|
||||
#endif
|
||||
|
||||
//printf("SerialPort: Wrote %d bytes on port %s.\n", byteswritten, port_name);
|
||||
/*-----------------------------------------------------*\
|
||||
| Return 0 on unsupported platforms |
|
||||
\*-----------------------------------------------------*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
//flush
|
||||
/*---------------------------------------------------------*\
|
||||
| serial_flush |
|
||||
\*---------------------------------------------------------*/
|
||||
void serial_port::serial_flush_rx()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
PurgeComm(file_descriptor, PURGE_RXABORT | PURGE_RXCLEAR);
|
||||
|
||||
#endif /* _WIN32 */
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
tcflush(file_descriptor, TCIFLUSH);
|
||||
#endif
|
||||
|
||||
#endif /* __linux__ */
|
||||
#ifdef __APPLE__
|
||||
tcflush(file_descriptor, TCIFLUSH);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*\
|
||||
| serial_flush_tx |
|
||||
\*---------------------------------------------------------*/
|
||||
void serial_port::serial_flush_tx()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
|
||||
PurgeComm(file_descriptor, PURGE_TXABORT | PURGE_TXCLEAR);
|
||||
|
||||
#endif /* _WIN32 */
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
tcflush(file_descriptor, TCOFLUSH);
|
||||
#endif
|
||||
|
||||
#endif /* __linux__ */
|
||||
#ifdef __APPLE__
|
||||
tcflush(file_descriptor, TCOFLUSH);
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,57 +49,57 @@
|
|||
|
||||
#endif /* __linux__ */
|
||||
|
||||
#ifdef __APPLE__
|
||||
|
||||
//Serial Port Class
|
||||
//The reason for this class is that serial ports are treated differently
|
||||
//on Windows and Linux. By creating a class, those differences can be
|
||||
//made invisible to the program and make cross-platform usage easy
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
/*-------------------------------------------------------------------------*\
|
||||
| Serial Port Class |
|
||||
| The reason for this class is that serial ports are treated differently |
|
||||
| on Windows and Linux. By creating a class, those differences can be |
|
||||
| made invisible to the program and make cross-platform usage easy |
|
||||
\*-------------------------------------------------------------------------*/
|
||||
class serial_port
|
||||
{
|
||||
public:
|
||||
serial_port();
|
||||
serial_port(const char * name, unsigned int baud);
|
||||
public:
|
||||
serial_port();
|
||||
serial_port(const char * name, unsigned int baud);
|
||||
|
||||
~serial_port();
|
||||
~serial_port();
|
||||
|
||||
//Function to open the port
|
||||
bool serial_open();
|
||||
bool serial_open(const char* name);
|
||||
bool serial_open(const char* name, unsigned int baud);
|
||||
bool serial_open();
|
||||
bool serial_open(const char* name);
|
||||
bool serial_open(const char* name, unsigned int baud);
|
||||
|
||||
//Function to close the port
|
||||
void serial_close();
|
||||
void serial_close();
|
||||
|
||||
//Functions for controlling baud rate
|
||||
void serial_set_baud(unsigned int baud);
|
||||
int serial_get_baud();
|
||||
void serial_set_baud(unsigned int baud);
|
||||
int serial_get_baud();
|
||||
|
||||
//Function to read data from the port buffer
|
||||
int serial_read(char * buffer, int length);
|
||||
int serial_read(char * buffer, int length);
|
||||
|
||||
//Function to write data to the serial port
|
||||
int serial_write(char * buffer, int length);
|
||||
int serial_write(char * buffer, int length);
|
||||
|
||||
//Functions to flush the serial port rx and tx buffers
|
||||
void serial_flush_rx();
|
||||
void serial_flush_tx();
|
||||
void serial_flush_rx();
|
||||
void serial_flush_tx();
|
||||
|
||||
//Function to list the number of available bytes
|
||||
int serial_available();
|
||||
int serial_available();
|
||||
|
||||
private:
|
||||
char port_name[1024];
|
||||
unsigned int baud_rate;
|
||||
private:
|
||||
char port_name[1024];
|
||||
unsigned int baud_rate;
|
||||
|
||||
#ifdef WIN32
|
||||
HANDLE file_descriptor;
|
||||
DCB dcb;
|
||||
|
||||
#else
|
||||
|
||||
int file_descriptor;
|
||||
#endif
|
||||
#ifdef _WIN32
|
||||
HANDLE file_descriptor;
|
||||
DCB dcb;
|
||||
#else
|
||||
int file_descriptor;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue