第三部分:上位机软件设计
前期准备:
一、硬件:STM32F407VET6板一块,IAP使用串口通信,板上需引出串口或有DB9接口都行(如果不使用串口,使用其他协议均可)。
二、软件:KEIL4.73版本,关于IAP读写FLASH的源代码是使用战舰的源码,共有iap、stmflash、sys等文件,上位机软件设计使用QT5.5。
工作开始:
一、界面设计:
二、串口基本配置如下
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显示下载完成,下载时还可以做一个超时处理,这里没有做,比如下载超过多少秒没有回应,则清除缓存,不下载之类的,都是可以自己再写的,最后再发张界面下载的图片,不能上传视频只有图片了。