1. 建立tty0tty-连接:
有两种方法可以建立一个tty0tty-连接(在两个虚拟端口之间)。两种方式都可能需要kernel header files。对于 2. 绝对有必要,否则error while make 是不可避免的。
(1.) 捷径:
- 下载并提取 tty0tty(标题中的第一个链接)。
- 打开一个终端和
cd到[Path to tty0tty-folder]/tty0tty/pts
- 执行
sudo ./tty0tty
然后应该显示两个连接的pseudo terminal slaves:
(/dev/pts/X) <=> (/dev/pts/Y) 带有 X、Y 变量。
(2.) 更长的路(但或多或少是永久性的):
- 关注Installation guide
也许在引导期间持续存在不起作用,因此需要在重新引导后重复安装指南的以下部分:
- 加载模块
sudo depmod
sudo modprobe tty0tty
- 为新的串行端口授予适当的权限 (native terminal devices)
执行ls /dev/tnt* 后应该显示端口列表:
/dev/tnt0 ... /dev/tnt7
2. 测试 tty0tty 连接是否有效(可选):
可以用cat测试连接:
-
打开一个终端[1] 并显示一个伪/本地终端设备的输出:
- (1.)
cat /dev/pts/X 或 (2.)cat /dev/tnt0
-
打开另一个终端[2]并写入这个伪/本地终端设备:
- (1.)
echo "message" > /dev/pts/Y 或 (2.)echo "hello" > /dev/tnt1
输出应该显示在终端[1]:
message
其他信息:要停止 cat,请按:Ctrl + Z
3. 在Qt-Project中使用QSerialPort将终端设备作为端口打开:
-
在[projectname].pro-文件中添加对Qt-specific configuration options 的serialport-reference:
QT += serialport
附加信息:允许将所有引用放在一行中:
即QT+= core gui serialport ...
-
在所需的[name].h-文件中添加所需的header file:
#include <QtSerialPort/QSerialPort>
-
添加两个QSerialPort-对象,通过void QSerialPort::setPortName(const QString &name) 设置终端设备 的路径,并通过bool QSerialPort::open(OpenMode mode) 以所需权限打开端口(@987654364@, WriteOnly,ReadWrite)。示例:
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;
isOpen1 和 isOpen2 应该是 true:
isOpen1: 1
isOpen2: 1
附加信息1:可能需要以超级用户权限执行编译后的代码:
- 编译代码。
- 打开一个终端和
cd到[Path to compiled project folder]/[projectname]
- 执行
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();
...
}