> kaip ant C# parasyt panasia programele kaip hyper terminal.. > pati problema aprasyta cia: http://www.xoom.lt/2010/05/20/tipo-skopas-voltage-logger/ Kodėl kodo neduodi, kad iškart matytųsi, kas negerai? Nuskaitinėti duomenis be buferizavimo, vos tik jiems atėjus, nėra prasmės. Čia kompas neužsiima raketos žemė-oras vairavimu, kad reikėtų išjungti vidinį UART buferį (default'as windowsuose 14 baitų), pačiam aptarnauti INT 0C/0B ir apskritai naudoti kokią nors realtime operacinę. O kur dar USB/RS232 keitikliai, juose vėlinimai išvis neprognozuojami. Bet koks PC-based oscilografas ar panaši duomenų surinkimo sistema neišvengia buferizavimo. Pakanka, kad buferio pildymas truktų kokią pusę sekundės ar panašiai, nes toliau vėlinimas darosi pastebimas ir nervina. Be to, skaityti iš porto turi atskiras thread'as. Kai jam skirtas buferis prisipildo, tada duoda signalą skaičiavimo bei atvaizdavimo thread'ui ir ima pildyti antrą buferį. Paskui atitinkamai sukeičia. Kartą dariau GPS logerį savo mobiliakui. Kuo primityvesnį, kad naudotų mažiau resursų ir nepamestų duomenų net vykstant pokalbiui. Taigi jokių C#. Štai priimantis thread'as: --------------------------------------------------------------------------- while (!stopASAP) { /* open the port anew and set it up */ if (hComm != INVALID_HANDLE_VALUE) CloseHandle(hComm); hComm = CreateFile(tszComm, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if ((hComm != NULL) && (hComm != INVALID_HANDLE_VALUE)) { DCB dcb; COMMTIMEOUTS ct; SetupComm(hComm, BUFSIZE / 4, BUFSIZE * 2); PurgeComm(hComm, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); if (GetCommState(hComm, &dcb)) { dcb.BaudRate = CBR_38400; dcb.ByteSize = 8; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; if (!SetCommState(hComm, &dcb)) if (!dwReadErrorCode || !fReadErrorHold) { dwReadErrorCode = GetLastError(); tszReadErrorLoc = _T("s"); fReadErrorHold = TRUE; } } else if (!dwReadErrorCode || !fReadErrorHold) { dwReadErrorCode = GetLastError(); tszReadErrorLoc = _T("g"); /* fReadErrorHold not set: unavailability of this call is not critical, especially for virtual ports like "External GPS" that constantly fail with ERROR_NOT_READY */ } /* timeouts will minimize amount of incomplete reads below */ ct.ReadTotalTimeoutConstant = ct.ReadTotalTimeoutMultiplier = 0; ct.WriteTotalTimeoutConstant = ct.WriteTotalTimeoutMultiplier = 0; ct.ReadIntervalTimeout = 1000; /* we expect some data each second */ SetCommTimeouts(hComm, &ct); /* setup finished, we can read now */ do { LPBYTE pbReadBuf; DWORD nReadAt; DWORD nToRead; DWORD nReadCount; nReadAt = 0; if (!fBufIdx) pbReadBuf = abBuffer1; else pbReadBuf = abBuffer2; /* ensure that the buffer is full */ fill: nToRead = BUFSIZE - nReadAt; if (!ReadFile(hComm, pbReadBuf + nReadAt, nToRead, &nReadCount, NULL)) /* a blocking call if no Bluetooth connection yet; however after a connection is established for the first time, and no data comes for the given time interval, ReadFile returns with no bytes read after that interval. Handy to detect a lost connection etc. */ { if (!dwReadErrorCode || !fReadErrorHold || (tszReadErrorLoc[0] == _T('g'))) { dwReadErrorCode = GetLastError(); tszReadErrorLoc = _T("r"); fReadErrorHold = TRUE; } break; } nReadAt += nReadCount; nBytesReadTotal += nReadCount; if ((nReadCount != nToRead) && !stopASAP) { ClearCommError(hComm, &nReadCount, NULL); goto fill; } /* reset state but only if the previous code was displayed */ if (!fReadErrorHold) dwReadErrorCode = 0; pbWriteBuf = pbReadBuf; nAvailSize = BUFSIZE; fBufIdx = !fBufIdx; PulseEvent(heDataAvail); } while (!stopASAP); } else if (!dwReadErrorCode || !fReadErrorHold) { tszReadErrorLoc = _T("c"); dwReadErrorCode = GetLastError(); fReadErrorHold = TRUE; } /* comm port may appear again after a while */ Sleep(1000); } --------------------------------------------------------------------------- BUFSIZE paskutiniu metu buvo 1024 ir gavosi pats tas. "goto fill": bus atiduotas tik pilnas buferis. Antras thread'as, kai nebeturi duomenų apdorojimui, su WaitForSingleObject laukia PulseEvent šitame thread'e. Su "overlapped" tipo operacijomis galbūt pavyktų viską padaryti ir vieninteliame thread'e. Bet Windows Mobile jų nepalaiko. Naudoti kaip Hyperterminal -- esą paspausi mygtuką tame ATtiny ir ekrane iškart atsiras simbolis -- tikrai nepavyks, paskirtis ne tokia. -- saimhe