前言
使用Qt串口类实现串口数据收发及端口选择
一、ui界面设计
非必须,可以不用,此处仅作展示
二、串口驱动文件
1.C++文件
#include "uart.h"
int uart::sendBytes = 0;
int uart::receBytes = 0;
uart::uart(QObject *parent) : QObject(parent)
{
serial = new QSerialPort;
connect(serial, &QSerialPort::readyRead, this, [=]()
{
QByteArray data = serial->readAll();
emit haveReceive(data);
});
}
//串口查找
void uart::serialPortFind(QComboBox *portBox)
{
/*清除comboxBox的内容,防止显示重复的串口*/
portBox->clear();
const auto infos = QSerialPortInfo::availablePorts();
//下面这个循环语句用来查找可以用的串口端口
//不确定有多少串口可用,也就不知道循环多少次,所以用foreach(不知道用的就百度)
for(const QSerialPortInfo &info : infos)
{
QSerialPort serial; //在循环语句内部实例化类,因为可用串口不一定只就一个
serial.setPort(info); //设置能够用的串口端口
if(serial.open(QIODevice::ReadWrite)) //用ReadWrite可读写的方式打开串口
{
//记录可用的uart名字serial.portName(),前面的ui->PortBox->addItem不用管,这个是界面里面的。
portBox->addItem(info.portName());
//然后关闭串口,因为这段代码打开串口只是为了查找串口可以用不可用而已。
serial.close();
}
}
}
//打开串口
bool uart::serialPortOpen(QComboBox *portBox,qint32 baud)
{
//设置串口名
serial->setPortName(portBox->currentText());
//打开串口
if(!serial->open(QIODevice::ReadWrite))
{
qDebug() << "串口打开失败" ;
return false; //失败返回0
}
//设置波特率
serial->setBaudRate(baud);
//设置数据位数 8
serial->setDataBits(QSerialPort::Data8);
//设置奇偶校验 0
serial->setParity(QSerialPort::NoParity);
//设置停止位 1
serial->setStopBits(QSerialPort::OneStop);
//设置流控制 无
serial->setFlowControl(QSerialPort::NoFlowControl);
return true; //成功返回1
}
//关闭串口
void uart::serialPortClose()
{
serial->close();
}
//串口发送数据
void uart::serialPortSendData(QByteArray data,int len)
{
serial->write(data,len); //串口发数据
}
//数据转换 字符串转十六进制
void uart::StringToHex(QString str, QByteArray &senddata)
{
int hexdata,lowhexdata;
int hexdatalen = 0;
int len = str.length();
senddata.resize(len/2);
char lstr,hstr;
for(int i=0; i<len; )
{
hstr=str[i].toLatin1();
if(hstr == ' ')
{
i++;
continue;
}
i++;
if(i >= len)
break;
lstr = str[i].toLatin1();
hexdata = convertHexChart(hstr);
lowhexdata = convertHexChart(lstr);
if((hexdata == 16) || (lowhexdata == 16))
break;
else
hexdata = hexdata*16+lowhexdata;
i++;
senddata[hexdatalen] = (char)hexdata;
hexdatalen++;
}
senddata.resize(hexdatalen);
}
//数据转换 字符串转16进制数据处理
char uart::convertHexChart(char ch)
{
if((ch >= '0') && (ch <= '9'))
return ch-0x30; // 0x30 对应 ‘0’
else if((ch >= 'A') && (ch <= 'F'))
return ch-'A'+10;
else if((ch >= 'a') && (ch <= 'f'))
return ch-'a'+10;
else
return ch-ch;//不在0-f范围内的会发送成0
}
2、头文件
#ifndef UART_H
#define UART_H
#include <QObject>
#include <QDebug> //日志打印
#include <QtSerialPort/QSerialPort> //提供访问串口的功能
#include <QtSerialPort/QSerialPortInfo> //提供系统中存在的串口的信息
#include <QComboBox>
class uart : public QObject
{
Q_OBJECT
public:
explicit uart(QObject *parent = nullptr);
void serialPortFind(QComboBox *portBox); //查找可用串口
bool serialPortOpen(QComboBox *portBox,qint32 baud); //打开串口,失败返回0,成功返回1
void serialPortClose(); //关闭串口
void serialPortSendData(const char *data,int len); //串口发送数据
void StringToHex(QString str, QByteArray &senddata); //数据转换 字符串转16进制
char convertHexChart(char ch); //数据转换 字符串转16进制 单字符处理
signals:
void haveReceive(QByteArray data);
private:
QSerialPort *serial; //创建串口处理对象
static int sendBytes;
static int receBytes;
};
#endif // UART_H
二、应用示例
.pro文件修改
QT += core gui serialport
/* ---------- 串口驱动处理 ---------- */
uart1 = new uart; //创建串口对象
uart1->serialPortFind(ui->portNameCBox); //查找可用串口,并在下拉框内显示
/* ---------- 以下部分为串口驱动相关函数 ---------- */
/* ---------- 更新串口按键槽函数 ---------- */
void debug::on_updataBtn_clicked()
{
uart1->serialPortFind(ui->portNameCBox); //查找可用串口,并在下拉框内显示
}
/* ---------- 打开串口按键槽函数 ---------- */
void debug::on_openPortBtn_clicked()
{
if(ui->openPortBtn->text()==tr("打开串口"))
{
if(uart1->serialPortOpen(ui->portNameCBox,uartBps.toUInt())) //若串口成功打开则提示打开成功 uartBps:串口波特率
{
//关闭串口下拉框使能
ui->portNameCBox->setEnabled(false);
ui->updataBtn->setEnabled(false);
ui->openPortBtn->setText(tr("关闭串口"));
connect(uart1,SIGNAL(haveReceive(QByteArray)),this,SLOT(ReadData(QByteArray))); //连接接收数据函数信号槽
}
else
{
QMessageBox::critical(this,"提示","串口不存在或被其他应用程序占用");
return;
}
}
else
{
//关闭串口
uart1->serialPortClose();
disconnect(uart1,SIGNAL(haveReceive(QByteArray)),this,SLOT(ReadData(QByteArray))); //断开连接接收数据函数信号槽
//恢复设置使能
ui->portNameCBox->setEnabled(true);
ui->updataBtn->setEnabled(true);
ui->openPortBtn->setText(tr("打开串口"));
}
}
/* ---------- 数据接收槽函数,并在接收区显示 ---------- */
void debug::ReadData(QByteArray data)
{
if (!data.isEmpty()) // 判断不为0,收到数据
{
/*这里添加应用程序*/
}
}