以前使用VB做串口上位机,现在试用QT来做,顺便学习一下,入个门。看看有多大区别。
QT上编程用的是C++,所以Class(类)的概念(公有、私有、继承、多态、构造、析构、重载这些名词)一定要搞明白。 QT专有的信号和槽的概念。
开发用的是开源的QT Creator,具体下载,安装方法可以上B站看看大牛们的讲解。界面和使用方法,新建一个工程的方法,同样也可以看B站。
串口编程在VB中使用comm控件。在现在的这个QT版本中没有这个comm控件。不过可以使用两个类来完成同样的工作。
在MainWindow 的类定义中,私有成员增加QSerialPort *serial;
记得一定要在MainWindow的构造函数中对serial进行实例化。也就是需要让serial指向的一个实体,用于操作。
serial = new QSerialPort; //new的作用相当于malloc,分配一个实体QSerialPort需要的内存。
严格的说,在析构函数中应该 delete serial; 以释放内存。
第一次编程时,没有实例化serial,空指针操作serial,结果程序一运行就崩溃退出。
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
const auto infos = QSerialPortInfo::availablePorts();
for(const QSerialPortInfo &info : infos){
ui->cbCom->addItem(info.portName());
}
serial = new QSerialPort; //实例化 serial
connect(serial, &QSerialPort::readyRead, this, &MainWindow::readData);
}
在连接用的按键点击可以打开或关闭串口了。方法是判断按键上的文字。神奇的是,经常用的strcmp不存在,不过可以这样用:
if(ui->pbConnect->text() == QString("连接")) 直接判断字符串相等,不比strcmp香么?判断字符串相等肯定还是得一个字节一个字节比较。我想这个QString类一定把 “ == ” 做了重载(新定义了 == 作为字符串比较的运算符)。
void MainWindow::on_pbConnect_clicked()
{
if(ui->pbConnect->text()==QString("连接")){
serial->setPortName(ui->cbCom->currentText());
serial->setBaudRate(QSerialPort::Baud115200);
serial->setDataBits(QSerialPort::Data8);
serial->setStopBits(QSerialPort::OneStop);
serial->setParity(QSerialPort::NoParity);
if(!serial->open(QIODevice::ReadWrite)){
QMessageBox::information(this,"错误提示","不能打开串口",QMessageBox::Ok);
}
else{
ui->cbCom->setEnabled(false);
ui->pbConnect->setText("关闭");
}
}
else{
serial->close();
ui->cbCom->setEnabled(true);
ui->pbConnect->setText("连接");
}
}
关于串口号的获取,在用VB时,用的是穷举法,捕获错误,非法的COM号会产生错误剔除,获得合法串口号。在QT里可以用QSerialPortInfo类,获取可用串口。这个for 循环也很有意思。不是常规的;;结构,感觉像是使用:对集合里的元素做一个遍历。可以在窗口构造函数中,或者其它地方把可用串口号送到combox里,方便选取。
const auto infos = QSerialPortInfo::availablePorts();
for(const QSerialPortInfo &info : infos){
ui->cbCom->addItem(info.portName());
}
为了从串口获取数据,需要连接一个串口取数的槽函数。
connect(serial, &QSerialPort::readyRead, this, &MainWindow::readData); 当串口产生readyRead信号时,调用readData函数处理。而 readData,当然需要定义到private slots里面。
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private slots:
void on_pbConnect_clicked();
void readData();
private:
Ui::MainWindow *ui;
QSerialPort *serial;
};
每产生一次readyRead, readData就被执行,程序中直接把所有接收到的内容存放到QString data里面。对于格式化数据,先前可以用sscanf读取分别放到数据或字符串里。QT里面没有sscanf,感觉不爽是吧。
QStringList datlist = data.split(",",QString::SkipEmptyParts); 这个split 一下就把字符串分好了,直接使用 datlist[],就能引用。
void MainWindow::readData()
{
QString data = serial->readAll();
QStringList datlist = data.split(",",QString::SkipEmptyParts);
ui->lineEdit->setText(data);
ui->lcdNumber1->display(datlist[0]);
ui->lcdNumber2->display(datlist[1]);
}
程序运行,结果满意。效率又提升了。So easy!
作者: southcreek, 来源:面包板社区
链接: https://mbb.eet-china.com/blog/uid-me-408807.html
版权声明:本文为博主原创,未经本人允许,禁止转载!
southcreek 2023-5-9 16:50
southcreek 2023-3-31 16:29
QT += serialport
不然与serial port 相关的内容不能编译