本帖最后由 w494143467 于 2021-3-11 09:09 编辑
1.介绍
上一篇说明了Demo的设计方案,今天这一篇就专门来写一个上位机,主要分为数据显示和数据通信部分,同时通过波形图显示出当时的速度,同时还需要设计一下与下位机的通信协议,这个只做一个简单的设计,因为通信的内容不多,所以采用简单的方案。
2.界面设计
对电机的主要设计四个按钮【开始】、【停止】、【正转】和【反转】,同时有一个滑杆用于控制速度,速度波形图采用QWT插件中的【QwtPlot】控件,如下图1所示。
图1
界面设计完成如下图2所示。
图2
这里创建一个类来对串口进行扫描,这样就可以动态的选择插入的串口设备了,代码如下所示。
//默认构造
SerialPortList::SerialPortList()
{
timer = new QTimer;
scanCycleMs = 1000;
oldPortStringList.clear();
connect(timer, SIGNAL(timeout()), this, SLOT(onTimeOut()));
}
//自定义扫描周期构造
SerialPortList::SerialPortList(quint16 CycleMs)
{
timer = new QTimer;
scanCycleMs = CycleMs;
oldPortStringList.clear();
connect(timer, SIGNAL(timeout()), this, SLOT(onTimeOut()));
}
SerialPortList::~SerialPortList()
{
delete timer;
}
//开始扫描
void SerialPortList::ScanStart()
{
timer->stop();
timer->start(scanCycleMs);
}
//停止扫描
void SerialPortList::ScanStop(){
timer->stop();
}
//周期扫描服务
void SerialPortList::onTimeOut(){
QStringList newPortStringList;
//搜索串口
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()){
#if DEBUG_INFOR_EN
qDebug() << "Name : " << info.portName();
qDebug() << "Description : " << info.description();
qDebug() << "Manufacturer: " << info.manufacturer();
#endif
newPortStringList += info.portName();
}
//更新旧的串口列表
if(newPortStringList.size() != oldPortStringList.size())
{
oldPortStringList = newPortStringList;
emit onNewSerialPort(oldPortStringList);
}
}
然后创建自定义的串口扫描类,再添加上串口通信对象,同时绑定串口接收信号槽,最后设置一下波形图的上下限,初始化代码如下所示。
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
serial = new QSerialPort; //声明对象
curve = new QwtPlotCurve();
portList = new SerialPortList(200); //创建串口数据
QObject::connect(portList, SIGNAL(onNewSerialPort(QStringList)), this, SLOT(onNewPortList(QStringList)));
QObject::connect(serial,SIGNAL(readyRead()), this, SLOT(SerialReadData()),Qt::UniqueConnection); //绑定串口接收服务信号槽
ui->qwtPlot->setAxisScale(QwtPlot::xBottom, 0, 100);
ui->qwtPlot->setAxisScale(QwtPlot::yLeft, 0, 100);
portList->ScanStart(); //开始串口扫描
}
最后实现按钮发送字符串,接收串口过来的数据即可,接收的处理函数如下所示。
/*
0~100:速度
255:反转
254:正转
253:停止
252:开始
*/
void MainWindow::SerialReadData()
{
QByteArray readArray = serial->readAll();
quint8 readInt = quint8(readArray.at(0));
if(readInt <= 100) //小于100是速度
{
ui->lblMotorSpeed->setText(QString::number(readInt, 10) + "km/h");
xdata.append(xdata.size()+1);
ydata.append(readInt);
curve->setSamples(xdata,ydata);
curve->attach(ui->qwtPlot);
ui->qwtPlot->replot();
}
else if(readInt == 252)
{
ui->lblMotorState->setText("开始");
}
else if(readInt == 253)
{
ui->lblMotorState->setText("停止");
}
else if(readInt == 254)
{
ui->lblMotorDirection->setText("正转");
}
else if(readInt == 255)
{
ui->lblMotorDirection->setText("反转");
}
}
发送的就根据协议进行发送即可,运行后的界面如下图3所示。
图3
接收一定数据后的波形图如下图4和图5所示。
图4 图5
3.总结
上位机基本可以说是完成了,就剩下位机的程序+联调了,上位机设计还是比较简单的,如果设计好了,给大家录一个视频看看,分享一下上位机的程序,不过需要安装QWT插件,大家自行百度哈,如果真的需要安装教程,我后面出一个,希望大家能够继续支持我哈!
下位机程序:
|