当前位置: 代码迷 >> 驱动开发 >> 封装了一个串口类,希望高手鉴定一下是否有异常
  详细解决方案

封装了一个串口类,希望高手鉴定一下是否有异常

热度:148   发布时间:2016-04-28 10:03:29.0
封装了一个串口类,希望高手鉴定一下是否有错误!
本帖最后由 shilei_312 于 2014-12-01 09:09:02 编辑
查了很多资料和源码,封装了一个串口类,只有一些简单的功能,希望各位能指点一下,现有功能是否有问题!另外还有那些必要的功能需要添加?

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 是干什么的。


  相关解决方案