前几天分享了一个使用C#开发的串口上位机,那么今天教你如何100行QT代码实现一个串口上位机。如果你学习过C ,那么使用QT开发软件,就不是什么大问题了,QT很多时候使用在linux上。所以使用QT开发还是挺不过的选择,QT兼容Linux和Windows,跨平台语言。话不多说,接下来说说他是怎么实现的。首先直接上软件效果图(温馨提示:代码没写完,哪有脸睡觉)。
源代码我放在我的github上:
git@github.com:RiceChen/SerialDemo.git
这个分享的软件也是实现基本功能,大家可以在这个基础上扩展自己想要的功能。
第一步,确定自己的需求,然后设计自己梦寐以求&华丽的UI。QT 的UI也是很容易设计的,通过拖拉控件即可。这是QT的控件栏,要什么控件就拖拉什么控件。
第二步,实现功能。这个串口软件我使用别人的API来实现,需要三个源文件(win_qextserialport.cpp/qextserialport.cpp/qextserialbase.cpp)和三个头文件(win_qextserialport.h/qextserialport.h/qextserialbase.h)
① 头文件(mainwindow.h)内容:通过Win_QextSerialPort定义串口对象myCom,定义一个串口是否打开标志,然后定义读数据信号槽函数readMyCom(),打开or关闭串口按键信号槽函数openOrCloseBtn(),发送数据按键信号槽函数sendMsgBtn()。
代码语言:javascript复制class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
Win_QextSerialPort *myCom; //声明对象
bool flag;
private slots:
void readMyCom();
void openOrCloseBtn();
void sendMsgBtn();
};
① 源文件(mainwindow.cpp)内容:
1、构造函数的实现:通过API函数setWindowTitle()设置软件的标题,通过函数connect()连接按键信号,与信号槽函数的关联。
代码语言:javascript复制MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
setWindowTitle(tr("QT Serial-<Rice DIY> Wechat:wueroo1314"));
ui->radioButton->setEnabled(false);
connect(ui->pushButton_2,SIGNAL(clicked(bool)),this,SLOT(openOrCloseBtn()));
//信号和槽函数关联,当按键按下时,进行串口打开关闭操作
connect(ui->pushButton,SIGNAL(clicked(bool)),this,SLOT(sendMsgBtn()));
//信号和槽函数关联,当按键按下时,进行数据发送操作
flag=false;
}
2、析构函数的实现:直接把窗体给杀了就可以。
代码语言:javascript复制MainWindow::~MainWindow()
{
delete ui;
}
3、打开or关闭信号槽函数的实现:如果是打开串口:首先获取UI上的串口号,然后实例化串口对象myCom,然后通过API函数open()打开串口,比设置为可读可写。然后设置串口参数。
其中:波特率设置API函数:setBaudRate();
校验位设置API函数:setParity();
数据位设置API函数:setDataBits();
停止位设置API函数:setStopBits();
数据流控制设置API函数:setFlowControl();
这个Demo串口定时器的方式读取串口数据,通过setTimeout()设置定时器时间,通过connect()连接串口读信号与读数据槽函数。
如果是关闭串口:通过API函数close()关闭串口。
代码语言:javascript复制void MainWindow::openOrCloseBtn()
{
if(flag==false)
{
QString portName=ui->comboBox->currentText();
myCom=new Win_QextSerialPort(portName,QextSerialBase::EventDriven);
myCom->open(QIODevice::ReadWrite);
//设置波特率
if(ui->comboBox_2->currentText()==tr("9600"))
myCom->setBaudRate(BAUD9600);
else if(ui->comboBox_2->currentText()==tr("115200"))
myCom->setBaudRate(BAUD115200);
//设置奇偶校验位
if(ui->comboBox_3->currentText()==QStringLiteral("无"))
myCom->setParity(PAR_NONE);
else if(ui->comboBox_3->currentText()==QStringLiteral("奇"))
myCom->setParity(PAR_ODD);
else if(ui->comboBox_3->currentText()==QStringLiteral("偶"))
myCom->setParity(PAR_EVEN);
//设置数据位
if(ui->comboBox_4->currentText()==tr("8"))
myCom->setDataBits(DATA_8);
else if(ui->comboBox_4->currentText()==tr("7"))
myCom->setDataBits(DATA_7);
//设置停止位
if(ui->comboBox_5->currentText()==tr("1"))
myCom->setStopBits(STOP_1);
else if(ui->comboBox_5->currentText()==tr("2"))
myCom->setStopBits(STOP_2);
myCom->setFlowControl(FLOW_OFF);//设置数据流控制,我们使用无数据流控制的默认设置
myCom->setTimeout(500); //设置延时
connect(myCom,SIGNAL(readyRead()),this,SLOT(readMyCom()));
//信号和槽函数关联,当串口缓冲区有数据时,进行读串口操作
ui->pushButton_2->setText(tr("关闭串口"));
ui->radioButton->setChecked(true);
ui->comboBox->setEnabled(false);
ui->comboBox_2->setEnabled(false);
ui->comboBox_3->setEnabled(false);
ui->comboBox_4->setEnabled(false);
ui->comboBox_5->setEnabled(false);
flag=true;
}
else
{
myCom->close();
ui->pushButton_2->setText(tr("打开串口"));
ui->radioButton->setChecked(false);
ui->comboBox->setEnabled(true);
ui->comboBox_2->setEnabled(true);
ui->comboBox_3->setEnabled(true);
ui->comboBox_4->setEnabled(true);
ui->comboBox_5->setEnabled(true);
flag=false;
}
}
4、读串口信号槽函数的实现:通过调取API函数readAll()去读串口的数据。然后将其数据设置到UI的receive控件上
代码语言:javascript复制//读串口
void MainWindow::readMyCom()
{
QByteArray temp = myCom->readAll();
ui->textBrowser->insertPlainText(temp);
}
5、发送信号槽函数的实现:通过调取API函数write()将发送控件的内容通过串口发送出去。
代码语言:javascript复制//写串口
void MainWindow::sendMsgBtn()
{
myCom->write(ui->lineEdit->text().toLatin1());
}
第三步,软件测试:下位机采用stm32通过串口发数据到上位机。演示如下: