[ Pobierz całość w formacie PDF ]
.Kodnaszej funkcji Write_Comm() zapisującej dane do portu będzie mógł przyjąć następującąuproszczoną postać:int __fastcall Write_Comm(HANDLE hCommDev, LPCVOID lpBuffer,DWORD nNumberOfBytesToWrite){DWORD NumberOfBytesWritten;if (WriteFile(hCommDev, lpBuffer, nNumberOfBytesToWrite,&NumberOfBytesWritten, NULL) > 0){WaitCommEvent(hCommDev, &fdwEvtMask, NULL);100 return TRUE;}elsereturn FALSE;}Zwróćmy jeszcze uwagę, że nagłówek tej funkcji mógłby być równie dobrze zapisany tradycyjnie:int __fastcall Write_Comm(HANDLE hCommDev, const void *Buffer,DWORD nNumberOfBytesToWrite)lub nawet jako:int __fastcall Write_Comm(., void *Buffer,.)// LPVOID lpBufferDeklarując wskaznik bufora reprezentującego pewien obszar pamięci operacyjnej przy wysyłaniudanych, wcale nie musimy wskazywać na jakiś stały obszar tej pamięci, chociaż API właśnie tosugeruje.Pamiętajmy, że operujemy na C-łańcuchach.Jeżeli w buforze wyjściowym znajdzie sięNUL bajt (nazywany niekiedy zerowym ogranicznikiem) kończący łańcuch, nadawanie zostanieprzerwane.Nieco inaczej będzie to wyglądało w przypadku danych odbieranych, co zostanieomówione za chwilę.PRZYPOMNIJMYDane typu LPVOID (void *), będąc wskazaniami adresowymi, nie wskazują na obiekty.Lokalizują jedynie pewne obszary pamięci operacyjnej.Pokazany sposób zapisu funkcji wysyłającej komunikaty do łącza szeregowego nie jest oczywiściejedynym z możliwych.Można ją zapisać w sposób maksymalnie uproszczony, jedynie z dwomaparametrami formalnymi, które tak naprawdę są dla nas najistotniejsze.Będą nimi: identyfikatorportu oraz liczba bajtów do wysłania:char Buffer_O[cbOutQueue]; // bufor danych wyjściowych.int __fastcall Write_Comm(HANDLE hCommDev,DWORD nNumberOfBytesToWrite){.if (WriteFile(hCommDev, &Buffer_O[0],nNumberOfBytesToWrite, &NumberOfBytesWritten, NULL) > 0){.return TRUE;}else101 return FALSE;}Jeżeli zdecydujemy się na taki zapis, wówczas jednym z parametrów wywoływanej funkcji APIWriteFile() musi być jawnie użyty bufor danych wyjściowych Buffer_O.Standardowoargumenty funkcji w C++ przekazujemy przez wartość.W ten sposób powodujemy utworzeniekopii argumentu w wywoływanej funkcji, zapobiegając tym samym możliwości zmodyfikowaniajego początkowej wartości.W przypadku naszej funkcji Write_Comm() będzie tonNumberOfBytesToWrite, czyli liczba bajtów do wysłania będąca jednocześnie parametremfunkcji Win32 API WriteFile().Jeżeli z kolei funkcja ma zmodyfikować wartości zmiennychbędących jej argumentami, parametry powinny być jawnie zadeklarowane jako wskazniki.Jest jeszcze wiele rzeczy, których nie uwzględniliśmy.Naprawdę niezawodna aplikacjapowinna mieć parę dodatkowych zabezpieczeń.Wszystkie je omówimy po kolei w następnychpodrozdziałach.Obecnie ważne jest dla nas to, że użyliśmy wszystkich omówionych do tej poryfunkcji Win32 API, poznaliśmy w jakiej kolejności należy je wywoływać.Po skompletowaniucałego programu przekonasz się, że mimo swojej prostoty będzie on funkcjonalny.Teraz, kiedypoznaliśmy, w jaki sposób można coś  powiedzieć do urządzenia, czas najwyższy, abyśmynauczyli się  słuchać i  rozumieć jego odpowiedzi.Segment odbierający komunikatyDRUGIE PRAWO SODDA:Wcześniej czy pózniej i tak musi nastąpić najgorszy z możliwych splotów okoliczności.Uzupełnienie:Każdy system musi być zaprojektowany w taki sposób, aby stawić czoła najgorszemu zmożliwych splotów okoliczności.Każdy, kto kiedykolwiek interesował się komunikacją komputerową wie, żewystępowanie błędów w tym procesie jest czymś nieuniknionym i poniekąd naturalnym.Ustaleniesposobu reagowania na wystąpienie błędu w czasie transmisji szeregowej jest zawsze bardzoistotnym elementem aplikacji.Przypominamy sobie z poprzednich rozdziałów, że istnieje pewiensposób zabezpieczenia danych przed zafałszowaniem w czasie ich przekazu.Sposobem tym jestkontrola bitu parzystości.Jest on jednak mało efektywny.Korzystając z zasobów struktury DCB,można w pewnym stopniu zabezpieczyć się przed odbieraniem przekłamanych danych.Wystarczyw części konfiguracyjnej aplikacji odwołać się do jednego ze znaczników DCB, a mianowicie dofAbortOnError (patrz tabela 5.5.), pisząc:dcb.fAbortOnError = TRUE;102 co spowoduje wstrzymanie wykonywania wszelkich operacji wysyłania i odbierania danych przywykryciu jakiegokolwiek błędu w komunikacji z portem szeregowym.Reinicjalizacja odbioru inadawania poprzez port komunikacyjny identyfikowany przez hCommDev nastąpi po wywołaniufunkcji:BOOL ClearCommError(HANDLE hCommDev,LPDWORD lpErrors,LPCOMSTAT lpStat);gdzie:lpErrors jest wskaznikiem do 32-bitowej danej typu DWORD, reprezentującej jeden z typówbłędów:CE_BREAK  wykryto przerwanie połączenia.CE_DNS  urządzenie przyłączone do łącza równoległego nie zostało określone (Win 9x).CE_FRAME  wystąpił błąd protokołu ramki danych.CE_IOE  podczas komunikacji nastąpił jakiś błąd wejścia-wyjścia ( Input-Output).CE_MODE  żądanie nadawania nie jest podtrzymywane lub identyfikator portu(urządzenia) ma błędną specyfikację.CE_OOP  urządzenie przyłączone do łącza równoległego sygnalizuje brak papieru, co jesttypowe dla drukarek, faksów, niektórych faksmodemów (Win 9x).CE_OVERRUN  nastąpiło całkowite wypełnienie wejściowego bufora danych.Następnyznak będzie zignorowany.CE_PTO  został przekroczony czas oczekiwania na połączenie z portem równoległym, tzw.przeterminowanie czasu połączenia (Win 9x).CE_RXOVER  bufor wejściowy został przepełniony.Albo nie ma w nim już fizyczniemiejsca, albo został odebrany jakiś znak następujący po znaku końcapliku EOF.CE_RXPARITY  wykryto błąd niezgodności kontroli parzystości.CE_TXFULL  próba transmisji znaku przy całkowitym wypełnieniu bufora wyjściowego.Zbiór wartości, na które wskazuje lpErrors, można z powodzeniem traktować jako maski bitowez możliwością wykonywania na nich odpowiednich działań.Zawarta tam pełna informacja możebyć aktualnie zapisana na 16 bitach [ Pobierz całość w formacie PDF ]

  • zanotowane.pl
  • doc.pisz.pl
  • pdf.pisz.pl
  • swpc.opx.pl
  •