Qt5:串口signal-slots机制信号连接错槽

Posted

技术标签:

【中文标题】Qt5:串口signal-slots机制信号连接错槽【英文标题】:Qt5: serial port signal-slots mechanism signal connect to the wrong slot 【发布时间】:2015-08-21 08:10:08 【问题描述】:

我对 qt 信号槽感到困惑。我使用了以下连接,但它连接到另一个插槽。

 void MainWindow::on_otpburndata1Btn_Rd_clicked()

    if(serialPort->clear(serialPort->AllDirections))
        QByteArray otpburndata1ord;
        otpburndata1ord.resize(3);
        otpburndata1ord[2]=0x02;
        otpburndata1ord[1]=0x08;
        otpburndata1ord[0]=0x1D;
        serialPort->write(otpburndata1ord.data(),3);
        connect(serialPort,SIGNAL(readyRead()),this,SLOT(receiveOtpBurnData1()));
    


void MainWindow::receiveOtpBurnData1()
    QByteArray otpburndata1;
    otpburndata1.resize(1);
    if(serialPort->bytesAvailable()==1)
    otpburndata1 = serialPort->readAll();
    if(otpburndata1[0]&0x01)
        ui->OTP_DATA0->setStyleSheet("background-color:red");
        ui->OTP_DATA0->setText("1");
        flagThree[0]=1;
    else
        ui->OTP_DATA0->setStyleSheet("background-color:rgb(170, 255, 127)");
        ui->OTP_DATA0->setText("0");
        flagThree[0]=0;
    
    ...
    ...
    ...
  

因为我在这个 on_otpburndata1Btn_Rd_clicked() 函数之前使用了另一个函数。当我单击按钮:otpburndata1Btn_Rd 时,它从端口读取数据,但连接到另一个插槽 otprddata1Received(),而不是正确的插槽 receiveOtpBurnData1()。之前的代码如下:

     void MainWindow::on_otprddata1Btn_clicked()

    if(serialPort->clear(serialPort->AllDirections))
        QByteArray otprdata1ord;
        otprdata1ord.resize(3);
        otprdata1ord[0]=0x9D;
        otprdata1ord[1]=0x00;
        otprdata1ord[2]=0x02;
        serialPort->write(otprdata1ord.data(),3);
        connect(serialPort,SIGNAL(readyRead()),this,SLOT(otprddata1Received()));
    


void MainWindow::otprddata1Received()
    QByteArray  otprdata1;
    otprdata1.resize(1);
    if(serialPort->bytesAvailable()==1)
        otprdata1 = serialPort->readAll();
        if(otprdata1[0]&0x01)
            ui->OTP_RD_DATA0->setStyleSheet("background-color:red");
            ui->OTP_RD_DATA0->setText("1");
        else
            ui->OTP_RD_DATA0->setStyleSheet("background-color:rgb(170, 255, 127)");
            ui->OTP_RD_DATA0->setText("0");
        
        ....

【问题讨论】:

在connect中改变slot后,你是否重新生成了moc文件? moc_MainWindow::qt_static_metacall 是什么样的? 您是否尝试过干净重建(删除构建目录)?我认为,您在每次点击 otpburndata1Btn_Rd 按钮时都会创建一个信号槽连接。为什么那里需要信号连接? 右键单击项目并清理,然后右键单击项目并运行 qmake,然后构建所有内容,作为一般建议,我认为最好在开始发送数据之前连接插槽 我重读了readyRead()的细节,它说当有新数据可供读取时,它会发出信号readyRead()。我认为问题就在这里。我需要,当点击不同的阅读按钮时,它会显示在不同的分组框上。 【参考方案1】:

我通过为每个数据添加额外的 2 个字节来区分单击了哪个按钮以及在哪里显示接收到的数据,从而解决了这个问题。这样区分每个数据是正确的。例如,如果 GUI 将从串口接收 1 个字节的数据,我添加另外 2 个字节用于区分(当然 1 个字节也可以)。代码如下:

    void MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)


....

 connect(this,SIGNAL(readyReadotprddata1()),this,SLOT(otprddata1Received()));
    connect(this,SIGNAL(readyReadotprddata2()),this,SLOT(otprddata2Received()));
    connect(this,SIGNAL(readyReadotprddata3()),this,SLOT(otprddata3Received()));
    connect(this,SIGNAL(readyReadotpburndata1()),this,SLOT(receiveOtpBurnData1()));
    connect(this,SIGNAL(readyReadotpburndata2()),this,SLOT(receiveOtpBurnData2()));
    connect(this,SIGNAL(readyReadotpburndata3()),this,SLOT(receiveOtpBurnData3()));
    connect(this,SIGNAL(readyReadotpctrlreg1()),this,SLOT(receiveOtpctrlReg1()));
    connect(this,SIGNAL(readyReadotpctrlreg2()),this,SLOT(receiveOtpctrlReg2()));
    connect(this,SIGNAL(readyReadsiliconid()),this,SLOT(receiveSiliconidDataord()));



    void MainWindow::on_otprddata1Btn_clicked()

    if(serialPort->clear(serialPort->AllDirections))
        QByteArray otprdata1ord;
        otprdata1ord.resize(3);
        otprdata1ord[0]=0x9D;
        otprdata1ord[1]=0x00;
        otprdata1ord[2]=0x02;
        serialPort->write(otprdata1ord.data(),3);
        connect(serialPort,SIGNAL(readyRead()),this,SLOT(commonDistinct()));
    


....

    void MainWindow::commonDistinct()
    if(serialPort->bytesAvailable()==3)
        data=serialPort->readAll();
        if(data[0].operator ==(0x9D) && data[1].operator ==(0x00)) emit readyReadotprddata1();
        else if(data[0].operator ==(0xBD) && data[1].operator ==(0x00)) emit readyReadotprddata2();
        else if(data[0].operator ==(0xDD) && data[1].operator ==(0x00)) emit readyReadotprddata3();
        else if(data[0].operator ==(0x1D) && data[1].operator ==(0x08)) emit readyReadotpburndata1();
        else if(data[0].operator ==(0x1D) && data[1].operator ==(0x04)) emit readyReadotpburndata2();
        else if(data[0].operator ==(0x3D) && data[1].operator ==(0x04))emit readyReadotpburndata3();
        else if(data[0].operator ==(0x1D) && data[1].operator ==(0x02))emit readyReadotpctrlreg1();
        else if(data[0].operator ==(0x1D) && data[1].operator ==(0x01))emit readyReadotpctrlreg2();
        else if(data[0].operator ==(0x5D) && data[1].operator ==(0x00))emit readyReadsiliconid();
    



void MainWindow::otprddata1Received()
        if(data[2]&0x01)
            ui->OTP_RD_DATA0->setStyleSheet("background-color:red");
            ui->OTP_RD_DATA0->setText("1");
        else
            ui->OTP_RD_DATA0->setStyleSheet("background-color:rgb(170, 255, 127)");
            ui->OTP_RD_DATA0->setText("0");
        
....


我使用这个答案的原因是,每当串口接收到数据时,都会发出 Qt5 信号 readyRead() 。我所有需要的数据都是 1 个字节。我不能使用 bytesAvailable() 函数来区分接收到的数据。

【讨论】:

以上是关于Qt5:串口signal-slots机制信号连接错槽的主要内容,如果未能解决你的问题,请参考以下文章

QT 5.10.1 串口不发送,为啥?

Qt5 UI信号槽自动连接的控件重名大坑(UI生成的槽函数存在一个隐患,即控件重名。对很复杂的控件,不要在 designer 里做提升,而是等到程序启动后,再动态创建,可以避免很多问题)

QT5.12.5 串口接收不了数据

QT5.12.5 串口接收不了数据

QT5.12.5 串口接受不了数据

QT5 连接信号到功能