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: Maciak Plock [dnia: Apr 03, 2020]
wynik jest wysoko w google, przy...
gryPrzez: MAMBA [dnia: Mar 24, 2020]
Warning: Only 61104 of 61105 MBy...
gryPrzez: Random32 [dnia: Mar 18, 2020]
Witam, u mnie na polskim Window...
gryPrzez: muffintodebil [dnia: Mar 04, 2020]
aha gosicu to niezly jestes zaaw...
gryPrzez: Maciek [dnia: Feb 20, 2020]
2 karty 512 kupione na allegro: ...
gryPrzez: xd [dnia: Feb 05, 2020]
zrobiłem sposób Vin/7 na dziesią...
gryPrzez: gtremik [dnia: Jan 25, 2020]
Dzięki seba86mu :) Działa
gryPrzez: Mirek [dnia: Jan 22, 2020]
A jest rozwiązanie dla Windowsa 10?
 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