基于STM32F407的bootloader、IAP、Flash_APP、上位机设计(三)

基于STM32F407的bootloader、IAP、Flash_APP、上位机设计

第三部分:上位机软件设计

前期准备:

一、硬件:STM32F407VET6板一块,IAP使用串口通信,板上需引出串口或有DB9接口都行(如果不使用串口,使用其他协议均可)。

二、软件:KEIL4.73版本,关于IAP读写FLASH的源代码是使用战舰的源码,共有iap、stmflash、sys等文件,上位机软件设计使用QT5.5。

工作开始:

一、界面设计:

基于STM32F407的bootloader、IAP、Flash_APP、上位机设计(三)_第1张图片

二、串口基本配置如下

void MainWindow::SerialViewConfig()
{
    ui->stackedWidget->setCurrentIndex(0);
    //QString Green = QString("green.png");
    QString Gray = QString("gray.png");
    QPixmap Com_map;
    Com_map.load(Gray);
    ui->com_img->setPixmap(Com_map);
    u_ViewIndex=view1;
    m_Com = new QSerialPort;
    ui->open_serial->setText("Open");
    m_serial.Status=Open;
    foreach (const QSerialPortInfo &info,QSerialPortInfo::availablePorts())
    {
        QSerialPort serial;
        serial.setPort(info);
        if(serial.open(QIODevice::ReadWrite))
        {
            ui->ComName->addItem(serial.portName());
            serial.close();
        }
    }
    ui->ComBaud->addItem("4800");
    ui->ComBaud->addItem("9600");
    ui->ComBaud->addItem("19200");
    ui->ComBaud->addItem("38400");
    ui->ComBaud->addItem("57600");
    ui->ComBaud->addItem("115200");
    ui->ComParity->addItem("None");
    ui->ComParity->addItem("Even");
    ui->ComParity->addItem("Odd");
    ui->ComDatabits->addItem("8");
    ui->ComDatabits->addItem("7");
    ui->ComDatabits->addItem("6");
    ui->ComDatabits->addItem("5");
    ui->ComStopBits->addItem("1");
    ui->ComStopBits->addItem("2");
    ui->open_file->setDisabled(true);
}

void MainWindow::ReadSerialConfig()
{
    QFile serial_file("SerialConfig.txt");


    QStringList strList,strData;
    QString str;
    if(!serial_file.exists())
    {
        qDebug()<<"read failed";
        if(!serial_file.open(QIODevice::ReadWrite))
        {
            qDebug()<<"creat failed";


        }
        else
        {
            qDebug()<<"creat success";
            QString W_Serial="ComBaud:0,ComParity:0,ComDatabits:0,ComStopBits:0";
            serial_file.write(W_Serial.toLatin1(),W_Serial.length());
        }
    }
    else
    {
        qDebug()<<"read  file success";
        if(serial_file.open(QIODevice::ReadOnly))
        {
            qDebug()<<"read success";
            QTextStream stream(&serial_file);
             QString Data = stream.readLine();
            if(Data.contains("ComBaud"))
            {
                strList = Data.split(QRegExp(","));
                for(int i=0 ;i < strList.size() ;i++)
                {
                    if(strList.at(i).contains("ComBaud"))
                    {
                        strData=strList.at(i).split(QRegExp(":"));
                        str=strData.at(1);
                        ui->ComBaud->setCurrentIndex(str.toInt()) ;
                    }
                    if(strList.at(i).contains("ComParity"))
                    {
                        strData=strList.at(i).split(QRegExp(":"));
                        str=strData.at(1);
                        ui->ComParity->setCurrentIndex(str.toInt()) ;
                    }
                    if(strList.at(i).contains("ComDatabits"))
                    {
                        strData=strList.at(i).split(QRegExp(":"));
                        str=strData.at(1);
                        ui->ComDatabits->setCurrentIndex(str.toInt()) ;
                    }
                    if(strList.at(i).contains("ComStopBits"))
                    {
                        strData=strList.at(i).split(QRegExp(":"));
                        str=strData.at(1);
                        ui->ComStopBits->setCurrentIndex(str.toInt()) ;
                    }
                    if(strList.at(i).contains("Path"))
                    {
                        strData=strList.at(i).split(QRegExp("-"));
                        FilePathSave=strData.at(1);
                        qDebug()<

这部分做了配置保存,保存到SerialConfig.txt文件中。

三、打开串口按键

void MainWindow::on_open_serial_clicked()
{
    QString Green = QString("green.png");
    QString Gray = QString("gray.png");
    QPixmap Com_map;

    if(m_serial.Status==Open)
    {
        m_Com->setPortName(ui->ComName->currentText());
        m_serial.Baud=ui->ComBaud->currentIndex();
        switch( m_serial.Baud)
        {

            case 0:m_Com->setBaudRate(QSerialPort::Baud4800);break;
            case 1:m_Com->setBaudRate(QSerialPort::Baud9600);break;
            case 2:m_Com->setBaudRate(QSerialPort::Baud19200);break;
            case 3:m_Com->setBaudRate(QSerialPort::Baud38400);break;
            case 4:m_Com->setBaudRate(QSerialPort::Baud57600);break;
            case 5:m_Com->setBaudRate(QSerialPort::Baud115200);break;
            default :m_Com->setBaudRate(QSerialPort::Baud115200);break;
        }
        m_serial.Databits=ui->ComDatabits->currentIndex();
        switch( m_serial.Databits)
        {
            case 0:m_Com->setDataBits(QSerialPort::Data8);break;
            case 1:m_Com->setDataBits(QSerialPort::Data7);break;
            case 2:m_Com->setDataBits(QSerialPort::Data6);break;
            case 3:m_Com->setDataBits(QSerialPort::Data5);break;
            default :m_Com->setDataBits(QSerialPort::Data8);break;
        }
        m_serial.Parity=ui->ComParity->currentIndex();
        switch(m_serial.Parity)
        {

            case 0:m_Com->setParity(QSerialPort::NoParity);break;
            case 1:m_Com->setParity(QSerialPort::EvenParity);break;
            case 2:m_Com->setParity(QSerialPort::OddParity);break;
            default :m_Com->setParity(QSerialPort::NoParity);break;
        }
        m_serial.Stop=ui->ComStopBits->currentIndex();
        switch( m_serial.Stop)
        {

            case 0:m_Com->setStopBits(QSerialPort::OneStop);break;
            case 1:m_Com->setStopBits(QSerialPort::TwoStop);break;
            default :m_Com->setStopBits(QSerialPort::OneStop);break;
        }
        m_Com->setFlowControl(QSerialPort::NoFlowControl);
        if(m_Com->open(QIODevice::ReadWrite)==true)
        {
            ui->open_serial->setText("Close");
            ui->pushButton_5->setDisabled(true);
            ui->open_file->setEnabled(true);
            connect(m_Com,SIGNAL(readyRead()),this,SLOT(Serial_Read()));
            ui->ComBaud->setDisabled(true);
            ui->ComDatabits->setDisabled(true);
            ui->ComName->setDisabled(true);
            ui->ComParity->setDisabled(true);
            ui->ComStopBits->setDisabled(true);
            QFile serial_file("SerialConfig.txt");
            Com_map.load(Green);
            statusBar()->showMessage("open success");
            if(serial_file.exists())
            {
                qDebug()<<"file was found";
                if(!serial_file.open(QIODevice::ReadWrite))
                {
                    qDebug()<<"open file failed";
                }
                else
                {
                    QString W_Serial="ComBaud:"+QString::number(m_serial.Baud,10)+",ComParity:"+QString::number(m_serial.Parity,10)+",ComDatabits:"+QString::number(m_serial.Databits,10)+",ComStopBits:"+QString::number(m_serial.Status,10)+",Path-"+FilePathSave;
                    serial_file.write(W_Serial.toLatin1(),W_Serial.length());
                }
            }

        }
        else QMessageBox::warning(this,"open failed","com is be used");

    }
    else  if(m_serial.Status==Close)
    {
        ui->open_serial->setText("Open");
        ui->pushButton_5->setEnabled(true);
        ui->open_file->setDisabled(true);
        ui->ComBaud->setEnabled(true);
        ui->ComDatabits->setEnabled(true);
        ui->ComName->setEnabled(true);
        ui->ComParity->setEnabled(true);
        ui->ComStopBits->setEnabled(true);
        disconnect(m_Com,&QSerialPort::readyRead,this,&MainWindow::Serial_Read);
        m_Com->close();
        statusBar()->showMessage("close success");
        Com_map.load(Gray);
    }
    ui->com_img->setPixmap(Com_map);
    m_serial.Status=!m_serial.Status;
}

四、打开Bin文件并保存到缓存

void MainWindow::on_open_file_clicked()
{
    int binSize;
    QString     Empty="                                                                                    ";
    QStringList FileList;
    QFile serial_file("SerialConfig.txt");
    QString  fileName = QFileDialog::getOpenFileName(this,"Open File",FilePathSave, QString::fromLocal8Bit("bin File(*.bin)"));

        FileList=fileName.split(QRegExp("/"));

        if(fileName.size()<2)
            ui->statusBar->showMessage(tr("打开文件错误"));
        else
        {
            FilePathSave.clear();
             for(int i =0;ifilePathLineEdit->setText (fileName);
        if(fileName.isEmpty())
        {
            QMessageBox::information(this,"Error Message", "Please Select a Text File");
            return;
        }
        QFileInfo *pcsfileInfo = new QFileInfo(fileName);
        binSize = pcsfileInfo->size ();

        QFile* file = new QFile;
        file->setFileName(fileName);
        bool ok = file->open(QIODevice::ReadOnly);
        if(ok)
        {
            delete tempByte;
    //        QTextStream in(file);
    //        ui->textEdit->setText(in.readAll());//read all context from the file
        }
        else
        {
            QMessageBox::information(this,"Error Message", "File Open Error" + file->errorString());
            return;
        }
        QDataStream in(file);
        char * binByte = new char[binSize];
        in.setVersion (QDataStream::Qt_5_5);

        ui->statusBar->showMessage(tr("准备读取数据"));
        in.readRawData (binByte, binSize);      //读出文件到缓存
        ui->statusBar->showMessage(tr("读取数据完毕"));

        tempByte = new QByteArray(binByte, binSize);                //格式转换
        //DownloadData = tempByte->data();

        QString *tempStr = new QString(tempByte->toHex ().toUpper ());

        //显示文件内容

        for(qint64 i = 2; i < tempStr->size ();)
        {
            tempStr->insert (i, ' ');//每个字节之间空一格
            i += 3;
        }
        ui->statusBar->showMessage(tr("准备显示"));
        ui->fileViewPlainTextEdit->insertPlainText (*tempStr);
        ui->statusBar->showMessage(tr("显示完毕"));
        DownLoadLen  = tempByte->size();
        ui->filePathLineEdit->append(QString::number(DownLoadLen,10));
        RcvProcess.UartRead.DownLoadAllPacket=DownLoadLen/100;
        RcvProcess.UartRead.DownLoadLastPack=DownLoadLen%100;
    //    timer->start(1000);
    //    serial->write(binByte,25);
//        delete tempByte;
        delete[] binByte;
        delete tempStr;

        file->close ();
        delete file;

}

五、开始下载

void MainWindow::on_DownLoad_clicked()
{
    uint8_t res[2],i=0;
    res[0]=Uart_DeviceGetDownStatus;

    if(DownLoadLen>0)
        TraProtocol(Uart_DeviceGetDownStatus,0,1,res);
    else
        ui->statusBar->showMessage(tr("下载失败,文件错误"));
    //m_Com->write(DownloadData,DownLoadLen);
}

六、协议情况

    开始下载的时候是发一条得到状态命令,待返回成功之后,得到该命令返回时发送下载命令。

uint8_t MainWindow::RcvPotocol(uint8_t CMD ,uint8_t PackNum ,uint8_t len ,uint8_t *Msg)
{
    uint8_t res[5];

    switch(CMD)
    {

            case Uart_DeviceAdress:
                        RcvProcess.UartRead.DeviceAdress=Msg[0];
                        //qDebug()<<"RcvProcess.UartRead.DeviceAdress"<statusBar->showMessage(tr("准备下载"));
                        emit DownLoad();
                     }

                break;
            case Uart_DeviceDownLoad:
                    if(RcvProcess.UartRead.DeviceGetDownStatus==Uart_DeviceGetDownStatus)
                    {
                        qDebug()<at((RcvProcess.UartRead.DownLoadPacketNum*100)+i);
                                TraProtocol(Uart_DeviceDownLoad,RcvProcess.UartRead.DownLoadPacketNum,DownOncePacket,(uint8_t*)data);
                                ui->progressBar->setValue(Per);
                            }
                            else if(RcvProcess.UartRead.DownLoadPacketNum==(RcvProcess.UartRead.DownLoadAllPacket))
                            {
                                for(i=0;iat((RcvProcess.UartRead.DownLoadPacketNum*100)+i);
                                TraProtocol(Uart_DeviceDownLoad,RcvProcess.UartRead.DownLoadPacketNum,RcvProcess.UartRead.DownLoadLastPack,(uint8_t*)data);
                                ui->progressBar->setValue(Per+(RcvProcess.UartRead.DownLoadLastPack*100.0/DownLoadLen));
                                qDebug()<<"finish";
                            }
                            else if(RcvProcess.UartRead.DownLoadPacketNum>(RcvProcess.UartRead.DownLoadAllPacket))
                            {
                               res[0]=0xaa;
                               TraProtocol(CMD+1,PackNum,1,res);
                            }


                        }
                        else
                        {

                        }
                    }
                //
                break;
            case Uart_DeviceDownLoadSts:
                    RcvProcess.UartRead.DeviceGetDownStatus=Msg[0];
                    if(RcvProcess.UartRead.DeviceGetDownStatus==Uart_DeviceDownLoadSts)
                     {
                        ui->progressBar->setValue(100);
                        ui->progressBar->setStyleSheet("QProgressBar::chunk { background-color: rgb(0, 255, 0) }");
                        Uart_DeviceGetDownStatus,RcvProcess.UartRead.DownLoadPacketNum=0;

                        ui->statusBar->showMessage(tr("下载完毕"));

                     }
                    else
                    {
                        ui->progressBar->setValue(100);
                        ui->progressBar->setStyleSheet("QProgressBar::chunk { background-color: rgb(255, 0, 0) }");
                        Uart_DeviceGetDownStatus,RcvProcess.UartRead.DownLoadPacketNum=0;
                        ui->statusBar->showMessage(tr("下载失败"));
                    }

                break;

            default :
                res[0] =Err_Cmd;
                break;
            //TraProtocol(CMD,PackNum,1,res);
    }
    //qDebug()<

七、其它

下载完毕之后清空所以缓存,starbar显示下载完成,下载时还可以做一个超时处理,这里没有做,比如下载超过多少秒没有回应,则清除缓存,不下载之类的,都是可以自己再写的,最后再发张界面下载的图片,不能上传视频只有图片了。

基于STM32F407的bootloader、IAP、Flash_APP、上位机设计(三)_第2张图片

 

你可能感兴趣的:(Windows_Qt,STM32)