QSerailPort使用readAll()接收數據不全問題解決

使用vs2013+qt5.5.0使用QSerialPort時,因qt-add插件中沒有QSerialPort模塊,但qt安裝目錄中有QSerialPort類,故將qt安裝目錄下的QSerialPort頭文件、庫文件、dll動態庫拷貝出來,使用
vs2013包含進頭文件和庫文件路徑中,當成普通的庫來使用。


近日在使用QSerialPort發送接收串口命令時,發送給串口的命令都正常,串口都有回覆,但每次接收的串口數據都只能接收到最開始的起始符一個字節,試過readAll(),readLine(),read()都是隻能
讀到起始的第一個字節,但實際上是有一串命令數據的。使用bytesAvailable()獲取適合的數據,也是返回1。接收數據代碼如下:read()函數始終只返回1個字節,下一次再讀就返回0沒有數據了。

int SerialPort::RecvData(unsigned char* data, int size, int timeoutMs)
{
if (!m_bOpen)
	{
		WLog(LOG_ERR, "serial is not open succ");
		return -1;
	}


    if(data == NULL)
    {
		WLog(LOG_ERR, "write data == NULL");
        return -1;
    }


    bool bsucc = m_serialPort.waitForReadyRead(timeoutMs);
    if(!bsucc)
    {
		WLog(LOG_ERR, "waitForReadyRead timeout");
        return -1;
    }


    int len = 0;
    while(len < size)
    {
        int n = m_serialPort.read((char*)data+len,size-len);
        if(n==-1 || n==0)
        {
			if(n!=0) WLog(LOG_ERR, "read data err[%s],n[%d]", m_serialPort.errorString().toLocal8Bit().data(), n);
			break;
        }


        len += n;
    }


	std::string str;
	for (int i = 0; i<len; i++)
	{
		char buf[8] = { 0 };
		sprintf(buf, "%02X ", data[i]);
		str += std::string(buf);
	}
	WLog(LOG_DEBUG, "recv data[%s]",str.c_str());


    return len;
}

後來想是不是串口發送其他數據時與第一個字符會有小段時間的延時,這樣就造成每次只有第一個字節數據,後面的數據後面纔來到。因此代碼修改爲讀取一次,就進入while循環,然後等待數據
到達,waitForReadyRead()裏面的超時時間設置爲10ms,這樣不會等待太久影響接收數據的時間,如果在該時間內有數據到達就接收,否則如果超時就當成數據已經接收完成。換了此種方法後,
串口發送的數據才全部接收到。使用普通的串口工具助手能夠一次接收到所有的數據,使用QSerialPort類接收會有這樣的問題,也不知道是串口工具助手做了處理還是QSerialPort類的接收數據方面有些小bug。
int SerialPort::RecvData(unsigned char* data, int size, int timeoutMs)
{
   	if (!m_bOpen)
	{
		WLog(LOG_ERR, "serial is not open succ");
		return -1;
	}


    if(data == NULL)
    {
		WLog(LOG_ERR, "write data == NULL");
        return -1;
    }


    bool bsucc = m_serialPort.waitForReadyRead(timeoutMs);
    if(!bsucc)
    {
		WLog(LOG_ERR, "waitForReadyRead timeout");
        return -1;
    }


	int n = m_serialPort.bytesAvailable();
	QString readData = m_serialPort.readAll(); //很奇怪的情況,一次只能讀到開始的:,其他數據讀取不了,只能用下列方式來讀取
	while (1)
	{
		bsucc = m_serialPort.waitForReadyRead(10);
		if (!bsucc)
		{
			break;
		}


		n += m_serialPort.bytesAvailable();
		readData += m_serialPort.readAll();
	}
	int len = readData.size();
	memcpy(data, readData.toLocal8Bit().data(), len);
	
    /*int len = 0;
    while(len < size)
    {
        int n = m_serialPort.read((char*)data+len,size-len);
        if(n==-1 || n==0)
        {
			if(n!=0) WLog(LOG_ERR, "read data err[%s],n[%d]", m_serialPort.errorString().toLocal8Bit().data(), n);
			break;
        }


        len += n;
    }*/


	std::string str;
	for (int i = 0; i<len; i++)
	{
		char buf[8] = { 0 };
		sprintf(buf, "%02X ", data[i]);
		str += std::string(buf);
	}
	WLog(LOG_DEBUG, "recv data[%s]",str.c_str());


    return len;
}


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