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()));

    //信號和槽函數關聯,當串口緩衝區有數據時,進行讀串口操作



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