Logowanie
 C/C++ Winapi: Komunikacja poprzez port COM (RS 232)
Po ogromnych problemach jakie miałem z komunikacją poprzez port COM (RS-232) z pewnym urządzeniem pomiarowym postanowiłem napisać krótki poradnik o tym jak komunikować się poprzez ten port. Niestety wiele poradników w sieci zamydla niesamowicie tą komunikację, a nawet jak się później okazuje, w ogóle nie działa.

Językiem programowania jaki używałem był klasyczny C (może być i C++ ), zaś środowiskiem WINAPI (czyli najbardziej klasyczne podejście do zagadnienia .

No to zaczynamy. Najpierw oczywiście podeklarujmy zmienne potrzebne nam w programie.

static DCB dcb;
static HANDLE hNumPort;
static char lpBuffor_read[33], lpBuffor_write[33];
static DWORD RS_ile;


Mamy zmienne, co one będą trzymać:
dcb - struktura DCB (Device Control Block) definiująca rodzaj połączenia
hNumPort - uchwyt do otwartego portu
lpBuffor_read, lpBuffor_write - tablice z danymi odbieranymi oraz wysyłanymi
RS_ile - zmienna trzymająca informację ile czego wysyłamy lub czytamy

Mając zdefiniowane zmienne zaczynamy zabawę z otwieraniem portu RS 232 . Najpierw otwieramy klasycznie urządzenie jako COM, tak samo jakby to by plik.


hNumPort = CreateFile("COM1", GENERIC_WRITE |
GENERIC_READ, 0, NULL,
OPEN_EXISTING, 0, NULL);



W wyniku funkcji CreateFile otrzymamy uchwyt do pliku, a raczej urządzenie do którego możemy zarówno pisać jak i odczytywać . W naszym przypadku jest to port COM1 lub inaczej COM A.

Mając uchwyt musimy powiedzieć z jakimi parametrami będzie pracował nasz port . Do tego służy struktura DCB. Przykład jej inicjacji.


dcb.DCBlength = sizeof(dcb);

dcb.BaudRate = CBR_9600;
dcb.fParity = TRUE;
dcb.Parity = EVENPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.ByteSize = 7;

dcb.fDtrControl = DTR_CONTROL_ENABLE;
dcb.fRtsControl = RTS_CONTROL_ENABLE;

dcb.fOutxCtsFlow = FALSE;
dcb.fOutxDsrFlow = FALSE;
dcb.fDsrSensitivity = FALSE;
dcb.fAbortOnError = FALSE;
dcb.fOutX = FALSE;
dcb.fInX = FALSE;
dcb.fErrorChar = FALSE;
dcb.fNull = FALSE;


W zasadzie nas obchodzą najbardziej początkowe linijki, pozwoliłem sobie je skomentować.


dcb.BaudRate = CBR_9600; // prędkość transmisji, CBR_110, CBR_300, CBR_600, CBR_1200, CBR_2400, CBR_4800, CBR_9600
dcb.fParity = TRUE; //TRUE jeśli ustawiamy kolejną opcję dla sprawdzenia parzystości
dcb.Parity = EVENPARITY; //Ustawienie parzystości: EVENPARITY (parzysta), MARKPARITY (bit parzystości 1), NOPARITY (bez bitu parzystości), ODDPARITY (nieparzysta)
dcb.StopBits = ONESTOPBIT; // Ustawienie bitu stopu: ONESTOPBIT (jeden bit), TWOSTOPBITS (dwa bity)
dcb.ByteSize = 7; //Liczba bitów wysyłanych/odebranych danych (UWAGA wartościod 5 do 8)

dcb.fDtrControl = DTR_CONTROL_ENABLE; //Kontrola linii DTR: DTR_CONTROL_DISABLE (sygnał nieaktywny), DTR_CONTROL_ENABLE (sygnał aktywny), DTR_CONTROL_HANDSHAKE
dcb.fRtsControl = RTS_CONTROL_ENABLE; //Kontrola linii RTS: RTS_CONTROL_DISABLE (sygnał nieaktywny), RTS_CONTROL_ENABLE (sygnał aktywny), RTS_CONTROL_HANDSHAKE



Te wartości poznasz dzięki instrukcji urządzenia, z którym się komunikujesz. Czasami widnieje inny zapis tego, np "COM1,9600,e,7,1". Tutaj "e" oznacza rodzaj kontroli parzystości EVENPARITY, potem liczba bitów do przesyłania danych i na końcu bit parzystości.

Skoro mamy już zainicjowaną DCB połączmy się z naszym portem. Służy do tego funkcja

SetCommState(hNumPort, &dcb);


Zwraca ona prawdę lub fałsz w zależności od tego czy połączenie nastąpiło czy nie. Zawszy warunkiem IF sprawdzaj czy możesz pisać/czytać czy też nie.

W tej chwili możemy swobodnie pisać i czytać z portu.

Dajmy na to, że chcemy wysłąć komendę, użyjmy do tego komendy WriteFile, tak jakbyśmy pisali do pliku.


strcpy(lpBuffor_write, "RES0070002");// Niech to będzie przykładowe polecenie dla urządzenia
WriteFile(hNumPort, lpBuffor_write, strlen(lpBuffor_write), &RS_ile, 0);



Jak wysyłamy dane to zawsze można je odczytać. Czytanie to klasyczny ReadFile. Odczytajmy sobie 15 znaków

ReadFile(hNumPort, lpBuffor_read, 15, &RS_ile, 0);


Dane można czytać w pętli, interpretować, przeliczać. Ja osobiście polecam w przypadku WINAPI używania Timera systemowego i czytać tylko w trakcie tyknięć zegara. A zatem w przypadku przechwycenia komunikatu WM_TIMER odczytać daną i jak można nawet zatrzymać urządzenie z którego czytamy. Przetworzyć wszystko i na nowo wysłać prośbę o kolejną daną w momencie nowego taktu TIMERa. Ba, można przecież zawsze przy użyciu funkcji KillTimer oraz SetTimer zatrzymywać sobie zegar, przetwarzać złożone operacje a na końcu na nowo uruchamiać zegar.

Na koniec jedna uwaga, zawsze zamykajmy to co otworzyliśmy. A zatem w naszym przypadku mamy otwarty uchwyt do naszego portu. Trzeba go koniecznie zamknąć.

CloseHandle(hNumPort);


W razie jakichkolwiek problemów zapraszam na FORUM. Z chęcią pomożemy.
 Reklama

 Komentarze
#1 | Janosik dnia 05/09/2012 09:22
Jesteś wielki! Bardzo mi pomogłeś.
#2 | olo dnia 28/02/2013 12:52
podpisuje się pod podziękowaniami Smile
#3 | Sobiesław dnia 11/04/2013 17:31
gdyby ktoś nie mógł otworzyć portu komendą;
hNumPort = CreateFile("COM1", GENERIC_WRITE |gENERIC_READ, 0, NULL, OPEN_EXISTING, 0, NULL);
zalecam wpisanie "\\\.\COM1" a w przypadku wartości dziesiętnych "\\\.\\COM25" to tak z własnego doświadczenia
#4 | Overkiller dnia 29/11/2013 10:15
Doskonały poradnik! Skórę mi ratujesz Smile
#5 | Mateuscod dnia 27/04/2014 20:25
Fajny poradnik ,ale mam pytankoSmile Czy w WINAPI istnieje mozliwosć wyszukania istniejacych portow ?
#6 | matka dnia 08/11/2014 16:43
Stary dzieki wielkieeeeeee Grin
#7 | raaasz dnia 19/12/2014 08:59
Mateuscod> próbujesz otwierać wszystkie porty po kolei, i sprawdzasz czy się powiodło. Jeśli port jest, to dopisujemy do listy dostępnych i zamykamy, jak nie ma portu lub jest otwarty przez inną aplikację to mamy błąd więc szukamy dalej
#8 | Borys_Horoneskul dnia 12/03/2019 21:01
Dzięki. Przydało się, zadziałało. Smile
 Dodaj komentarz
Dla wszystkich komentarzy wymagana jest ich akceptacja przez moderatora.

Nick:



AntyBOT (dla niezalogowanych): Napisz słowo hotfix wielkimi literami

/articles.php?article_id=334

 Artykuły
Polecany artykuł


Jak walczyć z pobieraczkiem? Jak odstąpić od umowy? O tym w artykule.
 Ostatnie komentarze
gryPrzez: stan2 [dnia: May 09, 2019]
A czy ma adsl do połączenia z ne...
gryPrzez: stan2 [dnia: May 09, 2019]
Czy połączę się z netią przez r...
gryPrzez: Projekt Zero2 [dnia: Mar 21, 2019]
Z pewnością coś jeszcze podeślem...
gryPrzez: Alla84 [dnia: Mar 18, 2019]
Dziękuję!!!!! Uratowaliście mi t...
gryPrzez: Borys_Horoneskul [dnia: Mar 12, 2019]
Dzięki. Przydało się, zadziałało...
gryPrzez: MKU [dnia: Feb 23, 2019]
Dziękuje za pomoc w rozwiązaniu ...
gryPrzez: Kamil [dnia: Feb 17, 2019]
HDAUDIO\FUNC_01& VEN_10EC&DEV_08...
gryPrzez: Werno [dnia: Feb 11, 2019]
Witam, mam problem z uszkodzenie...
 Gry
Polecany artykuł


Quake

Klasyk FPS w wersji flash.
 Programy
Polecany artykuł


Tapin Radio Darmowa aplikacja służąca do słuchania i nagrywania radia internetowego
 Recenzje
Polecana recenzja


Sleeping Dogs
Policjant pod przykrywką rozpracowuje Triadę.
 Facebook