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++ »
|
Записан
|
|
|
|