110VCGQ/文档说明/串口升级QT部分代码示例.md
2024-12-30 15:29:57 +08:00

6.3 KiB
Raw Permalink Blame History

//此处使用bin文件hex文件包含地址信息需要自己提取代码信息

QVector<QByteArray> groupedData;
//打开文件并分包
void MainWindow::on_OpenFile_Btn_clicked()
{
    groupedData.clear();
    QString curDir = QCoreApplication::applicationDirPath();
    *fileName  = QFileDialog::getOpenFileName(this,"选择一个txt文件",curDir,"*.bin");
    file->setFileName(*fileName);
    if(!file->open(QIODevice::ReadOnly))
    {
        QMessageBox::information(this,"提示","文件打开失败");
        return;
    }
    qint32 FileSize = file->size();
    ui->fileName_LEdit->setText(*fileName+"  "+QString::number(FileSize)+"byte");
    *fileData = file->readAll();
    if(fileData->size() != FileSize)
    {
        QMessageBox::information(this,"提示","文件读取失败");
        return;
    }

    const int groupSize = 128;
    for (int i = 0; i < FileSize; i += groupSize) {
        // 从 fileData 里截取 groupSize 大小的字节
        QByteArray chunk = fileData->mid(i, groupSize);

        // 如果截取的字节数不足 128则进行填充
        if (chunk.size() < groupSize) {
            chunk.append(QByteArray(groupSize - chunk.size(), static_cast<char>(0xFF)));
        }
        // 将分组后的数据添加到 QVector
        groupedData.append(chunk);
    }
    // 输出每组数据
    QString string;
    string = QString("文件分包成功每组128个数据共%1组").arg(groupedData.size());
    ui->SendFile_textEdit->append(string);//显示信息到文本框
}

//开始发送文件,发送起始段
void MainWindow::on_SenFile_Btn_clicked()
{
    QString byte;
    uint16_t crcValue;
    uint8_t b[137];
    state = sendFile;
    CurrentIndex = 0;  //数据段数复位

    if(!file->isOpen())
    {
        QMessageBox::warning(this,"提示","请选择一个bin文件");
        return;
    }
    qint32 FileSize = file->size();
    uint8_t cnt =0;
    if(ui->danbo_rBtn->isChecked())  //指定地址发送地址从ui控件获得
    {
        //指定地址发送有返回数据返回正确数据后CurrentIndex++,返回错误或超时,
        //CurrentIndex不变继续发送上一次数据
        start_addr = ui->start_spinBox->text().toInt();
        over_addr = ui->end_spinBox->text().toInt();
        current_addr = start_addr;
        b[cnt++]=current_addr;//485地址
    }
    else {
        //广播时地址为0 需要定时发送数据包建议每个数据包隔100ms以上
        b[cnt++]=0;//485地址
        time5->setInterval(300);
        time5->start();

    }
    b[cnt++]=0x10;                            //功能位
    b[cnt++]=CurrentIndex>>8;                 //寄存器起始地址
    b[cnt++]=CurrentIndex&0xFF;
    b[cnt++]=0;                              //寄存器个数
    b[cnt++]=1;
    b[cnt++]= 2;                            //字节数
    b[cnt++] = FileSize>>8;
    b[cnt++] = FileSize&0xFF;
    crcValue= crc->crc16_modbus(b,cnt);
    b[cnt++] = crcValue&0x00FF;
    b[cnt++] =crcValue>>8;


    for(int i=0;i<cnt;i++)
    {
        byte.append(QString("%1").arg(b[i],2,16,QLatin1Char('0')).toUpper());
        byte.append(" ");
    }

    if(port==NULL || !port->mSerialPort.isOpen())
    {
        QMessageBox::information(this,"","串口未打开或不存在");
    }
    else
    {
        ui->SendFile_textEdit->append(byte);
        port->mSerialPort.write((const char*)(b),cnt);

    }
}

//发送后续文件(发送代码数据)
void MainWindow::sendNextFile()
{
    QString byte;
    uint16_t crcValue;
    uint8_t b[150] ={0};
    state = sendFile;

    uint8_t cnt =0;
    if(ui->danbo_rBtn->isChecked())
    {
        b[cnt++]=current_addr;//485地址
        //打开定时器4
        time4->setInterval(300);
        time4->start();
    }
    else {
        b[cnt++]=0;//485地址
        CurrentIndex++;
    }
    if(CurrentIndex>groupedData.size())
    {
        on_overSend_Btn_clicked();//发送结束报文
        return;
    }

    b[cnt++]=0x10;                            //功能位
    b[cnt++]=CurrentIndex>>8;                 //寄存器起始地址
    b[cnt++]=CurrentIndex&0xFF;
    b[cnt++]=0;                              //寄存器个数
    b[cnt++]=64;
    b[cnt++]= 128;                            //字节数
    QByteArray datatosend = groupedData[CurrentIndex-1];
    std::memcpy(&b[cnt],datatosend.constData(),128);
    cnt = cnt+128;
    crcValue= crc->crc16_modbus(b,cnt);
    b[cnt++] = crcValue&0x00FF;
    b[cnt++] =crcValue>>8;


    for(int i=0;i<cnt;i++)
    {
        byte.append(QString("%1").arg(b[i],2,16,QLatin1Char('0')).toUpper());
        byte.append(" ");
    }

    if(port==NULL || !port->mSerialPort.isOpen())
    {
        QMessageBox::information(this,"","串口未打开或不存在");
    }
    else
    {
        ui->SendFile_textEdit->append(byte);
        port->mSerialPort.write((const char*)(b),cnt);
        ui->progressBar->setValue(CurrentIndex*100/groupedData.size());
    }
}

//发送结束报文
void MainWindow::on_overSend_Btn_clicked()
{
    QString byte;
    uint16_t crcValue;
    uint8_t b[137];
    state = sendFile;

    ui->progressBar->setValue(0);
    uint8_t cnt =0;
    if(ui->danbo_rBtn->isChecked())
    {
        start_addr = ui->start_spinBox->text().toInt();
        over_addr = ui->end_spinBox->text().toInt();
        current_addr = start_addr;
        b[cnt++]=current_addr;//485地址
    }
    else {
        b[cnt++]=0;//485地址
 //       CurrentIndex++;
    }
    b[cnt++]=0x10;                            //功能位
    b[cnt++]=0xFF;                              //寄存器起始地址
    b[cnt++]=0xFF;
    b[cnt++]=0;                              //寄存器个数
    b[cnt++]=1;
    b[cnt++]= 2;                            //字节数
    b[cnt++] = CurrentIndex>>8;
    b[cnt++] = CurrentIndex&0xFF;
    crcValue= crc->crc16_modbus(b,cnt);
    b[cnt++] = crcValue&0x00FF;
    b[cnt++] =crcValue>>8;


    for(int i=0;i<cnt;i++)
    {
        byte.append(QString("%1").arg(b[i],2,16,QLatin1Char('0')).toUpper());
        byte.append(" ");
    }

    if(port==NULL || !port->mSerialPort.isOpen())
    {
        QMessageBox::information(this,"","串口未打开或不存在");
    }
    else
    {
        ui->SendFile_textEdit->append(byte);
        port->mSerialPort.write((const char*)(b),cnt);
        //停止定时器44
        time4->stop();
        time5->stop();

    }
}