| 
							aba
							 
								Гость 
							 
						 | 
						
							
								  | 
								
									
									«   : 05-02-2004 10:06 »    | 
								
								 | 
							  
							 
							Столкнулся с проблемой с портом RS-232 (COM1) - на PocketPC (ARM) функция GetCommProperties(..) возвращает максимальный размер приемного буфера (dwMaxRxQueue) равным 1! Текущий размер буфера (dwCurrentRxQueue) составляет 0 байт, причем установить другой размер этого буфера функцией SetupComm(..) не могу - ошибки нет, но размер остается нулевым. Соответственно (я подозреваю), прием данных не возможен. Даже функция ClearCommError(..) возвращает установленный флаг ошибки CE_RXOVER (1) в любом случае - когда данные физически идут (кабель подсоединен, cbInQue = 1) и не идут (кабель не подсоединен, cbInQue = 0). Под Desktop PocketPC Emulation (x86) с подсоединенным устройством на COM1 все работает на ура. Размер приемного буфера по умолчанию 1000 байт, могу установить требуемый (ограничений на максимальный размер нет), в общем все как под "нормальной" виндой (Win2000). Машина - PocketPC iPAQ 3760. Кабель на COM - МакЦентр'овский (распайку проверил - все в соответствии с информацией на кабель на COM с сайта hp.com). Не стандартное использование линий RTS (всегда 0) и DTR (всегда 1). Чтение данных осуществляется в отдельном потоке с использованием WaitCommEvent(..). Что посоветуете? Следует ли использовать WaitCommEvent для ожидания байт? Может пример кода на C++? "Попутные" вопросы: 1. В чем разница между флагами ошибки CE_OVERRUN и CE_RXOVER (функция ClearCommError)? 2. Как работает ActiveSync (экспериментировали - использует все линии), спокойно принимает и отправляет данные на той же машине? 3. Не глючный ли драйвер на этой машине - хотя в свойствах (GetCommProperties) указано, что возможно установить любую скорость передачи данных, однако реально устанавливает только стандартные!? И опять - функция SetCommState не возвращает ошибки, а нестандартная скорость не устанавливается (остается прежде установленная или 9600). 4. Как узнать какой номер порта использовать - COM1, COM2 или какой-то другой. Пока на этой машине могут "одинаково" открыться COM1 и COM2, и одинаково плохо работать.   5. Есть подозрение, что это может быть связано и с USB. Как работать с USB (особенно интересно, когда на машинке PocketPC есть USB-Host), вкратце? Приведу свой код. Вероятно, где там закралась ошибка. Инициализация порта. Далее выполняемая функция потока чтения с COM-порта (точнее их две, запрятаны в класс). DWORD CISerial::PortInitialize(LPCTSTR lpPort, DWORD dwBaudRate, HWND hWndOnMsg) {
  	COMMPROP commProp; 	CString str;
  	COMSTAT Stat; 	DWORD   dwErrors; 	// Attempt to open the serial port (COM1)
  	PortClose(); 	m_bPortOpened = FALSE; 	m_hSerialPort = CreateFile (_T("COM1:"), // Pointer to the name of the port 								  GENERIC_READ | GENERIC_WRITE,  // Access (read-write) mode 								  0,            // Share mode 								  NULL,         // Pointer to the security attribute 								  OPEN_EXISTING,// How to open the serial port 								  0,            // Port attributes 								  NULL);        // Handle to port with attribute 												// to copy 	if (m_hSerialPort == INVALID_HANDLE_VALUE){ #ifdef DEBUG_MSGS_ON 			MessageBox(_T("Unable to open serial port"), _T("Error"), MB_OK); #endif 			return GetLastError(); 	} 	 	// Set the size of the input and output buffer 	if (!SetupComm(m_hSerialPort, 1024, 0)) { #ifdef DEBUG_MSGS_ON 		MessageBox (_T("Unable to set the buffer-size parameters"), _T("Error"), MB_OK); #endif 		return GetLastError()?GetLastError():-1; 	}
      // Terminates all outstanding read and write operations and clear the buffers     VERIFY(PurgeComm(m_hSerialPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR));
  	// Initialize the DCBlength member.  	DCB PortDCB; 	FillMemory(&PortDCB, sizeof(PortDCB), 0); 	PortDCB.DCBlength = sizeof (DCB); 
  	// Get the default port setting information. 	GetCommState (m_hSerialPort, &PortDCB);
  	// Change the DCB structure settings. 	PortDCB.BaudRate = dwBaudRate; //16384;              // Current baud  	PortDCB.fBinary = TRUE;               // Binary mode; no EOF check  	PortDCB.fParity = TRUE;               // Enable parity checking  	PortDCB.fOutxCtsFlow = FALSE;         // No CTS output flow control  	PortDCB.fOutxDsrFlow = FALSE;         // No DSR output flow control  	PortDCB.fDtrControl = DTR_CONTROL_ENABLE; //DTR_CONTROL_DISABLE; 										  // DTR flow control type  	PortDCB.fDsrSensitivity = FALSE;      // DSR sensitivity  	PortDCB.fTXContinueOnXoff = FALSE;     // XOFF continues Tx  	PortDCB.fOutX = FALSE;                // No XON/XOFF out flow control  	PortDCB.fInX = FALSE;                 // No XON/XOFF in flow control  	PortDCB.fErrorChar = FALSE;           // Disable error replacement  	PortDCB.fNull = FALSE;                // Disable null stripping  	PortDCB.fRtsControl = RTS_CONTROL_DISABLE; 										  // RTS flow control  	PortDCB.fAbortOnError = FALSE;        // Do not abort reads/writes on  										  // error 	PortDCB.ByteSize = 8;                 // Number of bits/byte, 4-8  	PortDCB.Parity = NOPARITY;            // 0-4=no,odd,even,mark,space  	PortDCB.StopBits = ONESTOPBIT;        // 0,1,2 = 1, 1.5, 2 
  	// Configure the port according to the specifications of the DCB  	// structure. 	if (!SetCommState (m_hSerialPort, &PortDCB)) 	{ 	  // Could not create the read thread. #ifdef DEBUG_MSGS_ON 		MessageBox(_T("Unable to configure the serial port"), _T("Error"), MB_OK); #endif 		return GetLastError(); 	}
  	// Retrieve the time-out parameters for all read and write operations 	// on the port.  	COMMTIMEOUTS CommTimeouts; 	GetCommTimeouts (m_hSerialPort, &CommTimeouts);
  	// Change the COMMTIMEOUTS structure settings. 	CommTimeouts.ReadIntervalTimeout = MAXDWORD;   	CommTimeouts.ReadTotalTimeoutMultiplier = 0;   	CommTimeouts.ReadTotalTimeoutConstant = 0;    //5 	CommTimeouts.WriteTotalTimeoutMultiplier = 0;   	CommTimeouts.WriteTotalTimeoutConstant = 10;
  	// Set the time-out parameters for all read and write operations 	// on the port.  	if (!SetCommTimeouts (m_hSerialPort, &CommTimeouts)) 	{ 	  // Could not create the read thread. #ifdef DEBUG_MSGS_ON 		MessageBox (_T("Unable to set the time-out parameters"), _T("Error"), MB_OK); #endif 		return GetLastError(); 	}
  	if (!ClearCommBreak(m_hSerialPort)) { #ifdef DEBUG_MSGS_ON 		MessageBox (_T("Unable to restore character transmission (unBREAK)"), _T("Error"), MB_OK); #endif 		return GetLastError(); 	}
  /*	if (!SetCommMask (m_hSerialPort, EV_RXCHAR | EV_CTS | EV_DSR | EV_RING)) { #ifdef DEBUG_MSGS_ON 		MessageBox (_T("Unable to specify a set of events to be monitored for a communications device"), _T("Error"), MB_OK); #endif 		return GetLastError(); 	} */ 	if (!EscapeCommFunction(m_hSerialPort, SETDTR)){ #ifdef DEBUG_MSGS_ON 			MessageBox (_T("Unable to set DTR line"), _T("Error"), MB_OK); #endif 			return GetLastError(); 	} 	if (!EscapeCommFunction(m_hSerialPort, CLRRTS)){ #ifdef DEBUG_MSGS_ON 			MessageBox (_T("Unable to clear RTS line"), _T("Error"), MB_OK); #endif 			return GetLastError(); 	}
  //	::Sleep(10);
  #ifdef DEBUG_MSGS_ON 	if (GetCommProperties(m_hSerialPort, &commProp)) { 		str.Format(_T("Comm properties: %X(dwMaxTxQueue), %X(dwMaxRxQueue), %X(dwMaxBaud), %X(dwProvSubType), %X(dwProvCapabilities), %X(dwSettableParams), %X(dwSettableBaud), %X(wSettableData), %X(wSettableStopParity), %X(dwCurrentTxQueue), %X(dwCurrentRxQueue)"), commProp.dwMaxTxQueue, commProp.dwMaxRxQueue, commProp.dwMaxBaud, commProp.dwProvSubType, commProp.dwProvCapabilities, commProp.dwSettableParams, commProp.dwSettableBaud, commProp.wSettableData, commProp.wSettableStopParity, commProp.dwCurrentTxQueue, commProp.dwCurrentRxQueue); 		MessageBox (str, _T("SerialPort"), MB_OK); 	} #endif 	 	dwErrors = 0; 	if (ClearCommError (m_hSerialPort, &dwErrors, &Stat)) { #ifdef DEBUG_MSGS_ON 		str.Format(_T("Possible errors: CE_BREAK(%d), CE_FRAME(%d), CE_IOE(%d), CE_MODE(%d), CE_OVERRUN(%d), CE_RXOVER(%d), CE_RXPARITY(%d), CE_TXFULL(%d)\nCOMM Status information: fCtsHold(%d), fDsrHold(%d), fRlsdHold(%d), fXoffHold(%d), fXoffSent(%d), fEof(%d), fTxim(%d), cbInQue(%d), cbOutQue(%d)"), dwErrors&CE_BREAK, dwErrors&CE_FRAME, dwErrors&CE_IOE, dwErrors&CE_MODE, dwErrors&CE_OVERRUN, dwErrors&CE_RXOVER, dwErrors&CE_RXPARITY, dwErrors&CE_TXFULL, Stat.fCtsHold, Stat.fDsrHold, Stat.fRlsdHold, Stat.fXoffHold, Stat.fXoffSent, Stat.fEof, Stat.fTxim, Stat.cbInQue, Stat.cbOutQue); 		MessageBox (str, _T("SerialPort"), MB_OK); #endif 	}
 
  		//GetCommState (m_hSerialPort, &PortDCB); 		//str.Format(_T("Actual BaudRate is %d"), PortDCB.BaudRate); 		//MessageBox (str, _T("OpeningPort"), MB_OK); 		m_BaudRate = dwBaudRate; 		m_lpPortName = lpPort;
 
  	m_bPortOpened = TRUE;
 
  	//Starting working thread for reading & processing inData 	THREADPARMS* ptp = new THREADPARMS; 	ptp->pClass = this; 	ptp->hWndOnMsg = hWndOnMsg;
  	//pReadThread = AfxBeginThread(PortReadThreadProcT, ptp, THREAD_PRIORITY_HIGHEST); //LPVOID(this));
 
  	pReadThread = ::CreateThread(NULL, 0, PortReadThreadProcT, ptp, 0, NULL); //LPVOID(this)); 	if (pReadThread == NULL) { #ifdef DEBUG_MSGS_ON 			MessageBox (_T("Unable to run ReadThread"), _T("Error"), MB_OK); #endif 			return GetLastError(); 	}
  	VERIFY(SetThreadPriority(pReadThread, THREAD_PRIORITY_HIGHEST));
 
  	return 0; }
  DWORD WINAPI CISerial::PortReadThreadProcT(LPVOID pParam) { 	// Route the method to the actual object 	THREADPARMS* ptp = (THREADPARMS*) pParam; 	CISerial* pThis = reinterpret_cast<CISerial*>(ptp->pClass);     HWND hWnd = ptp->hWndOnMsg;     delete ptp; 	 	return pThis->PortReadThreadProc(hWnd); }
  UINT CISerial::PortReadThreadProc(HWND hWnd) { 	DWORD inDataCount = sizeof(m_InDataPacketCur)/sizeof(m_InDataPacketCur[0]); 	DWORD dwBytesTransferred, dwTotalBytesTransferred = 0; 	BOOL bErr; 	DWORD dwCommModemStatus; 	int dCheckErrCount = NUM_CHECKSUM_TRY; 	COMSTAT Stat; 	DWORD   dwErrors; 	BYTE readBuf[RxBufferSize]; //	int pReadBuf = 0;	//pointer to current position in readBuf
  	CString str; 	 	::PostMessage (hWnd, WM_USER_SERIAL_PORT_READING_THREAD_WAITING, (WPARAM) 0, 0); 	VERIFY(PurgeComm(m_hSerialPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR)); 	VERIFY(SetCommMask (m_hSerialPort, EV_RXCHAR | EV_CTS | EV_DSR | EV_RING | EV_BREAK | EV_ERR));
  	dwErrors = 0; 	if (ClearCommError (m_hSerialPort, &dwErrors, &Stat)) { #ifdef DEBUG_MSGS_ON 		str.Format(_T("Possible errors: CE_BREAK(%d), CE_FRAME(%d), CE_IOE(%d), CE_MODE(%d), CE_OVERRUN(%d), CE_RXOVER(%d), CE_RXPARITY(%d), CE_TXFULL(%d)\nCOMM Status information: fCtsHold(%d), fDsrHold(%d), fRlsdHold(%d), fXoffHold(%d), fXoffSent(%d), fEof(%d), fTxim(%d), cbInQue(%d), cbOutQue(%d)"), dwErrors&CE_BREAK, dwErrors&CE_FRAME, dwErrors&CE_IOE, dwErrors&CE_MODE, dwErrors&CE_OVERRUN, dwErrors&CE_RXOVER, dwErrors&CE_RXPARITY, dwErrors&CE_TXFULL, Stat.fCtsHold, Stat.fDsrHold, Stat.fRlsdHold, Stat.fXoffHold, Stat.fXoffSent, Stat.fEof, Stat.fTxim, Stat.cbInQue, Stat.cbOutQue); 		MessageBox (str, _T("SerialPort"), MB_OK); #endif 	}
  	while (m_hSerialPort != INVALID_HANDLE_VALUE) |// 		// Wait for an event to occur for the port. 		WaitCommEvent (m_hSerialPort, &dwCommModemStatus, NULL); 		// Re-specify the set of events to be monitored for the port. 		SetCommMask (m_hSerialPort, EV_RXCHAR | EV_CTS | EV_DSR | EV_RING | EV_BREAK | EV_ERR);
  		//check the event for errors 		if (dwCommModemStatus & EV_ERR)  		{ 			dwErrors = 0; 			if (ClearCommError(m_hSerialPort, &dwErrors, &Stat)) { #ifdef DEBUG_MSGS_ON 				str.Format(_T("Possible errors: CE_BREAK(%d), CE_FRAME(%d), CE_IOE(%d), CE_MODE(%d), CE_OVERRUN(%d), CE_RXOVER(%d), CE_RXPARITY(%d), CE_TXFULL(%d)\nCOMM Status information: fCtsHold(%d), fDsrHold(%d), fRlsdHold(%d), fXoffHold(%d), fXoffSent(%d), fEof(%d), fTxim(%d), cbInQue(%d), cbOutQue(%d)"), dwErrors&CE_BREAK, dwErrors&CE_FRAME, dwErrors&CE_IOE, dwErrors&CE_MODE, dwErrors&CE_OVERRUN, dwErrors&CE_RXOVER, dwErrors&CE_RXPARITY, dwErrors&CE_TXFULL, Stat.fCtsHold, Stat.fDsrHold, Stat.fRlsdHold, Stat.fXoffHold, Stat.fXoffSent, Stat.fEof, Stat.fTxim, Stat.cbInQue, Stat.cbOutQue); 				MessageBox (str, _T("SerialPort"), MB_OK); #endif 			} 		} //if (dwCommModemStatus & EV_ERR) 
  		//check for RXCHAR 		if (dwCommModemStatus & EV_RXCHAR)  		{
  			// Loop for waiting for the data. 			do  			{ 				bErr = ReadFile(m_hSerialPort, &readBuf[0], (inDataCount>dwTotalBytesTransferred)?(inDataCount-dwTotalBytesTransferred):0, &dwBytesTransferred, NULL); 				if (!bErr) { 						return GetLastError(); 				}
  				if (dwBytesTransferred > 0){ 					m_mutexSerPortRxBufferBusy.Lock(); 					//copying inData from readBuf to m_InDataPacketCur 					memcpy(&m_InDataPacketCur[dwTotalBytesTransferred], &readBuf[0], dwBytesTransferred); 					m_mutexSerPortRxBufferBusy.Unlock(); 						 					dwTotalBytesTransferred += dwBytesTransferred;
  					if (dwTotalBytesTransferred < inDataCount) 						::PostMessage (hWnd, WM_USER_SERIAL_PORT_READING_THREAD_WAITING, (WPARAM) 0, 0); 						//return 2 ; 					else { //					if (dwTotalBytesTransferred >= inDataCount) { 						if (!CISerial::ProcessInData()) { 							//Error in checksum => try to receive extra data 							::PostMessage (hWnd, WM_USER_SERIAL_PORT_READING_THREAD_SUMCHECK_ERR, (WPARAM) (NUM_CHECKSUM_TRY-dCheckErrCount), 0); 							if (dCheckErrCount--) { 								m_mutexSerPortRxBufferBusy.Lock(); 								memmove(&m_InDataPacketCur[0], &m_InDataPacketCur[1], inDataCount-1); 								m_mutexSerPortRxBufferBusy.Unlock(); 								dwTotalBytesTransferred--; 							} 							else { 								dwTotalBytesTransferred = 0; 								::PostMessage (hWnd, WM_USER_SERIAL_PORT_READING_THREAD_CANCELED, (WPARAM) 0, 0); 								return 1; 							} 						} 						else { 							dwTotalBytesTransferred = 0; 							dCheckErrCount = NUM_CHECKSUM_TRY; 							::PostMessage (hWnd, WM_USER_SERIAL_PORT_READING_THREAD_FINISHED, (WPARAM) 0, 0); 						} 					} //if (dwTotalBytesTransferred >= inDataCount) 				} //if (dwBytesTransferred > 0)
  			} while ((dwBytesTransferred > 0));//&&(dwTotalBytesTransferred < inDataCount)); 		}
  		 		if (WaitForSingleObject(m_eventSerPortReadKill, 0) == WAIT_OBJECT_0){ 			break; 		}
 
  	} //while (m_hSerialPort != INVALID_HANDLE_VALUE)
  	return 0; }
 
  Надеюсь на скорый ответ, Андрей.  
						 | 
					 
					
						
							
								| 
								 | 
							 
								| 
									« Последнее редактирование: 23-11-2007 21:39 от Алексей1153++ »
								 | 
								
									 
									Записан
								 | 
							  
						 | 
					 
				 
			 |  
		 
	 |