qt5.0串口写数据返回为-1的问题

 开发环境是vs2012,qt5.2.0版本。通过串口通信与步进电机控制器进行交互。步进电机连接两个电机驱动器,步进电机控制器控制两个电机运动,正反转,回零,运行到一定位置,控制输入输出停等基本操作。为了调整镜头和相机的距离,从而调整相机的放大倍率。两个电机只能分时运动,两个命令直接需要加延时,全部停除外。
       遇到两个问题,一个是串口开始写数据返回为-1的问题,另一个是由于YL1和YL2输入端功能不单一:导致回零停时或是控制停时,步进电机控制器没有返回数据(用串口调试助手不存在这个问题,我也不清楚原因),没法保证命令是否完成,于是把输入端改成YL3-YL13其中的任何两个就可以。
        再说写串口返回为-1的问题,主要以前没有做过串口通信,对过程不是很了解,对qt封装的类构造函数了解不足。其实,qt封装的代码还是调用windows底层的东西。首先,我来申明一件事:网上给的代码有的是有问题的
。因为,我是这么做的,初次向串口写数据返回为-1。然后我查阅很多资料,都没有找到问题所在,后来受到一句话启发:串口必须先打开,然后在对他配置才是有效地。然后我仔细研究了源代码,主要是Qt封装的是有一点问题。其实,我们可以迈过这个问题,就是构造函数使用问题。
     Win_QextSerialPort();
     Win_QextSerialPort(Win_QextSerialPort const& s);
     Win_QextSerialPort(const QString & name, QextSerialBase::QueryMode mode = QextSerialBase::Polling);
     Win_QextSerialPort(const PortSettings& settings, QextSerialBase::QueryMode mode = QextSerialBase::Polling);
     Win_QextSerialPort(const QString & name, const PortSettings& settings, QextSerialBase::QueryMode mode = QextSerialBase::Polling);
    这五个构造函数第三个比较常用,我开始写得是用的第5个,然后并没又再次对PortSettings进行设置,所以写数据会返回为-1.
  

来看看端口的open函数:

bool Win_QextSerialPort::open(OpenMode mode) {
 unsigned long confSize = sizeof(COMMCONFIG);
 Win_CommConfig.dwSize = confSize;
 DWORD dwFlagsAndAttributes = 0;
 if (queryMode() == QextSerialBase::EventDriven)
  dwFlagsAndAttributes += FILE_FLAG_OVERLAPPED;
    LOCK_MUTEX();
    if (mode == QIODevice::NotOpen)
        return isOpen();
    if (!isOpen()) {
        /*open the port*/
        Win_Handle=CreateFileA(port.toAscii(), GENERIC_READ|GENERIC_WRITE,
                              FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, dwFlagsAndAttributes, NULL);
        if (Win_Handle!=INVALID_HANDLE_VALUE) {
            /*configure port settings*/
            GetCommConfig(Win_Handle, &Win_CommConfig, &confSize);
            GetCommState(Win_Handle, &(Win_CommConfig.dcb));
            /*set up parameters*/
            Win_CommConfig.dcb.fBinary=TRUE;
            Win_CommConfig.dcb.fInX=FALSE;
            Win_CommConfig.dcb.fOutX=FALSE;
            Win_CommConfig.dcb.fAbortOnError=FALSE;
            Win_CommConfig.dcb.fNull=FALSE;
            setBaudRate(Settings.BaudRate);
            setDataBits(Settings.DataBits);
            setStopBits(Settings.StopBits);
            setParity(Settings.Parity);
            setFlowControl(Settings.FlowControl);
            setTimeout(Settings.Timeout_Millisec);
            SetCommConfig(Win_Handle, &Win_CommConfig, sizeof(COMMCONFIG));
            //init event driven approach
   if (queryMode() == QextSerialBase::EventDriven) {
          Win_CommTimeouts.ReadIntervalTimeout = MAXDWORD;
          Win_CommTimeouts.ReadTotalTimeoutMultiplier = 0;
          Win_CommTimeouts.ReadTotalTimeoutConstant = 0;
        Win_CommTimeouts.WriteTotalTimeoutMultiplier = 0;
        Win_CommTimeouts.WriteTotalTimeoutConstant = 0;
    SetCommTimeouts(Win_Handle, &Win_CommTimeouts);
             if (!SetCommMask( Win_Handle, EV_TXEMPTY | EV_RXCHAR | EV_DSR)) {
              qWarning("Failed to set Comm Mask. Error code: %ld", GetLastError());
     UNLOCK_MUTEX();
              return false;
             }
             overlapThread->start();
            }
   QIODevice::open(mode);
        }
    } else {
  UNLOCK_MUTEX();
     return false;
    }
    UNLOCK_MUTEX();
    return isOpen();
}

而其中的:
            setBaudRate(Settings.BaudRate);
            setDataBits(Settings.DataBits);
            setStopBits(Settings.StopBits);
            setParity(Settings.Parity);
            setFlowControl(Settings.FlowControl);
            setTimeout(Settings.Timeout_Millisec);
这些函数只有在端口打开的时候才会设置有效的,具体自己看代码。 再看构造函数里面,if (!isOpen()) {}不打开又进行设置,所以说打开函数并不会PortSettings设置成功,所以在打开之后我们要单独对PortSettings进行设置。

     文件下载地址:http://sourceforge.net/projects/qextserialport/files/


     正确的写法是,以事件驱动的为例:    
     myCom = new Win_QextSerialPort(“COM1″,QextSerialBase::EventDriven);

    //定义串口对象,指定串口名和查询模式,这里使用事件驱动EventDriven

    myCom ->open(QIODevice::ReadWrite);

    //以读写方式打开串口

    myCom->setBaudRate(BAUD9600);

    //波特率设置,我们设置为9600

    myCom->setDataBits(DATA_8);

   //数据位设置,我们设置为8位数据位

    myCom->setParity(PAR_NONE);

    //奇偶校验设置,我们设置为无校验

    myCom->setStopBits(STOP_1);

    //停止位设置,我们设置为1位停止位

    myCom->setFlowControl(FLOW_OFF);

    //数据流控制设置,我们设置为无数据流控制

    myCom->setTimeout(500);

    //延时设置,我们设置为延时500ms,这个在Windows下好像不起作用

    connect(myCom,SIGNAL(readyRead()),this,SLOT(readMyCom()));

    //信号和槽函数关联,当串口缓冲区有数据时,进行读串口操作



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章