封装了一个串口类,希望高手鉴定一下是否有错误!

shilei_312 2014-11-30 10:45:56
查了很多资料和源码,封装了一个串口类,只有一些简单的功能,希望各位能指点一下,现有功能是否有问题!另外还有那些必要的功能需要添加?

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;
}
//-------------------------------------------------------------------------
...全文
177 3 打赏 收藏 转发到动态 举报
写回复
用AI写文章
3 条回复
切换为时间正序
请发表友善的回复…
发表回复
shilei_312 2014-12-02
  • 打赏
  • 举报
回复
引用 2 楼 Huntercao 的回复:
看上去想法很好。 不过OS内一般都提供COM口控制的API,你再封装一次感觉有些怪怪的。 代码里面好几处出现宏开关:

#ifndef OS_WIN
	typedef int SPTarget;
#else
#       error
#endif
你的代码在non OS_WIN上测试过么? 另外,你的头文件中定义

class _BoiExport SerialPort
_BoiExport 是干什么的。
想做一个跨平台的适用的封装,_BoiExport是想做一个库
zacharyLiu 2014-12-01
  • 打赏
  • 举报
回复
自己动手测试啊,拿个串口调试版测试一下,你测试没问题就可以啦!不要以为高手万能的,都是动手来的!!!!
曹大夯 2014-12-01
  • 打赏
  • 举报
回复
看上去想法很好。 不过OS内一般都提供COM口控制的API,你再封装一次感觉有些怪怪的。 代码里面好几处出现宏开关:

#ifndef OS_WIN
	typedef int SPTarget;
#else
#       error
#endif
你的代码在non OS_WIN上测试过么? 另外,你的头文件中定义

class _BoiExport SerialPort
_BoiExport 是干什么的。

21,595

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 驱动开发/核心开发
社区管理员
  • 驱动开发/核心开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧