遇到两个问题,一个是串口开始写数据返回为-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()));
//信号和槽函数关联,当串口缓冲区有数据时,进行读串口操作