Search code examples
c++qtsignals-slots

Qt5: serial port signal-slots mechanism signal connect to the wrong slot


I was confused about qt signal-slot. I used the following connect, but it connect to another slot.

 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;
    }
    ...
    ...
    ...
  }
}

As I used another function before this on_otpburndata1Btn_Rd_clicked() function. When I clicked the Button:otpburndata1Btn_Rd, it read the data from the port,but connect to another slot otprddata1Received(), not the right slot receiveOtpBurnData1(). The prior code is as following:

     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");
        }
        ....
}

Solution

  • I have solved the problem by adding an extra 2bytes for each data to distinct which button has been clicked and where to show the received data. So that it will be correct to distinct each data. For example, if the GUI will receive 1 byte data from serial port, I add another 2 bytes for distincting(of course 1byte is also ok). The code is as following:

        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");
            }
    ....
    
    }
    

    Why I used this answer is that, the Qt5 signal readyRead() will be emitted every time whenever there are data received by serial port. And all my need data are all 1 byte. I cannot use the bytesAvailable() func to distinct the received data.