遇到兩個問題,一個是串口開始寫數據返回爲-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();
}
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()));
//信號和槽函數關聯,當串口緩衝區有數據時,進行讀串口操作