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.