1、简介
本博文主要是介绍如何使用QT的串口类(QSerialPort)来实现串口的开发,使用这个类来实现串口的基本功能,比如如何查询本机可用串口(com),打开串口、设置串口波特率、设置数据位、设置校验位、停止位等窗口属性。还实现了十六进制收发显示数据,经过测试,本工程代码可以在WIN7+QT 或者 Ubuntu + QT环境下正常运行。
2、主要使用QSerialPort类的借口
(1)、void readyRead():串口信号,只要串口接收到数据,就会发送(emit)该信号,我们要用信号槽函数连接该信号以便 接收串口的所有数据。
(2)、QByteArray readAll():读取串口的所有数据,返回值QByteArray。
(3)、qint64 write(const QByteArray &data):发送数据到串口,发送成功,返回发送的字节数。
3、工程封装的主要接口
(1)、ShowMsg(int iTime, QString sMsg):显示提示消息函数,主要显示操作串口的提示消息,比如打开串口成功与否。
(2)、on_tbOpen_clicked():打开串口,本设置串口波特率等属性,并连接信号槽。
(3)、QString与QByteArray十六进制间的转换。
4、软件界面布局如下
5、代码演示
(1)、MainWindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include
#include
#include
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
void ShowMsg(int iTime, QString sMsg);
void msleep(int ms);
private slots:
void onReadData();
private slots:
void on_tbClearRecv_clicked();
void on_tbClearSend_clicked();
void on_tbOpen_clicked();
void on_tbExit_clicked();
void on_cbHexSHow_clicked(bool checked);
void on_tbSendData_clicked();
protected:
void timerEvent(QTimerEvent* event);
private:
Ui::MainWindow *ui;
int m_iTimerID;
QSerialPort *m_pSerial;
};
#endif // MAINWINDOW_H
(2)、MainWindow.cpp
#include "Mainwindow.h"
#include "ui_Mainwindow.h"
#include
#include
#include
#include
#include
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_iTimerID = 0;
m_pSerial = NULL;
//查找可用的串口
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
QSerialPort pSerial;
pSerial.setPort(info);
//尝试打开串口,如果能打开,说明串口可用,否则串口不可用
if(pSerial.open(QIODevice::ReadWrite))
{
//把可用的串口添加到界面控件
ui->tbPortBox->addItem(pSerial.portName());
pSerial.close();
}
}
//波特率默认115200,数据位默认7
ui->tbBaudBox->setCurrentIndex(7);
ui->tbBitNumBox->setCurrentIndex(3);
}
MainWindow::~MainWindow()
{
//关闭显示消息定时器
killTimer(m_iTimerID);
//关闭串口 释放资源
if (m_pSerial && m_pSerial->isOpen()) m_pSerial->close();
delete ui;
}
//显示信息
void MainWindow::ShowMsg(int iTime, QString sMsg)
{
if (m_iTimerID) killTimer(m_iTimerID);
ui->labelMsg->show();
ui->labelMsg->setText(sMsg);
m_iTimerID = this->startTimer(iTime);
}
//清空接受窗口
void MainWindow::on_tbClearRecv_clicked()
{
ui->teRecvData->clear();
}
//清空接收窗口
void MainWindow::on_tbClearSend_clicked()
{
ui->teSendData->clear();
}
//打开串口100
void MainWindow::on_tbOpen_clicked()
{
if(ui->tbOpen->text()==tr("打开串口"))
{
if (m_pSerial)
{
delete m_pSerial;
m_pSerial = NULL;
}
m_pSerial = new QSerialPort();
//设置串口名
QString sComName = ui->tbPortBox->currentText();
m_pSerial->setPortName(sComName);
//打开串口
bool b = m_pSerial->open(QIODevice::ReadWrite);
ShowMsg(4500, b ? tr("打开串口成功") : tr("打开串口失败"));
//设置波特率
int iBaudRate = ui->tbBaudBox->currentText().toInt();
m_pSerial->setBaudRate(iBaudRate);
//设置数据位数
int iDataType = ui->tbBitNumBox->currentIndex();
switch(iDataType)
{
case 0: m_pSerial->setDataBits(QSerialPort::Data5); break;
case 1: m_pSerial->setDataBits(QSerialPort::Data6); break;
case 2: m_pSerial->setDataBits(QSerialPort::Data7); break;
case 3: m_pSerial->setDataBits(QSerialPort::Data8); break;
default: break;
}
//设置奇偶校验
switch(ui->tbParityBox->currentIndex())
{
case 0: m_pSerial->setParity(QSerialPort::NoParity); break;
case 1: m_pSerial->setParity(QSerialPort::OddParity); break;
case 2: m_pSerial->setParity(QSerialPort::EvenParity); break;
default: break;
}
//设置停止位
int iStopType = ui->tbStopBox->currentIndex();
switch(iStopType)
{
case 0: m_pSerial->setStopBits(QSerialPort::OneStop); break;
case 1: m_pSerial->setStopBits(QSerialPort::TwoStop); break;
default: break;
}
//设置流控制
m_pSerial->setFlowControl(QSerialPort::NoFlowControl);
//关闭设置菜单使能
ui->tbPortBox->setEnabled(false);
ui->tbBaudBox->setEnabled(false);
ui->tbBitNumBox->setEnabled(false);
ui->tbParityBox->setEnabled(false);
ui->tbStopBox->setEnabled(false);
ui->tbOpen->setText(tr("关闭串口"));
//连接信号槽,接收串口发送过来的所有消息
connect(m_pSerial, SIGNAL(readyRead()), this, SLOT(onReadData()));
}
else
{
//关闭串口
if (m_pSerial)
{
m_pSerial->clear();
m_pSerial->close();
m_pSerial->deleteLater();
delete m_pSerial;
m_pSerial = NULL;
}
//恢复设置使能
ui->tbPortBox->setEnabled(true);
ui->tbBaudBox->setEnabled(true);
ui->tbBitNumBox->setEnabled(true);
ui->tbParityBox->setEnabled(true);
ui->tbStopBox->setEnabled(true);
ui->tbOpen->setText(tr("打开串口"));
ShowMsg(4500, "串口已关闭");
}
}
//退出程序
void MainWindow::on_tbExit_clicked()
{
//退出程序,关闭串口,释放资源
if (m_pSerial && m_pSerial->isOpen()) m_pSerial->close();
this->close();
}
//定时器时间出发函数
void MainWindow::timerEvent(QTimerEvent *event)
{
if (event->timerId() == m_iTimerID)
{
//时间到隐藏显示消息控件
killTimer(m_iTimerID);
m_iTimerID = 0;
ui->labelMsg->clear();
ui->labelMsg->hide();
}
}
//休眠函数
void MainWindow::msleep(int ms)
{
QTime tm;
tm.restart();
while (tm.elapsed() < ms)
{
QCoreApplication::processEvents();
}
}
//接收串口的所有数据
void MainWindow::onReadData()
{
if (m_pSerial == NULL) return;
//读取串口的所有数据
QByteArray buf = m_pSerial->readAll();
if (ui->cbHexSHow->isChecked())
{
//十六进制显示
ui->teRecvData->append(QString(buf.toHex()));
}
else
{
//原样显示
ui->teRecvData->append(QString(buf));
}
}
//十六进制显示
void MainWindow::on_cbHexSHow_clicked(bool checked)
{
if (checked)
{
//把QString转成十六进制的QByteArray
QByteArray ba = ui->teRecvData->toPlainText().toLocal8Bit();
ui->teRecvData->clear();
//显示到界面
ui->teRecvData->append(QString(ba.toHex()));
}
else
{
QString sText = ui->teRecvData->toPlainText();
ui->teRecvData->clear();
//十六进制的QString转QString
QByteArray ba = QByteArray::fromHex(sText.toLocal8Bit());
ui->teRecvData->append(QString(ba.data()));
}
}
//发送数据
void MainWindow::on_tbSendData_clicked()
{
if (m_pSerial == NULL) return;
//把发送的所有数据读取下来
QString sText = ui->teSendData->toPlainText();
if (sText.isEmpty()) return;
if (ui->cbHexSend->isChecked())
{
//按十六进制发送
m_pSerial->write(sText.toLocal8Bit().toHex());
}
else
{
//原样发送
m_pSerial->write(sText.toLocal8Bit());
}
//清空发送区
ui->teSendData->clear();
}
6、测试结果