21.08.2012 Aufrufe

Computertechnik mit Mikrocontrollern

Computertechnik mit Mikrocontrollern

Computertechnik mit Mikrocontrollern

MEHR ANZEIGEN
WENIGER ANZEIGEN

Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.

YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.

<strong>Computertechnik</strong><br />

<strong>mit</strong> <strong>Mikrocontrollern</strong><br />

Hanns-Konrad Unger<br />

mail@hanns-konrad.de<br />

2006 November 10<br />

Manuskript


Satz Hanns-Konrad Unger<br />

Fotos Hanns-Konrad Unger<br />

Gestaltung Hanns-Konrad Unger


Vorwort<br />

Computer sind als PCs verbreitet. Hinter intuitiv bedienbaren<br />

Fenstern arbeiten komplexe Programme, die versuchen, den<br />

Benutzer von der Technik fernzuhalten. Oft gelingt es.<br />

Dieses Buch wurde für Menschen geschrieben, die sich für die<br />

Grundlagen der <strong>Computertechnik</strong> interessieren und am liebsten<br />

praktisch lernen (learning by doing). Heute ist ein Mikrocontroller<br />

leicht handhabbar und preiswert. Trotzdem ist er<br />

ein gutes Beispiele für Computer.<br />

Die ersten beiden Teile des Buches bilden eine kurze<br />

Einführung. Um <strong>mit</strong> dem dritten Teil zurechtzukommen,<br />

sind gegebenenfalls Studien <strong>mit</strong> weiterer Literatur durchzuführen.<br />

Auch das Internet bietet z. B. <strong>mit</strong> der Enzyklopädie<br />

[wikipedia] gute Möglichkeiten zur Vertiefung.<br />

Die Hardware für die praktischen Übungen des Hauptteils ist<br />

vom Taschengeld finanzierbar und leicht erhältlich. Ein PC<br />

möglichst <strong>mit</strong> Druckerschnittstelle wird benötigt.<br />

Zielgruppen sind Schüler, Studenten und Praktiker.<br />

4


Für die Durchführung von Praktika in Gruppen können Masken<br />

<strong>mit</strong> mehreren Platinenlayouts gedruckt werden. Die Basisplatine<br />

ist in Bereiche aufgeteilt und kann auf verschiedene<br />

Arten <strong>mit</strong> Strom versorgt werden, um je nach Umfang und<br />

Kostenrahmen skalierbar zu sein. Der Mikrocontroller wird<br />

<strong>mit</strong> 4, 8 und 16 KB Flash-Speicher in der erforderlichen Bauart<br />

angeboten.<br />

Begriffe in eckigen Klammern [ ] weisen auf das Literaturverzeichnis<br />

am Ende des Buches hin.<br />

Die Fotos wurden <strong>mit</strong> höherer Auflösung gemacht, als drucktechnisch<br />

wiedergegeben wird. Die pdf-Version des Buches<br />

ermöglicht die Ansicht von Details.<br />

Bevor Sie <strong>mit</strong> dem Buch beginnen, erlauben Sie bitte einen<br />

Eingangstest:<br />

Verstehen Sie das Titelbild?<br />

Na klar! Die Themen der ersten beiden Teile<br />

werden Ihnen weitgehend vertraut sein.<br />

Ich glaube ja. Den ersten Teil können Sie vermutlich<br />

schnell lesen.<br />

Nein. Wahrscheinlich werden Sie das Buch<br />

zwei mal durcharbeiten müssen.<br />

5


Inhaltsverzeichnis<br />

I Einführung in die <strong>Computertechnik</strong> 13<br />

1 Entwicklung der Computer 14<br />

2 Zahlensysteme 17<br />

3 Rechnerarchitektur 25<br />

3.1 von-Neumann-Architektur . . . . . . . . . . . 25<br />

3.2 Register . . . . . . . . . . . . . . . . . . . . . 28<br />

3.3 Stackpointer . . . . . . . . . . . . . . . . . . . 28<br />

3.4 Statusregister . . . . . . . . . . . . . . . . . . 29<br />

3.5 Harvard-Architektur . . . . . . . . . . . . . . 29<br />

3.6 CISC und RISC . . . . . . . . . . . . . . . . . 29<br />

6


INHALTSVERZEICHNIS 7<br />

4 Computerschnittstellen 31<br />

4.1 Centronics . . . . . . . . . . . . . . . . . . . . 32<br />

4.2 RS-232 . . . . . . . . . . . . . . . . . . . . . 33<br />

4.2.1 RS232-Schnittstelle des IBM AT . . . . 35<br />

4.2.2 Schichten . . . . . . . . . . . . . . . . 38<br />

4.3 USB . . . . . . . . . . . . . . . . . . . . . . . 40<br />

5 Kurzeinführung in Linux 42<br />

5.1 Kern des Betriebssystems . . . . . . . . . . . 44<br />

5.2 Bäume wachsen – Dateisysteme . . . . . . . . 46<br />

5.2.1 Wurzelverzeichnis . . . . . . . . . . . . 49<br />

5.2.2 Heimatverzeichnis . . . . . . . . . . . . 50<br />

5.2.3 Arbeitsverzeichnis . . . . . . . . . . . . 50<br />

5.3 GNU - Tools . . . . . . . . . . . . . . . . . . 51<br />

5.3.1 bash . . . . . . . . . . . . . . . . . . . 53<br />

5.3.2 Editoren . . . . . . . . . . . . . . . . . 54<br />

5.3.3 make . . . . . . . . . . . . . . . . . . . 56<br />

5.3.4 X11 . . . . . . . . . . . . . . . . . . . 57<br />

5.3.5 Ghostscript . . . . . . . . . . . . . . . 58<br />

5.3.6 Datenbank . . . . . . . . . . . . . . . . 58


INHALTSVERZEICHNIS 8<br />

6 Assembler 61<br />

7 Programmiersprache C 64<br />

II Hardwaretechnik 68<br />

8 Hardware-Labor 69<br />

8.1 Lötkolben . . . . . . . . . . . . . . . . . . . . 69<br />

8.2 Multimeter . . . . . . . . . . . . . . . . . . . 71<br />

8.3 Netzgerät . . . . . . . . . . . . . . . . . . . . 76<br />

9 Kleine Bauteilekunde 77<br />

9.1 Platinenmaterial . . . . . . . . . . . . . . . . 77<br />

9.2 Stecker . . . . . . . . . . . . . . . . . . . . . . 78<br />

9.3 Kabel . . . . . . . . . . . . . . . . . . . . . . 79<br />

9.4 Widerstände . . . . . . . . . . . . . . . . . . . 80<br />

9.5 Kondensatoren . . . . . . . . . . . . . . . . . 83<br />

9.6 Quarze . . . . . . . . . . . . . . . . . . . . . . 85<br />

9.7 Dioden . . . . . . . . . . . . . . . . . . . . . . 87<br />

9.8 Transistoren . . . . . . . . . . . . . . . . . . . 89<br />

9.9 Integrierte Schaltungen . . . . . . . . . . . . . 91


INHALTSVERZEICHNIS 9<br />

10 Platinenlayouts 93<br />

10.1 Programmieren <strong>mit</strong> Klassen . . . . . . . . . . 93<br />

10.2 Klasse für elektronische Schaltungen . . . . . 97<br />

10.3 Platinen ätzen . . . . . . . . . . . . . . . . . . 101<br />

10.3.1 Material . . . . . . . . . . . . . . . . . 102<br />

10.3.2 Belichtungsmaske . . . . . . . . . . . . 103<br />

10.3.3 Belichtung . . . . . . . . . . . . . . . . 104<br />

10.3.4 Entwicklung . . . . . . . . . . . . . . . 106<br />

10.3.5 Ätzen . . . . . . . . . . . . . . . . . . 107<br />

10.3.6 Abschlussarbeiten . . . . . . . . . . . . 109<br />

11 Schaltalgebra 110<br />

11.1 Boolesche Algebra . . . . . . . . . . . . . . . . 110<br />

11.2 TTL . . . . . . . . . . . . . . . . . . . . . . . 113<br />

11.3 Flip-Flop . . . . . . . . . . . . . . . . . . . . . 115<br />

III Mikrocontroller 118<br />

12 Wurzeln 119<br />

12.1 Mikrocontroller . . . . . . . . . . . . . . . . . 122<br />

12.1.1 AVR Mikrocontroller . . . . . . . . . . 123


INHALTSVERZEICHNIS 10<br />

13 Aufbau des Systems 129<br />

13.1 Software . . . . . . . . . . . . . . . . . . . . . 130<br />

13.2 Programmier-Interface . . . . . . . . . . . . . 132<br />

13.2.1 Centronics Variante . . . . . . . . . . 132<br />

13.2.2 RS232 Variante . . . . . . . . . . . . . 136<br />

13.2.3 USB Variante . . . . . . . . . . . . . . 139<br />

13.3 Kabel . . . . . . . . . . . . . . . . . . . . . . 145<br />

13.4 Mikrocontroller-Board . . . . . . . . . . . . . 146<br />

13.4.1 Programmierschnittstelle . . . . . . . 146<br />

13.4.2 Erster Dialog . . . . . . . . . . . . . . 149<br />

13.4.3 Erste Baustufe . . . . . . . . . . . . . 153<br />

13.4.4 Netzteil . . . . . . . . . . . . . . . . . 168<br />

13.4.5 Oszillator . . . . . . . . . . . . . . . . 169<br />

13.4.6 RS232 Schnittstelle . . . . . . . . . . . 171<br />

13.4.7 Taster . . . . . . . . . . . . . . . . . . 191<br />

13.4.8 Buzzer . . . . . . . . . . . . . . . . . . 192<br />

13.4.9 Display . . . . . . . . . . . . . . . . . 195<br />

14 Erste Experimente 199<br />

14.1 RS232-Schnittstellen-Tester . . . . . . . . . . 199


INHALTSVERZEICHNIS 11<br />

14.2 Frequenzgenerator . . . . . . . . . . . . . . . 201<br />

14.3 Voltmeter . . . . . . . . . . . . . . . . . . . . 202<br />

14.4 Quarzuhr . . . . . . . . . . . . . . . . . . . . 204<br />

15 Weiterführende Experimente 207<br />

15.1 Messen . . . . . . . . . . . . . . . . . . . . . . 208<br />

15.2 Steuern . . . . . . . . . . . . . . . . . . . . . 208<br />

15.3 Regeln . . . . . . . . . . . . . . . . . . . . . . 208<br />

15.4 Solartechnik . . . . . . . . . . . . . . . . . . . 209<br />

15.5 Robotik . . . . . . . . . . . . . . . . . . . . . 209<br />

15.6 Fernwirken . . . . . . . . . . . . . . . . . . . . 209<br />

A Stolpersteine 211<br />

A.1 Reset und Brown-out . . . . . . . . . . . . . . 211<br />

A.2 Stackfault . . . . . . . . . . . . . . . . . . . . 212<br />

A.3 volatile . . . . . . . . . . . . . . . . . . . . . . 213<br />

A.4 Interrupts . . . . . . . . . . . . . . . . . . . . 213<br />

A.5 PORTx . . . . . . . . . . . . . . . . . . . . . 214<br />

A.6 Watchdog . . . . . . . . . . . . . . . . . . . . 214<br />

A.7 UCSRC . . . . . . . . . . . . . . . . . . . . . 214


INHALTSVERZEICHNIS 12<br />

A.8 Besonderheiten einzelner Modelle . . . . . . . 215<br />

A.8.1 AT90S1200 . . . . . . . . . . . . . . . 215<br />

A.8.2 AT90S2343 . . . . . . . . . . . . . . . 215<br />

A.8.3 Vom AT90S4433 zum ATmega8 . . . . 215<br />

B Technische Daten 217<br />

C Nachschlagebereich 219<br />

C.1 Assembler . . . . . . . . . . . . . . . . . . . . 219<br />

C.2 Programmiersprache C . . . . . . . . . . . . . 224<br />

C.3 Runtime . . . . . . . . . . . . . . . . . . . . . 226<br />

D Programm pcb 228<br />

E Skalieren des Systems 243<br />

F Die Datei Mikrocontroller.tgz 246<br />

G Rechtliches 248<br />

H Helfer 250


Teil I<br />

Einführung in die<br />

<strong>Computertechnik</strong><br />

13


Kapitel 1<br />

Entwicklung der<br />

Computer<br />

Betrachtet man die Entwicklung moderner Computer, so fallen<br />

Parallelen zum Auto auf. Beide sind Industrieprodukte <strong>mit</strong><br />

rasanter Entwicklung in jüngster Vergangenheit. Ich will hier<br />

nicht auf die Erfindung des Rades bzw. der Zahlen eingehen,<br />

sondern kurz den Weg zum Konsumartikel aufzeichnen.<br />

Die ersten Automobile konnten nur von Leuten <strong>mit</strong> beträchtlichem<br />

Fachwissen genutzt werden, wobei die Nutzung primär<br />

Selbstzweck war. Glatte Straßen gab es noch nicht. Nach der<br />

Gruppe der Pioniere kamen die Militärs, die <strong>mit</strong> ihren Kriegen<br />

die Entwicklung und industrielle Fertigung beschleunigten.<br />

In der Folgezeit waren Automobile elitären Schichten<br />

vorbehalten. Da immer mehr gefertigt wurde, konnte langsam<br />

die Bevölkerung <strong>mit</strong> Autos versorgt werden. Zwingen-<br />

14


KAPITEL 1. ENTWICKLUNG DER COMPUTER 15<br />

de Voraussetzung war, ein Automobil für jeden bedienbar zu<br />

machen. Die Automobiltechnik ist geschickt hinter dem Armaturenbrett<br />

verpackt. Die heutige Führerscheinausbildung<br />

beschäftigt sich primär <strong>mit</strong> dem Umgang der Verkehrsteilnehmer<br />

untereinander.<br />

Im zweiten Weltkrieg waren Computer zur Dechiffrierung von<br />

Nachrichten von hoher Bedeutung. Danach übernahmen sie<br />

wichtige Aufgaben in Industrie und Forschung, umgeben von<br />

Spezialisten. Mit dem Beginn der Massenfertigung in den 70er<br />

und 80er Jahren des letzten Jahrhunderts wurden naiv bedienbare<br />

Programmoberflächen notwendig. Heute ist es üblich<br />

und chic, Computer zu nutzen, ohne zu wissen, wo<strong>mit</strong> man<br />

eigentlich arbeitet. Die Technik ist hinter bunten Benutzeroberflächen<br />

verborgen, so komplex, dass manchmal der Eindruck<br />

entsteht, die Entwickler könnten den vollen Überblick<br />

nicht mehr behalten.<br />

Bei einem Projekt <strong>mit</strong> <strong>Mikrocontrollern</strong> erkannte ich einen<br />

meiner ersten Mikrocomputer wieder: KIM 1, eine Platine<br />

<strong>mit</strong> 8Bit-Prozessor, 2 KByte RAM (flüchtiger Speicher), 1<br />

KByte ROM (permanenter Speicher), Kassettenrecorder- und<br />

Fernschreiberinterface. Diese Platine, so groß wie ein heutiges<br />

PC-Motherboard, war im Jahre 1975 der Vorgänger des PET-<br />

Mikrocomputers der Firma Commodore. Die PC-Pioniere haben<br />

<strong>mit</strong> derartiger Hardware sogar Schach gespielt (und noch<br />

gewonnen). Jedenfalls haben sie dabei viel über Computer gelernt.<br />

Ein heutiger Mikrocontroller bietet im Vergleich bei ungefähr<br />

1 Promille an Gewicht, Preis und Energieverbrauch ähnlichen


KAPITEL 1. ENTWICKLUNG DER COMPUTER 16<br />

Hardwareumfang. Warum also nicht in die Tiefen der <strong>Computertechnik</strong><br />

eintauchen? Ein üblicher PC ersetzt den Fernschreiber,<br />

an den früher derartige Platinen angeschlossen wurden.<br />

Vor der Praxis steht noch ein wenig Theorie.


Kapitel 2<br />

Zahlensysteme<br />

Typisch für Computer ist, dass alles auf Zahlen abgebildet<br />

wird. Für einen normal denkenden Menschen erscheint das<br />

erst einmal ungewöhnlich. Im Laufe dieses Kurses wird jedoch<br />

langsam klar werden, wie das geht. Zur Rechtfertigung möchte<br />

ich nur darauf hinweisen, dass Mathematiker es als bewiesen<br />

betrachten, dass man alles Berechenbare letztendlich in einer<br />

einzigen Zahl unterbringen kann.<br />

Als die Menschen zu zählen anfingen, arbeiteten sie erst einmal<br />

<strong>mit</strong> Strichlisten. Das wurde zu aufwändig. Man entwickelte<br />

das Dezimalsystem 1 , hatte man doch 10 Finger zum Rechnen.<br />

Computer haben keine Finger, und so richtig zu funktionieren<br />

1 lateinisch: decem - zehn<br />

17


KAPITEL 2. ZAHLENSYSTEME 18<br />

begannen sie erst, als man stattdessen zwei Zustände in den<br />

Mittelpunkt stellte:<br />

0 Spannung nicht vorhanden<br />

1 Spannung vorhanden<br />

In Erinnerung an die Finger nannte man das Digitaltechnik 2 .<br />

Wie kann man aber statt <strong>mit</strong> zehn Ziffern nur <strong>mit</strong> zwei Spannungen<br />

rechnen?<br />

Dazu betrachte man den Aufbau unserer Zahlen, zum Beispiel<br />

4711, einmal genauer: Sie besteht aus einer Aneinanderreihung<br />

von Ziffern. Entscheidend für den Wert der Zahl ist<br />

der Stellenwert der Ziffern. In den sogenannten polyadischen<br />

Zahlensystemen [Formeln] berechnet sich der Wert einer Zahl<br />

Z folgendermaßen:<br />

Z = � ak · B k wobei B ≥ 2; 0 ≤ ak < B; ak, B ∈ N<br />

Unser Beispiel:<br />

also:<br />

Z = 4711; B = 10; a3 = 4; a2 = 7; a1 = 1; a0 = 1<br />

2 lateinisch: digitus - der Finger


KAPITEL 2. ZAHLENSYSTEME 19<br />

4711 = 4 · 10 3 + 7 · 10 2 + 1 · 10 1 + 1 · 10 0<br />

4711 = 4 · 1000 + 7 · 100 + 1 · 10 + 1 · 1<br />

4711 = 4000 + 700 + 10 + 1<br />

Tipps: Das Sigma � steht für lange Summen. Jede Zahl außer<br />

Null wird <strong>mit</strong> Null potenziert zu 1. Wenn das Verständnis von<br />

oben nach unten hakt, versuche man es von unten nach oben.<br />

Wichtig ist die Zahl B, auch Basis genannt, die in unserer<br />

gewohnten dezimalen Rechenwelt eben 10 ist.<br />

Verwendet man im polyadische Zahlensystem für B den Wert<br />

2, so bleiben die Ziffern 0 und 1 übrig. Das Rechensystem<br />

funktioniert aber immer noch, wie ein weiteres Beispiel demonstrieren<br />

soll:<br />

also:<br />

Z = 10102; B = 2; a3 = 1; a2 = 0; a1 = 1; a0 = 0<br />

10102 = 1 · 2 3 + 0 · 2 2 + 1 · 2 1 + 0 · 2 0<br />

10102 = 1 · 810 + 0 + 1 · 210 + 0<br />

10102 = 1010<br />

Tipps: 10102 liest man: Eins Null Eins Null zur Basis 2. Werden<br />

wie oben Zahlen gemischt, so muss die Basis ausdrücklich<br />

angegeben werden.


KAPITEL 2. ZAHLENSYSTEME 20<br />

Für B = 2 nennt man die Zahlen Dualzahlen oder Binärzahlen.<br />

Computer ordnen einfach den beiden Ziffern Spannungen<br />

zu. Eine duale Ziffer bezeichnet man auch als ein Bit 3 .<br />

Fasst man 4 Bits zusammen, so kann man Werte zwischen<br />

0..15 bezeichnen. Weist man diesen Werten die 16 Ziffern 0..9<br />

und A..F 4 zu, so hat man Hexadezimalzahlen, die manchmal<br />

auch Sedezimalzahlen genannt werden. B ist in diesem Fall<br />

16. Im Computerjargon nennt man eine solche Ziffer, die ein<br />

halbes Byte darstellt, auch Nibble.<br />

3Die Informationstheorie kommt bei der Definition eines Bits ohne<br />

Zahlen aus.<br />

4A..F werden hier als Ziffern betrachtet!


KAPITEL 2. ZAHLENSYSTEME 21<br />

Zahlensysteme<br />

B=2 B=8 B=10 B=16<br />

0 0 0 0<br />

1 1 1 1<br />

10 2 2 2<br />

11 3 3 3<br />

100 4 4 4<br />

101 5 5 5<br />

110 6 6 6<br />

111 7 7 7<br />

1000 10 8 8<br />

1001 11 9 9<br />

1010 12 10 A<br />

1011 13 11 B<br />

1100 14 12 C<br />

1101 15 13 D<br />

1110 16 14 E<br />

1111 17 15 F<br />

: : : :<br />

Alle Werte in einer Zeile der Tabelle der Zahlensysteme bezeichnen<br />

genau die selbe Zahl!<br />

Fasst man wiederum 2 Hexadezimalziffern zusammen, also 8<br />

Bit, so hat man jene Bytes, welche man von der PC-Werbung<br />

kennt. In den technischen Daten findet man Kilo- (1000, oft<br />

auch 1024 Bytes), Mega (1000 Kilobytes), Giga (1000 Megabytes)<br />

und Terabytes (1000 Gigabytes).<br />

Bytes haben deshalb eine hohe Bedeutung, da Buchstaben


KAPITEL 2. ZAHLENSYSTEME 22<br />

Bytes zugeordnet werden, früher als ASCII- oder EBSDIC-,<br />

heute als den ASCII- verwandten ISO-Codes.<br />

ISO-8859-1 Code-Tabelle<br />

0 1 2 3 4 5 6 7 8 9 A B C D E F<br />

0<br />

1<br />

2 ! ” # $ % & ’ ( ) ∗ + , - . /<br />

3 0 1 2 3 4 5 6 7 8 9 : ; < = > ?<br />

4 @ A B C D E F G H I J K L M N O<br />

5 P Q R S T U V W X Y Z [ \ ] ˆ<br />

6 ‘ a b c d e f g h i j k l m n o<br />

7<br />

8<br />

9<br />

p q r s t u v w x y z { | } ˜<br />

A ¡ ? £ ? ? S ˇ § ˇs c○ ā ≪ ¬ ? ?<br />

−<br />

B<br />

◦<br />

±<br />

2 3<br />

´ µ ¶ · ˇz<br />

1<br />

o<br />

¯ ≫ 1 C À Á Â Ã Ä ˚A Æ Ç È É Ê Ë<br />

4<br />

Ì<br />

1<br />

2<br />

Í<br />

3<br />

4<br />

Î<br />

¿<br />

Ï<br />

D<br />

E<br />

–D<br />

à<br />

Ñ<br />

á<br />

Ò<br />

â<br />

Ó<br />

ã<br />

Ô<br />

ä<br />

Õ<br />

˚a<br />

Ö<br />

æ<br />

×<br />

ç<br />

Ø<br />

è<br />

Ù<br />

é<br />

Ú<br />

ê<br />

Û<br />

ë<br />

Ü<br />

ì<br />

Y´ í<br />

bl î<br />

ß<br />

ï<br />

F ∂ ñ ò ó ô õ ö ÷ ø ù ú û ü ´y bl ¨y<br />

Beispiel: Das Zeichen ? ist der Zahl 3F16 zugeordnet. In der<br />

Programmiersprache C schreibt man auch 0x3F oder 0x3f.<br />

Die anderen Fragezeichen vertreten Buchstaben, die nicht gedruckt<br />

werden konnten.<br />

Die Werte von 0x00 bis 0x1f und 0x7f bis 0x9f werden nicht<br />

für Buchstaben, sondern für Befehle an verschiedene Geräte<br />

genutzt. So interpretieren verschiedene Geräte den Wert 0x0a<br />

dergestalt, dass der nächste Buchstabe am Zeilenanfang ausgegeben<br />

werden soll.<br />

Da Computer sehr häufig Buchstaben und Texte verarbeiten<br />

müssen, werden die meisten Datenwege 8Bit oder n · 8Bit<br />

breit ausgelegt.<br />

Es stellt sich jetzt die Frage, wie kann ein Computer eine Zahl<br />

von einem Buchstaben unterscheiden. Der Fachmann würde


KAPITEL 2. ZAHLENSYSTEME 23<br />

sagen, der Computer erkennt das am Kontext. Übertragen<br />

entspricht es der Frage:<br />

Woran kann ein Mensch die Ziffer Null vom Buchstaben O<br />

unterscheiden?<br />

In der Programmiersprache C wird diese Frage genauer betrachtet.<br />

Abbildung 2.1: Direkter Nachfahre des Abakus.<br />

Um noch einmal auf die Geschichte zurückzukommen: Es gab<br />

bereits in der Antike funktionierende Rechenmaschinen, heute<br />

als Abakus bekannt.


KAPITEL 2. ZAHLENSYSTEME 24<br />

Vertiefung: Warum kann man einen Brief als Zahl zur Basis<br />

256 ansehen?<br />

Herr Jubel feiert seit seinem 30. Geburtstag alle fünf Jahre<br />

den 50. Wie macht er das?


Kapitel 3<br />

Rechnerarchitektur<br />

3.1 von-Neumann-Architektur<br />

Moderne Rechner gehen im Wesentlichen auf die theoretischen<br />

Arbeiten von Burks, Goldstine und von Neumann aus den<br />

Jahren 1946/47 zurück. Man spricht deshalb häufig von von-<br />

Neumann-Architektur. Es wurde ein universeller Rechenautomat<br />

postuliert, der sich in vier Teile gliedert:<br />

• Speicherwerk<br />

• Steuerwerk (auch Leitwerk genannt) <strong>mit</strong> Befehlszähler<br />

• Rechenwerk<br />

• Ein-/Ausgabewerk<br />

25


KAPITEL 3. RECHNERARCHITEKTUR 26<br />

Das Speicherwerk ist geeignet, duale Zahlen zu speichern. Jede<br />

Speicherstelle besitzt eine eindeutige Adresse. Die Adressen<br />

sind natürliche Zahlen in aufsteigender Reihenfolge.<br />

Grundsätzlich enthält das Speicherwerk Programm- und Datenworte.<br />

Für die Verarbeitung der Programmworte ist das<br />

Steuerwerk zuständig. Hierzu besitzt es einen Zeiger, Befehlszähler<br />

1 genannt. Der Befehlszähler zeigt auf den aktuell<br />

gültigen Programmbefehl. Nach Bearbeitung des Befehls gibt<br />

es drei Varianten:<br />

• Der Befehlszähler zeigt auf den nächsten Befehl.<br />

• Der Befehlszähler zeigt auf einen anderen Befehl.<br />

• Abhängig vom Ausgang der Bearbeitung des Befehls<br />

zeigt der Befehlszähler auf den nächsten oder einen anderen<br />

Befehl.<br />

Für die Verarbeitung von Datenworten ist das Rechenwerk 2<br />

zuständig. Es kennt logische Verknüpfungen und höhere Operationen<br />

wie Addieren und Subtrahieren. Aufwendige Rechenwerke<br />

können sogar Multiplizieren und Dividieren. Gesteuert<br />

wird das Rechenwerk vom Steuerwerk, das hierzu das Programmwort<br />

analysiert.<br />

Programmbefehle kann man in drei Gruppen einteilen:<br />

1 Im Englischen Program Counter, häufig als PC abgekürzt.<br />

2 Im Englischen oft ALU genannt, die Abkürzung für Arithmetic and<br />

Logical Unit.


KAPITEL 3. RECHNERARCHITEKTUR 27<br />

• Befehle für das Kopieren von Daten zwischen Speicher-,<br />

Rechen- und Ein-/Ausgabewerk.<br />

• Befehle, die Berechnungen im Rechenwerk anstoßen.<br />

• Befehle zum Ändern des Befehlszählers. Die anderen Befehle<br />

zeigen nach der Bearbeitung auf den nächsten Befehl.<br />

Das Eingabewerk besorgt Aufgaben, die im Speicher abgelegt<br />

werden, das Ausgabewerk präsentiert die Ergebnisse.<br />

Für einen derartig aufgebauten Rechner kann man zeigen,<br />

dass er jedes berechenbare Problem lösen kann. Derartige<br />

Überlegungen übergehen die Grenzen von Zeit- und Materialaufwand.<br />

Hierzu sei bemerkt, dass der Preis für ein Speicherbyte<br />

Anfang der 70er Jahre noch bei umgerechnet einem Euro<br />

lag, dass die praktische Bewertung von Zeit- und Materialaufwand<br />

sich ständig verändert. Wissenschaftler und Techniker<br />

neigen häufig dazu, bei ihren Überlegungen einen Aspekt getrennt<br />

zu betrachten. Als Arbeitsmethode ist das sinnvoll, als<br />

Lebensweg fatal.<br />

Heutige Mikroprozessoren und Mikrocomputer haben Steuerwerk<br />

und Rechenwerk in einem Baustein. Mikrocontroller<br />

beherbergen darin sogar noch Ein-/Ausgabewerk, inzwischen<br />

auch das Speicherwerk. Ferner sind Register, Stackpointer<br />

(SP) und Statusregister 3 (SR) dazu gekommen, was Geschwindigkeit<br />

und Programmiertechnik entgegenkommt.<br />

3 Manchmal wird statt Statusregister Programm-Status-Wort (PSW)<br />

verwendet.


KAPITEL 3. RECHNERARCHITEKTUR 28<br />

3.2 Register<br />

Um Daten im Rechenwerk zu verknüpfen, benötigt dieses Zwischenspeicher,<br />

manchmal Akkumulatoren oder Akku genannt.<br />

Diese sind gegenüber dem Speicherwerk schneller. Da alle Teilberechnungen<br />

<strong>mit</strong> wenig Daten auskommen, besitzen moderne<br />

CPUs 4 nicht nur einen Akku, sondern mehrere Speicherplätze<br />

im Rechenwerk, Register genannt. Manchmal spricht<br />

man auch vom Registerwerk. Den Aufbau des Registerwerks,<br />

wie Namen und Funktion der Register, nennt man Registermodell.<br />

Das Registermodell ist einer der wesentlichen Unterschiede<br />

verschiedener CPU-Typen.<br />

3.3 Stackpointer<br />

Der Stackpointer ist ein Zeiger in den Datenspeicher. Die<br />

indirekt über den Stackpointer durchgeführten Speicherzugriffe<br />

arbeiten nach dem FiFo 5 -Prinzip. So lassen sich bequem<br />

Rücksprungadressen von Unterprogrammen als auch<br />

ausschließlich in diesen Unterprogrammen verwendete lokale<br />

Daten speichern. Einige CPU-Befehle wie Unterprogrammsprünge<br />

nutzen den Stackpointer. Höhere Programmiersprachen<br />

bauen besonders stark auf der Verwendung des Stackpointers<br />

auf.<br />

4Central Processing Unit, eine Bezeichnung, die Steuer- und Rechenwerk<br />

zusammenfasst.<br />

5FiFo steht für first in - first out. Ein anderes Prinzip ist last in - first<br />

out, LiFo.


KAPITEL 3. RECHNERARCHITEKTUR 29<br />

3.4 Statusregister<br />

Im Statusregister merkt sich die ALU das logische Ergebnis<br />

der letzen Berechnung. Die Bits des Statusregister zeigen an,<br />

ob das Ergebnis Null war, ob es negativ war, ob ein Übertrag<br />

statt fand usw. Hauptsächlich werden diese Werte für bedingte<br />

Programmsprünge verwendet.<br />

3.5 Harvard-Architektur<br />

Die zuvor beschriebene, in Princeton entwickelte von-<br />

Neumann-Architektur arbeitet <strong>mit</strong> einem Speicherwerk, das<br />

sowohl Programm als auch Daten in einem Speicher beherbergt.<br />

Bei der Harvard Architektur, der der in diesem<br />

Buch verwendete AVR Mikrocontroller entspricht, werden<br />

Programm und Daten in getrennten Speichern gehalten. Derartige<br />

Rechner sind robuster.<br />

3.6 CISC und RISC<br />

Nach den vorherigen Rezepten wurden viele Computer entwickelt.<br />

Dabei haben sich zwei Lager gebildet. CISC 6 kennen<br />

Befehle komplexer Art. Sie haben eine große, meist variable<br />

Wortbreite. Die Befehle haben sehr unterschiedliche<br />

Ausführungszeiten. Pentiums und Verwandte gehören dazu.<br />

6 Complex Instruction Set Computers


KAPITEL 3. RECHNERARCHITEKTUR 30<br />

RISC 7 haben einen schlanken Befehlsvorrat, feste Befehlslängen<br />

und Bearbeitungszeiten. Die in diesem Buch verwendeten<br />

AVR CPUs gehören zu dieser Gruppe.<br />

Übrigens verhält es sich nicht so, dass kleine Mikrocontroller<br />

RISC und große Mikroprozessoren CISC sind. Hier gibt es<br />

keinen Zusammenhang. Zum Beispiel sind Sparcs, die CPUs<br />

die in den Rechnern der Firma Sun arbeiten, RISC. Der Urahn<br />

der Mikrocontroller, der 8048 der Firma Intel, ist ein CISC.<br />

Manchmal ist es schwierig, eine CPU konkret einzuordnen.<br />

7 Reduced Instruction Set Computers


Kapitel 4<br />

Computerschnittstellen<br />

Fernschreiber, elektrische Schreibmaschinen, CD-Spieler,<br />

Fernseher oder Kameras waren ursprünglich nicht für Computer<br />

gedacht. Die Ein-/Ausgabewerke der Computer werden<br />

meist von anderen Firmen gebaut als die Computer selbst. Da<strong>mit</strong><br />

Produkte verschiedener Firmen zusammen funktionieren,<br />

müssen Schnittstellen vereinbart werden. Von diesen gibt es<br />

inzwischen unüberschaubar viele, meist <strong>mit</strong> netten Abkürzungen<br />

bedacht: RS232 RS485 VGA GDI PCI AGP I2C PS2 IDE<br />

ATAPI SCSI PCMCIA USB JETEC ... 1<br />

Technologisch kann man Schnittstellen in Gruppen einteilen.<br />

Es gibt<br />

• serielle – parallele Verbindungen<br />

1 Da fällt mir gerade ein Gesellschaftsspiel ein: Nenne eine Computerschnittstelle<br />

und lass sie von einem Mitspieler erklären.<br />

31


KAPITEL 4. COMPUTERSCHNITTSTELLEN 32<br />

• synchrone – asynchrone Verbindungen<br />

• unidirektionale – bidirektionale Verbindungen<br />

• Punkt zu Punkt Verbindung – Sternverbindung – Busverbindungen<br />

Man sollte noch zwischen norm- und nicht normgerecht verwendeten<br />

Verbindungen unterscheiden.<br />

Drei sehr wichtige Schnittstellen werden etwas tiefer behandelt,<br />

nicht nur, weil sie später tatsächlich verwendet werden.<br />

4.1 Centronics<br />

Diese eigentlich nur für Druckwerke gedachte Schnittstelle<br />

wurde vom gleichnamigen Drucker-Hersteller eingeführt.<br />

Wahrscheinlich aus historischen Gründen hat diese Schnittstelle<br />

einen Namen, der keine Abkürzung darstellt. Die Firma<br />

Centronics baute sehr schnelle mechanische Druckwerke, zuletzt<br />

Nadeldrucker. Zwar gibt es, glaube ich, keine Centronics-<br />

Drucker mehr, aber noch viele Druckermodelle <strong>mit</strong> dieser<br />

Schnittstelle.<br />

Es ist eine parallele, ehemals unidirektionale Schnittstelle <strong>mit</strong><br />

vielen Quittungssignalen. In den letzten Jahren wurden weitere<br />

Möglichkeiten zum Beispiel für die Nutzung von Scannern<br />

eingeführt. Vor diesen Erweiterungen war die Schnittstelle<br />

stabil und zuverlässig. Über Centronics angeschlossene


KAPITEL 4. COMPUTERSCHNITTSTELLEN 33<br />

Drucker funktionierten reibungslos. Die Kabel haben jedoch<br />

über 20 Leitungen. Die Reichweite ist auf ca. 10 m begrenzt.<br />

Die Funktionsweise ist im Prinzip synchron. Nachdem der<br />

Rechner die 8 Bit eines Zeichens auf 8 Datenleitungen eingestellt<br />

hat, signalisiert er dem Drucker <strong>mit</strong> dem, Strobe genannten,<br />

Signal, dass das Zeichen bereit ist. Der Drucker verarbeitet<br />

das Zeichen und antwortet auf der Leitung Acknowledge,<br />

dass er fertig ist. Ferner gibt es Leitungen für Paper<br />

out und andere Fehler.<br />

Die Anwendungen dieser Schnittstelle werden <strong>mit</strong>tlerweile<br />

durch USB ersetzt.<br />

Auch die Kommunikation <strong>mit</strong> unserem Mikrocontroller<br />

missbraucht diese Schnittstelle. Der ursprüngliche Sinn<br />

der Leitungen wird nicht angewendet. Da aber die PC-<br />

Architektur der Software ein Durchgreifen auf die einzelnen<br />

Leitungen erlaubt, eignen sich Centronicsschnittstellen dafür<br />

hervorragend.<br />

Am PC-Gehäuse ist diese Schnittstelle als DB-25 Buchse erkennbar.<br />

4.2 RS-232<br />

Dies ist eine asynchrone symmetrische bidirektionale Schnittstelle<br />

aus den 60er Jahren. Manchmal wird sie auch V24 genannt.<br />

Unter diesem Namen wurde die Schnittstelle für den<br />

Telefonbereich genormt.


KAPITEL 4. COMPUTERSCHNITTSTELLEN 34<br />

In vielen Dingen ist sie technisch überholt. Ursprünglich ersetzte<br />

sie die langsame Fernschreiberschnittstelle 2 zum Anschluß<br />

von Dialogschnittstellen (engl. Terminals) in Rechenzentren.<br />

Da die Verbindungsleitungen nur etwa Raumlänge<br />

haben konnten, wurden <strong>mit</strong> Hilfe von Modems beliebig lange<br />

Telefonverbindungen realisiert. So sind externe Modems<br />

heute noch die klassische Anwendung dieser Schnittstelle, deren<br />

Tage wegen ISDN und DSL gezählt werden. Im Laufe ihres<br />

langen Lebens wurde sie für fast alle Peripheriegeräte wie<br />

Drucker, Plotter, Maus, Kamera eingesetzt. Heutige Rechner<br />

haben oft noch zwei von diesen Schnittstellen eingebaut, ein<br />

Ersatz durch USB-Adapter wird aber üblich.<br />

Auch der hier verwendete Mikrocontroller enthält in seinem<br />

Ein-/Ausgabewerk etliche Vorkehrungen zur Unterstützung<br />

dieser Schnittstelle. Ein einziger gängiger Baustein zur elektrischen<br />

Pegelwandlung genügt für die Anpassung an die normgerechte<br />

Schnittstelle.<br />

Die Norm sah 25-polige Steckverbinder vor, die bei Modem<br />

und Computer so unterschiedlich belegt waren, dass eine einszu-eins<br />

Verbindung möglich war. Dies ist einer der möglichen<br />

Fallstricke, den RS232 bietet. Bei vielen Anwendungen ist<br />

schwer zu entscheiden, welche Seite das Modem und welche<br />

den Computer vertritt.


KAPITEL 4. COMPUTERSCHNITTSTELLEN 35<br />

Abbildung 4.1: DB9-Stecker des IBM-AT<br />

4.2.1 RS232-Schnittstelle des IBM AT<br />

Zur Vereinfachung werden PCs <strong>mit</strong> auf 9 Pole reduzierten<br />

RS232-Verbindungen ausgestattet. Abbildung 4.1 zeigt die<br />

Pin-Belegung eines derartigen Steckers. Die Pins haben folgende<br />

Funktion:<br />

Pin 1, DCD, data carrier detect<br />

Das Modem hat ein Trägersignal erkannt.<br />

Dieses Signal wird von Modems verwendet.<br />

Signalrichtung: input. Spannung: positiv.<br />

Pin 2, RXD, receive data<br />

Daten werden seriell empfangen.<br />

2 Der Marktführer für Fernschreiber war in Amerika die Firma Teletype.<br />

Von deren Firmennamen leitet sich die Abkürzung TTY ab.


KAPITEL 4. COMPUTERSCHNITTSTELLEN 36<br />

Dieses Signal wird immer verwendet.<br />

Signalrichtung: input. Spannung: wechselnd.<br />

Pin 3, TXD, trans<strong>mit</strong> data<br />

Daten werden seriell gesendet.<br />

Dieses Signal wird immer verwendet.<br />

Signalrichtung: output. Spannung: wechselnd.<br />

Pin 4, DTE, data terminal ready<br />

Der Computer ist bereit, eine Verbindung einzugehen.<br />

Dieses Signal wird weniger genutzt.<br />

Signalrichtung: output. Spannung: positiv.<br />

Pin 5, GND, ground<br />

Dies ist das Massepotential, auf das sich die anderen Signale<br />

beziehen.<br />

Diese Leitung wird immer verwendet.<br />

Signalrichtung: keine. Spannung: Massepotential.<br />

Pin 6, DSR, data set ready<br />

Die Gegenstation ist bereit, eine Verbindung einzugehen.<br />

Dieses Signal wird weniger genutzt.<br />

Signalrichtung: input. Spannung: positiv.<br />

Pin 7, RTS, request to send


KAPITEL 4. COMPUTERSCHNITTSTELLEN 37<br />

Der Computer ist bereit, Daten zu empfangen.<br />

Diese Leitung wird beim sogenannten Hardware-Handshake<br />

verwendet.<br />

Signalrichtung: output. Spannung: positiv.<br />

Pin 8, CTS, clear to send<br />

Die Gegenstation ist bereit, Daten zu empfangen.<br />

Diese Leitung wird beim sogenannten Hardware-Handshake<br />

verwendet.<br />

Signalrichtung: input. Spannung: positiv.<br />

Pin 9, RI, ring indicator<br />

Das Modem hat ein Klingelsignal erkannt.<br />

Dieses Signal wird von Modems verwendet.<br />

Signalrichtung: input. Spannung: positiv.<br />

Werden PCs <strong>mit</strong>einander verbunden, so müssen bestimmte<br />

Leitungen gekreuzt werden.<br />

Neben Varianten der Verdrahtung zweier Geräte gibt es noch<br />

Varianten in der Übertragungsgeschwindigkeit, im Aufbau der<br />

Übertragungsrahmen und in der Synchronisation. Die Multiplikation<br />

dieser Möglichkeiten ergibt eine beachtliche Anzahl,<br />

die schon manchen Nutzer verzweifeln ließ.<br />

Neben den üblichen Varianten der seriellen Schnittstelle gibt<br />

es obendrein auch noch solche <strong>mit</strong> unterschiedlichen Steckern<br />

und Spannungen. Auch die Programmierschnittstelle dasa2


KAPITEL 4. COMPUTERSCHNITTSTELLEN 38<br />

zu unserem Mikrocontroller nutzt die serielle Schnittstelle des<br />

PCs ohne Rücksicht auf Konventionen, trotzdem funktioniert<br />

es in der Regel.<br />

4.2.2 Schichten<br />

Im Prinzip kann man an RS232-Verbindungen sehr schön ein<br />

Schichtenmodell studieren<br />

• Kabel und Stecker<br />

• Spannungen<br />

• Signalform und Bitsynchronisation<br />

• Synchronisation<br />

• Treiber des Betriebsystems<br />

• Anwendung<br />

Alle Schichten sind weitgehend unabhängig voneinander und<br />

arbeiten über definierte Schnittstellen <strong>mit</strong>einander. Die Analyse<br />

eines Systems wird wiederum schichtenweise durchgeführt:<br />

• Ist das Kabel in Ordnung, stimmt die Belegung der<br />

Steckkontakte?


KAPITEL 4. COMPUTERSCHNITTSTELLEN 39<br />

• Sind die Spannungspegel richtig?<br />

• Stimmen Geschwindigkeit und Rahmenaufbau (Anzahl<br />

der Daten-, Prüf- und Stopbits)?<br />

• Welche Synchronisation wird verwendet?<br />

• Treiber geladen? Gerätename richtig?<br />

• Anwendung installiert?<br />

Besonders verwirrend ist die Synchronisation. Historisch sind<br />

drei Grundformen gewachsen:<br />

Hardware Handshake: Synchronisation <strong>mit</strong> Hilfe der<br />

Quittungsleitungen. Am wichtigsten sind CTS und<br />

RTS.<br />

Software Handshake: Synchronisation durch Steuerzeichen<br />

im Datenstrom. Meist werden ctrl-S 3 für Stop<br />

und ctrl-Q für Weiter verwendet. Diese Synchronisation<br />

funktioniert sogar in der shell.<br />

kein Handshake: Beide Partner sind so schnell, dass eine<br />

Synchronisation überflüssig ist.<br />

3 Die Eingabe dieses Steuerzeichens ist nach wie vor möglich. Man läßt<br />

sich einen sehr langen Text durch das Programm cat anzeigen. Durch<br />

gleichzeitiges Drücken der Tasten Strg und S wird die Anzeige angehalten,<br />

<strong>mit</strong> Strg und Q geht es weiter. Dies ist ein Relikt aus der Zeit,<br />

in der an Computer-Terminals <strong>mit</strong> RS232-Schnittstellen angeschlossen<br />

wurden.


KAPITEL 4. COMPUTERSCHNITTSTELLEN 40<br />

Teilweise werden die Synchronisationsarten bunt gemischt,<br />

weshalb sehr häufig Brücken in die Kabel eingebaut werden.<br />

CTS <strong>mit</strong> RTS und DSR <strong>mit</strong> DTR <strong>mit</strong> DCD sind übliche<br />

Brücken.<br />

4.3 USB<br />

USB ist eine moderne asynchrone serielle bidirektionale<br />

Schnittstelle <strong>mit</strong> Bus-Charakter. Bei der Entwicklung wurde<br />

vorgesehen, die meisten tradionellen Schnittstellen auf USB<br />

abbilden zu können. USB hat nur vier Leitungen, von denen<br />

zwei sogar eine 5 V Stromversorgung bis zu 500 mA übernehmen.<br />

Die beiden anderen verdrillten Leitungen übertragen ein<br />

serielles Signal, indem die Spannungen zwischen 0 V und 3,3 V<br />

hin und hergeschaltet werden. Jede Leitung überträgt das Gegenteil<br />

der anderen. Sie werden D+ und D- genannt.<br />

Da<strong>mit</strong> bis zu 128 Geräte in einer baumartigen Verdrahtung<br />

zuletzt über ein Kabel kommunizieren können, ist ein<br />

aufwändiges Protokoll für die Verteilung von Ressourcen und<br />

Adressen notwendig. Letztendlich befindet sich hinter jedem<br />

USB-Stecker ein eigener Mikrocontroller <strong>mit</strong> speziellen USB-<br />

Fähigkeiten. Für den Anschluß von RS232 und Centronics<br />

gibt es fertige Adaptergeräte, die zwischen alt und neu ver<strong>mit</strong>teln.<br />

Während bei RS232 noch viel Know-How vom Anwender erwartet<br />

wurde, funktioniert USB oder auch nicht. Die Nutzung<br />

der USB-Schnittstelle für eigene Experimente ohne zu-


KAPITEL 4. COMPUTERSCHNITTSTELLEN 41<br />

gekaufte Soft- und Hardware ist in der Regel ausgeschlossen.<br />

Die auf der USB-Homepage [usb] erhältliche Beschreibung der<br />

Schnittstelle enthält fast 600 Seiten.<br />

Die Wiener Firma Objective Development [obdev] hat einen<br />

USB-Treiber für Mikrocontroller ins Internet gestellt. Dieser<br />

Treiber ermöglichte die Entstehung einer Programmierhardware<br />

<strong>mit</strong> USB-Schnittstelle, wie sie im dritten Teil des Buches<br />

noch vorgestellt wird.


Kapitel 5<br />

Kurzeinführung in Linux<br />

Auch wenn der Aufbau der Hardware in diesem Buch <strong>mit</strong><br />

beschrieben wird, liegt der eigentliche Schwerpunkt bei der<br />

Entwicklung der Programme, also der Software. Zum Erzeugen<br />

der Programme braucht man wiederum Programme und<br />

diese brauchen wieder ein Programmsystem, Betriebssystem<br />

genannt.<br />

Dieses Projekt ist über eine Reihe von Schichten verteilt, die<br />

wie ein Obstkuchen aufeinander aufbauen: Mürbeteig, Marmelade,<br />

Biskuit, Obst, Guss, Sahne. Ich hoffe, der nächste<br />

Bäcker hat noch auf.<br />

Unser Projekt ist wie folgt aufgebaut:<br />

• PC Hardware<br />

42


KAPITEL 5. KURZEINFÜHRUNG IN LINUX 43<br />

• Betriebssystem Linux<br />

• Dialogprogramm bash<br />

• Werkzeuge wie Editor, Compiler, Assembler, Linker<br />

• Mikrocontroller, Kommunikationsprogramm<br />

Wenn diese Schichten gebacken sind, kann der Mikrocontroller<br />

wiederum in Schichten geteilt werden:<br />

• Mikrocontroller Platine<br />

• Mikrocontroller Bestückung<br />

• Verbindung <strong>mit</strong> PC<br />

• Verschiedene Test-Programme<br />

Wichtig ist, dass jede Schicht ausreichend funktionieren muss,<br />

bevor die nächste Schicht darauf aufgesetzt werden kann. Der<br />

Leser sollte sich also <strong>mit</strong> jeder Schicht so vertraut machen,<br />

dass er deren Funktionsfähigkeit beurteilen kann. Vor dem<br />

Aufbau der nächsten Schicht müssen Unklarheiten durch weitergehende<br />

Studien ausgeräumt werden, sonst ist ein Erfolg<br />

so gut wie ausgeschlossen.


KAPITEL 5. KURZEINFÜHRUNG IN LINUX 44<br />

5.1 Kern des Betriebssystems<br />

Es gibt zwei gebräuchliche Anwendungen des Begriffs Betriebssystem.<br />

Der weitergehende Begriff umfasst einen Kern<br />

als auch darüber angesiedelte Schichten von <strong>mit</strong> dem System<br />

gelieferten Dialogprogrammen und Werkzeugen.<br />

In diesem Buch soll nur der reine Kern als Betriebssystem<br />

bezeichnet werden.<br />

Zweck des Betriebssystems ist die Verteilung der verschiedenen<br />

Ressourcen, die der Computer verwaltet, an die laufenden<br />

Anwendungsprogramme. Ressourcen sind insbesondere<br />

• CPU-Zeit<br />

• RAM 1 , auch Kernspeicher 2 genannt<br />

• Plattenspeicher<br />

• Geräte (Bildschirm, Tastatur, Maus, Drucker, Modem,<br />

Netzwerk, ...)<br />

• ...<br />

1 engl.: random acesss memory, Speicher <strong>mit</strong> zufällig verteilbarem Zu-<br />

griff 2als Transistoren noch teuer waren, wurden Speicher <strong>mit</strong> kleinen Ma-<br />

gnetringen, sogenannten Kernen, aufgebaut


KAPITEL 5. KURZEINFÜHRUNG IN LINUX 45<br />

Anwendungsprogramme sind Programmschichten, die auf<br />

dem Betriebssystem aufbauen. Diese können erweiterte Systemfunktionalitäten<br />

realisieren als auch vom Anwender gestartete<br />

Programme sein.<br />

Der Betriebssystemkern von Linux ist ein im Jahre 1991 auf<br />

Initiative des damaligen Studenten Linus Torvalds 3 im Internet<br />

entstandener Clone des Betriebssystems Unix. Auslöser<br />

war, dass die damals etablierte PC-CPU der 80386 der Firma<br />

Intel mehr bot als die damals gängigen Betriebssysteme<br />

nutzten.<br />

Unix ist ein Betriebssystem, dass aus der Welt der Rechenzentren<br />

kommt, in der mehrere Benutzer einen Computer<br />

gleichzeitig nutzen. Die relativ hohe Rechengeschwindigkeit<br />

der CPU wird in Zeitscheiben an die Nutzer verteilt. Jeder<br />

Nutzer hat das Gefühl, einen eigenen Computer zu besitzen.<br />

Da<strong>mit</strong> die Nutzer sich nicht gegenseitig stören können, wird<br />

von Unix hoher Wert darauf gelegt, die Nutzer voneinander<br />

abzuschirmen. Daraus ergeben sich Vor- und Nachteile gegenüber<br />

Betriebssystemen, die scheinbar 4 von nur einem Benutzer<br />

genutzt werden.<br />

Nachteilig ist, dass die erhöhte Sicherheit für die Nutzer unbequem<br />

ist, da an verschiedenen Stellen zusätzliche Eingaben<br />

erforderlich sind. Vorteil ist, dass unter Unix ein Absturz des<br />

3 Die Biographie von Linus Torvalds gibt es als lesenswertes Taschenbuch<br />

[Torvalds].<br />

4Da Computernutzer in der Regel Programme von mehreren Programmierern<br />

ausführen, trügt der Schein, es gebe nur einen Benutzer!


KAPITEL 5. KURZEINFÜHRUNG IN LINUX 46<br />

Betriebssystems eine seltene Ausnahme ist. Ein Nutzer kann<br />

mehrere Programme gleichzeitig rechnen lassen.<br />

Da Unix von Anfang an einen durchdachten Ansatz verfolgt<br />

hat, sind Unverträglichkeiten im Verlauf der Weiterentwicklung<br />

selten.<br />

Linus Torvalds hat seines Geistes Kind sehr bald unter die<br />

GNU-Lizenz gestellt. Seit der Zeit hat sich ein regelrechter<br />

Markt von frei erhältlichen Unix-ähnlichen Betriebssystemen<br />

entwickelt. Für die weltweite Situation der Software war das<br />

ein entscheidender Schub in eine Richtung, die der ehemalige<br />

MIT-Mitarbeiter Richard Stallman <strong>mit</strong> der Free Software<br />

Foundation (FSF) eingeschlagen hatte.<br />

Die folgende Einführung in Linux ist knapp gehalten. Auch<br />

zum späteren Nachschlagen gut geeignet ist das Linux Anwenderhandbuch<br />

[Linux], das einen ernsthaften Einstieg in Linux<br />

gut begleitet.<br />

5.2 Bäume wachsen – Dateisysteme<br />

Ein wichtiger Punkt für den bewussten Umgang <strong>mit</strong> Computern<br />

ist das Verständnis des Dateisytems auf den Festplatten.<br />

Unter Unix wird ein Modell angewendet, welches sich Dateibaum<br />

nennt. Dateibäume bestehen vorwiegend aus zwei verschieden<br />

Typen von Objekten:


KAPITEL 5. KURZEINFÜHRUNG IN LINUX 47<br />

Verzeichnisse: werden auch Directory oder Ordner genannt.<br />

Bei Unix dürfen für deren Benennung Worte aus<br />

fast allen Buchstaben verwendet werden, was jedoch bei<br />

zu freizügigem Umgang zu Problemen <strong>mit</strong> den Werkzeugen<br />

führen kann. Man wählt anfangs besser nur Worte, die man<br />

ganz natürlich als Namen vergeben würde.<br />

Dateien: werden auch File genannt. Namen werden wie<br />

für Verzeichnisse gebildet. Die Dateien enthalten die Daten,<br />

die unter dem Dateinamen für (vorläufig unbegrenzte Zeit)<br />

gespeichert werden.<br />

Nun gelten drei einfache Regeln:<br />

1. Ein Dateibaum hat genau einen Anfang. Dieser Anfang<br />

wird Wurzelverzeichnis oder Root-Directory genannt.<br />

Das Wurzelverzeichnis hat keinen frei wählbaren Namen,<br />

sondern heisst ,, / ”.<br />

2. Jedes Verzeichnis (inklusive Wurzelverzeichnis) darf beliebig<br />

viele Dateien und Verzeichnisse enthalten.<br />

3. Die Namen werden <strong>mit</strong> dem Zeichen / getrennt.<br />

Wem obiges System zu abstrakt ist, stelle sich eine schön gewachsene<br />

Eiche vor: Der Stamm ist das Wurzelverzeichnis, die<br />

Verzeichnisse sind die Äste, die Blätter sind die Dateien und<br />

der Benutzer ist das Eichhörnchen.


KAPITEL 5. KURZEINFÜHRUNG IN LINUX 48<br />

Manchmal gibt es beim Verständnis des Baummodells ein kleines<br />

Problem: Bäume wachsen von unten nach oben. Wird das<br />

in Schriftform niedergelegt, geht das natürlich besser von oben<br />

nach unten, weil wir das Schreiben in dieser Richtung gewohnt<br />

sind.<br />

Dieses System wurde in einer vereinfachend modifizierten<br />

Form auch für MS-DOS und seine Töchter übernommen. Da<br />

das Internet primär in der Unix-Welt aufgewachsen ist, wird<br />

auch dort das Baummodell verwendet. Das Wurzelverzeichnis<br />

heißt dort http://, die ersten Bezeichner heißen Domain<br />

wie zum Beispiel www.google.de, die Adresse einer beliebten<br />

Suchmaschine.<br />

Dem Betriebssystemkern ist es egal, wie die Benutzer den Dateibaum<br />

wachsen lassen, solange sie die Festplattenkapazität<br />

beachten. Da<strong>mit</strong> die Unordnung nicht zu groß wird, gelten bei<br />

Linux weitere Regeln:<br />

/ Das Wurzelverzeichnis darf nur der Systemadministrator<br />

beschreiben.<br />

/bin Hier befinden sich die Programme, die manchmal auch<br />

zum Betriebssystem hinzugezählt werden. Siehe Abschnitt<br />

5.1.<br />

/sbin Programme für die Systemverwaltung<br />

/dev hier befinden sich die Geräteschnittstellen<br />

/etc Dateien zur Einstellung des Betriebsystems


KAPITEL 5. KURZEINFÜHRUNG IN LINUX 49<br />

/home die Heimatverzeichnisse der Nutzer<br />

/lib Bibliothek von Unterprogrammen<br />

/usr wichtige Programme und Daten; ziemlich unordentlich.<br />

/usr/bin die Fortsetzung von /bin<br />

/tmp Hier darf jeder Nutzer vorübergehende, unwichtige,<br />

Dateien ablegen. In manchen Systemen werden diese<br />

später automatisch gelöscht.<br />

Es soll eindringlich darauf hingewiesen werden, dass ein sicherer<br />

Umgang <strong>mit</strong> heutigen Computern, gleich welcher Art,<br />

ein Verständnis dieses Baummodells voraussetzt. Schon eine<br />

vernünftige Planung der notwendigen Datensicherung scheitert<br />

ohne dessen Verständnis.<br />

Da es so wichtig ist, möchte ich nochmal auf das Dateisystem<br />

eingehen. Es gibt drei besondere Verzeichnisse.<br />

5.2.1 Wurzelverzeichnis<br />

Dateinamen <strong>mit</strong> / am Anfang heißen absolute Dateinamen.<br />

Sie beziehen sich auf das Wurzelverzeichnis.<br />

Man gibt den kompletten Weg durch den Dateibaum vom<br />

Wurzelverzeichnis aus an. Beispiel eines Zugriffs auf nicht im<br />

Arbeitsverzeichnis liegende Daten:<br />

grep $HOME /etc/passwd


KAPITEL 5. KURZEINFÜHRUNG IN LINUX 50<br />

5.2.2 Heimatverzeichnis<br />

Es heißt auch Home Directory.<br />

$HOME entspricht dem Wurzelverzeichnis des Benutzers. Jedem<br />

Benutzer ist genau ein Heimatverzeichnis zugewiesen. In<br />

diesem Verzeichnis darf er seinen eigenen Teil des Dateibaums<br />

aufbauen. Un<strong>mit</strong>telbar nach der Anmeldung beim System ist<br />

das im nächsten Unterpunkt beschriebene Arbeitsverzeichnis<br />

auf das Heimatverzeichnis gesetzt.<br />

5.2.3 Arbeitsverzeichnis<br />

Dateinamen ohne / am Anfang heißen relative Dateinamen.<br />

Sie beziehen sich auf das Arbeitsverzeichnis.<br />

Das Arbeitsverzeichnis, die englische Bezeichnung ist Current<br />

Working Directory, ist das Verzeichnis, auf das sich in der<br />

Regel die Befehle des Nutzers beziehen. Falls es vorkommt,<br />

dass man den Namen des Arbeitsverzeichnisses gerade nicht<br />

weiß, da es ja variabel ist, gibt das Programm<br />

pwd<br />

(print working directory) Auskunft. Es ist sinnvoll, für getrennte<br />

Arbeiten getrennte Verzeichnisse anzulegen.<br />

Zum Wechseln des Arbeitsverzeichnisses gibt es das Programm


KAPITEL 5. KURZEINFÜHRUNG IN LINUX 51<br />

cd<br />

(change directory). Nicht immer ist es ausreichend, Dateien<br />

im Arbeitsverzeichnis anzusprechen, da es Dateien gibt, die<br />

für verschiedene Arbeitsvorgänge angelegt werden. In diesem<br />

Fall verwendet man absolute Dateinamen.<br />

Nach meiner Beobachtung ist ein wichtiger Grund für<br />

Missverständnisse zwischen Anfängern und fortgeschrittenen<br />

Nutzern das Unwissen um die Existenz des Arbeitsverzeichnisses!<br />

5.3 GNU - Tools<br />

Richard Stallman, der bereits vorgestellte Gründer der FSF,<br />

ist der Überzeugung, dass geistige Entwicklungen zwar einen<br />

Autor haben, der als solcher auch erwähnt werden muss, die<br />

Nutzung einer Idee aber allen Menschen verfügbar gemacht<br />

werden soll.<br />

Aus dieser Überzeugung heraus entwickelte er eine Softwarelizenz,<br />

die GPL, die einen Vertrag zwischen Autor und Nutzer<br />

knüpft und die Software vor eigennützigen Interessen schützt.<br />

Die wesentlichen Vertragspunkte sind:<br />

1 Die Software darf von jedem verteilt oder verkauft werden.<br />

2 Der Nutzer darf das Programm sogar ändern.


KAPITEL 5. KURZEINFÜHRUNG IN LINUX 52<br />

3 Der Nutzer hat Anspruch auf die Programmquellen.<br />

4 Der Vertrag darf nicht eingeschränkt werden (auch wenn<br />

nur Programmteile genutzt werden).<br />

7 Betroffene Patente müssen für Jedermann frei nutzbar<br />

sein.<br />

11 Der Autor gewährt keine Haftung.<br />

Richard Stallman legt Wert darauf, dass es nur eine<br />

gültige Version der Lizenz gibt. Diese findet man unter<br />

www.gnu.org/licences [gnu].<br />

GNU ist ein sogenanntes Akronym als Abkürzung für ,,GNU<br />

is Not Unix”, was wohl auf die Lizenzpolitik des ursprünglichen<br />

Unix anspielen soll.<br />

Es wurden GNU-Versionen der wichtigsten Unix-Werkzeuge<br />

neu programmiert:<br />

ls Listet den Inhalt eines Verzeichnisses.<br />

cat Zeigt Inhalt von Dateien, kann viel mehr.<br />

cp Kopierprogramm<br />

rm Löschprogramm


KAPITEL 5. KURZEINFÜHRUNG IN LINUX 53<br />

mkdir Erzeugt Verzeichnisse.<br />

rmdir Entfernt leere Verzeichnisse.<br />

find Sucht im Dateibaum.<br />

man Gibt Hilfe zu dem im Argument benannten Befehl.<br />

tar Sicherungsprogramm<br />

Dies ist nur eine kleine Auswahl wichtiger Programme der<br />

großen Menge der GNU-Werkzeuge, die sich vor allem in den<br />

Verzeichnissen /bin /usr/bin und /sbin befinden. Jedes Programm<br />

kennt eine Menge von Schaltern und Optionen, die<br />

man <strong>mit</strong> dem Schaltern -h oder --help abrufen kann. Weitere<br />

Hilfe bieten die Befehle man ls ... und info ls ...<br />

5.3.1 bash<br />

Der Betriebssystemkern kann nicht direkt <strong>mit</strong> dem Nutzer<br />

kommunizieren. Hierzu ist ein weiteres wichtiges Programm<br />

notwendig, dem der bildhafte Name Shell gegeben wurde, da<br />

es wie eine harte Schale den Kern vom Nutzer trennt. Die erste<br />

Shell, die weite Verbreitung fand, wurde von S. R. Bourne<br />

geschrieben. Da diese Shell noch viele Wünsche offen ließ,


KAPITEL 5. KURZEINFÜHRUNG IN LINUX 54<br />

entstanden andere Shells, wie die cshell, die leider recht inkompatibel<br />

zur Bourne-Shell war. Diesen Fehler korrigierte<br />

die Korne-Shell <strong>mit</strong> anderen Problemen.<br />

Bei der FSF entschied man sich, zur Bourne-Shell kompatibel<br />

zu bleiben, neue Features aber so gut wie möglich einzubauen.<br />

Es entstand die mächtige bash. Der Name ist eine Abkürzung<br />

von Bo(u)rn(e) Again SHell.<br />

Neben der notwendigen Eigenschaft, Befehle in der Form von<br />

Programmnamen und eventuellen Schaltern und Argumenten<br />

von der Tastatur anzunehmen, ist die Shell auch Programmiersprache.<br />

Man kann Befehle <strong>mit</strong> einem Editor in eine Datei<br />

schreiben und diese Datei wiederum wie ein Programm<br />

starten. Es ist möglich, Programme über Schleifen und Bedingungen<br />

zu komplexeren Programmen zu verbinden. Es gibt<br />

auch Unterprogramme. Ein derartiges Programm wird auch<br />

Shellscript genannt.<br />

So werden zwei wichtige Unix-Konzepte unterstützt: Programme<br />

einfach und begrenzt zu halten und <strong>mit</strong> einfachen<br />

Bausteinen komplexere Dinge zu realisieren.<br />

5.3.2 Editoren<br />

Editoren verwendet man, um Texte in den Computer einzugeben.<br />

Texte sind nicht nur Briefe und Aufsätze, es können<br />

auch Daten, Programme, Bücher usw. sein. Editoren sind also<br />

die wichtigsten Eingabeprogramme für Computer. Prinzipiell


KAPITEL 5. KURZEINFÜHRUNG IN LINUX 55<br />

könnten im nicht grafischen Bereich alle Eingaben über Editoren<br />

geschehen.<br />

Aus diesem Grund haben viele Leute ihren eigenen Editor<br />

geschrieben (Autor eingeschlossen). Sechs wichtige Editoren<br />

möchte ich erwähnen:<br />

vi ist der Nachfolger des ersten Unix-Editors ed. vi konnte<br />

<strong>mit</strong> den damals neuen Bildschirmterminals umgehen. ed funktionierte<br />

noch <strong>mit</strong> Fernschreibern. Eine wichtige Eigenschaft<br />

von vi ist, dass er <strong>mit</strong> dem Zehn-Finger-System blind bedient<br />

werden kann.<br />

vim ist eine umfangreiche Nachprogrammierung des vi <strong>mit</strong><br />

vielen Erweiterungen. In der Lizenz des vim wird man eingeladen,<br />

Kinder in Uganda finanziell zu unterstützen.<br />

emacs gehört zum Grundstock der FSF. emacs ist um einen<br />

Kern der Programmiersprache Lisp gebaut worden und in Lisp<br />

erweiterbar. Der Autor ist Richard Stallman. Leider entspricht<br />

emacs nicht mehr dem Unixkonzept, klein zu sein, weshalb die<br />

Meinung dazu recht gespalten ist.<br />

e3 ist ein sehr kleiner (8KB) in Assembler programmierter<br />

Editor, der dennoch Oberflächen bietet, die sich an vi, emacs,<br />

wordstar, nedit und pico anlehnen.


KAPITEL 5. KURZEINFÜHRUNG IN LINUX 56<br />

pico ist ein relativ einfach zu bedienender Editor ohne komplexe<br />

Funktionen.<br />

gvim ist der für X11-Oberflächen erweiterte vim. gvim<br />

setzt Farbe zur Hervorhebung von Programmiersprachen ein<br />

und kann auch sinnvoll <strong>mit</strong> der Maus bedient werden.<br />

Alle erwähnten Editoren sind für die Eingabe von Programmen<br />

geschrieben worden. Obwohl es für Linux auch sehr gute<br />

WYSIWYG 5 - Editoren gibt, werden diese vom Autor bewusst<br />

nicht eingesetzt. Der Autor nutzt heute vim, da dieser<br />

das Zehn-Finger-Blindschreiben am besten unterstützt. Mehr<br />

zu diesem Thema im makefile.latex auf der Homepage [unger]<br />

des Autors.<br />

5.3.3 make<br />

make wurde geschrieben, um das wiederholte Aufrufen von<br />

Programmierwerkzeugen zu erleichtern. In einem Makefile<br />

werden die Abläufe und Abhängigkeiten für die Übersetzung<br />

von Programmen formuliert. make kann <strong>mit</strong> dieser Beschreibung<br />

den Übersetzungslauf automatisieren und optimieren.<br />

Die Optimierung wird über die Angabe der Abhängigkeiten<br />

im Makefile und Änderungszeiten der beteiligten Dateien entschieden.<br />

In großen Systemen, wie zum Beispiel bei der Übersetzung<br />

des Linux Betriebssystems, wird dadurch viel Zeit<br />

gewonnen. In kleinen Systemen dokumentiert das Makefile<br />

5 What You See Is What You Get


KAPITEL 5. KURZEINFÜHRUNG IN LINUX 57<br />

immerhin noch den Entstehungsvorgang. make ist nicht auf<br />

Programmentwicklung beschränkt. Es leistet auch gute Dienste<br />

bei der Pflege von Datenbanken und mehr.<br />

In den Verzeichnissen, die die Software für das<br />

Mikrocontroller- Experimentiersystem enthalten, befindet<br />

sich meist ein Makefile <strong>mit</strong> integrierter Dokumentation.<br />

Der Aufruf von ,,make” oder ,,make help” erzeugt die<br />

Ausgabe<br />

Usage: make same as make help<br />

make help same as make<br />

make vi edit sourcefile<br />

make eeprom create data for eeprom<br />

make flash compile flashable file<br />

make upload upload flash into processor<br />

make upload_fuse program fuse<br />

make upload_eeprom upload eeprom into processor<br />

make download read data from processor and compare<br />

make disasm disasm flash<br />

make verify verify flash<br />

make erase erase chip<br />

make clean remove redundant data<br />

Die verfolgte Absicht dieses Konzeptes besteht darin, nur<br />

einen Befehl kennen zu müssen, nämlich ,,make”. Der Rest<br />

ergibt sich.<br />

5.3.4 X11<br />

Die graphische Oberfläche für Unix heißt X11. Das Konzept<br />

ist tief durchdacht. So ist es möglich, X11-Programme auf<br />

anderen Rechnern im Internet zu starten, d.h. Maus, Tastatur,<br />

Bildschirm und Programm können auf verschiedene Rechner<br />

verteilt werden.


KAPITEL 5. KURZEINFÜHRUNG IN LINUX 58<br />

Für X11 wurden verschiedene Fenstermanager programmiert.<br />

Modern sind Gnome und KDE. Ein sehr kleiner Fenstermanager<br />

wurde von den Entwicklern von X11 selbst entworfen.<br />

Er heißt twm. Wahrscheinlich dient er bei der Entwicklung<br />

als Testumgebung. Kleineren Computern ermöglicht twm eine<br />

grafische Oberfläche anzubieten, auf der man gut mehrere<br />

Fenster öffnen, Bilder betrachten, Bücher lesen und andere<br />

grafikorientierte Tätigkeiten erledigen kann.<br />

5.3.5 Ghostscript<br />

Da Drucker sehr unterschiedlich angesteuert werden, hat sich<br />

in der Unix-Welt eine Sprache für Druckwerke, namentlich<br />

Postscript etabliert. Postscript wurde von der Firma Adobe<br />

[adobe] entwickelt.<br />

Drucker, die Postscript direkt verstehen, sind manchmal teurer<br />

als einfachere Modelle. Um preiswerte Drucker einsetzen<br />

zu können, übersetzt das Programm ghostscript den<br />

Postscript-Code in einfache Druckerbefehle. Natürlich muss<br />

bei der Installation das vorhandene Druckermodell eingestellt<br />

werden.<br />

5.3.6 Datenbank<br />

Die folgenden Programme ermöglichen unter Zuhilfenahme eines<br />

Editors die Realisierung kleiner Datenbanken. Neben der


KAPITEL 5. KURZEINFÜHRUNG IN LINUX 59<br />

Textverarbeitung ist das eine häufige und wichtige Anwendung<br />

von Computern.<br />

grep selektiert Zeilen in Tabellen.<br />

cut selektiert Spalten in Tabellen.<br />

join vereinigt Tabellen.<br />

sort sortiert Tabellen.<br />

awk Programmiersprache für Tabellenbearbeitung.<br />

sed editiert Dateien programmgesteuert.<br />

Zu Zeilen sagt man oft Datensätze 6 . Spalten werden häufig<br />

Felder 7 . genannt. Tabellen speichert man in Dateien. Die<br />

Grundfunktionen grep, cut und join erzeugen wiederum Tabellen.<br />

Ein kleines Beispiel soll eine Idee der Funktion von Datenbanken<br />

ver<strong>mit</strong>tlen:<br />

Eine Tabelle <strong>mit</strong> dem Dateinamen ,,geburtstage” enthält folgende<br />

Daten:<br />

Huber:1980Apr01:Hamburg<br />

Meier:1975Mar04:Frankfurt<br />

Molch:1977Feb11:München<br />

Eine Anfrage an die Datenbank, wer am 1. April Geburtstag<br />

hat, sähe folgendermaßen aus:<br />

6 In der englischsprachigen Literatur records genannt.<br />

7 In der englischsprachigen Literatur fields genannt.


KAPITEL 5. KURZEINFÜHRUNG IN LINUX 60<br />

grep Apr01 geburtstage|cut -d: -f1<br />

Eine weitere Tabelle <strong>mit</strong> dem Dateinamen ,,telefon” enthält<br />

diese Daten:<br />

Huber:0123-1111111<br />

Meier:0111-1212121<br />

Molch:0333-3333333<br />

Eine Tabelle der Telefonnummern der Geburtstagskinder des<br />

1. April:<br />

grep Apr01 geburtstage|join -t: - telefon|cut -d: -f4<br />

Wer wundert sich noch über Werbeanrufe?<br />

Vertiefung: Man studiere die man-pages von grep, join und<br />

cut, um das vorherige Kommando zu verstehen.


Kapitel 6<br />

Assembler<br />

Assembler sind Sprachen, die die Befehlscodes der jeweiligen<br />

CPU direkt abbilden. Jede CPU-Familie hat ihre eigene<br />

Assembler-Sprache. Da alle CPUs dem im Kapitel 3 beschriebenen<br />

Modell folgen, kann man mühelos von einer Assembler-<br />

Sprache auf eine andere umsteigen.<br />

Beim ersten Studium einer Assembler-Sprache sind Abbildungen<br />

der CPU, welche das Registermodell veranschaulichen,<br />

hilfreich.<br />

Neben der prinzipiell einfachen Umsetzung der Befehle, Mnemonics<br />

genannt, in die binären Befehlscodes, leisten Assembler<br />

noch die Berechnung von Sprung- und Datenadressen, die<br />

frei bezeichnet werden dürfen.<br />

Eine lästige Pflicht bei der Programmierung <strong>mit</strong> Assembler<br />

ist das Erfinden von Namen für Sprungmarken. Mit Hilfe der<br />

61


KAPITEL 6. ASSEMBLER 62<br />

im nächsten Kapitel erklärten strukturierten Programmierung<br />

und einem Notizzettel für das Abstreichen verwendeter Nummern<br />

kann man sich das Programmieren vereinfachen, wie folgendes<br />

Beispiel einer Schleife, die im Register1 von 1 bis 100<br />

zählt, zeigt:<br />

;nach Semikolon folgt ein Kommentar<br />

;r1=1<br />

ldi r1,1 ;load immediate<br />

;loop<br />

loop1: ;Sprungmarke<br />

;if r1==100 then breakloop endif<br />

cpi r1,100 ;compare immediate<br />

breq endloop1;branch if equal<br />

;r1=r1+1<br />

addi r1,1 ;add immediate<br />

;endloop:<br />

jmp loop1 ;jump<br />

endloop1: ;Sprungmarke<br />

Mit dieser Methode bereitet das beliebig tiefe Schachteln von<br />

Programmschleifen kein Problem mehr. if-then-else-endif behandelt<br />

man analog.<br />

Programme werden oft in mehrere Teile zerlegt. Im Idealfall<br />

nennt man das ,,modulares Programmieren”. Nachdem der<br />

Assembler alle Programmmodule übersetzt hat, werden diese<br />

vom Linker zu einer Datei zusammengefügt. Beim Linkvorgang<br />

müssen außerdem absolute Speicheradressen für die


KAPITEL 6. ASSEMBLER 63<br />

freien Symbole der Sprung- und Datenadressen berechnet und<br />

vergeben werden.<br />

Vertiefung: Wie lange rechnet obiges Programm, wenn der<br />

Prozessor pro Takt ein Befehl ausführt und <strong>mit</strong> 8 Mhz getaktet<br />

ist?


Kapitel 7<br />

Programmiersprache C<br />

Der große Trick bei der Entwicklung von Unix war die Programmiersprache<br />

C. C ist einfach auf Maschinensprachen abbildbar,<br />

besitzt aber dennoch eine eindeutige Syntax und eine<br />

nahezu eindeutige Semantik. Über 90 Prozent von Unix<br />

konnten in C formuliert werden. Dadurch war die Portierung<br />

des Betriebssystems auf neue Prozessoren vereinfacht worden.<br />

Ferner war <strong>mit</strong> jeder Portierung des Betriebssystems sofort<br />

eine höhere Programmiersprache verfügbar. C hat relativ<br />

schnell die damals etablierten Programmiersprachen wie Algol,<br />

Cobol und Fortran verdrängt.<br />

Der C-Compiler von GNU, gcc genannt, hat inzwischen Referenzstatus.<br />

Später kommt er auch hier zum Einsatz.<br />

Zum Lernen von C ist das Originalbuch [C] der Autoren der<br />

Sprache bestens geeignet. Nicht nur, dass es die ursprüngli-<br />

64


KAPITEL 7. PROGRAMMIERSPRACHE C 65<br />

che Sprachdefinition darstellt, es kann auch als vorbildliches<br />

Lehrbuch bezeichnet werden.<br />

Das erste Programmierprojekt des Buches ist ein triviales Programm,<br />

das den Text<br />

hello, world<br />

ausgibt. Diese didaktische Idee bekam viele Nachahmer wie<br />

man in der Wikipedia [wikipedia] nachlesen kann.<br />

Wichtiges Konzept der Sprache C ist die sogenannte strukturierte<br />

Programmierung. Strukturierte Programme lassen<br />

sich in Blöcke gliedern <strong>mit</strong> genau einem Eingang und genau<br />

einem Ausgang. Um dies zu erreichen, werden Programmsprünge,<br />

die das von-Neumann-Konzept in ungezügelter Art<br />

und Weise zulässt, auf den Vorwärtssprung <strong>mit</strong>tels if-thenelse-endif<br />

und den Rückwärtssprung <strong>mit</strong>tels loop-endloop<br />

eingeschränkt. Für das Beenden von Schleifen gibt es ein<br />

breakloop. Beliebiges Ineinanderschachteln der Form loop1loop2-endloop2-endloop1<br />

usw. ist erlaubt.<br />

Nicht erlaubt ist ein Verschachteln der Form loop1-loop2endloop1-endloop2.<br />

Die Bedingung, genau einen Eingang zu<br />

haben, wäre verletzt.<br />

Die Sprache C verwendet zur Blockbildung geschweifte Klammern:<br />

{ und }. Für den Vorwärtssprung gibt es if, else und<br />

switch, case. Der Rückwärtssprung kann durch while oder for<br />

oder durch do <strong>mit</strong> while ausgedrückt werden.


KAPITEL 7. PROGRAMMIERSPRACHE C 66<br />

if-then-else-endif wird in C folgendermaßen formuliert:<br />

if (Bedingung)<br />

{<br />

Anweisungen;<br />

}<br />

else<br />

{<br />

Anweisungen;<br />

}<br />

Der else-Teil kann auch fehlen.<br />

Für loop-endloop gibt es in C drei mögliche Formulierungen,<br />

die nachfolgend <strong>mit</strong> der loop-Metasprache 1 erklärt werden:<br />

while (Bedingung) loop<br />

{ if not Bedingung then breakloop endif<br />

Anweisungen; Anweisungen<br />

} endloop<br />

for (Ausdruck1;Bedingung;Ausdruck2) Ausdruck1<br />

{ loop<br />

Anweisungen; if not Bedingung then breakloop endif<br />

} Anweisungen<br />

Ausdruck2<br />

endloop<br />

do loop<br />

{ Anweisungen<br />

Anweisungen; if not Bedingung then breakloop endif<br />

} while (Bedingung) endloop<br />

Da sich in einigen Fällen, oft bei Fehlerbehandlung, nicht<br />

strukturierte Sprünge vorteilhaft auswirken, kennt C auch goto<br />

und Label als Sprungziele zur verantwortungsvollen Nutzung.<br />

Ferner formuliert man den selten vorkommenden allgemeinsten<br />

Fall eines loop <strong>mit</strong> <strong>mit</strong>tiger Abruchbedingung in der<br />

Sprache C <strong>mit</strong> Hilfe von goto:<br />

1 Ein Metasprache ist eine Sprache, die eine andere Sprache erklärt.


KAPITEL 7. PROGRAMMIERSPRACHE C 67<br />

loopA: loop<br />

Anweisungen1; Anweisungen1<br />

if (Bedingung) goto endloopA; if Bedingung then breakloop endif<br />

Anweisungen2; Anweisungen2<br />

goto loopA; endloop<br />

endloopA:<br />

Die Korrektheit eines strukturierten Programmes kann bewiesen<br />

werden. Einen solchen Beweis nennt man Programmverifikation.<br />

Da derartige Beweise sehr aufwändig sind, werden sie<br />

nur selten durchgeführt.<br />

Auf Grund des geordneten Programmflusses gibt es viele Vorteile.<br />

Strukturierte Programme sind<br />

• leserlicher<br />

• verständlicher<br />

• robuster<br />

• leichter änderbar<br />

• eher wiederverwendbar<br />

All diese Vorzüge sind Gründe dafür, dass eigentlich alle modernen<br />

Programmiersprachen dieses Konzept unterstützen.<br />

Fortran, Cobol und Basic sind in ihrer ursprünglichen Form<br />

aussterbende Sprachen, weil sie das Konzept noch nicht kannten.


Teil II<br />

Hardwaretechnik<br />

68


Kapitel 8<br />

Hardware-Labor<br />

Mit diesem Buch soll ein komplettes Entwicklungssystem für<br />

Mikrocontroller der Firma Atmel aufgebaut werden. Aus diesem<br />

Grund wird kurz auf einige unverzichtbare Utensilien eines<br />

Hardware-Labors eingegangen.<br />

8.1 Lötkolben<br />

Für elektronische Bauteile braucht man einen Lötkolben<br />

<strong>mit</strong> ca. 16 Watt. Besser ist ein Gerät <strong>mit</strong> mehr Leistung<br />

und einer Temperaturregelung. Als Lötdraht verwendet man<br />

Elektronik-Lot <strong>mit</strong> 1 mm Durchmesser.<br />

Um einwandfreie Lötverbindungen herzustellen muss man ein<br />

69


KAPITEL 8. HARDWARE-LABOR 70<br />

Abbildung 8.1: Gute und schlechte Lötverbindungen.<br />

wenig üben und wissen, dass es drei Feinde einer guten Lötverbindung<br />

gibt:<br />

Zu geringe Temperatur. Der Lötkolben muss ausreichend<br />

Zeit zum Anheizen bekommen. Erst wenn der Lötdraht<br />

sofort schmilzt, ist die Anheizzeit vorbei. Lötkolben und Lot<br />

werden gleichzeitig zur Lötstelle geführt. Die Lötspitze wird<br />

noch ca. 1 Sekunde im flüssigen Lot gelassen, bis das Lot sich<br />

<strong>mit</strong> allen Teilen verbindet. Dies erkennt man an der Form der<br />

Oberfläche. Siehe Abbildung 8.1.<br />

Oxydation. An zwei Stellen macht Oxydation zu schaffen:<br />

Vor allem blanke Kupferoberflächen an Bauteilen oxydieren.<br />

Geringe Oxydation wird vom Fluss<strong>mit</strong>tel im Lot unterwandert.<br />

In schweren Fällen, zum Beispiel, wenn Handschweiß<br />

mehrere Tage auf Kupfer einwirken konnte, muss <strong>mit</strong> hartem<br />

Radiergummi oder <strong>mit</strong> feinem Schmirgelpapier Abhilfe<br />

geschaffen werden.


KAPITEL 8. HARDWARE-LABOR 71<br />

Wird der Lötkolben mehrere Minuten nicht benutzt, so verdampft<br />

die schützende Fluss<strong>mit</strong>telhülle um das heiße Lot herum.<br />

Danach entsteht eine Oxydationsschicht, die weiteres Arbeiten<br />

behindert. In diesem Fall muss die Lötspitze zum Beispiel<br />

<strong>mit</strong> einem Papiertaschentuch gereinigt und sofort <strong>mit</strong> ein<br />

wenig frischem Lot wieder geschützt werden.<br />

Bewegung beim Erstarren. Wird der Lötkolben von der<br />

Lötstelle entfernt, beginnt die mehrere Sekunden dauernde<br />

Erkaltungsphase. Wurde vor dem Löten nicht dafür gesorgt,<br />

dass die Teile unbeweglich sind, führt das zu einer sogenannten<br />

kalten Lötstelle. Die Oberfläche des Lotes ist nicht mehr<br />

glatt. Solche Stellen müssen unbedingt nachgelötet werden,<br />

da sie u. a. zu Wackelkontakten führen können!<br />

8.2 Multimeter<br />

Um zum Beispiel Spannungen nachzuweisen, ist es gut, ein<br />

Multimeter zu besitzen. Es ist quasi das wichtigste Messgerät,<br />

wenn man <strong>mit</strong> Elektrizität zu tun hat. Diese Geräte<br />

sind für Messungen von Spannung [Volt], Strom [Ampere] und<br />

Widerstand [Ohm] ausgelegt. Es gibt analoge Zeigerinstrumente<br />

und digitale Messgeräte. Auch wenn die technischen<br />

Daten bei gleichem Preis für digitale Messgeräte sprechen,<br />

würde ich als erstes Gerät ein Zeigerinstrument empfehlen.<br />

Der Grund dafür liegt darin, dass der zeitliche Verlauf des<br />

Zeigerausschlags weit mehr über das laufende physikalische


KAPITEL 8. HARDWARE-LABOR 72<br />

Experiment aussagt, als auch ein teures digitales Messgerät<br />

ver<strong>mit</strong>teln kann.<br />

Für den Umgang ist wieder etwas Theorie notwendig.<br />

In der Physik verwendet man oft vier Bezeichnungen: Den<br />

Namen des physikalischen Phänomens und dessen Abkürzung<br />

und die Dimension zur quantitiven (größenmäßigen) Bestimmung<br />

und dessen Abkürzung.<br />

Drei wichtige Größen der Elektrotechnik<br />

Phänomen Abkürzung Dimension Abkürzung<br />

Spannung U Volt V<br />

Strom I Ampere A<br />

Widerstand R Ohm Ω<br />

Die drei physikalischen Größen gehorchen unter bestimmten<br />

Bedingungen dem Ohmschen Gesetz:<br />

R · I = U<br />

⇔ U<br />

= R<br />

I<br />

⇔ U<br />

= I<br />

R<br />

Ströme kommen oft in sehr kleinen Größen vor und werden<br />

dann in Milliampere <strong>mit</strong> 1 mA = 0,001 A angegeben. Aus dem<br />

Ohmschen Gesetz kann man folgern, dass Widerstände <strong>mit</strong><br />

großen Werten vorkommen. Sie werden <strong>mit</strong> Kiloohm bezeichnet,<br />

wobei 1 KΩ = 1000 Ω ist.


KAPITEL 8. HARDWARE-LABOR 73<br />

Bei der Anwendung des Multimeters muss man sich als erstes<br />

darüber klar werden, welche Größe man messen will, da<br />

das Gerät entsprechend eingestellt und angeschlossen werden<br />

muss:<br />

Spannung: Dies ist die häufigste Messung <strong>mit</strong> dem Multimeter.<br />

Nach Einstellung des Messbereichs, in unseren Fällen<br />

auf Gleichspannung, wird der Minus-Eingang des Gerätes<br />

<strong>mit</strong> der Masse der Schaltung verbunden und <strong>mit</strong> dem Plus-<br />

Eingang zum Beispiel ein Ausgang des Mikrocontrollers<br />

berührt. Der größte Fehler, der bei dieser Messung passieren<br />

kann, wäre, das Messgerät auf Stommessung einzustellen,<br />

ein Kurzschluss wäre die Folge. Andere Fehler äußern sich in<br />

unsinnigen Messwerten.<br />

Abbildung 8.2: Schaltung einer Spannungsmessung.


KAPITEL 8. HARDWARE-LABOR 74<br />

Strom: Strommessungen sind seltener. Sie gehören zu den<br />

komplizierteren Messungen <strong>mit</strong> dem Multimeter. Nach Einstellen<br />

des Gleichstrombereiches verhält sich das Messgerät<br />

zwischen den beiden Messspitzen annähernd wie ein Stück<br />

Draht (niedriger Innenwiderstand). Verwendet man jetzt die<br />

Messspitzen wie ein Voltmeter, so kommt es zu einem Kurzschluss.<br />

Multimeter haben für diesen Fall eine Sicherung, welche<br />

dann eventuell gewechselt werden muss.<br />

Bei der Strommessung muss in der Schaltung eine Leitung,<br />

zum Beispiel die Stromversorgungsleitung, unterbrochen werden.<br />

Die Unterbrechung wird dann <strong>mit</strong> den Messspitzen überbrückt.<br />

Siehe Abbildung 8.3.<br />

Abbildung 8.3: Schaltung einer Strommessung.<br />

Die bei <strong>Mikrocontrollern</strong> vorkommenden Ströme sind meist<br />

so klein, dass sie im Bereich der unteren Messbereichsgrenzen<br />

liegen. Wer nun die gute Idee hat, das Ohmsche Gesetz einzusetzen,<br />

kommt leider auch nicht zum Ziel, da die Messung des<br />

Widerstandes <strong>mit</strong> dem Multimeter nur <strong>mit</strong> sogenannten Ohmschen<br />

Leitern (Schaltungen ohne Halbleiter, Spulen, Konden-


KAPITEL 8. HARDWARE-LABOR 75<br />

satoren) funktioniert.<br />

Widerstand: Widerstände werden außerhalb der Schaltung<br />

gemessen. Selbst Drehspulinstrumente <strong>mit</strong> Zeiger, die<br />

bei Strom- und Spannungsmessungen ihre Energie aus der<br />

zu messenden Schaltung beziehen (und da<strong>mit</strong> den Messwert<br />

etwas verfälschen), setzen für diese Messungen eine Batterie<br />

ein. Die Batterie wird geprüft, indem die Messspitzen kurzgeschlossen<br />

werden. Das Multimeter muss dann Null Ohm<br />

anzeigen.<br />

Abbildung 8.4: Schaltung einer Widerstandsmessung.<br />

Das Messgerät wird auf den größten Widerstandsbereich<br />

eingestellt und dann stufenweise heruntergeschaltet, bis der<br />

Messbereich optimal genutzt wird.<br />

Manche Geräte haben zur Durchgangsprüfung von Leitungen<br />

(sehr geringer Widerstand) einen Summer, der davon<br />

entlastet, bei solchen Prüfungen die Anzeige beobachten zu<br />

müssen. Zur Fehlersuche in neu aufgebauten Schaltungen ist<br />

das recht nützlich.


KAPITEL 8. HARDWARE-LABOR 76<br />

8.3 Netzgerät<br />

Netzgeräte gibt es in den verschiedensten Ausführungen. Sie<br />

können fehleranfällige Batterien ersetzen. Gute Netzgeräte besitzen<br />

eine einstellbare maximale Spannung und einen einstellbaren<br />

maximalen Strom. Mit Strom- und Spannungsanzeige<br />

können auf einen Blick die wichstigsten Parameter einer<br />

Schaltung kontrolliert werden.<br />

Für die Schaltungen in diesem Buch ist ein Netzgerät nicht unbedingt<br />

erforderlich. Für diejenigen, die weiter arbeiten wollen,<br />

steht es weit oben auf der Wunschliste.


Kapitel 9<br />

Kleine Bauteilekunde<br />

Die folgende Bauteilekunde geht nur auf solche Teile ein, die<br />

für unser Projekt gebraucht werden. Selbstverständlich gibt<br />

es weit mehr Bauteilesorten und Untersorten als hier erwähnt<br />

sind.<br />

Von jedem Bauteil werden Bezeichnung, Aussehen, wesentliche<br />

Eigenschaften und ein Funktionstest beschrieben.<br />

9.1 Platinenmaterial<br />

Wir verwenden fotobeschichtetes 1,5 mm starkes Epoxyd-<br />

Glashartgewebe <strong>mit</strong> einseitiger Kupferauflage von 35 µm<br />

Dicke. Diese Bezeichnung impliziert, dass es auch nicht fotobeschichtetes<br />

Material gibt, andere Dicken, zweiseitige Kupfer-<br />

77


KAPITEL 9. KLEINE BAUTEILEKUNDE 78<br />

auflage und andere Basismaterialien. Epoxyd-Glashartgewebe<br />

hat neben hoher Stabilität den Vorteil, dass die Kupferauflage<br />

gut an der Platine haftet. Das ist eine wichtige Eigenschaft, da<br />

es bei den Experimenten vorkommen kann, dass ein Bauteil<br />

wieder entlötet werden muss. Bei preiswerterem Hartpapier<br />

ist es normal, dass die Leiterbahn sich bei wiederholtem Erhitzen<br />

vom Basismaterial löst.<br />

9.2 Stecker<br />

Abbildung 9.1: Stecker<br />

Stecker werden hauptsächlich für die Stromversorgung und<br />

für Signalwege eingesetzt. Für die Stromversorgung setzen wir<br />

Hohlstecker ein, wie sie bei Steckernetzteilen Verwendung fin-


KAPITEL 9. KLEINE BAUTEILEKUNDE 79<br />

den. Diese gibt es <strong>mit</strong> verschiedenen Durchmessern. Wir verwenden<br />

häufig vorkommende 2,1 mm. Für den Übergang auf<br />

andere Durchmesser gibt es Adapter.<br />

Für die Signale verwenden wir Pfostenstecker und D-<br />

Sub-Steckverbinder. Auf der PC-Seite kommen die D-Sub-<br />

Steckverbinder DB-9 und DB-25 zum Einsatz. Deren Pole sind<br />

in der Regel auf der Lötseite eindeutig durchnummeriert.<br />

Für unsere Platine nehmen wir Pfostenstecker und Buchsen,<br />

die sich leicht und präzise <strong>mit</strong> Flachbandkabel verbinden<br />

lassen. Leider wird bei diesen meist nur der Pin 1 durch<br />

einen Pfeil gekennzeichnet. Obendrein gibt es Versionen ohne<br />

Führung und Kodiernase. Auch die Reihenfolge der Nummerierung<br />

ist anders als bei den D-Sub-Steckern!<br />

9.3 Kabel<br />

Bei Kabeln unterscheidet man Querschnitt, Isolation und Kabelaufbau.<br />

Für ein Ampere Strombelastung benötigt man<br />

0,1 mm 2 Querschnitt. Zu geringer Querschnitt führt zur Erhitzung.<br />

Isolation und Kabelaufbau wird durch die Art der<br />

Verwendung festgelegt. Nur bei fester Verlegung verwendet<br />

man massive Kabel. Sonst kommen Litzen zum Einsatz, da<br />

diese nicht so leicht brechen. Für Messkabel verwendet man<br />

teure, hoch flexible Litzen.<br />

Rote Kabel signalisieren positive Gleichspannung; das zugehörige<br />

schwarze Kabel signalisiert Masse.


KAPITEL 9. KLEINE BAUTEILEKUNDE 80<br />

Fehler in Steckverbindungen und Kabel sucht man <strong>mit</strong> dem<br />

Ohmmeter.<br />

9.4 Widerstände<br />

In Bauteilelisten werden Widerstände durch ein R und eine<br />

Nummer bezeichnet. Zum Beispiel R1. Amerikanische<br />

Schaltpläne stellen Widerstände auf andere Weise dar als europäische:<br />

Abbildung 9.2: Amerikanisches und europäisches Widerstandssymbol<br />

Der Widerstandswert wird durch einen Code von farbigen<br />

Ringen gekennzeichnet. Der letzte Ring kennzeichnet die Toleranz,<br />

zum Beispiel:<br />

silber 10%<br />

gold 5%<br />

Der vorletzte Ring gibt die Anzahl der Nullen an. Die Ringe<br />

davor bezeichnen die Ziffern nach folgendem Code:


KAPITEL 9. KLEINE BAUTEILEKUNDE 81<br />

Abbildung 9.3: Widerstände


KAPITEL 9. KLEINE BAUTEILEKUNDE 82<br />

schwarz 0<br />

braun 1<br />

rot 2<br />

orange 3<br />

gelb 4<br />

grün 5<br />

blau 6<br />

violett 7<br />

grau 8<br />

weiß 9<br />

In der für 10% Toleranz vorgesehenen Reihe E12 gibt es die<br />

Ziffernfolgen 10, 12, 15, 18, 22, 17, 33, 39, 47, 56, 68, 82. Ein<br />

Widerstand <strong>mit</strong> 4700 Ohm 1 und einer Toleranz von 5% trägt<br />

die Ringe rot, violett, rot und gold. Er wird auch <strong>mit</strong> 4700 Ω<br />

oder 4,7 kΩ oder 4k7 bezeichnet. Ausgesprochen wird das als<br />

,,4,7 Kiloohm”.<br />

Die maximale Verlustleistung von Widerständen variiert <strong>mit</strong><br />

der Größe. In unseren Schaltungen fließen nur kleine Ströme,<br />

so dass kleine Widerstände <strong>mit</strong> 0,25 Watt ausreichen. Bei<br />

Platzmangel kann man SMD-Widerstände einsetzen, die,<br />

wenn überhaupt, den Wert als Ziffern aufgedruckt haben. Die<br />

letzte Ziffer bezeichnet wieder die Anzahl der Nullen.<br />

Die Funktion eines Widerstandes prüft man <strong>mit</strong> dem Ohmmeter.<br />

Die umgebende Schaltung bestimmt, ob er für die<br />

1854<br />

1 benannt nach dem deutschen Physiker Georg Simon Ohm, 1787–


KAPITEL 9. KLEINE BAUTEILEKUNDE 83<br />

Messung separiert werden muss, was der Fall ist, wenn nicht<br />

annähernd der erwartete Wert gemessen wird.<br />

9.5 Kondensatoren<br />

Abbildung 9.4: Kondensator und Elektrolytkondensator<br />

Kondensatoren sperren Gleichstrom und sind durchlässig für<br />

Wechselstrom. Auch Stromimpulse sind eine Form von Wechselstrom.<br />

So wie es Wechselströme verschiedener Stärke, Wellenform<br />

und Frequenz gibt, so gibt es Kondensatoren <strong>mit</strong> verschiedener<br />

Kapazität. Die Einheit der Kapazität ist das Farad<br />

2 <strong>mit</strong> der Abkürzung F.<br />

Zwei Grundtypen von Kondensatoren müssen unterschieden<br />

werden. Elektrolyt-Kondensatoren besitzen eine hohe Kapazität,<br />

der sich im Bereich von µF bewegt. Dafür sind sie empfindlich<br />

gegen zu hohe Spannung. Kondensatoren im Bechergehäuse<br />

sind relativ groß, Tantalkondensatoren sind kleiner.<br />

2 benannt nach dem englischen Chemiker und Physiker Michael Fara-<br />

day 1791–1867


KAPITEL 9. KLEINE BAUTEILEKUNDE 84<br />

Beim Einbau von Elektrolyt-Kondensatoren muss man auf die<br />

Polung achten. Das Gehäuse ist entsprechend beschriftet. Bei<br />

manche Kondensatoren hat der positive Pol ein längeres Bein.<br />

Kondensatoren <strong>mit</strong> kleiner Kapazität sind meist keine Elektrolytkondensatoren<br />

und dürfen beliebig eingebaut werden.<br />

Auch sie haben eine begrenzte Spannungsfestigkeit, <strong>mit</strong> der<br />

auch die Baugröße schwankt. Die Kapazität hat ebenfalls Einfluß<br />

auf die Größe.<br />

Ein wichtiger Einsatz in digitalen Schaltungen ist das Filtern<br />

von Störimpulsen, die quasi kurz geschlossen werden.<br />

Abbildung 9.5: Kondensatoren<br />

Während große Kondensatoren meist im Klartext beschriftet<br />

werden, sind kleine Kondensatoren verschieden oder gar nicht<br />

beschriftet.<br />

Bessere Multimeter haben Messbereiche für Kapazitäten.<br />

Mit etwas Erfahrung kann man <strong>mit</strong> einem Zeigerinstrument<br />

Elektrolyt-Kondensatoren testen, indem man sie auflädt und


KAPITEL 9. KLEINE BAUTEILEKUNDE 85<br />

über das Messgerät wieder entlädt. Zuletzt bleibt nur die<br />

Möglichkeit, <strong>mit</strong> dem Ohmmeter zu prüfen, ob der Kondensator<br />

wirklich Gleichstrom sperrt, was sich als hoher Widerstandswert<br />

ausdrückt. Dieser Test sagt aber nichts über die<br />

ganze Funktion aus. Zum Trost sei vermerkt, dass defekte<br />

Kondensatoren häufig auch so aussehen.<br />

9.6 Quarze<br />

Abbildung 9.6: Schaltsymbol für einen Quarz<br />

Quarze sind piezokeramische Teile, die sich beim Anlegen<br />

einer Spannung verformen. Trifft man <strong>mit</strong> einer Wechselspannung<br />

die Resonanzfrequenz des Kristalls, so versucht der<br />

Quarz, diese Frequenz zu halten.<br />

Die Frequenz ist der wichtigste Wert des Quarzes und meist<br />

auf dem Gehäuse aufgedruckt oder eingeprägt. Die Einheit<br />

ist Kilo-, Mega- oder Gigahertz 3 . Die Funktion von Quarzen<br />

ist noch schwieriger zu messen als die von Kondensatoren. Im<br />

3 benannt nach dem deutschen Physiker Heinrich Hertz, 1857-1894


KAPITEL 9. KLEINE BAUTEILEKUNDE 86<br />

Abbildung 9.7: Quarze


KAPITEL 9. KLEINE BAUTEILEKUNDE 87<br />

Zweifel tauscht man meist das verdächtige Exemplar gegen<br />

ein Neuteil. Meist liegt der Fehler jedoch woanders.<br />

Das untere Bauteil in der Abbildung 9.7 ist kein reiner Quarz,<br />

sondern eine integrierte Schaltung <strong>mit</strong> Quarz. Für dieses als<br />

Quarzoszillator bezeichnete Bauteile gelten auch die folgenden<br />

Worte über integrierte Schaltungen.<br />

9.7 Dioden<br />

Abbildung 9.8: Schaltsymbole verschiedener Dioden<br />

Dioden leiten Strom nur in einer Richtung. Strom fließt nur,<br />

wenn die Anode ca. 0,7 V positiver als die Kathode ist. Die<br />

Kathode der Dioden wird auf dem Gehäuse durch einen Strich<br />

gekennzeichnet, denn auch diese Bauteile müssen richtig eingesetzt<br />

werden. Ein wichtiger Wert von Dioden ist der maximale<br />

Durchlassstrom, der auch die Größe des Gehäuses beeinflußt.<br />

Es gibt viele Untersorten, wobei Leuchtdioden und Schottky-<br />

Dioden nicht unerwähnt bleiben sollen: Erstere werden weni-


KAPITEL 9. KLEINE BAUTEILEKUNDE 88<br />

Abbildung 9.9: Dioden


KAPITEL 9. KLEINE BAUTEILEKUNDE 89<br />

ger als Dioden sondern, als Ersatz für Glühlampen eingesetzt.<br />

Ohne Strom begrenzenden Widerstand gehen sie kaputt.<br />

Schottky-Dioden haben gegenüber normalen Dioden die Eigenschaft,<br />

schon bei 0.5 V für Strom durchlässig zu sein.<br />

Die Funktion von Dioden kann man <strong>mit</strong> dem Ohmmeter<br />

prüfen, falls die Spannung zwischen den Prüfspitzen ausreicht.<br />

Digitale Multimeter haben oft einen eigenen Messbereich für<br />

Diodenmessung und zeigen dabei die Durchlassspannung an.<br />

9.8 Transistoren<br />

Abbildung 9.10: Transistoren<br />

Die frühen elektrischen Computer wurden <strong>mit</strong> Relais aufgebaut.<br />

Nach einem kurzen Zwischenspiel der elektronischen


KAPITEL 9. KLEINE BAUTEILEKUNDE 90<br />

Abbildung 9.11: Transistoren<br />

Röhren haben sich Transistoren in digitalen Schaltungen<br />

durchgesetzt. Ein kleiner Strom, der durch die Basis zum<br />

E<strong>mit</strong>ter fließt, öffnet den Transistor zwischen Kollektor und<br />

E<strong>mit</strong>ter für einen großen Strom. Das Verhältnis der beiden<br />

Ströme ist der Verstärkungsfaktor des Transistors. In digitalen<br />

Schaltungen werden nur zwei Arbeitspunkte genutzt.<br />

Der Transistor bleibt geschlossen oder wird ganz geöffnet, wie<br />

beim Relais. Auch Transistoren müssen richtig herum eingebaut<br />

werden. Leider gibt es keine Regeln für die Anordnung<br />

der Beine. Die Bestückungsliste oder das Datenblatt des Transistors<br />

sind zu Rate zu ziehen.<br />

Auch preiswerte digitale Multimeter können den<br />

Verstärkungsfaktor von Transistoren messen (hFE-Bereich).<br />

Die Messöffnung für den Kollektor wird wegen der englischen<br />

Schreibweise <strong>mit</strong> C gekennzeichnet. Ansonsten prüft man<br />

von Basis zu E<strong>mit</strong>ter und von Basis zu Kollektor wie Dioden.


KAPITEL 9. KLEINE BAUTEILEKUNDE 91<br />

Die npn-Typen haben eine gemeinsame Anode, pnp-Typen<br />

ein gemeinsame Kathode.<br />

Komplette Schaltungen aus mehreren Transistoren auf einem<br />

Halbleiterkristall heißen ...<br />

9.9 Integrierte Schaltungen<br />

Abbildung 9.12: Integrierte Schaltungen<br />

Hersteller, Typ und Woche der Herstellung sind die typische<br />

Aufschrift integrierter Schaltungen. Aus den Ziffern der Wo-


KAPITEL 9. KLEINE BAUTEILEKUNDE 92<br />

che und den letzten beiden Ziffern des Jahres wird der vierstellige<br />

Code für das Herstellungsdatum gebildet.<br />

Integrierte Schaltungen sind empfindlich gegenüber falschen<br />

Spannungen. Das gilt sogar für bei trockener Luft vorkommende<br />

statische Aufladungen. Meist werden sie deshalb in einer<br />

speziellen Verpackung geliefert.<br />

Es ist wichtig Pin 1 zu erkennen und richtig in die Schaltung<br />

einzusetzen. Die Funktion prüft man, indem man die individuelle<br />

Beschreibung nachvollzieht, meist durch Messen von<br />

Spannungen. Oft wird das IC 4 für einen Funktionstest ausgetauscht.<br />

Da das Auslöten von ICs schwierig ist, werden sie<br />

gerne in Sockel gesetzt. Sockel sind leider häufiger Fehlerquelle<br />

als die ICs selber. Eine ältere gesockelte integrierte Schaltung<br />

wird deshalb erstmal entfernt und wieder eingesetzt, was eventuelle<br />

Oxydationen beseitigen soll. Wurde auf diese Weise ein<br />

Fehler gefunden, ist es sinnvoll, das IC im Sockel festzulöten.<br />

4 Abkürung der englischen Bezeichnung integrated cicuit


Kapitel 10<br />

Platinenlayouts<br />

Auch Hardware wird Heute <strong>mit</strong> Software entworfen.<br />

10.1 Programmieren <strong>mit</strong> Klassen<br />

Nachdem sich die Programmiersprache C gut verbreitet hat,<br />

wurde über Verbesserungen der Sprache nachgedacht. Durchgesetzt<br />

hat sich die Erweiterung von Bjarne Stroustrup, die er<br />

C++ nannte [C++]. C++ ist ein Konstrukt aus der Sprache<br />

C selbst und bedeutet soviel wie ein Schritt weiter als C.<br />

Eine wesentliche Erweiterung gegenüber C ist die Einführung<br />

von Klassen. Eine Klasse beschreibt eine Familie von Daten<br />

und Methoden, die logisch zusammengehören. Methoden wurden<br />

in C als Unterprogramme programmiert. Der Zugang zu<br />

93


KAPITEL 10. PLATINENLAYOUTS 94<br />

einer Klasse führt über den Klassennamen und einen Punkt.<br />

Die Eigenschaften einer Klasse können von einer neuen Klasse<br />

geerbt werden. Als Beispiel denke man sich eine Klasse<br />

Viereck <strong>mit</strong> Methoden Viereck.umfang, Viereck.flaeche. Leitet<br />

man von der Klasse Viereck die Klasse Quadrat ab, so erbt<br />

sie die Methoden Quadrat.umfang und Quadrat.flaeche.<br />

Beim Umgang <strong>mit</strong> den <strong>Mikrocontrollern</strong> kommen wir nicht<br />

so weit, da der Einsatz von C++ eher bei größeren Programmen<br />

sinnvoll ist. Trotzdem wird das Klassenkonzept auch in<br />

diesem Kurs genutzt. Bevor der Mikrocontroller richtig zum<br />

Einsatz kommt, werden Platinen angefertigt. Hierfür wird ein<br />

Shellscript <strong>mit</strong> Namen pcb bereit gestellt. Die Quelle des Programms<br />

findet sich im Anhang D.<br />

Das Programm ist unter Anwendung eines Klassenkonzepts<br />

programmiert worden. Dieses Klassenkonzept wurde entwickelt,<br />

weil Shellscripte einige Gemeinsamkeiten haben:<br />

• Häufig entstehen Familien von Programmen, die sich<br />

<strong>mit</strong> einem Thema beschäftigen.<br />

• Wird ein Shellscript nicht so oft benutzt, gerät es wegen<br />

der Vielfalt der Namen in Vergessenheit.<br />

• Shellscripten fehlt meist eine ausreichende Dokumentation.<br />

Dies hat mehrere Gründe:<br />

– Man meint, das Programm sei so einfach, dass es<br />

keine braucht.


KAPITEL 10. PLATINENLAYOUTS 95<br />

– Im Notfall könne man ja das Script lesen, was<br />

später leider erforderlich wird.<br />

– Die Dokumentation geht verloren.<br />

• Sind nicht alle aufgerufenen Programme installiert, brechen<br />

Shellscripte <strong>mit</strong>unter ohne ausreichende Fehlermeldung<br />

den Programmlauf ab.<br />

• Shellscripten fehlt manchmal eine gewisse innere Ordnung.<br />

Es wurde eine Mutterklasse <strong>mit</strong> Namen class geschaffen, die<br />

folgende Grundeigenschaften bietet:<br />

• Alle Methoden sind über den Klassennamen und einen<br />

Punkt zwischen Klassen- und Methodennamen erreichbar.<br />

Das wurde von C++ abgeschaut.<br />

• Schon die Mutterklasse kennt ein mehrstufiges Hilfekonzept:<br />

– Aufruf der Klasse ohne den Methodennamen: Die<br />

Klasse gibt eine Kurzinformation über Name,<br />

Funktion, Version, Autor und erste Hilfe.<br />

– Aufruf der Klasse <strong>mit</strong> falschen Argumenten: Es<br />

wird eine Kurzhilfe ausgegeben.<br />

– Aufruf der Klasse <strong>mit</strong> dem Methodennamen help:<br />

Alle Methoden werden <strong>mit</strong> einer Kurzhilfe vorgestellt.


KAPITEL 10. PLATINENLAYOUTS 96<br />

– Aufruf der Klasse <strong>mit</strong> dem Methodennamen man:<br />

Es wird eine ausführlichere Hilfe über die im Argument<br />

benannte Methode gegeben.<br />

– Aufruf der Klasse <strong>mit</strong> dem Methodennamen info:<br />

Die Klasse wird <strong>mit</strong> ihren Konzepten ausführlich<br />

vorgestellt.<br />

Die Dokumentation ist Bestandteil des Programms,<br />

kann also nicht einzeln verloren gehen.<br />

• Methodenname new: Die Klasse vererbt ihre Methoden<br />

an eine neue Klasse. Das Argument bezeichnet den neuen<br />

Klassennamen.<br />

• Methodenname deinstall: Die Klasse kann sich deinstallieren.<br />

Installalliert hat sie sich beim Aufruf ohne Methodenname.<br />

Ferner vererbt die Mutterklasse die Fähigkeit der Reinkarnation.<br />

Wird eine Tochterklasse <strong>mit</strong> der Methode new und dem<br />

Argument class aufgerufen, zum Beispiel<br />

pcb.new class<br />

so entsteht wieder die reine Mutterklasse. Jeder, der das Konzept<br />

verwenden möchte, weil ihn eine Klasse überzeugt hat,<br />

kann dies also tun. Der Zugang zur Programmquelle ist Bestandteil<br />

des Programms. Die GPL läßt grüßen.<br />

Weitere Informationen bekommt man durch die Befehlsfolge:


KAPITEL 10. PLATINENLAYOUTS 97<br />

pcb.new class<br />

./class<br />

./class.info | less<br />

Es sei erwähnt, dass der Autor weitere Klassen auf seiner Homepage<br />

[unger] zum Download bereithält:<br />

bks Buchhaltungssystem<br />

data Kleine Datenbank<br />

learn Eine Lernhilfe<br />

ahnen Ahnentafeln verwalten und präsentieren.<br />

stamm Stammbäume verwalten und präsentieren.<br />

photo Fotoarchiv<br />

xdesk Desktop für X11 <strong>mit</strong> twm<br />

make.latex ist ein <strong>mit</strong> ähnlichen Konzepten ausgestattetes<br />

Makefile für Anwender von L ATEX.<br />

10.2 Klasse für elektronische Schaltungen<br />

Das Programm pcb wurde von class abgeleitet. Die Grundidee<br />

des Programms ist, eine elektronische Schaltung in Tabellenform<br />

zu speichern. Die Schaltung kann auf einer Lochrasterplatine<br />

aufgebaut oder auf einer photoempfindlichen Leiterplatte<br />

belichtet, entwickelt und geätzt werden.


KAPITEL 10. PLATINENLAYOUTS 98<br />

Für eine kleine Platine, auf der ein Quarz montiert wird, sieht<br />

die Tabelle folgendermaßen aus:<br />

#<br />

# Name: hardware/quarz.pcb<br />

# Function: Oszillator-Modul für Mikrocontollerboard<br />

# History: 2004Jan19 Hanns-Konrad Unger<br />

#<br />

(d7)board\<br />

(b6)(c6)wire (c6)(c2)wire (c3)(d3)wire (b1)(d1)wire (b4)(b2)wire (b2)(a2)wire\<br />

(a2)(a1)wire :1:PCB:Platine 7*4 :Bestellnummer:herstellen<br />

(b6)pad(b4)pad:1:Q1 :Quarz 7.372800Mhz :Bestellnummer:einlöten<br />

(b2)pad(b1)pad:2:C1 :Kondensatoren 22pF evtl. SMD:Bestellnummer:einlöten<br />

(c2)pad(c1)pad:0:C2 :Kondensator 22pF evtl. SMD :Bestellnummer:einlöten<br />

(a1)pad(a7)pad(d1)pad\<br />

(d3)pad(d7)pad:1:So :DIL-14 Präzisions-Sockel :Bestellnummer:<strong>mit</strong> Platine verbinden<br />

Die Datensätze beginnen am Anfang einer Zeile. Felder werden<br />

durch Doppelpunkt getrennt. Wenn ein Datensatz über<br />

mehrere Zeilen verteilt ist, so wird die unvollständige Zeile<br />

<strong>mit</strong> dem ,,\” beendet.<br />

Die Felder haben folgende Bedeutung:<br />

1. Feld: Befehle zum Zeichnen des Platinenlayouts<br />

2. Feld: Anzahl der Bauteile für Einkaufsliste<br />

3. Feld: Kurzbezeichnung des Bauteils für Bestückungsliste<br />

4. Feld: Beschreibung des Bauteils<br />

5. Feld: Bestellnummer des Bauteils<br />

6. Feld: Text für Bauanleitung


KAPITEL 10. PLATINENLAYOUTS 99<br />

Die Befehle zum Zeichnen des Platinenlayouts entsprechen<br />

der Syntax der Sprache Postscript. Erst werden Koordinaten<br />

des Platinenlayouts genannt. (a1) entspricht auf der Lötseite<br />

links oben. Die rechten Nachbarn von (a1) sind (b1) ... (z1),<br />

dann (A1) ... (Z1). Der rechte untere Punkt einer Euro-Platine<br />

der Größe 100 mm × 160 mm ist (M63). Hinter (lat.: post)<br />

den Koordinaten wird eines der folgenden Unterprogramme<br />

aufgerufen:<br />

board legt die Größe der Platine fest.<br />

wire zeichnet eine Verbindung zwischen zwei Pads.<br />

pad zeichnet ein Pad.<br />

smd zeichnet ein Pad für SMD-Bauteile.<br />

xpad zeichnet eine horizontale Reihe von Pads.<br />

ypad zeichnet eine vertikale Reihe von Pads.<br />

Die Klasse pcb verfügt über folgende Methoden zur Umwandlung<br />

der Tabellen:<br />

pcb.layout erzeugt ein Postscriptfile für die Belichtungsmaske.<br />

pcb.layout quarz.pcb | lpr<br />

pcb.list erzeugt eine Einkaufsliste als Textfile.<br />

pcb.list quarz.pcb|sed ”/ˆ0:/d”


KAPITEL 10. PLATINENLAYOUTS 100<br />

1:Platine 7*4 :Bestellnummer<br />

1:Quarz 7.372800Mhz :Bestellnummer<br />

2:Kondensatoren 22pF evtl. SMD:Bestellnummer<br />

1:DIL-14 Präzisions-Sockel :Bestellnummer<br />

pcb.kit erzeugt eine Beschreibung 1 als Textfile.<br />

pcb.kit quarz.pcb<br />

( ) PCB:Platine 7*4 :herstellen (a2) (a1)<br />

( ) Q1 :Quarz 7.372800Mhz :einlöten (b6) (b4)<br />

( ) C1 :Kondensatoren 22pF evtl. SMD:einlöten (b2) (b1)<br />

( ) C2 :Kondensator 22pF evtl. SMD :einlöten (c2) (c1)<br />

( ) So :DIL-14 Präzisions-Sockel :<strong>mit</strong> Platine verbinden (d3) (d7)<br />

Die Methoden pcb.list und pcb.kit sind einfach zu verstehen<br />

und eignen sich gut für das Studium von Shellscripten.<br />

Wenn im Rahmen von Unterricht für größere Gruppen Platinen<br />

hergestellt werden sollen, gibt es eine Methode, die mehrere<br />

Layouts nebeneinander ausdruckt:<br />

pcb.mlayout quarz.pcb 5 3<br />

Dieser Aufruf zeichnet eine Ätzmaske für 15 (5 × 3)Platinen.<br />

Falls der Leser keine Platinen ätzen möchte, sind die Layouts<br />

so ausgelegt, dass man die Schaltungen auch auf handelsüblichen<br />

Lochrasterplatinen aufbauen kann.<br />

1 Bausätze der früheren Firma Heathkit hatten ähnliche Listen zum<br />

Abhaken.


KAPITEL 10. PLATINENLAYOUTS 101<br />

Abbildung 10.1: Ätzmaske für 15 Platinen.<br />

10.3 Platinen ätzen<br />

Für die Experimente <strong>mit</strong> dem Mikrocontroller werden zwei<br />

Leiterplatten benötigt. Auf einer Platine im Europaformat<br />

(160 mm × 100 mm) wird das Computersystem aufgebaut. Eine<br />

kleinere Platine dient als Verbindungsglied 2 zwischen PC<br />

und Mikrocontroller.<br />

Beide Schaltungen wurden auf Lochrasterplatinen entwickelt.<br />

Wer dieses Kapitel überspringen möchte, kann die Schaltungen<br />

ebenso auf Lochrasterplatten aufbauen. Die Vor- und<br />

Nachteile muss man selbst abwägen.<br />

Platinen ätzen basiert auf foto-chemischen Verfahren, wie sie<br />

in der Fotographie wie auch bei der Herstellung von Halbleitern<br />

angewendet werden. Für Kleinserien werden Maschinen<br />

<strong>mit</strong> Pumpen und Heizungen angeboten, die Aquarien ähnlich<br />

sind. Das hier vorgestellte Verfahren für Einzelstücke kommt<br />

dagegen <strong>mit</strong> Entwicklerschalen aus.<br />

2 Die englische Bezeichnung ist Interface.


KAPITEL 10. PLATINENLAYOUTS 102<br />

10.3.1 Material<br />

Folgende Materalien werden benötigt:<br />

2 Fotobeschichtete Epoxydplatinen im Europaformat<br />

1 Laubsäge <strong>mit</strong> Sägeblättern<br />

1 Glasscheibe größer 160 mm × 100 mm<br />

1 Schutzbrille<br />

3 g Natriumhydroxyd als Granulat für Entwickler<br />

300 ml Wasser<br />

2 Entwicklerwannen 180 mm × 105 mm<br />

1 Kunststoffpinzette<br />

300 ml Wasser<br />

50 ml Salzsäure <strong>mit</strong> der Konzentration 32 %<br />

50 ml Wasserstoffperoxid <strong>mit</strong> der Konzentration 30 %<br />

1 Kunststoffflasche für verbrauchtes Ätz<strong>mit</strong>tel<br />

1 Kunststofftrichter<br />

1 Bohrmaschine <strong>mit</strong> Bohrer von 0,8 mm Durchmesser<br />

10 ml Aceton<br />

1 Kolophoniumblock<br />

1 kleiner Pinsel<br />

Die Chemikalien erhält man in Apotheken. Kolophonium 3<br />

gibt es in Musikgeschäften. Die Glasscheibe bekommt man<br />

am einfachsten <strong>mit</strong> einem Bilderrahmen.<br />

3 Kolophonium ist ein dem Bernstein ähnliches Harz-Produkt. Es<br />

wird im Geigenhandel in Blöcken verkauft, die etwa so groß wie Streichholzschachteln<br />

sind. Musiker streichen da<strong>mit</strong> ihre Bögen ein.


KAPITEL 10. PLATINENLAYOUTS 103<br />

10.3.2 Belichtungsmaske<br />

Die Belichtungsmaske wird <strong>mit</strong> dem Laserdrucker oder einem<br />

Fotokopierer auf Overheadfolie gedruckt. Da der Toner nicht<br />

gänzlich lichtdicht ist, muss man nachgebessern: Die (rauhe)<br />

Druckseite <strong>mit</strong> wasserlöslicher schwarzer Tinte bestreichen.<br />

Nach Eintrocknen der Tinte wird die Folie <strong>mit</strong> einem feuchten<br />

Tuch gesäubert.<br />

Eine zweite Methode besteht darin, zusätzlich eine seitenverkehrte<br />

Folie auszudrucken und die beiden Folien <strong>mit</strong> der<br />

Druckseite gegeneinander zu fixieren.<br />

Seit neuerem verwende ich eine dritte Methode, die einige<br />

Vorteile bietet: Mit Laser- oder Tintendrucker wird das Layout<br />

auf normalem Papier ausgedruckt. Der Ausdruck wird <strong>mit</strong><br />

Speiseöl in einen opaken Zustand versetzt, der genügend Licht<br />

zum Belichten der Platine durchläßt. Der einzige Nachteil des<br />

Verfahrens besteht darin, dass die Belichtungszeit gegenüber<br />

Folien verdoppelt werden muss.<br />

Eine falsch herum belichtete Platine ist vermeidbarer Abfall.<br />

Wenn das Layout keinen Schriftzug enthält, an dem man die<br />

richtige Orientierung erkennen kann, sollte man die dem Licht<br />

zugewandte Seite <strong>mit</strong> permanentem Filzstift als solche kennzeichnen.<br />

Bei der dritten Methode wird die Papierseite <strong>mit</strong><br />

der Druckerschwärze direkt auf den Fotolack gelegt. Das muss<br />

natürlich bereits beim Ausdruck berücksichtigt werden.


KAPITEL 10. PLATINENLAYOUTS 104<br />

10.3.3 Belichtung<br />

Die Platine wird <strong>mit</strong> der Laubsäge auf das passende Maß zugeschnitten.<br />

Bei gedämpften Licht (z. B. im Keller) wird die<br />

Schutzschicht entfernt. Unter der Belichtungsmaske wird die<br />

Platine nun in den Fotorahmen eingespannt, so dass die Glasplatte<br />

die Maske plan auf den Fotolack presst.<br />

Der problematische Vorgang bei der Platinenherstellung ist<br />

die richtige Belichtungszeit. Neben Temperatur, Konzentration<br />

und Alter der Chemikalien treten hier die breitesten<br />

Schwankungen auf, wie folgende Tabelle verdeutlicht:<br />

Lichtquelle Abstand Zeit<br />

[cm] [min]<br />

Höhensonnne (UV-A) 1000 W 50 1<br />

Sonne 5<br />

Nitraphotlampe 250 W 50 7<br />

Hallogenlampe 300 W 40 40<br />

Kryptonlampe 150 W 20 60<br />

Kryptonlampe 60 W 20 120<br />

Weiterhin haben Platinen von verschiedenen Herstellern unterschiedliche<br />

Belichtungszeiten. Auch das Alter der Platine<br />

wirkt sich aus: Ist der Fotolack sehr alt, verkürzt sich die<br />

Belichtungszeit. Aus diesem Grund haben gute Platinen ein<br />

Datum aufgedruckt.<br />

Der Abstand von der Lichtquelle wirkt sich quadratisch auf<br />

die Belichtungszeit aus: Zum Beispiel erfordert 1,4-facher Abstand<br />

die doppelte Zeit, doppelter Abstand bereits 4-fache


KAPITEL 10. PLATINENLAYOUTS 105<br />

Zeit. Außerdem muss der Abstand zwischen Lampe und Platine<br />

größer sein als die Diagonale der Platine. Die Lichtquelle<br />

darf den Fotolack nicht überhitzen.<br />

Die einfache Belichtung <strong>mit</strong> Sonnenlicht hat den Nachteil,<br />

dass Faktoren wie Luftfeuchtigkeit, Sonnenstand und Luftverschmutzung<br />

die Lichtmenge beeinflussen. Trotzdem ist die<br />

Methode praktikabel, da der Film auf den Platinen unkritisch<br />

ist, verschiedene Belichtungen also zum Erfolg führen.<br />

Zur Er<strong>mit</strong>tlung der richtigen Belichtungszeit gehe man nach<br />

folgender Methode aus dem Fotolabor vor:<br />

Ein Teststreifen Platinenmaterial der Größe 2 cm × 10 cm herrichten<br />

und <strong>mit</strong> dem Filzstift in 5 quadratische Felder unterteilen.<br />

Mit Hilfe der obigen Angaben schätzt man die Belichtungszeit,<br />

zum Beispiel 6 Minuten. Die Felder <strong>mit</strong> dem Viertel,<br />

dem Halben, dem Ganzen, dem Doppelten und Vierfachen der<br />

Zeit belichten, indem der Teststreifen während des Belichtens<br />

zu 80, 60, 40, 20 und 0 % abdeckt. Zwischen Abdeckung und<br />

Belichtungsmaske darf keine Glasscheibe gelegt werden, da<br />

das Streulicht das Ergebnis verfälscht. Unser Beispiel könnten<br />

wir ab 17:00 Uhr zu 80 % abdecken und belichten. Um<br />

17:12 Uhr werden zwei Felder, um 17:18 Uhr drei Felder, um<br />

17:21 Uhr vier Felder, um 17:22:30 Uhr der ganze Streifen bis<br />

17:24 Uhr belichtet.<br />

Statt Teststreifen kann man auch mehrere Versuche <strong>mit</strong> der<br />

kleinen Oszillatorplatine des Experimentiersystems machen.<br />

Woran man das richtig belichtete Feld erkennt, folgt in der<br />

Beschreibung des Entwicklungsvorgangs:


KAPITEL 10. PLATINENLAYOUTS 106<br />

10.3.4 Entwicklung<br />

Die Schutzbrille ist beim Umgang <strong>mit</strong> Entwicklerlauge und<br />

Ätzsäure unverzichtbar. Die Chemikalien können bei unsachgemäßer<br />

Anwendung Personen- und Sachschäden anrichten!<br />

Die Nebenprodukte Chlorgas und Ozon sind zwar sehr kurzlebig,<br />

aber unangenehme Atemgifte. Alle Chemikalien sind<br />

immer innerhalb ihrer Dosierung zu betrachten. Selbst reiner<br />

Sauerstoff ist giftig. Eine Liste von verschiedenen Konzentrationen<br />

und ihrer Anwendungen soll das verdeutlichen:<br />

Natronlauge 1 % Platinenherstellung:<br />

Entwickeln<br />

Wasserstoffperoxid 30 % Platinenherstellung:<br />

Kupfer oxidieren<br />

Wasserstoffperoxid 10 % Haare blond bleichen<br />

Wasserstoffperoxid 3 % Wunden desinfizieren<br />

Salzsäure 38 % konzentrierte Lösung<br />

Salzsäure 32 % technische Lösung<br />

Salzsäure 6 % Platinenherstellung<br />

Kupferoxid auflösen<br />

Salzsäure 0,5 % Magensaft<br />

Die 3 g Natriumhydroxid in 0,3 l handwarmem Wasser 4<br />

auflösen. Die belichtete Platine einlegen. Nach ca. 10, spätestens<br />

120 Sekunden müssen sich die belichteten Lackflächen<br />

verfärben, auflösen und wegschwimmen. Was bleibt, ist unterbelichtet.<br />

Leiterbahnen, die sich auflösen, sind überbelich-<br />

4 Eine Minderung der Temperatur um ein Grad führt bereits zu einer<br />

Verdopplung der Entwicklungszeit. Kellertemperatur ist zu kühl.


KAPITEL 10. PLATINENLAYOUTS 107<br />

tet. Nur Leiterbahnen, die nach dem Laugenbad unter fließendem<br />

Wasser klar sichtbar sind, wurden richtig belichtet.<br />

Beim nachfolgenden Ätzen müssen die freien Flächen sofort<br />

ermatten, sonst wurde unterbelichtet. 20 % Nachbelichten<br />

ohne Maske und wiederholtes Entwickeln ist eine mögliche<br />

Notlösung. Eine warme Lauge führt zu schnellen und scharfen<br />

Ergebnissen. Lange Entwicklungszeiten auf Grund kühler<br />

Lösung wirken sich negativ auf die Qualität der fertigen Platine<br />

aus.<br />

Der unbenutzte Entwickler kann in einer Kunststoffflasche unter<br />

sicherem Luftabschluß aufgehoben werden. Er reagiert <strong>mit</strong><br />

dem Kohlendioxid der Luft. Der benutzte Entwickler ist nur<br />

einige Wochen haltbar. Die Entsorgung <strong>mit</strong> viel Wasser ist<br />

unkritisch.<br />

10.3.5 Ätzen<br />

Die Salzsäure <strong>mit</strong> dem Wasserstoffperoxid in der Wanne bei<br />

Zimmertemperatur ansetzen. Wasser NICHT zur Säure gießen,<br />

sondern zuerst das Wasser in die Wanne füllen, da es<br />

sonst spritzen kann. Die Platine <strong>mit</strong> der Kupferseite nach oben<br />

einlegen und <strong>mit</strong> einem Streifen Plastikfolie die Flüssigkeit so<br />

bewegen, dass die entstehenden Gasblasen an die Oberfläche<br />

steigen. Nach ca. 10 bis 15 Minuten sollten die Leiterbahnen<br />

auf der Platine herausgeätzt sein. Das in Kupferchlorid umgesetzte<br />

Kupfer färbt die Lösung blaugrünlich.<br />

Wird sie aufgehoben, vor der Wiederverwendung Wasserstoffperoxid<br />

nachfüllen, da dieses in wenigen Tagen in Sauerstoff


KAPITEL 10. PLATINENLAYOUTS 108<br />

und Wasser zerfällt. Falls es Zweifel an der Qualität des Wasserstoffperoxids<br />

gibt, kann man <strong>mit</strong> Katalysatoren wie Braunstein<br />

aus Zink-Kohle-Batterien den Sauerstoffgehalt prüfen.<br />

Wegen des Kupferchlorids muss das Ätzbad letztendlich als<br />

Sondermüll entsorgt werden! Vor dem Verschließen der Kunststoffflasche<br />

die Lösung einige Tage ausgasen lassen.<br />

Die folgende Berechnung soll den Ätzvorgang verständlich<br />

machen:<br />

Das Kupfer wird zu Kupferchlorid und Wasser umgesetzt:<br />

H2O2 → O + H2O<br />

Cu + O → CuO<br />

CuO + 2 HCl → CuCl2 + H2O<br />

Ein Mol eines Stoffes enthält 6 ∗ 10 23 Moleküle. 5<br />

Ein Mol Cu benötigt ein Mol H2O2 und zwei Mol HCl. Der<br />

Zusammenhang zwischen Mol und Gramm ergibt sich aus den<br />

Atomgewicht der Elemente. In Gramm ausgedrückt: 64 g Cu<br />

brauchen 34 g H2O2 und 73 g HCl.<br />

Eine Europaplatine ist <strong>mit</strong> 10 cm × 16 cm × 0.0035 cm Kupfer<br />

beschichtet. Bei einer Dichte des Kupfers von 8,9 g<br />

cm3 sind das<br />

fast 5 g Kupfer.<br />

Für eine Europaplatine werden so<strong>mit</strong><br />

5 Diese Zahl heißt Avogadro-Konstante. In deutschsprachiger Literatur<br />

wird sie oft auch Loschmidt-Konstante genannt.


KAPITEL 10. PLATINENLAYOUTS 109<br />

ca. 9 g 30 %ige Wasserstoffperoxidlösung<br />

und 18 g 32 %ige Salzsäure<br />

verbraucht. Da<strong>mit</strong> die Reaktionen einigermaßen schnell ablaufen,<br />

müssen in der Ätzlösung ca. das dreifache an Salzsäure<br />

und ca. das sechsfache Wasserstoffperoxid und reichlich Wasser<br />

vorhanden sein. Der Überschuß an Chemikalien ist der<br />

Tribut, den das einfache Verfahren fordert.<br />

Ein anderes verbreitetes Ätzverfahren <strong>mit</strong> Eisen-III-Clorid ...<br />

2 FeCl3 + Cu → 2 FeCl2 + CuCl2<br />

... hat den gravierenden Nachteil, dass es bei Zimmertemperatur<br />

sehr langsam ist (ca. 10 bis 20 Stunden). Das Erwärmen<br />

dieses Ätzbades auf ca. 45 Grad bedeutet aber einen erheblichen<br />

Umstand.<br />

10.3.6 Abschlussarbeiten<br />

Die Löcher bohren und alles entgraten. Mit einem Tuch und<br />

Aceton kann der Fotolack entfernt werden, da dieser das Löten<br />

behindert. Zum Schutz des Kupfers und als Flusshilfe beim<br />

Löten eine Mischung aus einem Teelöffel Aceton und etwas<br />

abgeschabtem Kolophonium über die Leiterbahnen streichen.<br />

Die Platine ist nun fertig zum Bestücken.


Kapitel 11<br />

Schaltalgebra<br />

11.1 Boolesche Algebra<br />

Die Boolesche Algebra 1 ist jener Teil der Mathematik, der<br />

sich <strong>mit</strong> zweiwertigen Variablen beschäftigt. Die Aussagen gelten<br />

für Systeme, die <strong>mit</strong> ja – nein, wahr – falsch, geöffnet –<br />

geschlossen, oder eben ,,Spannung” – ,,keine Spannung” beschrieben<br />

werden.<br />

Das Interessante an diesem Teil der Mathematik ist, dass die<br />

meistens untersuchte Grundmenge {0, 1} so klein ist, dass die<br />

daraus entstehenden Grundfunktionen durchaus überschaubar<br />

sind. Dies ist letztendlich die Ursache, dass digitale Geräte<br />

sich gegenüber analogen so durchsetzen.<br />

1864).<br />

1 Benannt nach dem englischen Mathematiker George Boole (1815 –<br />

110


KAPITEL 11. SCHALTALGEBRA 111<br />

Betrachtet man zweidimensionale Funktionen f(x)=y, die bereits<br />

Stoff für etliche Schuljahre Mathematik bieten, so gibt<br />

es für 0 und 1 nur noch vier Funktionen:<br />

f(x) = 0 Konstanz<br />

f(x) = 1 Konstanz<br />

f(x) = x Identität<br />

f(x) = ¯x Negation<br />

Realisiert man die vier Funktionen durch elektronische Schaltungen,<br />

so ist nur die Negation nennenswert. Man benötigt<br />

zwei Widerstände und einen Transistor.<br />

Auch die nächste Stufe, die dreidimensionalen Funktionen<br />

f(x,y)=z bilden eine überschaubare Menge <strong>mit</strong> 16 Elementen.<br />

Ein bekannter Vertreter ist die Und-Funktion, auch Konjunktion<br />

genannt:<br />

f(0,0) = 0<br />

f(0,1) = 0<br />

f(1,0) = 0<br />

f(1,1) = 1<br />

Da die Und-Funktion der Multiplikation der natürlichen Zahlen<br />

ähnelt, wird sie oft wie eine Muliplikation dargestellt,<br />

manchmal auch <strong>mit</strong> dem Operator & oder <strong>mit</strong> ∧.<br />

Die Oder-Funktion wird ebenfalls oft verwendet. Wegen ihrer<br />

Verwandschaft zur Addition wird sie manchmal durch + symbolisiert.<br />

Ein anderes Symbol ist das ∨, das an das lateinische


KAPITEL 11. SCHALTALGEBRA 112<br />

Wort für ,,oder” nämlich ,,vel” erinnert. Die Punkt vor Strich<br />

Regel gilt analog für ∧ und ∨.<br />

Liste der Funktionen <strong>mit</strong> zwei Eingangsvariablen<br />

x = x = 0 1 0 1<br />

y = y = 0 0 1 1<br />

f(x,y) = 0 = 0 0 0 0 Konstanz<br />

f(x,y) = x∧y = 0 0 0 1 Konjunktion, und<br />

f(x,y) = ¯x∧y = 0 0 1 0 Inhibition<br />

f(x,y) = y = 0 0 1 1 Identität<br />

f(x,y) = x∧¯y = 0 1 0 0 Inhibition<br />

f(x,y) = x = 0 1 0 1 Identität<br />

f(x,y) = x∧¯y ∨ ¯x∧x = 0 1 1 0 Antivalenz, exklusiv<br />

f(x,y) = x ∨ y = 0 1 1 1 Disjunktion, oder<br />

f(x,y) = ¯x∧¯y = 1 0 0 0 NOR, weder noch<br />

f(x,y) = x∧y ∨ ¯x∧¯y = 1 0 0 1 Äquivalenz<br />

f(x,y) = ¯x = 1 0 1 0 Negation<br />

f(x,y) = ¯x ∨ y = 1 0 1 1 Implikation<br />

f(x,y) = ¯y = 1 1 0 0 Negation<br />

f(x,y) = x ∨ ¯y = 1 1 0 1<br />

f(x,y) = ¯x∨¯y = 1 1 1 0 NAND<br />

f(x,y) = 1 = 1 1 1 1 Konstanz<br />

Bemerkenswert ist, dass sowohl NAND- als auch NOR-<br />

Funktion geeignet sind, alle 16 Funktionen durch geeignete<br />

Verknüpfung nachzubilden. Hierin liegt die Ursache, dass diese<br />

den Grundbaustein digitaler IC-Familien bilden.


KAPITEL 11. SCHALTALGEBRA 113<br />

11.2 TTL<br />

Die Entstehung von Bausteinen läuft immer nach einem gewissen<br />

Schema. So entstand in den 60er Jahren eine Familie<br />

von digitalen integrierten Schaltungen, die TTL genannt wurde.<br />

TTL steht für Transistor-Transistor-Logik im Gegensatz<br />

zu Dioden-Transistor-Logik und anderen Techniken.<br />

Abbildung 11.1: IC SN7400 <strong>mit</strong> 4 NAND-Gattern<br />

Es entstand die Bausteinserie 74xxx, deren Grundvertreter<br />

das IC 7400 ist. Wie von Bausteinen erwartet, hat die Familie<br />

viele gemeinsame Eigenschaften wie<br />

• genormte Gehäuse<br />

• gleiche Versorgungsspannung<br />

• zueinander passende Aus- und Eingänge<br />

• ähnliches Zeitverhalten


KAPITEL 11. SCHALTALGEBRA 114<br />

Für Bausteinsysteme typisch, entstanden bald große Umsätze,<br />

was Rationalisierung und kleine Preise nach sich zog. Die 74er<br />

Familie hat in der Größenordnung 100 Mitglieder, von denen<br />

einige erwähnt werden sollen:<br />

7400 Vier NAND-Gatter <strong>mit</strong> 2 Eingängen<br />

7402 Vier NOR-Gatter <strong>mit</strong> 2 Eingängen<br />

7404 Sechs NICHT-Gatter (Inverter)<br />

7408 Vier UND-Gatter <strong>mit</strong> 2 Eingängen<br />

7410 Drei NAND-Gatter <strong>mit</strong> 3 Eingängen<br />

7430 Ein NAND-Gatter <strong>mit</strong> 8 Eingängen<br />

7432 Vier OR-Gatter <strong>mit</strong> 2 Eingängen<br />

7471 RS-Flipflop <strong>mit</strong> drei Eingängen, Preset und Clear<br />

7483 4 Bit Volladdierer<br />

74367 Sechs Bus-Leistungstreiber <strong>mit</strong> zwei Enable<br />

74681 4 Bit Binär Akkumulator<br />

Je komplexer die Schaltung, desto kürzer ist oft der Zeitraum<br />

der Produktion. Die Grundfunktionen werden nach wie vor<br />

hergestellt und angeboten, allerdings wandeln sich auch die<br />

Technologien. Es gibt sehr schnelle 74S00 (Schottky), stromsparende<br />

74LS00 (low power Schottky), schnelle und stromsparende<br />

74HC00 (high speed CMOS) und viele weitere Technologien,<br />

die nach wie vor neu auf den Markt kommen.<br />

Zu unserem Mikrocontroller passend ist die HC-Technologie,<br />

die inzwischen gut verfügbar ist. Betreibt man die Schaltung<br />

<strong>mit</strong> 5 Volt, wird auch ein alter 7400 noch funktionieren. Man<br />

konsultiere das Datenblatt für folgende Werte:<br />

• Versorgungsspannung


KAPITEL 11. SCHALTALGEBRA 115<br />

• Belastbarkeit der Ausgänge (Fan-Out)<br />

• Spannungsbereiche für High und Low<br />

11.3 Flip-Flop<br />

Eine wichtige Funktion erhält man durch Rückführung des<br />

Ergebnisses in den Eingang. Die Schaltung bekommt ein<br />

Gedächtnis, es entsteht ein RS-Flip-Flop. RS steht für set und<br />

reset.<br />

Abbildung 11.2: Prellfreie Taste<br />

Betrachtet man die Arbeitsweise der Schaltung in Abbildung<br />

11.2, so muss man für Ein- und Ausgänge x,y,z acht Zustände<br />

untersuchen:


KAPITEL 11. SCHALTALGEBRA 116<br />

x y z a<br />

0 0 0 1 unmöglich wegen Taster<br />

0 0 1 1 unmöglich wegen Taster<br />

0 1 0 1 unmöglich wegen ā∧¯x=z<br />

0 1 1 0<br />

1 0 0 1<br />

1 0 1 1 unmöglich wegen ā∧¯x=z<br />

1 1 0 1<br />

1 1 1 0<br />

Zwei Zustände sind wegen der Funktion des Tasters<br />

unmöglich: Der Kontakt des Tasters kann nur <strong>mit</strong> einem der<br />

beiden Eingänge x oder y verbunden sein, oder er befindet<br />

sich gerade auf dem Weg dazwischen.<br />

Zwei weitere Zustände sind durch die Rückführung des Signals<br />

z unmöglich, da z nur einen Wert annehmen kann.<br />

Simuliert man die beiden Schaltvorgänge, wobei es durchaus<br />

passiert, dass der Schaltkontakt wie ein Ball mehrfach vom<br />

Kontakt wieder weghüpft, so reicht das Hilfssignal a, um den<br />

Ausgang z von diesen unerwünschten Prellern zu befreien. Befindet<br />

sich der Schalter zwischen den Kontakten, erinnert sich<br />

die Schaltung an den letzten regulären Schaltzustand.


KAPITEL 11. SCHALTALGEBRA 117<br />

Einschalten Ausschalten<br />

x y a z alternativ x y a z<br />

1 0 1 0 0 1 0 1<br />

1 1 1 0 1 1 0 1<br />

0 1 0 1 1 0 1 0<br />

1 1 0 1 1 1 1 0<br />

0 1 0 1 1 0 1 0<br />

: :<br />

: :<br />

Die beiden Gatter NAND3 und NAND4 wurden nur deshalb<br />

verwendet, um die Eingänge des ICs nicht offen zu lassen,<br />

was bei einigen Technologien zu Schwingungen führt, welche<br />

Schaltung sogar zerstören können.<br />

Für unseren späteren Mikrocontroller kann die prellfreie Taste<br />

die Funktion eines Quarzoszillators <strong>mit</strong> manuell gespeister<br />

Frequenz übernehmen.


Teil III<br />

Mikrocontroller<br />

118


Kapitel 12<br />

Wurzeln<br />

Vor den <strong>Mikrocontrollern</strong> entstanden die Mikroprozessoren.<br />

Die Firma Intel hatte den Auftrag, einen damals hoch integrierten<br />

Baustein für den Einsatz in Taschenrechnern zu entwerfen.<br />

Der Ingenieur Ted Hoff legte einen Entwurf vor, der<br />

bald als allgemein einsetzbare 4-Bit CPU erkannt wurde. Ab<br />

dem 15. November 1971 wurde der 4004 für 200 Dollar pro<br />

Stück angeboten. 1972 folgte eine 8-Bit Version, der 8008.<br />

Der 8080 wurde bereits zum Welterfolg, dem die Typen 8085<br />

8086 8088 80186 80286 80386 80486 und Pentium folgten.<br />

Neben Intel haben auch andere Firmen versucht, den Markt<br />

der Mikroprozessoren zu gewinnen. Mostek entwickelte den<br />

6502, der in KIM, Comodore Pet und Apple II rechnete. Zilog<br />

verbesserte den 8085 zum Z80, der im Tandy TRS80 arbeitete.<br />

Bald kamen Mikroprozessoren <strong>mit</strong> 16 Bit Wortbreite auf den<br />

119


KAPITEL 12. WURZELN 120<br />

Abbildung 12.1: KIM-1 Mikrocomputer der Firma MOS aus<br />

dem Jahr 1975.


KAPITEL 12. WURZELN 121<br />

Markt. Zilog Z8000 und Texas Instruments TMS9900 sind<br />

von Motorolas M86000 und Intels 8086 wohl überholt worden.<br />

Motorola durfte an Apple für den Macintosh liefern und IBM<br />

hatte sich für eine Intel-CPU entschieden.<br />

Das Registermodell aller PC-kompatiblen CPUs ist zum<br />

8080 abwärtskompatibel. So konnten für den 8080 entwickelte<br />

Assembler-Programme durch einfaches Neuübersetzen auf<br />

den 8086 portiert werden. Der 8086 war intern und extern<br />

eine 16-Bit-CPU. Der 8088 war intern ein 8086, extern war<br />

er noch eine 8-Bit-CPU. Da ein Mikrocomputer <strong>mit</strong> 8-Bit im<br />

Jahr 1981 noch erheblich billiger als ein Mikrocomputer <strong>mit</strong><br />

16 Bit hergestellt werden konnte, wählte IBM den Kompromiss<br />

<strong>mit</strong> der 8088-CPU für den ersten IBM-PC. Erst im Jahr<br />

1984 wurde die PC-Architektur auf 16 Bit umgestellt. Dieser<br />

PC hieß IBM-AT und hatte eine 80286-CPU.<br />

Der technologische Durchbruch war die 80386-CPU. Sie hatte<br />

eine Speicherverwaltung auf dem Chip und kannte verschiedene<br />

Prioritätsstufen. Dies ermöglichte ihren Einsatz unter<br />

Bedingungen eines Rechenzentrums. Die Prozesse mehrerer<br />

Benutzer konnten gegenseitig abgesichert werden. So entstanden<br />

für den 80386 mehrere Unixversionen, von denen sich bekanntlich<br />

Linux am besten durchgesetzt hat. Der erste IBM-<br />

PC <strong>mit</strong> 80386 war das Modell 80, das im Jahr 1987 auf den<br />

Markt kam.<br />

Inzwischen werden sogar Supercomputer durch Zusammenschluß<br />

vieler preiswerter Mikroprozessoren gebaut.<br />

Der 80186 ist ein 8086, der einige Teile des Ein-/Ausgabewerks


KAPITEL 12. WURZELN 122<br />

<strong>mit</strong> auf den Chip bekommen hat.<br />

12.1 Mikrocontroller<br />

Während auf Seite der Mikroprozessoren die Möglichkeiten<br />

der höheren Integration zur Leistungssteigerung genutzt wurden,<br />

war es bei kleinen Anwendungen möglich, neben Rechenwerk<br />

und Steuerwerk das Ein-/Ausgabewerk <strong>mit</strong> auf den Chip<br />

zu nehmen. Die Mikrocontroller wurden geboren. Richtig interessant<br />

wurde ihr Einsatz in Telefonen, Fernsehern, Waschmaschinen,<br />

Autos usw., als auch das Speicherwerk in das IC<br />

integriert werden konnte.<br />

Einer der klassischen Mikrocontroller ist der 8051 der Firma<br />

Intel. Es gibt viele Varianten. Ein Vorzug dieser Familie ist,<br />

daß verschiedene Hersteller Bausteine anbieten.<br />

Die PIC Mikrocontroller der Firma Microchip werden vor allem<br />

in kleinen Systemen gerne eingesetzt.<br />

Der MSP430 von Texas Instruments ist ein weiterer moderner<br />

Mikrocontroller.<br />

Ferner gibt es eine schwer überschaubare Typenvielfalt verschiedener<br />

Hersteller, die meist direkt in Industrieprodukten<br />

eingesetzt und deshalb einzeln weniger angeboten werden.<br />

In diesem Buch wird ein AVR Mikrocontroller eingesetzt, weil<br />

er folgende Kritierien erfüllt:<br />

• Gute Dokumentation ist leicht erhältlich.


KAPITEL 12. WURZELN 123<br />

• Der Baustein ist in einem Gehäuse erhältlich, was manuelle<br />

Anfertigung von Prototypen erleichtert (DIL).<br />

• Eine Programmierschnittstelle, die im Zielsystem funktioniert<br />

(ISP), ermöglicht schnelles Testen ohne Umsetzen<br />

des Bausteins.<br />

• Ein leicht löschbarer Programmspeicher (Flash) beschleunigt<br />

ebenfalls die Reprogrammierung.<br />

• Programmierhardware in verschiedenen Ausführungen<br />

ist sehr preiswert verfügbar.<br />

• Programmiersoftware ist <strong>mit</strong> Quellen vorhanden.<br />

• Preiswerter C-Compiler ist <strong>mit</strong> Quellen verfügbar.<br />

• Das System ist skalierbar, was verschiedenste Projekte<br />

ermöglicht.<br />

• Unterstützung wird von verschiedenen Betriebssystemen<br />

angeboten.<br />

12.1.1 AVR Mikrocontroller<br />

Die Firma Atmel spezialisierte sich anfangs auf Halbleiterspeicher,<br />

die wie ROMs 1 ihren Inhalt ohne Spannungsversorgung<br />

erhalten, trotzdem wie RAMs 2 innerhalb der endgülti-<br />

1 Abkürzung für read only memories<br />

2 Abkürzung für random access memories, Speicher <strong>mit</strong> wahlfreiem<br />

Zugriff, so wie es das von-Neumann-Modell fordert.


KAPITEL 12. WURZELN 124<br />

gen Schaltung mehrfach beschrieben und gelöscht werden<br />

können. Diese Speicher heißen EEPROMs 3 . Während RAMs<br />

beliebig oft gelöscht werden dürfen, sind EEPROMs in dieser<br />

Hinsicht stark beschränkt. Ferner dauert das Ändern des<br />

Inhalts länger. Typische Anwendung sind Scheck- und Speicherkarten.<br />

EEPROMs eignen sich vorzüglich als Programmspeicher von<br />

<strong>Mikrocontrollern</strong>. So stellte Atmel zuerst 8051 kompatible<br />

Mikrocontroller her, entwickelte aber auch einen eigenen<br />

Typ, den AVR. Der erste AVR Mikrocontroller war<br />

der AT90S1200 aus dem Jahr 1997. Er hatte ein 20-poliges<br />

Gehäuse <strong>mit</strong> 1 KB Programmspeicher, 64 Byte EEPROM,<br />

15 Ein-/Ausgabeleitungen, Timer und Analogkomperator.<br />

Da er noch kein RAM für einen Stack hat, kann man nur<br />

zwei geschachtelte Unterprogrammsprünge ausführen. Der<br />

AT90S1200 eignet sich deshalb nur zur Programmierung <strong>mit</strong><br />

Assembler.<br />

Nach diesem Modell kam ein ganze Serie von <strong>Mikrocontrollern</strong><br />

für verschiedenste Anwendungen auf den Markt. Gemeinsame<br />

Eigenschaft der AVR-Serie sind:<br />

• Registermodell <strong>mit</strong> 32 Registern<br />

• Flash von 1..128.. KB als Programmspeicher<br />

• EEPROM von 0..4.. KB, analog einer Festplatte verwendbar<br />

3 Abkürzung für electric erasable programable read only memories


KAPITEL 12. WURZELN 125<br />

• RAM von 0..4.. KB<br />

• 3..53.. Ein-/Ausgabeleitungen<br />

• 0..11.. Analogeingänge<br />

• 8..64.. poliges Gehäuse<br />

• weitgehend zueinander kompatibel<br />

• innerhalb der Spezifikation <strong>mit</strong> jeder Frequenz taktbar<br />

• in der Anwendungsschaltung reprogrammierbar<br />

Für unser System wurde ursprünglich der AT90S4433 ausgewählt.<br />

Dieser Prozessor war vergleichbar <strong>mit</strong> den alten<br />

Mikrocomputer-Entwicklungssystemen, hatte dabei ein kleines<br />

Gehäuse und einen moderaten Preis. Die AT90-Serie<br />

wird inzwischen durch die ATtiny-Serie im unteren und die<br />

ATmega-Serie im oberen Bereich ersetzt. Der ATmega8 ist<br />

pinkompatibel zum AT90S4433, auch preislich ist er <strong>mit</strong> dem<br />

älteren Typ vergleichbar. Seine inneren Werte haben sich quasi<br />

verdoppelt:


KAPITEL 12. WURZELN 126<br />

AT90S4433 ATmega8<br />

maximaler Takt [Mhz] 8 16<br />

interner kalibrierter Oszillator x<br />

Befehle incl. Multiplikation 118 130<br />

Sleep-modes 2 5<br />

Flash [KB] 4 8<br />

Flash selbst programmierbar x<br />

Löschzyklen des Flash 1000 10.000<br />

EEPROM [Bytes] 256 512<br />

Löschzyklen des EEPROM 100.000 100.000<br />

RAM [Bytes] 128 1024<br />

8 Bit-Timer 1 2<br />

PWM-Kanäle 1 3<br />

I/O Lines (Reset,Xtal1,Xtal2) 20 23<br />

Serial I/O UART USART<br />

2 wire serial Interface x<br />

2.56V AD-Spannungsreferenz x<br />

Trotz der Verbesserungen wird bei der Herstellung für den<br />

ATmega8 weniger Siliziumfläche verbraucht. Dies ist ein wesentlicher<br />

variabler Kostenfaktor bei der Herstellung von ICs.<br />

Zur Abbildung 12.2 sei noch folgendes bemerkt: Stackpointer<br />

(SP) und Statusregister (SR) liegen zusätzlich im Adressraum<br />

des Ein-/Ausgabewerks (I/O). Die Adressräume von Registerwerk<br />

und Ein-/Ausgabewerk liegen zusätzlich im Adressraum<br />

des Datenspeichers (RAM). Dadurch vereinigt der AVR die<br />

Vorteile von zwei Konzepten:<br />

• Schnelle und effiziente Spezialbefehle für Register und<br />

I/O.


KAPITEL 12. WURZELN 127<br />

Abbildung 12.2: Architektur des ATmega8


KAPITEL 12. WURZELN 128<br />

• Variable Adressierungsmöglichkeiten für Register und<br />

I/O über die memory mapped Adressierung.<br />

Programmspeicher (Flash) und EEPROM haben jeweils einen<br />

eigenen Adressraum.<br />

Programmspeicher und EEPROM sind über Register des Ausgabewerks<br />

beschreibbar.<br />

Im Jahr 2004 will Atmel die Typen ATmega48, ATmega88<br />

und ATmega168 <strong>mit</strong> 4, 8 und 16 KB Flash im 28-poligen<br />

Gehäuse herausbringen.<br />

Diese Prozessoren haben weitere Vorteile:<br />

• Der Energieverbrauch ist durch kleinere Versorgungsspannung,<br />

neue Oszillatorschaltung und abschaltbare<br />

I/O-Bereiche reduzierbar.<br />

• Der Takt kann bis zu 20 Mhz eingestellt werden.<br />

• Alle I/O-Pins können einen Interrupt auslösen.<br />

• Der timer0 kennt CTC-Mode.<br />

• Alle Analogeingänge haben 10 Bit Auflösung.<br />

• Am Reset-Pin kann ein ICE angeschlossen werden<br />

(debug-wire).<br />

Die neuen Prozessoren sind hardware-kompatibel zu ihren<br />

Vorgängern. Programme müssen neu übersetzt werden, da der<br />

Bereich der I/O-Adressen verändert und erweitert wurde. Das<br />

RAM beginnt ab Adresse 0x100.


Kapitel 13<br />

Aufbau des Systems<br />

Unser Experimentiersystem besteht aus mehreren Teilen:<br />

• Software<br />

• Programmier-Interface<br />

• Verbindungskabel<br />

• Mikrocontroller-Board <strong>mit</strong> Oszillator<br />

• Stromversorgung<br />

Der Ausdruck der Layouts erfolgt auf einem Postscript-<br />

Drucker. Falls keiner vorhanden ist, muss die Emulationssoftware<br />

Ghostscript verwendet werden. Beim Ausdruck von graphischen<br />

Dateien hilft das hervorragende Programm gimp, für<br />

das verschiedene Bücher erschienen sind.<br />

129


KAPITEL 13. AUFBAU DES SYSTEMS 130<br />

Das Anfertigen der Platinen wurde bereits im Kapitel 10.3<br />

beschrieben. Erste Bauerfahrungen können <strong>mit</strong> der Schaltung<br />

des Programmier-Interfaces erlangt werden. Da es zentrale<br />

Komponente des Systems ist, werden wir da<strong>mit</strong> anfangen.<br />

13.1 Software<br />

Für Windows bietet die Firma Atmel eine kostenfreie Programmierumgebung<br />

an. Die Programmquellen sind jedoch<br />

nicht offengelegt. Ein relativ hoher Aufwand wurde in das<br />

graphische Benutzerinterface gelegt.<br />

Nutzer anderer Systeme, die <strong>mit</strong>tlerweile weitgehend irgendwie<br />

auf Unix aufbauen, werden von GNU gut bedient. In diesem<br />

Buch wird nur auf diese Programme eingegangen, die<br />

aber auch für Windows [winavr] erhältlich und gebräuchlich<br />

sind.<br />

Mindestens vier spezielle Programmpakete werden benötigt:<br />

avr-gcc C - Crosscompiler<br />

avr-binutils Assembler, Linker etc.<br />

avr-libc C - Runtime für AVR<br />

avrdude Programmiertool<br />

Benutzer von Debian [debian], einer bedeutenden Linux-<br />

Distribution, bekommen die notwendigen Programmpakete<br />

bereits <strong>mit</strong>geliefert. Allerdings gibt es auch für Debian-Nutzer


KAPITEL 13. AUFBAU DES SYSTEMS 131<br />

einen Wermutstropfen. Selbst die neueste Debian-Distribution<br />

hinkt der schnellen Entwicklung auf AVR-Seite hinterher. So<br />

kann man <strong>mit</strong> der aktuellen Software von Debian 3.1 für<br />

den ATmega8 gut entwickeln. Dieser ist jedoch bereits abgekündigt<br />

und wird durch den ATmega88 ersetzt. So sind<br />

auch Debian-Nutzer gezwungen, sich die aktuellen Versionen<br />

aus dem Internet zu besorgen. Auch die neueren Versionen<br />

auf http://packages.debian.org/testing sind gut gepflegt.<br />

Nutzer anderer Systeme müssen sich durch das Internet selber<br />

helfen. Nach meiner Beobachtung wird die hier beschriebene<br />

Software auch auf Apple- Freebsd- und Windowssystemen<br />

häufig benutzt.<br />

Noch einige Bemerkungen zum Programmiertool. Derartige<br />

Programme wurden für die verschiedensten Hardwareanschlüsse<br />

entwickelt. In den letzten Jahren war das Programm<br />

uisp recht beliebt, da es viele Anschlüsse gut bediente. Die<br />

Pflege von uisp wurde jedoch immer schwieriger, so dass inzwischen<br />

das Programm avrdude bevorzugt wird. Das Verhalten<br />

von avrdude kann über eine Konfigurationsdatei in gewissen<br />

Grenzen sogar erweitert werden.<br />

Die Ur-Version von avrdude hieß noch avrprog und wurde für<br />

die hier verwendete bsd-Schnittstelle entwickelt. Mit dieser<br />

Hardware funktioniert das Programm auch heute noch problemlos.<br />

Für die serielle Schnittstelle und usbasp wird mindestens<br />

die Version 5.2 benötigt.


KAPITEL 13. AUFBAU DES SYSTEMS 132<br />

13.2 Programmier-Interface<br />

Dies ist die Schicht, die das fertig übersetzte Programm von<br />

der Festplatte des PCs in den Speicher des Mikrocontrollers<br />

bringt. Die Hardware wird oft ISP genannt. Die Abkürzung<br />

für ,,In System Programmer” soll darauf hinweisen, das der<br />

Mikrocontroller nicht in einem eigenen Programmiergerät,<br />

sondern in der endgültigen Schaltung programmiert werden<br />

kann. Als Software verwenden wir das Programm avrdude.<br />

das eine Menge physikalischer Möglichkeiten unterstüzt.<br />

Drei Möglichkeiten, ponyser, bsd und usbasp genannt, werden<br />

hier beschrieben. Ponyser verwendet RS232, die bsd-Variante<br />

nutzt die Centronics-Schnittstelle, und usbasp wird am USB<br />

angeschlossen.<br />

13.2.1 Centronics Variante<br />

Diese Schnittstelle wird vom Programmiertool ,,bsd” genannt,<br />

da sie ursprünglich unter dem Betriebssystem Freebsd entwickelt<br />

wurde.<br />

Die vom Programm pcb.kit erzeugte Stückliste wird kein zu<br />

großes Loch in die Kasse reißen:<br />

1:1/9 Lochrasterplatine 13*15 :527777<br />

1:Stecker DB-25 :741671<br />

1:Pfostenstecker 10polig :742465<br />

4:Zehnerdioden BAT43 :153010<br />

1:Leuchtdiode gelb 3mm 2mA :145998<br />

1:Widerstand 2k2 Ohm :408212<br />

1:Widerstand 100K Ohm :408409<br />

1:IC 74HC367 :151165


KAPITEL 13. AUFBAU DES SYSTEMS 133<br />

Abbildung 13.1: Schaltplan der Centronics Variante des ISP-<br />

Interface


KAPITEL 13. AUFBAU DES SYSTEMS 134<br />

Der Bau der Platine ist deshalb auch für Anfänger im Löten<br />

noch zu bewerkstelligen.<br />

Abbildung 13.2: Layout der Centronics Variante des ISP-<br />

Interface<br />

( ) PCB :1/9 Lochrasterplatine 13*15 :herstellen<br />

( ) :Stecker DB-25 :anlöten, dass B5 fluchtet<br />

( ) :Pfostenstecker 10polig :anlöten (e14)<br />

( ) B1 :Drahtschlinge (optional) :einlöten (a12) (a14)<br />

( ) B2 :Draht :einlöten (c12) (j12)<br />

( ) B3 :Draht :nach Pin10 einlöten (c3)<br />

( ) B4 :Draht :nach Pin9 einlöten (d6)<br />

( ) B5 :Draht :nach Pin8 einlöten (e10)<br />

( ) B6 :Draht :nach Pin7 einlöten (g8)<br />

( ) B7 :Draht :nach Pin6 einlöten (i10)<br />

( ) B8 :Draht :nach Pin9 einlöten (e13)<br />

( ) B9 :Draht :nach Pin7 einlöten (f13)<br />

( ) B10 :Draht :nach Pin5 einlöten (g13)<br />

( ) B11 :Draht :nach Pin3 einlöten (h13)<br />

( ) B12 :Draht :nach Pin1 einlöten (i13)<br />

( ) D1 :Zehnerdioden BAT43 :Anode an Pin5 löten (i4)<br />

( ) D2 :Zehnerdiode BAT43 :Anode an Pin4 löten (j4)<br />

( ) D3 :Zehnerdiode BAT43 :Anode an Pin3 löten (k4)<br />

( ) D4 :Zehnerdiode BAT43 :Anode an Pin2 löten (l4)<br />

( ) LED1:Leuchtdiode gelb 3mm 2mA :Anode in j5 einlöten (j5) (j6)<br />

( ) R1 :Widerstand 2k2 Ohm :einlöten (j7) (j11)<br />

( ) R2 :Widerstand 100K Ohm :einlöten (k7) (k11)<br />

( ) IC1 :IC 74HC367 :Pin1 in Richtung DB25 einlöten (f4)


KAPITEL 13. AUFBAU DES SYSTEMS 135<br />

Abbildung 13.3: ISP-Interface in der Centronics Variante.<br />

Als Bestückungshilfe wird in der Abbildung 13.3 das fertige<br />

Interface gezeigt.<br />

Wird <strong>mit</strong> Lochrasterplatine gearbeitet, die auf beiden Seiten<br />

Lötaugen hat, so müssen diese im Bereich des DB-25 Steckers<br />

auf der Bestückungsseite entfernt werden, sonst wären Kurzschlüsse<br />

die Folge. DB-25 Stecker haben ein Rastermaß von<br />

2,5 mm, während Lochrasterplatinen <strong>mit</strong> einem Rastermaß<br />

von 2,54 mm ausgestattet sind. Bei der Montage des Steckers<br />

ist darauf zu achten, dass zwischen Pin14 bis Pin18 keine<br />

Kurzschlüsse entstehen. Pin18 bis Pin25 dagegen sind durchverbundene<br />

Masseanschlüsse.<br />

Die Kodieröffnung des Pfostensteckers muss, wie in der Abbildung<br />

13.3 ersichtlich, zur Bestückungsseite zeigen!


KAPITEL 13. AUFBAU DES SYSTEMS 136<br />

13.2.2 RS232 Variante<br />

Das Programmiertool uisp nannte diese Schnittstelle ,,dasa2”.<br />

Da die Schnittstellenbelegung auf ein Programmiertool <strong>mit</strong><br />

Namen PonyProg zurückgeht, nennt avrdude die Schnittstelle<br />

,,ponyser”.<br />

Falls die Druckerschnittstelle nicht verfügbar ist, kann auf diese<br />

Variante umgestiegen werden. Sie ist etwas schwieriger in<br />

der Handhabung.<br />

1:1/15 Lochrasterplatine 7*15 :527777<br />

1:Buchse Sub-D9 :742066<br />

1:Pfostenstecker 10polig :742465<br />

4:Widerstände 10K Ohm :408280<br />

5:Zehnerdioden BAT43 :153010<br />

1:BC 547 B :155012<br />

Die Montageanleitung fällt ebenfalls kleiner aus:<br />

( ) PCB :1/15 Lochrasterplatine 7*15 :herstellen<br />

( ) :Buchse Sub-D9 :Pin1..5 anlöten (b1)<br />

( ) :Pfostenstecker 10polig :Pin1,3,5,7,9 anlöten (b13)<br />

( ) R1 :Widerstände 10K Ohm :an Pin3 anlöten (c4)<br />

( ) R2 :Widerstand 10K Ohm :an Pin4 anlöten (d4)<br />

( ) R3 :Widerstand 10K Ohm :an Pin7 unten anlöten (f4)<br />

( ) R4 :Widerstand 10K Ohm :einlöten (d12) (g12)<br />

( ) B1 :Draht :an Pin8 unten anlöten (e4)<br />

( ) B2 :Draht :an Pin4,6,8,10 anlöten (a12)<br />

( ) B3 :Draht :von Pin2 über a14 nach g14 führen (a13) (g13)<br />

( ) B4 :0.2mm Trafodraht :verbinden (g4) (f13)<br />

( ) D1 :Zehnerdioden BAT43 :Anode in (c5) einlöten (c5) (g5)<br />

( ) D2 :Zehnerdiode BAT43 :Anode in (a6) einlöten (a6) (c6)<br />

( ) D3 :Zehnerdiode BAT43 :Anode in (b7) einlöten (b7) (e7)<br />

( ) D4 :Zehnerdiode BAT43 :Anode in (a8) einlöten (a8) (d8)<br />

( ) D5 :Zehnerdiode BAT43 :Anode in (e8) einlöten (e8) (g8)<br />

( ) T1 :BC 547 B :flache Seite Richtung (d1) einlöten<br />

Die Kodieröffnung des Pfostensteckers muss zur Lötseite der<br />

Platine zeigen! Das Einsetzen der Drahtbrücken erfordert etwas<br />

Sorgfalt. In der Abbildung 13.6 kann die Montage nachvollzogen<br />

werden. In der pdf-Version des Dokuments kann<br />

man die Fotos vergrößern.


KAPITEL 13. AUFBAU DES SYSTEMS 137<br />

Abbildung 13.4: Schaltplan der RS232 Variante des ISP-<br />

Interface


KAPITEL 13. AUFBAU DES SYSTEMS 138<br />

Abbildung 13.5: Layout der RS232 Variante des ISP-Interface<br />

Abbildung 13.6: ISP-Interface in der RS232 Variante.


KAPITEL 13. AUFBAU DES SYSTEMS 139<br />

Die abgebildete Version <strong>mit</strong> Lochrasterplatine hat ein etwas<br />

großzügigeres Layout. Wird <strong>mit</strong> Lochrasterplatine gearbeitet,<br />

die auf beiden Seiten Lötaugen hat, so müssen diese im Bereich<br />

des DB-9 Steckers auf der Bestückungsseite entfernt werden.<br />

13.2.3 USB Variante<br />

usbasp<br />

Der Entwickler dieser Schnittstelle Thomas Fischl nannte sie<br />

,,usbasp”. Die von ihm gelieferten Änderungen für avrdude<br />

erweitern das Programm um die Möglichkeit des Parameters.<br />

Moderne Notebooks sind <strong>mit</strong>tlerweile ohne RS232- und<br />

Centronics-Schnittstelle ausgestattet. Nahezu alles wird über<br />

USB angeschlossen. Wie zuvor im Kapitel über diese Schnittstelle<br />

angedeutet, gibt es eine ISP-Variante zum Selberbau<br />

<strong>mit</strong> USB. Die Quelle der Schaltung liegt auf Thomas Fischls<br />

Homepage www.fischl.de [fischl]. Leider existiert hier das<br />

Henne-Ei-Problem. Wer keinen Weg sieht, den notwendigen<br />

USB-Controller zu programmieren, ist wohl auf das fertige<br />

Angebot von Atmel, den AVRISP MKII, angewiesen.<br />

Der Selberbau ist durchaus lohnend, da nicht viele Bauteile<br />

notwendig sind:<br />

1:board 43mm x 71mm :BEL 160x100-1<br />

1:isolated bridge :<br />

1:10k resistor :1/4W 10k<br />

1:1k5 resistor :1/4W 1k5


KAPITEL 13. AUFBAU DES SYSTEMS 140<br />

Abbildung 13.7: Schaltplan der USB Variante des ISP-<br />

Interface


KAPITEL 13. AUFBAU DES SYSTEMS 141<br />

1:270 resistor :1/4W 270<br />

2:2k2 resistor :1/4W 2k2<br />

2: 68 resistor :1/4W 68<br />

2: 22pF capacitor :Kerko 22p<br />

1:100nF capacitor :Z5U-2,5 100n<br />

1: 10uF capacitor :AX 10/35<br />

1: 10uF capacitor :RAD 10/35<br />

1:12Mhz quartz :12-HC49U-S<br />

1: red led 2mA :LED 3mm 2MA rt<br />

1:green led 2mA :LED 3mm 2MA gr<br />

1:BAT43 schottky diode:BAT 43<br />

1:ATmega48-20PU :ATMEGA48-20 DIP<br />

1:jumper SCK :LU 2,5 MS2<br />

1:plug :WSL 10W<br />

1:USB-B-plug :USB BW<br />

Die Montageanleitung:<br />

( ) PCB:board 43mm x 71mm :saw<br />

( ) B1 :bridge :solder (h15) (i14)<br />

( ) B2 :bridge :solder (a22) (e22)<br />

( ) B3 :bridge :solder (d13) (d11)<br />

( ) B4 :bridge :solder (k19) (k22)<br />

( ) B5 :bridge :solder (h19) (h22)<br />

( ) B6 :bridge :solder (j7) (l7)<br />

( ) B7 :isolated bridge :solder if needed (h8) (i21)<br />

( ) R1 :10k resistor :solder (b8) (f8)<br />

( ) R2 :1k5 resistor :solder (a6) (e6)<br />

( ) R3 :270 resistor :solder (b10) (f10)<br />

( ) R4 :2k2 resistor :solder (l6) (l10)<br />

( ) R5 :2k2 resistor :solder (n6) (n10)<br />

( ) R6 : 68 resistor :solder (a4) (e4)<br />

( ) R7 : 68 resistor :solder (l4) (p4)<br />

( ) C1 : 22pF capacitor :solder (d15) (e15)<br />

( ) C2 : 22pF capacitor :solder (d21) (e21)<br />

( ) C3 :100nF capacitor :solder (f14) (f15)<br />

( ) C4 : 10uF capacitor :solder + in (n20) (n14) (n20)<br />

( ) C4a: 10uF capacitor :alternatively (n15) (n16)<br />

( ) Q1 :12Mhz quartz :solder (e17) (e19)<br />

( ) D1 : red led 2mA :solder anode in (l11) (l11) (l12)<br />

( ) D2 :green led 2mA :solder anode in (n11) (n11) (n12)<br />

( ) D3 :BAT43 schottky diode:solder anode in (n21) (n21) (n24)<br />

( ) IC1:ATmega48-20PU :solder Pin 1 in (g8)<br />

( ) J3 :jumper SCK :solder (k8) (k9)<br />

( ) K1 :plug :solder<br />

( ) K4 :USB-B-plug :solder<br />

Der Prozessor kann über den ISP-Stecker programmiert werden.<br />

Hierzu sind eine Brücke über die Diode und eine Brücke<br />

zwischen den beiden SMD-Pads zu löten. Nach dem Programmieren<br />

müssen auch die L- und H-Fuse neu gesetzt werden!


KAPITEL 13. AUFBAU DES SYSTEMS 142<br />

Abbildung 13.8: Layout der USB Variante des ISP-Interface


KAPITEL 13. AUFBAU DES SYSTEMS 143<br />

Abbildung 13.9: ISP-Interface in der USB Variante.


KAPITEL 13. AUFBAU DES SYSTEMS 144<br />

Der Jumper muss gesteckt werden, wenn die am ISP angeschlossene<br />

MCU <strong>mit</strong> weniger als 1,5 Mhz getaktet wird. Dies<br />

ist z.B. bei unseren MCUs im Auslieferungszustand der Fall.<br />

Um diese Lösung zum Arbeiten zu bekommen müsste man<br />

diesen Kurs bereits teilweise durchlaufen haben. Deshalb rate<br />

ich Einzelkämpfern, besser die etwas teurere Lösung von Atmel<br />

zu kaufen. In Gruppen sind die Einsparungen durch die<br />

Eigenleistung durchaus lohnend, vom Einblick in die Interna<br />

von USB ganz zu schweigen.<br />

Zuletzt ist zu beachten, dass das Programm avrdude die<br />

Schnittstelle usbasp kennt. Zur Zeit von avrdude Version 5.1<br />

muss hierzu noch eine Spezialversion aus den Programmquellen<br />

erzeugt werden.<br />

Innerhalb einer Diskussion im Internet wurde erwähnt, dass<br />

die Spezifikation der USB-Schnittstelle für die Signale D+ und<br />

D- nur 3,3 V +/- 10 % vorsieht. Die hier vorgestellte einfache<br />

Lösung verwendet jedoch 5 V. Sollte das Probleme machen,<br />

so kann man einfach <strong>mit</strong> zwei Dioden die Versorgungsspannung<br />

der Schaltung reduzieren. Der verwendete ATmega48-<br />

20 kann auch bei 3,3 V noch <strong>mit</strong> den notwendigen 12 Mhz<br />

getaktet werden. Die reduzierte Spannung kann natürlich zu<br />

Problemen auf der ISP-Seite führen.<br />

usbisp<br />

Mattias Weißer bietet auf seiner Homepage www.matwei.de<br />

[matwei] eine weitere interessante Lösung an. Er verwendet


KAPITEL 13. AUFBAU DES SYSTEMS 145<br />

den FTDI-Chip FT245BM, der vom Betriebssystem als serieller<br />

Schnittstellenkonverter erkannt wird. Softwaremäßig wird<br />

das STK500 von Atmel emuliert. Daraus ergeben sich Vorund<br />

Nachteile:<br />

- Den FTDI-Chip gibt es nur als SMD-Bauteil.<br />

- Die Schaltung ist aufwändiger als usbasp.<br />

+ Für den FTDI-Chip gibt es fertige Treiber.<br />

+ Für das STK500 gibt es fertige ISP-Software.<br />

+ Die Lösung ist relativ schnell.<br />

Auch wer diese Lösung verfolgt steht vor dem Henne-Ei-<br />

Problem. Zumindest eine (ebenfalls zum STK500 kompatible)<br />

Boot-Software muss <strong>mit</strong> einem vorhandenen Programmiergerät<br />

in die MCU geladen werden.<br />

Die Firmware von usbisp ist aber auch ohne den FTDI-<br />

Chip <strong>mit</strong> einer RS232-Schnittstelle verwendbar. Bei dieser<br />

Lösung, sie wurde RS232isp genannt, entfallen obige Nachteile.<br />

Für den Anschluss an USB reicht ein einfacher RS232-<br />

USB-Konverter. Im Anhang E wird auf diese Lösung nochmal<br />

eingegangen.<br />

13.3 Kabel<br />

Ein ein bis zwei Meter langes 10-adriges Flachbandkabel wird<br />

an beiden Seiten <strong>mit</strong> Pfostensteckern versehen. Meist haben<br />

Flachbandkabel eine farbige Ader. Diese wird <strong>mit</strong> Pin1 verbunden.<br />

Pin1 der Pfostenstecker ist <strong>mit</strong> einem kleinen Pfeil


KAPITEL 13. AUFBAU DES SYSTEMS 146<br />

gekennzeichnet. Zusammendrücken kann man die Stecker in<br />

einem Schraubstock, gefühlvolles Drehen am Knebel vorausgesetzt!<br />

13.4 Mikrocontroller-Board<br />

Je unbekannter das Terrain, desto langsamer sollte man fortschreiten.<br />

Der Aufbau des Experimentiersystems wird deshalb<br />

in sechs Baustufen unterteilt. Die erste Stufe ist auf dem<br />

Schaltplan in Abbildung 13.10 nicht grau hinterlegt und wird<br />

hier nochmal in zwei Stufen geteilt.<br />

13.4.1 Programmierschnittstelle<br />

Im zur Hardware gehörigen Verzeichnis befindet sich<br />

ein Platinenlayout, bei dem die Kupferlackdrähte Kl1<br />

und Kl2 im Layout integriert wurden in der Datei<br />

hardware/layout mainboard.png.<br />

( ) PCB :1/1 Lochrasterplatine 39*63:herstellen<br />

( ) Mon1:4 Platinenfüße :befestigen (K61)<br />

( ) B3 :Draht :einlöten (v6) (v12)<br />

( ) B4 :Draht :einlöten (c56) (a56)<br />

( ) B5 :Draht :einlöten (c16) (a16)<br />

( ) B6 :Draht :einlöten (M16) (J16)<br />

( ) B7 :Draht :einlöten (J15) (C15)<br />

( ) B8 :Draht :einlöten (a7) (h7)<br />

( ) B9 :Draht :einlöten (f8) (f13)<br />

( ) B10 :Draht :einlöten (g8) (g13)<br />

( ) B11 :Draht :einlöten (D1) (D3)<br />

( ) B12 :Draht :einlöten (c19) (a19)<br />

( ) B13 :Draht :verbinden (F6) (H9)<br />

( ) Pfo1:Steckerliste 2x5 90Grad :einlöten (F6)<br />

( ) So1 :DIL-28S Präzisions-Sockel :einlöten (w12)


KAPITEL 13. AUFBAU DES SYSTEMS 147<br />

Abbildung 13.10: Schaltplan der ersten sechs Baustufen


KAPITEL 13. AUFBAU DES SYSTEMS 148<br />

Abbildung 13.11: Layout der Hauptplatine


KAPITEL 13. AUFBAU DES SYSTEMS 149<br />

( ) Kl1 :Kupferlackdraht 0.2mm :einlöten (J6) (p5)<br />

( ) Kl2 :Kupferlackdraht 0.2mm :einlöten (H6) (w6)<br />

( ) IC1 :Mikrocontroller ATmega..8 :Pin1 in w12 einsetzen<br />

Der Draht B12 wird VOR dem Einsetzen des Sockels am Pin<br />

17 festgelötet. Nach dem Einlöten in die Platine wird der<br />

Draht <strong>mit</strong> der Steckerleiste verbunden. Ist alles montiert, kann<br />

ein Test eingeschoben werden.<br />

13.4.2 Erster Dialog<br />

Nachdem das Programmierinterface fertig ist und eine letzte<br />

optische Kontrolle keine Fehler mehr erkennen läßt, soll ein<br />

erstes Experiment die Funktionstüchtigkeit beweisen.<br />

Dieses Experiment funktioniert nicht <strong>mit</strong> der RS232-Variante<br />

der ISP-Schnittstelle, da diese keine Stromversorgung beinhaltet.<br />

Bei ausschließlicher Verwendung der Variante muss der<br />

Aufbau der Stromversorgung, im Kapitel 13.4.4 beschrieben,<br />

vorgezogen werden.<br />

Für die Verbindung zwischen dem Mikrocontroller und der<br />

ISP-Schnittstelle wurde die Experimentierplatine <strong>mit</strong> Drahtbrücken,<br />

CPU-Sockel und ISP-Stecker bestückt. Der Mikrocontroller<br />

sollte fabrikneu sein, da er sonst eventuell auf einen<br />

externen Oszillator eingestellt wurde. In diesem Fall kann man<br />

ohne Oszillator den Mikrocontroller nicht mehr ansprechen.<br />

Das Programm avrdude wird aufgerufen. Der erste Testaufruf<br />

heißt


KAPITEL 13. AUFBAU DES SYSTEMS 150<br />

oder<br />

oder<br />

avrdude -c bsd -p atmega48 -P /dev/parport0<br />

avrdude -c ponyser -p atmega48 -P /dev/ttyS0<br />

avrdude -c usbasp -p atmega48<br />

je nach verwendeter Schnittstelle. parport0, ttyS0 und atmega48<br />

sind Parameter, die natürlich stimmen müssen. Eine<br />

entsprechende Freigabe der Schnittstellen vom PC-Bios muss<br />

beim Urladen (BIOS-Setup) erfolgt sein. Die Treiberschichten<br />

des Betriebssystems müssen vorhanden sein.<br />

Da die libusb in avrdude <strong>mit</strong> dem Verzeichnis /proc arbeitet,<br />

dies aber nur <strong>mit</strong> Superuser-Rechten erlaubt ist, müssen diese<br />

Rechte dem Programm während der Ausführung <strong>mit</strong> folgendem<br />

Befehl eingeräumt werden:<br />

chmod 4755 /usr/local/bin/avrdude<br />

Solche Rechte kann natürlich nur der Superuser vergeben.<br />

Wird eine Schnittstelle im Verzeichnis /dev verwendet, so<br />

braucht der User ausreichend Rechte für den Zugriff auf die<br />

entsprechende Schnittstelle. Der Superuser muss also zum<br />

Beispiel folgenden Befehl eingeben:


KAPITEL 13. AUFBAU DES SYSTEMS 151<br />

chmod 666 /dev/ttyS0<br />

Fehler können in vier Bereichen liegen, fehlende Dateien, fehlende<br />

Rechte, fehlende Systemtreiber, falsche Verdrahtung.<br />

Diese Hürde muss erklommen werden.<br />

Erkennt das Programm avrdude endlich den Prozessortyp,<br />

zum Beispiel <strong>mit</strong> der Meldung<br />

...<br />

avrdude: Device signature = 0x1e9205<br />

...<br />

so ist die erste Stufe geschafft, unser System ist bereit, das<br />

erste Experiment kann starten:<br />

Eeprom <strong>mit</strong> Hello World! beschreiben und auslesen.<br />

Die binutils-avr sind hoffentlich installiert.<br />

Als erstes wird eine Quelldatei <strong>mit</strong> dem Editor erstellt:<br />

vi eeprom.s<br />

In diese Datei schreiben wir eine Assembler-Anweisung, die<br />

unseren Text erzeugt:<br />

.string ”Hello World!”


KAPITEL 13. AUFBAU DES SYSTEMS 152<br />

Anschließend wird die Datei dem Assembler zum Übersetzen<br />

gegeben.<br />

avr-as eeprom.s<br />

Die Datei <strong>mit</strong> dem default-Namen a.out muss nun für das<br />

Programmierprogramm avrdude vorbereitet werden:<br />

avr-ld -o eeprom --oformat srec a.out<br />

Es entsteht eine kleine Datei im Motorola S-records Format,<br />

die man <strong>mit</strong> dem Befehl<br />

ansehen kann.<br />

cat eeprom<br />

S0090000656570726F6D6E<br />

S110000048656C6C6F20576F726C642100B2<br />

S104000D00EE<br />

S9030000FC<br />

Jede Zeile bildet eine S-record bestehend aus folgenden Feldern:<br />

S, Satztyp, Datenlänge, Ladeadresse, Daten, Prüfbyte.<br />

Diese Datei kann vom Programmierprogramm ins Speicherwerk<br />

des Mikrocontrollers geladen werden:


KAPITEL 13. AUFBAU DES SYSTEMS 153<br />

avrdude -c usbasp -p atmega48 -U eeprom:w:eeprom:s<br />

Zur Kontrolle liest der Befehl<br />

avrdude -c usbasp -p atmega48 -U eeprom:r:-:s<br />

unsere Daten aus dem Mikrocontroller wieder aus.<br />

Mit diesem einfachen Versuch ist bewiesen, dass sich unser<br />

Mikrocontroller programmieren lässt. Den nächsten Experimenten<br />

steht nichts mehr im Weg.<br />

Vertiefung: Die vier Zeilen der Datei eeprom lassen sich <strong>mit</strong><br />

den Tabellen aus dem Kapitel 2 decodieren.<br />

13.4.3 Erste Baustufe<br />

Nun wird die Schaltung um Oszillator und Leuchtdioden erweitert:<br />

( ) B1 :Drahtschlinge für -Messp. :einlöten (L6) (L7)<br />

( ) B2 :Drahtschlinge für +Messp. :einlöten (a6) (a8)<br />

( ) So3 :DIL-14 Präzisions-Sockel :einlöten (D17)<br />

( ) Stl3:Stiftleiste 1polig :einlöten (y8)<br />

( ) Stl4:Stiftleiste 2polig (option):bei ISP-Betrieb einlöten (v13)<br />

( ) :Jumper (option) :bei ISP-Betrieb einlöten<br />

( ) LED1:Leuchtdioden grün 3mm 2mA :Anode in y3 einlöten (y2) (y3)<br />

( ) LED2:Leuchtdioden gelb 3mm 2mA :Anode in t3 einlöten (t2) (t3)<br />

( ) LED3:Leuchtdioden rot 3mm 2mA :Anode in o3 einlöten (o2) (o3)<br />

( ) C1 :Kondensator 100 nF :einlöten (B10) (B11)<br />

( ) C2 :Kondensator 100 nF :einlöten (E10) (E11)<br />

( ) C13 :Kondensator 33 nF (option):bei ISP-Betrieb zwischen Pin1 und GND<br />

( ) L1 :Festinduktivität 10uH :liegend einlöten (D4) (D8)<br />

( ) R7 :Widerstand 2k7 Ohm :stehend einlöten (y4) (y5)<br />

( ) R8 :Widerstand 2k7 Ohm :stehend einlöten (t4) (t5)<br />

( ) R9 :Widerstand 2k7 Ohm :stehend einlöten (o4) (o5)<br />

( ) R11 :Widerstand 47k Ohm :liegend einlöten (L8) (I8)<br />

( ) R12 :Widerstand 47k Ohm :liegend einlöten (C13) (w13)<br />

( ) IC2 :Oszillator 7.3728 Mhz :Pin1 in J14 einsetzen<br />

( ) Stl1:Stiftleiste 3polig :einlöten (c13)<br />

( ) D1 :Diode BAT 43 :Anode in d14 einlöten (d14) (d16)


KAPITEL 13. AUFBAU DES SYSTEMS 154<br />

Abbildung 13.12: Erste Baustufe<br />

Obige Tests können wiederholt werden. Bereits beim up- und<br />

download müssen die Leuchtdioden heftig blinken, da sie<br />

auch als Kontrollleuchten für die Programmierleitungen MO-<br />

SI, SCK and MISO gedacht sind. Im Fehlerfall muss man<br />

Leiterbahnen und Polung der LEDs kontrollieren.<br />

Funktioniert die Platine so weit, sind wir bereit für das erste<br />

Programmierprojekt. Zur Einführung programmieren wir in<br />

Assembler.<br />

Blinkende LED<br />

Für die Ausgabe von ,,Hello World!” sind schon viele Voraussetzungen<br />

auf Hard- und Softwareseite zu erfüllen. Un-


KAPITEL 13. AUFBAU DES SYSTEMS 155<br />

ser System ist noch zu einfach und muss für diese Aufgabe<br />

noch wachsen. Mikrocontroller begrüßen die Welt oft <strong>mit</strong> einer<br />

Leuchtdiode, die einfach an und aus geht. Das ließe sich<br />

auch einfacher lösen, dann würde man aber nichts über Mikrocontroller<br />

lernen.<br />

Reine Assembler Version<br />

Das einfache Programm besteht aus vier Teilen:<br />

• Vorbereiten des Programmspeichers auf alle Interrupts,<br />

auf die der Mikrocontroller reagieren würde.<br />

• Vorbereiten des RAMs durch Initialisieren des Stackpointers.<br />

• Vorbereiten des Ausgabewerkes.<br />

• Programmschleife zum Schalten der LED.<br />

Die genaue Beschreibung aller AVR-Befehle befindet sich in<br />

der von Atmel erhältlichen Beschreibung ,,AVR Instruction<br />

Set”.<br />

Einige Regeln des Programms:<br />

• Kommentare starten <strong>mit</strong> einem Semikolon und erstrecken<br />

sich bis zum Zeilenende.


KAPITEL 13. AUFBAU DES SYSTEMS 156<br />

• Die Section .text liegt im Programmspeicher (im Gegensatz<br />

zu .eeprom).<br />

• Programmmarken wie Sprungadressen enden <strong>mit</strong> Doppelpunkt.<br />

• Worte, die der Assembler kennt, sind in der Regel klein<br />

geschrieben.<br />

• Es empfiehlt sich, eingeführte Worte wie Sprungmarken<br />

am Anfang groß, dann klein zu schreiben.<br />

• Die von Atmel eingeführten Registeradressen etc. sind<br />

in der Regel komplett groß geschrieben.<br />

Das gezeigte Beispiel verwendet noch keine Namen für die<br />

Register des Ein-/Ausgabewerkes. Diese sind als Kommentar<br />

angefügt. Das Programm funktioniert deshalb nur für die<br />

vorgesehene Version des AVR-Prozessors. Es kann <strong>mit</strong> einem<br />

einfachen Befehl übersetzt werden:<br />

avr-as fastled.as<br />

Die entstandene Datei a.out kann zur Kontrolle wieder<br />

rückübersetzt werden.<br />

avr-objdump -d a.out<br />

Diesen Vorgang nennt man Disassemblieren.


KAPITEL 13. AUFBAU DES SYSTEMS 157<br />

../software/led.assembler/a.out: file format elf32-avr<br />

Disassembly of section .text:<br />

00000000 :<br />

0: 19 c0 rjmp .+50 ; 0x34<br />

2: 17 c0 rjmp .+46 ; 0x32<br />

4: 16 c0 rjmp .+44 ; 0x32<br />

6: 15 c0 rjmp .+42 ; 0x32<br />

8: 14 c0 rjmp .+40 ; 0x32<br />

a: 13 c0 rjmp .+38 ; 0x32<br />

c: 12 c0 rjmp .+36 ; 0x32<br />

e: 11 c0 rjmp .+34 ; 0x32<br />

10: 10 c0 rjmp .+32 ; 0x32<br />

12: 0f c0 rjmp .+30 ; 0x32<br />

14: 0e c0 rjmp .+28 ; 0x32<br />

16: 0d c0 rjmp .+26 ; 0x32<br />

18: 0c c0 rjmp .+24 ; 0x32<br />

1a: 0b c0 rjmp .+22 ; 0x32<br />

1c: 0a c0 rjmp .+20 ; 0x32<br />

1e: 09 c0 rjmp .+18 ; 0x32<br />

20: 08 c0 rjmp .+16 ; 0x32<br />

22: 07 c0 rjmp .+14 ; 0x32<br />

24: 06 c0 rjmp .+12 ; 0x32<br />

26: 05 c0 rjmp .+10 ; 0x32<br />

28: 04 c0 rjmp .+8 ; 0x32<br />

2a: 03 c0 rjmp .+6 ; 0x32<br />

2c: 02 c0 rjmp .+4 ; 0x32<br />

2e: 01 c0 rjmp .+2 ; 0x32<br />

30: 00 c0 rjmp .+0 ; 0x32<br />

00000032 :<br />

32: e6 cf rjmp .-52 ; 0x0<br />

00000034 :<br />

34: 02 e0 ldi r16, 0x02 ; 2<br />

36: 0e bf out 0x3e, r16 ; 62<br />

38: 0f ef ldi r16, 0xFF ; 255<br />

3a: 0d bf out 0x3d, r16 ; 61<br />

0000003c :<br />

3c: 25 9a sbi 0x04, 5 ; 4<br />

0000003e :<br />

3e: 2d 9a sbi 0x05, 5 ; 5<br />

40: 2d 98 cbi 0x05, 5 ; 5<br />

42: fd cf rjmp .-6 ; 0x3e<br />

Den Zusammenhang zwischen Befehlen des Assemblers und<br />

Befehlscodes kann man in der Rückübersetzung gut erkennen.<br />

Das Disassemblieren ist auch später interessant, wenn nicht<br />

klar ist, wie der Compiler ein Programm verstanden hat.


KAPITEL 13. AUFBAU DES SYSTEMS 158<br />

Wie das Programm in den Flash-Speicher des Mikrocontrollers<br />

kommt, wissen wir schon: <strong>mit</strong> den Werkzeugen avr-ld und<br />

avrdude.<br />

Sofort nachdem das Programm geladen wird, wird der Mikrocontroller<br />

<strong>mit</strong> einem Reset aktiviert. Er springt auf die Adresse<br />

0 und beginnt <strong>mit</strong> der Programmbearbeitung. In diesem<br />

Punkt unterscheiden sich viele CPUs. Dieses Verhalten ist ein<br />

wichtiger Aspekt des Datenblattes.<br />

Die Leuchtdiode leuchtet zwar, aber scheint nicht zu blinken.<br />

Untersucht man den Pin 5 des Port B <strong>mit</strong> dem Oszilliskop, wie<br />

es die Abbildung 13.13 zeigt, so blinkt er doch. Die horizon-<br />

tale Ablenkung des Oszilloskops ist auf 1 µsec<br />

cm<br />

eingestellt. Der<br />

Mikrocontroller arbeitet <strong>mit</strong> dem internen Takt von 1 Mhz.<br />

Ein Takt des Mikrocontrollers entspricht also 1 cm horizontaler<br />

Ablenkung. Im Oszillogramm kann man gut die zwei Takte<br />

des Befehls sbi, gefolgt von den jeweils zwei Takten der Befehle<br />

cbi und rjmp erkennen. Dannach folgt der nächste Schleifendurchlauf.<br />

Der Befehl rjmp liegt jetzt außerhalb der Breite der<br />

Kathodenstrahlröhre. Der nächste Schleifendurchlauf triggert<br />

wieder die Synchronisation und der Kathodenstrahl läuft auf<br />

der gleichen Bahn wie 12 µsec zuvor.<br />

Vertiefung: Mit welcher Frequenz blinkt die Leuchtdiode?<br />

Assembler Version <strong>mit</strong> Präprozessor<br />

In obigem Programm sind typabhängige Werte wie RAMEND<br />

und PORTB als Konstante ins Programm eingetragen. Das


KAPITEL 13. AUFBAU DES SYSTEMS 159<br />

Abbildung 13.13: Schnell blinkende Leuchtdiode


KAPITEL 13. AUFBAU DES SYSTEMS 160<br />

ist nicht nur schlecht zu lesen, sondern macht auch Probleme,<br />

wenn das Programm auf ein anderes Mikrocontrollermodell<br />

portiert werden soll. Deshalb wird normalerweise eine<br />

Datei <strong>mit</strong> dem Befehl .include eingeführt, die die Werte für<br />

das entsprechende Modell definiert. Das avr-binutils-Paket ist<br />

primär auf die Programmiersprache C ausgerichtet. So ist es<br />

verständlich, dass die vom Prozessor abhängigen Includefiles<br />

nur für C und nicht für Assembler vorhanden sind. Mit einem<br />

(nicht ganz sauberen) Trick kann man die C Includefiles auch<br />

für Assembler nutzen. Es wird der C Präprozessor eingesetzt.<br />

avr-cpp -mmcu=atmega48 fastled.s | sed ”s/ + 0x20//g” |<br />

avr-as<br />

Leider muss ein kleines Problem <strong>mit</strong> dem Streameditor sed<br />

ausgebügelt werden. Dies ist natürlich bei der Programmierung<br />

zu berücksichtigen. Statt ” + 0x20” verwende man<br />

”+32”, falls die Konstante gebraucht wird.<br />

An den Anfang der Datei stellt der zusätzliche cpp-Befehl<br />

#include <br />

zusammen <strong>mit</strong> der -mmcu Option die Konstanten als Namen<br />

entsprechend dem Datenblatt von Atmel zur Verfügung. Die<br />

Kommentare der Befehle des obigen Hauptprogramms können<br />

jetzt in die Befehle integriert werden.


KAPITEL 13. AUFBAU DES SYSTEMS 161<br />

Nachdem das Problem der Portabilität gelöst ist, betrachten<br />

wir ein praktisches Problem des Programms: Der Mikrocontroller<br />

ist so schnell, dass das Blinken nicht sichtbar wird. Zwei<br />

Lösungsmöglichkeiten bieten sich an:<br />

• Der Takt des Prozessors wird gebremst, zum Beispiel<br />

auf zwei Hertz.<br />

• Das Programm wird um Warteschleifen erweitert.<br />

Die erste Möglichkeit wird hier nicht vertieft. Der Sockel des<br />

Oszillators lässt Raum für eigene Experimente wie das Takten<br />

<strong>mit</strong> einer prellfreien Taste. Die AVR-Mikrocontroller sind statisch<br />

aufgebaut und funktionieren bis zur oberen Grenze <strong>mit</strong><br />

jeder Taktfrequenz. Diese Eigenschaft ist nicht selbstverständlich!<br />

Langsamer Takt verbraucht weniger Strom. Es ist zu<br />

beachten, dass die Fuses der MCU auf die jeweilige Taktart<br />

eingestellt werden müssen. Das Datenblatt gibt auch hierzu<br />

detaillierte Auskunft. Dies ist eine der Möglichkeiten, den<br />

Mikrocontroller an ein konkretes Projekt anzupassen, auch<br />

skalieren genannt.<br />

Assembler Version <strong>mit</strong> Warteschleifen<br />

Die zweite Möglichkeit, die Blinkfrequenz zu verkleinern, besteht<br />

darin, zwischen dem Umschalten eine Pause einzulegen.<br />

Die Programmschleife zum Schalten der LED wird um Warte-<br />

Aufrufe erweitert:


KAPITEL 13. AUFBAU DES SYSTEMS 162<br />

;// Wait()<br />

Wait:<br />

;// register Cnt1, Cnt2, Cnt3<br />

#define Cnt1 r16<br />

#define Cnt2 r17<br />

#define Cnt3 r18<br />

;// for (Cnt1=100;Cnt1;Cnt1--)<br />

ldi Cnt1, 100<br />

Loop2:<br />

tst Cnt1<br />

breq Endloop2<br />

dec Cnt1<br />

;// for (Cnt2=100;Cnt2;Cnt2--)<br />

ldi Cnt2, 100<br />

Loop3:<br />

tst Cnt2<br />

breq Endloop3<br />

dec Cnt2<br />

;// for (Cnt3=100;Cnt3;Cnt3--)<br />

ldi Cnt3, 100<br />

Loop4:<br />

tst Cnt3<br />

breq Endloop4<br />

dec Cnt3<br />

;// end for<br />

rjmp Loop4<br />

Endloop4:<br />

;// end for<br />

rjmp Loop3<br />

Endloop3:<br />

;// end for<br />

rjmp Loop2<br />

Endloop2:<br />

;// end Wait<br />

ret<br />

;// Main()<br />

Main:<br />

;// DDRB5 becomes output<br />

sbi DDRB,5<br />

;// loop<br />

Loop1:<br />

;// switch on PORTB5<br />

sbi PORTB,5<br />

;// Wait ()<br />

rcall Wait<br />

;// switch off PORTB5<br />

cbi PORTB,5<br />

;// Wait ()<br />

rcall Wait<br />

;// end loop<br />

rjmp Loop1<br />

Endloop1:<br />

Die Warte-Funktion besteht aus einer geschachtelten Zählschleife,<br />

die 100 ∗ 100 ∗ 100 also eine Million mal durchlaufen


KAPITEL 13. AUFBAU DES SYSTEMS 163<br />

wird. Ein so verzögertes Umschalten ist <strong>mit</strong> blosem Auge erkennbar.<br />

Das Assembler-Programm wurde erst in einer zu C ähnlichen<br />

Pseudosprache formuliert, die als Kommentar zwischen<br />

den Befehlen steht. Ein derart strukturiertes Assembler-<br />

Programm kann man schnell entwickeln. Eine lästige Arbeit,<br />

das Erfinden von Sprungmarken wird auf die Verwaltung von<br />

Nummern reduziert. Der Rest ist fast mechanische Übersetzungsarbeit.<br />

Eine Arbeit für die es eigentlich Compiler gibt.<br />

Die Hauptgründe beim heutigen Einsatz von Assembler sind,<br />

die Programmgröße zu minimieren oder die Programmgeschwindigkeit<br />

zu maximieren. Diese beiden Ziele können aber<br />

nur <strong>mit</strong> hohem Aufwand erreicht werden. Vergleicht man die<br />

obige Assembler-Version <strong>mit</strong> der folgenden C-Version der blinkenden<br />

Leuchtdiode, so wird das klar. Hier war der Einsatz<br />

des Assemblers wichtig, um eine Vorstellung von der Arbeitsweise<br />

des Computers zu bekommen.<br />

C Version<br />

Für die folgenden Programmbeispiele ist die Kenntnis der<br />

wichtigsten Eigenschaften der Programmiersprache C Voraussetzung.<br />

//<br />

// Program: led.c<br />

// Funktion: program-sample for c: blinking led<br />

// History: 20031203 HKU creation<br />

//<br />

#include


KAPITEL 13. AUFBAU DES SYSTEMS 164<br />

void wait ()<br />

{<br />

// unsigned char cnt1,cnt2,cnt3; // does not work with -O2 and -O3<br />

// volatile unsigned char cnt1,cnt2,cnt3;<br />

register cnt1,cnt2,cnt3;<br />

for (cnt1=100;cnt1;cnt1--)<br />

for (cnt2=100;cnt2;cnt2--)<br />

for (cnt3=100;cnt3;cnt3--);<br />

}<br />

#define led_DDR DDRB // LED<br />

#define led_PORT PORTB<br />

#define led_PIN PINB<br />

#define led_PB PB5<br />

main()<br />

{<br />

led_DDR |= 1


KAPITEL 13. AUFBAU DES SYSTEMS 165<br />

An dieser Stelle sei erwähnt, daß der Aufruf des gcc eigentlich<br />

mehrere Programme aktiviert:<br />

cpp Der C-Preprozessor bearbeitet alle Zeilen, die <strong>mit</strong> dem<br />

Zeichen # beginnen.<br />

cc Der C-Compiler übersetzt die Sprache C in Assembler.<br />

as Der Assembler übersetzt in relokativen Maschinencode.<br />

Relokativer Code kennt noch keine feste Adresse.<br />

ld Der Linker verbindet eine oder mehrere Objektdateien<br />

(Ausgaben des Assemblers) <strong>mit</strong> den Programmen des<br />

Runtimes zu einem fertigen Maschinenprogramm.<br />

Mit dem Disassembler kann man sehr gut die Erweiterungen<br />

des Programmes durch Teile des Runtime-Pakets erkennen.<br />

In diesem Fall entspricht das der Initialisierung der Interrupt-<br />

Vektoren und der Initalisierung des Arbeitsspeichers.<br />

Interessant sind auch die Optimierungsstufen des Compilers.<br />

Werden die drei Variablen der Funktion wait nicht als register<br />

bzw volatile deklariert, so werden die Schleifen in den<br />

Optimierungsstufen -O2 und -O3 wegoptimiert. Der Compiler<br />

erkennt, dass <strong>mit</strong> den Variablen nichts mehr passiert und<br />

die Schleifen nur Zeit verschwenden und entfernt diese! Aus<br />

diesem Grund sollte man Optimierung erst am Ende der Programmentwicklung<br />

einsetzen.


KAPITEL 13. AUFBAU DES SYSTEMS 166<br />

C Version <strong>mit</strong> Interrupt<br />

Nachdem bisher sehr einfache Programmversionen betrachtet<br />

wurden, um verschiedene Programmiertechniken zu demonstrieren,<br />

soll hier eine Lösung gezeigt werden, die die Möglichkeiten<br />

des Ein-/Ausgabewerks des Mikrocontrollers mehr ausnutzt<br />

und so dem Programm Vorteile verschafft.<br />

//<br />

// Program: led.c<br />

// Funktion: program-sample for c: blinking led, interrupt version<br />

// History: 20031204 HKU creation<br />

//<br />

#include <br />

#include <br />

#define CLOCK 1000000 //7372800 // Hz<br />

#define TIMERCLK 50 // Hz<br />

#define CLOCKSRC0 5 /* CK1024 */<br />

#define CLOCKCNT0 -(CLOCK/1024/TIMERCLK-256)<br />

/* 1024


KAPITEL 13. AUFBAU DES SYSTEMS 167<br />

sei();<br />

for (;;) {<br />

led_PORT |= 1


KAPITEL 13. AUFBAU DES SYSTEMS 168<br />

Ein Nachteil des Verfahrens sei nicht verschwiegen. Die Fehlersuche<br />

in Programmen <strong>mit</strong> Interrupts kann sehr aufwändig<br />

sein, da das Programm nicht mehr Schritt für Schritt abläuft.<br />

Das Prinzip des early testings ist unbedingt anzuwenden. Als<br />

Anfänger sollte man sich Interrupts sehr vorsichtig zuwenden.<br />

Vertiefung: Frequenz des internen RC-Oszillator des Mikrocontrollers<br />

<strong>mit</strong> der Spannungsversorgung des Centronics-<br />

Interfaces (ca. 3 V) ausmessen.<br />

13.4.4 Netzteil<br />

Die Stromversorgung über die Centronics-Schnittstelle schafft<br />

nur wenige Milliampere und wenig mehr als 3 Volt. Schon der<br />

Pegelwandler der RS232-Schnittstelle fordert mehr. Eine externe<br />

Stromversorgung ist deshalb die nächste Baustufe. Besitzer<br />

eines Labornetzteils können darauf natürlich verzichten.<br />

( ) Stl2:Stiftleiste 1polig :einlöten (j56)<br />

( ) :Printbuchse 2.1mm :einlöten<br />

( ) R13 :Widerstand 10k Ohm :liegend einlöten (r56) (n56)<br />

( ) R14 :Widerstand 100kOhm :liegend einlöten (l57) (h57)<br />

( ) D2 :Diode 1N4001 :Anode in r58 einlöten (r58) (o58)<br />

( ) D3 :Diode 1N4001 :Anode in o59 einlöten (r59) (o59)<br />

( ) D4 :Diode 1N4001 :Anode in o60 einlöten (r60) (o60)<br />

( ) D5 :Diode 1N4001 :Anode in r61 einlöten (r61) (o61)<br />

( ) D6 :Diode BAT 43 :Anode in g58 einlöten (g56) (g58)<br />

( ) D7 :Diode BAT 43 :Anode in j60 einlöten (j60) (j62)<br />

( ) Tr1 :BC 547 B :flache Seite n. innen einlöten (m56) (m57)<br />

( ) IC1 :Spannungregler 78L05 :flache Seite n. aussen einlöten (j59) (i59)<br />

( ) C10 :Kondensator 10 uF :+ in g59 einlöten (g59) (g60)<br />

( ) C11 :Kondensator 100 uF 25V :+ in m59 einlöten (m59) (m60)<br />

( ) C12 :Kondensator 10 nF :einlöten (s55) (s56)<br />

Vor dem Einsetzen der Printbuchse werden die äußeren Anschlussfahnen<br />

verkürzt, da<strong>mit</strong> sie als Lötflächen für Anschlußdrähte<br />

dienen können. Für die innere Anschlußfahne muss <strong>mit</strong>


KAPITEL 13. AUFBAU DES SYSTEMS 169<br />

der Laubsäge ein 2,54 mm langer Schlitz in die Platine gesägt<br />

werden.<br />

Das Netzteil ist so ausgelegt, dass es <strong>mit</strong> vielen Steckernetzteilen<br />

zusammen funktioniert. Passt der Stecker, ist nur der<br />

unwahrscheinliche Fall, dass die Spannung zu niedrig oder zu<br />

hoch ist, an den Daten im Anhang B zu prüfen.<br />

Vor der ersten Inbetriebnahme entfernt man den Mikrocontroller.<br />

Vor dem erneuten Einsetzen wird die Funktion des<br />

Netzteils <strong>mit</strong> dem Multimeter geprüft. Die Gleichspannung<br />

muss nahe 5 Volt, die Wechselspannung nahe 0 Volt liegen.<br />

Andernfalls ist die Polung und Funktion aller Bauteile zu kontrollieren.<br />

Vertiefung: Frequenz des RC-Oszillator bei 5 V bestimmen.<br />

13.4.5 Oszillator<br />

Der Prozessor kann auf mehrere Möglichkeiten getaktet werden.<br />

Die internen Register und Speicher benötigen keinen<br />

Takt, um ihren Inhalt zu erhalten. Man nennt derartige Speicher<br />

statisch, im Gegensatz zu dynamisch. Statische Speicher<br />

sind ungefähr um das vierfache aufwändiger als dynamische<br />

Speicher! Aus diesem Grund kann der Prozessor unterhalb der<br />

oberen Grenze <strong>mit</strong> jeder Taktfrequenz versorgt werden. Das<br />

Experimentiersystem wurde <strong>mit</strong> einem Sockel für den Oszillator<br />

ausgestattet, um alle Möglichkeiten offen zu lassen.<br />

Zusätzlich kann der Prozesser durch eine von vier verschiedenen<br />

Techniken <strong>mit</strong> Takt versorgt werden. Die jeweilige Be-


KAPITEL 13. AUFBAU DES SYSTEMS 170<br />

triebsart wird durch Einstellen der Fuses <strong>mit</strong> dem Programm<br />

avrdude ausgewählt.<br />

Interner RC-Oszillator<br />

Der interne RC-Oszillator kann auf 1, 2, 4 oder 8 Mhz eingestellt<br />

werden. Fabrikneue ICs sind auf 1 Mhz voreingestellt.<br />

Diese Variante benötigt keine weiteren Bauteile. Die beiden<br />

freien Anschlüsse können als zusätzliche I/O-Ports genutzt<br />

werden. Leider schwingen RC-Oszillatoren recht ungenau, so<br />

dass zeitkritische Anwendungen, wie z.B. asynchrone serielle<br />

Datenübertragungen einen stabileren Takt erfordern.<br />

Externer RC-Oszillator<br />

Diese Variante macht dann Sinn, wenn die verfügbaren internen<br />

Frequenzen nicht passen.<br />

Externer Quarz<br />

Die gebräuchlichste Variante für zeitlich genaue Anwendungen.<br />

Im Abschnitt 10.2 wurde der Aufbau des Quarzmoduls<br />

als Beispiel vorweggenommen.<br />

Externes Oszillator-IC<br />

Die Lösung besteht aus nur einem Bauteil. Es ist aber teuerer<br />

als die Summe der Teile des selbst gelöteten Quarz-Moduls.<br />

Dafür sind Quarzoszillatoren präzise abgestimmt.


KAPITEL 13. AUFBAU DES SYSTEMS 171<br />

13.4.6 RS232 Schnittstelle<br />

Die relativ einfache Erweiterung unseres Mikrocontrollers um<br />

eine RS232 Schnittstelle schafft neue Möglichkeiten. Nicht nur<br />

für Anwendungen, auch beim Testen und bei der Fehlersuche<br />

gibt es Einsatzgebiete.<br />

( ) Pfo1:Steckerlisten 2x5 90Grad :einlöten (d6)<br />

( ) So4 :DIL-16 Präzisions-Sockel :einlöten (e8)<br />

( ) C4 :Kondensator 100 nF :einlöten (i8) (i9)<br />

( ) C5 :Tantal-Kondensator 1 uF :+ in j12 einlöten (j11) (j12)<br />

( ) C6 :Tantal-Kondensator 1 uF :+ in j13 einlöten (j13) (j14)<br />

( ) C7 :Tantal-Kondensator 1 uF :+ in c9 einlöten (c9) (c10)<br />

( ) C8 :Tantal-Kondensator 1 uF :+ in c11 einlöten (c11) (c12)<br />

( ) Kl3 :Kupferlackdraht 0.2mm :einlöten (e5) (f7)<br />

( ) Kl4 :Kupferlackdraht 0.2mm :einlöten (f5) (g7)<br />

( ) Kl5 :Kupferlackdraht 0.2mm :einlöten (j12) (f9)<br />

( ) Kl6 :Kupferlackdraht 0.2mm :einlöten (i14) (e13)<br />

( ) IC3 :MAX (3)232 N :Pin1 in e8 einsetzen<br />

Abbildung 13.14: Adapter


KAPITEL 13. AUFBAU DES SYSTEMS 172<br />

Als Kabel wird das gleiche 10-adrige Flachbandkabel wie für<br />

die ISP-Schnittstelle verwendet. Zwischen Pfostenbuchse und<br />

RS232-Stecker des PC muss ein selbst gelöteter Adapter eingesetzt<br />

werden: Pin 1 eines Pfostensteckers wird <strong>mit</strong> der Zange<br />

entfernt. Auf der Lötseite des Pfostensteckers werden die restlichen<br />

4 Pins der Reihe etwas in die Richtung des ehemaligen<br />

Pin 1 gebogen. Pin 1 bis Pin 5 einer DB9-Buchse werden <strong>mit</strong><br />

der fünf Pin Reihe des Pfostensteckers verlötet. Die gebogene<br />

vier Pin Reihe wird <strong>mit</strong> den restlichen Pins 6 bis 9 verlötet.<br />

Das Foto der Abbildung 13.14 macht das deutlich.<br />

Falls der Mikrocontroller noch <strong>mit</strong> internem RC-Oszillator arbeitet,<br />

muss ein <strong>mit</strong> Quarz stabilisierter Oszillator eingesetzt<br />

werden. Falls ein IC eingesetzt wird, muss man darauf achten,<br />

dass der Pin 1 anders ausgerichtet ist als bei der CPU! Für<br />

den Betrieb <strong>mit</strong> RS232 eignet sich die Frequenz 7372800 Hz<br />

am besten. Mit dem Programm avrdude werden die Fuses des<br />

Mikrocontrollers so eingestellt, dass er ohne internen Oszillator<br />

arbeitet:<br />

avrdude -c usbasp -p atmega48 -U lfuse:w:0xdc:m<br />

Vertiefung: Man analysiere den Befehl <strong>mit</strong> Hilfe des Datenblatts.<br />

Mit dieser Erweiterung ist das System so weit, Texte auszugeben.<br />

Als Anzeige verwenden wir ein Terminal. Terminals<br />

sind Ein-/Ausgabegeräte für Großrechner. Sie bestehen<br />

aus einer Tastatur, einem Textbildschirm und einer RS232-<br />

Schnittstelle. Eingaben auf der Tastatur gehen zur RS232.


KAPITEL 13. AUFBAU DES SYSTEMS 173<br />

Werden von der RS232 Daten empfangen, werden sie auf<br />

dem Bildschirm angezeigt. Schon lange sind PCs wegen ihrer<br />

großen Verbreitung preiswerter als reine Terminals. Die<br />

Programme, die Terminals simulieren, nennt man Terminalemulationen.<br />

Eine verbreitete Terminalemulation für Linux ist<br />

minicom.<br />

Die Einstellungen des Terminals können im Programm per<br />

Dialog durchgeführt werden. Die Datei $HOME/.minirc.dfl<br />

speichert die Werte für weitere Programmaufrufe:<br />

# Machine-generated file - use setup menu in minicom to change parameters.<br />

pu port /dev/ttyS1<br />

pu baudrate 2400<br />

pu bits 8<br />

pu parity N<br />

pu stopbits 1<br />

Natürlich muss auch der Treiber für serielle Schnittstellen im<br />

Kernel eingebunden sein.<br />

Ein Programm zur Ausgabe eines Textes ist schnell geschrieben:<br />

/*<br />

** Name: software/hello/hello_uart.c<br />

** Funktion: display "hello, world"<br />

** History: 20060405 Hanns-Konrad Unger creation<br />

*/<br />

#include <br />

#define putbyte_clock Clock<br />

#define putbyte_baud 2400<br />

#define putbyte_DDR DDRD<br />

#define putbyte_PORT PORTD<br />

#define putbyte_PIN PIND<br />

#define putbyte_PB PD1<br />

#include "../include/mainboard.h"<br />

#include "../include/putbyte_uart.c" // uses uart


KAPITEL 13. AUFBAU DES SYSTEMS 174<br />

void putstring (unsigned char * ptr) {while (*ptr) putbyte (*ptr++);}<br />

main () {<br />

putbyte_init();<br />

putstring ("\f* Hello World! *\r\n");<br />

putstring ("================\r\n");<br />

}<br />

Die Funktion putstring() ruft die Funktion putbyte() solange<br />

auf, bis der String durch eine Null beendet wird. Diese elegante<br />

C-Lösung eignet sich nur für Fälle, bei denen man sicher<br />

ist, keine Null ausgeben zu müssen. Terminals verwenden die<br />

binäre Null in der Regel nicht. Für die Funktion putbyte()<br />

<strong>mit</strong> der zugehörigen Funktion putbyte init() sollen jetzt drei<br />

Lösungsvarianten gezeigt werden:<br />

RS232 Ausgabe <strong>mit</strong> UART<br />

//<br />

// Name: software/include/putbyte_uart.c<br />

// Function: AVR serial putbyte over UART<br />

// History: 20030213 Hanns-Konrad Unger creation<br />

// Usage: #define putbyte_clock 6553600 /* frequence of system-clock */<br />

// #define putbyte_baud 38400 /* baud-rate */<br />

//<br />

// #include "putbyte_uart.c"<br />

// putbyte_init();<br />

// putbyte (’\n’);<br />

//<br />

#ifndef putbyte_uart_c<br />

#define putbyte_uart_c<br />

#include <br />

#include "mainboard.h"<br />

// at90s4433: UBRR=(putbyte_clock/putbyte_baud/16-1);<br />

#ifdef __AVR_ATmega8__<br />

#define putbyte_T 16<br />

#else // ATmega48 ...<br />

#define putbyte_T 16<br />

#endif<br />

#define putbyte_init()\


KAPITEL 13. AUFBAU DES SYSTEMS 175<br />

UBRR0H = (putbyte_clock/putbyte_baud/putbyte_T-1)>>8;\<br />

UBRR0L = (putbyte_clock/putbyte_baud/putbyte_T-1);\<br />

sbi (UCSR0B,TXEN0);<br />

// UCSRC = (1


KAPITEL 13. AUFBAU DES SYSTEMS 176<br />

#ifndef putbyte_port_c<br />

#define putbyte_port_c<br />

#include "mainboard.h"<br />

#define putbyte_init() sbi (putbyte_DDR, putbyte_PB);\<br />

sbi (putbyte_PORT,putbyte_PB)<br />

void putbyte (unsigned char txbyte)<br />

{<br />

char len = 1+8+1; /* startbit+databits+stopbit */<br />

char carry = 1; /* startbit */<br />

int cnt;<br />

txbyte = ~txbyte;<br />

for (;;)<br />

{<br />

if (carry) // (!carry)<br />

cbi (putbyte_PORT,putbyte_PB);<br />

else<br />

sbi (putbyte_PORT,putbyte_PB);<br />

cnt=putbyte_clock/putbyte_baud/4-4;<br />

#ifdef O0<br />

asm ("loop4cycl: subi r24,1"); /* subtract constant 1 */<br />

asm (" sbci r25,0"); /* compute carrybit */<br />

asm (" brne loop4cycl");<br />

#else<br />

#ifdef O1<br />

while (--cnt);<br />

#else<br />

#error Use "gcc -O1 -DO1 ..." to compile while (--cnt);<br />

#endif<br />

#endif<br />

if (! --len) break;<br />

carry = txbyte % 2;<br />

txbyte /= 2;<br />

}<br />

}<br />

#endif<br />

Die Geschwindigkeit der Übertragung, Baudrate 2 genannt,<br />

wird durch eine Zählschleife beeinflußt. Wie wir schon gesehen<br />

haben, sind Zählschleifen vom Grad der Optimierung<br />

abhängig. Deshalb muss für verschiedene Optimierungsstufen<br />

ein unterschiedlicher Code erzeugt werden.<br />

2 Die Einheit Baud für Impulse pro Sekunde erinnert an den französi-<br />

chen Erfinder Baudot.


KAPITEL 13. AUFBAU DES SYSTEMS 177<br />

Nebenbei kann man das Programm als Definition der Bit-<br />

Übertragungs-Schicht von RS232 ansehen. Sinnvoll einsetzen<br />

kann man das Programm auf den kleineren AVR <strong>Mikrocontrollern</strong>,<br />

die noch keinen UART besitzen.<br />

RS232 Ausgabe <strong>mit</strong> UART und Interrupt<br />

//<br />

// Name: software/include/putbyte_buff.c<br />

// Function: AVR serial putbyte over UART using interrupt<br />

// History: 20031208 Hanns-Konrad Unger creation<br />

// Usage: #define putbyte_clock 6553600 /* frequence of system-clock */<br />

// #define putbyte_baud 38400 /* baud-rate */<br />

//<br />

// #include "putbyte_buff.c"<br />

// putbyte_init();<br />

// putbyte (’\n’);<br />

//<br />

#ifndef putbyte_buff_c<br />

#define putbyte_buff_c<br />

#include "mainboard.h"<br />

#include <br />

#include <br />

// AT90s4433: UBRR = (putbyte_clock/putbyte_baud/16-1);<br />

#define putbyte_init()\<br />

UBRRH = (putbyte_clock/putbyte_baud/16-1)>>8;\<br />

UBRRL = (putbyte_clock/putbyte_baud/16-1);\<br />

sbi (UCSRB,TXEN);\<br />

sei();<br />

// UCSRC = (1


KAPITEL 13. AUFBAU DES SYSTEMS 178<br />

cbi (UCSRB,UDRIE);<br />

}<br />

void putbyte (unsigned char txbyte)<br />

{<br />

while (putbyte_buffil >= putbyte_buflen) asm ("sleep");<br />

cbi (UCSRB,UDRIE);<br />

putbyte_buffer[putbyte_bufput]=txbyte;<br />

putbyte_bufinc(putbyte_bufput);<br />

putbyte_buffil++;<br />

sbi (UCSRB,UDRIE);<br />

}<br />

#endif<br />

Diese Version nutzt die Hardware in vollem Umfang aus.<br />

Zwar werden nicht wenig Programmworte verbraucht, zusätzlich<br />

benötigt das Programm auch noch einen Ringpuffer im<br />

wertvollen Schreib-/Lesespeicher, dafür ist der Bedarf an Rechenzeit<br />

minimal. Beim Aufruf von putbyte init() muss man<br />

berücksichtigen, dass der Interrupt frei geschaltet wird! So<br />

lange der Ringpuffer belegt ist, legt sich die CPU schlafen.<br />

Nachdem das Senden über die RS232-Schnittstelle funktioniert,<br />

ist das Empfangen nicht mehr schwer. Als Hauptprogramm<br />

erstellen wir ein Echo, das empfangene Zeichen einfach<br />

wieder zurückschickt:<br />

/*<br />

** Name: software/rs232/rs232.c<br />

** Funktion: echos keyboard<br />

** History: 20031223 Hanns-Konrad Unger creation<br />

*/<br />

#include <br />

#define putbyte_clock Clock<br />

#define putbyte_baud 2400<br />

#include "../include/putbyte_uart.c" // uses uart<br />

//#include "../include/putbyte_buff.c" // uses uart with interrupt<br />

//#include "../include/putbyte_disp.c" // uses lcd-display<br />

#define getbyte_clock putbyte_clock


KAPITEL 13. AUFBAU DES SYSTEMS 179<br />

#define getbyte_baud putbyte_baud<br />

#include "../include/getbyte_uart.c" // uses uart<br />

//#include "../include/getbyte_buff.c" // uses uart with interrupt<br />

main ()<br />

{<br />

putbyte_init();<br />

getbyte_init();<br />

for (;;)<br />

if (getbyte_ready()) // verhindert, dass getbyte() blockiert<br />

putbyte(getbyte());<br />

}<br />

Wird dies Programm im Mikrocontroller aktiviert und <strong>mit</strong> der<br />

Terminalemulation auf dem PC verbunden, so werden Tastatureingaben<br />

am PC über den Mikrocontroller auf den Bildschirm<br />

der Emulation gebracht.<br />

Die Abfrage von getbyte ready() ist eigentlich nicht notwendig.<br />

In aufwändigeren Programmen wird so verhindert, dass<br />

die Funktion getbyte() blockiert.<br />

Wie beim Hallo-Beispiel gibt es verschiedene Möglichkeiten,<br />

die Funtion des UART zu realisieren:<br />

RS232 Eingabe <strong>mit</strong> UART<br />

//<br />

// Name: software/include/getbyte_uart.c<br />

// Function: AVR serial getbyte over UART<br />

// History: 20031223 Hanns-Konrad Unger creation<br />

// Usage: #define getbyte_clock 6553600 /* frequence of system-clock */<br />

// #define getbyte_baud 38400 /* baud-rate */<br />

//<br />

// #include "getbyte_uart.c"<br />

// getbyte_init();<br />

// if (getbyte_ready()) c=getbyte ();<br />

//<br />

#ifndef getbyte_uart_c<br />

#define getbyte_uart_c<br />

#ifdef __AVR_ATmega8__


KAPITEL 13. AUFBAU DES SYSTEMS 180<br />

#define getbyte_T 16<br />

#else // ATmega48 ...<br />

#define getbyte_T 16<br />

#endif<br />

#define getbyte_init()\<br />

UBRR0H = (getbyte_clock/getbyte_baud/getbyte_T-1)>>8;\<br />

UBRR0L = (getbyte_clock/getbyte_baud/getbyte_T-1);\<br />

sbi (UCSR0B,RXEN0);<br />

#define getbyte_ready() bit_is_set(UCSR0A,RXC0)<br />

unsigned char getbyte () {<br />

loop_until_bit_is_set (UCSR0A,RXC0);<br />

return UDR0;<br />

}<br />

#endif<br />

Auf die Initilisierung von UBRR kann eventuell verzichtet<br />

werden, da sie ja auch von putbyte init() erledigt wird. Dann<br />

bleiben nur sechs Worte Programmcode übrig.<br />

RS232 Eingabe <strong>mit</strong> UART und Interrupt<br />

//<br />

// Name: software/include/getbyte_buff.c<br />

// Function: AVR serial getbyte over UART using interrupt<br />

// History: 20031223 Hanns-Konrad Unger creation<br />

// Usage: #define getbyte_clock 6553600 /* frequence of system-clock */<br />

// #define getbyte_baud 38400 /* baud-rate */<br />

//<br />

// #include "getbyte_buff.c"<br />

// getbyte_init();<br />

// if (getbyte_ready()) c=getbyte();<br />

//<br />

#ifndef getbyte_buff_c<br />

#define getbyte_buff_c<br />

#include <br />

#include <br />

#define getbyte_init()\<br />

UBRRH = (getbyte_clock/getbyte_baud/16-1)>>8;\<br />

UBRRL = (getbyte_clock/getbyte_baud/16-1);\<br />

sbi (UCSRB,RXEN);\<br />

sbi (UCSRB,RXCIE);\<br />

sei();<br />

#define getbyte_bufinc(x) (((x)==getbyte_buflen-1)?((x)=0):((x)+=1))


KAPITEL 13. AUFBAU DES SYSTEMS 181<br />

#define getbyte_buflen 2<br />

static unsigned char getbyte_buffer[getbyte_buflen];<br />

static volatile unsigned char getbyte_bufget = 0;<br />

static volatile unsigned char getbyte_bufput = 0;<br />

volatile unsigned char getbyte_buffil = 0;<br />

#define getbyte_ready() getbyte_buffil<br />

SIGNAL (SIG_UART_RECV)<br />

{<br />

getbyte_buffer[getbyte_bufget]=UDR;<br />

getbyte_bufinc(getbyte_bufget);<br />

if ((++getbyte_buffil)>getbyte_buflen)<br />

getbyte_buffil=getbyte_buflen; // buffer-overrun<br />

}<br />

unsigned char getbyte ()<br />

{<br />

unsigned char c;<br />

while (!getbyte_buffil) asm ("sleep");<br />

cbi (UCSRB,RXCIE); //disabel interrupt SIG_UART_RECV<br />

c=getbyte_buffer[getbyte_bufput];<br />

getbyte_bufinc(getbyte_bufput);<br />

getbyte_buffil--;<br />

sbi (UCSRB,RXCIE);<br />

return c;<br />

}<br />

#endif<br />

Auch diese Version ist aufwändiger als die ohne Interrupt.<br />

Ob sie überhaupt Vorteile bringt, hängt von einer Analyse<br />

der gesamten Anwendung ab. Werden ohne Interrupt Zeichen<br />

verloren, kann diese Version <strong>mit</strong> ausreichend großem Puffer<br />

Abhilfe schaffen. Letztendlich sollte aber auch die Implementierung<br />

eines Hardware-Handshake <strong>mit</strong> CTS und RTS in Betracht<br />

gezogen werden.<br />

RS232 Eingabe ohne UART<br />

Diese Möglichkeit macht dann Sinn, wenn keine UART-<br />

Hardware vorhanden ist. Die Funktion getbyte ready() ist<br />

nicht verfügbar. Nach Entdecken der Flanke des Startbits wird


KAPITEL 13. AUFBAU DES SYSTEMS 182<br />

der halbe Sendezeitraum eines Bits abgewartet. Dann wird die<br />

empfangende Leitung Bit für Bit gelesen und in ein Ergebnisbyte<br />

geschoben. Das Prinzip entspricht dem Sendeprogramm.<br />

Bei der Zeitschleife muss wieder auf die Art der Optimierung<br />

geachtet werden!<br />

Vertiefung: Implementierung des Programms.<br />

Fehler und Fehlersuche<br />

Die Erfahrung zeigt, dass neu geschriebene Programme fehlerhaft<br />

sind. Sehr grob gesagt, besteht ein Programm zu je einem<br />

Viertel aus Planung, Programmierung, Fehlersuche und<br />

Wartung. Die effektivste Methode gegen Fehler heißt ,,early<br />

testing.” Man strebt möglichst kleine Zwischenschritte an,<br />

nach deren Erreichen der neue Programmcode getestet wird.<br />

Da der Fehler <strong>mit</strong> hoher Wahrscheinlichkeit in dem neuen<br />

Programmstück ist, dieses aber klein gehalten wurde, kann er<br />

auch leicht gefunden werden.<br />

Für die Fehlersuche gibt es Werkzeuge verschiedener Art und<br />

Komplexität:<br />

Eine beliebte, da einfache Methode, ist das Verändern des Programms<br />

durch zusätzliche Ausgaben. Leuchtdioden, RS2332<br />

und Display sind geeignet, zusätzliche Meldungen oder Inhalte<br />

von Variablen anzuzeigen, um Soll- und Ist-Werte zu<br />

vergleichen.<br />

Zum Beispiel zeigt das Ein- und Ausschalten einer Leuchtdiode<br />

vor und nach jedem sleep-Befehl, wie beschäftigt der


KAPITEL 13. AUFBAU DES SYSTEMS 183<br />

Mikrocontroller ist. Bewegt man die Platine hin und her,<br />

kann man an Hand der Länge der Striche sogar prozentuale<br />

Schätzungen machen.<br />

Eine etwas aufwändigere Methode ist ein Software-Debugger.<br />

Dies ist ein Programm, welches zusätzlich in den Speicher<br />

geladen wird und eine Dialogschnittstelle bietet, die Befehle<br />

zum Schreiben und Lesen der Speicher und zur Steuerung des<br />

Programmablaufs enthält. Der Vorteil gegenüber der einfachen<br />

Methode ist, dass <strong>mit</strong> einer Programmänderung mehrere<br />

Messungen durchgeführt werden können.<br />

Zuletzt sei noch das aufwändigste Verfahren, der Hardware-<br />

Debugger, erwähnt. Dieses Werkzeug bietet auch ohne Programmänderungen<br />

die Möglichkeit, Messungen vorzunehmen,<br />

idealer Weise sogar unter Echtzeitbedingungen. Früher waren<br />

dafür teure Laborinstrumente notwendig. Die neueren<br />

Prozessoren von Atmel enthalten auf dem Chip Möglichkeiten,<br />

auch <strong>mit</strong> preiswerten Einrichtungen Messungen durchzuführen<br />

(JTEG-Interface, one wire debugging interface).<br />

Hierzu wird ein ICE (in circuit emulator) angeboten.<br />

Software Debugger<br />

Die typische Fehlersuche in einem Programm durchläuft folgende<br />

Schleife:<br />

• Verdächtige Stelle des Programms suchen.


KAPITEL 13. AUFBAU DES SYSTEMS 184<br />

• Sollwert der Variablen an der Stelle des Programms berechnen.<br />

• Programm an der Stelle anhalten.<br />

• Istwert der Variablen bestimmen.<br />

• Differenz von Soll- und Istwert interpretieren.<br />

Der Vergleich von Soll- und Istwert bestätigt oder widerlegt<br />

die Überlegungen, was die Fehlersuche in die Richtung<br />

des Fehlers bewegt. Eine schwierige Situation kann entstehen,<br />

wenn ein Fehlersymptom tatsächlich zwei Ursachen hat. An<br />

diesen Fall sollte man sich erinnern, wenn die Fehlersuche irgendwie<br />

absonderlich wird.<br />

Unser bekanntes Programm dient wieder als Beispiel. Die Pfeile<br />

deuten auf die notwendigen Ergänzungen hin.<br />

/*<br />

** Name: software/debug/main.c<br />

** Funktion: test-main for software-debugger<br />

** History: 20040124 Hanns-Konrad Unger creation<br />

*/<br />

#include "putbyte_uart.c"<br />

#include "../include/debug.c"<br />

char * help_debug_ptr;<br />

static void putstring (unsigned char * ptr) {<br />

help_debug_ptr=ptr;<br />

debug();<br />

while (*ptr) putbyte (*ptr++);}<br />

main() {<br />

debug_init();<br />

for (;;) {<br />

putstring ("* Hello World! *\r\n");<br />

putstring ("================\r\n");<br />

}<br />

}


KAPITEL 13. AUFBAU DES SYSTEMS 185<br />

Vor der Ausgabe des Strings kann der Zustand des Speichers<br />

<strong>mit</strong> der Funktion debug(); begutachtet werden. Die<br />

Zeile #include ’’debug.c’’ stellt den notwendigen Programmcode<br />

zur Verfügung. Etwas mehr als 0.5 KB werden<br />

gebraucht. Für die Initialisierung der seriellen Schnittstelle<br />

sorgt sich das Makro debug init();. Prinzipell wären diese<br />

drei zusätzlichen Zeilen ausreichend. Da die lokale Variable ptr<br />

auf dem Stack steht, debug() jedoch selbst den Stack erweitert,<br />

ist ein Suchen von ptr kompliziert. Die statische Variable<br />

help debug ptr vereinfacht das Verfahren.<br />

Bedienung der Funktion debug()<br />

Befehl Syntax Semantik<br />

read memory rm addr [leng] display leng bytes<br />

write memory wm addr byte *addr = byte<br />

read eeprom re addr [leng] display leng bytes<br />

write eeprom we addr byte *addr = byte<br />

read program rp addr [leng] display leng bytes<br />

continue c return from debug()<br />

Mit dem Befehl make disasm wird der Programmcode untersucht:<br />

00000202 :<br />

202: cf 93 push r28<br />

204: df 93 push r29<br />

206: ec 01 movw r28, r24<br />

208: 90 93 88 00 sts 0x0088, r25<br />

20c: 80 93 87 00 sts 0x0087, r24<br />

210: 8b df rcall .-234 ; 0x128<br />

212: 88 81 ld r24, Y<br />

214: 88 23 and r24, r24<br />

216: 29 f0 breq .+10 ; 0x222<br />

218: 89 91 ld r24, Y+


KAPITEL 13. AUFBAU DES SYSTEMS 186<br />

21a: 20 df rcall .-448 ; 0x5c<br />

21c: 88 81 ld r24, Y<br />

21e: 88 23 and r24, r24<br />

220: d9 f7 brne .-10 ; 0x218<br />

222: df 91 pop r29<br />

224: cf 91 pop r28<br />

226: 08 95 ret<br />

Als Beispiel dient folgende debugging-Sitzung:<br />

c<br />

* Hello World! *<br />

c<br />

================<br />

rm 87 2=60 00<br />

rm 060 10=2A 20 48 65 6C 6C 6F 20 57 6F 72 6C 64 21 20 2A<br />

rm 070 10=0D 0A 00 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D 3D<br />

rm 080 10=3D 3D 3D 0D 0A 00 0D 60 00 8E 2D 0A EF 0F 82 80<br />

rm 5d 2=54 04<br />

rm 450 10=6C 8D 51 00 C8 00 60 00 08 81 01 09 04 5F 01 22<br />

Die Variable help debug ptr (0x87) zeigt erwartungsgemäß<br />

auf den auszugebenden String. Leider sind die auf dem Stack<br />

gespeicherten Rücksprungadressen schwer erkennbar, da sie<br />

um ein Bit nach rechts verschoben sind (0122 ist 0244 kommt<br />

von main, 0109 ist 0212 kommt von putstring). Der letzte auf<br />

dem Stack gespeicherte Wert ist die Variable ptr.<br />

Eine weitere Variante bei der Fehlersuche ist das Ausschalten<br />

der Optimierung des Compilers. Dadurch wird der erzeugte<br />

Code verständlicher.<br />

Mit dem Befehl spm könnte man den Programmspeicher<br />

ändern, um weitere Aufrufe der Funktion debug() an variablen<br />

Stellen zu hinterlegen. Der Befehl funktioniert aber nur<br />

im oberen Bereich des Programmspeichers, der sogenannten<br />

boot-section, was weitergehende Maßnahmen erfordert.


KAPITEL 13. AUFBAU DES SYSTEMS 187<br />

Vertiefung: Die Register des Ein-/Ausgabewerks werden<br />

zusätzlich in den Datenspeicher zwischen die Adressen 0x20<br />

.. 0x5F gespiegelt. Mit dem wm-Befehl des Debuggers kann<br />

man die Leuchtdioden schalten usw...<br />

Uhr<br />

Das nächste Projekt soll eine Uhr sein. Die Quelle des Programms<br />

kann folgendermaßen aussehen:<br />

/*<br />

** Name: software/clock/clock.c<br />

** Funktion: simple clock<br />

** History: 20040112 Hanns-Konrad Unger creation<br />

** 20061010 Hanns-Konrad Unger 32.768KHz<br />

*/<br />

#include <br />

#include <br />

#if Clock > 13107200<br />

#error Clock zu groß<br />

#endif<br />

#if Clock == 32768<br />

#define Timerclk 8<br />

#define PRECISION 64<br />

#define CLOCKSRC0 3<br />

#define CLOCKPERI 64<br />

#else<br />

#define Timerclk 50<br />

#define PRECISION 100<br />

#define CLOCKSRC0 5<br />

#define CLOCKPERI 1024<br />

#endif<br />

#define putbyte_clock Clock<br />

#define putbyte_baud 19200<br />

#define putbyte_DDR DDRD<br />

#define putbyte_PORT PORTD<br />

#define putbyte_PIN PIND<br />

#define putbyte_PB PD1<br />

//#include "putbyte_port.c" // uses I/O-port<br />

//#include "putbyte_uart.c" // uses uart<br />

//#include "putbyte_buff.c" // uses uart with interrupt


KAPITEL 13. AUFBAU DES SYSTEMS 188<br />

#define putbyte_drsDDR DDRB<br />

#define putbyte_drsPORT PORTB<br />

#define putbyte_drsPB PB0<br />

#define putbyte_drwDDR DDRD<br />

#define putbyte_drwPORT PORTD<br />

#define putbyte_drwPB PD7<br />

#define putbyte_deDDR DDRD<br />

#define putbyte_dePORT PORTD<br />

#define putbyte_dePB PD6<br />

#define putbyte_dd4DDR DDRD<br />

#define putbyte_dd4PORT PORTD<br />

#define putbyte_dd4PB PD5<br />

#define putbyte_dd5DDR DDRD<br />

#define putbyte_dd5PORT PORTD<br />

#define putbyte_dd5PB PD4<br />

#define putbyte_dd6DDR DDRD<br />

#define putbyte_dd6PORT PORTD<br />

#define putbyte_dd6PB PD3<br />

#define putbyte_dd7DDR DDRD<br />

#define putbyte_dd7PORT PORTD<br />

#define putbyte_dd7PB PD2<br />

#include "putbyte_disp.c" // uses lcd-display<br />

void putstring (unsigned char * ptr)<br />

{<br />

while (*ptr) putbyte (*ptr++);<br />

}<br />

#define CLOCKCNT0 -(Clock/CLOCKPERI/Timerclk-256)<br />

/* 1024


KAPITEL 13. AUFBAU DES SYSTEMS 189<br />

#define tas2_PB PC4<br />

#define tas3_DDR DDRC<br />

#define tas3_PORT PORTC<br />

#define tas3_PIN PINC<br />

#define tas3_PB PC3<br />

#define tas4_DDR DDRC<br />

#define tas4_PORT PORTC<br />

#define tas4_PIN PINC<br />

#define tas4_PB PC2<br />

#define taster_init() cbi (tas2_DDR,tas2_PB);\<br />

sbi (tas2_PORT,tas2_PB);\<br />

cbi (tas3_DDR,tas3_PB);\<br />

sbi (tas3_PORT,tas3_PB);\<br />

cbi (tas4_DDR,tas4_PB);\<br />

sbi (tas4_PORT,tas4_PB);<br />

void taster ()<br />

{<br />

if ( bit_is_clear(tas4_PIN, tas4_PB) ) uhr.second = uhr.nanosec = 0;;<br />

if ( bit_is_clear(tas3_PIN, tas3_PB) && ! uhr.nanosec ) uhr.minute++;<br />

if ( bit_is_clear(tas2_PIN, tas2_PB) && ! uhr.nanosec ) uhr.hour++;<br />

}<br />

#define Displen 16<br />

char Disp0[Displen+3] = { "\f** Clock **\n" };<br />

char Disp [Displen+2] = { "\r HH:MM:SS " };<br />

// 01234567890123456 78<br />

void displa (unsigned char i1, unsigned char i2)<br />

{Disp[i1++]=i2/10+’0’; Disp[i1]=i2%10+’0’;}<br />

void display()<br />

{<br />

static unsigned char lastval;<br />

if (uhr.nanosec < lastval ) // saves 1 mA<br />

{<br />

displa (5,uhr.hour);<br />

displa (8,uhr.minute);<br />

displa (11,uhr.second);<br />

putstring (Disp);<br />

}<br />

lastval = uhr.nanosec;<br />

}<br />

ISR ( SIG_OVERFLOW0 ) // timer0<br />

{<br />

sei();<br />

TCNT0=CLOCKCNT0;<br />

quarzuhr ();<br />

taster ();<br />

display ();<br />

}


KAPITEL 13. AUFBAU DES SYSTEMS 190<br />

main ()<br />

{<br />

TCCR0B=CLOCKSRC0;<br />

TCNT0=CLOCKCNT0;<br />

sbi (TIMSK0,TOIE0);<br />

taster_init();<br />

putbyte_init();<br />

putstring (Disp0);<br />

sei();<br />

sbi (MCUCR,SE); // enable sleep, sleepmode is default idle<br />

for (;;) {asm ("sleep");} //* 1mA sleep, will be kissed by interrupt */<br />

}<br />

Der timer0 des Ein-/Ausgabewerks wird auf 50 Hz eingestellt,<br />

kann aber auch anders eingestellt werden. Der Timer läuft<br />

synchron zum CPU-Takt. Im Programmteil, der den Interrupt<br />

des timer0 behandelt, werden die Funktionen quarzuhr() und<br />

display() aufgerufen. Die Funktion quarzuhr() führt die uhrentypische<br />

Modulo-Berechnung der Uhrzeit durch. Die Funktion<br />

display() zeigt die Uhrzeit an. Da die Uhrzeit noch nicht<br />

verstellt werden kann, ist unsere Uhr vorerst nur als Stoppuhr<br />

zu gebrauchen, es sei denn, sie wird zur Geisterstunde<br />

eingeschaltet.<br />

Wird das Netzteil <strong>mit</strong> Wechselspannung versorgt, so kann<br />

man an dem einzelnen Pfostenstecker im Netzteil ein Rechtecksignal<br />

abgreifen. Dieses Signal ist zur Netzfrequenz synchron.<br />

Man verbinde es <strong>mit</strong> der offenen Datenleitung 7 des<br />

Displays. Das Display wurde ja noch nicht eingebaut. Das<br />

Netzsignal ist so an den Eingang int0 des Mikrocontrollers<br />

angeschlossen. Die Quarzuhr kann als Netzsynchronuhr betrieben<br />

werden.<br />

Vertiefung: Programm zur Netzsynchronuhr umbauen.


KAPITEL 13. AUFBAU DES SYSTEMS 191<br />

13.4.7 Taster<br />

Um die Uhrzeit verstellen zu können, bauen wir jetzt Taster<br />

ein:<br />

( ) R3 :Widerstand 470 Ohm :liegend einlöten (z5) (z8)<br />

( ) R4 :Widerstand 470 Ohm :liegend einlöten (x5) (x8)<br />

( ) R5 :Widerstand 470 Ohm :liegend einlöten (s5) (s8)<br />

( ) R6 :Widerstand 470 Ohm :liegend einlöten (n5) (n8)<br />

( ) Tas1:Drucktaster :einlöten (C4) (z4)<br />

( ) Tas2:Drucktaster :einlöten (x4) (u4)<br />

( ) Tas3:Drucktaster :einlöten (s4) (p4)<br />

( ) Tas4:Drucktaster :einlöten (n4) (k4)<br />

Zwischen den Aufrufen von quarzuhr() und display() wird<br />

der Aufruf der Funktion taster() eingefügt. Die Ports, an denen<br />

die Taster angeschlossen sind, werden im Hauptprogramm<br />

main() durch das Makro taster init() auf Eingabe und aktivierten<br />

Pullup-Widerstand eingestellt.<br />

#define tas2_DDR DDRC<br />

#define tas2_PORT PORTC<br />

#define tas2_PIN PINC<br />

#define tas2_PB PC4<br />

#define tas3_DDR DDRC<br />

#define tas3_PORT PORTC<br />

#define tas3_PIN PINC<br />

#define tas3_PB PC3<br />

#define tas4_DDR DDRC<br />

#define tas4_PORT PORTC<br />

#define tas4_PIN PINC<br />

#define tas4_PB PC2<br />

#define taster_init() cbi (tas2_DDR,tas2_PB);\<br />

sbi (tas2_PORT,tas2_PB);\<br />

cbi (tas3_DDR,tas3_PB);\<br />

sbi (tas3_PORT,tas3_PB);\<br />

cbi (tas4_DDR,tas4_PB);\<br />

sbi (tas4_PORT,tas4_PB);<br />

void taster ()<br />

{<br />

if ( bit_is_clear(tas4_PIN, tas4_PB) ) uhr.second = uhr.nanosec = 0;;<br />

if ( bit_is_clear(tas3_PIN, tas3_PB) && ! uhr.nanosec ) uhr.minute++;<br />

if ( bit_is_clear(tas2_PIN, tas2_PB) && ! uhr.nanosec ) uhr.hour++;<br />

}


KAPITEL 13. AUFBAU DES SYSTEMS 192<br />

Der Taster4 setzt die Sekunde auf 0. Solange Taster3 gedrückt<br />

wird, werden die Minuten im Sekundentakt hochgezählt. Analog<br />

verstellt Taster2 die Stunden.<br />

13.4.8 Buzzer<br />

Da<strong>mit</strong> sich unser Mikrocontroller auch Gehör verschaffen<br />

kann, bekommt er einen Buzzer. Dies ist ein moderner billiger<br />

Ersatz für Lautsprecher. Zwischen zwei Metallfolien liegt ein<br />

Piezokristall. Unter Spannung verformt sich der Kristall. Wegen<br />

der relativ großen Fläche kann man die Verformung hören.<br />

Die Beine des Bauteils können bei manchen Ausführungen<br />

leicht abbrechen.<br />

( ) R10 :Widerstand 2k7 Ohm :liegend einlöten (p11) (p8)<br />

( ) LED4:Leuchtdioden rot 3mm 2mA :Anode in q12 einlöten (p12) (p13)<br />

( ) R2 :Widerstand 1K Ohm :liegend einlöten (t14) (t11)<br />

( ) C9 :Tantal-Kondensator 1 uF :+ in s10 einlöten (s10) (s11)<br />

( ) Tr2 :BC 547 B :flache Seite n. innen einlöten (r12) (s12)<br />

( ) Beep:Piezobeeper 12 mm :+ in l11 einlöten (l11) (n11)<br />

Um die akustischen Qualitäten dieser vorletzten Baustufe kennen<br />

zu lernen, brauchen wir ein Testprogramm. Ein Frequenzgenerator<br />

auf Basis des timer0 im Mikrocontroller kann <strong>mit</strong><br />

den Tasten umprogrammiert werden. Die erzeugte Frequenz<br />

wird auf dem Buzzer ausgegeben.<br />

/*<br />

** Name: software/generator/generator.c<br />

** Funktion: frequency generator<br />

** History: 20040113 Hanns-Konrad Unger creation<br />

*/<br />

#include


KAPITEL 13. AUFBAU DES SYSTEMS 193<br />

#include <br />

// parameter for Timer0<br />

unsigned short prescaler[6]={ 0,1,8,64,256,1024 };<br />

unsigned char psindex = 5;<br />

unsigned char tim0cnt = 144; // => 25 Hz<br />

#include "mainboard.h"<br />

#include "putbyte_disp.c"<br />

void displa (unsigned long i2)<br />

{<br />

if (i2>=10) displa (i2/10);<br />

putbyte (i2%10+’0’);<br />

}<br />

void display()<br />

{<br />

putbyte (’\f’);<br />

displa (Clock);<br />

putbyte (’H’); putbyte (’z’);<br />

putbyte (’/’); putbyte (’2’); putbyte (’/’);<br />

putbyte (’\r’); putbyte (’\n’);<br />

displa (prescaler[psindex]);<br />

putbyte (’/’);<br />

displa (tim0cnt);<br />

putbyte (’=’);<br />

displa (Clock/2/prescaler[psindex]/tim0cnt);<br />

putbyte (’H’); putbyte (’z’);<br />

}<br />

unsigned char taster (unsigned char n)<br />

{<br />

static unsigned char state [4];<br />

switch (n) {<br />

case 1: if(!state[0] && bit_is_clear(tas1_PIN,tas1_PB)) return state[0]=1;<br />

else if (bit_is_set(tas1_PIN,tas1_PB)) state[0]=0; return 0;<br />

case 2: if(!state[1] && bit_is_clear(tas2_PIN,tas2_PB)) return state[1]=1;<br />

else if (bit_is_set(tas2_PIN,tas2_PB)) state[1]=0; return 0;<br />

case 3: if(!state[2] && bit_is_clear(tas3_PIN,tas3_PB)) return state[2]=1;<br />

else if (bit_is_set(tas3_PIN,tas3_PB)) state[2]=0; return 0;<br />

case 4: if(!state[3] && bit_is_clear(tas4_PIN,tas4_PB)) return state[3]=1;<br />

else if (bit_is_set(tas4_PIN,tas4_PB)) state[3]=0; return 0;<br />

}<br />

}<br />

ISR ( SIG_OVERFLOW0 ) // timer0<br />

{<br />

static unsigned char buzzer;<br />

sei();<br />

TCNT0 = ~tim0cnt;<br />

if (buzzer) {sbi(buzzer_PORT,buzzer_PB);buzzer=0;}<br />

else {cbi(buzzer_PORT,buzzer_PB);buzzer=1;}<br />

}<br />

main ()<br />

{<br />

TCCR0B = psindex;<br />

TCNT0 = ~tim0cnt;<br />

sbi (TIMSK0,TOIE0);


KAPITEL 13. AUFBAU DES SYSTEMS 194<br />

buzzer_init();<br />

putbyte_init();<br />

tas1_init(); tas2_init(); tas3_init(); tas4_init();<br />

display();<br />

sei();<br />

sbi (MCUCR,SE); // enable sleep, sleepmode is default idle<br />

for (;;) {<br />

asm ("sleep");<br />

if (taster(1)) {psindex=psindex>=5?1:psindex+1;<br />

TCCR0B = psindex; display();}<br />

if (taster(2)) {tim0cnt=tim0cnt>156?tim0cnt%100:tim0cnt+100;<br />

display();}<br />

if (taster(3)) {tim0cnt=tim0cnt%100>=90?tim0cnt-90:tim0cnt+10;<br />

display();}<br />

if (taster(4)) {tim0cnt=tim0cnt%10>=9?tim0cnt-9:tim0cnt+1;<br />

display();}<br />

}<br />

}<br />

Das Programm gibt auf der Ausgabe die aktuelle Einstellung<br />

des timer0 aus:<br />

7372800Hz/2/<br />

1024/144=25Hz<br />

Der erste Wert ist die Frequenz des Systemtakts. Die Division<br />

durch 2 ist notwendig, da das Programm bei jedem Ablauf des<br />

Timers den Ausgabeport umschaltet. Für eine ganze Schwingung<br />

sind also zwei Timer-Interrupts notwendig. Die Division<br />

durch 1024 vertritt die Einstellung des Vorteilers, im Datenblatt<br />

wird dieser Prescaler genannt. Der letzte Teiler ist der<br />

Wert des Counters. Prescaler und Counter können <strong>mit</strong> den<br />

Tasten verändert werden. So können alle Einstellungen des<br />

timer0 gehört, gesehen und berechnet werden.<br />

Wird die Einstellung so gewählt, dass das Produkt von Prescaler<br />

und Counter kleiner als 22 wird, stürzt das Programm<br />

ab. Warum?


KAPITEL 13. AUFBAU DES SYSTEMS 195<br />

Vertiefung: Das Programm wird auf den genaueren timer1 des<br />

Mikrocontrollers umgestellt. Der timer1 wird im Datenblatt<br />

ausführlich erklärt.<br />

Beobachtung der eigenen Sinne: Das Gehör eignet sich für<br />

Zeitmessungen weit besser als das Auge.<br />

13.4.9 Display<br />

Die letzte Baustufe des Systems wird am besten steckbar ausgeführt.<br />

So kann statt des Displays andere Hardware ohne<br />

Umstände angeschlossen werden.<br />

( ) R1 :Widerstand 33 Ohm :liegend einlöten (u14) (u18)<br />

( ) C3 :Kondensator 100 nF :einlöten (i18) (h18)<br />

( ) Pot :Potentiometer 10 KOhm lin :stehend einlöten<br />

( ) So5 :Präzisionskontakt-Buchsenl.:einlöten<br />

( ) Ada1:Adapternleiste :<strong>mit</strong> Display verlöten<br />

( ) Mon2:2 Distanzrollen 10mm :montieren<br />

( ) Mon3:2 Schrauben M3x16 :montieren<br />

( ) Mon4:4 Muttern M3 :montieren<br />

Das Display wird <strong>mit</strong> Buchsenleiste, Adapterleiste Distanzrollen<br />

(oder Muttern) und Schrauben auf der Hauptplatine<br />

montiert. Mit dem Potentiometer wird der Kontrast eingestellt.<br />

Bei falscher Einstellung des Potentiometers kann man<br />

auf dem Display nichts erkennen. Meist wird der Kontrasteingang<br />

auf 5 V eingestellt, so dass auf das Potentiometer verzichtet<br />

werden kann.<br />

Für den ersten schnellen Test eignet sich das Hello-Programm<br />

aus dem Abschnitt 13.4.6. Das Unterprogramm putbyte() soll<br />

hier nicht sehr vertieft werden. Es wurde entsprechend dem


KAPITEL 13. AUFBAU DES SYSTEMS 196<br />

Datenblatt HD44780U des Herstellers Hitachi 3 programmiert.<br />

Die im Datenbatt beschriebene Initialisierung muss wie ein<br />

Kochrezept durchgeführt werden:<br />

Power on<br />

Wait > 15ms<br />

Write 0011 function_set.high: 8 bits interface<br />

Wait > 41ms<br />

Write 0011 function_set.high: 8 bits interface<br />

Wait > 100ms<br />

Write 0011 function_set.high: 8 bits interface<br />

Write 0010 function_set.high: 4 bits interface<br />

Write 0010 function_set.high: 4 bits interface<br />

Write 1000 function_set.low : 2 line display, 5*7 dots<br />

Write 0000 display_onoff.high:<br />

Write 1000 display_onoff.low : display off, cursor off, blinking off<br />

Write 0000 display_clear.high:<br />

Write 0001 display_clear.low :<br />

Write 0000 entry_mode_set.high:<br />

Write 0110 entry_mode_set.low : increase cursor, display not shifted<br />

Im Anzeigeprogramm werden drei Steuerzeichen so interpretiert,<br />

dass sie zur Terminalemulation minicom kompatibel<br />

sind:<br />

\r carriage return Der Cursor wird an den Anfang der Zeile<br />

gesetzt.<br />

\n new line Der Cursor wird in die zweite Zeile gesetzt.<br />

\f form feed Die Anzeige wird gelöscht, der Cursor wird an<br />

den Anfang der ersten Zeile gesetzt.<br />

Das Display wird über eine vier Bit parallele Schnittstelle angeschlossen.<br />

Mit Steuersignalen werden sieben Leitungen gebraucht.<br />

Entsprechend umfangreich sind die Definitionen der<br />

Ports:<br />

3 Viele kleine LCD-Anzeigen sind hierzu kompatibel.


KAPITEL 13. AUFBAU DES SYSTEMS 197<br />

#define putbyte_drsDDR DDRB<br />

#define putbyte_drsPORT PORTB<br />

#define putbyte_drsPB PB0<br />

#define putbyte_drwDDR DDRD<br />

#define putbyte_drwPORT PORTD<br />

#define putbyte_drwPB PD7<br />

#define putbyte_deDDR DDRD<br />

#define putbyte_dePORT PORTD<br />

#define putbyte_dePB PD6<br />

#define putbyte_dd4DDR DDRD<br />

#define putbyte_dd4PORT PORTD<br />

#define putbyte_dd4PB PD5<br />

#define putbyte_dd5DDR DDRD<br />

#define putbyte_dd5PORT PORTD<br />

#define putbyte_dd5PB PD4<br />

#define putbyte_dd6DDR DDRD<br />

#define putbyte_dd6PORT PORTD<br />

#define putbyte_dd6PB PD3<br />

#define putbyte_dd7DDR DDRD<br />

#define putbyte_dd7PORT PORTD<br />

#define putbyte_dd7PB PD2<br />

#include "putbyte_disp.c"<br />

Um die Programme übersichtlich zu machen, wurden alle<br />

Definitionen, die das Mainboard betreffen, in der Datei<br />

include/mainboard.h gesammelt. Dieses Vorgehen entspricht<br />

auch dem Schichtenmodell. Änderungen an dem Board<br />

erfordern ausschließlich Änderungen in dieser Datei. Im Makefile<br />

wird dem Compiler das Verzeichnis <strong>mit</strong> der Option -I<br />

bekannt gemacht. So<strong>mit</strong> ist folgende Zeile für die Deklaration<br />

der Hardware ausreichend:<br />

#include "mainboard.h"<br />

Das Entwicklungsystem ist fertig. Im Laufe des Aufbaus wurden<br />

drei Programmierprojekte angefangen, um die Funktionsfähigkeit<br />

zu demonstrieren.<br />

Vertiefung: Ein Testprogramm für das Mainboard verwendet<br />

Leuchtdioden, Buzzer, Taster, RS232 und Display. Eine


KAPITEL 13. AUFBAU DES SYSTEMS 198<br />

Drahtbrücke zwischen TXD und RXD ermöglicht den einfachen<br />

Test der seriellen Schnittstelle, ohne dass Quarz und Gegenstation<br />

erforderlich sind.


Kapitel 14<br />

Erste Experimente<br />

Mit dem Display ist das Mikrocontroller Board zu einem<br />

nützlichen Werkzeug gewachsen. Es lohnt sich, die folgenden<br />

Geräte fertigzustellen, um sie bei Bedarf einzusetzen.<br />

14.1 RS232-Schnittstellen-Tester<br />

Für Arbeiten <strong>mit</strong> RS232-Schnittstellen gibt es billige Mini-<br />

Tester <strong>mit</strong> Leuchtdioden, ferner Wiring-Boxen zum Erstellen<br />

von Leitungskombinationen. Geräte, die die nächste Schicht<br />

<strong>mit</strong> Framelänge und Übertragungsgeschwindigkeit messen,<br />

sind teuer. Mittlerweile werden derartige Geräte durch PC-<br />

Programme verdrängt.<br />

199


KAPITEL 14. ERSTE EXPERIMENTE 200<br />

Unser Mikrocontroller soll eingehende Daten auf dem Display<br />

anzeigen und als Echo wieder senden.<br />

Das Display wird folgendermaßen eingesetzt:<br />

* RS232-Tester *<br />

Testdaten...Test<br />

Die Testdaten in der zweiten Zeile werden von rechts nach<br />

links durchgeschoben.<br />

Das Umschalten geschieht bei fallender Flanke der Taster. Solange<br />

ein Taster gedrückt ist, wird in der oberen Zeile des<br />

Displays die Einstellung des UART angezeigt:<br />

Funktion des Taster1<br />

115200B,8B,nP,2S<br />

Testdaten...Test<br />

Der Taster1 schaltet zwischen ASCII- und Hexadezimalmode<br />

um. Die Hexadezimalzeichen werden durch Leerzeichen getrennt:<br />

Funktion des Taster2<br />

* RS232-Tester *<br />

e 2e 54 65 73 74


KAPITEL 14. ERSTE EXPERIMENTE 201<br />

Der Taster2 ändert die Geschwindigkeit der Übertragung. Es<br />

wird zyklisch zwischen den Geschwindigkeiten 150 300 600<br />

1200 2400 4800 9600 19200 38400 57600 und 115200 Baud<br />

umgeschaltet.<br />

Funktion des Taster3<br />

Der Taster3 schaltet zwischen 5..8 Bit Wortlänge um.<br />

Funktion des Taster4<br />

Der Taster4 schaltet zwischen even odd und no Parity und ein<br />

und zwei Stopbits um.<br />

Funktion der Leuchtdioden<br />

Led1 zeigt Datenüberlauf an.<br />

Led2 zeigt Rahmenfehler an.<br />

Led3 zeigt Paritätsfehler an.<br />

14.2 Frequenzgenerator<br />

Das für den timer1 geänderte Programm wird modifiziert. Die<br />

auszugebende Frequenz wird angezeigt.<br />

* Hz-Generator *<br />

81920 Hertz<br />

Die Frequenz wird <strong>mit</strong> den Tastern folgendermaßen verstellt:


KAPITEL 14. ERSTE EXPERIMENTE 202<br />

Funktion des Taster1<br />

Der Eingabecursor, als blinkende Stelle in der unteren Zeile<br />

des Displays dargestellt, wird nach links verschoben.<br />

Funktion des Taster2<br />

Der Eingabecursor wird nach rechts verschoben.<br />

Funktion des Taster3<br />

Die blinkende Stelle der Frequenzanzeige wird inkrementiert.<br />

Freqenzen die zum Absturz führen würden, werden nicht akzeptiert.<br />

Funktion des Taster4<br />

Die blinkende Stelle der Frequenzanzeige wird dekrementiert.<br />

Frequenzen unter 1 Hz werden nicht eingestellt.<br />

Der Frequenzgenerator erweitert nicht nur das Elektroniklabor,<br />

sondern eignet sich auch für einfache Hörtests.<br />

14.3 Voltmeter<br />

Neben Bit-I/O, seriellem I/O, Timern und Countern verfügt<br />

unser Mikrocontroller über aufwändige analoge Eingangsschaltungen.<br />

Um Spannungen zwischen Masse und Vcc zu<br />

messen, ist keine weitere Hardware notwendig.<br />

Für dieses Experiment wurden Leuchtdioden in drei Farben<br />

eingebaut. An roten LEDs fällt die Spannung ca. 1,6 Volt ab,


KAPITEL 14. ERSTE EXPERIMENTE 203<br />

an gelben ca. 1,7 Volt und an grünen ca. 1,8 Volt. Mit einem<br />

Draht und Prüfspitzen läßt sich leicht zwischen Leuchtdiode<br />

und dem Pin an ADC3 eine Messverbindung herstellen.<br />

Das folgende Programm nutzt die interne Referenzspannung,<br />

die laut Datenblatt beim ATmega8 zwischen 2,45 und<br />

2,80 Volt liegen kann. Für genaue Messungen muss kalibriert<br />

werden.<br />

/*<br />

** Name: software/dvm/dvm.c<br />

** Funktion: Digital Voltage Meter, interrupt and polling version<br />

** History: 20041002 Hanns-Konrad Unger creation<br />

*/<br />

#include <br />

#include <br />

#include "putbyte_disp.c"<br />

#include "../include/adc.c"<br />

#ifdef __AVR_ATmega8__<br />

#define AREF 25575 // calibrate here, nice are 24552 25575 26598 27621<br />

#else // ATmega48 ...<br />

#define AREF 11000<br />

#endif<br />

static void putstring (unsigned char *p) {while (*p) putbyte (*p++);}<br />

unsigned char display_arr[18] = "\r 2.5600 Volt DC";<br />

// 0123456789012345678<br />

void display() {<br />

volatile unsigned short val; //!!!!!!!!!!!!!!!!!!!!!!!!!!!<br />

val=adc_result[3]*(AREF/0x3ff);<br />

unsigned char i;<br />

for (i=8;i>=5;) {display_arr[i--]=val%10+’0’; val/=10;}<br />

display_arr[3]=val+’0’;<br />

putstring (display_arr);<br />

}<br />

ISR (TIMER2_COMPB_vect) { // timer2<br />

sei();<br />

display();<br />

#if adc_FLAG == ADIF<br />

adc();<br />

#endif<br />

}<br />

main() {<br />

led_init();<br />

led1_on(); led2_on(); led3_on(); // Voltages to measure


KAPITEL 14. ERSTE EXPERIMENTE 204<br />

}<br />

putbyte_init();<br />

putstring ("\f* Volt-Meter *\n");<br />

adc_init();<br />

// Timer/Counter2 for 50Hz<br />

OCR2B=Clock/1024/50-1; // count<br />

TCCR2B=7; // prescaler<br />

TCCR2B|=(1


KAPITEL 14. ERSTE EXPERIMENTE 205<br />

Der Inhalt des Feldes function bestimmt die Bedeutung des<br />

zugehörigen Datensatzes.<br />

0x00 Fre Der Datensatz ist frei, darf verändert werden.<br />

0x01 Bu+ Den Buzzer <strong>mit</strong> 2,4 kHz summen lassen.<br />

0x02 Bu- Den Buzzer nicht summen lassen.<br />

0x03 Li+ Die Beleuchtung der LCD-Anzeige einschalten.<br />

0x04 Li- Die Beleuchtung der LCD-Anzeige ausschalten.<br />

0x05 L1+ Die Leuchtdiode LED1 einschalten.<br />

0x06 L1- Die Leuchtdiode LED1 ausschalten.<br />

0x07 L2+ Die Leuchtdiode LED2 einschalten.<br />

0x08 L2- Die Leuchtdiode LED2 ausschalten.<br />

0x09 L3+ Die Leuchtdiode LED3 einschalten.<br />

0x0a L3- Die Leuchtdiode LED3 ausschalten.<br />

0x0b Ch+ Das Stundensignal einschalten.<br />

0x0c Ch- Das Stundensignal ausschalten.<br />

0x0d Tx+ Den Anzeigentext wechseln.<br />

0x0e Tx- Den Anzeigentext wiederherstellen.<br />

0x0f Txt Die Daten des Anzeigetextes.<br />

0xff Der Datensatz darf nicht verändert werden.<br />

Da Datensätze der function 0xff nicht verändert werden<br />

dürfen, wird erst durch Initialisieren des EEPROMS festgelegt,<br />

wieviel der maximal 102 Speicherplätze editierbar sind.<br />

Für den Bediener der Uhr befinden sich vor den Datensätzen<br />

des EEPROMS zwei Datensätze <strong>mit</strong> den Werten von MEZ<br />

und MES. Obwohl diese Sätze nur im RAM gehalten werden,<br />

werden sie beim Editieren <strong>mit</strong> den Tasten <strong>mit</strong> angezeigt.<br />

Mit den Tasten können die Sätze auf folgende Art verändert<br />

werden:


KAPITEL 14. ERSTE EXPERIMENTE 206<br />

Funktion des Taster1<br />

Die untere Zeile der Anzeige schaltet auf den nächsten<br />

veränderbaren Datensatz um. Der erste Datensatz enthält<br />

MEZ. Der zweite Datensatz enthält MES. Dann folgen die<br />

veränderbaren Datensätze des EEPROM. Hinter dem letzten<br />

veränderbare Datensatz des EEPROM steht wieder MEZ.<br />

Funktion des Taster2<br />

Der Cursor der Anzeige wird um eine Position nach rechts verschoben.<br />

Der Cursor ist ein blinkendes Feld der unteren Zeile<br />

der Anzeige. Der Wochentag und die Anzeige der Funktion<br />

blinken komplett. Die Leerstellen und Doppelpunkte werden<br />

übersprungen. Zwischen erstem und letztem Feld befindet sich<br />

eine nicht blinkende Ruhezohne.<br />

Funktion des Taster3<br />

Der zum Cursor gehörige Wert wird um eins erhöht. Die<br />

Wochentage werden folgendermaßen durchgezählt: Mon, Die,<br />

Mit, Don, Fre, Sam, Son, any.<br />

Die Funktion des Speicherplatzes wird ab der aktuellen<br />

gültigen Funktion folgendermaßen zyklisch durchgezählt: Fre,<br />

Bu+, Bu-, Li+, Li-, L1+, L1-, L2+, L2-, L3+, L3-. Die Funktionen<br />

MEZ und MES können nicht verändert werden.<br />

Funktion des Taster4<br />

Analog zu Taster3 nur in anderer Richtung.


Kapitel 15<br />

Weiterführende<br />

Experimente<br />

Nun ist das Experimentiersystem in die Welt gesetzt. Bis auf<br />

die letzten Experimente war alles ziemlich Selbstzweck. War<br />

es wirklich? Das Buch neigt sich dem Ende zu. Für die Beschreibung<br />

weiterer Experimente hat der Autor im Moment<br />

keine Zeit, nur noch Ideen. Hat jemand etwas Zeit und sucht<br />

Vorschläge, um weitere Ideen zu entwickeln? Eine Liste weiterführender<br />

Experimente soll nicht unterschlagen werden.<br />

Über die Nachricht entsprechender Aktivitäten freut sich der<br />

Autor.<br />

207


KAPITEL 15. WEITERFÜHRENDE EXPERIMENTE 208<br />

15.1 Messen<br />

HW: Analog-Input<br />

SW: Voltmeter<br />

SW: Amperemeter<br />

SW: Ohmmeter<br />

SW: 2-Kanal Signaltracer <strong>mit</strong> Display<br />

SW: Frequenzgenerator (Elektor 1998/11 pX2)<br />

15.2 Steuern<br />

HW: SPS (Elektor 2002/11 p22 2002/06 p14)<br />

SW: Bytecode-Interpreter für SPS Elektor (1998/11 p76)<br />

HW: Lichtsensor LDR<br />

SW: Dämmerungsschalter<br />

HW: Näherungsschalter (Elektor 2004/01 p22)<br />

SW: Mit Schalter Led dimmen und schalten<br />

15.3 Regeln<br />

HW: Temperatursensor KTY10 HW: Temperatursensor NTC<br />

(Elektor 2003/10 p24)


KAPITEL 15. WEITERFÜHRENDE EXPERIMENTE 209<br />

SW: Zimmertemperatur auf Display anzeigen<br />

SW: PID-Regler (Elektor 1999/09 p28)<br />

15.4 Solartechnik<br />

HW: Akkus und Solarzelle<br />

SW: Solarladegerät <strong>mit</strong> Überwachung der Ladungsmenge<br />

15.5 Robotik<br />

HW: Modellbauservo<br />

SW: Ansteuern eines Servos<br />

HW: Motor schalten (Elektor 2001/05 p62)<br />

SW: Motor choppen<br />

HW: Spielzeugauto oder -schiff umrüsten<br />

SW: Interpreter für Bytecode<br />

SW: Verbindung zu NQC (not quite C)<br />

15.6 Fernwirken<br />

HW: DCF77 Empfänger


KAPITEL 15. WEITERFÜHRENDE EXPERIMENTE 210<br />

SW: Uhr <strong>mit</strong> DCF synchronisieren<br />

HW: IR-LED (Elektor 2001/04 p62)<br />

SW: Fernsteuern <strong>mit</strong> RC5-Codes (ct 2005/23 p225)<br />

SW: Terminalverbindung über Infrarot (Elektor 2003/10 p12)<br />

HW: RS485 (Elektor 2003/11 p70)<br />

SW: Point/Point Verbindung <strong>mit</strong> PC<br />

SW: Netzwerk<br />

HW: Chrystal CS8900<br />

SW: TCP/IP Stack<br />

HW: 2.4 GHz Funkmodul<br />

SW: Drahtlose Verbindung <strong>mit</strong> dem PC über V24<br />

SW: Gesicherte Verbindung<br />

HW: Mobilfunk (Elektor 2002/01 p14)<br />

SW: Senden/Empfangen von SMS-Nachrichten <strong>mit</strong> einem<br />

Mobilfunktelefon<br />

HW: RFID-Leser (Elektor 2006/09 p36)


Anhang A<br />

Stolpersteine<br />

Erfahrungen, vor denen gewarnt werden soll:<br />

A.1 Reset und Brown-out<br />

Entspricht die Spannungsversorgung nicht den technischen<br />

Daten, so kann es vorkommen, dass der Mikrocontroller unvorhersehbare<br />

Programmsequenzen ausführt. Dies passiert<br />

zum Beispiel auch, wenn ein <strong>mit</strong> Kondensatoren bestücktes<br />

Netzteil ein- oder abgeschaltet wird. Die unangenehme Folge<br />

ist, dass auch Flash oder EEPROM verändert werden können.<br />

Um diesen heimtückischen Effekt zu vermeiden, müssen entweder<br />

im Netzteil oder beim Reset Vorkehrungen getroffen<br />

werden.<br />

211


ANHANG A. STOLPERSTEINE 212<br />

Neuere Modelle der AVR Serie besitzen eine einstellbare<br />

brown-out detection. Diese versetzt den Prozessor bei gefährlichen<br />

Spannungszuständen in den Reset-Zustand.<br />

Auf der anderen Seite kann ein Aktivieren des brown-out bei<br />

mangelhafter Spannungsversorgung zu sporadischem reset des<br />

Programms führen.<br />

A.2 Stackfault<br />

Im RAM müssen sich statische Variable, lokale Variable und<br />

Rücksprungadressen den Platz teilen. Der Compiler füllt das<br />

RAM von unten <strong>mit</strong> statischen Variablen auf. Der Rest bleibt<br />

dem vom Runtime initialisierten Stack, der lokale Variable<br />

und Rücksprungadressen beherbergen muss. Leider ist der<br />

Aufruf von Unterprogrammen schwer, in vielen Fällen sogar<br />

grundsätzlich gar nicht, vorhersehbar. So kann es vorkommen,<br />

dass Stack und statische Variable sich überschreiben.<br />

Dies führt in der Regel zu sonderbarem Programmverhalten<br />

oder zum Programmabsturz. Ein Stackfault-Interrupt für eine<br />

kontrollierte Fehlerbehandlung wäre sehr wünschenswert.<br />

Als einfache Lösung kann man am Anfang jeder Funktion den<br />

Stackpointer überprüfen.


ANHANG A. STOLPERSTEINE 213<br />

A.3 volatile<br />

Der gcc erkennt Code, der Variable nicht verändert. Mit eingeschalteter<br />

Optimierung (default ist -O1!) werden derartige<br />

Programmstücke wegoptimiert. Zum Beispiel bei Warteschleifen<br />

führt das zu unerwartetem Verhalten des Programms.<br />

Wird der gcc <strong>mit</strong> der Option -O0 aufgerufen, so ist die Optimierung<br />

ausgeschaltet. Um trotz Warteschleifen <strong>mit</strong> Optimierung<br />

arbeiten zu können, gibt es für betroffene Variablen die<br />

C-Anweisung ,,volatile”. Die Ur-Version von C kannte diese<br />

Anweisung übrigens noch nicht.<br />

A.4 Interrupts<br />

Wird in einem Interrupt behandelnden Programm der Interrupt<br />

wieder eingeschaltet, so führt ein weiterer Interrupt zur<br />

Unterbrechung des Interrupts. Derartige Programme müssen<br />

reentrant programmiert worden sein. So muss der Zugriff auf<br />

statische bzw. externe Variable über Semaphore gesichert werden.<br />

Da der Compiler Interrupts nicht nachvollziehen kann, müssen<br />

statische Variable, die innerhalb und außerhalb von Interrupts<br />

verwendet werden, als volatile deklariert werden.


ANHANG A. STOLPERSTEINE 214<br />

A.5 PORTx<br />

Der Name PORT verführt dazu, nach dem Löschen des DDR-<br />

Bits daraus zu lesen. Ports müssen jedoch über die Adresse<br />

PINx gelesen werden.<br />

A.6 Watchdog<br />

Der Watchdog erzeugt einen Reset des Systems. Im Runtime<br />

werden alle statischen Variablen vor dem Aufruf von main()<br />

initalisiert. Nach der Definition von C werden im Programm<br />

nicht explizit initalisierte statische Variablen <strong>mit</strong> Null initialisiert.<br />

Dieses Verhalten des Watchdog und von C verhindert,<br />

dass man den sehr stromsparenden Sleepmodus <strong>mit</strong> aktiviertem<br />

Watchdog nicht bei Programmen verwenden kann, die<br />

auf externe oder statische Variable angewiesen sind.<br />

A.7 UCSRC<br />

Das Einstellregister des USARTS teilt sich die selbe Adresse<br />

<strong>mit</strong> UBRRH. Bit7 schaltet zwischen beiden Registern um. Der<br />

Befehl ,,sbi(UCSRC,7)” funktioniert nicht, um anschließend<br />

einzelne Bits umzustellen. Das Register UCSRC darf also nur<br />

komplett beschrieben werden.


ANHANG A. STOLPERSTEINE 215<br />

A.8 Besonderheiten einzelner Modelle<br />

A.8.1 AT90S1200<br />

Da dieses Modell über kein RAM und so<strong>mit</strong> keinen Stack<br />

verfügt, wird es vom gcc nicht unterstützt.<br />

A.8.2 AT90S2343<br />

Es wurden ICs verkauft, die <strong>mit</strong> aktiviertem internem Oszillator<br />

nicht richtig anlaufen. Der Fehler wurde ab Revision G<br />

beseitigt.<br />

A.8.3 Vom AT90S4433 zum ATmega8<br />

Ein Vorteil der AVR-Familie ist die Typenvielfalt. Zeigt sich<br />

im Zuge einer Entwicklung, dass Speicher oder I/O-Leitungen<br />

nicht ausreichen, wechselt man zum nächsten Modell. In der<br />

Regel geht der Umzug relativ einfach, da die Entwickler bei<br />

Atmel bei der Namensgebung von Registern etc. diszipliniert<br />

vorgehen.<br />

Bei gleichem Gehäuse sind viele interne Werte des ATmega8<br />

fast doppelt so gut wie bei seinem Vorgänger. Folgende Änderungen<br />

waren bei einem Umstieg notwendig:


ANHANG A. STOLPERSTEINE 216<br />

• Die Software der Debian 3.0 Distribution kennt den ATmega8<br />

noch nicht. Installation des neueren avr-gcc 3.3,<br />

lib-avr und binutils-avr werden notwendig. Leider bedingt<br />

das auch ein Erneuern der libc. Bis Debian 3.1<br />

hilft Knoppix.<br />

• Der Taktteiler für den USART ist von 8 auf 12 Bit gewachsen.<br />

Aus UBRR wird UBRRL und UBRRH. Der<br />

Compiler erkennt das fehlende Symbol.<br />

• Die Zahl der Sleep-modes hat sich erhöht. Aus SM wird<br />

SM0..2. Auch hier bemerkt der Compiler den Symbolwechsel.<br />

• Der ATmega8 wird <strong>mit</strong> aktiviertem internen 1Mhz Oszillator<br />

geliefert. Um z. B. auf externen Quarz umzustellen,<br />

müssen die Fuses des Prozessors umprogrammiert<br />

werden. Das Datenblatt gibt ausführlich Auskunft.<br />

Dieses ist eine ziemliche Falle, da die meisten Programme<br />

für Mikrocontroller <strong>mit</strong> der Taktfrequenz stark verknüpft<br />

sind. Andererseits garantiert diese Eigenschaft<br />

die Programmierbarkeit eines fabrikneuen Chips in einer<br />

Schaltung ohne externen Oszillator.<br />

Eine umfassende Beschreibung der Unterschiede befindet sich<br />

in der Technical Library von Atmel [atmel] als Application<br />

Note AVR081.


Anhang B<br />

Technische Daten<br />

Spannungen des Experimentiersystems:<br />

Steckernetzteil <strong>mit</strong> Geichspannung (DC) 9 .. 35 V<br />

Steckernetzteil <strong>mit</strong> Wechselspannung (AC) 6 .. 24 V<br />

Batterieversorgung 4.8 .. 6.0 V<br />

CPU 1.8 .. 5.5 V<br />

LED <strong>mit</strong> Vorwiderstand 2.7 .. 5.5 V<br />

Max 232 4.2 .. 5.0 V<br />

(Max 3232 3.0 .. 5.5 V)<br />

Displaytech 162 4.2 .. 5.0 V<br />

Displaybeleuchtung 4.2 .. 5.0 V<br />

217


ANHANG B. TECHNISCHE DATEN 218<br />

Stromverbrauch einzelner Teile des Experimentiersystems:<br />

CPU 3. mA<br />

Oszillator 1. mA<br />

LED 1. mA<br />

Buzzer 4. mA<br />

Max 232 4. mA<br />

Displaytech 162 3. mA<br />

Displaybeleuchtung 10. mA


Anhang C<br />

Nachschlagebereich<br />

C.1 Assembler<br />

Genaue Beschreibung der Befehle befindet sich im Datenblatt<br />

der Firma Atmel ,,8-bit AVR Instruction Set”.<br />

Rechenbefehle<br />

add Rd,Rr Add without Carry<br />

adc Rd,Rr Add with Carry<br />

adiw Rd,K Add Immediate to Word<br />

sub Rd,Rr Subtract without Carry<br />

subi Rd,K Subtract Immediate<br />

sbc Rd,Rr Subtract with Carry<br />

sbci Rd,K Subtract Immediate with Carry<br />

sbiw Rd,K Subtract Immediate from Word<br />

219


ANHANG C. NACHSCHLAGEBEREICH 220<br />

and Rd,Rr Logical And<br />

andi Rd,K Logical And with Immediate<br />

or Rd,Rr Logical Or<br />

ori Rd,K Logical Or with Immediate<br />

eor Rd,Rr Exclusive Or<br />

com Rd One’s Complement<br />

neg Rd Two’s Complement<br />

sbr Rd,K Set Bits in Register<br />

cbr Rd,K Clear Bits in Register<br />

inc Rd Increment<br />

dec Rd Decrement<br />

cp Rd,Rr Compare<br />

cpc Rd,Rr Compare with Carry<br />

cpi Rd,K Compare with Immediate<br />

tst Rd Test for Zero or Minus<br />

clr Rd Clear Register<br />

ser Rd Set Register<br />

mul Rd,Rr Multiply Unsigned<br />

muls Rd,Rr Multiply Signed<br />

mulsu Rd,Rr Multiply Signed with Unsigned<br />

fmul Rd,Rr Fractional Multiply Unsigned<br />

fmuls Rd,Rr Fractional Multiply Signed<br />

fmulsu Rd,Rr Fractional Multiply Signed with Uns.<br />

Jumps<br />

rjmp k Relative Jump<br />

ijmp Indirect Jump to (Z)<br />

eijmp Extended Indirect Jump to (Z)


ANHANG C. NACHSCHLAGEBEREICH 221<br />

jmp k Jump<br />

rcall k Relative Call Subroutine<br />

icall Indirect Call Subroutine to (Z)<br />

eicall Extended Indirect Call Subr. to (Z)<br />

call k Call Subroutine<br />

ret Subroutine Return<br />

iret Interrupt Return<br />

cpse Rd,Rr Compare, Skip if Equal<br />

sbrc Rr,b Skip if Bit in Register Cleared<br />

sbrs Rr,b Skip if Bit in Register Set<br />

sbic Rr,b Skip if Bit in I/O Register Cleared<br />

sbis Rr,b Skip if Bit in I/O Register Set<br />

brbs s,k Branch if Status Flag Set<br />

brbc s,k Branch if Status Flag Cleared<br />

breq k Branch if Equal<br />

brne k Branch if Not Equal<br />

brcs k Branch if Carry Set<br />

brcc k Branch if Carry Cleared<br />

brsh k Branch if Same of Higher<br />

brlo k Branch if Lower<br />

brmi k Branch if Minus<br />

brpl k Branch if Plus<br />

brge k Branch if Greater or Equal, Signed<br />

brlt k Branch if Less Than, Signed<br />

brhs k Branch if Half Carry Set<br />

brhc k Branch if Half Carry Cleared<br />

brts k Branch if T Flag Set<br />

brtc k Branch if T Flag Cleared<br />

brvs k Branch if Overflow Flag is Set


ANHANG C. NACHSCHLAGEBEREICH 222<br />

brvc k Branch if Overflow Flag is Cleared<br />

brie k Branch if Interrupt Enabled<br />

brid k Branch if Interrupt Disabled<br />

Moves<br />

mov Rd,Rr Copy Register<br />

movw Rd,Rr Copy Register Pair<br />

ldi Rd,k Load Immediate<br />

lds Rd,k Load Direct from Data Space<br />

ld Rd,xyz Load Indirect<br />

ld Rd,xyz+ Load Indirect and Post-Increment<br />

ld Rd,-xyz Load Indirect and Pre-Decrement<br />

ldd Rd,yz+q Load Indirect with Displacement<br />

sts k,Rr Store Direct to Data Space<br />

st xyz,Rr Store Indirect<br />

st xyz+,Rr Store Indirect and Post-Increment<br />

st -xyz,Rr Store Indirect and Pre-Decrement<br />

std yz+q,Rr Store Indirect with Displacement<br />

lpm Load Program Memory to R0<br />

lpm Rd,Z Load Program Memory to Register<br />

lpm Rd,Z+ LPM. and Post-Increment<br />

elpm Extended LPM. to R0<br />

elpm Rd,Z Extended LPM. to Register<br />

elpm Rd,Z+ Extended LPM. and Post-Increment<br />

spm Store Program Memory<br />

in Rd,A In from I/O Location<br />

out A,Rd Out to I/O Location<br />

push Rr Push Register to Stack


ANHANG C. NACHSCHLAGEBEREICH 223<br />

pop Rd Pop Register from Stack<br />

Bitbefehle<br />

lsl Rd Logical Shift Left<br />

lsr Rd Logical Shift Right<br />

rol Rd Rotate Left Through Carry<br />

ror Rd Rotate Right Through Carry<br />

asr Rd Arithmetic Shift Right<br />

swap Rd Swap Nibbles<br />

Bset s Flag Set<br />

Bclr s Flag Clear<br />

sbi A,b Set Bit in I/O Register<br />

cbi A,b Clear Bit in I/O Register<br />

bst Rr,b Bit Store from Register T<br />

bld Rd,b Bit Load from Register T<br />

sec Set Carry<br />

clc Clear Carry<br />

sen Set Negative Flag<br />

cln Clear Negative Flag<br />

sez Set Zero Flag<br />

clz Clear Zero Flag<br />

sei Global Interrupt Enable<br />

cli Global Interrupt Disable<br />

ses Set Signed Test Flag<br />

cls Clear Signed Test Flag<br />

sev Set Two’s Complement Overflow<br />

clv Clear Two’s Complement Overflow<br />

set Set T in SREG


ANHANG C. NACHSCHLAGEBEREICH 224<br />

clt Clear T in SREG<br />

seh Set Half Carry Flag in SREG<br />

clh Clear Half Carry Flag in SREG<br />

Control<br />

break Break<br />

nop No Operation<br />

sleep Sleep<br />

wdr Watchdog Reset<br />

Steueranweisungen<br />

.text .data .bss<br />

.string<br />

.word<br />

.byte<br />

C.2 Programmiersprache C<br />

Neben verschiedensten Büchern über C findet man die<br />

ursprüngliche Beschreibung der Sprache im Buch ,,Die<br />

Programmiersprache C” der Autoren der Sprache Kernighan/Ritchie<br />

[Kernighan].


ANHANG C. NACHSCHLAGEBEREICH 225<br />

Operatoren<br />

( ) [ ] -> .<br />

! ~ ++ -- + - * & (type) sizeof<br />

* / %<br />

+ -<br />

><br />

< >=<br />

== !=<br />

&<br />

^<br />

|<br />

&&<br />

||<br />

?:<br />

= += -= *= /= %= &= ^= |= =<br />

,<br />

Präprozessor<br />

define undef<br />

include<br />

line error pragma<br />

if elif else endif<br />

ifdef ifndef<br />

Sprachelemente<br />

static extern<br />

const volatile auto register


ANHANG C. NACHSCHLAGEBEREICH 226<br />

signed unsigned<br />

void char short int long float double<br />

struct union enum typedef<br />

sizeof<br />

if else<br />

do while for continue<br />

switch case break default<br />

goto return<br />

Erweiterungen<br />

asm<br />

C.3 Runtime<br />

Die Schnittstellen des Runtimes findet man im Verzeichnis<br />

/usr/avr/include.<br />

#include <br />

#define bit_is_set(port,bit) ...<br />

#define bit_is_clear(port,bit) ...<br />

#define loop_until_bit_is_set(port,bit) ...<br />

#define loop_until_bit_is_clear(port,bit) ...<br />

#define RAMEND 0x45F<br />

#define E2END 0x1FF<br />

#define FLASHEND 0x1FFF<br />

#define SIG_INTERRUPT0 _VECTOR(1)<br />

.<br />

.<br />

.


ANHANG C. NACHSCHLAGEBEREICH 227<br />

#include <br />

extern uint8_t eeprom_read_byte (uint8_t *addr);<br />

extern uint16_t eeprom_read_word (uint16_t *addr);<br />

extern void eeprom_read_block (void *buf, void *addr, size_t n);<br />

extern void eeprom_write_byte (uint8_t *addr, uint8_t val);<br />

extern void eeprom_read_block (void *buf, void *addr, size_t n);<br />

#include <br />

typedef void prog_void PROGMEM;<br />

typedef char prog_char PROGMEM;<br />

typedef unsigned char prog_uchar PROGMEM;<br />

typedef int prog_int PROGMEM;<br />

typedef long prog_long PROGMEM;<br />

typedef long long prog_long_long PROGMEM;<br />

extern void *memcpy_P(void *, PGM_VOID_P, size_t);<br />

extern char *strcat_P(char *, PGM_P);<br />

extern int strcmp_P(const char *, PGM_P) __ATTR_PURE__;<br />

extern char *strcpy_P(char *, PGM_P);<br />

extern int strcasecmp_P(const char *, PGM_P) __ATTR_PURE__;<br />

extern size_t strlen_P(PGM_P) __ATTR_CONST__;<br />

extern int strncmp_P(const char *, PGM_P, size_t) __ATTR_PURE__;<br />

extern int strncasecmp_P(const char *, PGM_P, size_t) __ATTR_PURE__;<br />

extern char *strncpy_P(char *, PGM_P, size_t);<br />

#include <br />

#define ISR (signame) ...<br />

#define sei() ...<br />

#define cli() ...


Anhang D<br />

Programm pcb<br />

#!/bin/bash<br />

#.#############################################################################<br />

#. Programheader<br />

#.#############################################################################<br />

Prognam="pcb"<br />

Version="0.1-20060322"<br />

Maintainer="Hanns-Konrad Unger "<br />

Description="tool for creating printed circuit boards (pcbs)"<br />

Architecture="all"<br />

Section="electronics"<br />

Priority="optional"<br />

Depends="bash (>= 2.05)"<br />

Location="/usr/bin"<br />

Programheader () { cat


ANHANG D. PROGRAMM PCB 229<br />

Myp=$0 # Patch here if next if exits<br />

if [ ! -x "$Myp" ]<br />

then echo Please use latest version of bash or ash.; exit -1; fi<br />

Myn=$(basename $Myp) # My Name<br />

Noa=$# # Number Of Args<br />

Dir=$(echo $Myp|sed -e s#$Myn\$## -e s#/\$## ) # Directory program comes from<br />

if [ "$Dir" = "" ]; then Dir=.; fi<br />

Nam=$(echo $Myn|sed s/\\..*//) # Name of programfile without dot<br />

Fun=$(echo $Myn|sed s/${Nam}.//) # Name of running method<br />

Edi=/bin/vi # prefered editor<br />

Lom="" # List Of Methods<br />

Lop="" # List OF temP. files 20020107<br />

Lot="basename sh echo sed type" # List Of Tools<br />

Loc="class" # List Of Classes<br />

#.Added:2005May07:class:new:pcb:Global Variables<br />

Loc="$Loc pcb"<br />

#.Added:2006Nov18:pcb:new:pcb:Global Variables<br />

Loc="$Loc pcb"<br />

#.#############################################################################<br />

#. Global Functions<br />

#.#############################################################################<br />

# Debug () { bash; } # 1st line MUST BE: #!/bin/bash -a<br />

# Debug () { set | less; } # see all variables<br />

# Debug () { set -x; } # activates bash -x<br />

# Debug () { set -v; } # activates bash -v<br />

# Debug () { echo $@; sleep 5; }<br />

# Debug () { logger $@; }<br />

# Debug () { export $@; bash; }<br />

Exit_onerror () # $1=programname; run very critical program<br />

{ if ! $1 ; then echo $Myn aborted: Error running $1 !; Quit -1; fi; }<br />

Testargs () { # testarguments num [file]<br />

if [ $Noa -lt $1 ]; then Met=man; $Nam.$Fun; Quit -1; fi<br />

if [ -z "$2" ]; then return; fi<br />

if [ "$2" = "-" ]; then return; fi # stdin<br />

if ! [ -f "$2" ]; then echo Cannot find $2!; Quit -1; fi; }<br />

Lot="$Lot mktemp"<br />

Mktmp_return="" # Mktmp() is string_function, $() does not change global $Lop<br />

Mktmp () { # make temporary File 20021118 HKU<br />

local n=$(mktemp Tmp$$XXXXXX); Lop="$(pwd)/$n $Lop"; Mktmp_return=$n; }<br />

Mktmpdir () { # make temporary Dir<br />

local n=$(mktemp -d Tmp$$XXXXXX); Lop="$(pwd)/$n $Lop"; Mktmp_return=$n; }<br />

Lot="$Lot ln"<br />

Install () { (cd $Dir;ln -sf $Myn $1 2>/dev/null); }<br />

Lot="$Lot rm"<br />

Deinstall () { rm $Dir/$1; }<br />

Quit () {<br />

local n<br />

for n in $Lop; do<br />

if [ -f $n ]; then rm $n;<br />

else if [ -d $n ]; then rmdir $n; fi; fi<br />

done; exit $1; }<br />

#.Added:2005May07:class:new:pcb:Global Functions<br />

#.Added:2006Nov18:pcb:new:pcb:Global Functions<br />

pslayout () {<br />

echo "%!PS-Adobe-1.0"<br />

echo "%%Title: $(echo $1|sed s/\\..*//).ps"<br />

echo "%%Creator: ${Myn} from www.hanns-konrad.de"<br />

echo -n "%%Date: "; date "+%Y%b%d %H:%M"<br />

cat


ANHANG D. PROGRAMM PCB 230<br />

/mm { 25.4 div 72 mul } def<br />

/inch { 72 mul } def<br />

/pt { 1 mul } def<br />

/white [ 1.0 1.0 1.0 ] def<br />

/black [ 0.0 0.0 0.0 ] def<br />

/setcolor { aload pop setrgbcolor } def<br />

/leftmargin 25.4 mm def<br />

/topmargin 10 mm def<br />

/pageheight 297 mm def /pagewidth 210 mm def % a4<br />

%%EndProlog<br />

/boardscale 1 def % 1 is normal scale, 2 is wide scale<br />

/psize 7.2 def % diameter of one pad (0.1 inch)<br />

% /xpos 0 def % xresult of cvpad<br />

% /ypos 0 def % yresult of cvpad<br />

/multpcb false def % Platine nur einfach ausgeben<br />

/multx 1 def % Kopien in x-Richtung<br />

/multy 1 def % Kopien in y-Richtung<br />

% /dx 0 def % x-size<br />

% /dy 0 def % y-size<br />

1 setlinejoin<br />

/cvpad % (a15) cvpad => xpos=1 ypos=15 ; works from (a1)..(z1),(A1)..(Z1)<br />

% to (Z113)<br />

{<br />

dup 0 get<br />

dup 64 le % A-1<br />

{ pop 0 }<br />

{ dup 90 le % Z<br />

{ 64 sub 26 add }<br />

{ dup 96 le % a-1<br />

{ pop 0 }<br />

{ dup 122 le % z<br />

{ 96 sub }<br />

{ pop 0<br />

} ifelse<br />

} ifelse<br />

} ifelse<br />

} ifelse<br />

/xpos exch def<br />

dup length 1 sub 1 exch getinterval cvi /ypos exch def<br />

} def<br />

/mboard { /multy exch def /multx exch def /multpcb true def } def<br />

/board2 { /boardscale 2 def /psize psize 2 div def board } def<br />

/board % (n15) board<br />

{<br />

cvpad /dy ypos 1 add def /dx xpos 1 add def<br />

/st ( ) def<br />

[ 1 0 0 -1 0 0 ] concat<br />

multpcb<br />

{<br />

leftmargin<br />

pageheight topmargin sub -1 mul<br />

translate


ANHANG D. PROGRAMM PCB 231<br />

psize psize scale<br />

0 setlinewidth<br />

1 1 multy<br />

{<br />

/y exch def<br />

1 1 multx<br />

{<br />

1 sub dx mul y 1 sub dy mul moveto<br />

dx 0 rlineto 0 dy rlineto dx -1 mul 0 rlineto closepath stroke<br />

} for<br />

} for<br />

}<br />

{<br />

pagewidth leftmargin sub dx psize mul sub 2 div leftmargin add<br />

pageheight dy psize mul add -2 div<br />

translate<br />

psize psize scale<br />

0 setlinewidth<br />

0 0 moveto dx 0 lineto dx dy lineto 0 dy lineto closepath stroke<br />

/Courier findfont .8 scalefont setfont<br />

1 1 dx 1 sub<br />

{<br />

dup -1 moveto<br />

dup 26 gt<br />

{ 64 add 26 sub } % A..Z<br />

{ 96 add } ifelse % a..z<br />

st exch 0 exch put st<br />

[ 1 0 0 -1 0 0 ] concat -.4 0 rmoveto show [ 1 0 0 -1 0 0 ] concat<br />

} for<br />

1 1 dy 1 sub<br />

{<br />

dup -1 exch moveto 10 (999) cvrs<br />

[ 1 0 0 -1 0 0 ] concat -1 -.4 rmoveto show [ 1 0 0 -1 0 0 ] concat<br />

} for<br />

} ifelse<br />

} def<br />

/iwire % (a1) (c3) iwire<br />

{<br />

exch<br />

cvpad<br />

/xlen xpos def /ylen ypos def<br />

cvpad<br />

/xlen xlen xpos sub def /ylen ylen ypos sub def<br />

0 1 multy 1 sub<br />

{<br />

dy mul ypos add /y exch def<br />

0 1 multx 1 sub<br />

{<br />

dx mul xpos add y moveto xlen ylen rlineto closepath stroke<br />

} for<br />

} for<br />

} def<br />

/wire % (a1) (c3) wire<br />

{<br />

0.2 setlinewidth<br />

iwire<br />

} def


ANHANG D. PROGRAMM PCB 232<br />

/wire2 % (a1) (c3) wire2<br />

{<br />

0.8 setlinewidth<br />

iwire<br />

} def<br />

/ipad<br />

{<br />

0 setlinewidth<br />

0 1 multy 1 sub<br />

{<br />

dy mul ypos add /argy exch def<br />

0 1 multx 1 sub<br />

{<br />

dx mul xpos add /argx exch def<br />

argx argy 0.3 boardscale mul 0 360 arc fill<br />

white setcolor argx argy 0.1 boardscale mul 0 360 arc fill black setcolor<br />

} for<br />

} for<br />

} def<br />

/pad % (a1) pad<br />

{ cvpad ipad } def<br />

/smd<br />

{<br />

cvpad<br />

0 setlinewidth<br />

0 1 multy 1 sub<br />

{<br />

dy mul ypos add /argy exch def<br />

0 1 multx 1 sub<br />

{<br />

dx mul xpos add .25 sub argy .25 sub moveto<br />

.5 0 rlineto 0 .5 rlineto -.5 0 rlineto closepath fill<br />

} for<br />

} for<br />

} def<br />

/xpad % (a1) 3 xpad => (a1) pad (b1) pad (c1) pad<br />

{ 1 sub boardscale mul exch cvpad xpos exch boardscale exch xpos add<br />

{ /xpos exch def ipad } for<br />

} def<br />

/ypad % (a1) 3 ypad => (a1) pad (a2) pad (a3) pad<br />

{ 1 sub boardscale mul exch cvpad ypos exch boardscale exch ypos add<br />

{ /ypos exch def ipad } for<br />

} def<br />

/mirror { pagewidth 0 translate -1 1 scale } def<br />

%(n15)board (n1)(n15)wire (a1)pad(n1)pad(n14)pad(n15)smd (c3)4 xpad(e3)4 ypad<br />

end_of_pslayout<br />

}<br />

#.#############################################################################<br />

#. Methods<br />

#.#############################################################################<br />

################################## info ###################################<br />

Lot="$Lot cat echo"


ANHANG D. PROGRAMM PCB 233<br />

Lom="$Lom info"; pcb.info () { funcname=$Nam.info # 20011207 HKU<br />

case $Met in<br />

help|man) echo "Usage: $funcname [tutorial]"<br />

if test "$Met" = "man"; then echo Informs about programs concepts.; fi;;<br />

doit) Testargs 0;<br />

case "$1" in<br />

"")<br />

cat


ANHANG D. PROGRAMM PCB 234<br />

Global Variables<br />

Global Functions<br />

Methods<br />

Main<br />

müssen in DIESER Reihenfolge vorhanden sein.<br />

#. bedeutet, daß der Kommentar von class verarbeitet wird.<br />

Solche Kommentare dürfen nicht entfernt werden!<br />

Globale Namen Beginnen Mit Einem Großbuchstaben.<br />

VOM SYSTEM ANGEBOTENE VARIABLE SIND I.D.R. KOMPLETT GROSS.<br />

lokale namen sollten klein geschrieben werden.<br />

Für die Anwendung dieses Programmiersystems sind grundlegende Kenntnisse der<br />

(b)ash notwendig (siehe "man bash").<br />

Es folgt eine Liste der Vorzüge des Konzeptes:<br />

Die Bildung von Programmfamilien fördert die Benutzerfreundlichkeit:<br />

Einziger Zugang über den Klassennamen.<br />

Einheitliche Benutzerschnittstelle.<br />

Einheitliche Hilfefunktionen.<br />

Integrierte Installation und Deinstallation.<br />

Integrierte Überprüfung der Systemvoraussetzungen.<br />

Vererbung bessert die Programmqualität:<br />

Fehlerminderung durch Verwendung bewährten Codes.<br />

Kompaktheit durch mehrfache Verwendung des Codes.<br />

Zentrale Haltung globaler Variablen.<br />

Klassenbildung fördert die Tiefe der Problemanalyse.<br />

Programmstruktur ist vorbestimmt.<br />

Kinder erben Funktionalität der Eltern<br />

(z.B. Dokumentation und Installation)<br />

Abgeschlossenheit erhöht die Verfügbarkeit des Programms:<br />

Programminstallation ist überschaubar.<br />

Programmverbreitung ist so einfach wie das Kopieren einer Datei.<br />

Verwendung üblicher Tools wie bash und textutils:<br />

Minimale Systemvoraussetzungen<br />

Portabel<br />

Sofortige Einsetzbarkeit<br />

Wartungsarm, da geringe Umgebungsänderungen zu erwarten.<br />

Programmcode ist eine einfache Text-Datei:<br />

Das Programm ist einsehbar.<br />

Das Programm ist änderbar.<br />

Reinkarnation erhöht die Verfügbarkeit des Konzepts:<br />

Jede Programmkopie verbreitet das Programmiersystem.<br />

Die Verbreitung des Systems erhöht die Benutzerfreundlichkeit.<br />

end_of_info<br />

;;<br />

"tutorial")<br />

cat


ANHANG D. PROGRAMM PCB 235<br />

if test "$Met" = "man"; then cat


ANHANG D. PROGRAMM PCB 236<br />

local m=./usr/share/man/man1<br />

if ! [ -d $c ]; then mkdir $c; chmod 755 ${c}; fi<br />

echo "Call $Nam for copyright-information." >${c}/copyright<br />

echo "Call $Nam for changelog-information." >${c}/changelog.Debian<br />

gzip -9 ${c}/changelog.Debian<br />

chmod 644 ${c}/*<br />

cat >${m}/$Nam.1<br />

(exec $Dir/$Nam.man $n|sed -e 2,\$d -e "s/[^\\.]*\\./.B /" >>${m}/$Nam.1)<br />

(exec $Dir/$Nam.man $n|sed 1d >>${m}/$Nam.1)<br />

done<br />

cat ${m}/$Nam.1<br />

.RE<br />

.SH INFO<br />

EOF<br />

(exec $Dir/$Nam.info >>${m}/$Nam.1)<br />

cat ${m}/$Nam.1<br />

.SH AUTHOR<br />

This manual page was written by $Nam.makedeb.<br />

EOF<br />

gzip -9 ${m}/$Nam.1<br />

chmod 644 ${m}/$Nam.1.gz<br />

tar -zcvf $d.tar.gz .${Location}/$Nam ${c} ${m}/$Nam.1.gz<br />

ar -r ${Nam}_${Version}_${Architecture}.deb \<br />

debian-binary control.tar.gz $d.tar.gz<br />

rm debian-binary control.tar.gz $d.tar.gz<br />

mv ${Nam}_${Version}_${Architecture}.deb $pwd # 20021105 HKU<br />

if [ $Dir != $Location ]; then # 20021121 HKU<br />

rm $Location/$Nam $Location/$Nam.include<br />

fi<br />

;; esac; } # end of method makedeb<br />

################################### new ###################################<br />

Lot="$Lot grep"<br />

Lom="$Lom new"; pcb.new () { funcname=$Nam.new<br />

case $Met in


ANHANG D. PROGRAMM PCB 237<br />

help|man) echo "Usage: $funcname CLASSNAME"<br />

if test "$Met" = "man"; then cat >$tmp<br />

cat $tmp<br />

Prognam="class"<br />

Version="0.4-20050506"<br />

Maintainer="Hanns-Konrad Unger "<br />

Description="Classes for ash and bash"<br />

Architecture="all"<br />

Section="devel"<br />

Priority="optional"<br />

Location="/usr/bin"<br />

Programheader () { cat $tmp;cutsection "$1" $Myp|sed "/^#.Added:/,\$d" >>$tmp;}<br />

gensection "Global Variables"<br />

gensection "Global Functions"<br />

gensection "Methods"<br />

genheader "Main" >>$tmp; cutsection "Main" $Myp >>$tmp<br />

else # new class, no reincarnation<br />

local i=$Dir/$Nam.include<br />

local c=$1<br />

gensection () { # sectionname<br />

genheader "$1" >>$tmp; cutsection "$1" $Myp >>$tmp<br />

echo "#.Added:$(date +%Y%b%d):$Nam:new:$c:$1" >>$tmp<br />

if test -f $i; then cutsection "$1" $i >>$tmp; fi; }<br />

echo ’#!’"/bin/bash" >$tmp<br />

genheader "Programheader" >>$tmp


ANHANG D. PROGRAMM PCB 238<br />

if test -f $i; then local h=$i; else local h=$Myp; fi<br />

cutsection "Programheader" $h|sed "/^#.Usage:/,\$d" >>$tmp<br />

history $1 >>$tmp<br />

cutsection "Programheader" $h|sed -n "/^#.Usage:/,\$p" >>$tmp<br />

gensection "Global Variables"<br />

echo "Loc=\"\$Loc $1\"" >>$tmp<br />

gensection "Global Functions"<br />

gensection "Methods"<br />

genheader "Main" >>$tmp; cutsection "Main" $Myp >>$tmp<br />

fi<br />

sed s/${Nam}\\./$1./g $tmp >$1 # (re)name new class<br />

mv $1 $tmp<br />

sed -n 1,4p $tmp >$1<br />

echo " Prognam=\"$1\"" >>$1<br />

sed -n 6,\$p $tmp >>$1<br />

chmod a+x,a+r $1<br />

### grep $1 $1<br />

if test -f $1.include -o $1 = class; then # create no include<br />

ls -l $1.include<br />

echo "----- No $1.include created. -----"<br />

else # create include for new class<br />

genheader "Programheader" >$1.include<br />

chmod a+r $1.include<br />

cutsection "Programheader" $1 >>$1.include<br />

genheader "Global Variables" >>$1.include<br />

genheader "Global Functions" >>$1.include<br />

genheader "Methods" >>$1.include<br />

cat $1.include<br />

################################ example #################################<br />

#Lot="\$Lot" # List Of Tools (to check installation)<br />

#Lom="\$Lom example"; $1.example () { funcname=$1.example # 20020424 HKU $1<br />

#case \$Met in<br />

# help|man) echo "Usage: \$funcname"<br />

# if test "\$Met" = "man"; then cat


ANHANG D. PROGRAMM PCB 239<br />

pcb.layout makes postscriptfile for layout<br />

pcb.mlayout makes multiple layouts (for schools..)<br />

pcb.list generate part-list<br />

** pcb.move dx dy move a circuit<br />

** pcb.rotate rotate a circuit 90 degree<br />

** pcb.parts make part-position-plan<br />

pcb.kit Heathkit-Style soldering instructions<br />

** Todo<br />

Example of a circuit-list for input:<br />

------------------------------------------------------------------------<br />

#<br />

# Name: ispbsd.pcb<br />

# Function: Atmel ISP interface for uisp -dprog=bsd<br />

# Centronics If. Atmel Progrport.<br />

# Pin02 Data0 --> Vcc Pin02<br />

# Pin03 Data1 --> Vcc Pin02<br />

# Pin04 Data2 --> Vcc Pin02<br />

# Pin05 Data3 --> Vcc Pin02<br />

# Pin06 Data4 --> /Enable<br />

# Pin07 Data5 --> /Reset Pin05<br />

# Pin08 Data6 --> SCK Pin07<br />

# Pin09 Data7 --> MOSI Pin01<br />

# Pin10 Ack


ANHANG D. PROGRAMM PCB 240<br />

(e10)pad :0:B5 :Draht : :nach Pin8 einlöten<br />

(g8)pad :0:B6 :Draht : :nach Pin7 einlöten<br />

(i10)pad :0:B7 :Draht : :nach Pin6 einlöten<br />

(e13)pad :0:B8 :Draht : :nach Pin9 einlöten<br />

(f13)pad :0:B9 :Draht : :nach Pin7 einlöten<br />

(g13)pad :0:B10 :Draht : :nach Pin5 einlöten<br />

(h13)pad :0:B11 :Draht : :nach Pin3 einlöten<br />

(i13)pad :0:B12 :Draht : :nach Pin1 einlöten<br />

(i4)pad :4:D1 :Schottkydioden BAT43 :153010:nach Pin5 einlöten<br />

(j4)pad :0:D2 :Schottkydiode BAT43 :153010:nach Pin4 einlöten<br />

(k4)pad :0:D3 :Schottkydiode BAT43 :153010:nach Pin3 einlöten<br />

(l4)pad :0:D4 :Schottkydiode BAT43 :153010:nach Pin2 einlöten<br />

(i5)pad(j5)pad :1:LED1:Leuchtdiode gelb 3mm 2mA :145998:Anode in i5 einlöten<br />

(c12)pad(j12)pad:1:R1 :Widerstand 2k2 Ohm :408212:einlöten<br />

(k7) 5 ypad\<br />

(l7) 5 ypad :1: :Schalter 2xUM :708216:Schlitze sägen und einlöten<br />

(c4) 8 ypad\<br />

(f4) 8 ypad :1:IC1 :IC 74HC367 :151165:einlöten<br />

-----------------------------------------------------------------------end_of_info<br />

;; esac ; } # end of method info<br />

################################## kit ###################################<br />

Lot="$Lot" # List Of Tools (to check installation)<br />

Lom="$Lom kit"; pcb.kit () { funcname=pcb.kit<br />

case $Met in<br />

help|man) echo "Usage: $funcname FILENAME"<br />

if test "$Met" = "man"; then cat


ANHANG D. PROGRAMM PCB 241<br />

pslayout $1<br />

sed -e "/^#/d" -e "/^$/d" -e "s/\\\//" $1| cut -d: -f1<br />

echo showpage<br />

;; esac ; } # end of method layout<br />

################################## mlayout ###################################<br />

Lot="$Lot" # List Of Tools (to check installation)<br />

Lom="$Lom mlayout"; pcb.mlayout () { funcname=pcb.mlayout<br />

case $Met in<br />

help|man) echo "Usage: $funcname FILENAME x y"<br />

if test "$Met" = "man"; then cat &1; then echo CANNOT FIND Program $n !; fi; done<br />

if test $Myn = $Prognam; then # basic Classname. called<br />

Programheader<br />

for n in help man deinstall $(echo $Lom); do Install $Nam.$n; done<br />

else # method Classname.Fun called<br />

if [ "$1" = "-h" -o "$1" = "--help" ]; then ${Dir}/${Nam}.help ; Quit -1; fi<br />

trap "Quit -1" SIGINT # ^C<br />

case $Fun in<br />

man)<br />

case $1 in<br />

"") echo Usage: ${Nam}.man METHODNAME;;<br />

deinstall) echo ${Nam}.$1 Unlinks all methods.;;<br />

help) echo ${Nam}.$1 Gives short help for all methods.;;<br />

man) echo ${Nam}.$1 Gives help for named method.;;<br />

*) Met=$Fun; ${Nam}.$1;;<br />

esac;;<br />

help)<br />

echo Usage: ${Nam}<br />

echo Usage: ${Nam}.deinstall<br />

echo Usage: ${Nam}.help<br />

echo Usage: ${Nam}.man METHODNAME<br />

for n in $(echo $Lom|tr " " "\n"|sort|uniq); do


ANHANG D. PROGRAMM PCB 242<br />

Met=help; ${Nam}.$n; done # calls function<br />

;;<br />

deinstall)<br />

for n in help man deinstall $(echo $Lom); do Deinstall ${Nam}.$n; done<br />

for n in ${Dir}/${Nam}*; do<br />

if [ "$n" != "${Dir}/${Nam}" ] &&\<br />

[ "$n" != "${Dir}/${Nam}.include" ]; then<br />

echo Ambiguous file $n found, please remove by hand:<br />

ls -l $n<br />

fi<br />

done;;<br />

*)<br />

for n in $Lom; do<br />

if test $n = $Fun<br />

then Met=doit; ${Nam}.$Fun "$@"; Quit 0; fi<br />

done<br />

echo $Dir/$Nam.$Fun is a unlisted method. Please remove it.<br />

Quit -1;;<br />

esac<br />

fi<br />

Quit 0


Anhang E<br />

Skalieren des Systems<br />

Abbildung E.1: Kleine Variante des Experimentiersystems<br />

243


ANHANG E. SKALIEREN DES SYSTEMS 244<br />

Die im Buch beschriebene Variante <strong>mit</strong> LCD-Display, Lochrasterfeld<br />

und Netzteil ist aufwändiger als ein für viele Experimente<br />

ausreichendes Minimum.<br />

Wird die ISP-Hardware der Centronics-Schnittstelle und ein<br />

teurerer MAX 3232 verwendet, so kann ohne zusätzliche<br />

Stromversorgung gearbeitet werden. Das System wird vom<br />

PC über die Programmierschnittstelle <strong>mit</strong>versorgt.<br />

Gegebenenfalls kann die Hardware so reduziert werden, dass<br />

für große Gruppen eine finanzielle Entlastung spürbar wird.<br />

Das in Abbildung E.1 gezeigte Experimentiersystem dürfte<br />

im Verhältnis Preis zu Leistung schwer zu unterbieten sein.<br />

Drei komplette Systeme können <strong>mit</strong> einer einseitigen Europaplatine<br />

aufgebaut werden. Die Kosten der Bauteile liegen im<br />

Bereich einer Audio-CD.<br />

Abbildung E.2: Layout des kleinen Experimentiersystems<br />

Nach der Durchführung der Experimente kann die MCU <strong>mit</strong><br />

der ISP-Software von Matthias Weisser [matwei] geladen wer-


ANHANG E. SKALIEREN DES SYSTEMS 245<br />

den. Durch dieses Programm verwandelt sich das Experimentierboard<br />

in ein Programmiergerät, das auch an der USB-<br />

Schnittstelle noch gut funktionert.<br />

Drei kleine Änderungen werden notwendig:<br />

Die Verbindung zwischen Pin1 (Reset) der MCU und der ISP-<br />

Schnittstelle wird am besten durch einen Jumper aufgetrennt.<br />

Stattdessen wird eine Brücke nach Pin16 (PB2/SS) gelegt, um<br />

einen Reset der externen MCU zu ermöglichen. Nach Setzen<br />

des BOOTRST-Flags benötigt unsere MCU einen 33 nF Kondensator<br />

zwischen Pin1 (Reset) und Masse, da<strong>mit</strong> der Boot-<br />

Loader nach dem Power-On aktiv wird.<br />

Der in der Firmware enthaltene, zum STK500 kompatible,<br />

Boot-Loader ermöglicht sogar den Verzicht auf das<br />

Programmierschnittstellen-Platinchen. Das 1 kByte große Ladeprogramm<br />

läd die Programme direkt von der seriellen<br />

Schnittstelle <strong>mit</strong> dem STK500 Protokoll in den Flash-Speicher<br />

der MCU. Allerdings muss in diesem Fall an eine externe<br />

Stromversorgung gedacht werden.


Anhang F<br />

Die Datei<br />

Mikrocontroller.tgz<br />

246


ANHANG F. DIE DATEI MIKROCONTROLLER.TGZ247<br />

autorun.bat Startdatei für Windows<br />

autorun.inf Startdatei für Windows<br />

Mikrocontroller.ico Icon für Windows<br />

index.html Startdatei für Internet-Browser<br />

Readme diese Datei<br />

hardware Verzeichnis <strong>mit</strong> Schaltplänen etc.<br />

software Verzeichnis <strong>mit</strong> Software zum Üben<br />

book Verzeichnis des Buches<br />

dokus Verzeichnis <strong>mit</strong> Datenblättern<br />

packets Verzeichnis <strong>mit</strong> Softwarepaketen<br />

bin Verzeichnis <strong>mit</strong> ausführbaren Programmen


Anhang G<br />

Rechtliches<br />

Dieses Buch <strong>mit</strong> den Beispielprogrammen ist Open Source.<br />

Es gelten sinngemäß die Bestimmungen der GPL [gnu] <strong>mit</strong><br />

folgender Einschränkung:<br />

Der Autor wünscht für das Anlegen jeder Kopie, die außerhalb<br />

seines Einflußbereiches erstellt wird, eine Spende von<br />

10,10 Euro an eine der folgenden Institutionen:<br />

• FSF — Free Software Foundation<br />

FSF Europe -Chapter Germany e.V.<br />

National-Bank Essen, BLZ 360 200 30, Konto 300 4724<br />

• Greenpeace e. V., Hamburg<br />

Postbank, BLZ 200 100 20, Konto 20 61-206<br />

248


ANHANG G. RECHTLICHES 249<br />

• UNICEF — United Nations Children’s Fund<br />

Stadtsparkasse Köln, BLZ 370 502 98, Konto 999 2959


Anhang H<br />

Helfer<br />

Ein Moment der Besinnung: Allein die Vorkehrungen für<br />

Strom aus der Steckdose sind unüberschaubar. — Daneben<br />

sind andere Hilfen natürlich besonders auffällig:<br />

Ohne Internet und Suchmaschinen wie www.google.de hätte<br />

der Autor weder die gesuchten Informationen noch Programme<br />

erhalten. Besonders hilfreich waren:<br />

• www.atmel.com — Datenblätter, Datenbücher und Applikationen<br />

zu den AVR-<strong>Mikrocontrollern</strong> gibt es direkt<br />

vom Hersteller.<br />

• www.avrfreaks.net — Ein Pool von Informationen zu<br />

den AVRs aus der Sicht der Praktiker.<br />

• www.debian.de — Hier fanden sich die aktuellen Versionen<br />

von avr-gcc, avr-binutils, avr-lib und uisp.<br />

250


ANHANG H. HELFER 251<br />

Dieses Buch wurde <strong>mit</strong> Programmen erstellt, die frei erhältlich<br />

sind. Ich möchte sie deshalb nicht unerwähnt lassen:<br />

Distribution Debian<br />

Betriebssystem Linux<br />

Shell bash<br />

Tools GNU<br />

Fenstersystem X11<br />

Editor vim<br />

Scannerprogramm sane<br />

Bildbearbeitungsprogramm gimp<br />

CAD-Programm qcad<br />

Schaltpläne electric<br />

Textsatzsystem pdfL ATEX<br />

Postscript-Emulation Ghostscript<br />

Auf dem Weg vom Manuskript zum Buch braucht man Lektoren.<br />

Der Mühe des Korrekturlesens haben sich unterzogen:<br />

• Frau Ruth Unger<br />

• Frau Helga Bruns<br />

• Herr Andreas Mull<br />

Einen herzlichen Dank an die Helfer.


Abbildungsverzeichnis<br />

2.1 Direkter Nachfahre des Abakus. . . . . . . . . 23<br />

4.1 DB9-Stecker des IBM-AT . . . . . . . . . . . 35<br />

8.1 Gute und schlechte Lötverbindungen. . . . . . 70<br />

8.2 Schaltung einer Spannungsmessung. . . . . . 73<br />

8.3 Schaltung einer Strommessung. . . . . . . . . 74<br />

8.4 Schaltung einer Widerstandsmessung. . . . . 75<br />

9.1 Stecker . . . . . . . . . . . . . . . . . . . . . . 78<br />

9.2 Amerikanisches und europäisches Widerstandssymbol<br />

. . . . . . . . . . . . . . . . . . . . . . 80<br />

9.3 Widerstände . . . . . . . . . . . . . . . . . . . 81<br />

9.4 Kondensator und Elektrolytkondensator . . . 83<br />

252


ABBILDUNGSVERZEICHNIS 253<br />

9.5 Kondensatoren . . . . . . . . . . . . . . . . . 84<br />

9.6 Schaltsymbol für einen Quarz . . . . . . . . . 85<br />

9.7 Quarze . . . . . . . . . . . . . . . . . . . . . . 86<br />

9.8 Schaltsymbole verschiedener Dioden . . . . . . 87<br />

9.9 Dioden . . . . . . . . . . . . . . . . . . . . . . 88<br />

9.10 Transistoren . . . . . . . . . . . . . . . . . . . 89<br />

9.11 Transistoren . . . . . . . . . . . . . . . . . . . 90<br />

9.12 Integrierte Schaltungen . . . . . . . . . . . . . 91<br />

10.1 Ätzmaske für 15 Platinen. . . . . . . . . . . . 101<br />

11.1 IC SN7400 <strong>mit</strong> 4 NAND-Gattern . . . . . . . 113<br />

11.2 Prellfreie Taste . . . . . . . . . . . . . . . . . 115<br />

12.1 KIM-1 Mikrocomputer der Firma MOS aus<br />

dem Jahr 1975. . . . . . . . . . . . . . . . . . 120<br />

12.2 Architektur des ATmega8 . . . . . . . . . . . 127<br />

13.1 Schaltplan der Centronics Variante des ISP-<br />

Interface . . . . . . . . . . . . . . . . . . . . . 133<br />

13.2 Layout der Centronics Variante des ISP-Interface134<br />

13.3 ISP-Interface in der Centronics Variante. . . . 135


ABBILDUNGSVERZEICHNIS 254<br />

13.4 Schaltplan der RS232 Variante des ISP-Interface137<br />

13.5 Layout der RS232 Variante des ISP-Interface . 138<br />

13.6 ISP-Interface in der RS232 Variante. . . . . . 138<br />

13.7 Schaltplan der USB Variante des ISP-Interface 140<br />

13.8 Layout der USB Variante des ISP-Interface . . 142<br />

13.9 ISP-Interface in der USB Variante. . . . . . . 143<br />

13.10Schaltplan der ersten sechs Baustufen . . . . . 147<br />

13.11Layout der Hauptplatine . . . . . . . . . . . . 148<br />

13.12Erste Baustufe . . . . . . . . . . . . . . . . . 154<br />

13.13Schnell blinkende Leuchtdiode . . . . . . . . . 159<br />

13.14Adapter . . . . . . . . . . . . . . . . . . . . . 171<br />

E.1 Kleine Variante des Experimentiersystems . . 243<br />

E.2 Layout des kleinen Experimentiersystems . . . 244


Literaturverzeichnis<br />

[Formeln] Bartsch, Hans-Jochen:<br />

Mathematische Formeln<br />

(1977, VEB Fachbuchverlag Leipzig)<br />

[Kernighan] Brian W. Kernighan/Dennis M. Ritchie:<br />

Programmieren in C.<br />

(1990, Carl Hanser Verlag, München Wien)<br />

[C] Kernighan/Ritchie:<br />

The C Programming Language.<br />

(1978, Printice-Hall Inc. Englewood Cliffs,<br />

New Jersey)<br />

[C++] Stroustrup, Bjarne:<br />

The C++ Programming Language.<br />

(1987, Addison-Wesley Publishing Company)<br />

[Linux] Hetze, Hohndel, Müller, Kirch:<br />

Linux Anwenderhandbuch<br />

(1993..., LunetIX Softfair)<br />

255


LITERATURVERZEICHNIS 256<br />

[Torvalds] Linus Torvalds und David Diamond:<br />

Just for Fun.<br />

(2002, DTV Deutscher Taschenbuch Verlag)<br />

[Elektor] Michael Möge:<br />

Tipps zur Platinenherstellung<br />

Elektor 2002-09p36<br />

[adobe] http://www.adobe.com<br />

Homepage der Postscript-Entwickler.<br />

[atmel] http://www.atmel.com<br />

Homepage des IC-Herstellers.<br />

[avrdude] http://www.savannah.nongnu.org/projects/avrdude<br />

CVS-Verzeichnis eines Programmes zur<br />

In-System-Programmierung von AVR-<br />

<strong>Mikrocontrollern</strong> unter Linux<br />

[debian] http://www.debian.de<br />

Debian ist eine umfassende freie GNU/Linux<br />

Distribution.<br />

[fischl] http://www.fischl.de<br />

Homepage eines ISP für den USB, der usbasp<br />

genannt wird.<br />

[gnu] http://www.gnu.org/licences<br />

GNU General Public Licence.


LITERATURVERZEICHNIS 257<br />

[knoppix] http://www.knoppix.de<br />

Debian basiertes Linux, läuft ohne Installation.<br />

[obdev] http://www.obdev.at<br />

Entwickeln USB-Lösungen <strong>mit</strong> <strong>Mikrocontrollern</strong>.<br />

[unger] http://www.hanns-konrad.de<br />

Homepage des Autors.<br />

[usb] http://www.usb.org<br />

Die Homepage des Universal Serial Bus.<br />

[matwei] http://www.matwei.de<br />

Homepage eines ISP für den USB, der usbisp<br />

genannt wird.<br />

[winavr] http://winavr.sourceforge.net<br />

Frei Entwicklungssoftware für AVRs.<br />

[wikipedia] http://de.wikipedia.org<br />

Eine Enzyklopädie im Internet, die Begriffe<br />

aus der <strong>Computertechnik</strong> gut abdeckt. Sie ist<br />

in verschiedenen Sprachen verfügbar.

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!