最近写了一个简单的串口助手,给大家分享一下.
一.UI界面的搭建
界面的基本搭建情况如下
左部分为发送区,发送按钮以及接收区
右上角为串口连接状态
下面是串口和波特率
可以进行进制转换
下面的三个按钮分别为打开串口.关闭串口和清空接收区
主要包含的控件如下
二.主要程序的编写
#include "serial.h"
#include "ui_serial.h"
#include <QSerialPortInfo>
Serial::Serial(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Serial)
{
ui->setupUi(this);
global_port = new QSerialPort();
system_init();
ui->cmb_port_name->addItems(getPortNameList()); // 自己选择是要方法1还是2
}
Serial::~Serial()
{
if(global_port->isOpen())//推出前如果串口还打开着 先给他关闭了
{
global_port->clear();
global_port->close();
}
delete ui;
}
/*-----------------------------------------------------
* functions
* ---------------------------------------------------*/
void Serial::system_init()
{
//port config
global_port->setParity(QSerialPort::NoParity);
global_port->setDataBits(QSerialPort::Data8);
global_port->setStopBits(QSerialPort::OneStop);
//connect
connect(ui->btn_open,&QPushButton::clicked,this,&Serial::btn_open_port);
connect(ui->btn_close,&QPushButton::clicked,this,&Serial::btn_close_port);
connect(ui->btn_send,&QPushButton::clicked,this,&Serial::btn_send_data);
connect(global_port,&QSerialPort::readyRead,this,&Serial::receive_data);
}
/*-----------------------------------------------------
* slots
* ---------------------------------------------------*/
// 方法1:获取串口的名字(真实上线时使用)
QStringList Serial::getPortNameList() {
QStringList m_serialPortName;
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
m_serialPortName << info.portName();
qDebug() << "serialportname:" << info.portName();
}
return m_serialPortName;
}
// 方法2:创建串口名字(使用虚拟串口时使用)
QStringList Serial::createPortNameList() {
QStringList virtualSerialPortName;
for(int i= 0; i < 20; ++i) {
QString str;
str = "/dev/pts/" + QString::number(i);
virtualSerialPortName << str;
}
// qDebug() << virtualSerialPortName;
return virtualSerialPortName;
}
void Serial::btn_open_port(bool)
{
/*----------port name----------------*/
/*//qDebug()<<ui->cmb_port_name->currentIndex();
// switch (ui->cmb_port_name->currentIndex()) {
// case 0:
// global_port->setPortName("/dev/pts/18");
// break;
// case 1:
// global_port->setPortName("/dev/pts/19");
// break;
// case 2:
// global_port->setPortName("COM3");
// break;
// case 3:
// global_port->setPortName("COM4");
// break;
// case 4:
// global_port->setPortName("COM5");
// break;
// case 5:
// global_port->setPortName("COM6");
// break;
// case 6:
// global_port->setPortName("COM7");
// break;
// default:
// global_port->setPortName("COM8");
// break;
// }*/
global_port->setPortName(ui->cmb_port_name->currentText());
/*--------------baud rate-------------*/
switch (ui->cmb_baud_rate->currentIndex()) {
case 0:
global_port->setBaudRate(QSerialPort::Baud115200);
break;
case 1:
global_port->setBaudRate(QSerialPort::Baud57600);
break;
case 2:
global_port->setBaudRate(QSerialPort::Baud38400);
break;
case 3:
global_port->setBaudRate(QSerialPort::Baud19200);
break;
case 4:
global_port->setBaudRate(QSerialPort::Baud9600);
break;
case 5:
global_port->setBaudRate(QSerialPort::Baud4800);
break;
case 6:
global_port->setBaudRate(QSerialPort::Baud2400);
break;
default:
global_port->setBaudRate(QSerialPort::Baud1200);
break;
}
//open
if(global_port->isOpen())// 打开前如果串口还打开着 先给他关闭了
{
global_port->clear();
global_port->close();
}
if(!global_port->open(QIODevice::ReadWrite)) //用ReadWrite 的模式尝试打开串口
{
qDebug()<<"打开失败!";
return;
}
qDebug()<<"串口打开成功!";
ui->lab_status->setText("Connected");
//test
//global_port.write("1")
}
void Serial::btn_close_port(bool)
{
global_port->close();
ui->lab_status->setText("Disconnected");
}
/*-------------sending data-----------------------*/
void Serial::btn_send_data(bool)
{
QString data=ui->lint_send_data->text();
QByteArray array=data.toLatin1();
global_port->write(array);
}
/*-------------receive data------------------*/
void Serial::receive_data()
{
QByteArray array=global_port->readAll();
qDebug()<<array;
if(ui->checkBox->checkState()==Qt::Checked){
ui->plainTextEdit->insertPlainText(QString(array.toHex(' ').toUpper().append(' ')));
}
else {
ui->plainTextEdit->insertPlainText(QString(array));
}
}
void Serial::on_pushButton_clicked()
{
ui->plainTextEdit->clear();
}
程序中包括使用虚拟串口和实际串口两种情况,转换时只需要改变相应的函数名即可.
三.虚拟串口
在该串口助手中,主要通过python的程序产生了一对虚拟串口
具体程序如下
#coding = utf-8
import pty
import os
import select
def mkpty():
master1, slave = pty.openpty()
slaveName1 = os.ttyname(slave)
master2, slave = pty.openpty()
slaveName2 = os.ttyname(slave)
print '\nslave device names: ', slaveName1, slaveName2
return master1, master2
if __name__ == "__main__":
master1, master2 = mkpty()
while True:
rl, wl, el = select.select([master1, master2], [], [], 1)
for master in rl:
data = os.read(master, 128)
print "read %d data." %len(data)
if master == master1:
os.write(master2, data)
else:
os.write(master1, data)
首先把这个程序放在盘里,然后在终端输入python mkptych.py
输入密码后,产生一对虚拟串口
最后在QT程序运行两次后,在串口处选择这两个串口,点击OPEN,进行连接.
另外需要注意当从虚拟串口改成实际串口时,除去改函数名称,还要在终端对实际串口进行授权
即输入sudo chmod 777 /dev/ttyUSB1
四.最终效果
实现功能有限,后续会改进!