qt串口通信:需要用到QSerialport类。
1、pro文件中添加QT += serialport。
2、获取当前有哪些串口设备(QSerialPortInfo::availablePorts()))。
3、设置要打开的串口(setPortName),然后打开(open)。
4、设置串口的参数,波特率,数据位,控制位,奇偶未和停止位(setBaudRate,setDataBits,setFlowControl,setParity,setStopBits)
5、写数据和读数据。
虚拟串口百度云分享:
链接: https://pan.baidu.com/s/1sE_lFneZaFo8mvIYW4JA8Q 提取码: m8cn
如果只是练习,可以使用虚拟串口工具创建两个虚拟串口com6和com7.
串口调试助手百度云分享:
链接: https://pan.baidu.com/s/1W3dSIrqxFDNhxMeGKRCUzg 提取码: 3wwq
然后和三方的串口调试工具通信,一个打开com6,一个打开com7.
如果不用第三方串口调试助手,可以自己开两个程序,一个打开com6,一个打开com7.
.h
#ifndef WIDGET_H
#define WIDGET_H
#include
#include
#include
#include
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = nullptr);
void convertStringToHex(const QString &str, QByteArray &byteData);
char convertCharToHex(char ch);
~Widget();
private slots:
void slotLoadSerialPort();
void slotOpenSerialPort();
void slotReadData();
void slotSend();
void slotCloseSerialPort();
private:
Ui::Widget *ui;
QPushButton* m_loadportbtn;
QPushButton* m_openSerialPortbtn;
QPushButton* m_sendbtn;
QPushButton* m_closeSerialPortbtn;
QComboBox* m_serialportbox;
QComboBox* m_baudratebox;
QComboBox* m_databitbox;
QComboBox* m_stopbitbox;
QComboBox* m_paritybox;
QComboBox* m_flowcontrolbox;
QLabel* m_portlab;
QLabel* m_Baudratelab;
QLabel* m_DataBitlab;
QLabel* m_FlowControllab;
QLabel* m_StopBitlab;
QLabel* m_Paritylab;
QLabel* m_readlab;
QLineEdit* m_sendedit;
QTextEdit* m_readedit;
QStringList m_flowcontrollist;
QStringList m_paritylist;
QStringList m_stopbitlist;
QStringList m_databitlist;
QStringList m_baudratelist;
QSerialPort* m_serialPort;
};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"
#include
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
m_serialPort = nullptr;
m_portlab = new QLabel("端口:",this);
m_serialportbox = new QComboBox(this);
m_loadportbtn = new QPushButton("加载端口",this);
m_openSerialPortbtn = new QPushButton("打开串口",this);
m_closeSerialPortbtn = new QPushButton("关闭串口",this);
m_Baudratelab = new QLabel("数据位:",this);
m_DataBitlab = new QLabel("数据位:",this);
m_FlowControllab = new QLabel("控制流:",this);
m_Paritylab = new QLabel("校验位:",this);
m_StopBitlab = new QLabel("停止位:",this);
m_baudratebox = new QComboBox(this);
m_databitbox = new QComboBox(this);
m_flowcontrolbox = new QComboBox(this);
m_paritybox = new QComboBox(this);
m_stopbitbox = new QComboBox(this);
m_sendbtn = new QPushButton("发送",this);
m_sendedit = new QLineEdit(this);
m_readlab = new QLabel("接收:",this);
m_readedit = new QTextEdit(this);
QGridLayout* lay = new QGridLayout(this);
lay->addWidget(m_loadportbtn,0,0,1,2);
lay->addWidget(m_portlab,1,0,1,1);
lay->addWidget(m_serialportbox,1,1,1,1);
lay->addWidget(m_Baudratelab,2,0,1,1);
lay->addWidget(m_baudratebox,2,1,1,1);
lay->addWidget(m_DataBitlab,3,0,1,1);
lay->addWidget(m_databitbox,3,1,1,1);
lay->addWidget(m_FlowControllab,4,0,1,1);
lay->addWidget(m_flowcontrolbox,4,1,1,1);
lay->addWidget(m_Paritylab,5,0,1,1);
lay->addWidget(m_paritybox,5,1,1,1);
lay->addWidget(m_StopBitlab,6,0,1,1);
lay->addWidget(m_stopbitbox,6,1,1,1);
lay->addWidget(m_openSerialPortbtn,7,0,1,2);
lay->addWidget(m_closeSerialPortbtn,8,0,1,2);
lay->addWidget(m_sendedit,9,0,1,1);
lay->addWidget(m_sendbtn,9,1,1,1);
lay->addWidget(m_readlab,10,0,1,1);
lay->addWidget(m_readedit,11,0,1,2);
this->setLayout(lay);
m_flowcontrollist<<"无"<<"硬控制"<<"软控制";
m_paritylist<<"No"<<"Even"<<"Odd"<<"Space"<<"Mark";
m_baudratelist<<"1200"<<"2400"<<"4800"<<"9600"<<"19200"<<"38400"<<"57600"<<"115200";
m_databitlist<<"5"<<"6"<<"7"<<"8";
m_stopbitlist<<"1"<<"2"<<"1.5";
m_baudratebox->addItems(m_baudratelist);
m_databitbox->addItems(m_databitlist);
m_flowcontrolbox->addItems(m_flowcontrollist);
m_paritybox->addItems(m_paritylist);
m_stopbitbox->addItems(m_stopbitlist);
connect(m_loadportbtn,SIGNAL(clicked()),this,SLOT(slotLoadSerialPort()));
connect(m_openSerialPortbtn,SIGNAL(clicked()),this,SLOT(slotOpenSerialPort()));
connect(m_closeSerialPortbtn,SIGNAL(clicked()),this,SLOT(slotCloseSerialPort()));
connect(m_sendbtn,SIGNAL(clicked()),this,SLOT(slotSend()));
}
Widget::~Widget()
{
delete ui;
}
void Widget::slotLoadSerialPort()
{
QStringList m_serialPortName;
foreach(const QSerialPortInfo &info,QSerialPortInfo::availablePorts()) //获取有效的串口列表
{
m_serialPortName << info.portName();
qWarning()<<"serialPortName:"<clear();
m_serialportbox->addItems(m_serialPortName);
}
void Widget::slotCloseSerialPort()
{
if (m_serialPort)
m_serialPort->close();
}
void Widget::slotOpenSerialPort()
{
m_serialPort = new QSerialPort(this);
if(m_serialPort->isOpen())
{
m_serialPort->clear();
m_serialPort->close();
}
m_serialPort->setPortName(m_serialportbox->currentText());
if (!m_serialPort->open(QIODevice::ReadWrite))
{
qWarning()<<"打开串口"<currentText()<<"失败";
return;
}
m_serialPort->setBaudRate(m_baudratebox->currentText().toInt());
m_serialPort->setDataBits((QSerialPort::DataBits)(m_databitbox->currentIndex()+5));
m_serialPort->setFlowControl((QSerialPort::FlowControl)m_flowcontrolbox->currentIndex());
int parity = m_paritybox->currentIndex();
if (parity > 0)
parity++;
m_serialPort->setParity((QSerialPort::Parity)parity);
m_serialPort->setStopBits((QSerialPort::StopBits)(m_stopbitbox->currentIndex()+1));
qWarning()<<"打开串口"<currentText()<<"成功";
connect(m_serialPort,SIGNAL(readyRead()),this,SLOT(slotReadData()));
}
void Widget::slotReadData()
{
QString data = m_serialPort->readAll();
qWarning()<<"接收数据:"<append("接收数据:"+data);
}
void Widget::slotSend()
{
if (m_serialPort)
{
if (!m_serialPort->isOpen())
qWarning()<<"请打开一个串口";
QString info = m_sendedit->text();
QByteArray sendBuf;
// if (info.contains(" "))
// {
// info.replace(QString(" "),QString(""));//我这里是把空格去掉,根据你们定的协议来
// }
// convertStringToHex(info, sendBuf); //把QString 转换 为 hex
qWarning()<<"发送数据:"<baudRate()<dataBits()<flowControl()<parity()<stopBits();
sendBuf = info.toLocal8Bit();
m_serialPort->write(sendBuf);
}
}
//Qstring 转为 16进制的函数
void Widget::convertStringToHex(const QString &str, QByteArray &byteData)
{
int hexdata,lowhexdata;
int hexdatalen = 0;
int len = str.length();
byteData.resize(len/2);
char lstr,hstr;
for(int i=0; i= len)
break;
lstr = str[i].toLatin1();
hexdata = convertCharToHex(hstr);
lowhexdata = convertCharToHex(lstr);
if((hexdata == 16) || (lowhexdata == 16))
break;
else
hexdata = hexdata*16+lowhexdata;
i++;
byteData[hexdatalen] = (char)hexdata;
hexdatalen++;
}
byteData.resize(hexdatalen);
}
//另一个 函数 char 转为 16进制
char Widget::convertCharToHex(char ch)
{
/*
0x30等于十进制的48,48也是0的ASCII值,,
1-9的ASCII值是49-57,,所以某一个值-0x30,,
就是将字符0-9转换为0-9
*/
if((ch >= '0') && (ch <= '9'))
return ch-0x30;
else if((ch >= 'A') && (ch <= 'F'))
return ch-'A'+10;
else if((ch >= 'a') && (ch <= 'f'))
return ch-'a'+10;
else return (-1);
}
注意:如果是在UBuntu系统上,你会发现有点不一样,串口可能打不开。
解决方法如下:
如果是第一次在UBuntu上打开串口,串口名一般为ttyUSB0,需要给串口设置权限,否则是无法打开成功的。设置权限方法如下:
方法一:
sudo chmod 666 /dev/ttyUSB0
方法二:
添加配置
sudo vim /etc/udev/rules.d/20-usb-serial.rules
内容为
KERNEL=="ttyUSB*" MODE="0666"
匹配内核以 ttyUSB 开头的驱动, 权限为 666
使配置生效
sudo service udev reload
sudo service udev restart
如果不想修改权限, 还有一种方法是当前用户加入 dialout 组(ttyUSB0 设备文件属于这个组), 加入这个组后就有权限了, 之后重启一下
sudo usermod -aG dialout jianghuixin
详情介绍