• 您的位置:首页 > 新闻动态 > 技术文章

    LINUX串口通信

    2021/3/16      点击:

    serialport.h,serialport.cpp


    #ifndef SER_COM_PORT_TX_H
    #define SER_COM_PORT_TX_H
    #include <QSocketNotifier>
    #include <linux/fs.h>
    #include<fcntl.h>
    #include<errno.h>
    #include<termio.h>
    #include<sys/ioctl.h>
    #include<sys/stat.h>
    #include<sys/types.h>
    #include<stdlib.h>
    #include<unistd.h>
    #include <stdio.h>
    #include<QTimer>
    #include<QMutex>
    #include<QWidget>
    enum BaudRateType
    {
        BAUD50,                //POSIX ONLY
        BAUD75,                //POSIX ONLY
        BAUD110,
        BAUD134,               //POSIX ONLY
        BAUD150,               //POSIX ONLY
        BAUD200,               //POSIX ONLY
        BAUD300,
        BAUD600,
        BAUD1200,
        BAUD1800,              //POSIX ONLY
        BAUD2400,
        BAUD4800,
        BAUD9600,
        BAUD14400,             //WINDOWS ONLY
        BAUD19200,
        BAUD38400,
        BAUD56000,             //WINDOWS ONLY
        BAUD57600,
        BAUD76800,             //POSIX ONLY
        BAUD115200,
        BAUD128000,            //WINDOWS ONLY
        BAUD256000             //WINDOWS ONLY
    };
    enum DataBitsType
    {
        DATA_5,
        DATA_6,
        DATA_7,
        DATA_8
    };
    enum ParityType
    {
        PAR_NONE,
        PAR_ODD,
        PAR_EVEN,
        PAR_MARK,               //WINDOWS ONLY
        PAR_SPACE
    };
    enum StopBitsType
    {
        STOP_1,
        STOP_1_5,               //WINDOWS ONLY
        STOP_2
    };
    enum FlowType
    {
        FLOW_OFF,
        FLOW_HARDWARE,
        FLOW_XONXOFF
    };
    class SerialPort:public QObject
    {
        Q_OBJECT
    
    public:
        explicit SerialPort(QWidget *parent = 0);
    private:
        int m_fd;
        termios new_serialArry;
        QSocketNotifier *m_notifier;
        QByteArray  *rev_buf;
        QMutex mutex_r;
    public :  
        //open
        bool openPort(QString portName,BaudRateType baundRate,DataBitsType dataBits,ParityType parity,
                  StopBitsType stopBits, FlowType flow ,int time_out);
        //close
        bool close();
        //write
        int  write(QByteArray buf);
        //read
        QByteArray read();
    signals:
        void hasdata();
    private slots:
        void remoteDateInComing();
    };
    #endif // SER_COM_PORT_TX_H
    
    //serialport.cpp
    #include "serialport.h"
    #include<QDebug>
    SerialPort::SerialPort(QWidget *parent):
        QObject(parent)
    {
        m_fd=-1;
        rev_buf=new QByteArray();
    }
    //open
    bool SerialPort::openPort(QString portName, BaudRateType baundRate, DataBitsType dataBits,
                              ParityType parity, StopBitsType stopBits, FlowType flow, int time_out)
    {
        if(m_fd!=-1)
        {
            qDebug("is aready opened!");
            return false;
        }
        rev_buf->clear();
        memset(&new_serialArry,0,sizeof new_serialArry);
        m_fd=::open(portName.toLatin1(),O_RDWR|O_NONBLOCK);
        if( m_fd==-1)
        {
            qDebug("serial port  open erro!");
            return false;
        }
        switch(baundRate)
        {
        case BAUD50:
            new_serialArry.c_cflag |=  B50;
            break;
        case BAUD75:
            new_serialArry.c_cflag |=  B75;
            break;
        case BAUD110:
            new_serialArry.c_cflag |=  B110;
            break;
        case BAUD300:
            new_serialArry.c_cflag |=  B300;
            break;
        case BAUD600:
            new_serialArry.c_cflag |=  B600;
            break;
        case BAUD1200:
            new_serialArry.c_cflag |=  B1200;
            break;
        case BAUD2400:
            new_serialArry.c_cflag |=  B2400;
            break;
        case BAUD4800:
            new_serialArry.c_cflag |=  B4800;
            break;
        case BAUD9600:
            new_serialArry.c_cflag |=  B9600;
            break;
        case BAUD19200:
            new_serialArry.c_cflag |=  B19200;
            break;
        case BAUD38400:
            new_serialArry.c_cflag |=  B38400;
            break;
        case BAUD57600:
            new_serialArry.c_cflag |=  B57600;
            break;
        case BAUD115200:
            new_serialArry.c_cflag |=  B115200;
            break;
        default:
            new_serialArry.c_cflag |=  B9600;
            break;
        }
        switch(dataBits)
        {
        case DATA_5:
            new_serialArry.c_cflag|=CS5;
            break;
        case DATA_6:
            new_serialArry.c_cflag|=CS6;
            break;
        case DATA_7:
            new_serialArry.c_cflag|=CS7;
            break;
        case DATA_8:
            new_serialArry.c_cflag|=CS8;
            break;
        default:
            new_serialArry.c_cflag|=CS8;
            break;
        }
        switch (parity)
        {
    
        case PAR_NONE:
            new_serialArry.c_cflag &= (~PARENB);
            break;
        case PAR_EVEN:
            new_serialArry.c_cflag &= (~PARODD);
            new_serialArry.c_cflag |= PARENB;
            break;
        case PAR_ODD:
            new_serialArry.c_cflag |= (PARODD|PARENB);
            break;
        default:
            break;
        }
        switch(stopBits)
        {
        case STOP_1:
            new_serialArry.c_cflag &=(~CSTOPB);
            break;
        case STOP_1_5:
            break;
        case STOP_2:
            new_serialArry.c_cflag |=CSTOPB;
            break;
        default:
            new_serialArry.c_cflag &=(~CSTOPB);
            break;
        }
        switch(flow)
        {
        case FLOW_OFF:
            new_serialArry.c_cflag &=(~CRTSCTS);
            new_serialArry.c_iflag &=(~(IXON|IXOFF|IXANY));
            break;
        case FLOW_XONXOFF:
            new_serialArry.c_cflag &=(~CRTSCTS);
            new_serialArry.c_iflag |=(IXON|IXOFF|IXANY);
            break;
        case FLOW_HARDWARE:
            new_serialArry.c_cflag |=~CRTSCTS;
            new_serialArry.c_iflag &=(~(IXON|IXOFF|IXANY));
            break;
        default:
            break;
        }
        new_serialArry.c_oflag=0;
        new_serialArry.c_cc[VTIME]=time_out/100;
        tcflush(m_fd,TCIFLUSH);
        tcsetattr(m_fd,TCSANOW,&new_serialArry);
        m_notifier= new QSocketNotifier(m_fd,QSocketNotifier::Read,0);
        connect(m_notifier,SIGNAL(activated(int)),this,SLOT(remoteDateInComing()));
        return true;
    
    }
    //close
    bool SerialPort::close()
    {
        mutex_r.lock();
    
        if(m_fd!=-1)
        {
            disconnect(m_notifier,SIGNAL(activated(int)),this,SLOT(remoteDateInComing()));
            delete m_notifier;
            m_fd=-1;
            mutex_r.unlock();
            return true;
        }
        mutex_r.unlock();
        return false;
    }
    //recive data
    void SerialPort::remoteDateInComing()
    {
    
        unsigned char c[1024];
        int n= ::read(m_fd,&c,sizeof c);
        mutex_r.lock();
        for(int i=0;i<n;i++)
        {
            rev_buf->append(c[i]);
        }
        mutex_r.unlock();
        emit hasdata();
    }
    //write data
    int SerialPort::write(QByteArray buf)
    {
        mutex_r.lock();
        int ret;
        ret=0;
        if(m_fd!=-1)
        {        
                   ret= :: write(m_fd,buf.data(),buf.length());
        }
        mutex_r.unlock();
        return ret;
    }
    
    QByteArray SerialPort::read()
    {
        mutex_r.lock();
        QByteArray retByteArray;
        if(rev_buf->isEmpty())
        {
            retByteArray.append("aaa");
            retByteArray.clear();
        }else
        {
            //RECEIVE 00 ERROR 2019/2/19  retByteArray.append(rev_buf->data())
            retByteArray.append(rev_buf->data(),rev_buf->size());
            rev_buf->clear();
        }
        mutex_r.unlock();
        return retByteArray;
    }