Port równoległy LPT w C na Linux – obsługa portu i sterowanie diodami LED

Port LPT bardzo dobrze nadaje się do pierwszych prób skomunikowania komputera z zewnętrzną elektroniką. Jest to możliwe dzięki temu, że w przeciwieństwie do inny portów (np. COM, USB, etc.) możemy ustawić dane wyjście w stan wysoki (lub niski) i stan ten będzie się utrzymywać.

Zacznijmy od określenia, które wyprowadzenia będą dla nas interesujące. Pomoże w tym poniższa ilustracja z Wikipedii.

lpt_pint

Co prawda ta się wysterować wszystkie z pokazanych wyprowadzeń, ale dla prostoty, zajmiemy się tylko liniami danych. Na ilustracji opisane są one jako Data Out. Jest ich 8, czyli tyle ile bitów w bajcie. Dzięki temu, możemy wysterować wszystkie linie danych jednym bajtem wysłanym na port.

Teraz podłączanie diod LED. Diody powinniśmy podłączać między masę (na ilustracji to Ground) oraz linię danych poprzez rezystor (np. 200 Ohm). Podłączenie samej diody możę spowodować spalenie portu, gdyż popłynie zbyt duży prąd. Jednak wbrew temu, na poniższym rysunko pokazuje podłączone same diody, gdyż eksperymentalnie sprawdziłem, że port wciąż funkcjonuje. Jest tak, gdyż na mojej płycie głównej, port sam ogranicza maksymalny prąd, ale jak już pisałem, u kogoś innego może od tego uszkodzić się port. Pamiętamy jeszcze tylko, że diody LED są spolaryzowane, czyli działąją tylko, gdy są podłączone w dobrym kierunku. Odwrotne podłączenie nie powoduje uszkodzenia, ale dioda świcić tak nie będzie.

lpt_led

Teraz czas na kod w C. Wygląda on następująco.

#include <sys/io.h>
#include <stdio.h>
#include <stdlib.h>
 
#define BASEPORT 0x378
 
int main()
{
	if( ioperm(BASEPORT, 3, 1) ) {
		perror( "ioperm" );
		exit( 1 );
	}
 
	int tab[8];
	tab[0] = 1;
	tab[1] = 2;
	tab[2] = 4;
	tab[3] = 8;
	tab[4] = 16;
	tab[5] = 32;
	tab[6] = 64;
	tab[7] = 128;
 
	int i;
 
	while( 1 )
	{
		for( i=0; i<8; i++)
		{
			outb( tab[i], BASEPORT );
			usleep( 100000 );
			printf( "status: %d\n", tab[i] );
		}
	}
}

Stała BASEPORT, która ma wartość 0×378 to nic innego jak standardowy w komputerach PC adres portu LPT dla linii danych. Następnie za pomocą funkcji ioperm prosimy system o dostęp do portu. Pierwszy parametr to początkowy adres portów, do których chcemy uzyskać dostęp. Drugi parametr to liczba bajtów, do których chcemy uzyskać dostęp. My wykorzystujemy tylko jeden bajt, ale cały port LPT jest obsługiwany przez 3 bajty. Pozostałymi 2 bajtami sterujemy pozostałe linie. Na nasze potrzeby wystarczyłby w tym miejscu 1 bajt, ale przyszłościowo wstawiłem w tym miejscu 3. Trzeci parametr określa, czy nadajemy, czy odbieramy dostęp – my chcemy uzyskać. Dalej zdefiniowałem tabicę, która określa jakie wartości będę przesyłał do port. Odpowiadają one 1-nce na kolejnych bitach bajtu, a więc kolejnym diodom LED podłączonym do portu. Następnie w pętli wysyłam do portu bajt za pomocą funkcji outb. Po każdym bajcie czekam 100ms (0,1s) za pomocą funkcji usleep. Aktualnie wysyłany bajt wypisuje na konsoli.

Teraz czas skompilować nasz program. Zrealizujemy to poniższym polecenim. Zakładamy oczywiście, że powyższy kod zapisaliśmy w pliku lpt.c, a wynikowy program będzie umieszczony w plik lpt.

gcc -o lpt lpt.c

Gdybyśmy nie mieli zainstalowanego kompilatora gcc, to jeżeli w naszym systemie jest yum (np. na Fedorze), to możemy sobie go zainstalować wydając polecenie, jak poniżej.

yum install gcc

Aby uruchomić program potrezbujemy uprawnień administratora, gdyż zwykły użytkownik nie może bezpośrednio zapisywać do portu. Uprawnienia root możemy sobie przydzielić poniższym poleceniem i podaniem hasła.

su

No i pozostaje tylko odpalić program poniższą komendą. Oczywiście zakłądamy że jesteśmy w folderze, gdzie skompilował się nasz program.

./lpt