Qt串口编程出错问题解决

Qt串口编程出错问题解决方案

       使用Qt在 Windows和Linux 下进行串口编程,整个教程笔者也是使用网上很流行的一片帖子:Qt编写串口通信程序全程图文讲解。这篇帖子访问量和转载量都很多,笔者也不清楚我给出的地址是不是原创作者,不过这都无关紧要
 
(但是这篇帖子的大量转载给网络搜索带来巨大的麻烦,搜了半天“Qt串口编程”都是这篇文章的大量转载版本,笔者在此建议读者转载须谨慎,既然已经是公开文章可以私人收藏嘛!)。
       笔者将对这篇教程中未提及的一些事宜做一些说明和解决方案,这些问题和解决办法也都来自网络,由于太杂就不列举源出处了。
 

我们在 Windows 下只需要使用其中的6个文件:

qextserialbase.cpp和qextserialbase.h,qextserialport.cpp和qextserialport.h,win_qextserialport.cpp和win_qextserialport.h

如果在 Linux 下则是:qextserialbase.cpp和qextserialbase.h,qextserialport.cpp和qextserialport.h,posix_qextserialport.cpp和posix_qextserialport.h。

 

Windows/Linux下的串口编程:

        由源码我们知道:串口类 Win_QextSerialPort (Linux下则是 Posix_Qextserialport,以下不再说明)是继承自类QextSerialBase ,而类 QextSerialBase  又继承自 QIODevice 。

 

定义类 Win_QextSerialPort  时:

Windows下是:myCom = new Win_QextSerialPort("com1", QextSerialBase::EventDriven);

Linux下则是:   myCom = new Posix_QextSerialPort("/dev/ttyS1", QextSerialBase::Polling);

有两处不同:一是类名不同,二是两个参数都不同。

 

一眼就能看出第一个参数是串口名称:

Windows下是 com1,com2,。。。。

Linux下是 /dev/ttyS0,/dev/ttyS1。。。。

需要说明的是:如果第一个参数直接使用"com1"这样的形式,那么当打开串口号大于10的串口时(如"com11","com12"),是无法成功打开的。据说是因为这个类库没有考虑串口号大于10的情况(不管是不是这个原因,我们找到解决办法就行了)。遇到这个问题,解决办法是:这么写 "\\\\.\\com11" 。打开串口就没有任何限制了。(Linux下不存在以上问题)

在PC机上,一般是用USB转串口,则应当是 "/dev/ttyUSB0" ,具体端口号是多少,自己去查看一下。如果是做嵌入式开发,在交叉编译的时候记得改回来。

第二个参数是指 打开串口的模式。模式有两种,源码中是这么写的

enum QueryMode 
{
        Polling,
        EventDriven
};


是个枚举类型,是类 QextSerialBase  的成员。所以是 QextSerialBase::EventDriven 。

需要说明的是:这两种方式是指串口查询方式。Windows下两种方式都支持;但是 Linux 下只支持Polling 方式。在EventDriven(事件驱动)模式下,每当串口收到数据后就会发送信号 readyRead() 。所以我们可以这么连接信号与槽:

connect(myCom0, SIGNAL(readyRead()), this, SLOT(read_com()));

由于 EventDriven 只能在 Windows 下使用,故Poliing模式下(不管是Windows下还是Linux下)都需要自己定时检查是否收到数据。

在网上下载类库 qextserialport-1.2win-alpha 时,发现文件夹内有 examples 文件夹,研究里面的例子发现以下问题。

在例子中,它用下面的语句检查串口是否打开

QTextStream out(stdout);
	QCoreApplication app(argc, argv);
	Win_QextSerialPort * port = new Win_QextSerialPort("COM1",QextSerialPort::EventDriven);
	port->setBaudRate(BAUD56000);	// 波特率
	port->setFlowControl(FLOW_OFF);
	port->setParity(PAR_NONE);	// 校验位
	port->setDataBits(DATA_8);	// 数据位
	port->setStopBits(STOP_2);	// 停止位
	port->open(QIODevice::ReadWrite);
	if (!(port->lineStatus() & LS_DSR)) 
         {
		out << "warning: device is not turned on" << endl;
	}


在类库源码的注释中如下解释函数 ulongWin_QextSerialPort::lineStatus(void)

/*!
\fn unsigned long Posix_QextSerialPort::lineStatus()
returns the line status as stored by the port function.  This function will retrieve the states
of the following lines: DCD, CTS, DSR, and RI.  On POSIX systems, the following additional lines
can be monitored: DTR, RTS, Secondary TXD, and Secondary RXD.  The value returned is an unsigned
long with specific bits indicating which lines are high.  The following constants should be used
to examine the states of individual lines:

\verbatim
Mask        Line
------      ----
LS_CTS      CTS
LS_DSR      DSR
LS_DCD      DCD
LS_RI          RI
LS_RTS      RTS (POSIX only)
LS_DTR      DTR (POSIX only)
LS_ST        Secondary TXD (POSIX only)
LS_SR        Secondary RXD (POSIX only)
\endverbatim

This function will return 0 if the port associated with the class is not currently open.
*/

 

其中:


RS-232针脚的功能:

  数据:

  TXD(pin 3):串口数据输出(Transmit Data)

  RXD(pin 2):串口数据输入(Receive Data)

  握手:

  RTS(pin 7):发送数据请求(Request to Send)

  CTS(pin 8):清除发送(Clear to Send)

  DSR(pin 6):数据发送就绪(Data Send Ready)

  DCD(pin 1):数据载波检测(Data Carrier Detect)

  DTR(pin 4):数据终端就绪(Data Terminal Ready)

  地线:

  GND(pin 5):地线

  其他

  RI(pin 9):铃声指示

也即程序是通过判断 DSR(pin 6):数据发送就绪(Data Send Ready) 信号是否正常来确定串口是否打开。在源码中他们的值为:

 

/*line status constants*/
#define LS_CTS  0x01
#define LS_DSR  0x02
#define LS_DCD  0x04
#define LS_RI   0x08
#define LS_RTS  0x10
#define LS_DTR  0x20
#define LS_ST   0x40
#define LS_SR   0x80

 

而实际上通过 Win_QextSerialPort::isOpen() 能够检测串口是否被打开。


 


 

 

你可能感兴趣的:(C/C++,Qt,Qt4,串口通信)