加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

QextSerialPort类多线程读写串口的方法

(2015-05-29 16:39:31)
标签:

it

分类: qt

QextSerialPort是一个跨平台的第三方串口类,可以很方便地在QT中对串口读写操作。但是默认使用的读写方式是查询方式,一般都是在程序中使用定时器。如果需要快速响应串口读写,可以使用多线程方式。在qtcentre论坛上找到了一位作者贴出了自己的源码,在此转贴出来,方便大家。(原帖地址:http://www.qtcentre.org/threads/21063-QextSerialPort-with-QTimer-approch-for-reading?p=103325&highlight=#post103325

 

程序是QT4直接可用的。如果是QTE2,相应做一些修改后也可以工作。


mythreadport.h

 #ifndef MYSERIALPORT_H
#define MYSERIALPORT_H
#include
#include
#include
#include
#include
#include "qextserialport.h"
Q_DECLARE_METATYPE(BaudRateType);
Q_DECLARE_METATYPE(DataBitsType);
Q_DECLARE_METATYPE(ParityType);
Q_DECLARE_METATYPE(StopBitsType);
Q_DECLARE_METATYPE(FlowType);
class SendThread;
class ReceiveThread;
class MySerialPort : public QObject
{
    Q_OBJECT
public:
    MySerialPort();
    MySerialPort(const QString &name, const BaudRateType baudRate, const DataBitsType dataBits,
                 const ParityType parity, const StopBitsType stopBits, const FlowType flowControl,
                 ulong seconds = 0, ulong milliseconds = 10);
    ~MySerialPort();
    bool open();
    bool open(const QString &name, const BaudRateType baudRate, const DataBitsType dataBits,
              const ParityType parity, const StopBitsType stopBits, const FlowType flowControl,
              ulong seconds = 0, ulong milliseconds = 10);
    bool isOpen() const;
    void close();
    // Setter and getter for the basic property of the QextSerialPort
    void setPortName(const QString &name);
    QString portName() const;
    void setBaudRate(const BaudRateType baudRate);
    BaudRateType baudRate() const;
    void setDataBits(const DataBitsType dataBits);
    DataBitsType dataBits() const;
    void setParity(const ParityType parity);
    ParityType parity() const;
    void setStopBits(StopBitsType stopBits);
    StopBitsType stopBits() const;
    void setFlowControl(const FlowType flowControl);
    FlowType flowControl() const;
    void setTimeout(const ulong seconds, const ulong milliseconds);
   
    void enableSending();           // enable the SerialPort to send data (init the thread)
    void disableSending();          // disable the SerialPort to send data (terminate the thread)
    bool isSendingEnable() const;
    void stopSending();             // stop the currently sending data operation (don't terminate the thread)
    uchar sendData(const QByteArray &data); // send data to the SerialPort (enqueue data to the sendThread queue)
    // return 1     OK
    // return 2     port not open
    // return 3     sending operation disable
   
    void enableReceiving();         // enable the SerialPort to receive data (init the thread)
    void disableReceiving();        // disable the SerialPort to receive data (terminate the thread)
    bool isReceivingEnable() const;
    void stopReceiving();           // stop the currently receiving data operation (don't terminate the thread)
    uchar receiveData();                    // Start the receiving thread
    // return 1     OK
    // return 2     port closed
    // return 3     receiving operation disable
signals:
    void dataReceived(const QByteArray &dataReceived);
private:
    void initPrivateVariable();
private:
    QextSerialPort port;
    SendThread *sendThread;
    ReceiveThread *receiveThread;
    bool sendingEnable;
    bool receivingEnable;
    // Variables to restore the previous state to a reopening of the SerialPort
    bool closeCalled;
    bool saveStateSendingEnable;
    bool saveStateReceivingEnable;
    bool saveStateReceiveData;
};
class SendThread : public QThread
{
    Q_OBJECT
public:
    SendThread(QextSerialPort &adrPort);
    ~SendThread();
    void addDataToSend(const QByteArray &dataToAdd);
    void stopSending();
protected:
    void run();
private:
    QextSerialPort &port;
    QQueue dataToSend;
    QMutex mutexSend;
    bool stopped;
};
class ReceiveThread : public QThread
{
    Q_OBJECT
public:
    ReceiveThread(QextSerialPort &adrPort);
    ~ReceiveThread();
    void stopReceiving();
protected:
    void run();
signals:
    void dataReceived(const QByteArray &dataReceived);
private :
    QextSerialPort &port;
    QMutex mutexReceive;
    bool stopped;
};
#endif // MYSERIALPORT_H

 

mythreadport.cpp

 #include "myserialport.h"

void MySerialPort::initPrivateVariable()
{
    // Init private variable
    sendThread = NULL;
    receiveThread = NULL;
    sendingEnable = false;
    receivingEnable = false;
    closeCalled = false;
    saveStateSendingEnable = false;
    saveStateReceivingEnable = false;
    saveStateReceiveData = false;
}


MySerialPort::MySerialPort()
{
    initPrivateVariable();
}
MySerialPort::MySerialPort(const QString &name, const BaudRateType baudRate, const DataBitsType dataBits,
                           const ParityType parity, const StopBitsType stopBits, const FlowType flowControl,
                           ulong seconds, ulong milliseconds)
{
    initPrivateVariable();
    setPortName(name);
    setBaudRate(baudRate);
    setDataBits(dataBits);
    setParity(parity);
    setStopBits(stopBits);
    setFlowControl(flowControl);
    setTimeout(seconds, milliseconds);
}

MySerialPort::~MySerialPort()
{
    if (sendThread)
    {
        delete sendThread;
        sendThread = NULL;
    }
    if (receiveThread)
    {
        delete receiveThread;
        receiveThread = NULL;
    }
    if (isOpen())
        port.close();
}

// Open the SerialPort
bool MySerialPort::open()
{
    bool res = port.open(QIODevice::ReadWrite);
    // If the port is reopened after an earlier closure restores the previous state
    if (closeCalled)
    {
        if (saveStateSendingEnable)
            enableSending();
        if (saveStateReceivingEnable)
            enableReceiving();
        if (saveStateReceiveData)
            receiveData();
        closeCalled = false;
    }
    return res;
}
bool MySerialPort::open(const QString &name, const BaudRateType baudRate, const DataBitsType dataBits,
                        const ParityType parity, const StopBitsType stopBits, const FlowType flowControl,
                        ulong seconds, ulong milliseconds)
{
    setPortName(name);
    setBaudRate(baudRate);
    setDataBits(dataBits);
    setParity(parity);
    setStopBits(stopBits);
    setFlowControl(flowControl);
    setTimeout(seconds, milliseconds);
    //return open();
    return port.open(QIODevice::ReadWrite);
}
// SerialPort is open?
bool MySerialPort::isOpen() const
{
    return port.isOpen();
}
// Close the SerialPort
void MySerialPort::close()
{
    closeCalled = true;
    // Save the state
    saveStateSendingEnable = isSendingEnable();
    saveStateReceivingEnable = isReceivingEnable();
    // Close the port
    disableReceiving();
    disableSending();
    port.close();
    // TODO: should I stop send and receive?
}
// Setter and getter for the basic property of the QextSerialPort
void MySerialPort::setPortName(const QString &name)
{
    port.setPortName(name);
}
QString MySerialPort::portName() const
{
    return port.portName();
}
void MySerialPort::setBaudRate(const BaudRateType baudRate)
{
    port.setBaudRate(baudRate);
}
BaudRateType MySerialPort::baudRate() const
{
    return port.baudRate();
}
void MySerialPort::setDataBits(const DataBitsType dataBits)
{
    port.setDataBits(dataBits);
}
DataBitsType MySerialPort::dataBits() const
{
    return port.dataBits();
}
void MySerialPort::setParity(const ParityType parity)
{
    port.setParity(parity);
}
ParityType MySerialPort::parity() const
{
    return port.parity();
}
void MySerialPort::setStopBits(StopBitsType stopBits)
{
    port.setStopBits(stopBits);
}
StopBitsType MySerialPort::stopBits() const
{
    return port.stopBits();
}
void MySerialPort::setFlowControl(const FlowType flowControl)
{
    port.setFlowControl(flowControl);
}
FlowType MySerialPort::flowControl() const
{
    return port.flowControl();
}
void MySerialPort::setTimeout(const ulong seconds, const ulong milliseconds)
{
    port.setTimeout(seconds, milliseconds);
}

// Enable the SerialPort to send data (init the thread)
void MySerialPort::enableSending()
{
    // If the Sending is not already active AND the sendThead is not initialized
    if (!sendingEnable && !sendThread)
    {
        sendThread = new SendThread(port);
        sendingEnable = true;
    }
}
// Disable the SerialPort to send data (terminate the thread)
void MySerialPort::disableSending()
{
    // If the Sending is already active AND there is a sendThread
    if (sendingEnable && sendThread)
    {
        delete sendThread;
        sendThread = NULL;
        sendingEnable = false;
    }
}
bool MySerialPort::isSendingEnable() const
{
    return sendingEnable;
}
// Stop the currently sending data operation (don't terminate the thread)
void MySerialPort::stopSending()
{
    // If the Sending is not alread active OR the sendThread is not initialized
    if (!sendingEnable || !sendThread)
        return;
    // If the SerialPort is currently sending data, stop
    if (sendThread->isRunning())
    {
        sendThread->stopSending();
        //wait(); ??????????
        sendThread->wait();
    }
}
// Enqueue data to the sendThread queue
// return 1     OK
// return 2     port closed
// return 3     sending operation disable
uchar MySerialPort::sendData(const QByteArray &data)
{
    // check the port if is open
    if (!isOpen())
        return 2;
    // check if sending operation is enable
    if (!sendingEnable || !sendThread)
        return 3;
    sendThread->addDataToSend(data);
    return 1;
}

// Enable the SerialPort to receive data (init the thread)
void MySerialPort::enableReceiving()
{
    // If the Receiving is not already active AND the receiveThead is not initialized
    if (!receivingEnable && !receiveThread)
    {
        receiveThread = new ReceiveThread(port);
        connect(receiveThread, SIGNAL(dataReceived(const QByteArray &)),
                this, SIGNAL(dataReceived(const QByteArray &)));
        receivingEnable = true;
    }
}
// Disable the SerialPort to receive data (terminate the thread)
void MySerialPort::disableReceiving()
{
     // If the Receiving is already active AND there is a receiveThread
    if (receivingEnable && receiveThread)
    {
        delete receiveThread;
        receiveThread = NULL;
        receivingEnable = false;
    }
}
bool MySerialPort::isReceivingEnable() const
{
    return receivingEnable;
}
// Stop the currently receiving data operation (don't terminate the thread)
void MySerialPort::stopReceiving()
{
        // If the Receiving is not alread active OR the receiveThread is not initialized
    if (!receivingEnable || !receiveThread)
        return;
    // If the SerialPort is currently receiving data, stop
    if (receiveThread->isRunning())
    {
        saveStateReceiveData = false;
        receiveThread->stopReceiving();
        // wait();
        receiveThread->wait();
    }
}
// Start the receiving thread
// return 1     OK
// return 2     port closed
// return 3     receiving operation disable
uchar MySerialPort::receiveData()
{
    // check the port if is open
    if (!isOpen())
        return 2;
    // check if receiving operation is enable
    if (!receivingEnable && !receiveThread)
        return 3;
    // If the SerialPort receiving thread is not currently active, start it
    if (!receiveThread->isRunning())
    {
        saveStateReceiveData = true;
        receiveThread->start();
    }
    return 1;
}


SendThread::SendThread(QextSerialPort &adrPort): port(adrPort)
{
    dataToSend.clear();
    stopped = false;
}

SendThread::~SendThread()
{
    if (isRunning())
    {
        stopSending();
        wait();
    }
}

// Add the data to the Send Queue
void SendThread::addDataToSend(const QByteArray &dataToAdd)
{
    QMutexLocker locker(&mutexSend);
    for (int i=0; i
        dataToSend.enqueue(QByteArray(1,dataToAdd.at(i)));
    if (!isRunning())
        start();
}
// Stop the sending operation
void SendThread::stopSending()
{
    stopped = true;
}
// Thread Send Loop
void SendThread::run()
{
    QByteArray byteArray;
    forever
    {
        mutexSend.lock();
        if (dataToSend.isEmpty() || stopped)
        {
            mutexSend.unlock();
            stopped = false;
            break;
        }
        byteArray = dataToSend.dequeue();
        mutexSend.unlock();
        port.write(byteArray, 1);
    }
}


ReceiveThread::ReceiveThread(QextSerialPort &adrPort) : port(adrPort)
{
    stopped = false;
}

ReceiveThread::~ReceiveThread()
{
    if (isRunning())
    {
        stopReceiving();
        wait();
    }
}

// Stop the sending operation
void ReceiveThread::stopReceiving()
{
    stopped = true;
}
// Thread Receive Loop
void ReceiveThread::run()
{
    int numBytes = 0;
    QByteArray data;
    forever
    {
        if (stopped)
        {
            stopped = false;
            break;
        }
        numBytes = port.bytesAvailable();
        if (numBytes>0)
        {
            mutexReceive.lock();
            data = port.read(numBytes);
            mutexReceive.unlock();
            emit dataReceived(data);
        }
    }
}

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有