【问题标题】:How to send data to tty0tty null modem emulator port opened in QT如何将数据发送到在 QT 中打开的 tty0tty 空调制解调器仿真器端口
【发布时间】:2016-08-25 22:45:00
【问题描述】:

我已经通过 QSerialPort 与使用 tty0tty nullmodem 模拟器创建的模拟串行端口建立了工作连接,我可以向其写入数据,如下所示:

QSerialPort serial_stream;
...
serial_stream.setPortName(QString("/dev/tnt0"));
bool loc = serial_stream.open(serial_stream.ReadWrite)
...
serial_stream.write(buf);

我打开一个终端并通过“屏幕”连接到已连接的(在本例中为 tnt1)tnt 端口(例如 tnt0 tnt1 已连接):

screen /dev/tnt1

当我执行程序时,我会在屏幕上看到预期的输入(这里是“buf”)。但是如何将数据发送回 Qt 中打开的端口,以便我可以执行以下操作来读取数据:

int size = serial_stream.bytesAvailable();
QByteArray data = serial_stream.read(size);

我已经尝试用“sleep”停止程序...:

#include <unistd.h>
...
usleep(15*1000000);

...并像这样将数据发送给它:

echo “TEXT“ > /dev/tnt1

但它不起作用。很高兴得到您的帮助!

【问题讨论】:

  • 尝试使用 dataTerminalReady 信号。将信号连接到您将读取串行端口的插槽。
  • @Ibarros 我该怎么做?
  • 在主窗口中创建一个插槽来读取串口并将信号 dataTerminalReady 信号连接到该插槽:connect(serialport,SIGNAL(readyRead()),this,SLOT(readPortSlot()));
  • 其实是readyRead()信号,但在此之前要确保两个端口的配置相同,比如波特率、奇偶校验位......
  • 我用readyRead()试了一下,还是不行,serial_stream.bytesAvailable()还是0。

标签: c++ qt serial-port virtual tty


【解决方案1】:

使用QSerialPort 使用tty0tty - null modem emulator (v1.2) 发送/读取数据

1. 建立tty0tty-连接:

有两种方法可以建立一个tty0tty-连接(在两个虚拟端口之间)。两种方式都可能需要kernel header files。对于 2. 绝对有必要,否则error while make 是不可避免的。

(1.) 捷径:

  1. 下载并提取 tty0tty(标题中的第一个链接)。
  2. 打开一个终端和cd[Path to tty0tty-folder]/tty0tty/pts
  3. 执行sudo ./tty0tty

然后应该显示两个连接的pseudo terminal slaves

(/dev/pts/X) &lt;=&gt; (/dev/pts/Y) 带有 X、Y 变量。

(2.) 更长的路(但或多或少是永久性的):

  1. 关注Installation guide

也许在引导期间持续存在不起作用,因此需要在重新引导后重复安装指南的以下部分:

  1. 加载模块
    • sudo depmod
    • sudo modprobe tty0tty
  2. 为新的串行端口授予适当的权限 (native terminal devices)
    • sudo chmod 666 /dev/tnt*

执行ls /dev/tnt* 后应该显示端口列表:

/dev/tnt0 ... /dev/tnt7

2. 测试 tty0tty 连接是否有效(可选):

可以用cat测试连接:

  1. 打开一个终端[1] 并显示一个伪/本地终端设备的输出

    • (1.)cat /dev/pts/X 或 (2.)cat /dev/tnt0
  2. 打开另一个终端[2]并写入这个伪/本地终端设备

    • (1.)echo "message" &gt; /dev/pts/Y 或 (2.)echo "hello" &gt; /dev/tnt1

输出应该显示在终端[1]:

message

其他信息:要停止 cat,请按:Ctrl + Z

3. 在Qt-Project中使用QSerialPort将终端设备作为端口打开:

  1. [projectname].pro-文件中添加对Qt-specific configuration optionsserialport-reference:

    QT += serialport

    附加信息:允许将所有引用放在一行中:

    QT+= core gui serialport ...

  2. 在所需的[name].h-文件中添加所需的header file

    #include &lt;QtSerialPort/QSerialPort&gt;

  3. 添加两个QSerialPort-对象,通过void QSerialPort::setPortName(const QString &amp;name) 设置终端设备 的路径,并通过bool QSerialPort::open(OpenMode mode) 以所需权限打开端口(@98​​7654364@, WriteOnlyReadWrite)。示例:

        std::string tty0ttyPort1 = "/dev/tnt0";// or = "/dev/pts/X
        std::string tty0ttyPort2 = "/dev/tnt1";// or = "/dev/pts/Y
        QSerialPort qport1;
        QSerialPort qport2;
        qport1.setPortName(QString(tty0ttyPort1.c_str()));
        bool isOpen1 = qport1.open(qport1.ReadWrite);//Read and Write permission
        std::cout << "isOpen1: " << isOpen1 << std::endl;
        qport2.setPortName(QString(tty0ttyPort2.c_str()));
        bool isOpen2 = qport2.open(qport2.ReadWrite);
        std::cout << "isOpen2: " << isOpen2 << std::endl;
    

isOpen1isOpen2 应该是 true

isOpen1: 1
isOpen2: 1

附加信息1:可能需要以超级用户权限执行编译后的代码:

  1. 编译代码。
  2. 打开一个终端和cd[Path to compiled project folder]/[projectname]
  3. 执行sudo [executable_file]或以超级用户身份运行su(inadvisable)

附加信息2:如果出现以下警告...:

QSocketNotifier: Can only be used with threads started with QThread

...没有Qt 事件循环,它应该总是在main()-function 中:

int main(int argc, char *argv[]){
    QCoreApplication a(argc, argv);
    //My Testcode (Showed above in section 3.3)
    return a.exec();
}

4. 使用打开的QSerialPorts:

(1.) 没有信号:

使用qint64 QIODevice::write(const char * data) 从一个QSerialPort 写入另一个。使用qint64 QIODevice::read(char * data, qint64 maxSize)QByteArray QIODevice::readAll() 读取发送的数据。这里重要的是要知道通过QIODevice::write()发送数据后必须使用bool QIODevice::waitForReadyRead(int msecs),否则将无法正常工作。我还建议使用bool QIODevice::waitForBytesWritten(int msecs)。示例:

    const char* sendMessage = "myMessage";
    std::cout << "sendMessage: " << sendMessage << std::endl;
    qport1.write(sendMessage);
    qport1.waitForBytesWritten(2000);
    qport2.waitForReadyRead(2000);//required
    const char* readMessage = qport2.readAll().data();
    std::cout << "readMessage: " << readMessage << std::endl;

应该给出输出:

readMessage: myMessage

如果需要读取定义的字节数,请使用QIODevice::read()

    const char* readMessage = qport2.read(5);
    std::cout << "readMessage: " << readMessage << std::endl;

应该给出输出:

readMessage: myMess

其他信息:要检查有多少字节可供读取,请使用qint64 QIODevice::bytesAvailable() const。示例:

std::cout << qport2.bytesAvailable() << std::endl;

(2.) 有信号:

在类的构造函数中,可以使用QObject::connect()private slot 连接到readyRead() 信号:

Classname::Classname(){
    ...
    QObject::connect(&qport1, SIGNAL(readyRead()), this, SLOT(myPrivateSlotFunction()));
    //with "qport1" as sender and "this" as receiver
}

...

Classname::myPrivateSlotFunction(){
    ...
    const char* readMessage = qport1.readAll().data();
    ...
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-23
    • 2016-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多