<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://www.mikrocontroller.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=User-s</id>
	<title>Mikrocontroller.net - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="https://www.mikrocontroller.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=User-s"/>
	<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/articles/Spezial:Beitr%C3%A4ge/User-s"/>
	<updated>2026-04-22T16:08:28Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.39.7</generator>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Ports_benutzen_(GCC)&amp;diff=27453</id>
		<title>Ports benutzen (GCC)</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Ports_benutzen_(GCC)&amp;diff=27453"/>
		<updated>2008-04-13T15:23:30Z</updated>

		<summary type="html">&lt;p&gt;User-s: /* I2C Treiber installieren (Kernel 2.6) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Linux]]&lt;br /&gt;
[[Category:PC-Programmierung]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Einleitung==&lt;br /&gt;
&lt;br /&gt;
Über die Ansteuerung der Schnittstellen unter Linux findet man im Internet überall etwas anderes. Die einen sagen, man soll die Schnittstellen über ihre I/O-Adresse (0x3F8,0x2F8,0x378,...) ansteuern, allerdings ist das nicht portabel und funktioniert nur mit Root-Rechten.&lt;br /&gt;
&lt;br /&gt;
Die hier vorgestellte Methode ermöglicht folgendes:&lt;br /&gt;
* Zugriff auf Schnittstellen &#039;&#039;&#039;ohne&#039;&#039;&#039; Root-Berechtigung&lt;br /&gt;
* Zugriff auf &#039;&#039;&#039;alle&#039;&#039;&#039; parallelen oder seriellen Schnittstellen, egal ob USB oder nicht&lt;br /&gt;
* einfaches Portieren des Codes auf MacOSX, FreeBSD, ...&lt;br /&gt;
&lt;br /&gt;
Für den weiteren Artikel werden C/C++ Kenntnisse vorausgesetzt, denn die meisten Funktionen werden mit C-Code erklärt.&lt;br /&gt;
&lt;br /&gt;
==Allgemein==&lt;br /&gt;
&lt;br /&gt;
===Zugriffsrechte===&lt;br /&gt;
Damit man auf die Schnittstellen zugreifen kann braucht man die passende Berechtigung. Auf meinem Debian-System sehen die Zugriffsrechte so aus:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:/# ll /dev/ttyUSB? /dev/ttyS? /dev/parport?&lt;br /&gt;
crw-rw----    1 root     lp        99,   0 Feb 28 16:00 /dev/parport0&lt;br /&gt;
crw-rw----    1 root     lp        99,   1 Feb 28 16:00 /dev/parport1&lt;br /&gt;
crw-rw----    1 root     lp        99,   2 Feb 28 16:00 /dev/parport2&lt;br /&gt;
crw-rw----    1 root     lp        99,   3 Feb 28 16:00 /dev/parport3&lt;br /&gt;
crw-rw----    1 root     dialout    4,  64 Jan 22 01:11 /dev/ttyS0&lt;br /&gt;
crw-rw----    1 root     dialout    4,  65 Jan 22 01:11 /dev/ttyS1&lt;br /&gt;
crw-rw----    1 root     dialout    4,  66 Jan 22 01:11 /dev/ttyS2&lt;br /&gt;
crw-rw----    1 root     dialout    4,  67 Jan 22 01:11 /dev/ttyS3&lt;br /&gt;
crw-rw----    1 root     dialout  188,   0 Jan 22 01:11 /dev/ttyUSB0&lt;br /&gt;
crw-rw----    1 root     dialout  188,   1 Jan 22 01:11 /dev/ttyUSB1&lt;br /&gt;
crw-rw----    1 root     dialout  188,   2 Jan 22 01:11 /dev/ttyUSB2&lt;br /&gt;
crw-rw----    1 root     dialout  188,   3 Jan 22 01:11 /dev/ttyUSB3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit der User auf die Schnittstellen zugreifen kann, muss er in die Gruppen &amp;quot;lp&amp;quot; und &amp;quot;dialout&amp;quot; eingetragen werden. Wie das funktioniert kann man hier nachlesen: http://www.tuxhausen.de/kurs_user.html&lt;br /&gt;
&lt;br /&gt;
==Schnittstellen öffnen und schliessen==&lt;br /&gt;
===Schnittstelle mit open(2) öffnen===&lt;br /&gt;
Bevor man auf eine Schnittstelle zugreifen kann muss man diese mit open(2) öffnen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int port;&lt;br /&gt;
port = open(&amp;quot;/dev/ttyS0&amp;quot;, O_RDWR);&lt;br /&gt;
if ( port == -1 )&lt;br /&gt;
{&lt;br /&gt;
  // FEHLER: Port konnte nicht geöffnet werden!&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn das Programm beendet wird sollte man diese auch wieder schliessen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
close( port );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Schnittstelle mit fopen(3) öffnen===&lt;br /&gt;
&lt;br /&gt;
Öffnen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
FILE* port;&lt;br /&gt;
port = fopen(&amp;quot;/dev/ttyS0&amp;quot;, &amp;quot;rw&amp;quot;);&lt;br /&gt;
if ( port == NULL )&lt;br /&gt;
{&lt;br /&gt;
  // ein FEHLER ist aufgetreten&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schliessen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fclose (port);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Warum open(2) und nicht fopen(3)?===&lt;br /&gt;
&lt;br /&gt;
Der Zugriff mittels open(2) ist vorzuziehen, da hierbei deutlich flexiblere IO-Möglichkeiten (z.B. select, poll) zur Verfügung stehen, die sonst nur mittels Umweg über fileno(3) zu erreichen sind. Ferner kann die libc Schreibzugriffe mit fputs o.ä. Puffern, so dass man, um sicher zu stellen, dass die Daten auch tatsächlich übertragen wurden, fsync(3) aufrufen muss.&lt;br /&gt;
&lt;br /&gt;
Natürlich funktionieren beide Methoden.&lt;br /&gt;
&lt;br /&gt;
===Die Namen der Schnittstellen===&lt;br /&gt;
&lt;br /&gt;
Die Schnittstellen die man benutzen kann sind unter anderem:&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=5&lt;br /&gt;
| &#039;&#039;die RS-232  Schnittstellen&#039;&#039;&lt;br /&gt;
| /dev/ttyS0&lt;br /&gt;
| /dev/ttyS1&lt;br /&gt;
| /dev/ttySx&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;die USB-RS232 Schnittstellen&#039;&#039;&lt;br /&gt;
| /dev/ttyUSB0&lt;br /&gt;
| /dev/ttyUSB1&lt;br /&gt;
| /dev/ttyUSBx&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;die parallelen Schnittstellen&#039;&#039;&lt;br /&gt;
| /dev/parport0&lt;br /&gt;
| /dev/parport1&lt;br /&gt;
| /dev/parportx&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;die USB-parallelen Schnittstellen&#039;&#039;&lt;br /&gt;
| /dev/?&lt;br /&gt;
| /dev/?&lt;br /&gt;
| /dev/?&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;der I2C-/SM-Bus&#039;&#039;&lt;br /&gt;
| /dev/i2c-0&lt;br /&gt;
| /dev/i2c-1&lt;br /&gt;
| /dev/i2c-x&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Serielle Schnittstelle==&lt;br /&gt;
&lt;br /&gt;
Die Serielle Schnittstelle besitzt 3 Ausgangspins (TX,RTS,DTR) und 5 Eingangspins (RX,DCD,DSR,CTS,RI).&lt;br /&gt;
&lt;br /&gt;
Der Zugriff auf die serielle Schnittstelle erfolgt entweder:&lt;br /&gt;
* auf Protokollebene, oder&lt;br /&gt;
* auf Pinebene (Pin1 -&amp;gt; an, Pin2 -&amp;gt; aus, ...)&lt;br /&gt;
&lt;br /&gt;
===Die Pinebene===&lt;br /&gt;
&lt;br /&gt;
Die Pins der Seriellen Schnittstelle können &#039;&#039;&#039;ohne vorherige Konfiguration&#039;&#039;&#039; gelesen/gesetzt werden. Der Zugriff auf die Pins erfolgt über ioctl(2). Dabei muss beachtet werden dass dieser Zugriff &#039;&#039;&#039;ohne Interrupts&#039;&#039;&#039; und &#039;&#039;&#039;ohne FIFO&#039;&#039;&#039; erfolgt, daher ist es eine polling-only Lösung, aber für die Programmierung eines Chip&#039;s über ISP oder die Ansteuerung eines Schieberegisters reicht es allemal.&lt;br /&gt;
&lt;br /&gt;
====Die Pins DCD,DSR,CTS,RI lesen====&lt;br /&gt;
Die Eingangspins werden mit ioctl(2) gelesen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int i;&lt;br /&gt;
ioctl( port, TIOCMGET, &amp;amp;i );&lt;br /&gt;
&lt;br /&gt;
// Jetzt kann abgefragt werden welche Pins gesetzt sind:&lt;br /&gt;
&lt;br /&gt;
if ( (i &amp;amp; TIOCM_CD )==TIOCM_CD  ) // Pin DCD&lt;br /&gt;
{&lt;br /&gt;
  // am Pin liegt Spannung an (3 bis 12V)&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  // am Pin liegt keine Spannung an (0 bis -12V)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( (i &amp;amp; TIOCM_DSR)==TIOCM_DSR ) // Pin DSR&lt;br /&gt;
 ...&lt;br /&gt;
if ( (i &amp;amp; TIOCM_CTS)==TIOCM_CTS ) // Pin CTS&lt;br /&gt;
 ...&lt;br /&gt;
if ( (i &amp;amp; TIOCM_RI )==TIOCM_RI  ) // Pin RI&lt;br /&gt;
 ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Die Pins RTS,DTR setzen/löschen====&lt;br /&gt;
Aktiviert wird RTS,DTR so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int i = 0;&lt;br /&gt;
if (...) i |= TIOCM_RTS; // Pin RTS wird aktiviert (12V)&lt;br /&gt;
if (...) i |= TIOCM_DTR; // Pin DTR wird aktiviert (12V)&lt;br /&gt;
ioctl( port, TIOCMBIS, &amp;amp;i );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Und deaktiviert so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int i = 0;&lt;br /&gt;
if (...) i |= TIOCM_RTS; // Pin RTS wird deaktiviert (-12V)&lt;br /&gt;
if (...) i |= TIOCM_DTR; // Pin DTR wird deaktiviert (-12V)&lt;br /&gt;
ioctl( port, TIOCMBIC, &amp;amp;i );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Den Pin TX setzen/löschen====&lt;br /&gt;
Aktiviert wird TX so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ioctl( port, TIOCSBRK, NULL );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Und deaktiviert so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ioctl( port, TIOCCBRK, NULL );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Die Protokollebene===&lt;br /&gt;
Üblicherweise steuert man die serielle Schnittstelle nicht auf der Pinebene an, sondern auf der Protokollebene. Dabei übernimmt die Hardware die Aufgabe, die Pins zu steuern. Um die Schnittstelle auf der Protokollebene zu benutzen, muss man:&lt;br /&gt;
&lt;br /&gt;
* die Schnittstelle öffnen&lt;br /&gt;
* die Schnittstelle konfigurieren&lt;br /&gt;
* die Daten mit read(2) lesen und mit write(2) schreiben&lt;br /&gt;
* die Schnittstelle schließen&lt;br /&gt;
&lt;br /&gt;
====Konfigurieren====&lt;br /&gt;
Vor der Benutzung muss die RS232-Schnittstelle erstmal konfiguriert werden. Dazu verwendet man tcsetattr(3). Vorher allerdings nicht vergessen, die alten Einstellungen mit tcgetattr(3) zu sichern, um sie bei Beendigung des Programmes wiederherzustellen. Dies sollte zwar eigentlich nicht nötig sein, aber es gibt fehlerhafte Programme, die nicht mehr funktionieren, wenn man exotische Einstellungen getätigt hat und den Zustand der seriellen Schnittstelle nicht wiederhergestellt hat.&lt;br /&gt;
&lt;br /&gt;
=====Konfiguration lesen=====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct termios config;&lt;br /&gt;
// int tcgetattr ( int fd, struct termios *termios_p );&lt;br /&gt;
if ( tcgetattr( port, &amp;amp;config ) == -1 )&lt;br /&gt;
{&lt;br /&gt;
  // error&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Konfiguration schreiben=====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct termios config;&lt;br /&gt;
// int tcsetattr ( int fd, int optional_actions, struct termios *termios_p );&lt;br /&gt;
if ( tcsetattr( port, TCSANOW, &amp;amp;config ) == -1 )&lt;br /&gt;
{&lt;br /&gt;
  // error&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Eigene Konfiguration erstellen=====&lt;br /&gt;
Auszug aus &amp;lt;bits/termios.h&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct termios&lt;br /&gt;
{&lt;br /&gt;
  tcflag_t c_iflag;           /* input mode flags */&lt;br /&gt;
  tcflag_t c_oflag;           /* output mode flags */&lt;br /&gt;
  tcflag_t c_cflag;           /* control mode flags */&lt;br /&gt;
  tcflag_t c_lflag;           /* local mode flags */&lt;br /&gt;
  cc_t c_line;                /* line discipline */&lt;br /&gt;
  cc_t c_cc[NCCS];            /* control characters */&lt;br /&gt;
  speed_t c_ispeed;           /* input speed */&lt;br /&gt;
  speed_t c_ospeed;           /* output speed */&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct termios config;            // struct erstellen&lt;br /&gt;
bzero( &amp;amp;config, sizeof(config) ); // struct nullen&lt;br /&gt;
&lt;br /&gt;
config.c_iflag = ;                // flags setzen&lt;br /&gt;
config.c_oflag = ;&lt;br /&gt;
config.c_cflag = ;&lt;br /&gt;
config.c_lflag = ;&lt;br /&gt;
config.c_cc[x] = ;&lt;br /&gt;
&lt;br /&gt;
cfsetospeed( &amp;amp;config, B9600 );    // baudrate setzen&lt;br /&gt;
&lt;br /&gt;
// jetzt kann die konfiguration der schnittstelle zugewiesen werden&lt;br /&gt;
if ( tcsetattr( port, TCSANOW, &amp;amp;config ) == -1 )&lt;br /&gt;
{&lt;br /&gt;
  // error&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Daten lesen/schreiben====&lt;br /&gt;
Mit read(2) kann man nun Daten von der Schnittstelle lesen. Wenn keine Daten anliegen und man read(2) aufruft, blockiert der Aufruf den weiteren Programmablauf. Dies kann man durch benutzen von [http://www.pronix.de/pronix-66.html select(2)] verhindern.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int bytes;&lt;br /&gt;
char buffer[ x ];&lt;br /&gt;
bytes = read( port, buffer, sizeof( buffer ) ); &lt;br /&gt;
// read(2) gibt die Anzahl der gelesenen Bytes zurück&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Möchte man Daten über die Schnittstelle senden, muss man dafür write(2) verwenden. Dieser Aufruf blockt für gewöhnlich nicht.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int bytes;&lt;br /&gt;
int size;&lt;br /&gt;
char buffer[ x ];&lt;br /&gt;
bytes = write( port, buffer, size ); &lt;br /&gt;
// write(2) gibt die Anzahl der tatsächlich geschriebenen Bytes zurück&lt;br /&gt;
if ( bytes != size ) ... // Fehler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Parallele Schnittstelle==&lt;br /&gt;
Die parallele Schnittstelle besitzt 8 Datenleitungen, 9 Steuerleitungen und 8 Massepins. Die Datenleitungen können bidirektional verwendet werden (hängt allerdings von den Einstellungen im BIOS-Setup ab, Printer oder SPP reicht nicht; Bidirectional, ECP oder EPP ist erforderlich), die Steuerleitungen haben aber unabhängig von der BIOS-Einstellung eine festgelegte Richtung.&lt;br /&gt;
&lt;br /&gt;
Die benötigte Include-Datei heisst: &amp;lt;linux/ppdev.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Parallelport kann, wie die serielle Schnittstelle auch, in verschiedenen Modi angesprochen werden, dazu gehören:&lt;br /&gt;
* Die Pinebene, nur bei sehr alter Hardware unidirektional, sonst immer bidirektional.&lt;br /&gt;
* Die Protokollebene, dazu gehören die Protokolle SPP, EPP und ECP.&lt;br /&gt;
&lt;br /&gt;
===Die Pinebene===&lt;br /&gt;
Wer früher den Parallelport unter DOS programmiert hat, wird sicher noch die Register kennen. Unter Linux wird auf diese Register aber nicht mehr direkt zugegriffen. Weil der Kernel jetzt den direkten Zugriff auf die Register steuert, muss man ihm über ioctl() sagen, was er machen soll.&lt;br /&gt;
&lt;br /&gt;
====Die Bits im Register und die dazugehörigen Pins====&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=5&lt;br /&gt;
| &#039;&#039;Registername&#039;&#039;&lt;br /&gt;
| &#039;&#039;Bit im Register&#039;&#039;&lt;br /&gt;
| &#039;&#039;Type&#039;&#039;&lt;br /&gt;
| &#039;&#039;Pin Nummer&#039;&#039;&lt;br /&gt;
| &#039;&#039;Name&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | data&lt;br /&gt;
| 7&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | I/O&lt;br /&gt;
| 9&lt;br /&gt;
| data bit 7&lt;br /&gt;
|-&lt;br /&gt;
| 6&lt;br /&gt;
| 8&lt;br /&gt;
| data bit 6&lt;br /&gt;
|-&lt;br /&gt;
| 5&lt;br /&gt;
| 7&lt;br /&gt;
| data bit 5&lt;br /&gt;
|-&lt;br /&gt;
| 4&lt;br /&gt;
| 6&lt;br /&gt;
| data bit 4&lt;br /&gt;
|-&lt;br /&gt;
| 3&lt;br /&gt;
| 5&lt;br /&gt;
| data bit 3&lt;br /&gt;
|-&lt;br /&gt;
| 2&lt;br /&gt;
| 4&lt;br /&gt;
| data bit 2&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 3&lt;br /&gt;
| data bit 1&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| 2&lt;br /&gt;
| data bit 0&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | status&lt;br /&gt;
| 7&lt;br /&gt;
| rowspan=&amp;quot;5&amp;quot; | I&lt;br /&gt;
| 11&lt;br /&gt;
| busy#&lt;br /&gt;
|-&lt;br /&gt;
| 6&lt;br /&gt;
| 10&lt;br /&gt;
| ack#&lt;br /&gt;
|-&lt;br /&gt;
| 5&lt;br /&gt;
| 12&lt;br /&gt;
| paper empty&lt;br /&gt;
|-&lt;br /&gt;
| 4&lt;br /&gt;
| 13&lt;br /&gt;
| printer is selected&lt;br /&gt;
|-&lt;br /&gt;
| 3&lt;br /&gt;
| 15&lt;br /&gt;
| error#&lt;br /&gt;
|-&lt;br /&gt;
| 2&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | -&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | -&lt;br /&gt;
| Interrupt has occurred&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| ?&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | control&lt;br /&gt;
| 7&lt;br /&gt;
| rowspan=&amp;quot;4&amp;quot; | -&lt;br /&gt;
| rowspan=&amp;quot;4&amp;quot; | -&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 6&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 5&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 4&lt;br /&gt;
| enable Interrupt&lt;br /&gt;
|-&lt;br /&gt;
| 3&lt;br /&gt;
| rowspan=&amp;quot;4&amp;quot; | O&lt;br /&gt;
| 17&lt;br /&gt;
| select printer&lt;br /&gt;
|-&lt;br /&gt;
| 2&lt;br /&gt;
| 16&lt;br /&gt;
| initialize printer#&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 14&lt;br /&gt;
| automatic line feed&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| 1&lt;br /&gt;
| strobe&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
data:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Pin  9, I/O, Bit 7 = data bit 7&lt;br /&gt;
Pin  8, I/O, Bit 6 = data bit 6&lt;br /&gt;
Pin  7, I/O, Bit 5 = data bit 5&lt;br /&gt;
Pin  6, I/O, Bit 4 = data bit 4&lt;br /&gt;
Pin  5, I/O, Bit 3 = data bit 3&lt;br /&gt;
Pin  4, I/O, Bit 2 = data bit 2&lt;br /&gt;
Pin  3, I/O, Bit 1 = data bit 1&lt;br /&gt;
Pin  2, I/O, Bit 0 = data bit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
status:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Pin 11, I, Bit 7 = busy#&lt;br /&gt;
Pin 10, I, Bit 6 = ack#&lt;br /&gt;
Pin 12, I, Bit 5 = paper empty&lt;br /&gt;
Pin 13, I, Bit 4 = printer is selected&lt;br /&gt;
Pin 15, I, Bit 3 = error#&lt;br /&gt;
           Bit 2 = Interrupt has occurred&lt;br /&gt;
           Bit 1 = ?&lt;br /&gt;
           Bit 0 = ?&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
control:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
           Bit 7 = ?&lt;br /&gt;
           Bit 6 = ?&lt;br /&gt;
           Bit 5 = ?&lt;br /&gt;
           Bit 4 = enable Interrupt&lt;br /&gt;
Pin 17, O, Bit 3 = select printer&lt;br /&gt;
Pin 16, O, Bit 2 = initialize printer#&lt;br /&gt;
Pin 14, O, Bit 1 = automatic line feed&lt;br /&gt;
Pin  1, O, Bit 0 = strobe&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Parallelport öffnen====&lt;br /&gt;
Das Öffnen der Parallelschnittstelle gestaltet sich ein wenig anders, als das Öffnen der seriellen Schnittstelle. Da an den Parallelport mehrere Geräte gleichzeitig angeschlossen werden können, und Linux das auch unterstüzt, braucht man eine Methode, mit der sich mehrere Programme die Schnittstelle teilen können. Dafür öffnet man die Schnittstelle, genau wie die serielle, erst mit open(2). Danach muss man ppdev sagen, dass man die Schnittstelle auch benutzen mag, das geschieht mit dem PPCLAIM ioctl-call.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int port;&lt;br /&gt;
port = open( &amp;quot;/dev/parport0&amp;quot;, O_RDWR );&lt;br /&gt;
ioctl( port, PPCLAIM, NULL );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Parallelport schliessen====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ioctl( port, PPRELEASE, NULL );&lt;br /&gt;
close( port );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Parallelport lesen/schreiben====&lt;br /&gt;
Der Zugriff auf den Port erfolgt über seine Register, zu diesen gehören:&lt;br /&gt;
# Das &amp;quot;data&amp;quot; Register, &lt;br /&gt;
# &amp;quot;status&amp;quot; Register,&lt;br /&gt;
# &amp;quot;control&amp;quot; Register.&lt;br /&gt;
&lt;br /&gt;
=====Register lesen=====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
unsigned char r;&lt;br /&gt;
ioctl( port, PPRCONTROL, &amp;amp;r ); // liest das &amp;quot;control&amp;quot; Register&lt;br /&gt;
ioctl( port, PPRSTATUS , &amp;amp;r ); // liest das &amp;quot;status&amp;quot;  Register&lt;br /&gt;
ioctl( port, PPRDATA   , &amp;amp;r ); // liest das &amp;quot;data&amp;quot;    Register&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Register schreiben=====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
unsigned char r;&lt;br /&gt;
r = 0xXX;&lt;br /&gt;
ioctl( port, PPWCONTROL, &amp;amp;r ); // schreibt das &amp;quot;control&amp;quot; Register&lt;br /&gt;
ioctl( port, PPWDATA   , &amp;amp;r ); // schreibt das &amp;quot;data&amp;quot;    Register&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====&amp;quot;read modify write&amp;quot; umgehen=====&lt;br /&gt;
Wenn man nur ein paar Bits setzen/löschen möchte, könnte man erst den Registerinhalt lesen, die Bits ändern, und den Inhalt wieder schreiben.&lt;br /&gt;
&lt;br /&gt;
Das geht aber besser, weil der Kernel dafür selbst eine Funktion anbietet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 struct ppdev_frob_struct {&lt;br /&gt;
        unsigned char mask;&lt;br /&gt;
        unsigned char val;&lt;br /&gt;
 };&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
ppdev_frob_struct frob;&lt;br /&gt;
frob.mask = 0xXX;&lt;br /&gt;
frob.val  = 0xXX;&lt;br /&gt;
ioctl( port, PPFCONTROL, &amp;amp;frob ); // ändert Bits im &amp;quot;control&amp;quot; Register&lt;br /&gt;
                                  // new_control = (old_control &amp;amp; ~mask) | val;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Funktion ist nur für das control Register verfügbar.&lt;br /&gt;
&lt;br /&gt;
====Parallelport [[Ausgangsstufen_Logik-ICs#Tri-state|Tri-State]]-Modus aktivieren====&lt;br /&gt;
Bei deaktiviertem Tri-State-Modus treibt der Port die Datenleitungen. Dabei ist der Zustand vom data Register abhängig.&lt;br /&gt;
&lt;br /&gt;
Wenn man nun den Tri-State-Modus aktiviert, treibt der Port die Datenleitungen nicht mehr. Nun kann man den Zustand der Datenleitungen über das data Register lesen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int i;&lt;br /&gt;
i = 0; // Tri-State &#039;&#039;&#039;aus&#039;&#039;&#039; (Der PC treibt die Data-Leitungen)&lt;br /&gt;
i = 1; // Tri-State &#039;&#039;&#039;an&#039;&#039;&#039;  (Der PC treibt die Data-Leitungen &#039;&#039;&#039;nicht&#039;&#039;&#039;)&lt;br /&gt;
ioctl( port, PPDATADIR, &amp;amp;i );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Die Protokollebene SPP===&lt;br /&gt;
(to do)&lt;br /&gt;
&lt;br /&gt;
===Die Protokollebene EPP (IEEE 1284)===&lt;br /&gt;
(to do)&lt;br /&gt;
&lt;br /&gt;
==Der I2C Bus &amp;amp; SMBus==&lt;br /&gt;
Für den Linuxkernel gibt es auch I2C und SMBus Treiber, in Kernelversion 2.5 und 2.6 sind diese schon drin. Für Version 2.4 muss man diese extra installieren.&lt;br /&gt;
&lt;br /&gt;
Wer es nicht so genau wissen möchte, kann sich einfach merken, das der SMBus ein I2C-Bus ist. Wer den SMBus aber ansteuern möchte, muss sich mit den kleinen Unterschieden aueinandersetzen. Hierfür wird auf das AN476 von Maxim verwiesen: http://www.maxim-ic.com/appnotes.cfm/appnote_number/476&lt;br /&gt;
&lt;br /&gt;
=== Software ===&lt;br /&gt;
==== I2C u. SMBus Treiber installieren (Kernel 2.4) ====&lt;br /&gt;
Auf meinem Debian läuft ein selbstkompilierter Kernel, deswegen musste ich die Pakete i2c-source und sensors-source installieren. Voraussetzung ist das die Kernelquellen installiert sind.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt-get install i2c-source lm-sensors-source&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach liegen in /usr/src/ zwei *.tar Dateien:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:/usr/src# ll&lt;br /&gt;
-rw-r--r--   1 root root 146976 Apr 15  2005 i2c.tar.gz&lt;br /&gt;
-rw-r--r--   1 root root 924605 Sep 12  2005 lm-sensors.tar.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese muss man nun auspacken, danach in das Verzeichniss modules/i2c wechseln, und make ausführen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:/usr/src# cd modules/i2c&lt;br /&gt;
noway:/usr/src/modules/i2c# make&lt;br /&gt;
noway:/usr/src/modules/i2c# make install&lt;br /&gt;
noway:/usr/src/modules/i2c# cd ../..&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Und das gleiche nochmal für das lm-sensors-source Paket.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:/usr/src# cd modules/lm-sensors&lt;br /&gt;
noway:/usr/src/modules/lm-sensors# make&lt;br /&gt;
noway:/usr/src/modules/lm-sensors# make install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach wird man um diese Programme reicher:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
i2cdetect&lt;br /&gt;
i2cdump&lt;br /&gt;
i2cset&lt;br /&gt;
isadump&lt;br /&gt;
isaset&lt;br /&gt;
sensors-detect&lt;br /&gt;
sensors&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Jetzt sollte man die /dev/ Einträge erstellen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:~# cd /dev&lt;br /&gt;
noway:/dev# ./MAKEDEV i2c&lt;br /&gt;
noway:/dev# l i2c-*&lt;br /&gt;
crw-------  1 root root 89, 0 Mar 17 21:00 i2c-0&lt;br /&gt;
crw-------  1 root root 89, 1 Mar 17 21:00 i2c-1&lt;br /&gt;
crw-------  1 root root 89, 2 Mar 17 21:00 i2c-2&lt;br /&gt;
crw-------  1 root root 89, 3 Mar 17 21:00 i2c-3&lt;br /&gt;
crw-------  1 root root 89, 4 Mar 17 21:00 i2c-4&lt;br /&gt;
crw-------  1 root root 89, 5 Mar 17 21:00 i2c-5&lt;br /&gt;
crw-------  1 root root 89, 6 Mar 17 21:00 i2c-6&lt;br /&gt;
crw-------  1 root root 89, 7 Mar 17 21:00 i2c-7&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit kann jetzt nur &amp;quot;root&amp;quot; etwas anfangen. Damit die normalen Benutzer den Bus benutzen können, muss man eine neue Gruppe erstellen und die Zugriffsrechte anpassen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:/dev# groupadd i2c&lt;br /&gt;
noway:/dev# chmod 660 i2c-*&lt;br /&gt;
noway:/dev# chgrp i2c i2c-*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach sollte es so aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:/dev# l i2c-*&lt;br /&gt;
crw-rw----  1 root i2c 89, 0 Mar 17 21:00 i2c-0&lt;br /&gt;
crw-rw----  1 root i2c 89, 1 Mar 17 21:00 i2c-1&lt;br /&gt;
crw-rw----  1 root i2c 89, 2 Mar 17 21:00 i2c-2&lt;br /&gt;
crw-rw----  1 root i2c 89, 3 Mar 17 21:00 i2c-3&lt;br /&gt;
crw-rw----  1 root i2c 89, 4 Mar 17 21:00 i2c-4&lt;br /&gt;
crw-rw----  1 root i2c 89, 5 Mar 17 21:00 i2c-5&lt;br /&gt;
crw-rw----  1 root i2c 89, 6 Mar 17 21:00 i2c-6&lt;br /&gt;
crw-rw----  1 root i2c 89, 7 Mar 17 21:00 i2c-7&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Jetzt muss man sensors-detect aufrufen. Danach sollte für den SMBus das richtige Modul geladen sein. Mit &amp;quot;modprobe i2c-pport&amp;quot; kann man das Parallelport-I2C-Modul laden.&lt;br /&gt;
&lt;br /&gt;
Welche Busse nun verfügbar sind, kann man mit &amp;quot;cat /proc/bus/i2c&amp;quot; erfahren.&lt;br /&gt;
&lt;br /&gt;
Mit i2cdetect kann man jetzt die verfügbaren Busse scannen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:~# i2cdetect -l&lt;br /&gt;
i2c-0   smbus           SMBus Via Pro adapter at e800           Non-I2C SMBus adapter&lt;br /&gt;
i2c-1   i2c             Primitive Parallel port adaptor         Bit-shift algorithm&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:~# i2cdetect -y 0&lt;br /&gt;
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f&lt;br /&gt;
00:          XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
10: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
20: XX XX XX XX XX XX XX XX XX XX XX XX XX UU XX XX&lt;br /&gt;
30: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
40: XX XX XX XX XX XX XX XX UU UU XX XX XX XX XX XX&lt;br /&gt;
50: 50 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
60: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
70: XX XX XX XX XX XX XX XX&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:~# i2cdetect -y 1&lt;br /&gt;
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f&lt;br /&gt;
00:          XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
10: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
20: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
30: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
40: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
50: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
60: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
70: XX XX XX XX XX XX XX XX&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== I2C Treiber installieren (Kernel 2.6) ====&lt;br /&gt;
Hier [http://www.mikrocontroller.net/wikifiles/4/4d/I2c-pport-26.tar.gz] gibt es die angepassten Sourcen für das i2c-pport Modul, dieses muss man selbst kompilieren. Der Rest funktioniert wie oben für Kernel 2.4 beschrieben.&amp;lt;br&amp;gt;&lt;br /&gt;
Wichtig ist, dass man die Module lp und parport_pc auf die Blacklist setzt und den Parallelport im SPP-Modus betreibt (Bios-Einstellung). Dieser kleine Treiber benötigt keine weitere Hardware. (Quelle: [http://2z4gn8.blogspot.com/2008/04/saa1064-sieben-segment-anzeige-via-i2c.html])&lt;br /&gt;
&lt;br /&gt;
==== I2C Bus öffnen/schliessen ====&lt;br /&gt;
Den Bus öffnet man nun genau wie die anderen Schnittstellen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int bus;&lt;br /&gt;
bus = open( &amp;quot;/dev/i2c-0&amp;quot;, O_RDWR );&lt;br /&gt;
if ( bus == -1 )&lt;br /&gt;
{&lt;br /&gt;
  // error&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
close( bus );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die include-Datei &amp;lt;linux/i2c-dev.h&amp;gt; wird benötigt, ggf. auch &amp;lt;linux/i2c.h&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== I2C Bus steuern (ioctl) ====&lt;br /&gt;
An einem I2C-Bus können viele Chips angeschlossen werden, damit der Kernel weiss, mit welchem er Kontakt aufnehmen muss, braucht man diesen ioctl-call:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
uint8_t slave_addr = 0xXX;&lt;br /&gt;
ioctl( bus, I2C_SLAVE, slave_addr );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;slave_addr&amp;quot; ist in diesem Fall die I2C-Adresse von dem Chip, den man ansprechen möchte.&lt;br /&gt;
&lt;br /&gt;
==== I2C Bus lesen/schreiben ====&lt;br /&gt;
Nachdem man eine Slave-Adresse zugewiesen hat, kann man den selektierten Chip mit read(2) und write(2) ansprechen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
char buffer[256];&lt;br /&gt;
uint16_t bytes;&lt;br /&gt;
bytes = read( bus, buffer, sizeof(buffer) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== SMBus Zugriffe ====&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
==== Der interne SMBus ====&lt;br /&gt;
Hier gibt es eine Beschreibung, wie man den SMBus findet: http://secure.netroedge.com/~lm78/hardhack.html&lt;br /&gt;
&lt;br /&gt;
==== Externe I2C Busse ====&lt;br /&gt;
===== Parallelport-Bitbang Dongle =====&lt;br /&gt;
&lt;br /&gt;
Für Linux gibt es ein Kernelmodul namens &amp;quot;i2c-pport&amp;quot;. Das ist ein I2C-Bus über den Parallelport. Dieser Bus ist erschreckend einfach aufgebaut: es werden bis auf zwei Stecker &#039;&#039;&#039;keine&#039;&#039;&#039; Bauteile benötigt. Die notwendigen Verbindungen sehen so aus:&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=5&lt;br /&gt;
| Parallelport&lt;br /&gt;
| I2C-Bus&lt;br /&gt;
|-&lt;br /&gt;
| 14&lt;br /&gt;
| SDA&lt;br /&gt;
|-&lt;br /&gt;
| 16&lt;br /&gt;
| SCL&lt;br /&gt;
|-&lt;br /&gt;
| 18-25&lt;br /&gt;
| GND&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Das funktioniert nur deswegen, weil der Parallelport [[Ausgangsstufen_Logik-ICs#Open-collector|Open-Collector]] Ausgänge mit Pullup-Widerständen besitzt, und mehr braucht man für einen I2C-Bus nicht. Der PC kann die Leitungen SDA und SCL übrigends auch lesen.&lt;br /&gt;
&lt;br /&gt;
===== Parallelport I2C-Bus Adapter mit PCF8584 =====&lt;br /&gt;
(to do)&lt;br /&gt;
&lt;br /&gt;
==Verweise auf man-pages==&lt;br /&gt;
Die manpages können online betrachtet werden unter http://www.rt.com/man/&lt;br /&gt;
&lt;br /&gt;
===Dateien öffnen===&lt;br /&gt;
-&amp;gt; open(2)&lt;br /&gt;
http://www.rt.com/man/open.2.html&lt;br /&gt;
&lt;br /&gt;
===Dateien schliessen===&lt;br /&gt;
-&amp;gt; close(2)&lt;br /&gt;
http://www.rt.com/man/close.2.html&lt;br /&gt;
&lt;br /&gt;
===Dateien lesen===&lt;br /&gt;
-&amp;gt; read(2)&lt;br /&gt;
http://www.rt.com/man/read.2.html&lt;br /&gt;
&lt;br /&gt;
===Dateien schreiben===&lt;br /&gt;
-&amp;gt; write(2)&lt;br /&gt;
http://www.rt.com/man/write.2.html&lt;br /&gt;
&lt;br /&gt;
===Besonderer Dateizugriff===&lt;br /&gt;
-&amp;gt; ioctl(2)&lt;br /&gt;
http://www.rt.com/man/ioctl.2.html&lt;br /&gt;
&lt;br /&gt;
===Abfragen ob Daten zum lesen bereit sind===&lt;br /&gt;
-&amp;gt; select(2)&lt;br /&gt;
http://www.rt.com/man/select.2.html&lt;br /&gt;
&lt;br /&gt;
==Benötigte include Dateien==&lt;br /&gt;
&lt;br /&gt;
===write(2) read(2) close(2)===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===open(2)===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===ioctl(2)===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/ioctl.h&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===select(2)===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/time.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== für I2C und SMBus ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;linux/i2c-dev.h&amp;gt;&lt;br /&gt;
#include &amp;lt;linux/i2c.h&amp;gt; //zumindest für 2.6.x&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&amp;lt;!-- * [[Ports benutzen (GCC)]] unter Linux --&amp;gt;&lt;br /&gt;
* [[Ports benutzen (PHP)]]&lt;br /&gt;
* [[Ports benutzen (Windows)]]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/93089#803530 Forumsbeitrag]: Sourcecode RS232 bzw. V24 in C unter Linux&lt;/div&gt;</summary>
		<author><name>User-s</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Ports_benutzen_(GCC)&amp;diff=27451</id>
		<title>Ports benutzen (GCC)</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Ports_benutzen_(GCC)&amp;diff=27451"/>
		<updated>2008-04-13T15:21:32Z</updated>

		<summary type="html">&lt;p&gt;User-s: /* I2C Bus öffnen/schliessen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Linux]]&lt;br /&gt;
[[Category:PC-Programmierung]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Einleitung==&lt;br /&gt;
&lt;br /&gt;
Über die Ansteuerung der Schnittstellen unter Linux findet man im Internet überall etwas anderes. Die einen sagen, man soll die Schnittstellen über ihre I/O-Adresse (0x3F8,0x2F8,0x378,...) ansteuern, allerdings ist das nicht portabel und funktioniert nur mit Root-Rechten.&lt;br /&gt;
&lt;br /&gt;
Die hier vorgestellte Methode ermöglicht folgendes:&lt;br /&gt;
* Zugriff auf Schnittstellen &#039;&#039;&#039;ohne&#039;&#039;&#039; Root-Berechtigung&lt;br /&gt;
* Zugriff auf &#039;&#039;&#039;alle&#039;&#039;&#039; parallelen oder seriellen Schnittstellen, egal ob USB oder nicht&lt;br /&gt;
* einfaches Portieren des Codes auf MacOSX, FreeBSD, ...&lt;br /&gt;
&lt;br /&gt;
Für den weiteren Artikel werden C/C++ Kenntnisse vorausgesetzt, denn die meisten Funktionen werden mit C-Code erklärt.&lt;br /&gt;
&lt;br /&gt;
==Allgemein==&lt;br /&gt;
&lt;br /&gt;
===Zugriffsrechte===&lt;br /&gt;
Damit man auf die Schnittstellen zugreifen kann braucht man die passende Berechtigung. Auf meinem Debian-System sehen die Zugriffsrechte so aus:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:/# ll /dev/ttyUSB? /dev/ttyS? /dev/parport?&lt;br /&gt;
crw-rw----    1 root     lp        99,   0 Feb 28 16:00 /dev/parport0&lt;br /&gt;
crw-rw----    1 root     lp        99,   1 Feb 28 16:00 /dev/parport1&lt;br /&gt;
crw-rw----    1 root     lp        99,   2 Feb 28 16:00 /dev/parport2&lt;br /&gt;
crw-rw----    1 root     lp        99,   3 Feb 28 16:00 /dev/parport3&lt;br /&gt;
crw-rw----    1 root     dialout    4,  64 Jan 22 01:11 /dev/ttyS0&lt;br /&gt;
crw-rw----    1 root     dialout    4,  65 Jan 22 01:11 /dev/ttyS1&lt;br /&gt;
crw-rw----    1 root     dialout    4,  66 Jan 22 01:11 /dev/ttyS2&lt;br /&gt;
crw-rw----    1 root     dialout    4,  67 Jan 22 01:11 /dev/ttyS3&lt;br /&gt;
crw-rw----    1 root     dialout  188,   0 Jan 22 01:11 /dev/ttyUSB0&lt;br /&gt;
crw-rw----    1 root     dialout  188,   1 Jan 22 01:11 /dev/ttyUSB1&lt;br /&gt;
crw-rw----    1 root     dialout  188,   2 Jan 22 01:11 /dev/ttyUSB2&lt;br /&gt;
crw-rw----    1 root     dialout  188,   3 Jan 22 01:11 /dev/ttyUSB3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit der User auf die Schnittstellen zugreifen kann, muss er in die Gruppen &amp;quot;lp&amp;quot; und &amp;quot;dialout&amp;quot; eingetragen werden. Wie das funktioniert kann man hier nachlesen: http://www.tuxhausen.de/kurs_user.html&lt;br /&gt;
&lt;br /&gt;
==Schnittstellen öffnen und schliessen==&lt;br /&gt;
===Schnittstelle mit open(2) öffnen===&lt;br /&gt;
Bevor man auf eine Schnittstelle zugreifen kann muss man diese mit open(2) öffnen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int port;&lt;br /&gt;
port = open(&amp;quot;/dev/ttyS0&amp;quot;, O_RDWR);&lt;br /&gt;
if ( port == -1 )&lt;br /&gt;
{&lt;br /&gt;
  // FEHLER: Port konnte nicht geöffnet werden!&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn das Programm beendet wird sollte man diese auch wieder schliessen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
close( port );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Schnittstelle mit fopen(3) öffnen===&lt;br /&gt;
&lt;br /&gt;
Öffnen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
FILE* port;&lt;br /&gt;
port = fopen(&amp;quot;/dev/ttyS0&amp;quot;, &amp;quot;rw&amp;quot;);&lt;br /&gt;
if ( port == NULL )&lt;br /&gt;
{&lt;br /&gt;
  // ein FEHLER ist aufgetreten&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schliessen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fclose (port);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Warum open(2) und nicht fopen(3)?===&lt;br /&gt;
&lt;br /&gt;
Der Zugriff mittels open(2) ist vorzuziehen, da hierbei deutlich flexiblere IO-Möglichkeiten (z.B. select, poll) zur Verfügung stehen, die sonst nur mittels Umweg über fileno(3) zu erreichen sind. Ferner kann die libc Schreibzugriffe mit fputs o.ä. Puffern, so dass man, um sicher zu stellen, dass die Daten auch tatsächlich übertragen wurden, fsync(3) aufrufen muss.&lt;br /&gt;
&lt;br /&gt;
Natürlich funktionieren beide Methoden.&lt;br /&gt;
&lt;br /&gt;
===Die Namen der Schnittstellen===&lt;br /&gt;
&lt;br /&gt;
Die Schnittstellen die man benutzen kann sind unter anderem:&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=5&lt;br /&gt;
| &#039;&#039;die RS-232  Schnittstellen&#039;&#039;&lt;br /&gt;
| /dev/ttyS0&lt;br /&gt;
| /dev/ttyS1&lt;br /&gt;
| /dev/ttySx&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;die USB-RS232 Schnittstellen&#039;&#039;&lt;br /&gt;
| /dev/ttyUSB0&lt;br /&gt;
| /dev/ttyUSB1&lt;br /&gt;
| /dev/ttyUSBx&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;die parallelen Schnittstellen&#039;&#039;&lt;br /&gt;
| /dev/parport0&lt;br /&gt;
| /dev/parport1&lt;br /&gt;
| /dev/parportx&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;die USB-parallelen Schnittstellen&#039;&#039;&lt;br /&gt;
| /dev/?&lt;br /&gt;
| /dev/?&lt;br /&gt;
| /dev/?&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;der I2C-/SM-Bus&#039;&#039;&lt;br /&gt;
| /dev/i2c-0&lt;br /&gt;
| /dev/i2c-1&lt;br /&gt;
| /dev/i2c-x&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Serielle Schnittstelle==&lt;br /&gt;
&lt;br /&gt;
Die Serielle Schnittstelle besitzt 3 Ausgangspins (TX,RTS,DTR) und 5 Eingangspins (RX,DCD,DSR,CTS,RI).&lt;br /&gt;
&lt;br /&gt;
Der Zugriff auf die serielle Schnittstelle erfolgt entweder:&lt;br /&gt;
* auf Protokollebene, oder&lt;br /&gt;
* auf Pinebene (Pin1 -&amp;gt; an, Pin2 -&amp;gt; aus, ...)&lt;br /&gt;
&lt;br /&gt;
===Die Pinebene===&lt;br /&gt;
&lt;br /&gt;
Die Pins der Seriellen Schnittstelle können &#039;&#039;&#039;ohne vorherige Konfiguration&#039;&#039;&#039; gelesen/gesetzt werden. Der Zugriff auf die Pins erfolgt über ioctl(2). Dabei muss beachtet werden dass dieser Zugriff &#039;&#039;&#039;ohne Interrupts&#039;&#039;&#039; und &#039;&#039;&#039;ohne FIFO&#039;&#039;&#039; erfolgt, daher ist es eine polling-only Lösung, aber für die Programmierung eines Chip&#039;s über ISP oder die Ansteuerung eines Schieberegisters reicht es allemal.&lt;br /&gt;
&lt;br /&gt;
====Die Pins DCD,DSR,CTS,RI lesen====&lt;br /&gt;
Die Eingangspins werden mit ioctl(2) gelesen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int i;&lt;br /&gt;
ioctl( port, TIOCMGET, &amp;amp;i );&lt;br /&gt;
&lt;br /&gt;
// Jetzt kann abgefragt werden welche Pins gesetzt sind:&lt;br /&gt;
&lt;br /&gt;
if ( (i &amp;amp; TIOCM_CD )==TIOCM_CD  ) // Pin DCD&lt;br /&gt;
{&lt;br /&gt;
  // am Pin liegt Spannung an (3 bis 12V)&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  // am Pin liegt keine Spannung an (0 bis -12V)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( (i &amp;amp; TIOCM_DSR)==TIOCM_DSR ) // Pin DSR&lt;br /&gt;
 ...&lt;br /&gt;
if ( (i &amp;amp; TIOCM_CTS)==TIOCM_CTS ) // Pin CTS&lt;br /&gt;
 ...&lt;br /&gt;
if ( (i &amp;amp; TIOCM_RI )==TIOCM_RI  ) // Pin RI&lt;br /&gt;
 ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Die Pins RTS,DTR setzen/löschen====&lt;br /&gt;
Aktiviert wird RTS,DTR so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int i = 0;&lt;br /&gt;
if (...) i |= TIOCM_RTS; // Pin RTS wird aktiviert (12V)&lt;br /&gt;
if (...) i |= TIOCM_DTR; // Pin DTR wird aktiviert (12V)&lt;br /&gt;
ioctl( port, TIOCMBIS, &amp;amp;i );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Und deaktiviert so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int i = 0;&lt;br /&gt;
if (...) i |= TIOCM_RTS; // Pin RTS wird deaktiviert (-12V)&lt;br /&gt;
if (...) i |= TIOCM_DTR; // Pin DTR wird deaktiviert (-12V)&lt;br /&gt;
ioctl( port, TIOCMBIC, &amp;amp;i );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Den Pin TX setzen/löschen====&lt;br /&gt;
Aktiviert wird TX so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ioctl( port, TIOCSBRK, NULL );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Und deaktiviert so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ioctl( port, TIOCCBRK, NULL );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Die Protokollebene===&lt;br /&gt;
Üblicherweise steuert man die serielle Schnittstelle nicht auf der Pinebene an, sondern auf der Protokollebene. Dabei übernimmt die Hardware die Aufgabe, die Pins zu steuern. Um die Schnittstelle auf der Protokollebene zu benutzen, muss man:&lt;br /&gt;
&lt;br /&gt;
* die Schnittstelle öffnen&lt;br /&gt;
* die Schnittstelle konfigurieren&lt;br /&gt;
* die Daten mit read(2) lesen und mit write(2) schreiben&lt;br /&gt;
* die Schnittstelle schließen&lt;br /&gt;
&lt;br /&gt;
====Konfigurieren====&lt;br /&gt;
Vor der Benutzung muss die RS232-Schnittstelle erstmal konfiguriert werden. Dazu verwendet man tcsetattr(3). Vorher allerdings nicht vergessen, die alten Einstellungen mit tcgetattr(3) zu sichern, um sie bei Beendigung des Programmes wiederherzustellen. Dies sollte zwar eigentlich nicht nötig sein, aber es gibt fehlerhafte Programme, die nicht mehr funktionieren, wenn man exotische Einstellungen getätigt hat und den Zustand der seriellen Schnittstelle nicht wiederhergestellt hat.&lt;br /&gt;
&lt;br /&gt;
=====Konfiguration lesen=====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct termios config;&lt;br /&gt;
// int tcgetattr ( int fd, struct termios *termios_p );&lt;br /&gt;
if ( tcgetattr( port, &amp;amp;config ) == -1 )&lt;br /&gt;
{&lt;br /&gt;
  // error&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Konfiguration schreiben=====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct termios config;&lt;br /&gt;
// int tcsetattr ( int fd, int optional_actions, struct termios *termios_p );&lt;br /&gt;
if ( tcsetattr( port, TCSANOW, &amp;amp;config ) == -1 )&lt;br /&gt;
{&lt;br /&gt;
  // error&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Eigene Konfiguration erstellen=====&lt;br /&gt;
Auszug aus &amp;lt;bits/termios.h&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct termios&lt;br /&gt;
{&lt;br /&gt;
  tcflag_t c_iflag;           /* input mode flags */&lt;br /&gt;
  tcflag_t c_oflag;           /* output mode flags */&lt;br /&gt;
  tcflag_t c_cflag;           /* control mode flags */&lt;br /&gt;
  tcflag_t c_lflag;           /* local mode flags */&lt;br /&gt;
  cc_t c_line;                /* line discipline */&lt;br /&gt;
  cc_t c_cc[NCCS];            /* control characters */&lt;br /&gt;
  speed_t c_ispeed;           /* input speed */&lt;br /&gt;
  speed_t c_ospeed;           /* output speed */&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct termios config;            // struct erstellen&lt;br /&gt;
bzero( &amp;amp;config, sizeof(config) ); // struct nullen&lt;br /&gt;
&lt;br /&gt;
config.c_iflag = ;                // flags setzen&lt;br /&gt;
config.c_oflag = ;&lt;br /&gt;
config.c_cflag = ;&lt;br /&gt;
config.c_lflag = ;&lt;br /&gt;
config.c_cc[x] = ;&lt;br /&gt;
&lt;br /&gt;
cfsetospeed( &amp;amp;config, B9600 );    // baudrate setzen&lt;br /&gt;
&lt;br /&gt;
// jetzt kann die konfiguration der schnittstelle zugewiesen werden&lt;br /&gt;
if ( tcsetattr( port, TCSANOW, &amp;amp;config ) == -1 )&lt;br /&gt;
{&lt;br /&gt;
  // error&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Daten lesen/schreiben====&lt;br /&gt;
Mit read(2) kann man nun Daten von der Schnittstelle lesen. Wenn keine Daten anliegen und man read(2) aufruft, blockiert der Aufruf den weiteren Programmablauf. Dies kann man durch benutzen von [http://www.pronix.de/pronix-66.html select(2)] verhindern.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int bytes;&lt;br /&gt;
char buffer[ x ];&lt;br /&gt;
bytes = read( port, buffer, sizeof( buffer ) ); &lt;br /&gt;
// read(2) gibt die Anzahl der gelesenen Bytes zurück&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Möchte man Daten über die Schnittstelle senden, muss man dafür write(2) verwenden. Dieser Aufruf blockt für gewöhnlich nicht.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int bytes;&lt;br /&gt;
int size;&lt;br /&gt;
char buffer[ x ];&lt;br /&gt;
bytes = write( port, buffer, size ); &lt;br /&gt;
// write(2) gibt die Anzahl der tatsächlich geschriebenen Bytes zurück&lt;br /&gt;
if ( bytes != size ) ... // Fehler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Parallele Schnittstelle==&lt;br /&gt;
Die parallele Schnittstelle besitzt 8 Datenleitungen, 9 Steuerleitungen und 8 Massepins. Die Datenleitungen können bidirektional verwendet werden (hängt allerdings von den Einstellungen im BIOS-Setup ab, Printer oder SPP reicht nicht; Bidirectional, ECP oder EPP ist erforderlich), die Steuerleitungen haben aber unabhängig von der BIOS-Einstellung eine festgelegte Richtung.&lt;br /&gt;
&lt;br /&gt;
Die benötigte Include-Datei heisst: &amp;lt;linux/ppdev.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Parallelport kann, wie die serielle Schnittstelle auch, in verschiedenen Modi angesprochen werden, dazu gehören:&lt;br /&gt;
* Die Pinebene, nur bei sehr alter Hardware unidirektional, sonst immer bidirektional.&lt;br /&gt;
* Die Protokollebene, dazu gehören die Protokolle SPP, EPP und ECP.&lt;br /&gt;
&lt;br /&gt;
===Die Pinebene===&lt;br /&gt;
Wer früher den Parallelport unter DOS programmiert hat, wird sicher noch die Register kennen. Unter Linux wird auf diese Register aber nicht mehr direkt zugegriffen. Weil der Kernel jetzt den direkten Zugriff auf die Register steuert, muss man ihm über ioctl() sagen, was er machen soll.&lt;br /&gt;
&lt;br /&gt;
====Die Bits im Register und die dazugehörigen Pins====&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=5&lt;br /&gt;
| &#039;&#039;Registername&#039;&#039;&lt;br /&gt;
| &#039;&#039;Bit im Register&#039;&#039;&lt;br /&gt;
| &#039;&#039;Type&#039;&#039;&lt;br /&gt;
| &#039;&#039;Pin Nummer&#039;&#039;&lt;br /&gt;
| &#039;&#039;Name&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | data&lt;br /&gt;
| 7&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | I/O&lt;br /&gt;
| 9&lt;br /&gt;
| data bit 7&lt;br /&gt;
|-&lt;br /&gt;
| 6&lt;br /&gt;
| 8&lt;br /&gt;
| data bit 6&lt;br /&gt;
|-&lt;br /&gt;
| 5&lt;br /&gt;
| 7&lt;br /&gt;
| data bit 5&lt;br /&gt;
|-&lt;br /&gt;
| 4&lt;br /&gt;
| 6&lt;br /&gt;
| data bit 4&lt;br /&gt;
|-&lt;br /&gt;
| 3&lt;br /&gt;
| 5&lt;br /&gt;
| data bit 3&lt;br /&gt;
|-&lt;br /&gt;
| 2&lt;br /&gt;
| 4&lt;br /&gt;
| data bit 2&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 3&lt;br /&gt;
| data bit 1&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| 2&lt;br /&gt;
| data bit 0&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | status&lt;br /&gt;
| 7&lt;br /&gt;
| rowspan=&amp;quot;5&amp;quot; | I&lt;br /&gt;
| 11&lt;br /&gt;
| busy#&lt;br /&gt;
|-&lt;br /&gt;
| 6&lt;br /&gt;
| 10&lt;br /&gt;
| ack#&lt;br /&gt;
|-&lt;br /&gt;
| 5&lt;br /&gt;
| 12&lt;br /&gt;
| paper empty&lt;br /&gt;
|-&lt;br /&gt;
| 4&lt;br /&gt;
| 13&lt;br /&gt;
| printer is selected&lt;br /&gt;
|-&lt;br /&gt;
| 3&lt;br /&gt;
| 15&lt;br /&gt;
| error#&lt;br /&gt;
|-&lt;br /&gt;
| 2&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | -&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | -&lt;br /&gt;
| Interrupt has occurred&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| ?&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | control&lt;br /&gt;
| 7&lt;br /&gt;
| rowspan=&amp;quot;4&amp;quot; | -&lt;br /&gt;
| rowspan=&amp;quot;4&amp;quot; | -&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 6&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 5&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 4&lt;br /&gt;
| enable Interrupt&lt;br /&gt;
|-&lt;br /&gt;
| 3&lt;br /&gt;
| rowspan=&amp;quot;4&amp;quot; | O&lt;br /&gt;
| 17&lt;br /&gt;
| select printer&lt;br /&gt;
|-&lt;br /&gt;
| 2&lt;br /&gt;
| 16&lt;br /&gt;
| initialize printer#&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 14&lt;br /&gt;
| automatic line feed&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| 1&lt;br /&gt;
| strobe&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
data:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Pin  9, I/O, Bit 7 = data bit 7&lt;br /&gt;
Pin  8, I/O, Bit 6 = data bit 6&lt;br /&gt;
Pin  7, I/O, Bit 5 = data bit 5&lt;br /&gt;
Pin  6, I/O, Bit 4 = data bit 4&lt;br /&gt;
Pin  5, I/O, Bit 3 = data bit 3&lt;br /&gt;
Pin  4, I/O, Bit 2 = data bit 2&lt;br /&gt;
Pin  3, I/O, Bit 1 = data bit 1&lt;br /&gt;
Pin  2, I/O, Bit 0 = data bit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
status:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Pin 11, I, Bit 7 = busy#&lt;br /&gt;
Pin 10, I, Bit 6 = ack#&lt;br /&gt;
Pin 12, I, Bit 5 = paper empty&lt;br /&gt;
Pin 13, I, Bit 4 = printer is selected&lt;br /&gt;
Pin 15, I, Bit 3 = error#&lt;br /&gt;
           Bit 2 = Interrupt has occurred&lt;br /&gt;
           Bit 1 = ?&lt;br /&gt;
           Bit 0 = ?&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
control:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
           Bit 7 = ?&lt;br /&gt;
           Bit 6 = ?&lt;br /&gt;
           Bit 5 = ?&lt;br /&gt;
           Bit 4 = enable Interrupt&lt;br /&gt;
Pin 17, O, Bit 3 = select printer&lt;br /&gt;
Pin 16, O, Bit 2 = initialize printer#&lt;br /&gt;
Pin 14, O, Bit 1 = automatic line feed&lt;br /&gt;
Pin  1, O, Bit 0 = strobe&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Parallelport öffnen====&lt;br /&gt;
Das Öffnen der Parallelschnittstelle gestaltet sich ein wenig anders, als das Öffnen der seriellen Schnittstelle. Da an den Parallelport mehrere Geräte gleichzeitig angeschlossen werden können, und Linux das auch unterstüzt, braucht man eine Methode, mit der sich mehrere Programme die Schnittstelle teilen können. Dafür öffnet man die Schnittstelle, genau wie die serielle, erst mit open(2). Danach muss man ppdev sagen, dass man die Schnittstelle auch benutzen mag, das geschieht mit dem PPCLAIM ioctl-call.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int port;&lt;br /&gt;
port = open( &amp;quot;/dev/parport0&amp;quot;, O_RDWR );&lt;br /&gt;
ioctl( port, PPCLAIM, NULL );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Parallelport schliessen====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ioctl( port, PPRELEASE, NULL );&lt;br /&gt;
close( port );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Parallelport lesen/schreiben====&lt;br /&gt;
Der Zugriff auf den Port erfolgt über seine Register, zu diesen gehören:&lt;br /&gt;
# Das &amp;quot;data&amp;quot; Register, &lt;br /&gt;
# &amp;quot;status&amp;quot; Register,&lt;br /&gt;
# &amp;quot;control&amp;quot; Register.&lt;br /&gt;
&lt;br /&gt;
=====Register lesen=====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
unsigned char r;&lt;br /&gt;
ioctl( port, PPRCONTROL, &amp;amp;r ); // liest das &amp;quot;control&amp;quot; Register&lt;br /&gt;
ioctl( port, PPRSTATUS , &amp;amp;r ); // liest das &amp;quot;status&amp;quot;  Register&lt;br /&gt;
ioctl( port, PPRDATA   , &amp;amp;r ); // liest das &amp;quot;data&amp;quot;    Register&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Register schreiben=====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
unsigned char r;&lt;br /&gt;
r = 0xXX;&lt;br /&gt;
ioctl( port, PPWCONTROL, &amp;amp;r ); // schreibt das &amp;quot;control&amp;quot; Register&lt;br /&gt;
ioctl( port, PPWDATA   , &amp;amp;r ); // schreibt das &amp;quot;data&amp;quot;    Register&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====&amp;quot;read modify write&amp;quot; umgehen=====&lt;br /&gt;
Wenn man nur ein paar Bits setzen/löschen möchte, könnte man erst den Registerinhalt lesen, die Bits ändern, und den Inhalt wieder schreiben.&lt;br /&gt;
&lt;br /&gt;
Das geht aber besser, weil der Kernel dafür selbst eine Funktion anbietet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 struct ppdev_frob_struct {&lt;br /&gt;
        unsigned char mask;&lt;br /&gt;
        unsigned char val;&lt;br /&gt;
 };&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
ppdev_frob_struct frob;&lt;br /&gt;
frob.mask = 0xXX;&lt;br /&gt;
frob.val  = 0xXX;&lt;br /&gt;
ioctl( port, PPFCONTROL, &amp;amp;frob ); // ändert Bits im &amp;quot;control&amp;quot; Register&lt;br /&gt;
                                  // new_control = (old_control &amp;amp; ~mask) | val;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Funktion ist nur für das control Register verfügbar.&lt;br /&gt;
&lt;br /&gt;
====Parallelport [[Ausgangsstufen_Logik-ICs#Tri-state|Tri-State]]-Modus aktivieren====&lt;br /&gt;
Bei deaktiviertem Tri-State-Modus treibt der Port die Datenleitungen. Dabei ist der Zustand vom data Register abhängig.&lt;br /&gt;
&lt;br /&gt;
Wenn man nun den Tri-State-Modus aktiviert, treibt der Port die Datenleitungen nicht mehr. Nun kann man den Zustand der Datenleitungen über das data Register lesen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int i;&lt;br /&gt;
i = 0; // Tri-State &#039;&#039;&#039;aus&#039;&#039;&#039; (Der PC treibt die Data-Leitungen)&lt;br /&gt;
i = 1; // Tri-State &#039;&#039;&#039;an&#039;&#039;&#039;  (Der PC treibt die Data-Leitungen &#039;&#039;&#039;nicht&#039;&#039;&#039;)&lt;br /&gt;
ioctl( port, PPDATADIR, &amp;amp;i );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Die Protokollebene SPP===&lt;br /&gt;
(to do)&lt;br /&gt;
&lt;br /&gt;
===Die Protokollebene EPP (IEEE 1284)===&lt;br /&gt;
(to do)&lt;br /&gt;
&lt;br /&gt;
==Der I2C Bus &amp;amp; SMBus==&lt;br /&gt;
Für den Linuxkernel gibt es auch I2C und SMBus Treiber, in Kernelversion 2.5 und 2.6 sind diese schon drin. Für Version 2.4 muss man diese extra installieren.&lt;br /&gt;
&lt;br /&gt;
Wer es nicht so genau wissen möchte, kann sich einfach merken, das der SMBus ein I2C-Bus ist. Wer den SMBus aber ansteuern möchte, muss sich mit den kleinen Unterschieden aueinandersetzen. Hierfür wird auf das AN476 von Maxim verwiesen: http://www.maxim-ic.com/appnotes.cfm/appnote_number/476&lt;br /&gt;
&lt;br /&gt;
=== Software ===&lt;br /&gt;
==== I2C u. SMBus Treiber installieren (Kernel 2.4) ====&lt;br /&gt;
Auf meinem Debian läuft ein selbstkompilierter Kernel, deswegen musste ich die Pakete i2c-source und sensors-source installieren. Voraussetzung ist das die Kernelquellen installiert sind.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt-get install i2c-source lm-sensors-source&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach liegen in /usr/src/ zwei *.tar Dateien:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:/usr/src# ll&lt;br /&gt;
-rw-r--r--   1 root root 146976 Apr 15  2005 i2c.tar.gz&lt;br /&gt;
-rw-r--r--   1 root root 924605 Sep 12  2005 lm-sensors.tar.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese muss man nun auspacken, danach in das Verzeichniss modules/i2c wechseln, und make ausführen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:/usr/src# cd modules/i2c&lt;br /&gt;
noway:/usr/src/modules/i2c# make&lt;br /&gt;
noway:/usr/src/modules/i2c# make install&lt;br /&gt;
noway:/usr/src/modules/i2c# cd ../..&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Und das gleiche nochmal für das lm-sensors-source Paket.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:/usr/src# cd modules/lm-sensors&lt;br /&gt;
noway:/usr/src/modules/lm-sensors# make&lt;br /&gt;
noway:/usr/src/modules/lm-sensors# make install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach wird man um diese Programme reicher:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
i2cdetect&lt;br /&gt;
i2cdump&lt;br /&gt;
i2cset&lt;br /&gt;
isadump&lt;br /&gt;
isaset&lt;br /&gt;
sensors-detect&lt;br /&gt;
sensors&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Jetzt sollte man die /dev/ Einträge erstellen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:~# cd /dev&lt;br /&gt;
noway:/dev# ./MAKEDEV i2c&lt;br /&gt;
noway:/dev# l i2c-*&lt;br /&gt;
crw-------  1 root root 89, 0 Mar 17 21:00 i2c-0&lt;br /&gt;
crw-------  1 root root 89, 1 Mar 17 21:00 i2c-1&lt;br /&gt;
crw-------  1 root root 89, 2 Mar 17 21:00 i2c-2&lt;br /&gt;
crw-------  1 root root 89, 3 Mar 17 21:00 i2c-3&lt;br /&gt;
crw-------  1 root root 89, 4 Mar 17 21:00 i2c-4&lt;br /&gt;
crw-------  1 root root 89, 5 Mar 17 21:00 i2c-5&lt;br /&gt;
crw-------  1 root root 89, 6 Mar 17 21:00 i2c-6&lt;br /&gt;
crw-------  1 root root 89, 7 Mar 17 21:00 i2c-7&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit kann jetzt nur &amp;quot;root&amp;quot; etwas anfangen. Damit die normalen Benutzer den Bus benutzen können, muss man eine neue Gruppe erstellen und die Zugriffsrechte anpassen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:/dev# groupadd i2c&lt;br /&gt;
noway:/dev# chmod 660 i2c-*&lt;br /&gt;
noway:/dev# chgrp i2c i2c-*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach sollte es so aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:/dev# l i2c-*&lt;br /&gt;
crw-rw----  1 root i2c 89, 0 Mar 17 21:00 i2c-0&lt;br /&gt;
crw-rw----  1 root i2c 89, 1 Mar 17 21:00 i2c-1&lt;br /&gt;
crw-rw----  1 root i2c 89, 2 Mar 17 21:00 i2c-2&lt;br /&gt;
crw-rw----  1 root i2c 89, 3 Mar 17 21:00 i2c-3&lt;br /&gt;
crw-rw----  1 root i2c 89, 4 Mar 17 21:00 i2c-4&lt;br /&gt;
crw-rw----  1 root i2c 89, 5 Mar 17 21:00 i2c-5&lt;br /&gt;
crw-rw----  1 root i2c 89, 6 Mar 17 21:00 i2c-6&lt;br /&gt;
crw-rw----  1 root i2c 89, 7 Mar 17 21:00 i2c-7&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Jetzt muss man sensors-detect aufrufen. Danach sollte für den SMBus das richtige Modul geladen sein. Mit &amp;quot;modprobe i2c-pport&amp;quot; kann man das Parallelport-I2C-Modul laden.&lt;br /&gt;
&lt;br /&gt;
Welche Busse nun verfügbar sind, kann man mit &amp;quot;cat /proc/bus/i2c&amp;quot; erfahren.&lt;br /&gt;
&lt;br /&gt;
Mit i2cdetect kann man jetzt die verfügbaren Busse scannen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:~# i2cdetect -l&lt;br /&gt;
i2c-0   smbus           SMBus Via Pro adapter at e800           Non-I2C SMBus adapter&lt;br /&gt;
i2c-1   i2c             Primitive Parallel port adaptor         Bit-shift algorithm&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:~# i2cdetect -y 0&lt;br /&gt;
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f&lt;br /&gt;
00:          XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
10: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
20: XX XX XX XX XX XX XX XX XX XX XX XX XX UU XX XX&lt;br /&gt;
30: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
40: XX XX XX XX XX XX XX XX UU UU XX XX XX XX XX XX&lt;br /&gt;
50: 50 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
60: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
70: XX XX XX XX XX XX XX XX&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:~# i2cdetect -y 1&lt;br /&gt;
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f&lt;br /&gt;
00:          XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
10: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
20: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
30: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
40: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
50: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
60: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
70: XX XX XX XX XX XX XX XX&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== I2C Treiber installieren (Kernel 2.6) ====&lt;br /&gt;
Hier [http://www.mikrocontroller.net/wikifiles/4/4d/I2c-pport-26.tar.gz] gibt es die angepassten Sourcen für das i2c-pport Modul. Funktioniert wie oben für Kernel 2.4 beschrieben.&amp;lt;br&amp;gt;&lt;br /&gt;
Wichtig ist, dass man die Module lp und parport_pc auf die Blacklist setzt und den Parallelport im SPP-Modus betreibt (Bios-Einstellung). Dieser kleine Treiber benötigt keine weitere Hardware. (Quelle: [http://2z4gn8.blogspot.com/2008/04/saa1064-sieben-segment-anzeige-via-i2c.html])&lt;br /&gt;
&lt;br /&gt;
==== I2C Bus öffnen/schliessen ====&lt;br /&gt;
Den Bus öffnet man nun genau wie die anderen Schnittstellen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int bus;&lt;br /&gt;
bus = open( &amp;quot;/dev/i2c-0&amp;quot;, O_RDWR );&lt;br /&gt;
if ( bus == -1 )&lt;br /&gt;
{&lt;br /&gt;
  // error&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
close( bus );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die include-Datei &amp;lt;linux/i2c-dev.h&amp;gt; wird benötigt, ggf. auch &amp;lt;linux/i2c.h&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== I2C Bus steuern (ioctl) ====&lt;br /&gt;
An einem I2C-Bus können viele Chips angeschlossen werden, damit der Kernel weiss, mit welchem er Kontakt aufnehmen muss, braucht man diesen ioctl-call:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
uint8_t slave_addr = 0xXX;&lt;br /&gt;
ioctl( bus, I2C_SLAVE, slave_addr );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;slave_addr&amp;quot; ist in diesem Fall die I2C-Adresse von dem Chip, den man ansprechen möchte.&lt;br /&gt;
&lt;br /&gt;
==== I2C Bus lesen/schreiben ====&lt;br /&gt;
Nachdem man eine Slave-Adresse zugewiesen hat, kann man den selektierten Chip mit read(2) und write(2) ansprechen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
char buffer[256];&lt;br /&gt;
uint16_t bytes;&lt;br /&gt;
bytes = read( bus, buffer, sizeof(buffer) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== SMBus Zugriffe ====&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
==== Der interne SMBus ====&lt;br /&gt;
Hier gibt es eine Beschreibung, wie man den SMBus findet: http://secure.netroedge.com/~lm78/hardhack.html&lt;br /&gt;
&lt;br /&gt;
==== Externe I2C Busse ====&lt;br /&gt;
===== Parallelport-Bitbang Dongle =====&lt;br /&gt;
&lt;br /&gt;
Für Linux gibt es ein Kernelmodul namens &amp;quot;i2c-pport&amp;quot;. Das ist ein I2C-Bus über den Parallelport. Dieser Bus ist erschreckend einfach aufgebaut: es werden bis auf zwei Stecker &#039;&#039;&#039;keine&#039;&#039;&#039; Bauteile benötigt. Die notwendigen Verbindungen sehen so aus:&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=5&lt;br /&gt;
| Parallelport&lt;br /&gt;
| I2C-Bus&lt;br /&gt;
|-&lt;br /&gt;
| 14&lt;br /&gt;
| SDA&lt;br /&gt;
|-&lt;br /&gt;
| 16&lt;br /&gt;
| SCL&lt;br /&gt;
|-&lt;br /&gt;
| 18-25&lt;br /&gt;
| GND&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Das funktioniert nur deswegen, weil der Parallelport [[Ausgangsstufen_Logik-ICs#Open-collector|Open-Collector]] Ausgänge mit Pullup-Widerständen besitzt, und mehr braucht man für einen I2C-Bus nicht. Der PC kann die Leitungen SDA und SCL übrigends auch lesen.&lt;br /&gt;
&lt;br /&gt;
===== Parallelport I2C-Bus Adapter mit PCF8584 =====&lt;br /&gt;
(to do)&lt;br /&gt;
&lt;br /&gt;
==Verweise auf man-pages==&lt;br /&gt;
Die manpages können online betrachtet werden unter http://www.rt.com/man/&lt;br /&gt;
&lt;br /&gt;
===Dateien öffnen===&lt;br /&gt;
-&amp;gt; open(2)&lt;br /&gt;
http://www.rt.com/man/open.2.html&lt;br /&gt;
&lt;br /&gt;
===Dateien schliessen===&lt;br /&gt;
-&amp;gt; close(2)&lt;br /&gt;
http://www.rt.com/man/close.2.html&lt;br /&gt;
&lt;br /&gt;
===Dateien lesen===&lt;br /&gt;
-&amp;gt; read(2)&lt;br /&gt;
http://www.rt.com/man/read.2.html&lt;br /&gt;
&lt;br /&gt;
===Dateien schreiben===&lt;br /&gt;
-&amp;gt; write(2)&lt;br /&gt;
http://www.rt.com/man/write.2.html&lt;br /&gt;
&lt;br /&gt;
===Besonderer Dateizugriff===&lt;br /&gt;
-&amp;gt; ioctl(2)&lt;br /&gt;
http://www.rt.com/man/ioctl.2.html&lt;br /&gt;
&lt;br /&gt;
===Abfragen ob Daten zum lesen bereit sind===&lt;br /&gt;
-&amp;gt; select(2)&lt;br /&gt;
http://www.rt.com/man/select.2.html&lt;br /&gt;
&lt;br /&gt;
==Benötigte include Dateien==&lt;br /&gt;
&lt;br /&gt;
===write(2) read(2) close(2)===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===open(2)===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===ioctl(2)===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/ioctl.h&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===select(2)===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/time.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== für I2C und SMBus ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;linux/i2c-dev.h&amp;gt;&lt;br /&gt;
#include &amp;lt;linux/i2c.h&amp;gt; //zumindest für 2.6.x&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&amp;lt;!-- * [[Ports benutzen (GCC)]] unter Linux --&amp;gt;&lt;br /&gt;
* [[Ports benutzen (PHP)]]&lt;br /&gt;
* [[Ports benutzen (Windows)]]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/93089#803530 Forumsbeitrag]: Sourcecode RS232 bzw. V24 in C unter Linux&lt;/div&gt;</summary>
		<author><name>User-s</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Ports_benutzen_(GCC)&amp;diff=27450</id>
		<title>Ports benutzen (GCC)</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Ports_benutzen_(GCC)&amp;diff=27450"/>
		<updated>2008-04-13T15:20:21Z</updated>

		<summary type="html">&lt;p&gt;User-s: /* I2C u. SMBus Treiber installieren (Kernel 2.6) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Linux]]&lt;br /&gt;
[[Category:PC-Programmierung]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Einleitung==&lt;br /&gt;
&lt;br /&gt;
Über die Ansteuerung der Schnittstellen unter Linux findet man im Internet überall etwas anderes. Die einen sagen, man soll die Schnittstellen über ihre I/O-Adresse (0x3F8,0x2F8,0x378,...) ansteuern, allerdings ist das nicht portabel und funktioniert nur mit Root-Rechten.&lt;br /&gt;
&lt;br /&gt;
Die hier vorgestellte Methode ermöglicht folgendes:&lt;br /&gt;
* Zugriff auf Schnittstellen &#039;&#039;&#039;ohne&#039;&#039;&#039; Root-Berechtigung&lt;br /&gt;
* Zugriff auf &#039;&#039;&#039;alle&#039;&#039;&#039; parallelen oder seriellen Schnittstellen, egal ob USB oder nicht&lt;br /&gt;
* einfaches Portieren des Codes auf MacOSX, FreeBSD, ...&lt;br /&gt;
&lt;br /&gt;
Für den weiteren Artikel werden C/C++ Kenntnisse vorausgesetzt, denn die meisten Funktionen werden mit C-Code erklärt.&lt;br /&gt;
&lt;br /&gt;
==Allgemein==&lt;br /&gt;
&lt;br /&gt;
===Zugriffsrechte===&lt;br /&gt;
Damit man auf die Schnittstellen zugreifen kann braucht man die passende Berechtigung. Auf meinem Debian-System sehen die Zugriffsrechte so aus:&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:/# ll /dev/ttyUSB? /dev/ttyS? /dev/parport?&lt;br /&gt;
crw-rw----    1 root     lp        99,   0 Feb 28 16:00 /dev/parport0&lt;br /&gt;
crw-rw----    1 root     lp        99,   1 Feb 28 16:00 /dev/parport1&lt;br /&gt;
crw-rw----    1 root     lp        99,   2 Feb 28 16:00 /dev/parport2&lt;br /&gt;
crw-rw----    1 root     lp        99,   3 Feb 28 16:00 /dev/parport3&lt;br /&gt;
crw-rw----    1 root     dialout    4,  64 Jan 22 01:11 /dev/ttyS0&lt;br /&gt;
crw-rw----    1 root     dialout    4,  65 Jan 22 01:11 /dev/ttyS1&lt;br /&gt;
crw-rw----    1 root     dialout    4,  66 Jan 22 01:11 /dev/ttyS2&lt;br /&gt;
crw-rw----    1 root     dialout    4,  67 Jan 22 01:11 /dev/ttyS3&lt;br /&gt;
crw-rw----    1 root     dialout  188,   0 Jan 22 01:11 /dev/ttyUSB0&lt;br /&gt;
crw-rw----    1 root     dialout  188,   1 Jan 22 01:11 /dev/ttyUSB1&lt;br /&gt;
crw-rw----    1 root     dialout  188,   2 Jan 22 01:11 /dev/ttyUSB2&lt;br /&gt;
crw-rw----    1 root     dialout  188,   3 Jan 22 01:11 /dev/ttyUSB3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit der User auf die Schnittstellen zugreifen kann, muss er in die Gruppen &amp;quot;lp&amp;quot; und &amp;quot;dialout&amp;quot; eingetragen werden. Wie das funktioniert kann man hier nachlesen: http://www.tuxhausen.de/kurs_user.html&lt;br /&gt;
&lt;br /&gt;
==Schnittstellen öffnen und schliessen==&lt;br /&gt;
===Schnittstelle mit open(2) öffnen===&lt;br /&gt;
Bevor man auf eine Schnittstelle zugreifen kann muss man diese mit open(2) öffnen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int port;&lt;br /&gt;
port = open(&amp;quot;/dev/ttyS0&amp;quot;, O_RDWR);&lt;br /&gt;
if ( port == -1 )&lt;br /&gt;
{&lt;br /&gt;
  // FEHLER: Port konnte nicht geöffnet werden!&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn das Programm beendet wird sollte man diese auch wieder schliessen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
close( port );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Schnittstelle mit fopen(3) öffnen===&lt;br /&gt;
&lt;br /&gt;
Öffnen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
FILE* port;&lt;br /&gt;
port = fopen(&amp;quot;/dev/ttyS0&amp;quot;, &amp;quot;rw&amp;quot;);&lt;br /&gt;
if ( port == NULL )&lt;br /&gt;
{&lt;br /&gt;
  // ein FEHLER ist aufgetreten&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schliessen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fclose (port);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Warum open(2) und nicht fopen(3)?===&lt;br /&gt;
&lt;br /&gt;
Der Zugriff mittels open(2) ist vorzuziehen, da hierbei deutlich flexiblere IO-Möglichkeiten (z.B. select, poll) zur Verfügung stehen, die sonst nur mittels Umweg über fileno(3) zu erreichen sind. Ferner kann die libc Schreibzugriffe mit fputs o.ä. Puffern, so dass man, um sicher zu stellen, dass die Daten auch tatsächlich übertragen wurden, fsync(3) aufrufen muss.&lt;br /&gt;
&lt;br /&gt;
Natürlich funktionieren beide Methoden.&lt;br /&gt;
&lt;br /&gt;
===Die Namen der Schnittstellen===&lt;br /&gt;
&lt;br /&gt;
Die Schnittstellen die man benutzen kann sind unter anderem:&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=5&lt;br /&gt;
| &#039;&#039;die RS-232  Schnittstellen&#039;&#039;&lt;br /&gt;
| /dev/ttyS0&lt;br /&gt;
| /dev/ttyS1&lt;br /&gt;
| /dev/ttySx&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;die USB-RS232 Schnittstellen&#039;&#039;&lt;br /&gt;
| /dev/ttyUSB0&lt;br /&gt;
| /dev/ttyUSB1&lt;br /&gt;
| /dev/ttyUSBx&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;die parallelen Schnittstellen&#039;&#039;&lt;br /&gt;
| /dev/parport0&lt;br /&gt;
| /dev/parport1&lt;br /&gt;
| /dev/parportx&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;die USB-parallelen Schnittstellen&#039;&#039;&lt;br /&gt;
| /dev/?&lt;br /&gt;
| /dev/?&lt;br /&gt;
| /dev/?&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;der I2C-/SM-Bus&#039;&#039;&lt;br /&gt;
| /dev/i2c-0&lt;br /&gt;
| /dev/i2c-1&lt;br /&gt;
| /dev/i2c-x&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Serielle Schnittstelle==&lt;br /&gt;
&lt;br /&gt;
Die Serielle Schnittstelle besitzt 3 Ausgangspins (TX,RTS,DTR) und 5 Eingangspins (RX,DCD,DSR,CTS,RI).&lt;br /&gt;
&lt;br /&gt;
Der Zugriff auf die serielle Schnittstelle erfolgt entweder:&lt;br /&gt;
* auf Protokollebene, oder&lt;br /&gt;
* auf Pinebene (Pin1 -&amp;gt; an, Pin2 -&amp;gt; aus, ...)&lt;br /&gt;
&lt;br /&gt;
===Die Pinebene===&lt;br /&gt;
&lt;br /&gt;
Die Pins der Seriellen Schnittstelle können &#039;&#039;&#039;ohne vorherige Konfiguration&#039;&#039;&#039; gelesen/gesetzt werden. Der Zugriff auf die Pins erfolgt über ioctl(2). Dabei muss beachtet werden dass dieser Zugriff &#039;&#039;&#039;ohne Interrupts&#039;&#039;&#039; und &#039;&#039;&#039;ohne FIFO&#039;&#039;&#039; erfolgt, daher ist es eine polling-only Lösung, aber für die Programmierung eines Chip&#039;s über ISP oder die Ansteuerung eines Schieberegisters reicht es allemal.&lt;br /&gt;
&lt;br /&gt;
====Die Pins DCD,DSR,CTS,RI lesen====&lt;br /&gt;
Die Eingangspins werden mit ioctl(2) gelesen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int i;&lt;br /&gt;
ioctl( port, TIOCMGET, &amp;amp;i );&lt;br /&gt;
&lt;br /&gt;
// Jetzt kann abgefragt werden welche Pins gesetzt sind:&lt;br /&gt;
&lt;br /&gt;
if ( (i &amp;amp; TIOCM_CD )==TIOCM_CD  ) // Pin DCD&lt;br /&gt;
{&lt;br /&gt;
  // am Pin liegt Spannung an (3 bis 12V)&lt;br /&gt;
}&lt;br /&gt;
else&lt;br /&gt;
{&lt;br /&gt;
  // am Pin liegt keine Spannung an (0 bis -12V)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
if ( (i &amp;amp; TIOCM_DSR)==TIOCM_DSR ) // Pin DSR&lt;br /&gt;
 ...&lt;br /&gt;
if ( (i &amp;amp; TIOCM_CTS)==TIOCM_CTS ) // Pin CTS&lt;br /&gt;
 ...&lt;br /&gt;
if ( (i &amp;amp; TIOCM_RI )==TIOCM_RI  ) // Pin RI&lt;br /&gt;
 ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Die Pins RTS,DTR setzen/löschen====&lt;br /&gt;
Aktiviert wird RTS,DTR so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int i = 0;&lt;br /&gt;
if (...) i |= TIOCM_RTS; // Pin RTS wird aktiviert (12V)&lt;br /&gt;
if (...) i |= TIOCM_DTR; // Pin DTR wird aktiviert (12V)&lt;br /&gt;
ioctl( port, TIOCMBIS, &amp;amp;i );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Und deaktiviert so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int i = 0;&lt;br /&gt;
if (...) i |= TIOCM_RTS; // Pin RTS wird deaktiviert (-12V)&lt;br /&gt;
if (...) i |= TIOCM_DTR; // Pin DTR wird deaktiviert (-12V)&lt;br /&gt;
ioctl( port, TIOCMBIC, &amp;amp;i );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Den Pin TX setzen/löschen====&lt;br /&gt;
Aktiviert wird TX so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ioctl( port, TIOCSBRK, NULL );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Und deaktiviert so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ioctl( port, TIOCCBRK, NULL );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Die Protokollebene===&lt;br /&gt;
Üblicherweise steuert man die serielle Schnittstelle nicht auf der Pinebene an, sondern auf der Protokollebene. Dabei übernimmt die Hardware die Aufgabe, die Pins zu steuern. Um die Schnittstelle auf der Protokollebene zu benutzen, muss man:&lt;br /&gt;
&lt;br /&gt;
* die Schnittstelle öffnen&lt;br /&gt;
* die Schnittstelle konfigurieren&lt;br /&gt;
* die Daten mit read(2) lesen und mit write(2) schreiben&lt;br /&gt;
* die Schnittstelle schließen&lt;br /&gt;
&lt;br /&gt;
====Konfigurieren====&lt;br /&gt;
Vor der Benutzung muss die RS232-Schnittstelle erstmal konfiguriert werden. Dazu verwendet man tcsetattr(3). Vorher allerdings nicht vergessen, die alten Einstellungen mit tcgetattr(3) zu sichern, um sie bei Beendigung des Programmes wiederherzustellen. Dies sollte zwar eigentlich nicht nötig sein, aber es gibt fehlerhafte Programme, die nicht mehr funktionieren, wenn man exotische Einstellungen getätigt hat und den Zustand der seriellen Schnittstelle nicht wiederhergestellt hat.&lt;br /&gt;
&lt;br /&gt;
=====Konfiguration lesen=====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct termios config;&lt;br /&gt;
// int tcgetattr ( int fd, struct termios *termios_p );&lt;br /&gt;
if ( tcgetattr( port, &amp;amp;config ) == -1 )&lt;br /&gt;
{&lt;br /&gt;
  // error&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Konfiguration schreiben=====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct termios config;&lt;br /&gt;
// int tcsetattr ( int fd, int optional_actions, struct termios *termios_p );&lt;br /&gt;
if ( tcsetattr( port, TCSANOW, &amp;amp;config ) == -1 )&lt;br /&gt;
{&lt;br /&gt;
  // error&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Eigene Konfiguration erstellen=====&lt;br /&gt;
Auszug aus &amp;lt;bits/termios.h&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct termios&lt;br /&gt;
{&lt;br /&gt;
  tcflag_t c_iflag;           /* input mode flags */&lt;br /&gt;
  tcflag_t c_oflag;           /* output mode flags */&lt;br /&gt;
  tcflag_t c_cflag;           /* control mode flags */&lt;br /&gt;
  tcflag_t c_lflag;           /* local mode flags */&lt;br /&gt;
  cc_t c_line;                /* line discipline */&lt;br /&gt;
  cc_t c_cc[NCCS];            /* control characters */&lt;br /&gt;
  speed_t c_ispeed;           /* input speed */&lt;br /&gt;
  speed_t c_ospeed;           /* output speed */&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct termios config;            // struct erstellen&lt;br /&gt;
bzero( &amp;amp;config, sizeof(config) ); // struct nullen&lt;br /&gt;
&lt;br /&gt;
config.c_iflag = ;                // flags setzen&lt;br /&gt;
config.c_oflag = ;&lt;br /&gt;
config.c_cflag = ;&lt;br /&gt;
config.c_lflag = ;&lt;br /&gt;
config.c_cc[x] = ;&lt;br /&gt;
&lt;br /&gt;
cfsetospeed( &amp;amp;config, B9600 );    // baudrate setzen&lt;br /&gt;
&lt;br /&gt;
// jetzt kann die konfiguration der schnittstelle zugewiesen werden&lt;br /&gt;
if ( tcsetattr( port, TCSANOW, &amp;amp;config ) == -1 )&lt;br /&gt;
{&lt;br /&gt;
  // error&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Daten lesen/schreiben====&lt;br /&gt;
Mit read(2) kann man nun Daten von der Schnittstelle lesen. Wenn keine Daten anliegen und man read(2) aufruft, blockiert der Aufruf den weiteren Programmablauf. Dies kann man durch benutzen von [http://www.pronix.de/pronix-66.html select(2)] verhindern.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int bytes;&lt;br /&gt;
char buffer[ x ];&lt;br /&gt;
bytes = read( port, buffer, sizeof( buffer ) ); &lt;br /&gt;
// read(2) gibt die Anzahl der gelesenen Bytes zurück&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Möchte man Daten über die Schnittstelle senden, muss man dafür write(2) verwenden. Dieser Aufruf blockt für gewöhnlich nicht.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int bytes;&lt;br /&gt;
int size;&lt;br /&gt;
char buffer[ x ];&lt;br /&gt;
bytes = write( port, buffer, size ); &lt;br /&gt;
// write(2) gibt die Anzahl der tatsächlich geschriebenen Bytes zurück&lt;br /&gt;
if ( bytes != size ) ... // Fehler&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Parallele Schnittstelle==&lt;br /&gt;
Die parallele Schnittstelle besitzt 8 Datenleitungen, 9 Steuerleitungen und 8 Massepins. Die Datenleitungen können bidirektional verwendet werden (hängt allerdings von den Einstellungen im BIOS-Setup ab, Printer oder SPP reicht nicht; Bidirectional, ECP oder EPP ist erforderlich), die Steuerleitungen haben aber unabhängig von der BIOS-Einstellung eine festgelegte Richtung.&lt;br /&gt;
&lt;br /&gt;
Die benötigte Include-Datei heisst: &amp;lt;linux/ppdev.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Parallelport kann, wie die serielle Schnittstelle auch, in verschiedenen Modi angesprochen werden, dazu gehören:&lt;br /&gt;
* Die Pinebene, nur bei sehr alter Hardware unidirektional, sonst immer bidirektional.&lt;br /&gt;
* Die Protokollebene, dazu gehören die Protokolle SPP, EPP und ECP.&lt;br /&gt;
&lt;br /&gt;
===Die Pinebene===&lt;br /&gt;
Wer früher den Parallelport unter DOS programmiert hat, wird sicher noch die Register kennen. Unter Linux wird auf diese Register aber nicht mehr direkt zugegriffen. Weil der Kernel jetzt den direkten Zugriff auf die Register steuert, muss man ihm über ioctl() sagen, was er machen soll.&lt;br /&gt;
&lt;br /&gt;
====Die Bits im Register und die dazugehörigen Pins====&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=5&lt;br /&gt;
| &#039;&#039;Registername&#039;&#039;&lt;br /&gt;
| &#039;&#039;Bit im Register&#039;&#039;&lt;br /&gt;
| &#039;&#039;Type&#039;&#039;&lt;br /&gt;
| &#039;&#039;Pin Nummer&#039;&#039;&lt;br /&gt;
| &#039;&#039;Name&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | data&lt;br /&gt;
| 7&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | I/O&lt;br /&gt;
| 9&lt;br /&gt;
| data bit 7&lt;br /&gt;
|-&lt;br /&gt;
| 6&lt;br /&gt;
| 8&lt;br /&gt;
| data bit 6&lt;br /&gt;
|-&lt;br /&gt;
| 5&lt;br /&gt;
| 7&lt;br /&gt;
| data bit 5&lt;br /&gt;
|-&lt;br /&gt;
| 4&lt;br /&gt;
| 6&lt;br /&gt;
| data bit 4&lt;br /&gt;
|-&lt;br /&gt;
| 3&lt;br /&gt;
| 5&lt;br /&gt;
| data bit 3&lt;br /&gt;
|-&lt;br /&gt;
| 2&lt;br /&gt;
| 4&lt;br /&gt;
| data bit 2&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 3&lt;br /&gt;
| data bit 1&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| 2&lt;br /&gt;
| data bit 0&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | status&lt;br /&gt;
| 7&lt;br /&gt;
| rowspan=&amp;quot;5&amp;quot; | I&lt;br /&gt;
| 11&lt;br /&gt;
| busy#&lt;br /&gt;
|-&lt;br /&gt;
| 6&lt;br /&gt;
| 10&lt;br /&gt;
| ack#&lt;br /&gt;
|-&lt;br /&gt;
| 5&lt;br /&gt;
| 12&lt;br /&gt;
| paper empty&lt;br /&gt;
|-&lt;br /&gt;
| 4&lt;br /&gt;
| 13&lt;br /&gt;
| printer is selected&lt;br /&gt;
|-&lt;br /&gt;
| 3&lt;br /&gt;
| 15&lt;br /&gt;
| error#&lt;br /&gt;
|-&lt;br /&gt;
| 2&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | -&lt;br /&gt;
| rowspan=&amp;quot;3&amp;quot; | -&lt;br /&gt;
| Interrupt has occurred&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| ?&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;8&amp;quot; | control&lt;br /&gt;
| 7&lt;br /&gt;
| rowspan=&amp;quot;4&amp;quot; | -&lt;br /&gt;
| rowspan=&amp;quot;4&amp;quot; | -&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 6&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 5&lt;br /&gt;
| ?&lt;br /&gt;
|-&lt;br /&gt;
| 4&lt;br /&gt;
| enable Interrupt&lt;br /&gt;
|-&lt;br /&gt;
| 3&lt;br /&gt;
| rowspan=&amp;quot;4&amp;quot; | O&lt;br /&gt;
| 17&lt;br /&gt;
| select printer&lt;br /&gt;
|-&lt;br /&gt;
| 2&lt;br /&gt;
| 16&lt;br /&gt;
| initialize printer#&lt;br /&gt;
|-&lt;br /&gt;
| 1&lt;br /&gt;
| 14&lt;br /&gt;
| automatic line feed&lt;br /&gt;
|-&lt;br /&gt;
| 0&lt;br /&gt;
| 1&lt;br /&gt;
| strobe&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
data:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Pin  9, I/O, Bit 7 = data bit 7&lt;br /&gt;
Pin  8, I/O, Bit 6 = data bit 6&lt;br /&gt;
Pin  7, I/O, Bit 5 = data bit 5&lt;br /&gt;
Pin  6, I/O, Bit 4 = data bit 4&lt;br /&gt;
Pin  5, I/O, Bit 3 = data bit 3&lt;br /&gt;
Pin  4, I/O, Bit 2 = data bit 2&lt;br /&gt;
Pin  3, I/O, Bit 1 = data bit 1&lt;br /&gt;
Pin  2, I/O, Bit 0 = data bit 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
status:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Pin 11, I, Bit 7 = busy#&lt;br /&gt;
Pin 10, I, Bit 6 = ack#&lt;br /&gt;
Pin 12, I, Bit 5 = paper empty&lt;br /&gt;
Pin 13, I, Bit 4 = printer is selected&lt;br /&gt;
Pin 15, I, Bit 3 = error#&lt;br /&gt;
           Bit 2 = Interrupt has occurred&lt;br /&gt;
           Bit 1 = ?&lt;br /&gt;
           Bit 0 = ?&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
control:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
           Bit 7 = ?&lt;br /&gt;
           Bit 6 = ?&lt;br /&gt;
           Bit 5 = ?&lt;br /&gt;
           Bit 4 = enable Interrupt&lt;br /&gt;
Pin 17, O, Bit 3 = select printer&lt;br /&gt;
Pin 16, O, Bit 2 = initialize printer#&lt;br /&gt;
Pin 14, O, Bit 1 = automatic line feed&lt;br /&gt;
Pin  1, O, Bit 0 = strobe&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Parallelport öffnen====&lt;br /&gt;
Das Öffnen der Parallelschnittstelle gestaltet sich ein wenig anders, als das Öffnen der seriellen Schnittstelle. Da an den Parallelport mehrere Geräte gleichzeitig angeschlossen werden können, und Linux das auch unterstüzt, braucht man eine Methode, mit der sich mehrere Programme die Schnittstelle teilen können. Dafür öffnet man die Schnittstelle, genau wie die serielle, erst mit open(2). Danach muss man ppdev sagen, dass man die Schnittstelle auch benutzen mag, das geschieht mit dem PPCLAIM ioctl-call.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int port;&lt;br /&gt;
port = open( &amp;quot;/dev/parport0&amp;quot;, O_RDWR );&lt;br /&gt;
ioctl( port, PPCLAIM, NULL );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Parallelport schliessen====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
ioctl( port, PPRELEASE, NULL );&lt;br /&gt;
close( port );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Parallelport lesen/schreiben====&lt;br /&gt;
Der Zugriff auf den Port erfolgt über seine Register, zu diesen gehören:&lt;br /&gt;
# Das &amp;quot;data&amp;quot; Register, &lt;br /&gt;
# &amp;quot;status&amp;quot; Register,&lt;br /&gt;
# &amp;quot;control&amp;quot; Register.&lt;br /&gt;
&lt;br /&gt;
=====Register lesen=====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
unsigned char r;&lt;br /&gt;
ioctl( port, PPRCONTROL, &amp;amp;r ); // liest das &amp;quot;control&amp;quot; Register&lt;br /&gt;
ioctl( port, PPRSTATUS , &amp;amp;r ); // liest das &amp;quot;status&amp;quot;  Register&lt;br /&gt;
ioctl( port, PPRDATA   , &amp;amp;r ); // liest das &amp;quot;data&amp;quot;    Register&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Register schreiben=====&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
unsigned char r;&lt;br /&gt;
r = 0xXX;&lt;br /&gt;
ioctl( port, PPWCONTROL, &amp;amp;r ); // schreibt das &amp;quot;control&amp;quot; Register&lt;br /&gt;
ioctl( port, PPWDATA   , &amp;amp;r ); // schreibt das &amp;quot;data&amp;quot;    Register&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====&amp;quot;read modify write&amp;quot; umgehen=====&lt;br /&gt;
Wenn man nur ein paar Bits setzen/löschen möchte, könnte man erst den Registerinhalt lesen, die Bits ändern, und den Inhalt wieder schreiben.&lt;br /&gt;
&lt;br /&gt;
Das geht aber besser, weil der Kernel dafür selbst eine Funktion anbietet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 struct ppdev_frob_struct {&lt;br /&gt;
        unsigned char mask;&lt;br /&gt;
        unsigned char val;&lt;br /&gt;
 };&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
ppdev_frob_struct frob;&lt;br /&gt;
frob.mask = 0xXX;&lt;br /&gt;
frob.val  = 0xXX;&lt;br /&gt;
ioctl( port, PPFCONTROL, &amp;amp;frob ); // ändert Bits im &amp;quot;control&amp;quot; Register&lt;br /&gt;
                                  // new_control = (old_control &amp;amp; ~mask) | val;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Funktion ist nur für das control Register verfügbar.&lt;br /&gt;
&lt;br /&gt;
====Parallelport [[Ausgangsstufen_Logik-ICs#Tri-state|Tri-State]]-Modus aktivieren====&lt;br /&gt;
Bei deaktiviertem Tri-State-Modus treibt der Port die Datenleitungen. Dabei ist der Zustand vom data Register abhängig.&lt;br /&gt;
&lt;br /&gt;
Wenn man nun den Tri-State-Modus aktiviert, treibt der Port die Datenleitungen nicht mehr. Nun kann man den Zustand der Datenleitungen über das data Register lesen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int i;&lt;br /&gt;
i = 0; // Tri-State &#039;&#039;&#039;aus&#039;&#039;&#039; (Der PC treibt die Data-Leitungen)&lt;br /&gt;
i = 1; // Tri-State &#039;&#039;&#039;an&#039;&#039;&#039;  (Der PC treibt die Data-Leitungen &#039;&#039;&#039;nicht&#039;&#039;&#039;)&lt;br /&gt;
ioctl( port, PPDATADIR, &amp;amp;i );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Die Protokollebene SPP===&lt;br /&gt;
(to do)&lt;br /&gt;
&lt;br /&gt;
===Die Protokollebene EPP (IEEE 1284)===&lt;br /&gt;
(to do)&lt;br /&gt;
&lt;br /&gt;
==Der I2C Bus &amp;amp; SMBus==&lt;br /&gt;
Für den Linuxkernel gibt es auch I2C und SMBus Treiber, in Kernelversion 2.5 und 2.6 sind diese schon drin. Für Version 2.4 muss man diese extra installieren.&lt;br /&gt;
&lt;br /&gt;
Wer es nicht so genau wissen möchte, kann sich einfach merken, das der SMBus ein I2C-Bus ist. Wer den SMBus aber ansteuern möchte, muss sich mit den kleinen Unterschieden aueinandersetzen. Hierfür wird auf das AN476 von Maxim verwiesen: http://www.maxim-ic.com/appnotes.cfm/appnote_number/476&lt;br /&gt;
&lt;br /&gt;
=== Software ===&lt;br /&gt;
==== I2C u. SMBus Treiber installieren (Kernel 2.4) ====&lt;br /&gt;
Auf meinem Debian läuft ein selbstkompilierter Kernel, deswegen musste ich die Pakete i2c-source und sensors-source installieren. Voraussetzung ist das die Kernelquellen installiert sind.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
apt-get install i2c-source lm-sensors-source&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach liegen in /usr/src/ zwei *.tar Dateien:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:/usr/src# ll&lt;br /&gt;
-rw-r--r--   1 root root 146976 Apr 15  2005 i2c.tar.gz&lt;br /&gt;
-rw-r--r--   1 root root 924605 Sep 12  2005 lm-sensors.tar.gz&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese muss man nun auspacken, danach in das Verzeichniss modules/i2c wechseln, und make ausführen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:/usr/src# cd modules/i2c&lt;br /&gt;
noway:/usr/src/modules/i2c# make&lt;br /&gt;
noway:/usr/src/modules/i2c# make install&lt;br /&gt;
noway:/usr/src/modules/i2c# cd ../..&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Und das gleiche nochmal für das lm-sensors-source Paket.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:/usr/src# cd modules/lm-sensors&lt;br /&gt;
noway:/usr/src/modules/lm-sensors# make&lt;br /&gt;
noway:/usr/src/modules/lm-sensors# make install&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach wird man um diese Programme reicher:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
i2cdetect&lt;br /&gt;
i2cdump&lt;br /&gt;
i2cset&lt;br /&gt;
isadump&lt;br /&gt;
isaset&lt;br /&gt;
sensors-detect&lt;br /&gt;
sensors&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Jetzt sollte man die /dev/ Einträge erstellen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:~# cd /dev&lt;br /&gt;
noway:/dev# ./MAKEDEV i2c&lt;br /&gt;
noway:/dev# l i2c-*&lt;br /&gt;
crw-------  1 root root 89, 0 Mar 17 21:00 i2c-0&lt;br /&gt;
crw-------  1 root root 89, 1 Mar 17 21:00 i2c-1&lt;br /&gt;
crw-------  1 root root 89, 2 Mar 17 21:00 i2c-2&lt;br /&gt;
crw-------  1 root root 89, 3 Mar 17 21:00 i2c-3&lt;br /&gt;
crw-------  1 root root 89, 4 Mar 17 21:00 i2c-4&lt;br /&gt;
crw-------  1 root root 89, 5 Mar 17 21:00 i2c-5&lt;br /&gt;
crw-------  1 root root 89, 6 Mar 17 21:00 i2c-6&lt;br /&gt;
crw-------  1 root root 89, 7 Mar 17 21:00 i2c-7&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit kann jetzt nur &amp;quot;root&amp;quot; etwas anfangen. Damit die normalen Benutzer den Bus benutzen können, muss man eine neue Gruppe erstellen und die Zugriffsrechte anpassen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:/dev# groupadd i2c&lt;br /&gt;
noway:/dev# chmod 660 i2c-*&lt;br /&gt;
noway:/dev# chgrp i2c i2c-*&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach sollte es so aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:/dev# l i2c-*&lt;br /&gt;
crw-rw----  1 root i2c 89, 0 Mar 17 21:00 i2c-0&lt;br /&gt;
crw-rw----  1 root i2c 89, 1 Mar 17 21:00 i2c-1&lt;br /&gt;
crw-rw----  1 root i2c 89, 2 Mar 17 21:00 i2c-2&lt;br /&gt;
crw-rw----  1 root i2c 89, 3 Mar 17 21:00 i2c-3&lt;br /&gt;
crw-rw----  1 root i2c 89, 4 Mar 17 21:00 i2c-4&lt;br /&gt;
crw-rw----  1 root i2c 89, 5 Mar 17 21:00 i2c-5&lt;br /&gt;
crw-rw----  1 root i2c 89, 6 Mar 17 21:00 i2c-6&lt;br /&gt;
crw-rw----  1 root i2c 89, 7 Mar 17 21:00 i2c-7&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Jetzt muss man sensors-detect aufrufen. Danach sollte für den SMBus das richtige Modul geladen sein. Mit &amp;quot;modprobe i2c-pport&amp;quot; kann man das Parallelport-I2C-Modul laden.&lt;br /&gt;
&lt;br /&gt;
Welche Busse nun verfügbar sind, kann man mit &amp;quot;cat /proc/bus/i2c&amp;quot; erfahren.&lt;br /&gt;
&lt;br /&gt;
Mit i2cdetect kann man jetzt die verfügbaren Busse scannen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:~# i2cdetect -l&lt;br /&gt;
i2c-0   smbus           SMBus Via Pro adapter at e800           Non-I2C SMBus adapter&lt;br /&gt;
i2c-1   i2c             Primitive Parallel port adaptor         Bit-shift algorithm&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:~# i2cdetect -y 0&lt;br /&gt;
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f&lt;br /&gt;
00:          XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
10: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
20: XX XX XX XX XX XX XX XX XX XX XX XX XX UU XX XX&lt;br /&gt;
30: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
40: XX XX XX XX XX XX XX XX UU UU XX XX XX XX XX XX&lt;br /&gt;
50: 50 XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
60: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
70: XX XX XX XX XX XX XX XX&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
noway:~# i2cdetect -y 1&lt;br /&gt;
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f&lt;br /&gt;
00:          XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
10: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
20: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
30: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
40: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
50: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
60: XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX&lt;br /&gt;
70: XX XX XX XX XX XX XX XX&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== I2C Treiber installieren (Kernel 2.6) ====&lt;br /&gt;
Hier [http://www.mikrocontroller.net/wikifiles/4/4d/I2c-pport-26.tar.gz] gibt es die angepassten Sourcen für das i2c-pport Modul. Funktioniert wie oben für Kernel 2.4 beschrieben.&amp;lt;br&amp;gt;&lt;br /&gt;
Wichtig ist, dass man die Module lp und parport_pc auf die Blacklist setzt und den Parallelport im SPP-Modus betreibt (Bios-Einstellung). Dieser kleine Treiber benötigt keine weitere Hardware. (Quelle: [http://2z4gn8.blogspot.com/2008/04/saa1064-sieben-segment-anzeige-via-i2c.html])&lt;br /&gt;
&lt;br /&gt;
==== I2C Bus öffnen/schliessen ====&lt;br /&gt;
Den Bus öffnet man nun genau wie die anderen Schnittstellen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int bus;&lt;br /&gt;
bus = open( &amp;quot;/dev/i2c-0&amp;quot;, O_RDWR );&lt;br /&gt;
if ( bus == -1 )&lt;br /&gt;
{&lt;br /&gt;
  // error&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
close( bus );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die include-Datei &amp;lt;linux/i2c-dev.h&amp;gt; wird benötigt.&lt;br /&gt;
&lt;br /&gt;
==== I2C Bus steuern (ioctl) ====&lt;br /&gt;
An einem I2C-Bus können viele Chips angeschlossen werden, damit der Kernel weiss, mit welchem er Kontakt aufnehmen muss, braucht man diesen ioctl-call:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
uint8_t slave_addr = 0xXX;&lt;br /&gt;
ioctl( bus, I2C_SLAVE, slave_addr );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;slave_addr&amp;quot; ist in diesem Fall die I2C-Adresse von dem Chip, den man ansprechen möchte.&lt;br /&gt;
&lt;br /&gt;
==== I2C Bus lesen/schreiben ====&lt;br /&gt;
Nachdem man eine Slave-Adresse zugewiesen hat, kann man den selektierten Chip mit read(2) und write(2) ansprechen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
char buffer[256];&lt;br /&gt;
uint16_t bytes;&lt;br /&gt;
bytes = read( bus, buffer, sizeof(buffer) );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== SMBus Zugriffe ====&lt;br /&gt;
&lt;br /&gt;
=== Hardware ===&lt;br /&gt;
==== Der interne SMBus ====&lt;br /&gt;
Hier gibt es eine Beschreibung, wie man den SMBus findet: http://secure.netroedge.com/~lm78/hardhack.html&lt;br /&gt;
&lt;br /&gt;
==== Externe I2C Busse ====&lt;br /&gt;
===== Parallelport-Bitbang Dongle =====&lt;br /&gt;
&lt;br /&gt;
Für Linux gibt es ein Kernelmodul namens &amp;quot;i2c-pport&amp;quot;. Das ist ein I2C-Bus über den Parallelport. Dieser Bus ist erschreckend einfach aufgebaut: es werden bis auf zwei Stecker &#039;&#039;&#039;keine&#039;&#039;&#039; Bauteile benötigt. Die notwendigen Verbindungen sehen so aus:&lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=5&lt;br /&gt;
| Parallelport&lt;br /&gt;
| I2C-Bus&lt;br /&gt;
|-&lt;br /&gt;
| 14&lt;br /&gt;
| SDA&lt;br /&gt;
|-&lt;br /&gt;
| 16&lt;br /&gt;
| SCL&lt;br /&gt;
|-&lt;br /&gt;
| 18-25&lt;br /&gt;
| GND&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Das funktioniert nur deswegen, weil der Parallelport [[Ausgangsstufen_Logik-ICs#Open-collector|Open-Collector]] Ausgänge mit Pullup-Widerständen besitzt, und mehr braucht man für einen I2C-Bus nicht. Der PC kann die Leitungen SDA und SCL übrigends auch lesen.&lt;br /&gt;
&lt;br /&gt;
===== Parallelport I2C-Bus Adapter mit PCF8584 =====&lt;br /&gt;
(to do)&lt;br /&gt;
&lt;br /&gt;
==Verweise auf man-pages==&lt;br /&gt;
Die manpages können online betrachtet werden unter http://www.rt.com/man/&lt;br /&gt;
&lt;br /&gt;
===Dateien öffnen===&lt;br /&gt;
-&amp;gt; open(2)&lt;br /&gt;
http://www.rt.com/man/open.2.html&lt;br /&gt;
&lt;br /&gt;
===Dateien schliessen===&lt;br /&gt;
-&amp;gt; close(2)&lt;br /&gt;
http://www.rt.com/man/close.2.html&lt;br /&gt;
&lt;br /&gt;
===Dateien lesen===&lt;br /&gt;
-&amp;gt; read(2)&lt;br /&gt;
http://www.rt.com/man/read.2.html&lt;br /&gt;
&lt;br /&gt;
===Dateien schreiben===&lt;br /&gt;
-&amp;gt; write(2)&lt;br /&gt;
http://www.rt.com/man/write.2.html&lt;br /&gt;
&lt;br /&gt;
===Besonderer Dateizugriff===&lt;br /&gt;
-&amp;gt; ioctl(2)&lt;br /&gt;
http://www.rt.com/man/ioctl.2.html&lt;br /&gt;
&lt;br /&gt;
===Abfragen ob Daten zum lesen bereit sind===&lt;br /&gt;
-&amp;gt; select(2)&lt;br /&gt;
http://www.rt.com/man/select.2.html&lt;br /&gt;
&lt;br /&gt;
==Benötigte include Dateien==&lt;br /&gt;
&lt;br /&gt;
===write(2) read(2) close(2)===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===open(2)===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/stat.h&amp;gt;&lt;br /&gt;
#include &amp;lt;fcntl.h&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===ioctl(2)===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/ioctl.h&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===select(2)===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/time.h&amp;gt;&lt;br /&gt;
#include &amp;lt;sys/types.h&amp;gt;&lt;br /&gt;
#include &amp;lt;unistd.h&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== für I2C und SMBus ===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;linux/i2c-dev.h&amp;gt;&lt;br /&gt;
#include &amp;lt;linux/i2c.h&amp;gt; //zumindest für 2.6.x&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&amp;lt;!-- * [[Ports benutzen (GCC)]] unter Linux --&amp;gt;&lt;br /&gt;
* [[Ports benutzen (PHP)]]&lt;br /&gt;
* [[Ports benutzen (Windows)]]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/93089#803530 Forumsbeitrag]: Sourcecode RS232 bzw. V24 in C unter Linux&lt;/div&gt;</summary>
		<author><name>User-s</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:I2c-pport-26.tar.gz&amp;diff=27449</id>
		<title>Datei:I2c-pport-26.tar.gz</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:I2c-pport-26.tar.gz&amp;diff=27449"/>
		<updated>2008-04-13T15:10:48Z</updated>

		<summary type="html">&lt;p&gt;User-s: i2c-pport modul für kernel 2.6.x&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;i2c-pport modul für kernel 2.6.x&lt;/div&gt;</summary>
		<author><name>User-s</name></author>
	</entry>
</feed>