⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 posix_qextserialport.cpp

📁 QT 下linux串口类
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    LOCK_MUTEX();
    if (Settings.FlowControl!=flow) {
        Settings.FlowControl=flow;
    }
    if (isOpen()) {
        switch(flow) {

            /*no flow control*/
            case FLOW_OFF:
                Posix_CommConfig.c_cflag&=(~CRTSCTS);
                Posix_CommConfig.c_iflag&=(~(IXON|IXOFF|IXANY));
                tcsetattr(Posix_File->handle(), TCSAFLUSH, &Posix_CommConfig);
                break;

            /*software (XON/XOFF) flow control*/
            case FLOW_XONXOFF:
                Posix_CommConfig.c_cflag&=(~CRTSCTS);
                Posix_CommConfig.c_iflag|=(IXON|IXOFF|IXANY);
                tcsetattr(Posix_File->handle(), TCSAFLUSH, &Posix_CommConfig);
                break;

            case FLOW_HARDWARE:
                Posix_CommConfig.c_cflag|=CRTSCTS;
                Posix_CommConfig.c_iflag&=(~(IXON|IXOFF|IXANY));
                tcsetattr(Posix_File->handle(), TCSAFLUSH, &Posix_CommConfig);
                break;
        }
    }
    UNLOCK_MUTEX();
}

/*!
\fn void Posix_QextSerialPort::setTimeout(ulong sec, ulong millisec);
Sets the read and write timeouts for the port to sec seconds and millisec milliseconds.
Note that this is a per-character timeout, i.e. the port will wait this long for each
individual character, not for the whole read operation.  This timeout also applies to the
bytesWaiting() function.

\note
POSIX does not support millisecond-level control for I/O timeout values.  Any
timeout set using this function will be set to the next lowest tenth of a second for
the purposes of detecting read or write timeouts.  For example a timeout of 550 milliseconds
will be seen by the class as a timeout of 500 milliseconds for the purposes of reading and
writing the port.  However millisecond-level control is allowed by the select() system call,
so for example a 550-millisecond timeout will be seen as 550 milliseconds on POSIX systems for
the purpose of detecting available bytes in the read buffer.

*/
void Posix_QextSerialPort::setTimeout(ulong sec, ulong millisec)
{
    LOCK_MUTEX();
    Settings.Timeout_Sec=sec;
    Settings.Timeout_Millisec=millisec;
    Posix_Copy_Timeout.tv_sec=sec;
    Posix_Copy_Timeout.tv_usec=millisec;
    if (isOpen()) {
        tcgetattr(Posix_File->handle(), &Posix_CommConfig);
        Posix_CommConfig.c_cc[VTIME]=sec*10+millisec/100;
        tcsetattr(Posix_File->handle(), TCSAFLUSH, &Posix_CommConfig);
    }
    UNLOCK_MUTEX();
}

/*!
\fn bool Posix_QextSerialPort::open(OpenMode mode)
Opens the serial port associated to this class.
This function has no effect if the port associated with the class is already open.
The port is also configured to the current settings, as stored in the Settings structure.
*/
bool Posix_QextSerialPort::open(OpenMode mode)
{
    LOCK_MUTEX();
    if (mode == QIODevice::NotOpen)
    	return isOpen();
    if (!isOpen()) {
        /*open the port*/
        Posix_File->setFileName(port);
        qDebug("Trying to open File");
        if (Posix_File->open(QIODevice::ReadWrite|QIODevice::Unbuffered)) {
            qDebug("Opened File succesfully");
            /*set open mode*/
            QIODevice::open(mode);

            /*configure port settings*/
            tcgetattr(Posix_File->handle(), &Posix_CommConfig);

            /*set up other port settings*/
            Posix_CommConfig.c_cflag|=CREAD|CLOCAL;
            Posix_CommConfig.c_lflag&=(~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|ISIG));
            Posix_CommConfig.c_iflag&=(~(INPCK|IGNPAR|PARMRK|ISTRIP|ICRNL|IXANY));
            Posix_CommConfig.c_oflag&=(~OPOST);
            Posix_CommConfig.c_cc[VMIN]=0;
            Posix_CommConfig.c_cc[VINTR] = _POSIX_VDISABLE;
            Posix_CommConfig.c_cc[VQUIT] = _POSIX_VDISABLE;
            Posix_CommConfig.c_cc[VSTART] = _POSIX_VDISABLE;
            Posix_CommConfig.c_cc[VSTOP] = _POSIX_VDISABLE;
            Posix_CommConfig.c_cc[VSUSP] = _POSIX_VDISABLE;
            setBaudRate(Settings.BaudRate);
            setDataBits(Settings.DataBits);
            setParity(Settings.Parity);
            setStopBits(Settings.StopBits);
            setFlowControl(Settings.FlowControl);
            setTimeout(Settings.Timeout_Sec, Settings.Timeout_Millisec);
            tcsetattr(Posix_File->handle(), TCSAFLUSH, &Posix_CommConfig);
        } else {
            qDebug("Could not open File! Error code : %d", Posix_File->error());
        }
    }
    UNLOCK_MUTEX();
    return isOpen();
}

/*!
\fn void Posix_QextSerialPort::close()
Closes a serial port.  This function has no effect if the serial port associated with the class
is not currently open.
*/
void Posix_QextSerialPort::close()
{
    LOCK_MUTEX();
    Posix_File->close();
    QIODevice::close();
    UNLOCK_MUTEX();
}

/*!
\fn void Posix_QextSerialPort::flush()
Flushes all pending I/O to the serial port.  This function has no effect if the serial port
associated with the class is not currently open.
*/
void Posix_QextSerialPort::flush()
{
    LOCK_MUTEX();
    if (isOpen()) {
        Posix_File->flush();
    }
    UNLOCK_MUTEX();
}

/*!
\fn qint64 Posix_QextSerialPort::size() const
This function will return the number of bytes waiting in the receive queue of the serial port.
It is included primarily to provide a complete QIODevice interface, and will not record errors
in the lastErr member (because it is const).  This function is also not thread-safe - in
multithreading situations, use Posix_QextSerialPort::bytesWaiting() instead.
*/
qint64 Posix_QextSerialPort::size() const
{
    int numBytes;
    if (ioctl(Posix_File->handle(), FIONREAD, &numBytes)<0) {
        numBytes=0;
    }
    return (qint64)numBytes;
}

/*!
\fn qint64 Posix_QextSerialPort::bytesAvailable()
Returns the number of bytes waiting in the port's receive queue.  This function will return 0 if
the port is not currently open, or -1 on error.  Error information can be retrieved by calling
Posix_QextSerialPort::getLastError().
*/
qint64 Posix_QextSerialPort::bytesAvailable()
{
    LOCK_MUTEX();
    if (isOpen()) {
        int bytesQueued;
        fd_set fileSet;
        FD_ZERO(&fileSet);
        FD_SET(Posix_File->handle(), &fileSet);

        /*on Linux systems the Posix_Timeout structure will be altered by the select() call.
          Make sure we use the right timeout values*/
        //memcpy(&Posix_Timeout, &Posix_Copy_Timeout, sizeof(struct timeval));
        Posix_Timeout = Posix_Copy_Timeout;
        int n=select(Posix_File->handle()+1, &fileSet, NULL, &fileSet, &Posix_Timeout);
        if (!n) {
            lastErr=E_PORT_TIMEOUT;
            UNLOCK_MUTEX();
            return -1;
        }
        if (n==-1 || ioctl(Posix_File->handle(), FIONREAD, &bytesQueued)==-1) {
            translateError(errno);
            UNLOCK_MUTEX();
            return -1;
        }
        lastErr=E_NO_ERROR;
        UNLOCK_MUTEX();
        return bytesQueued + QIODevice::bytesAvailable();
    }
    UNLOCK_MUTEX();
    return 0;
}

/*!
\fn void Posix_QextSerialPort::ungetChar(char)
This function is included to implement the full QIODevice interface, and currently has no
purpose within this class.  This function is meaningless on an unbuffered device and currently
only prints a warning message to that effect.
*/
void Posix_QextSerialPort::ungetChar(char)
{
    /*meaningless on unbuffered sequential device - return error and print a warning*/
    TTY_WARNING("Posix_QextSerialPort: ungetChar() called on an unbuffered sequential device - operation is meaningless");
}

/*!
\fn void Posix_QextSerialPort::translateError(ulong error)
Translates a system-specific error code to a QextSerialPort error code.  Used internally.
*/
void Posix_QextSerialPort::translateError(ulong error)
{
    switch (error) {
        case EBADF:
        case ENOTTY:
            lastErr=E_INVALID_FD;
            break;

        case EINTR:
            lastErr=E_CAUGHT_NON_BLOCKED_SIGNAL;
            break;

        case ENOMEM:
            lastErr=E_NO_MEMORY;
            break;
    }
}

/*!
\fn void Posix_QextSerialPort::setDtr(bool set)
Sets DTR line to the requested state (high by default).  This function will have no effect if
the port associated with the class is not currently open.
*/
void Posix_QextSerialPort::setDtr(bool set)
{
    LOCK_MUTEX();
    if (isOpen()) {
        int status;
        ioctl(Posix_File->handle(), TIOCMGET, &status);
        if (set) {
            status|=TIOCM_DTR;
        }
        else {
            status&=~TIOCM_DTR;
        }
        ioctl(Posix_File->handle(), TIOCMSET, &status);
    }
    UNLOCK_MUTEX();
}

/*!
\fn void Posix_QextSerialPort::setRts(bool set)
Sets RTS line to the requested state (high by default).  This function will have no effect if
the port associated with the class is not currently open.
*/
void Posix_QextSerialPort::setRts(bool set)
{
    LOCK_MUTEX();
    if (isOpen()) {
        int status;
        ioctl(Posix_File->handle(), TIOCMGET, &status);
        if (set) {
            status|=TIOCM_RTS;
        }
        else {
            status&=~TIOCM_RTS;
        }
        ioctl(Posix_File->handle(), TIOCMSET, &status);
    }
    UNLOCK_MUTEX();
}

/*!
\fn unsigned long Posix_QextSerialPort::lineStatus()
returns the line status as stored by the port function.  This function will retrieve the states
of the following lines: DCD, CTS, DSR, and RI.  On POSIX systems, the following additional lines
can be monitored: DTR, RTS, Secondary TXD, and Secondary RXD.  The value returned is an unsigned
long with specific bits indicating which lines are high.  The following constants should be used
to examine the states of individual lines:

\verbatim
Mask        Line
------      ----
LS_CTS      CTS
LS_DSR      DSR
LS_DCD      DCD
LS_RI       RI
LS_RTS      RTS (POSIX only)
LS_DTR      DTR (POSIX only)
LS_ST       Secondary TXD (POSIX only)
LS_SR       Secondary RXD (POSIX only)
\endverbatim

This function will return 0 if the port associated with the class is not currently open.
*/
unsigned long Posix_QextSerialPort::lineStatus()
{
    unsigned long Status=0, Temp=0;
    LOCK_MUTEX();
    if (isOpen()) {
        ioctl(Posix_File->handle(), TIOCMGET, &Temp);
        if (Temp&TIOCM_CTS) {
            Status|=LS_CTS;
        }
        if (Temp&TIOCM_DSR) {
            Status|=LS_DSR;
        }
        if (Temp&TIOCM_RI) {
            Status|=LS_RI;
        }
        if (Temp&TIOCM_CD) {
            Status|=LS_DCD;
        }
        if (Temp&TIOCM_DTR) {
            Status|=LS_DTR;
        }
        if (Temp&TIOCM_RTS) {
            Status|=LS_RTS;
        }
        if (Temp&TIOCM_ST) {
            Status|=LS_ST;
        }
        if (Temp&TIOCM_SR) {
            Status|=LS_SR;
        }
    }
    UNLOCK_MUTEX();
    return Status;
}

/*!
\fn qint64 Posix_QextSerialPort::readData(char * data, qint64 maxSize)
Reads a block of data from the serial port.  This function will read at most maxSize bytes from
the serial port and place them in the buffer pointed to by data.  Return value is the number of
bytes actually read, or -1 on error.

\warning before calling this function ensure that serial port associated with this class
is currently open (use isOpen() function to check if port is open).
*/
qint64 Posix_QextSerialPort::readData(char * data, qint64 maxSize)
{
    LOCK_MUTEX();
    int retVal=0;
    retVal=Posix_File->read(data, maxSize);
    if (retVal==-1)
        lastErr=E_READ_FAILED;
    UNLOCK_MUTEX();

    return retVal;
}

/*!
\fn qint64 Posix_QextSerialPort::writeData(const char * data, qint64 maxSize)
Writes a block of data to the serial port.  This function will write maxSize bytes
from the buffer pointed to by data to the serial port.  Return value is the number
of bytes actually written, or -1 on error.

\warning before calling this function ensure that serial port associated with this class
is currently open (use isOpen() function to check if port is open).
*/
qint64 Posix_QextSerialPort::writeData(const char * data, qint64 maxSize)
{
    LOCK_MUTEX();
    int retVal=0;
    retVal=Posix_File->write(data, maxSize);
    if (retVal==-1)
       lastErr=E_WRITE_FAILED;
    UNLOCK_MUTEX();

    flush();
    return retVal;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -