查了很多资料和源码,封装了一个串口类,只有一些简单的功能,希望各位能指点一下,现有功能是否有问题!另外还有那些必要的功能需要添加?
SerialPort.h
/*!
********************************************************************************
* @file SerialPort.h
* @brief 串口.
* @version 1.1
* @date 2014.11.25
*******************************************************************************
*/
#ifndef _SERIALPORT_H
#define _SERIALPORT_H
#ifndef OS_WIN
# include <termios.h>
#else
# error
#endif
enum SPIndex
{
COM_1,
COM_2,
COM_3,
COM_4,
COM_5,
COM_6,
COM_7,
COM_8,
COM_9
};
enum SPBaudRate
{
BAUD_000150,
BAUD_000300,
BAUD_000600,
BAUD_001200,
BAUD_002400,
BAUD_004800,
BAUD_009600,
BAUD_019200,
BAUD_038400,
BAUD_057600,
BAUD_115200,
BAUD_230400,
BAUD_460800,
BAUD_921600
};
enum SPFlowControl
{
FLOW_CONTROL_NONE,
FLOW_CONTROL_RTSCTS,
FLOW_CONTROL_XONXOFF,
FLOW_CONTROL_BOTH
};
enum SPParity
{
PARITY_NONE,
PARITY_EVEN,
PARITY_ODD,
PARITY_SPACE,
PARITY_MARK
};
enum SPCharSize
{
CHAR_SIZE_5,
CHAR_SIZE_6,
CHAR_SIZE_7,
CHAR_SIZE_8
};
enum SPStopBits
{
STOP_BITS_1,
STOP_BITS_2
};
class SPOption
{
public:
SPBaudRate baud_rate = BAUD_115200;
SPParity parity = PARITY_NONE;
SPFlowControl flow_control = FLOW_CONTROL_NONE;
SPCharSize char_size = CHAR_SIZE_8;
SPStopBits stop_bits = STOP_BITS_1;
};
class _BoiExport SerialPort
{
public:
#ifndef OS_WIN
typedef int SPTarget;
#else
# error
#endif
SerialPort();
~SerialPort();
bool Open (SPIndex _index);
SPTarget GetTarget();
int Read (byte* _buf, long _len);
int Write (byte* _buf, long _len);
bool SetOption (const SPOption& _op);
SPOption GetOption ();
bool SetBlocking (bool _blocking = true);
bool Close ();
private:
SPTarget fd;
SPOption option;
#ifndef OS_WIN
struct termios new_t, old_t;
#else
# error
#endif
};
#endif //_SERIALPORT_H
SerialPort.cpp
/*!
********************************************************************************
* @file SerialPort.cpp
* @version 1.1
* @date 2014.11.25
*******************************************************************************
*/
#include "SerialPort.h"
#ifndef OS_WIN
# include <fcntl.h>
# include <unistd.h>
#else
# error
#endif
//-------------------------------------------------------------------------
SerialPort::SerialPort()
{
fd = -1;
}
//-------------------------------------------------------------------------
SerialPort::~SerialPort()
{
Close();
}
//-------------------------------------------------------------------------
static std::string SerialPortName[] =
{
"/dev/ttyS0",
"/dev/ttyS1",
"/dev/ttyS2",
"/dev/ttyS3",
"/dev/ttyS4",
"/dev/ttyS5",
"/dev/ttyS6",
"/dev/ttyS7",
"/dev/ttyS8"
};
//-------------------------------------------------------------------------
bool SerialPort::Open(SPIndex _index)
{
fd = open(SerialPortName[_index].c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK);
return fd >= 0;
}
//-------------------------------------------------------------------------
SerialPort::SPTarget SerialPort::GetTarget()
{
return fd;
}
//-------------------------------------------------------------------------
static speed_t SerialPortBaudRate[] =
{
B150, B300, B600, B1200,
B2400, B4800,B9600, B19200,
B38400, B57600, B115200,
B230400, B460800, B921600
};
//-------------------------------------------------------------------------
bool SerialPort::SetOption(const SPOption& _op)
{
if (tcgetattr(fd, &new_t) != 0)
{
return false;
}
old_t = new_t;
cfsetispeed(&new_t, SerialPortBaudRate[option.baud_rate]);
cfsetospeed(&new_t, SerialPortBaudRate[option.baud_rate]);
new_t.c_cflag &= ~CSIZE;
switch (option.char_size)
{
case CHAR_SIZE_5:
new_t.c_cflag |= CS5;
break;
case CHAR_SIZE_6:
new_t.c_cflag |= CS6;
break;
case CHAR_SIZE_7:
new_t.c_cflag |= CS7;
break;
case CHAR_SIZE_8:
new_t.c_cflag |= CS8;
break;
}
#define CMSPAR 010000000000
switch (option.parity)
{
case PARITY_NONE:
new_t.c_cflag &= ~PARENB;
new_t.c_iflag &= ~INPCK;
break;
case PARITY_EVEN:
new_t.c_cflag |= PARENB;
new_t.c_cflag &= ~PARODD;
new_t.c_iflag |= INPCK;
break;
case PARITY_ODD:
new_t.c_cflag |= PARENB;
new_t.c_cflag |= PARODD;
new_t.c_iflag |= INPCK;
break;
case PARITY_SPACE:
new_t.c_cflag &= ~PARENB;
new_t.c_cflag &= ~CSTOPB;
break;
case PARITY_MARK:
new_t.c_cflag |= PARENB;
new_t.c_cflag |= CMSPAR;
break;
}
switch (option.stop_bits)
{
case STOP_BITS_1:
new_t.c_cflag &= ~CSTOPB;
break;
case STOP_BITS_2:
new_t.c_cflag |= CSTOPB;
break;
}
new_t.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG | IEXTEN);
new_t.c_iflag &= ~(BRKINT | IGNCR |ICRNL | INPCK | ISTRIP | IXANY);
new_t.c_iflag |= IGNPAR;
new_t.c_oflag &= ~OPOST;
switch (option.flow_control)
{
case FLOW_CONTROL_NONE:
new_t.c_cflag &= ~CRTSCTS;
new_t.c_iflag &= ~(IXON | IXOFF);
break;
case FLOW_CONTROL_RTSCTS:
new_t.c_cflag |= CRTSCTS;
new_t.c_iflag &= ~(IXON | IXOFF);
break;
case FLOW_CONTROL_XONXOFF:
new_t.c_cflag &= ~CRTSCTS;
new_t.c_iflag |= (IXON | IXOFF);
break;
case FLOW_CONTROL_BOTH:
new_t.c_cflag |= CRTSCTS;
new_t.c_iflag |= (IXON | IXOFF);
break;
}
new_t.c_cc[VINTR] = 0;
new_t.c_cc[VQUIT] = 0;
new_t.c_cc[VERASE] = 0;
new_t.c_cc[VKILL] = 0;
new_t.c_cc[VEOF] = 0;
new_t.c_cc[VTIME] = 1;
new_t.c_cc[VMIN] = 0;
new_t.c_cc[VSWTC] = 0;
new_t.c_cc[VSTART] = 0;
new_t.c_cc[VSTOP] = 0;
new_t.c_cc[VSUSP] = 0;
new_t.c_cc[VEOL] = 0;
new_t.c_cc[VREPRINT] = 0;
new_t.c_cc[VDISCARD] = 0;
new_t.c_cc[VWERASE] = 0;
new_t.c_cc[VLNEXT] = 0;
new_t.c_cc[VEOL2] = 0;
tcflush(fd, TCIFLUSH);
if (tcsetattr(fd, TCSANOW, &new_t) != 0)
{
return false;
}
return option = _op, true;
}
//-------------------------------------------------------------------------
SPOption SerialPort::GetOption()
{
return option;
}
//-------------------------------------------------------------------------
int SerialPort::Read(byte* _buf, long _len)
{
return read(fd, _buf, _len);
}
//-------------------------------------------------------------------------
int SerialPort::Write(byte* _buf, long _len)
{
return write(fd, _buf, _len);
}
//-------------------------------------------------------------------------
bool SerialPort::Close()
{
if (fd < 0)
{
return true;
}
tcflush(fd, TCOFLUSH);
tcsetattr(fd, TCSANOW, &old_t);
int err = close(fd);
fd = -1;
return !err;
}
//-------------------------------------------------------------------------
bool SerialPort::SetBlocking(bool _blocking)
{
if (fd < 0)
{
return false;
}
int err = -1;
if (!_blocking)
{
err = fcntl(fd, F_SETFL, FNDELAY);
}
else
{
err = fcntl(fd, F_SETFL, 0);
}
return err != -1;
}
//-------------------------------------------------------------------------
------解决思路----------------------
自己动手测试啊,拿个串口调试版测试一下,你测试没问题就可以啦!不要以为高手万能的,都是动手来的!!!!
------解决思路----------------------
看上去想法很好。
不过OS内一般都提供COM口控制的API,你再封装一次感觉有些怪怪的。
代码里面好几处出现宏开关:
#ifndef OS_WIN
typedef int SPTarget;
#else
# error
#endif
你的代码在non OS_WIN上测试过么?
另外,你的头文件中定义
class _BoiExport SerialPort
_BoiExport 是干什么的。