3

我对编程很陌生,我正在自学。我编写了一个应用程序来轮询来自控制单元的多个请求。我基本上连续向控制单元发送各种读取命令并读回响应。我的程序正常工作,我成功发送命令并接收答案。但是读取速度很慢(我的代码中有 100 毫秒超时,以确保我得到完整的答复)女士和我总是在那个时间范围内收到完整的答案。我有相同的设置 57K 波特 8 位 1 停止位并且没有奇偶校验。然而,我的 QT 代码需要将近 100 毫秒才能收到答案。在我的代码中,我读取了前 2 个字节(第一个字节是消息标识符,第二个字节是消息长度的剩余部分)然后我循环读取,直到总消息长度等于消息长度字节 +1(+ 1 包含第一个字节)。当我知道它知道硬件是限制因素时,为什么我的代码在 QT 中如此缓慢,我对此一无所知。请求总是 3 个字节,而回复从 3 到 61 个字节不等。请帮我指出我的错误。如果我删除超时,我总是有短读。到目前为止,我还尝试了 read(all) 但结果相同。以下是我阅读响应的代码摘录。完整代码位于 当我知道它知道硬件是限制因素时,为什么我的代码在 QT 中如此缓慢,我对此一无所知。请求总是 3 个字节,而回复从 3 到 61 个字节不等。请帮我指出我的错误。如果我删除超时,我总是有短读。到目前为止,我还尝试了 read(all) 但结果相同。以下是我阅读响应的代码摘录。完整代码位于 当我知道它知道硬件是限制因素时,为什么我的代码在 QT 中如此缓慢,我对此一无所知。请求总是 3 个字节,而回复从 3 到 61 个字节不等。请帮我指出我的错误。如果我删除超时,我总是有短读。到目前为止,我还尝试了 read(all) 但结果相同。以下是我阅读响应的代码摘录。完整代码位于https://github.com/MarkusIppy/PowerTune

//Error handling 
QTime startTime = QTime::currentTime(); 
int timeOut = 100; // timeout in milisec. 
QByteArray recvData = m_serialport->read(2);  // reading first two bytes of received message to determine lenght of ecpected message 
int msgLen = recvData[1]; //Total message Lenght excluding the first byte 
while ( recvData.size() <= (msgLen+1) ) 
{ 
    if ( startTime.msecsTo(QTime::currentTime()) > timeOut ) break; 
    recvData += m_serialport->read(msgLen+1-recvData.size()); 
} 

if (msgLen +1 == recvData.length())  //if the received data lenght equals the message lenght from lenght byte + identifier byte (correct message lenght received ) 
{ 
    qDebug() << "Received data OK"<<msgLen +1; 
    if(requestIndex <= 61){requestIndex++;} 
    else{requestIndex = 58;} 
    readData(recvData); 
} 
else   //if the lenght of the received message does not correspond with the expected lenght repeat the request 
{ 
    qDebug() << "Received data lenght NIO"; 
    readData(recvData); 
    qDebug() << "Request Message again"<< requestIndex; 
}
4

3 回答 3

2

再次稍微更改了我的代码,现在它可以在实际硬件上完美运行 下面是我准备阅读的插槽:

void Serial::readyToRead()
{
    qDebug() << "ready read";
    if(ecu == 0)
    {
        m_readData.append(m_serialport->readAll());
        Bytesexpected = m_readData[1]+1;
        qDebug() << "readdata current" <<m_readData.toHex();
        if (Bytesexpected == m_readData.size())
        {
            m_timer.stop();
            if(requestIndex <= 62){requestIndex++;}
            else{requestIndex = 59;}
            readData(m_readData);
            Serial::clear();
            m_readData.clear();
            Serial::sendRequest(requestIndex);
        }
        if (Bytesexpected != m_readData.size())
        {
            qDebug() << "starting timer";
            m_timer.start(5000);
        }
    }
于 2017-06-24T17:02:08.653 回答
2

很抱歉,我没有足够的时间来完成您的项目,并且根据您提供的代码,我无法 100% 确定原因是什么。不过,我最好的猜测是,在这种情况下,问题是您明确等待接收数据,并且事件处理以某种方式延迟或根本不发生。

无论如何,在这里你有几个建议:

  1. 使用QTimer代替QTime超时。
  2. 了解Qt5 的信号和插槽,并使用它们从串行端口异步读取。

我通过将QSerialPortbytesWritten(qint64 bytes)readyRead()信号连接到我的程序的插槽来使用 QSerialPort,比如说on_bytesWritten(qint64 bytes)on_readyRead()。然后我向目标设备发送请求,并在on_readyRead()插槽中处理结果。对于每个发送命令,我都会启动一个QTimer,其timeout()信号连接到on_timeout()我的应用程序的插槽。通过这种方式,我可以监控设备是否及时响应,并在数据到来时立即获取数据。您也可以使用QSerialPorterrorOccurred(QSerialPort::SerialPortError error)的信号来检查传输是否有问题。

于 2017-06-16T15:12:08.890 回答
1

这是我到目前为止所拥有的(只是发布了我的 cpp 文件的重要部分)这个代码现在几乎可以完美地与我的消息模拟器一起使用。它现在按预期进行轮询,但超时总是在 5 秒后触发(我需要将其更改为仅在没有消息发送时触发)。我只能在下周末的实际硬件上对其进行测试。这是我到目前为止所拥有的:

    void Serial::initSerialPort()
    {
    if (m_serialport)
        delete m_serialport;
    m_serialport = new SerialPort(this);
    connect(this->m_serialport,SIGNAL(readyRead()),this,SLOT(readyToRead()));
    connect(m_serialport, static_cast<void (QSerialPort::*)    (QSerialPort::SerialPortError)>(&QSerialPort::error),
            this, &Serial::handleError);
    connect(&m_timer, &QTimer::timeout, this, &Serial::handleTimeout);
     m_timer.start(5000);


    }

    void Serial::readyToRead() 
    {
    if(ecu == 0)
    {

        m_readData.append(m_serialport->readAll());
        Bytesexpected = m_readData[1]+1;
        if (Bytesexpected == m_readData.size())
        {
            if(requestIndex <= 62){requestIndex++;}
            else{requestIndex = 59;}
            readData(m_readData); // message for processing
            Serial::clear();
            m_readData.clear();
        }
    //Timeout
        if (!m_timer.isActive())
            m_timer.start(5000);

}
}

     void Serial::handleTimeout()
    {
    qDebug() << "Timeout";
    //request Data Again
    QString fileName = "Errors.txt";
    QFile mFile(fileName);
    if(!mFile.open(QFile::Append | QFile::Text)){
        qDebug() << "Could not open file for writing";
    }
    QTextStream out(&mFile);
    out << "Timeout Request Index " << int(requestIndex)<< " lenght received  "<< int(m_readData.length())<< " Bytes "<< " Expected Bytes "<< int(Bytesexpected)<< " bytes " <<" Message "<< QByteArray(m_readData.toHex()) <<endl;
    mFile.close();
    Serial::clear();
    m_readData.clear();
    Serial::sendRequest(requestIndex);
    }

    void Serial::handleError(QSerialPort::SerialPortError serialPortError)
    {
    if (serialPortError == QSerialPort::ReadError) {
        QString fileName = "Errors.txt";
        QFile mFile(fileName);
        if(!mFile.open(QFile::Append | QFile::Text)){
            qDebug() << "Could not open file for writing";
        }
        QTextStream out(&mFile);
        out << "Serial Error " << (m_serialport->errorString()) <<endl;
        mFile.close();
        qDebug() <<"Serialport Error" <<(m_serialport->errorString());
    }
    }
于 2017-06-23T07:54:35.610 回答