现在我正在 QT Creator 5.12 中编写一个数据交换程序,比如说,一个特定的数据传输网络。该网络的“调制解调器”通过 UART RS-232 运行,并且仅在硬件流控制模式下运行。
问题的本质。
向端口发送数据时没有问题。我可以设置或重置 DTR 和 RTS 信号 QSerialPort::dataTerminalReady(bool) 和 QSerialPort::requestToSend(bool) 并使用 QSerialPort::pinoutSignals 检查 CTS 和 DSR 响应()。当然,在那之后,数据传输成功。
从设备接收数据时出现问题:我认为原因是 QSerialPort 类中缺少 QSerialPort::setClearToSend(bool) 和 QSerialPort::setDataSetReady(bool) 方法,因为我无法回答来自 RTS 数据通道的请求带有 CTS 和带有 DSR 的 DSR 的设备在硬件流控制下接收数据,尽管我当然可以使用 QSerialPort::pinoutSignals() 看到这些请求。因此,数据从调制解调器到我的程序的简单传输不会开始。用示波器观察信号。
当然,理论上,可以制作一根特殊的电缆,将RTS信号到CTS,DTR到DSR信号将在每个连接器内部循环,但是带有电缆的设备已经在接收器中使用了很长时间,不可能重写“调制解调器”中的端口控制器代码以进行不受控制的数据流传输。
也许我不明白什么?谁知道 - 告诉我摆脱这个困难的方法。
数据交换的实际类代码:头文件
#ifndef PORTUART_H
#define PORTUART_H
#include <QObject>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QTimer>
class PortUART : public QObject
{
Q_OBJECT
public:
explicit PortUART(QObject *parent = nullptr);
~PortUART();
signals:
void signalReadedPortIO(QByteArray Str); //Resived data
void signalErrComPort(QSerialPort::SerialPortError err); //Retranslate Error
public slots:
bool setComData(QString name, QSerialPort::BaudRate baud, QSerialPort::DataBits databits, QSerialPort::Parity parbits, QSerialPort::StopBits stopbits, QSerialPort::FlowControl qflow_control);
bool open(void);
bool close(void);
QString getName();
qint64 WriteToPort(QByteArray message);
bool isOpen(void);
bool isWritable(void);
bool isReadable(void);
void read();
void errorSerail(QSerialPort::SerialPortError err);
void timerOverflow(void);
private:
QTimer *pTimer;
int timeInterval = 1000;
QByteArray rcBuffer;
QSerialPort *serial = nullptr;
QString port_name;
QSerialPort::BaudRate baud_rate;
QSerialPort::DataBits data_bits;
QSerialPort::Parity parity;
QSerialPort::StopBits stop_bits;
QSerialPort::FlowControl flow_control;
};
#endif // PORTUART_H
实施文件
#include "portuart.h"
#include <QDebug>
PortUART::PortUART(QObject *parent) : QObject(parent)
{
baud_rate = QSerialPort::Baud115200;
data_bits = QSerialPort::Data8;
parity = QSerialPort::NoParity;
stop_bits = QSerialPort::OneStop;
flow_control = QSerialPort::HardwareControl;
serial = new QSerialPort(this);
connect(serial, SIGNAL(readyRead()), this, SLOT(read()));
connect(serial, SIGNAL(error(QSerialPort::SerialPortError)), this, SLOT(errorSerail(QSerialPort::SerialPortError)));
pTimer = new QTimer;
connect(pTimer, SIGNAL(timeout()), this, SLOT(timerOverflow()));
}
PortUART::~PortUART()
{
if (serial != nullptr)
{
if(serial->isOpen())
serial->close();
delete serial;
}
if (pTimer != nullptr)
delete pTimer;
}
bool PortUART::setComData(QString name, QSerialPort::BaudRate baud, QSerialPort::DataBits databits, QSerialPort::Parity parbits, QSerialPort::StopBits stopbits, QSerialPort::FlowControl qflow_control)
{
port_name = name;
baud_rate = baud;
data_bits = databits;
parity = parbits;
stop_bits = stopbits;
flow_control = qflow_control;
timeInterval = static_cast<int>((1000.0 / static_cast<int>(baud_rate)) * 500);
timeInterval < 50 ? timeInterval = 50 : timeInterval += 0; // пауза не меньше 50 мс
timeInterval > 250 ? timeInterval = 1000 : timeInterval += 0; // пауза не больше 1000 мс
return true;
}
bool PortUART::open(void)
{
try
{
//setup COM port
serial->setPortName(port_name);
serial->setBaudRate(baud_rate);
serial->setDataBits(data_bits);
serial->setParity(parity);
serial->setStopBits(stop_bits);
serial->setFlowControl(flow_control);
serial->open(QIODevice::ReadWrite);
if(serial->isWritable())
{
qDebug() << "Yes, i can write to port!";
}
serial->clear();
if (flow_control == QSerialPort::HardwareControl)
{
serial->setDataTerminalReady(true);
serial->setRequestToSend(true);
serial->pinoutSignals( );
}
}
catch(...)
{
return false;
}
return true;
}
bool PortUART::close(void)
{
if (serial->isOpen())
{
serial->close();
return true;
}
else
{
return false;
}
}
void PortUART::read()
{
if (pTimer->isActive())
pTimer->stop();
else
rcBuffer.clear();
QByteArray bytes = serial->readAll();
qDebug() << QString(bytes.toHex().toUpper());
//qDebug() << QString(bytes);
rcBuffer.append(bytes);
//emit signalReadedPortIO(bytes);
pTimer->start(timeInterval);
}
void PortUART::timerOverflow(void)
{
if (rcBuffer.size() > 0)
{
emit signalReadedPortIO(rcBuffer);
}
pTimer->stop();
}
void PortUART::errorSerail(QSerialPort::SerialPortError err)
{
if (err != 0)
{
qDebug() << "Error: " << err;
emit signalErrComPort(err);
}
}
QString PortUART::getName(void)
{
return port_name;
}
bool PortUART::isOpen()
{
return serial->isOpen();
}
bool PortUART::isWritable()
{
return serial->isOpen();
}
bool PortUART::isReadable()
{
return serial->isOpen();
}
qint64 PortUART::WriteToPort(QByteArray message)
{
if (serial->isWritable() == false)
{
return 0;
}
return serial->write(message);
}
在 QT 支持的建议下,我对 C:\Qt\Qt5.12.7\5.12.7\Src\qtserialport\src\serialport\qserialport_win.cpp 文件进行了更改,并在“发布”模式下重新编译了这个库。
之后,正如您可能猜到的那样,DTR->DSR 反应额外打开,RTS->CTS 成功开始工作。