2014-01-27 1706 views
0

我正在使用QT连接到硬件串行设备,我基于我的应用程序大致围绕终端示例,但由于通信需要非常同步,因此串行处理程序生活在另一个线程。该连接通过一个2xRS232连接到带有FTDI芯片组的USB适配器。关闭串口的正确方法QT

串行通信很好,我可以连接,发送命令等。但是,当我退出并重新加载应用程序时,串行端口似乎被阻止。

让COM1为连接的设备,COM2未连接。

如果我运行该程序,做一些与硬件通话并退出,下一次运行程序(数据LED不会在适配器上闪烁)时不能再连接到COM1,除非我尝试首先连接到COM2。一旦我尝试过,我可以像往常一样连接回COM1。在硬件的参考实用程序中没有看到这种行为,因此必须以某种方式处理端口。

我身边的代码是:

void mydevice::closeSerialPort() 
{ 
    this->stop(); 
    serial->close(); 
    emit serialClosed(); 
    emit log("Serial port closed."); 
} 

serialQTSerialPort。首先发送一个停止命令来关闭硬件(与问题无关,这只是一种方便),然后我发送一个关闭命令给串口。

我有我的主窗口中的子类的QWidget,要求退出该命令:

/* In the constructor */ 
connect(this, SIGNAL(WindowClosed()), mydevice, SLOT(closeSerialPort())); 


void mainwindow::closeEvent(QCloseEvent *event) 
{ 
     emit WindowClosed(); 
     event->accept(); 
} 

没有任何理由为这种行为?我假设我以某种方式阻止港口开放,但肯定会抱怨它已经开放。

另一个奇怪的问题是,说设备是在COM1上,我在我的应用程序中打开它,COM1在其他实用程序中无响应,设备出现在COM2上。但是,当我切换回我的程序并拨弄一下时,设备再次出现在COM1上(尽管总是在另一个应用程序的COM2中)。

回答

1

所以似乎有一个相当简单的解决方案,但我不明白究竟是什么导致了问题。

我有两个线程,每个线程控制不同的串行设备。串行配置通过我从QT示例(终端)偷取的对话框访问。每个线程都有一个此设置对话框的实例。看起来在选择端口时出现了问题 - 例如,如果在调试器中选中,则对话框中的所有选择实际上指向相同的COM端口。

无论如何,我把这写成非线程安全的代码,并将程序改为只询问串行端口名称,因为数据速率,停止位,奇偶校验等由硬件固定,并且不会改变。这已经解决了这个问题。

0

有两个可能的答案,我想:

  1. 过程不,尽管你关闭主窗口的终止。您如何验证该流程实际上已被终止?

  2. 您对qt的serialport模块的使用暴露了FTDI驱动程序中的一个错误。这并不是不可想象的,但我现在称之为遥远的可能性。

就我个人而言,我没有看到FTDI驱动程序的串口仿真的任何用途,它没有任何理由添加额外的图层。如果您不想使用诸如libftdi之类的东西,D2XX接口是实现它的方法。在Windows上,我发现D2XX和libftdi是唯一可行的替代方案,在虚拟机上,libftdi比D2XX工作得更好。

+0

我使用的是通用QT库,因为代码很可能以各种系统结束,其中一些内置串行端口(旧套件!),其中一些可能使用Prolific驱动程序等。 我玩了更多,甚至只有在需要的波特率工程未使用的端口尝试。例如该设备工作在115200波特。如果我尝试使用9600打开COM2,然后在115200打开COM1,请使用zip。如果我尝试COM2与115200,然后COM1,它的工作原理。 程序肯定被终止,QT Creator获取程序的返回码,任何东西都不会出现在taskmgr中。 – Josh

0

不知道这可能是有用的。

我有一个类似的问题(但不是相同的)与多产pl2303。 在我的情况下,当我关闭端口(或者甚至在启动之前,在打开它之前!),无论如何都会收到数据,并在我打开端口时立即显示。

这种情况只发生在usb-rs232适配器上,如果我使用ttyS0(物理串行端口),则不会出现问题。

对于我来说,解决方案是迫使QSerialPort :: clear()在QSerialPort :: open()之后清除缓冲区。这避免了准备好的信号被发射并因此接收不需要的数据。

相关问题