<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://www.mikrocontroller.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Nollsen</id>
	<title>Mikrocontroller.net - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="https://www.mikrocontroller.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Nollsen"/>
	<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/articles/Spezial:Beitr%C3%A4ge/Nollsen"/>
	<updated>2026-04-23T09:11:01Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.39.7</generator>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_Checkliste&amp;diff=35304</id>
		<title>AVR Checkliste</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_Checkliste&amp;diff=35304"/>
		<updated>2009-03-23T10:51:10Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: /* Software */ volatile hinzugefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:AVR]]&lt;br /&gt;
Diese Seite soll als erste Anlaufstelle dienen, wenn der [[AVR]]-Mikrocontroller mal wieder nicht so will wie er soll. Es wird versucht, die Standardfehler und Probleme aufzulisten und zu erklären, was man dagegen tun kann.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
=== Anderen Controller benutzt als den im Schaltplan: Pinkompatibilität sichergestellt? ===&lt;br /&gt;
&lt;br /&gt;
Nur wenige AVR-Controller sind pinkompatibel und damit untereinander austauschbar. Manchmal liegen gar die am dringensten benötigten Funktionen (ISP-Programmierung) bei anderen Controllern auf anderen Pins. Unbedingt vorher die Belegungen anhand der Datenblätter vergleichen!&lt;br /&gt;
&lt;br /&gt;
=== Fuses richtig gesetzt? ===&lt;br /&gt;
&lt;br /&gt;
Die AVR-Controller haben &#039;Fuses&#039; (deutsch: &#039;Sicherungen&#039;), die das Verhalten des Prozessors auf grundlegender Ebene bestimmen. Ein häufiger Fehler ist beispielsweise, dass die falsche Taktquelle gewählt wurde (Fuse &amp;quot;CKSEL&amp;quot; etc.): einige AVRs können mit dem internen Oszillator (&amp;lt;i&amp;gt;internal R/C&amp;lt;/i&amp;gt;), mit einem externen Oszillator (&amp;lt;i&amp;gt;external clock&amp;lt;/i&amp;gt;), mit einem Quarz (&amp;lt;i&amp;gt;external crystal&amp;lt;/i&amp;gt;) oder mit einem Resonator (&amp;lt;i&amp;gt;external R/C&amp;lt;/i&amp;gt;) betrieben werden. Wenn die Einstellung über die Fusebits nicht dazu passt (z. B. &amp;lt;i&amp;gt;external clock&amp;lt;/i&amp;gt; statt &amp;lt;i&amp;gt;external crystal&amp;lt;/i&amp;gt;), fehlt dem Controller unter Umständen der Systemtakt und er läuft nicht an, oder man bekommt auf der seriellen Schnittstelle Nonsens, oder die Timer bzw. Zeitschleifen im Programm laufen zu langsam oder zu schnell.&lt;br /&gt;
&lt;br /&gt;
Eine andere Fuse (JTAGEN) schaltet auf einem Port (z.B. PORTC auf ATMega32) die JTAG-Unterstützung ein bzw. aus. Wenn sie eingeschaltet ist, funktionieren vier Bits dieses Ports nicht wie gewohnt, da sie für die JTAG-Schnittstelle reserviert werden.&lt;br /&gt;
&lt;br /&gt;
In dem zum STK500 gehörenden Entwicklungstool &#039;AVR Studio&#039; gibt es in der Programmer-Dialogbox einen Tab &#039;Fuses&#039;, der controllerabhängig den Status der Fusebits anzeigt und Änderungen ermöglicht.&lt;br /&gt;
Siehe auch: [[AVR Fuses]].&lt;br /&gt;
&lt;br /&gt;
=== ISP-Adapter ===&lt;br /&gt;
&lt;br /&gt;
Bei ISP-Programmieradaptern für den Parallelport kann es zu Inkompatibilitäten mit manchen Ports kommen. Tritt das Problem auch auf, wenn der ISP-Adapter an einem anderen Rechner angeschlossen ist? Funktioniert es vielleicht mit einer anderen Software? Siehe auch: [[AVR In System Programmer]]).&lt;br /&gt;
&lt;br /&gt;
Bei seriellem Programmer mit Controller (STK500, Atmel AVRISP etc.): Programmieren dauert sehr lange, es gibt Fehler. Abhilfe: ISP Taktrate richtig einstellen (&amp;lt;1/4 F_CPU).&lt;br /&gt;
&lt;br /&gt;
Beim Programmieren mit dem usbasp Programmieradapter muss die Geschwindigkeit richtig eingestellt werden. Bei einem AVR der auf den eingebauten 1 Mhz läuft muss mit langsamer Geschwindigkeit (Jumper zu) programmiert werden.&lt;br /&gt;
&lt;br /&gt;
=== Spannungsversorgung richtig angeschlossen? ===&lt;br /&gt;
&lt;br /&gt;
Der AVCC-Pin ist der Versorgungsanschluss für den AD-Wandler und den zugehörigen Port. Er ist nicht an allen AVRs vorhanden; wenn er aber vorhanden ist, so muss er auf jeden Fall angeschlossen sein, auch wenn der AD-Wandler nicht benutzt wird. Wird der AD-Wandler verwendet, sollte zur Verbesserung der Genauigkeit der AVCC-Pin über einen Lowpass-Filter angeschlossen werden (siehe Datenblatt).&lt;br /&gt;
Oft funktioniert die Programmierung des Controllers auch, wenn Vcc oder GND nicht richtig angeschlossen ist. Zur Sicherheit kann man mit einem Messgerät direkt an den Anschlüssen des AVRs kontrollieren (VCC-GND, AVCC-GND) prüfen, ob die Verbindungen korrekt sind. Es empfiehlt sich, vor dem Einsetzen bzw. Einlöten des Controllers die Versorgungsanschlüsse nochmals zu prüfen, um sicherzustellen, dass man den IC nicht durch eine zu hohe Spannung aufgrund eines Fehlers in der Versorgung zerstört.&lt;br /&gt;
&lt;br /&gt;
=== Reset-Pin korrekt beschaltet? ===&lt;br /&gt;
&lt;br /&gt;
Der Reset-Anschluss am AVR ist &#039;active-low&#039;, d. h. wenn man den Pin mit GND (Masse) verbindet, wird der Controller resettet. Zwar haben AVRs einen internen Pullup-Widerstand, der den Reset-Pin gegen VCC &amp;quot;zieht&amp;quot;, dieser ist jedoch relativ hochohmig (ca. 50 kOhm, vgl. Datenblatt) und reicht unter Umständen nicht aus, um den Reset-Pin sicher &amp;quot;hochzuhalten&amp;quot;. Als Mindestbeschaltung empfiehlt sich dringend, einen externen Pullup-Widerstand vorzusehen (typisch 10 kOhm), der den Reset-Pin mit VCC verbindet. Er sollte nicht kleiner als 4,7 kOhm sein, da der Programmieradapter sonst eventuell den Reset-Pin während des Programmiervorgangs nicht sicher auf &amp;quot;low&amp;quot; ziehen kann. Zusätzlich sollte man auch noch einen Kondensator 47 nF oder 100 nF zwischen Reset-Pin und GND anordnen. Dieses RC-Glied sorgt dafür, dass der Controller beim Einschalten der Versorgungsspannung für eine definierte Zeitspanne im Reset gehalten wird. Im laufenden Betrieb sorgt der Kondensator dafür, dass der Reseteingang unempfindlich gegenüber Spikes und Glitches wird. Er sollte deshalb unmittelbar in Pin-Nähe beim Prozessor untergebracht werden. Dieser Kondensator darf jedoch nicht verwendet werden, wenn [[debugWIRE]] möglich sein soll.&lt;br /&gt;
&lt;br /&gt;
Atmel empfiehlt zusätzlich noch zum Schutz vor Überspannungen eine externe Diode nach VCC (&amp;quot;Clamp-Diode&amp;quot;), da für den Reset-Pin keine interne vorhanden ist. Diese Diode bereitet jedoch bei manchen Programmieradaptern Schwierigkeiten. Allerdings schützt die Diode den Controller davor, in den High-Voltage Programming Mode zu schalten, zum Beispiel als Folge von Störspannung wegen EMV, und dadurch den Programmspeicher zu überschreiben.&lt;br /&gt;
&lt;br /&gt;
=== Abblockkondensator(en) ordnungsgemäß installiert? ===&lt;br /&gt;
&lt;br /&gt;
Abblockkondensatoren (&amp;quot;Bunker-Kondensatoren&amp;quot;) dienen dazu, sehr kurze Versorgungsspannungseinbrüche, die durch Schaltvorgänge verursacht werden können, zu kompensieren. Diesen Zweck erfüllen sie optimal, wenn folgende Regeln eingehalten werden: &lt;br /&gt;
&lt;br /&gt;
* Ein Abblockkondensator sollte möglichst dicht am IC sitzen.&lt;br /&gt;
&lt;br /&gt;
* Jedes IC in einer Schaltung sollte einen Abblockkondensator besitzen.&lt;br /&gt;
&lt;br /&gt;
* Bei ICs mit mehreren Anschlüssen für VCC und GND sollte jedes VCC-GND-Paar mit einem eigenen Abblockkondensator beschaltet werden (z. B. AVRs in SMD-Bauform wie dem ATmega16A also mit vier Kondensatoren).&lt;br /&gt;
&lt;br /&gt;
* Es sollten keramische Kondensatoren mit einer Kapazität von 100 nF verwendet werden. Größere Kondensatoren, etwa 10 µF-Elkos, sind für diese Aufgabe &#039;&#039;nicht&#039;&#039; geeignet, weil sie &amp;quot;zu langsam&amp;quot; sind!&lt;br /&gt;
&lt;br /&gt;
=== Quarz oder Quarzoszillator angeschlossen? ===&lt;br /&gt;
&lt;br /&gt;
Die neueren AVRs haben einen internen [[Oszillator]], der im Auslieferungszustand über die entsprechenden Fuses eingeschaltet ist. In diesem Fall muss kein externer [[Quarz]] mehr angeschlossen werden. Man kann in den [[AVR Fuses|Fuse-Bits]] aber einstellen, dass man einen externen Taktgenerator (&#039;&#039;external clock&#039;&#039;, z. B. Quarzoszillator) oder externen Quarz (&#039;&#039;external crystal&#039;&#039;) verwenden möchte.&lt;br /&gt;
&lt;br /&gt;
Dann, oder wenn der AVR keinen internen Takt hat, wird an die entsprechenden Pins des Controllers ein Quarz (&#039;&#039;external crystal&#039;&#039;, Bauelement mit zwei &amp;quot;Beinchen&amp;quot;) oder Quarzoszillator (&#039;&#039;external clock&#039;&#039;, Bauelement mit vier &amp;quot;Beinchen&amp;quot;) angeschlossen. Im Falle eines Quarzes werden die XTAL-Pins mit den beiden Anschlüssen des Quarzes und jeweils mit einem Kondensator (ca. 12 bis 22 pF) (vgl. Datenblatt ATMega 8) gegen Masse angeschlossen. Im Falle eines Quarzoszillators reicht es aus, den Taktausgang mit dem XTAL1-Pin zu verbinden, und den XTAL2-Pin unbeschaltet zu lassen. Die Fuses sind entsprechend einzustellen.&lt;br /&gt;
&lt;br /&gt;
=== Alle Ground-Anschlüsse beschaltet? ===&lt;br /&gt;
&lt;br /&gt;
Bei AVRs mit mehreren Ground-Anschlüssen müssen alle Anschlüsse beschaltet werden. Siehe http://www.mikrocontroller.net/forum/read-1-107259.html&lt;br /&gt;
&lt;br /&gt;
=== Alle Lötstellen in Ordnung? ===&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Kalte&amp;quot;, d.h. schlechte Lötstellen erkennt man an ihrer matten Oberfläche (bei bleihaltigem Lot). Bei beschädigten Lötstellen erkennt man oft einen Riss, der sich kreisförmig um die Mitte des Lötpunktes herum gebildet hat. Solche Stellen verursachen oft erst bei mechanischer Beanspruchung Probleme.&lt;br /&gt;
&lt;br /&gt;
Bei kleinen Abständen (SMD-Bauteile) müssen besonders Verbindungen zwischen benachbarten Lötungen kontrolliert werden.&lt;br /&gt;
&lt;br /&gt;
Bei Lochrasterplatinen kann man mit einem spitzen Messer (Bastelmesser) die Zwischenräume von möglichen leitenden Verbindungen befreien. &lt;br /&gt;
&lt;br /&gt;
=== Eingänge ===&lt;br /&gt;
&lt;br /&gt;
Taster müssen:&lt;br /&gt;
&lt;br /&gt;
* entprellt werden ([[Entprellung]])&lt;br /&gt;
&lt;br /&gt;
* einen [[AVR-GCC-Tutorial#Tasten_und_Schalter|Pullup-Widerstand]] besitzen, so sie &#039;&#039;active-low&#039;&#039; betrieben werden, d.h. wenn beim Tastendruck der Pin mit GND (Masse) verbunden wird (dies ist die übliche Anschaltung). Man kann einen externen Pull-Up Widerstand (typ. 10 kOhm) benutzen oder den internen aktivieren (DDR als Eingang also &amp;quot;0&amp;quot;, PORT auf &amp;quot;1&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Will man einen Taster &#039;&#039;active-high&#039;&#039; betreiben, soll also bei Tastendruck eine &amp;quot;1&amp;quot; in PIN gelesen werden, ist ein externer Pull-Down-Widerstand (typ. 10 kOhm) gegen GND anzuschließen, denn interne Pull-Downs sind nicht verfügbar.&lt;br /&gt;
&lt;br /&gt;
Symptome: Aufgrund des Prellens bekommt man bei einem Tastendruck statt eines Signals mehrere, und beim fehlenden Pullup fängt man sich Störungen (z.B. das 50 Hz-Netzbrummen) ein, da der Pin nicht auf einem &amp;quot;definierten Pegel&amp;quot; liegt, wenn der Taster nicht geschlossen ist. Soll z.B. bei einem Tastendruck eine LED angehen, dann leuchtet die LED durch das Netzbrummen plötzlich mit 50 Hz anstatt aus zu sein.&lt;br /&gt;
&lt;br /&gt;
* active low: ein Anschluss des Tasters an den Port-Pin, den anderen Taster-Anschluss an GND; internen Pull-Up-Widerstand aktivieren oder externen Widerstand zwischen Port-Pin und VCC.&lt;br /&gt;
&lt;br /&gt;
* active high: Taster zwischen Port-Pin und VCC; externen Widerstand zwischen Port-Pin und GND.&lt;br /&gt;
&lt;br /&gt;
=== Ausgänge ===&lt;br /&gt;
&lt;br /&gt;
Man sollte darauf achten, das &amp;quot;kritische&amp;quot; Ausgänge, d.h. Ausgänge, über die nicht &amp;quot;nur&amp;quot; eine LED geschaltet wird, einen definierten Zustand haben, wenn der Portpin auf &amp;quot;Eingang&amp;quot; und damit hochohmig geschaltet ist. Dadurch wird sichergestellt, dass beim Einschalten nicht kurz ein Verbraucher geschaltet wird (z.B. &amp;quot;Zucken&amp;quot; eines Motors). Dies kann man bewerkstelligen, indem man extern Widerstände (auch hier Pull-Up bzw. Pull-Down genannt, typ. 10 kOhm) an den Ausgangs-Pins vorsieht, die den Ausgang auf den gewünschten Zustand ziehen.&lt;br /&gt;
&lt;br /&gt;
=== Besonderheiten bei ATmega128 und seinen Derivaten im 64-Pin-Gehäuse===&lt;br /&gt;
&lt;br /&gt;
Der ATmega64 und der ATmega128 sowie &amp;lt;b&amp;gt; alle vom ATMega128 abgeleiteten AVRs im 64-Pin-Gehäuse&amp;lt;/b&amp;gt; (ATMega641/1281/2561 sowie AT90CAN32/64/128, &amp;lt;b&amp;gt;Ausnahme&amp;lt;/b&amp;gt; sind nur AT90USB64/128, die eine ganz andere Pinbelegung haben) haben besondere Fallstricke, über die man bei nicht ausreichendem Datenblattstudium leicht stolpert. &lt;br /&gt;
&lt;br /&gt;
* Der erste betrifft den Anschluss der ISP-Signale (MISO, MOSI, SCK, RESET). Dieser erfolgt nicht wie bei den meisten anderen AVR-Controllern an den gleichnamigen Pins, sondern an PDI, PDO, SCK und RESET. Die Pinzuordnung ist:  MOSI-&amp;gt;PE0 (Pin 2), MISO-&amp;gt;PE1 (Pin 3), SCK-&amp;gt;PB1 (Pin 11) und RESET-&amp;gt;RESET (Pin 20). PEN (Pin 1) hat für normale ISP-Adapter keine Bedeutung und kann offen gelassen oder direkt mit Vcc verbunden werden. Die Benutzung der Pins PDI und PDO anstelle von MOSI und MISO gilt für praktisch alle ATMega128-Derivate im 64-Pin-TQFP-Gehäuse (darunter AT90CAN32/64/128, ATMega641/1281/2561)! Im Zweifelsfall im Datenblatt (Pin Configuration) nachsehen, ob PE0 und PE1 mit &amp;quot;PDI&amp;quot; bzw. &amp;quot;PDO&amp;quot; beschriftet sind.&lt;br /&gt;
&lt;br /&gt;
* Die zweite kleine &amp;quot;Gemeinheit&amp;quot; betrifft die &#039;&#039;&#039;M103C-Fuse&#039;&#039;&#039; (Atmega103 Compatibility Mode, nur bei den ATMega-Typen, nicht beim AT90CAN32/64/128). Diese ist bei fabrikneuen Atmega64/128 und Atmega641/1281/2561 gesetzt und sorgt dafür, dass sich diese wie ein Atmega103 verhalten.&lt;br /&gt;
** Dies hat zur Folge, dass ein für den Atmega64 oder Atmega128 geschriebenes Programm beim ersten &amp;quot;ret&amp;quot; abstürzt, da der SRAM an einer anderen Stelle liegt als erwartet und somit der Prozessor keine gültige Rücksprungadresse vom Stack holen kann. &lt;br /&gt;
** Außerdem funktionieren einige IO-Pins an PORTC, PORTF und PORTG anders.&lt;br /&gt;
** Für weitere Infos bzgl. [[TWI]], [[UART]], [[Timer]], [[Bootloader]] und Kalibrierung des internen RC-Oszillators unbedingt das Datenblatt lesen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:isp.jpg|640px]]&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
&lt;br /&gt;
=== Alle Interruptvektoren definiert? ===&lt;br /&gt;
&lt;br /&gt;
Wenn man irgendwelche [[Interrupt]]vektoren verwendet, sollte man alle definieren, auch die nicht benutzten. Passiert es dann aufgrund eines Fehlers, dass ein Interrupt unbeabsichtigt ausgeführt wird, so führt der Controller dann eine definierte Aktion aus. Benutzt man eine Hochsprache wie C oder Basic, nimmt einem der Compiler diese Arbeit ab.&lt;br /&gt;
&lt;br /&gt;
Ausserdem sollte man immer im Datenblatt des Controllers nachsehen, wie die Interrupttabelle aufgebaut ist. Die kleinen AVRs verwenden ein &#039;&#039;&#039;RCALL&#039;&#039;&#039; zum Anspringen der Interrupts, welches 1 Wort lang ist. Die grossen AVRs mit mehr als 8 KiBi FLASH verwenden ein &#039;&#039;&#039;CALL&#039;&#039;&#039;, welches 2 Worte lang ist. Verwendet man nun  den falschen Befehl, verschieben sich die Einsprungadressen und das Chaos ist perfekt.&lt;br /&gt;
&lt;br /&gt;
In einem komplett interruptlosen Programm kann man auf die Interrupttabelle selbstverständlich verzichten (erkennbar daran, dass nirgendwo im Code Interrupts mittels Assembler-Befehl &#039;&#039;&#039;sei&#039;&#039;&#039; eingeschaltet werden).&lt;br /&gt;
&lt;br /&gt;
=== Alle Konfigurationsregister korrekt initialisiert? ===&lt;br /&gt;
&lt;br /&gt;
Alle benötigten Konfigurationsregister (auch &amp;quot;I/O-Register&amp;quot; genannt) eines Mikrocontrollers müssen korrekt initialisiert werden. Bei Fehlfunktionen sollten diese Konfigurationen noch einmal mit dem Datenblatt abgeglichen werden. &lt;br /&gt;
Manchmal ist es auch sinnvoll, bestimmte Funktionen explizit abzuwählen. Ein Beispiel hierfür ist der [[Analog-Komparator]] des AVR: Schaltet man diesen ab, wenn man ihn nicht benötigt, kann man dadurch ein wenig Strom sparen. &lt;br /&gt;
Wenn man besonders &amp;quot;sauber&amp;quot; programmieren möchte, initialisiert man Konfigurationsregister immer, d.h. auch wenn sie nicht im Programm verwendet werden. Dies verhindert mögliche zufällige Fehlkonfigurationen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Stackpointer initialisiert? (Nur in Assembler relevant) ===&lt;br /&gt;
&lt;br /&gt;
Fehlerbeschreibung: &#039;&#039;Das Programm lief, bis ein &amp;quot;rcall&amp;quot; oder ein Interrupt eingefügt wurde. Danach ging plötzlich gar nichts mehr.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wahrscheinliche Ursache: Der Stack ist ein spezieller Bereich im RAM, der von Sprungbefehlen und Interruptaufrufen dazu verwendet wird, die Rücksprungadresse ins Hauptprogramm zu speichern.  Da der Stack bei den AVRs nach &amp;quot;unten&amp;quot; wächst, d.h. in Richtung Anfang des RAMs, wird er üblicherweise ans Ende des RAMs gelegt. Der Stack muss vor der ersten Benutzung, am besten direkt am Anfang des Programms, initialisiert werden (sonst ist nach einem Sprung in ein Unterprogramm die Rücksprungadresse undefiniert und das Programm wird an einer unvorhersehbaren Stelle weiter ausgeführt, was in der Regel einen Absturz zur Folge hat). &amp;quot;Den Stack initialisieren&amp;quot; bedeutet, den Stackpointer auf den gewünschten &amp;quot;Startwert&amp;quot; zu setzen. Meistens wird dafür die letzte RAM-Adresse gewählt. &lt;br /&gt;
&lt;br /&gt;
Die Initialisierung unterscheidet sich geringfügig je nach verwendetem AVR. Bei den alten AT90xxxx und den ATtinys ist sie mit zwei Zeilen erledigt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
       ldi r16, RAMEND   ;Die Adresse der letzten Stelle im RAM in r16 laden&lt;br /&gt;
       out SPL, r16      ;Die Adresse in das Register SPL ausgeben&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Da die ATmegas mehr RAM haben, reicht das 8 bit-Register SPL nicht mehr, und es ist ein zweites (SPH) dazugekommen.  Die Initialisierung des Stacks erfordert hier vier Zeilen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
       ldi r16, LOW(RAMEND)    ;Untere 8 bit des 16 bit-Wertes RAMEND laden&lt;br /&gt;
       out SPL, r16&lt;br /&gt;
       ldi r16, HIGH(RAMEND)   ;Obere 8 bit laden&lt;br /&gt;
       out SPH, r16&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 16bit-Register in richtiger Reihenfolge geladen/gelesen? (Nur in Assembler relevant) ===&lt;br /&gt;
&lt;br /&gt;
Bei den 16-bit Registern (z.B. Timer1) genau die Hinweise im Kapitel &amp;quot;Accessing 16-bit Registers&amp;quot; beachten!&lt;br /&gt;
&lt;br /&gt;
So muss z.B. das High-Byte VOR dem Low-Byte geschrieben werden, weil mit dem Schreiben des Low Byte das gesamte Register &amp;quot;übernommen&amp;quot; wird.&lt;br /&gt;
Beim Lesen muss zuerst das Low-Byte gelesen werden, dann das High-Byte.&lt;br /&gt;
Es wird dadurch garantiert, dass sich zwischen den beiden einzelnen Befehlen nicht noch das Register weiter verändert, z.B. beim 16bit Counter.&lt;br /&gt;
Möglich wird das durch ein &amp;quot;temporary Register&amp;quot;, von dem es aber nur eines gibt - was beachtet werden muss, da zwischen diesen beiden einzelnen Lese-/Schreib-Befehlen kein Interrupt auftreten darf, der selber das temporary Rgegister benutzt.&lt;br /&gt;
&lt;br /&gt;
In C oder Basic kümmert sich der Compiler um das Problem - man liest oder beschreibt dann einfach z.B. TCNT1 anstatt TCNT1H und TCNT1L einzeln.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Flag richtig gelöscht? ===&lt;br /&gt;
&lt;br /&gt;
Ein beliebter Fehler ist, dass man überliest, dass gesetzte Flags (z.B. die Interrupt-Flags) durch beschreiben mit einer &#039;1&#039; und nicht mit einer &#039;0&#039; gelöscht werden! &lt;br /&gt;
&lt;br /&gt;
Beispiel: &lt;br /&gt;
* das Flag ist zuerst &#039;0&#039;&lt;br /&gt;
* das Ereignis (z.B. Zählerüberlauf, also Bit TOV0 in TIFR) tritt auf und setzt das jeweilige Bit im Register auf &#039;1&#039;&lt;br /&gt;
* wir haben auf die &#039;1&#039; gewartet und wollen das Bit nun wieder löschen und müssen dafür eine &#039;1&#039; (eins!) in das Register schreiben, &#039;&#039;&#039;keine&#039;&#039;&#039; &#039;0&#039;. Trotzdem wird das Bit dadurch &#039;0&#039; z.B.:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
    TIFR = (1&amp;lt;&amp;lt;TOV0);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das ganze ist kein Fehler, sondern hat seine guten Gründe.&lt;br /&gt;
&lt;br /&gt;
Wenn Interrupts zugelassen sind (z.B. in TIMSK) und die Interruptroutine aufgerufen wird, werden diese Flags zumeist automatisch gelöscht.&lt;br /&gt;
&lt;br /&gt;
Der UART-Empfangs-Interrupt (RXC in UCSRA) jedoch nicht! Der wird gelöscht durch Auslesen des Empfangsregisters (UDR). Hier liegt wiederum ein beliebter Stolperstein: Man prüft oft zuerst in der Interruptroutine die Fehlerflags (z.B. Parity) und macht dann manchmal den Fehler das empfangene Zeichen im Fehlerfall nicht auszulesen. Das führt dann zum Absturz (der IRQ wird immer wieder aufgerufen) - man muss also immer das UDR lesen auch wenn etwas Fehlerhaftes drinsteht.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich ist zu beachten, dass in C die Interrupt-Flags &#039;&#039;&#039;nicht&#039;&#039;&#039; mit einer Veroderung des Registers (z.B. TIFR |= (1 &amp;lt;&amp;lt; TOV0)) gelöscht werden sollten, da bei dieser Operation alle anderen evtl. gesetzten Flags im betreffenden Register ebenfalls gelöscht werden. Es ist die Schreibweise von oben zu benutzen (also TIFR = (1 &amp;lt;&amp;lt; TOV0))!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Alle Interrupt Variablen als volatile bezeichnet? ===&lt;br /&gt;
&lt;br /&gt;
Das Schlüsselwort volatile kann als Attribut an Variablen gehängt werden. Der Ausdruck „volatile int i“ versieht die Integervariable i mit dem Attribut volatile. Das Attribut weißt den Compiler an, diese Variable nicht zu optimieren, sondern im Speicher abzulegen und zu beachten, dass diese Variable von anderen Prozessen geändert werden kann. Normale Variablen können durch den Compiler auf Register reduziert werden, oder die Daten werden einmalig aus dem Speicher geladen und erst am Ende des Programmes wieder zurückgeschrieben. Das kann Probleme bereiten, wenn beispielsweise in einer Interruptroutine die Variable verändert wird. Darum müssen alle globalen Variablen, die in einer Interruptroutine geändert werden, mit diesem Schlüsselwort versehen werden.&lt;br /&gt;
&lt;br /&gt;
== Serielle Verbindungen ==&lt;br /&gt;
&lt;br /&gt;
=== [[I²C]]/[[TWI]] ===&lt;br /&gt;
&lt;br /&gt;
Sind die Leitungen SCL und SDA mit einem Pullup-Widerstand ausgestattet? Die I²C-Bus-Leitungen SCL und SDA müssen über einen Pullup-Widerstand mit einem Wert von 4,7 kOhm bis 10 kOhm mit der Versorgungsspannung (+5 V) verbunden sein.&lt;br /&gt;
&lt;br /&gt;
=== UART/USART ===&lt;br /&gt;
&lt;br /&gt;
==== Übertragungsprobleme durch falschen oder ungenauen Takt ====&lt;br /&gt;
&lt;br /&gt;
* Der interne [[Oszillator]] ist recht ungenau und nicht temperaturstabil. Daher kann die Umgebungstemperatur auch den [[UART | USART]]-Takt verändern. Für serielle, asynchrone Kommunikation per UART sollte man deshalb immer einen Quarz(oszillator) verwenden, egal bei welcher Baudrate (3% sind immer 3%, egal ob bei 1200 oder 9600 [[Baud]]). Falls doch der interne Oszillator verwendet wird, wurde er für die richtige Frequenz und Betriebsspannung kalibriert?&lt;br /&gt;
&lt;br /&gt;
* Nicht mit allen Quarzen kann man alle Baudraten genau genug erzeugen; deswegen gibt es [[Baudratenquarz]]e wie z.B. 3,6864 MHz. Näheres steht im Datenblatt.&lt;br /&gt;
&lt;br /&gt;
* Geschieht die Konfiguration des U(S)ART automatisch durch die Programmiersprache (z.B. in [[Bascom AVR | BASCOM]], [[C]]), dann muss dort der Takt &#039;&#039;&#039;genau&#039;&#039;&#039; angegeben werden. Setzt man z.B. einen 3,6864 MHz-Quarz ein, darf man dort nicht einfach &amp;quot;4 MHz&amp;quot; angeben, weil dann die Abweichung mit ca. 8% viel zu hoch wäre. Damit funktioniert die Übertragung nicht mehr.&lt;br /&gt;
&lt;br /&gt;
* Wenn ein externer Oszillator oder Quarz angeschlossen ist: Sind die [[AVR Fuses | Fuses]] des Controllers so gesetzt, dass er auch verwendet wird?&lt;br /&gt;
&lt;br /&gt;
* Ist die Fuse CLKDIV &#039;&#039;&#039;nicht&#039;&#039;&#039; programmiert?&lt;br /&gt;
&lt;br /&gt;
* Um zu prüfen ob der externe Quarz auch wirklich verwendet wird, kann man mittels _delay_ms() einfach mal eine LED im Sekundentakt blinken lassen. Den Unterschied zwischen Quarz und internem RC-Oszillator kann man bei grösseren Frequenzunterschieden leicht sehen. Ebenso sieht man, ob versehentlich die CLKDIV Fuse gesetzt ist, die Blinkfreqeunz ist dann achtmal langsamer. Allerdings muss man auch hier aufpassen. Siehe [[AVR-GCC-Tutorial#Warteschleifen_.28delay.h.29 |AVR-Tutorial]].&lt;br /&gt;
&lt;br /&gt;
* Erscheinen im Terminalprogramm kryptische Zeichen anstatt ordentlichen Buchstaben (z.B. ü statt A), liegt das zu 99,9% an einer falsch eingestellten/erzeugten Baudrate im Mikrocontroller.&lt;br /&gt;
&lt;br /&gt;
* In den Tutorials für [[AVR-Tutorial: UART |Assembler]] und [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Der_UART GCC] wird die Nutzung recht gut erklärt und mit Beispielen hinterlegt.&lt;br /&gt;
&lt;br /&gt;
==== Sonstige Fehlerquellen bei UART/USART ====&lt;br /&gt;
&lt;br /&gt;
* Funktioniert die Datenübertragung zum PC nur solange der Programmieradapter eingesteckt ist, deutet dies auf ein Problem mit der Masse hin (z.B. GND-Anschluss am RS232-Stecker nicht belegt oder dergleichen).&lt;br /&gt;
&lt;br /&gt;
* Der Pegelwandler/Inverter (z.B. MAX232) muss mit Kondensatoren für die internen Ladungspumpen beschaltet werden. Beim MAX232 sind dies mindestens vier Kondensatoren &amp;gt;= 1 µF (Polung beachten!), beim MAX202, MAX232&amp;lt;u&amp;gt;&#039;&#039;&#039;A&#039;&#039;&#039;&amp;lt;/u&amp;gt; und MAX3232 vier Kondensatoren &amp;gt;= 100 nF. Hinzu kommt der obligatorische Abblockkondensator (100 nF keramisch) zwischen VCC und GND des ICs. Das jeweilige Datenblatt gibt Auskunft über die Beschaltung bei &amp;quot;typischer Anwendung&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
* TX/RX vertauscht? Modem- oder Nullmodemkabel?&lt;br /&gt;
&lt;br /&gt;
* Bei Kommunikation mit PC: ist die serielle Schnittstelle richtig konfiguriert? Nicht nur Baudrate, Stopp- und Parity-Bits, sondern auch Handshakeverhalten (kein Hardwarehandshake bei ausschließlicher Verwendung der Pins RX/TX!).&lt;br /&gt;
&lt;br /&gt;
* Die Hardware und Verkabelung kann man schnell prüfen, indem man das Pin R1OUT bzw. R2OUT mit T1IN bzw. T2IN verbindet (je nachdem welches verwendet wird). Dann sollte man auf dem PC ein Terminalprogramm starten (z.B. Hyperterminal) und Zeichen eigeben können und sofort angezeigt bekommen, egal mit welcher Baudrate. Lediglich die Flusssteuerung muss auf &amp;quot;Kein&amp;quot; eingestellt werden. Man muss aber beachten, dass T1IN bzw. T2IN für diesen Test &#039;&#039;&#039;nicht&#039;&#039;&#039; mit dem Mikrocontroller verbunden sein darf, weil sonst zwei Ausgänge miteinander verbunden sind, was nicht wirklich gut ist (siehe [[Ausgangsstufen Logik-ICs]]). Wenn der uC gesockelt ist kann man ihn dafür einfach aus dem Sockel nehmen und die RX/TX Pins mit einem Stück Draht verbinden.&lt;br /&gt;
&lt;br /&gt;
=== SPI (Hardware) ===&lt;br /&gt;
* Master Mode: SS Pin als Ausgang oder auf High gelegt? (siehe hier: [http://www.holger-klabunde.de/avr/avrhelp.htm] )&lt;br /&gt;
* SPI zu schnell&lt;br /&gt;
* andere SPI Devices am Bus hängen, die undefiniertes CS haben?&lt;br /&gt;
* DDR Register der SPI Ports richtig gesetzt?&lt;br /&gt;
&lt;br /&gt;
== Analog-Digital-Wandler ==&lt;br /&gt;
&lt;br /&gt;
* Sind die Pullup-Widerstände deaktiviert?&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc2521.pdf Application Note AVR042: AVR Hardware Design Considerations]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc1619.pdf Application Note AVR040: EMC Design Considerations]&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_Checkliste&amp;diff=28884</id>
		<title>AVR Checkliste</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_Checkliste&amp;diff=28884"/>
		<updated>2008-07-02T23:25:24Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: /* Serielle Verbindungen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:AVR]]&lt;br /&gt;
Diese Seite soll als erste Anlaufstelle dienen, wenn der [[AVR]]-Mikrocontroller mal wieder nicht so will wie er soll. Es wird versucht, die Standardfehler und Probleme aufzulisten und zu erklären, was man dagegen tun kann.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
=== Anderen Controller benutzt als den im Schaltplan: Pinkompatibilität sichergestellt? ===&lt;br /&gt;
&lt;br /&gt;
Nur wenige AVR-Controller sind pinkompatibel und damit untereinander austauschbar. Manchmal liegen gar die am dringensten benötigten Funktionen (ISP-Programmierung) bei anderen Controllern auf anderen Pins. Unbedingt vorher die Belegungen anhand der Datenblätter vergleichen!&lt;br /&gt;
&lt;br /&gt;
=== Fuses richtig gesetzt? ===&lt;br /&gt;
&lt;br /&gt;
Die AVR-Controller haben &#039;Fuses&#039; (deutsch: &#039;Sicherungen&#039;), die das Verhalten des Prozessors auf grundlegender Ebene bestimmen. Ein häufiger Fehler ist beispielsweise, dass die falsche Taktquelle gewählt wurde (Fuse &amp;quot;CKSEL&amp;quot; etc.): einige AVRs können mit dem internen Oszillator (&amp;lt;i&amp;gt;internal R/C&amp;lt;/i&amp;gt;), mit einem externen Oszillator (&amp;lt;i&amp;gt;external clock&amp;lt;/i&amp;gt;), mit einem Quarz (&amp;lt;i&amp;gt;external crystal&amp;lt;/i&amp;gt;) oder mit einem Resonator (&amp;lt;i&amp;gt;external R/C&amp;lt;/i&amp;gt;) betrieben werden. Wenn die Einstellung über die Fusebits nicht dazu passt (z. B. &amp;lt;i&amp;gt;external clock&amp;lt;/i&amp;gt; statt &amp;lt;i&amp;gt;external crystal&amp;lt;/i&amp;gt;), fehlt dem Controller unter Umständen der Systemtakt und er läuft nicht an, oder man bekommt auf der seriellen Schnittstelle Nonsens, oder die Timer bzw. Zeitschleifen im Programm laufen zu langsam oder zu schnell.&lt;br /&gt;
&lt;br /&gt;
Eine andere Fuse (JTAGEN) schaltet auf einem Port (z.B. PORTC auf ATMega32) die JTAG-Unterstützung ein bzw. aus. Wenn sie eingeschaltet ist, funktionieren vier Bits dieses Ports nicht wie gewohnt, da sie für die JTAG-Schnittstelle reserviert werden.&lt;br /&gt;
&lt;br /&gt;
In dem zum STK500 gehörenden Entwicklungstool &#039;AVR Studio&#039; gibt es in der Programmer-Dialogbox einen Tab &#039;Fuses&#039;, der controllerabhängig den Status der Fusebits anzeigt und Änderungen ermöglicht.&lt;br /&gt;
Siehe auch: [[AVR Fuses]].&lt;br /&gt;
&lt;br /&gt;
=== ISP-Adapter ===&lt;br /&gt;
&lt;br /&gt;
Bei ISP-Programmieradaptern für den Parallelport kann es zu Inkompatibilitäten mit manchen Ports kommen. Tritt das Problem auch auf, wenn der ISP-Adapter an einem anderen Rechner angeschlossen ist? Funktioniert es vielleicht mit einer anderen Software? Siehe auch: [[AVR In System Programmer]]).&lt;br /&gt;
&lt;br /&gt;
Bei seriellem Programmer mit Controller (STK500, Atmel AVRISP etc.): Programmieren dauert sehr lange, es gibt Fehler. Abhilfe: ISP Taktrate richtig einstellen (&amp;lt;1/4 F_CPU).&lt;br /&gt;
&lt;br /&gt;
Beim Programmieren mit dem usbasp Programmieradapter muss die Geschwindigkeit richtig eingestellt werden. Bei einem AVR der auf den eingebauten 1 Mhz läuft muss mit langsamer Geschwindigkeit (Jumper zu) programmiert werden.&lt;br /&gt;
&lt;br /&gt;
=== Spannungsversorgung richtig angeschlossen? ===&lt;br /&gt;
&lt;br /&gt;
Der AVCC-Pin ist der Versorgungsanschluss für den AD-Wandler und den zugehörigen Port. Er ist nicht an allen AVRs vorhanden; wenn er aber vorhanden ist, so muss er auf jeden Fall angeschlossen sein, auch wenn der AD-Wandler nicht benutzt wird. Wird der AD-Wandler verwendet, sollte zur Verbesserung der Genauigkeit der AVCC-Pin über einen Lowpass-Filter angeschlossen werden (siehe Datenblatt).&lt;br /&gt;
Oft funktioniert die Programmierung des Controllers auch, wenn Vcc oder GND nicht richtig angeschlossen ist. Zur Sicherheit kann man mit einem Messgerät direkt an den Anschlüssen des AVRs kontrollieren (VCC-GND, AVCC-GND) prüfen, ob die Verbindungen korrekt sind. Es empfiehlt sich, vor dem Einsetzen bzw. Einlöten des Controllers die Versorgungsanschlüsse nochmals zu prüfen, um sicherzustellen, dass man den IC nicht durch eine zu hohe Spannung aufgrund eines Fehlers in der Versorgung zerstört.&lt;br /&gt;
&lt;br /&gt;
=== Reset-Pin korrekt beschaltet? ===&lt;br /&gt;
&lt;br /&gt;
Der Reset-Anschluss am AVR ist &#039;active-low&#039;, d. h. wenn man den Pin mit GND (Masse) verbindet, wird der Controller resettet. Zwar haben AVRs einen internen Pullup-Widerstand, der den Reset-Pin gegen VCC &amp;quot;zieht&amp;quot;, dieser ist jedoch relativ hochohmig (ca. 50 kOhm, vgl. Datenblatt) und reicht unter Umständen nicht aus, um den Reset-Pin sicher &amp;quot;hochzuhalten&amp;quot;. Als Mindestbeschaltung empfiehlt sich dringend, einen externen Pullup-Widerstand vorzusehen (typisch 10 kOhm), der den Reset-Pin mit VCC verbindet. Er sollte nicht kleiner als 4,7 kOhm sein, da der Programmieradapter sonst eventuell den Reset-Pin während des Programmiervorgangs nicht sicher auf &amp;quot;low&amp;quot; ziehen kann. Zusätzlich sollte man auch noch einen Kondensator 47 nF oder 100 nF zwischen Reset-Pin und GND anordnen. Dieses RC-Glied sorgt dafür, dass der Controller beim Einschalten der Versorgungsspannung für eine definierte Zeitspanne im Reset gehalten wird. Im laufenden Betrieb sorgt der Kondensator dafür, dass der Reseteingang unempfindlich gegenüber Spikes und Glitches wird. Er sollte deshalb unmittelbar in Pin-Nähe beim Prozessor untergebracht werden. Dieser Kondensator darf jedoch nicht verwendet werden, wenn [[debugWIRE]] möglich sein soll.&lt;br /&gt;
&lt;br /&gt;
Atmel empfiehlt zusätzlich noch zum Schutz vor Überspannungen eine externe Diode nach VCC (&amp;quot;Clamp-Diode&amp;quot;), da für den Reset-Pin keine interne vorhanden ist. Diese Diode bereitet jedoch bei manchen Programmieradaptern Schwierigkeiten.&lt;br /&gt;
&lt;br /&gt;
=== Abblockkondensator(en) ordnungsgemäß installiert? ===&lt;br /&gt;
&lt;br /&gt;
Abblockkondensatoren (&amp;quot;Bunker-Kondensatoren&amp;quot;) dienen dazu, sehr kurze Versorgungsspannungseinbrüche, die durch Schaltvorgänge verursacht werden können, zu kompensieren. Diesen Zweck erfüllen sie optimal, wenn folgende Regeln eingehalten werden: &lt;br /&gt;
&lt;br /&gt;
* Ein Abblockkondensator sollte möglichst dicht am IC sitzen.&lt;br /&gt;
&lt;br /&gt;
* Jedes IC in einer Schaltung sollte einen Abblockkondensator besitzen.&lt;br /&gt;
&lt;br /&gt;
* Bei ICs mit mehreren Anschlüssen für VCC und GND sollte jedes VCC-GND-Paar mit einem eigenen Abblockkondensator beschaltet werden (z. B. AVRs in SMD-Bauform wie dem ATmega16A also mit vier Kondensatoren).&lt;br /&gt;
&lt;br /&gt;
* Es sollten keramische Kondensatoren mit einer Kapazität von 100 nF verwendet werden. Größere Kondensatoren, etwa 10 µF-Elkos, sind für diese Aufgabe &#039;&#039;nicht&#039;&#039; geeignet, weil sie &amp;quot;zu langsam&amp;quot; sind!&lt;br /&gt;
&lt;br /&gt;
=== Quarz oder Quarzoszillator angeschlossen? ===&lt;br /&gt;
&lt;br /&gt;
Die neueren AVRs haben einen internen [[Oszillator]], der im Auslieferungszustand über die entsprechenden Fuses eingeschaltet ist. In diesem Fall muss kein externer [[Quarz]] mehr angeschlossen werden. Man kann in den [[AVR Fuses|Fuse-Bits]] aber einstellen, dass man einen externen Taktgenerator (&#039;&#039;external clock&#039;&#039;, z. B. Quarzoszillator) oder externen Quarz (&#039;&#039;external crystal&#039;&#039;) verwenden möchte.&lt;br /&gt;
&lt;br /&gt;
Dann, oder wenn der AVR keinen internen Takt hat, wird an die entsprechenden Pins des Controllers ein Quarz (&#039;&#039;external crystal&#039;&#039;, Bauelement mit zwei &amp;quot;Beinchen&amp;quot;) oder Quarzoszillator (&#039;&#039;external clock&#039;&#039;, Bauelement mit vier &amp;quot;Beinchen&amp;quot;) angeschlossen. Im Falle eines Quarzes werden die XTAL-Pins mit den beiden Anschlüssen des Quarzes und jeweils mit einem Kondensator (ca. 22 bis 27 pF) gegen Masse angeschlossen. Im Falle eines Quarzoszillators reicht es aus, den Taktausgang mit dem XTAL1-Pin zu verbinden, und den XTAL2-Pin unbeschaltet zu lassen. Die Fuses sind entsprechend einzustellen.&lt;br /&gt;
&lt;br /&gt;
=== Alle Ground-Anschlüsse beschaltet? ===&lt;br /&gt;
&lt;br /&gt;
Bei AVRs mit mehreren Ground-Anschlüssen müssen alle Anschlüsse beschaltet werden. Siehe http://www.mikrocontroller.net/forum/read-1-107259.html&lt;br /&gt;
&lt;br /&gt;
=== Alle Lötstellen in Ordnung? ===&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Kalte&amp;quot;, d.h. schlechte Lötstellen erkennt man an ihrer matten Oberfläche (bei bleihaltigem Lot). Bei beschädigten Lötstellen erkennt man oft einen Riss, der sich kreisförmig um die Mitte des Lötpunktes herum gebildet hat. Solche Stellen verursachen oft erst bei mechanischer Beanspruchung Probleme.&lt;br /&gt;
&lt;br /&gt;
Bei kleinen Abständen (SMD-Bauteile) müssen besonders Verbindungen zwischen benachbarten Lötungen kontrolliert werden.&lt;br /&gt;
&lt;br /&gt;
Bei Lochrasterplatinen kann man mit einem spitzen Messer (Bastelmesser) die Zwischenräume von möglichen leitenden Verbindungen befreien. &lt;br /&gt;
&lt;br /&gt;
=== Eingänge ===&lt;br /&gt;
&lt;br /&gt;
Taster müssen:&lt;br /&gt;
&lt;br /&gt;
* entprellt werden ([[Entprellung]])&lt;br /&gt;
&lt;br /&gt;
* einen [[AVR-GCC-Tutorial#Tasten_und_Schalter|Pullup-Widerstand]] besitzen, so sie &#039;&#039;active-low&#039;&#039; betrieben werden, d.h. wenn beim Tastendruck der Pin mit GND (Masse) verbunden wird (dies ist die übliche Anschaltung). Man kann einen externen Pull-Up Widerstand (typ. 10 kOhm) benutzen oder den internen aktivieren (DDR als Eingang also &amp;quot;0&amp;quot;, PORT auf &amp;quot;1&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Will man einen Taster &#039;&#039;active-high&#039;&#039; betreiben, soll also bei Tastendruck eine &amp;quot;1&amp;quot; in PIN gelesen werden, ist ein externer Pull-Down-Widerstand (typ. 10 kOhm) gegen GND anzuschließen, denn interne Pull-Downs sind nicht verfügbar.&lt;br /&gt;
&lt;br /&gt;
Symptome: Aufgrund des Prellens bekommt man bei einem Tastendruck statt eines Signals mehrere, und beim fehlenden Pullup fängt man sich Störungen (z.B. das 50 Hz-Netzbrummen) ein, da der Pin nicht auf einem &amp;quot;definierten Pegel&amp;quot; liegt, wenn der Taster nicht geschlossen ist. Soll z.B. bei einem Tastendruck eine LED angehen, dann leuchtet die LED durch das Netzbrummen plötzlich mit 50 Hz anstatt aus zu sein.&lt;br /&gt;
&lt;br /&gt;
* active low: ein Anschluss des Tasters an den Port-Pin, den anderen Taster-Anschluss an GND; internen Pull-Up-Widerstand aktivieren oder externen Widerstand zwischen Port-Pin und VCC.&lt;br /&gt;
&lt;br /&gt;
* active high: Taster zwischen Port-Pin und VCC; externen Widerstand zwischen Port-Pin und GND.&lt;br /&gt;
&lt;br /&gt;
=== Ausgänge ===&lt;br /&gt;
&lt;br /&gt;
Man sollte darauf achten, das &amp;quot;kritische&amp;quot; Ausgänge, d.h. Ausgänge, über die nicht &amp;quot;nur&amp;quot; eine LED geschaltet wird, einen definierten Zustand haben, wenn der Portpin auf &amp;quot;Eingang&amp;quot; und damit hochohmig geschaltet ist. Dadurch wird sichergestellt, dass beim Einschalten nicht kurz ein Verbraucher geschaltet wird (z.B. &amp;quot;Zucken&amp;quot; eines Motors). Dies kann man bewerkstelligen, indem man extern Widerstände (auch hier Pull-Up bzw. Pull-Down genannt, typ. 10 kOhm) an den Ausgangs-Pins vorsieht, die den Ausgang auf den gewünschten Zustand ziehen.&lt;br /&gt;
&lt;br /&gt;
=== Besonderheiten bei ATmega64 / ATmega128 ===&lt;br /&gt;
&lt;br /&gt;
Der ATmega64 und der ATmega128 haben zwei besondere Fallstricke, über die man bei nicht ausreichendem Datenblattstudium leicht stolpert. &lt;br /&gt;
&lt;br /&gt;
* Der erste betrifft den Anschluss der ISP-Signale (MISO, MOSI, SCK, RESET). Dieser erfolgt nicht wie bei den meisten anderen AVR-Controllern an den gleichnamigen Pins, sondern an PDI, PDO, SCK und RESET. Die Pinzuordnung ist:  MOSI-&amp;gt;PE0 (Pin 2), MISO-&amp;gt;PE1 (Pin 3), SCK-&amp;gt;PB1 (Pin 11) und RESET-&amp;gt;RESET (Pin 20). PEN (Pin 1) hat für normale ISP-Adapter keine Bedeutung und kann offen gelassen oder direkt mit Vcc verbunden werden. Die Benutzung der Pins PDI und PDO anstelle von MOSI und MISO gilt zusätzlich für einige ATMega128-Derivate im 64-Pin-TQFP-Gehäuse (darunter AT90CAN128, ATMega1281/2561)! Im Zweifelsfall im Datenblatt (Pin Configuration) nachsehen, ob PE0 und PE1 mit &amp;quot;PDI&amp;quot; bzw. &amp;quot;PDO&amp;quot; beschriftet sind.&lt;br /&gt;
&lt;br /&gt;
* Die zweite kleine &amp;quot;Gemeinheit&amp;quot; betrifft die &#039;&#039;&#039;M103C-Fuse&#039;&#039;&#039; (Atmega103 Compatibility Mode). Diese ist bei fabrikneuen Atmega64 und Atmega128 gesetzt und sorgt dafür, dass sich diese wie ein Atmega103 verhalten.&lt;br /&gt;
** Andererseits hat dies zur Folge, dass ein für den Atmega64 oder Atmega128 geschriebenes Programm beim ersten &amp;quot;ret&amp;quot; abstürzt, da der SRAM an einer anderen Stelle liegt als erwartet und somit der Prozessor keine gültige Rücksprungadresse vom Stack holen kann. &lt;br /&gt;
** Außerdem funktionieren einige IO-Pins an PORTC, PORTF und PORTG anders.&lt;br /&gt;
** Für weitere Infos bzgl. [[TWI]], [[UART]], [[Timer]], [[Bootloader]] und Kalibrierung des internen RC-Oszillators unbedingt das Datenblatt lesen.&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
&lt;br /&gt;
=== Alle Interruptvektoren definiert? ===&lt;br /&gt;
&lt;br /&gt;
Wenn man irgendwelche [[Interrupt]]vektoren verwendet, sollte man alle definieren, auch die nicht benutzten. Passiert es dann aufgrund eines Fehlers, dass ein Interrupt unbeabsichtigt ausgeführt wird, so führt der Controller dann eine definierte Aktion aus. Benutzt man eine Hochsprache wie C oder Basic, nimmt einem der Compiler diese Arbeit ab.&lt;br /&gt;
&lt;br /&gt;
Ausserdem sollte man immer im Datenblatt des Controllers nachsehen, wie die Interrupttabelle aufgebaut ist. Die kleinen AVRs verwenden ein &#039;&#039;&#039;RCALL&#039;&#039;&#039; zum Anspringen der Interrupts, welches 1 Wort lang ist. Die grossen AVRs mit mehr als 8 KiBi FLASH verwenden ein &#039;&#039;&#039;CALL&#039;&#039;&#039;, welches 2 Worte lang ist. Verwendet man nun  den falschen Befehl, verschieben sich die Einsprungadressen und das Chaos ist perfekt.&lt;br /&gt;
&lt;br /&gt;
In einem komplett interruptlosen Programm kann man auf die Interrupttabelle selbstverständlich verzichten (erkennbar daran, dass nirgendwo im Code Interrupts mittels Assembler-Befehl &#039;&#039;&#039;sei&#039;&#039;&#039; eingeschaltet werden).&lt;br /&gt;
&lt;br /&gt;
=== Alle Konfigurationsregister korrekt initialisiert? ===&lt;br /&gt;
&lt;br /&gt;
Alle benötigten Konfigurationsregister (auch &amp;quot;I/O-Register&amp;quot; genannt) eines Mikrocontrollers müssen korrekt initialisiert werden. Bei Fehlfunktionen sollten diese Konfigurationen noch einmal mit dem Datenblatt abgeglichen werden. &lt;br /&gt;
Manchmal ist es auch sinnvoll, bestimmte Funktionen explizit abzuwählen. Ein Beispiel hierfür ist der [[Analog-Komparator]] des AVR: Schaltet man diesen ab, wenn man ihn nicht benötigt, kann man dadurch ein wenig Strom sparen. &lt;br /&gt;
Wenn man besonders &amp;quot;sauber&amp;quot; programmieren möchte, initialisiert man Konfigurationsregister immer, d.h. auch wenn sie nicht im Programm verwendet werden. Dies verhindert mögliche zufällige Fehlkonfigurationen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Stackpointer initialisiert? (Nur in Assembler relevant) ===&lt;br /&gt;
&lt;br /&gt;
Fehlerbeschreibung: &#039;&#039;Das Programm lief, bis ein &amp;quot;rcall&amp;quot; oder ein Interrupt eingefügt wurde. Danach ging plötzlich gar nichts mehr.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wahrscheinliche Ursache: Der Stack ist ein spezieller Bereich im RAM, der von Sprungbefehlen und Interruptaufrufen dazu verwendet wird, die Rücksprungadresse ins Hauptprogramm zu speichern.  Da der Stack bei den AVRs nach &amp;quot;unten&amp;quot; wächst, d.h. in Richtung Anfang des RAMs, wird er üblicherweise ans Ende des RAMs gelegt. Der Stack muss vor der ersten Benutzung, am besten direkt am Anfang des Programms, initialisiert werden (sonst ist nach einem Sprung in ein Unterprogramm die Rücksprungadresse undefiniert und das Programm wird an einer unvorhersehbaren Stelle weiter ausgeführt, was in der Regel einen Absturz zur Folge hat). &amp;quot;Den Stack initialisieren&amp;quot; bedeutet, den Stackpointer auf den gewünschten &amp;quot;Startwert&amp;quot; zu setzen. Meistens wird dafür die letzte RAM-Adresse gewählt. &lt;br /&gt;
&lt;br /&gt;
Die Initialisierung unterscheidet sich geringfügig je nach verwendetem AVR. Bei den alten AT90xxxx und den ATtinys ist sie mit zwei Zeilen erledigt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
       ldi r16, RAMEND   ;Die Adresse der letzten Stelle im RAM in r16 laden&lt;br /&gt;
       out SPL, r16      ;Die Adresse in das Register SPL ausgeben&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Da die ATmegas mehr RAM haben, reicht das 8 bit-Register SPL nicht mehr, und es ist ein zweites (SPH) dazugekommen.  Die Initialisierung des Stacks erfordert hier vier Zeilen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
       ldi r16, LOW(RAMEND)    ;Untere 8 bit des 16 bit-Wertes RAMEND laden&lt;br /&gt;
       out SPL, r16&lt;br /&gt;
       ldi r16, HIGH(RAMEND)   ;Obere 8 bit laden&lt;br /&gt;
       out SPH, r16&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 16bit-Register in richtiger Reihenfolge geladen/gelesen? (Nur in Assembler relevant) ===&lt;br /&gt;
&lt;br /&gt;
Bei den 16-bit Registern (z.B. Timer1) genau die Hinweise im Kapitel &amp;quot;Accessing 16-bit Registers&amp;quot; beachten!&lt;br /&gt;
&lt;br /&gt;
So muss z.B. das High-Byte VOR dem Low-Byte geschrieben werden, weil mit dem Schreiben des Low Byte das gesamte Register &amp;quot;übernommen&amp;quot; wird.&lt;br /&gt;
Beim Lesen muss zuerst das Low-Byte gelesen werden, dann das High-Byte.&lt;br /&gt;
Es wird dadurch garantiert, dass sich zwischen den beiden einzelnen Befehlen nicht noch das Register weiter verändert, z.B. beim 16bit Counter.&lt;br /&gt;
Möglich wird das durch ein &amp;quot;temporary Register&amp;quot;, von dem es aber nur eines gibt - was beachtet werden muss, da zwischen diesen beiden einzelnen Lese-/Schreib-Befehlen kein Interrupt auftreten darf, der selber das temporary Rgegister benutzt.&lt;br /&gt;
&lt;br /&gt;
In C oder Basic kümmert sich der Compiler um das Problem - man liest oder beschreibt dann einfach z.B. TCNT1 anstatt TCNT1H und TCNT1L einzeln.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Flag richtig gelöscht? ===&lt;br /&gt;
&lt;br /&gt;
Ein beliebter Fehler ist, dass man überliest, dass gesetzte Flags (z.B. die Interrupt-Flags) durch beschreiben mit einer &#039;1&#039; und nicht mit einer &#039;0&#039; gelöscht werden! &lt;br /&gt;
&lt;br /&gt;
Beispiel: &lt;br /&gt;
* das Flag ist zuerst &#039;0&#039;&lt;br /&gt;
* das Ereignis (z.B. Zählerüberlauf, also Bit TOV0 in TIFR) tritt auf und setzt das jeweilige Bit im Register auf &#039;1&#039;&lt;br /&gt;
* wir haben auf die &#039;1&#039; gewartet und wollen das Bit nun wieder löschen und müssen dafür eine &#039;1&#039; (eins!) in das Register schreiben, &#039;&#039;&#039;keine&#039;&#039;&#039; &#039;0&#039;. Trotzdem wird das Bit dadurch &#039;0&#039; z.B.:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
    TIFR = (1&amp;lt;&amp;lt;TOV0);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das ganze ist kein Fehler, sondern hat seine guten Gründe.&lt;br /&gt;
&lt;br /&gt;
Wenn Interrupts zugelassen sind (z.B. in TIMSK) und die Interruptroutine aufgerufen wird, werden diese Flags zumeist automatisch gelöscht.&lt;br /&gt;
&lt;br /&gt;
Der UART-Empfangs-Interrupt (RXC in UCSRA) jedoch nicht! Der wird gelöscht durch Auslesen des Empfangsregisters (UDR). Hier liegt wiederum ein beliebter Stolperstein: Man prüft oft zuerst in der Interruptroutine die Fehlerflags (z.B. Parity) und macht dann manchmal den Fehler das empfangene Zeichen im Fehlerfall nicht auszulesen. Das führt dann zum Absturz (der IRQ wird immer wieder aufgerufen) - man muss also immer das UDR lesen auch wenn etwas Fehlerhaftes drinsteht.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich ist zu beachten, dass in C die Interrupt-Flags &#039;&#039;&#039;nicht&#039;&#039;&#039; mit einer Veroderung des Registers (z.B. TIFR |= (1 &amp;lt;&amp;lt; TOV0)) gelöscht werden sollten, da bei dieser Operation alle anderen evtl. gesetzten Flags im betreffenden Register ebenfalls gelöscht werden. Es ist die Schreibweise von oben zu benutzen (also TIFR = (1 &amp;lt;&amp;lt; TOV0))!&lt;br /&gt;
&lt;br /&gt;
== Serielle Verbindungen ==&lt;br /&gt;
&lt;br /&gt;
=== [[I²C]]/[[TWI]] ===&lt;br /&gt;
&lt;br /&gt;
Sind die Leitungen SCL und SDA mit einem Pullup-Widerstand ausgestattet? Die I²C-Bus-Leitungen SCL und SDA müssen über einen Pullup-Widerstand mit einem Wert von 4,7 kOhm bis 10 kOhm mit der Versorgungsspannung (+5 V) verbunden sein.&lt;br /&gt;
&lt;br /&gt;
=== UART/USART ===&lt;br /&gt;
&lt;br /&gt;
==== Übertragungsprobleme durch falschen oder ungenauen Takt ====&lt;br /&gt;
&lt;br /&gt;
* Der interne [[Oszillator]] ist recht ungenau und nicht temperaturstabil. Daher kann die Umgebungstemperatur auch den [[UART | USART]]-Takt verändern. Für serielle, asynchrone Kommunikation per UART sollte man deshalb immer einen Quarz(oszillator) verwenden, eagl bei welcher Baudrate (3% sind immer 3%, egal ob bei 1200 oder 9600 [[Baud]]). Falls doch der interne Oszillator verwendet wird, wurde er für die richtige Frequenz und Betriebsspannung kalibriert?&lt;br /&gt;
&lt;br /&gt;
* Nicht mit allen Quarzen kann man alle Baudraten genau genug erzeugen; deswegen gibt es [[Baudratenquarz]]e wie z.B. 3,6864 MHz. Näheres steht im Datenblatt.&lt;br /&gt;
&lt;br /&gt;
* Geschieht die Konfiguration des U(S)ART automatisch durch die Programmiersprache (z.B. in [[Bascom AVR | BASCOM]], [[C]]), dann muss dort der Takt &#039;&#039;&#039;genau&#039;&#039;&#039; angegeben werden. Setzt man z.B. einen 3,6864 MHz-Quarz ein, darf man dort nicht einfach &amp;quot;4 MHz&amp;quot; angeben, weil dann die Abweichung mit ca. 8% viel zu hoch wäre. Damit funktioniert die Übertragung nicht mehr.&lt;br /&gt;
&lt;br /&gt;
* Wenn ein externer Oszillator oder Quarz angeschlossen ist: Sind die [[AVR Fuses | Fuses]] des Controllers so gesetzt, dass er auch verwendet wird?&lt;br /&gt;
&lt;br /&gt;
* Ist die Fuse CLKDIV &#039;&#039;&#039;nicht&#039;&#039;&#039; programmiert?&lt;br /&gt;
&lt;br /&gt;
* Um zu prüfen ob der externe Quarz auch wirklich verwendet wird, kann man mittels _delay_ms() einfach mal eine LED im Sekundentakt blinken lassen. Den Unterschied zwischen Quarz und internem RC-Oszillator kann man bei grösseren Frequenzunterschieden leicht sehen. Ebenso sieht man, ob versehentlich die CLKDIV Fuse gesetzt ist, die Blinkfreqeunz ist dann achtmal langsamer. Allerdings muss man auch hier aufpassen. Siehe [[AVR-GCC-Tutorial#Warteschleifen_.28delay.h.29 |AVR-Tutorial]].&lt;br /&gt;
&lt;br /&gt;
* Erscheinen im Terminalprogramm kryptische Zeichen anstatt ordentlichen Buchstaben (z.B. ü statt A), liegt das zu 99,9% an einer falsch eingestellten/erzeugten Baudrate im Mikrocontroller.&lt;br /&gt;
&lt;br /&gt;
* In den Tutorials für [[AVR-Tutorial: UART |Assembler]] und [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Der_UART GCC] wird die Nutzung recht gut erklärt und mit Beispielen hinterlegt.&lt;br /&gt;
&lt;br /&gt;
==== Sonstige Fehlerquellen bei UART/USART ====&lt;br /&gt;
&lt;br /&gt;
* Funktioniert die Datenübertragung zum PC nur solange der Programmieradapter eingesteckt ist, deutet dies auf ein Problem mit der Masse hin (z.B. GND-Anschluss am RS232-Stecker nicht belegt oder dergleichen).&lt;br /&gt;
&lt;br /&gt;
* Der Pegelwandler/Inverter (z.B. MAX232) muss mit Kondensatoren für die internen Ladungspumpen beschaltet werden. Beim MAX232 sind dies mindestens vier Kondensatoren &amp;gt;= 1 µF (Polung beachten!), beim MAX202, MAX232&amp;lt;u&amp;gt;&#039;&#039;&#039;A&#039;&#039;&#039;&amp;lt;/u&amp;gt; und MAX3232 vier Kondensatoren &amp;gt;= 100 nF. Hinzu kommt der obligatorische Abblockkondensator (100 nF keramisch) zwischen VCC und GND des ICs. Das jeweilige Datenblatt gibt Auskunft über die Beschaltung bei &amp;quot;typischer Anwendung&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
* TX/RX vertauscht? Modem- oder Nullmodemkabel?&lt;br /&gt;
&lt;br /&gt;
* Die Hardware und Verkabelung kann man schnell prüfen, indem man das Pin R1OUT bzw. R2OUT mit T1IN bzw. T2IN verbindet (je nachdem welches verwendet wird). Dann sollte man auf dem PC ein Terminalprogramm starten (z.B. Hyperterminal) und Zeichen eigeben können und sofort angezeigt bekommen, egal mit welcher Baudrate. Lediglich die Flusssteuerung muss auf &amp;quot;Kein&amp;quot; eingestellt werden. Man muss aber beachten, dass T1IN bzw. T2IN für diesen Test &#039;&#039;&#039;nicht&#039;&#039;&#039; mit dem Mikrocontroller verbunden sein darf, weil sonst zwei Ausgänge miteinander verbunden sind, was nicht wirklich gut ist (siehe [[Ausgangsstufen Logik-ICs]]). Wenn der uC gesockelt ist kann man ihn dafür einfach aus dem Sockel nehmen und die RX/TX Pins mit einem Stück Draht verbinden.&lt;br /&gt;
&lt;br /&gt;
=== SPI (Hardware) ===&lt;br /&gt;
* Master Mode: SS Pin als Ausgang oder auf High gelegt?&lt;br /&gt;
* SPI zu schnell&lt;br /&gt;
* andere SPI Devices am Bus hängen, die undefiniertes CS haben?&lt;br /&gt;
* DDR Register der SPI Ports richtig gesetzt?&lt;br /&gt;
&lt;br /&gt;
== Analog-Digital-Wandler ==&lt;br /&gt;
&lt;br /&gt;
* Sind die Pullup-Widerstände deaktiviert?&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc2521.pdf Application Note AVR042: AVR Hardware Design Considerations]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc1619.pdf Application Note AVR040: EMC Design Considerations]&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=SMD_L%C3%B6ten&amp;diff=27539</id>
		<title>SMD Löten</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=SMD_L%C3%B6ten&amp;diff=27539"/>
		<updated>2008-04-18T16:29:17Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: /* Reflow-Techniken */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Löten]]&lt;br /&gt;
== Einlöten von SMD Bauteilen ==&lt;br /&gt;
&lt;br /&gt;
Irgendwann ist man an dem Punkt angelangt, an dem man ein Bauteil braucht, das bloß in [[SMD]] verfügbar ist. [[TI]] zum Beispiel bietet seine [[MSP430]]-[[Mikrocontroller]] ausschließlich in [[SMD]] an. Das ist dann der Zeitpunkt an dem man sich fragt: &amp;quot;Wie lötet man sowas?&amp;quot;. Nun, eigentlich ist es gar nicht so schwer, sobald man den richtigen Trick dabei mal raus hat. &lt;br /&gt;
&lt;br /&gt;
=== Handlöten ===&lt;br /&gt;
&lt;br /&gt;
==== Voraussetzungen ====&lt;br /&gt;
&lt;br /&gt;
* Grundvoraussetzung ist ein Lötkolben mit einer ausreichend dünnen Spitze. 0,8 mm sollten reichen.&lt;br /&gt;
* Außerdem braucht man noch Entlötlitze. Hier sollte man die dünnste, die man bekommen kann, nehmen.&lt;br /&gt;
* Natürlich braucht man auch noch das Lötzinn, bestenfalls mit Flussmittel im Kern. 0,5 mm ist praktikabel, 0,23 mm ist bei kleinerem Pitch sehr zu empfehlen.&lt;br /&gt;
* Flüssiges Flussmittel in Stiftform mit eingebautem Pinsel&lt;br /&gt;
* Schließlich ist auch noch eine Leiterplatte (PCB) von Nöten. Hier hat man entweder die Möglichkeit, sich eine bei den verschiedenen PCB-Herstellern fertigen zu lassen, oder sie selber zu belichten und zu ätzen.  Besonders bei Chips mit kleinem Pin-Abstand hilft eine Lötstoppmaske und die Vorverzinnung der Pads; die kleine Menge Zinn, die bei industriell gefertigten Platinen auf den Pads ist, reicht völlig aus, man braucht dann kein oder nicht viel extra Lötzinn.&lt;br /&gt;
&lt;br /&gt;
==== Löten von Widerständen, Kondensatoren und anderen 2-Pinnern ====&lt;br /&gt;
&lt;br /&gt;
Es gibt diese Bauteile hauptsächlich in diesen Bauformen:&lt;br /&gt;
* 1206:  Länge: 3,20 mm  Breite: 1,60 mm (laufen langsam aus)&lt;br /&gt;
* 0805:  Länge: 2,00 mm  Breite: 1,25 mm&lt;br /&gt;
* 0603:  Länge: 1,60 mm  Breite: 0,80 mm (derzeit in der Industrie aktuell)&lt;br /&gt;
* 0402:  Länge: 1,00 mm  Breite: 0,50 mm (wird derzeit Standard in der Industrie)&lt;br /&gt;
* 0201:  Länge: 0,50 mm  Breite: 0,25 mm (Handy)&lt;br /&gt;
* 01005: Länge: 0,25 mm  Breite: 0,13 mm (Handy)&lt;br /&gt;
&lt;br /&gt;
Das Einlöten von 2-Pinnern ist sehr einfach. Es gibt eigentlich bloß einen kleinen Trick:&lt;br /&gt;
&lt;br /&gt;
# Ein Pad auf der Leiterplatte verzinnen.&lt;br /&gt;
# Das Bauteil mit einer Pinzette in Endposition halten und leicht an beide Pads andrücken.&lt;br /&gt;
# Dabei das verzinnte Pad mit dem Lötkolben erwärmen. Das Bauteil ist nun einseitig eingelötet.&lt;br /&gt;
# Das zweite Pad normal löten.&lt;br /&gt;
# Anschließend evtl. das erste Pad nochmal kurz erhitzen.&lt;br /&gt;
&lt;br /&gt;
Und schon hat man das Bauteil eingelötet.&lt;br /&gt;
&lt;br /&gt;
Als Pinzette empfiehlet sich eine mit ca. 1 mm breiter Spitze, die als SMD-Pinzette (meist schwarz brüniert) ab ca. 10.- angeboten werden. Hier zu sparen lohnt nicht.&lt;br /&gt;
&lt;br /&gt;
==== Lötpaste ====&lt;br /&gt;
ist eine Mischung aus Mg(OH)2 und Al2(Cl)3.&lt;br /&gt;
&lt;br /&gt;
==== Löten von Bauteilen im SO-Package ====&lt;br /&gt;
&lt;br /&gt;
Das Löten von Bauteilen im SO Package gestaltet sich fast genauso einfach wie das Löten von Widerständen:&lt;br /&gt;
&lt;br /&gt;
# Ein Pad, das an einer Ecke des ICs liegt, verzinnen.&lt;br /&gt;
# Den IC platzieren.&lt;br /&gt;
# Den IC nach unten drücken.&lt;br /&gt;
# Das Pad erwärmen. Es ist möglich, dass der IC jetzt nicht richtig sitzt. Wenn das passiert ist, einfach nochmal das Zinn erwärmen und den IC verschieben bis er sitzt. Allerdings muss man dabei aufpassen, den IC nicht zu stark zu erwärmen.&lt;br /&gt;
# Das dem ersten gelöteten Pad diagonal gegenüberliegende Pad löten.&lt;br /&gt;
# Alle anderen Pads verlöten. Es ist nicht schlimm, wenn Zinnbrücken entstehen.&lt;br /&gt;
# Die Zinnbrücken mit Hilfe von Entlötlitze entfernen. Dazu hält man die Entlötlitze an die betroffenen Pads und erwärmt sie. Das Zinn geht dann automatisch auf die Entlötlitze und es gibt keine Brücken mehr.&lt;br /&gt;
&lt;br /&gt;
==== Löten von (T)SSOPs und QFPs ====&lt;br /&gt;
&lt;br /&gt;
War es bei Bauteilen im SO-Package mit einer ruhigen Hand noch möglich die Pins ohne Zinnbrücken zu verlöten, ist das bei TSSOPs nun praktisch nicht mehr möglich, da der Abstand der Pins einfach zu klein ist.&lt;br /&gt;
&lt;br /&gt;
# Platzieren des Bauteils.&lt;br /&gt;
# Das Bauteil irgendwie fixieren (Pinzette oder vorsichtig mit dem Zeigefinger etc.) Tesafilm ist recht praktisch und lässt sich leicht wieder entfernen.&lt;br /&gt;
# Mit dem Lötkolben einen Tropfen Zinn aufnehmen (entfällt bei verzinnten Pads).&lt;br /&gt;
# Das Bauteil an zwei diagonal gegenüberliegenden Pins festlöten.&lt;br /&gt;
# Überprüfen, ob der Chip wirklich richtig auf der Platine liegt, jetzt sind Korrekturen noch möglich.&lt;br /&gt;
# Wenn man einen Stift mit flüssigem Flussmittel hat, auf der zu lötenden Seite damit einfach über alle Pins pinseln.&lt;br /&gt;
# Mit dem Lötkolben über die erste Seite des TSSOP fahren. Dabei spielt es keine Rolle, ob Brücken entstehen. Wenn man vorverzinnte Pads und Lötstopplack hat, entstehen normalerweise keine Brücken, da die Oberflächenspannung die geringe Menge Zinn an Pad und Pin sammelt, so dass es zu wenig Zinn für eine Brücke ist.  Den Lötkolben mit einer Geschwindigkeit von ca. 1 - 2 Pins pro Sekunde vorwärts bewegen.&lt;br /&gt;
# Jetzt kann man das Bauteil loslassen, da es genügend fixiert ist.&lt;br /&gt;
# Mit dem Lötkolben über die andere(n) Seite(n) fahren.&lt;br /&gt;
# Mit Entlötlitze überflüssiges Zinn entfernen.&lt;br /&gt;
# Zum Abschluss kann man mit einer Lupe die Lötstellen überprüfen.&lt;br /&gt;
&lt;br /&gt;
Bei QFPs ist das Verfahren gleich, außer dass man 4 Seiten bearbeiten muss.&lt;br /&gt;
&lt;br /&gt;
Alternativ zur Entlötlitzentechnik gibt es auch Lötspitzen mit Hohlkehle.&lt;br /&gt;
&lt;br /&gt;
# Zuerst das Bauteil an zwei diagonalen Pins mit Lötzinn fixieren und die Ausrichtung prüfen. Ob Lötbrücken entstehen, ist zu diesem Zeitpunkt nicht wichtig.&lt;br /&gt;
# Dann genügend Flussmittel über die zu lötenden Pins streichen.&lt;br /&gt;
# Die Hohlkehle mit wenig Lötzinn füllen und über eine Seite des ICs führen.&lt;br /&gt;
# Jetzt hat man an einigen Stellen (meist am Ende der Seite, die man gelötet hat) einige Lötbrücken.&lt;br /&gt;
# Die Hohlkehle von Lötzinn reinigen und mit leerer Hohlkehle über die Lötbrücken fahren. Vorher nochmal genug Flussmittel draufgeben.&lt;br /&gt;
# Meist sind schon nach dem ersten mal keine Brücken mehr vorhanden. Falls doch, nochmals mit Flussmittel benetzen und an den entsprechenden Stellen mit der Hohlkehlspitze Lötzinn entfernen.&lt;br /&gt;
&lt;br /&gt;
Vorsicht! Flussmittel sind ätzend. Also nur bei eingeschalteter Lötdampfabsaugung arbeiten!&lt;br /&gt;
&lt;br /&gt;
==== Der Trick mit der Entlötlitze ====&lt;br /&gt;
&lt;br /&gt;
Bei kleinen SMD-Bauteilen kann es passieren, dass man beim Löten Zinnbrücken verursacht. Diese lassen sich recht einfach mittels Entlötlitze entfernen. Dabei sollte man direkt mit dem Ende der Litze entlöten und nicht der Mitte. Hilfreich kann bei wenig Platz auch ein schräges Anschneiden der Litze sein. Scharfe Schneidwerkzeuge, die ein Ausfransen der Litze verhindern, sind unverzichtbar (Tipp: SMD-Werkzeuge markieren, damit sie nicht versehentlich für grobe Arbeiten verwendet werden).&lt;br /&gt;
&lt;br /&gt;
Es empfiehlt sich die Entlötlitze vorher leicht mit Flussmittel zu tränken, damit das Zinn besser aufgenommen werden kann.&lt;br /&gt;
&lt;br /&gt;
Grundsätzlich sollte man beim Arbeiten mit Entlötlitze, ob an SMD- oder anderen Bauteilen, etwas Vorsicht walten lassen. Entlötlitze ist ein sehr guter Wärmeleiter. Daher kann man sich beim Entlöten, wenn man die Litze direkt mit den Fingern hält, böse verbrennen. Über 300° vom Lötkolben über die Litze zu den Fingern übertragen sind kein Pappenstiel. Leider kann das Führen der Litze mit einer Pinzette oder kleinen Flachzange gerade bei SMD-Bauteilen zu ungenau sein, so dass man verleitet wird die Finger zu nehmen.&lt;br /&gt;
&lt;br /&gt;
==== Trick 17 mit der Entlötlitze ====&lt;br /&gt;
&lt;br /&gt;
Mit der &amp;quot;Invertierte Entlötlitzen Methode&amp;quot; kann man auch mechanisch empfindliche Pins auf sehr kleinem Raster &#039;&#039;&#039;verlöten&#039;&#039;&#039;, indem man mit der Entlötlitze Lötzinn an das Pin/Pad-Paar zuführt. ([http://www.mikrocontroller.net/topic/94451#833286 Forumsbeitrag von Ulrich]).&lt;br /&gt;
&lt;br /&gt;
=== Reflow-Techniken ===&lt;br /&gt;
&lt;br /&gt;
Bei Reflow-Lötverfahren wird vor der Bestückung auf die Lötpunkte der Platine eine Lötpaste aufgetragen. Die Anschlüsse der zu lötenden Bauteile werden dann in diese Paste positioniert. Nach dieser Bestückung wird die Platine mit den Bauteilen erhitzt. Die Lötpaste schmilzt auf. Sind alle Lötpunkte aufgeschmolzen wird die Platine abgekühlt, das Lot härtet aus und die Bauteile sind verlötet.&lt;br /&gt;
&lt;br /&gt;
Reflow-Techniken galten lange Zeit als zu aufwendig für Amateure. Dies änderte sich, nachdem sich gezeigt hat, dass auch etwas hemdsärmelige Methoden zum Ziel führen. Auch diese setzen etwas Aufwand voraus, daher sind sie im folgenden nur kurz beschrieben.&lt;br /&gt;
&lt;br /&gt;
==== Lötpaste auftragen ====&lt;br /&gt;
&lt;br /&gt;
In der industriellen Fertigung wird die Lötpaste zum Beispiel mittels einer Schablone aufgetragen. Eine Schablonenfertigung (Laser) ist für Einzelstücke zu Aufwendig und zu teuer, daher bleibt die Lötpaste von Hand aufzutragen. Für diese Zwecke ist Lötpaste in Spritzen erhältlich. Die Preise für Lötpaste sind horrend. Mit ein bis zwei Euro pro Gramm(!) muss man rechnen. Allerdings benötigt man nur sehr geringe Mengen pro Platine und Lötpaste ist nicht unbegrenzt lagerbar. Es sollte eine &amp;quot;no clean&amp;quot; Paste verwendet werden. &amp;quot;No clean&amp;quot; bedeutet, dass die Platine nicht von Flussmittelresten gereinigt werden muss.&lt;br /&gt;
&lt;br /&gt;
Vor dem Auftragen der Paste ist die Platine zu säubern, und nochmal zu säubern, und nochmal ... Dann wird eine sehr kleine Menge der Paste auf jeden Lötpunkt aufgetragen.&lt;br /&gt;
&lt;br /&gt;
==== Bauteile bestücken ====&lt;br /&gt;
&lt;br /&gt;
Die Anschlüsse der Bauteile werden in die Lötpaste gesetzt. Bei bleihaltiger Lötpaste muss die Ausrichtung nicht 100% genau sein, da die Bauteile beim Schmelzen der Paste durch den Kapillareffekt in Position gezogen werden. Bei bleifreier Lötpaste ist dieser Effekt kaum vorhanden. Daher müssen die Bauteile in diesem Fall genau ausgerichtet sein.&lt;br /&gt;
&lt;br /&gt;
==== Umgebauter Pizzaofen ====&lt;br /&gt;
&lt;br /&gt;
Als Standardmethode für Amateure scheint sich die Verwendung eines umgebauten Pizzaofen durchzusetzen. Ein Elektro-Pizzaofen/Miniofen für den Hausgebrauch für vielleicht 20€ bis 50€ wird mit einer Mikrocontroller-Temperatursteuerung versehen. Mit dieser Steuerung werden die gewünschten Heiz- und Abkühl-Temperaturkurven gesteuert. Beim Umbau ist Vorsicht zu walten lassen, da die Heizung und Temperaturregelung solcher Öfen mit Netzspannung erfolgt.&lt;br /&gt;
&lt;br /&gt;
Aus Gesundheitsgründen sollte ein zum Reflow-Löten verwendeter Ofen nicht mehr für Nahrungsmittel verwendet werden.&lt;br /&gt;
&lt;br /&gt;
==== Elektro-Pfanne ====&lt;br /&gt;
&lt;br /&gt;
Statt eines mit einer Temperatursteuerung nachgerüsteten Pizzaofens wird gelegentlich einfach eine teflonbeschichtete Elektro-Pfanne verwendete. Elektro-Pfannen, manchmal auch Party-Pfannen genannt, sind in Deutschland eher selten in Haushalten zu finden. Es handelt sich dabei im Prinzip um eine Elektro-Heizplatte, die jedoch nicht flach, sondern deren Oberseite als Pfanne ausgeformt ist.&lt;br /&gt;
&lt;br /&gt;
Zum Reflowlöten wird eine bestückte Platine in die kalte Pfanne gelegt, mit der Lötseite, also den Bauelementen nach oben. Die Pfanne wird aufgeheizt und dabei die Platine beobachtet, bis die Lötpaste an allen Lötpunkten aufgeschmolzen ist. Da eine Elektro-Pfanne nicht überall gleichmäßig heizt, wird gelegentlich vorsichtiges Schwenken der Platine in der Pfanne vorgeschlagen, um die Platine gleichmäßig zu erwärmen. Ist die Lötpaste überall aufgeschmolzen wird die Elektro-Pfanne abgestellt. Die Platine bleibt in der Pfanne und kühlt dort langsam mit der Pfanne aus.&lt;br /&gt;
&lt;br /&gt;
Bei dieser Methode hat man keine Kontrolle über die Temperaturkurve. Selbige hängt nicht nur von der Bauart der Pfanne, sondern auch von der Umgebungstemperatur und der eigenen Reaktionszeit ab.&lt;br /&gt;
&lt;br /&gt;
Aus Gesundheitsgründen sollte ein zum Reflow-Löten verwendete Elektro-Pfanne nicht mehr für Nahrungsmittel verwendet werden.&lt;br /&gt;
&lt;br /&gt;
==== Heißluft ====&lt;br /&gt;
&lt;br /&gt;
Mit Heißluft kann man Platinen bereichsweise löten. Entsprechende Stationen, häufig Rework-Stations genannt, sind relativ teuer. Mit Übung lässt sich auch eine einfache Heißluft-Pistole verwenden. Allerdings ermöglichen deren Düsen kein sonderlich genaues Arbeiten. Ebenso muss man aufpassen, dass man mit einer Heißluft-Pistole nicht einfach die in der Lötpaste sitzenden Bauteile verschiebt oder sogar von der Platine bläst. Da man sich mit Heißluft verbrennen kann ist etwas Vorsicht geboten.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Herdplatte ====&lt;br /&gt;
&lt;br /&gt;
Mit etwas Erfahrung kann man auch sehr gut auf der Herdplatte löten. Die Herdplatte wird dabei rund eine halbe Stunde vorgeheizt, damit die Temperatur einigermaßen konstant bliebt. Mit etwas Lötzinn kann getestet werden, ob die Löttemperatur erreicht wurde. Die Herdplatte sollte nicht zu heiß eingestellt werden, damit der Lötstopplack sowie das Epoxyd nicht verheizt wird. &lt;br /&gt;
Die bestückte Platine wird mit einer Pinzette auf die Herdplatte gelegt. Schon nach kurzer Zeit sollte das Lötzinn anfangen zu schmelzen. Wenn alle Lötstellen verlötet sind, kann die Platine wieder heruntergenommen werden und abkühlen.&lt;br /&gt;
&lt;br /&gt;
== Entlöten von SMD-Bauteilen ==&lt;br /&gt;
&lt;br /&gt;
Leider halten ICs etc. nicht ewig und irgendwann muss jeder einmal SMD Bauteile wieder auslöten. Das Entlöten gestaltet sich im Grunde genauso einfach wie das Einlöten.&lt;br /&gt;
&lt;br /&gt;
Es gibt zwei Fälle: Entweder soll der Chip überleben oder die Platine.&lt;br /&gt;
&lt;br /&gt;
=== Die einfachste Methode ===&lt;br /&gt;
&lt;br /&gt;
Die einfachste Methode ist ganz einfach den Lötkolben auf maximale Temperatur zu stellen und dann, mit etwas Lötzinn für besseren Wärmekontakt, auf die Mitte des auszulötenden ICs zu legen (mit der Spitze und dem Lötzinn darunter).&lt;br /&gt;
&lt;br /&gt;
Der IC stirbt dabei durch die rund 400 Grad des Lötkolbens sicherlich den Hitzetod, aber durch die Wärmeleitung schmilzt an den Beinchen des ICs das Lötzinn nach rund einer Minute und man kann den IC mit einer Pinzette dann abheben. Hierzu sollte man alle paar Sekunden testweise anheben und den Lötkolben nur leicht aufdrücken, um so ganz sicher alle anderen Bauteile heil zu lassen.&lt;br /&gt;
&lt;br /&gt;
Das auf der Platine verlaufene Lötzinn entfernt man, indem man mit der gereinigten Lötspitze (bei 200 Grad) über die nun geleerten Pads geht; Zubehör wie Entlötlitze ist überflüssig.&lt;br /&gt;
&lt;br /&gt;
So kann man beispielsweise einen USB-RS232-Adapter in einen USB-UART-Adapter umwandeln ;-)&lt;br /&gt;
&lt;br /&gt;
Getestet habe ich es bisher mit einem SD213 (28 Pins) und einem FT232 (32 Pins), aber etwas größere ICs, bis zum MSP430 mit 100 Pins, müssten auch möglich sein.&lt;br /&gt;
Durch Umdrehen der Platine sollten auch noch größere ICs so auslötbar sein (wobei man wegen der Schwerkraft dann die Pinzette einsparen kann), weil dann durch die Konvektion noch mehr Wärme übertragen wird.&lt;br /&gt;
&lt;br /&gt;
=== Chip Quick-Methode ===&lt;br /&gt;
[http://www.chipquik.com/ Chip Quick] bietet ein Set an mit dem sich SMT-Bauteile sehr einfach und zerstoerungsfrei entloeten lassen.&lt;br /&gt;
&lt;br /&gt;
Dabei wird auf die Beinchen reichlich Flussmittel aufgetragen. Dann eine grosse Menge speziellem Loetzinn aufgetragen das eine sehr geringen Schmelztemperatur hat. Das verbindet sich mit dem Loetzinn und bleibt lange fluessig. Die Temperatur ist so gering, dass das Bauteil ueberlebt.&lt;br /&gt;
Wenn alle Beinchen in dem Loetzinn-Blob stehen, faellt das Bauteil fast von alleine ab.&lt;br /&gt;
&lt;br /&gt;
Diese Methode wird in dem Make-Magazine Video gezeigt das unten verlinkt ist.&lt;br /&gt;
&lt;br /&gt;
=== Die Zahnarztmethode ===&lt;br /&gt;
&lt;br /&gt;
==== Benötigtes Werkzeug ====&lt;br /&gt;
&lt;br /&gt;
* Lötkolben&lt;br /&gt;
* Lötzinn &lt;br /&gt;
* Zahntechnischer Helfer&lt;br /&gt;
* Entlötlitze&lt;br /&gt;
&lt;br /&gt;
==== Der Zahntechnische Helfer ====&lt;br /&gt;
&lt;br /&gt;
Wohl das genialste Hilfsmittel, wenn man ein IC wieder auslöten muss. Dieses benutzt der Zahnarzt normalerweise zum Entfernen von Zahnstein. Der Zahntechnische Helfer ist sehr hilfreich beim Auslöten jeglicher SMD-Bauteile mit mehr als 4 Pins.&lt;br /&gt;
&lt;br /&gt;
==== Der Entlötvorgang ====&lt;br /&gt;
&lt;br /&gt;
Das Entlöten ist bei fast allen SMD-Bauteilen gleich, egal welcher Pinabstand und wie viele Pins. Hauptsache mehr als 8, denn davor macht es kaum Sinn diesen zusätzlichen Aufwand zu betreiben.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ACHTUNG: Der IC geht dabei kaputt!!&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
# Man bringt eine dicke Zinnwurst auf alle Pins auf.&lt;br /&gt;
# Erwärmen des Zinns mit dem Lötkolben.&lt;br /&gt;
# Ausheben der Pins mithilfe des zahntechnischen Helfers. Hier kann man bei den Bauteilen mit kleinem Pinabstand gleichzeitig mehrere hochheben.&lt;br /&gt;
# Solange wiederholen, bis alles raus ist.&lt;br /&gt;
# Entfernen der Zinnreste mit Entlötlitze.&lt;br /&gt;
&lt;br /&gt;
=== Die Cuttermethode ===&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit, ein SMD IC von einer Platine zu entfernen, ist es die Beinchen vor dem Entlöten zu durchtrennen. Dazu nimmt man ein Cuttermesser mit Abbrechklingen, setzt es so nah wie möglich am Gehäuse auf ein paar der IC-Beinchen auf und drückt gerade &#039;&#039;&#039;ohne Seitwärtsbewegung&#039;&#039;&#039; nach unten. Dies durchtrennt die Beine ohne darunterliegende Leiterbahnen zu verletzen. Ein wenig Gefühl ist dabei natürlich nötig, Üben auf einem alten PC Mainboard lohnt sich. Nachdem auf diese Weise alle Beine vom IC abgetrennt sind, kann man die auf der Platine verbliebenen Reste der Beinchen einfach mit dem Lötkolben &amp;quot;abwischen&amp;quot; und die Lötzinreste mit Entlötlitze entfernen. Die Wärmebelastung der Platine ist bei dieser Methode wesentlich geringer, allerdings besteht die latente Möglichkeit Leiterbahnen zu durchtrennen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Anmerkung:&#039;&#039;&#039; Es hat sich dabei bewährt, vorher alle Pins mit einer relativ dicken Schicht Lötzinn zu verbinden. So werden abgerissene Leiterbahnen durch versehentliche Seitwärtsbewegungen verhindert. Es muss allerdings darauf geachtet werden, dass das Lötzinn nicht ganz bis ans Gehäuse reicht, da sonst das Schneiden nahezu unmöglich ist.&lt;br /&gt;
&lt;br /&gt;
=== Die Mini-Trennscheiben-Methode ===&lt;br /&gt;
&lt;br /&gt;
Man nehme eine sehr schnelle, kleine Handbohrmaschine (Proxxon, Dremel oder dergleichen), setze eine kleine Trennscheibe auf und flexe unter der Lupenbrille vorsichtig die Beinchen nahe dem Gehäuse ab. Das Gehäuse fällt irgendwann ab, die Beinchen werden mit einem Lötkolben weggewischt.&lt;br /&gt;
&lt;br /&gt;
=== Die 2-Lötkolben-Methode ===&lt;br /&gt;
&lt;br /&gt;
Diese Methode eignet sich für alle SMD-Bauteile mit 2 gelöteten Seiten: Widerstände, Kondensatoren, kurze ICs (z.B. 2x8 Pins). Bei den Widerständen und Kondensatoren ist alles klar. Von jeder Seite einen Lötkolben anhalten, das Bauteil löst sich ab und bleibt meist an einem der Kolben kleben, wo man es abschütteln kann. Bei ICs verzinnt man zunächst beide Pin-Reihen ordentlich, danach versucht man mit den Kolben das Zinn auf beiden Reihen und der gesamten Länge flüssig zu bekommen, evtl. muss man die Lötkolben dabei etwas bewegen. Ist das Zinn komplett flüssig, kann man das IC beiseite schieben. Das geht besonders gut bei Platinen mit Lötstopplack. Bei dieser Methode kann man die Bauteile in der Regel anschließend weiter verwenden, überflüssiges Zinn an den Pins mit Lötsauglitze entfernen.&lt;br /&gt;
&lt;br /&gt;
=== Die Rohrstückmethode ===&lt;br /&gt;
&lt;br /&gt;
Diese Methode eignet sich für ICs mit Pins an zwei Seiten (SO-Gehäuse). Chip und Platine haben Chancen zu überleben.  Man nehme ein Stück Kupferrohr der passenden Länge und sägt es der Länge nach durch, so dass man zwei Halbschalen hat. Eine der Halbschalen befestigt man an einer alten Lötspitze, z.B. indem man ein Gewinde schneidet oder hartlötet.  Nun kann man alle Pins gleichzeitig erwärmen und das IC abnehmen.&lt;br /&gt;
&lt;br /&gt;
=== Die Kupferdraht-Haken-Methode ===&lt;br /&gt;
&lt;br /&gt;
Die Methode funktioniert ähnlich wie die zuvor beschriebenen &#039;&#039;Rohrstückmethode&#039;&#039;. Das Erstellen des Hilfsmittels ist wesentlich einfacher, allerdings ist es keine Dauerlösung. Die Methode eignet sich für kleine Bauteile (Widerstände, etc.) mit Pins an zwei Seiten.&lt;br /&gt;
&lt;br /&gt;
Das Ende eines langen Stück blanken Kupferdrahts wird mittels einer kleinen Flachzange zu einem U-förmigen Haken abgebogen. Dabei wählt man die Lichte Weite des Hakens so, dass man mit zwei Seiten des Hakens die Pins des zu entlötenden Bauteils gleichzeitig erreichen kann. Das andere Ende des Kupferdrahts wickelt man mehrfach um die Spitze eines kalten(!) Lötkolbens. Das Ende mit dem Hacken sollte dabei nicht mehr als vielleicht 2 cm über die Lötkolbenspitze hinausreichen und der Draht wird so gebogen (gekröpft), dass man den Lötkolben bequen führen kann um den Haken flach am Bauteil anzulegen. Um Missverständnisse zu vermeiden, der Haken soll am Bauteil angelegt und nicht etwa in irgendeienr Weise unter das Bauteil geschoben werden.&lt;br /&gt;
&lt;br /&gt;
Nun wird der Lötkolben und damit der Haken erhitzt. Ist die Hakenspitze heiß genug, legt man den Haken am Bauteil an. Sobald das Lötzinn an den Pins geschmolzen ist zieht man das Bauteil von den Pads. Bauteile haben dabei die Angewohnheit für immer auf dem Fußboden verloren zu gehen. Benötigt man das Teil noch, so sollte man etwas Vorsicht walten lassen.&lt;br /&gt;
&lt;br /&gt;
=== Die dicke Kupferdrahtmethode ===&lt;br /&gt;
&lt;br /&gt;
1,5 - 2,5 mm² Massivdraht so zurechtbiegen, dass er exakt und plan auf die Pins passt. Dann mit viel Zinn schnell verlöten. Das geht am besten mit zwei oder drei stärkeren Lötkolben und einer zweiten Person. Ich habe aber auch schon alleine mit 2 Kolben 160-Poler ausgelötet, ohne IC oder Platine zu beschädigen.&lt;br /&gt;
&lt;br /&gt;
IC am besten mit einer Pinzette oder einem Vakuumsauger (z.B. Kontaklinsensauger für harte KL aus Silikon) abheben und noch im heißen Zustand den dicken Draht samt Zinn abklopfen. Danach das IC möglichst schonend (gleichmäßig und schnell) abkühlen, evtl. schon vor dem Löten einen kleinen Kühlkörper auf das IC legen / kleben.&lt;br /&gt;
&lt;br /&gt;
Die Methode kombiniert sich gut mit der Bügeleisen- oder Ceranfeld-Vorwärm-Methode.&lt;br /&gt;
&lt;br /&gt;
=== Der Trick mit dem Platinensicherungshalter ===&lt;br /&gt;
&lt;br /&gt;
Speziell zum Auslöten von SO-ICs mit 2x4 Beinchen kann man den einzelnen Clip eines Platinensicherungshalters (Durchstecktechnik, für 5 x 20 mm Sicherungen) benutzen. Mit einer feinen Zange biegt man zunächst die sich nach außen öffnenden Enden des Clips etwas nach innen. Auf diese Weise entsteht eine Mini-Zange, die genauso breit ist wie die Beinreihe des IC und sich aufgrund ihrer Vorspannung am IC festhalten kann. Den modifizierten Clip klemmt man von oben über den IC und erhitzt seine Bodenplatte mit dem Lötkolben (16W). (Anstelle der oben beschrieben Zinn-Wurst-Methode bildet nun der Clip die Wärmebrücke, ähnlich der oben beschriebenen Rohrstückmethode) Der Clip wird mit einer Pinzette abgehoben und nimmt den IC mit.&lt;br /&gt;
&lt;br /&gt;
Die Platine und der IC bleiben ganz.&lt;br /&gt;
&lt;br /&gt;
=== Die Abschlagmethode ===&lt;br /&gt;
&lt;br /&gt;
Wenn man SMD ICs von einer Platine retten möchte, die Platine aber später in den Müll wandert, kann man das IC mit seinem Körper auch auf eine harte Kante legen (die Platine ist dabei mehr oder weniger senkrecht).  Dann ein beherzter Schlag mit dem Handballen auf die Platinenkante und der Chip wird von der Platine abgerissen.  Die Beinchen muss man nachher etwas richten, aber allermeistens funktioniert diese Methode sehr zuverlässig, besonders bei maschinell gelöteten Platinen.  Diese Methode funktioniert sowohl mit SO-Gehäusen als auch mit radiergummigroßen DC/DC Wandlern.&lt;br /&gt;
&lt;br /&gt;
=== Alternative: Die Stechbeitelmethode ===&lt;br /&gt;
&lt;br /&gt;
Hier gilt das gleiche Prinzip wie bei der Abschlagmethode: Zuerst knicken die Beinchen ein und reißen dann von den Leiterbahnen ab. Sie lassen sich aber leicht zurückbiegen und das IC wird garantiert nicht überhitzt. Der Beitel sollte ca. 8 - 15 mm breit sein, ein alter, angeschliffener Schraubendreher mit großem Griff tut&#039;s auch. Dann die Platine flach vor sich auf den Tisch legen, das IC liegt senkrecht zur Tischkante. Den Beitel senkrecht zur Platine mit der flachen Seite an das IC anlegen, die linke Ecke der Schneide liegt dabei auf der Stirnseite in Höhe der Mittellinie, die rechte Ecke der Schneide wird als Widerlager in die Platine gepresst. Den Beitel dafür etwas nach rechts kippen, mit Gewicht fest in die Platine drücken und mit Gefühl im Uhrzeigersinn drehen. So wird das IC in Längsrichtung und parallel zur Platine weggehebelt. Die benötigte Kraft kann man sehr gut dimensionieren. Wenn man das raus hat, braucht man ca. 1 - 2 Sekunden pro IC.&lt;br /&gt;
&lt;br /&gt;
=== Heißluftpistole ===&lt;br /&gt;
&lt;br /&gt;
Eine Heißluftpistole, wie man sie im Baumarkt zum Abbrennen alter Farbe u.ä. kaufen kann, kann gute Dienste beim SMD-Löten leisten. Empfehlenswert sind solche mit Temperaturregler, aber selbst die einfachsten Varianten (die in der Regel nur zwei Stufen haben, mit denen man sowohl die Gebläsegeschwindigkeit als auch die Heizleistung umschaltet) sind für viele Zwecke brauchbarer, als man auf den ersten Blick annehmen würde.&lt;br /&gt;
&lt;br /&gt;
Einfach Platine einspannen und mit der Heißluftpistole langsam und gleichmäßig erwärmen. Dabei nicht zu heiß arbeiten, etwas mehr Zeit für die Arbeit schadet Platine und Bauteilen weniger, als mit zu großer Temperatur alles zu verbrennen.  Wenn man vorsichtig arbeitet und den Punkt gut herausfindet, an dem sich das fragliche Bauteil ablösen lässt, taugt die Methode sogar für Reparaturlötungen, d.h. sowohl Platine als auch Bauteil bleiben dabei ganz.  Damit ist die Methode auch durchaus geeignet, alten Elektronikschrott zu recyclen, um auf diese Weise preiswert zu einem Grundstock an diversen SMD-&amp;quot;Hühnerfutter&amp;quot; (Widerstände, Kondensatoren, oft auch Tantal-Elkos) sowie teilweise auch Standard-ICs (74xxx, LM358 u.ä.) zu gelangen.&lt;br /&gt;
&lt;br /&gt;
Vermutlich lassen sich Pertinax-Platinen danach nicht mehr verwenden, aber diese haben bei den schmalen Leiterzugbreiten von SMD ohnehin kaum eine Überlebenschance.  Besser gleich trotz des höheren Preises alles auf Epoxyd anfertigen -- gerade bei den hobbytypischen Einzelstücken ist andernfalls die verschwendete Arbeitszeit sehr viel ärgerlicher als der höhere Preis der Epoxyd-Platine.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Tipp:&#039;&#039;&#039; Die Platine mit einem Stück Alufolie so abdecken, dass nur das auszulötende Bauteil im Luftstrom ist (an der Stelle ein Loch in die Folie machen).&lt;br /&gt;
&lt;br /&gt;
Falls das Überleben der Platine wirklich völlig egal ist, kann man auch die Rückseite der Platine mit der Heißluftpistole erhitzen, bis die Vorderseite so heiß ist, dass die SMD-Chips einfach abfallen. Zwei Vorteile ergeben sich aus diesem Verfahren für die Überlebenswahrscheinlichkeit der Bauteile:&lt;br /&gt;
&lt;br /&gt;
* Der Temperaturgradient ist so gerichtet, dass die Beine des Chips die höchste Temperatur haben und nicht der Chip selbst, wenn man von oben auf das Gehäuse bläst&lt;br /&gt;
* Die, wenn auch geringe, Wärmeleitung der Platine sorgt für eine gleichmäßigere Temperaturverteilung auf der Vorderseite.&lt;br /&gt;
&lt;br /&gt;
Von Nachteil allerdings ist, dass die Platine evtl. auf der Rückseite so heiß wird, dass sie anfängt, sich zu zersetzen. Das ist sicherlich nicht gesund und daher sollte man hier vorsichtig sein (langsam erhitzen, frische Luft).&lt;br /&gt;
&lt;br /&gt;
Alternativ geht es auch mit der Heißluftdüse eines Gaslötkolbens (z.B. von Ersa). Dabei geht man zügig mit dem heißen Luftstrom über die Pins des ICs und erwärmt sie, bis sich das IC gewaltfrei abheben lässt. Richtig gemacht überleben IC und Platine.&lt;br /&gt;
&lt;br /&gt;
=== Variante: Gasherdmethode ===&lt;br /&gt;
&lt;br /&gt;
Auf einer einseitig bestückten SMD-Platine kann man Bauteil und Platine auch zerstörungsfrei wie folgt trennen: Von der großen Gasflamme die Abdeckung herunternehmen, diese Abdeckung z.B. mit Hilfe des Halters für kleine Töpfe über die kleine Gasflamme legen (natürlich geht das auch mit einem anderem Stück Metall, Hauptsache gerade) und dann mit der kleinen Gasflamme die Metallplatte/Abdeckung darüber erwärmen. Mit einem Stück Lötzinn probieren, ob es schon heiß genug ist (Lötzinn muss schmelzen, perlen und abtropfen).&lt;br /&gt;
&lt;br /&gt;
Wenn ja: Flamme ausmachen, Platine mit der nicht bestückten Seite auf das heiße Metall drücken, ein paar Sekunden warten, bis die Wärme von unten durch die Platine gewandert ist, und das Bauteil mit einer Pinzette abnehmen. Getestet mit Epoxyd-Platine. Sie hat überlebt, nur etwas dunkel verfärbt. Es empfiehlt sich, mit einer unkritischen Platine etwas zu üben.&lt;br /&gt;
&lt;br /&gt;
=== Variante: Heissluft Guru Methode ===&lt;br /&gt;
High Tech Warmluft Methode mit Gaslötkolben. Man kaufe für ca €60 einen Gaslötkolben mit Heissluftdüse. Gaslötkolben mit Heissluftdüse auf volle Power, soll dann angeblich bis 600 Grad Warmluft abgeben. Damit SMD Bauteil durch kreisförmige Bewegung rundherum an den Pins mit 2 cm Abstand gezielt erhitzen. Das dauert ca. 2 Minuten. Das Bauteil lässt sich dann abnehmen, wegschieben oder abschlagen. Teilweise werden wenige eng am Bauteil bestückte Blockkondensatoren ebenfalls ausgelötet.&lt;br /&gt;
Es lassen sich SMD&#039;s jeder Grösse und Pinabstand ohne Beschädigung auslöten. Die ausgelöteten Bauteile lassen sich problemlos wieder verwenden. Die Platine mit Lötsauglitze und Aceton säubern und neues Bauteil drauf. Habe so während der Entwicklung FPGAS und Treiber IC&#039;s auf einer Platine schon bis zu fünf mal getauscht.&lt;br /&gt;
&lt;br /&gt;
=== Variante: Bügeleisenmethode ===&lt;br /&gt;
&lt;br /&gt;
Ein Bügeleisen umgekehrt in einen Schraubstock spannen, eventuell mit einem&lt;br /&gt;
Tuch am Griff vor Kratzern schützen und die Gleitfläche mit Alufolie abdecken - um Ärger mit der besseren Hälfte zu vermeiden ;-) Auf maximale Temperatur stellen (Leinen), Platine mit der nicht bestückten Seite auflegen und warten, bis das Lot flüssig wird. Bauteile mit einer Pinzette abheben. Platine nach und nach verschieben um alle Stellen zu erhitzen.&lt;br /&gt;
&lt;br /&gt;
=== Ceran-Herd ===&lt;br /&gt;
&lt;br /&gt;
Geht nur bei einseitig bestückten Platinen!&lt;br /&gt;
&lt;br /&gt;
Ähnelt der Bügeleisen-Methode, ist wegen der IR-Strahlung besser.&lt;br /&gt;
&lt;br /&gt;
Platine auf das Ceranfeld legen. Dann das Feld ca. alle 1 - 2 Sekunden ein- und ausschalten. Dabei das An-Intervall langsam erhöhen. Dies so lange durchführen, bis das Zinn geschmolzen ist. Nun die gewünschten Bauelemente verschieben oder abheben. Darauf achten, dass das Glas frei von Zinn und anderen Stoffen bleibt.&lt;br /&gt;
&lt;br /&gt;
Achtung: Das Glas wird ungleichmäßig heiß, da die Heizwendeln lokal angeordnet sind.&lt;br /&gt;
&lt;br /&gt;
Wichtig: die Platine ist über ihrer Glastemperatur, also biegsam. Die Platine einfach auf dem Ceran Herd auf eine kalte Platte legen und abkühlen lassen.&lt;br /&gt;
&lt;br /&gt;
Eignet sich gut zum Vorwärmen auf ca. 100 - 150°C, auch bei beidseitig bestückten Boards, in Verbindung mit anderen Methoden (z.B. Heißluft).&lt;br /&gt;
&lt;br /&gt;
Ähnliche Vorwärmplatten gibt es speziell für die Löttechnik.&lt;br /&gt;
&lt;br /&gt;
=== Kupferlackdraht ===&lt;br /&gt;
&lt;br /&gt;
Eine weitere sehr elegante Möglichkeit um auch grössere SMD-ICs zerstörungsfei von einer Platine zu bekommen, ist die &amp;quot;Kupferlackdraht-Methode&amp;quot;. Man benötigt lediglich etwas Kupferlackdraht (0,2 - 0,3 mm) und natürlich einen Lötkolben. Die einzige Bedingung ist, dass man den Kupferlackdraht auch unter den Pins bzw. dem Bauteilgehäuse durch fädeln kann.&lt;br /&gt;
&lt;br /&gt;
==== Vorgehensweise ====&lt;br /&gt;
&lt;br /&gt;
# Kupferlackdraht unter den Pins durchfädeln&lt;br /&gt;
# Jeden einzelnen Pin kurz mit dem Lötkolben leicht berühren und gleichzeitig den Kupferlackdraht zwischen Platine und Pin durchziehen&lt;br /&gt;
# Eventuell den Kupferlackdraht erneut unter den Pins durchfädeln und die Pins, bei denen der Kupferlackdraht beim Durchziehen &amp;quot;hängen bleibt&amp;quot;, nochmals mit dem Lötkolben antippen&lt;br /&gt;
&lt;br /&gt;
Es gibt aber auch dünnen Stahldraht (D=0,2mm) für diesen Zweck zu kaufen.&lt;br /&gt;
Das Optimum ist dünnes Bandblech aus Edelstahl, ca 4 - 5 mm breit, ebenfalls 0,2mm dick. Alternativ zu diesem Blech kann man auch einen Skalpellhalter mit Einmalklingen verwenden. Die Spitze des Skalpells wird hinter dem Pin angesetzt (in der Lücke zwischen Pin und Gehäuse), nach unten und vorn gedrückt und der Pin mit dem Lötkolben erwärmt. Sobald der Lötzinn geschmolzen ist, rutscht das Skalpell zum nächsten Pin weiter. Hinterher müssen lediglich die Pins wieder gerade gebogen werden.&lt;br /&gt;
&lt;br /&gt;
=== Recycelte Chips wiederaufbereiten ===&lt;br /&gt;
&lt;br /&gt;
* Zuerst müssen die Lötzinnreste entfernt werden. &lt;br /&gt;
In Alkohol gelöstes Kolophonium wirkt da Wunder. Einfach den Chip in dieses Flussmittel tauchen, welches man vorher z.B. auf einen kleinen Unterteller oder -tasse in kleinen Mengen vergossen hat. &lt;br /&gt;
* Dann mit sauberer Lötspitze an den Pins entlangziehen und das überflüssige Lötzinn an einem Schwamm oder Zellstoff (-Taschentuch) abstreifen. &lt;br /&gt;
* Verklebte Pins mittels dünner Lötspitze auseinanderbringen, auch ein Zahnstocher aus Holz leistet wertvolle Dienste.&lt;br /&gt;
* Bei Pins, die enger als 0,6 mm sind, hilft zusätzlich Entlötsauglitze. Anstelle von Entlötsauglitze kann auch ein dünnes, abisoliertes Litzenkabel (möglichst feindrahtig) dienen.&lt;br /&gt;
:Man sollte aber immer daran denken, dass die Gefahr des Ausfalls durch Überhitzung besteht. &lt;br /&gt;
&lt;br /&gt;
Eine zweite Möglichkeit besteht darin das Lötzin &amp;quot;abzudremeln&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Dazu eine kleine rotierende Messingbürste in den Dremel (Multifunktions-Schleifer) und an den Pins von innen nach außen entlangziehen.&lt;br /&gt;
&lt;br /&gt;
* Stahlbürsten sind mit Vorsicht zu genießen, weil sie einfach zu hart sind. &lt;br /&gt;
* Kunststoffbürsten hingegen können sich elektrostatisch aufladen!&lt;br /&gt;
* Eine &amp;quot;dritte Hand&amp;quot; oder Einspannvorrichtung erleichtert das Recyceln erheblich.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Dritte ist Graphit: Lötzinn und Bleistift sind von Natur aus Feinde. Warmmachen, und Zinn mit Bleistift &amp;quot;wegdrängeln&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Das Ausrichten und Geradebiegen der Pins überlasse ich den eigenen Fähigkeiten.&lt;br /&gt;
== Schlusswort ==&lt;br /&gt;
&lt;br /&gt;
Man sollte nicht glauben, dass man jetzt sofort jegliches SMD einlöten kann, mal abgesehen von Widerständen. Alles benötigt eine gewisse Übung und es empfiehlt sich, erst mit den einfacheren SO-Packages anzufangen und einige TSSOPS einzulöten bevor man sich an TQFP oder ähnliches heranwagt. Außerdem sollte man sich für die ersten Versuche nicht unbedingt einen 10 Euro teuren Chip hernehmen. Wenn man aber nicht 2 linke Hände hat, sollten alle Packages beim zweiten oder dritten Lötversuch einigermaßen sauber eingelötet sein. Und besonders bei den TSSOPs und TQFPs sieht es dann fast wie Industriefertigung aus.&lt;br /&gt;
&lt;br /&gt;
Auslöten kann man gut an defekten Platinen, z.B. aus Computern, üben.&lt;br /&gt;
&lt;br /&gt;
Und ja keine Lötpaste essen!!!!&lt;br /&gt;
Dann wird alles Gut :D&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
[[IC-Gehäuseformen#Adapterplatinen für SMD-ICs|Adapterplatinen für SMD-ICs]]&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* [http://thomaspfeifer.net/ SMD löten/entlöten und Reflow Ofen Selbstbau (unter Trickkiste und AVR Projekte)]&lt;br /&gt;
* [http://www.seattlerobotics.org/encoder/200006/oven_art.htm SMD-Löten im Toastofen] (englisch)&lt;br /&gt;
* [http://www.elv-downloads.de/downloads/journal/SMD-Anleitung.pdf SMD-Anleitung von ELV] praktische Tips (deutsch)&lt;br /&gt;
* [http://www.bimbel.de/artikel/artikel-17.html Bilder und kleine Anleitung]&lt;br /&gt;
* [http://www.ulrichradig.de/ SMD-ICs ein-/auslöten (unter Tipps&amp;amp;Tricks)]&lt;br /&gt;
* [http://www.gadgetpool.de/nuke/modules.php?name=News&amp;amp;file=article&amp;amp;sid=23 SMD-Löten für jedermann]&lt;br /&gt;
* [http://www.makezine.com/blog/archive/2007/01/soldering_tutor_1.html MAKE-Magazine Podcast Loet und Entloet-Tips]&lt;br /&gt;
* [http://www.circuitrework.com Circuit Technology Center] - Surgeon grade rework and repair, by the book and guaranteed. Deeplink: [http://www.circuitrework.com/guides/guides.shtml Guides]&lt;br /&gt;
*[http://www.martin-smt.de SMD Bearbeitungsgeräte - Reworksysteme]&lt;br /&gt;
*[http://www.fritsch-smt.de Bestückungsautomaten / Siebdruckgeräte]&lt;br /&gt;
*[http://www.sef.de Reflowlötanlagen]&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_Checkliste&amp;diff=23938</id>
		<title>AVR Checkliste</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_Checkliste&amp;diff=23938"/>
		<updated>2007-09-28T18:18:31Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: /* ISP-Adapter */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:AVR]]&lt;br /&gt;
Diese Seite soll als erste Anlaufstelle dienen, wenn der AVR-Mikrocontroller mal wieder nicht so will wie er soll. Es wird versucht, die Standardfehler aufzulisten und zu erklären, was man dagegen tun kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
=== Anderen Controller benutzt als den im Schaltplan: Pinkompatibilität sichergestellt? ===&lt;br /&gt;
&lt;br /&gt;
Nur wenige AVR-Controller sind pinkompatibel und damit untereinander austauschbar. Manchmal liegen gar die am dringensten benötigten Funktionen (ISP-Programmierung) bei anderen Controllern auf anderen Pins. Unbedingt vorher die Belegungen anhand der Datenblätter vergleichen!&lt;br /&gt;
&lt;br /&gt;
=== Fuses richtig gesetzt? ===&lt;br /&gt;
&lt;br /&gt;
Die AVR-Controller haben &#039;Fuses&#039; (deutsch: &#039;Sicherungen&#039;), die das Verhalten des Prozessors auf grundlegender Ebene bestimmen. Ein häufiger Fehler ist beispielsweise, dass die falsche Taktquelle gewählt wurde (Fuse &amp;quot;CKSEL&amp;quot; etc.): einige AVRs können mit dem internen Oszillator (&amp;lt;i&amp;gt;internal R/C&amp;lt;/i&amp;gt;), mit einem externen Oszillator (&amp;lt;i&amp;gt;external clock&amp;lt;/i&amp;gt;), mit einem Quarz (&amp;lt;i&amp;gt;external crystal&amp;lt;/i&amp;gt;) oder mit einem Resonator (&amp;lt;i&amp;gt;external R/C&amp;lt;/i&amp;gt;) betrieben werden. Wenn die Einstellung über die Fusebits nicht dazu passt (z. B. &amp;lt;i&amp;gt;external clock&amp;lt;/i&amp;gt; statt &amp;lt;i&amp;gt;external crystal&amp;lt;/i&amp;gt;), fehlt dem Controller unter Umständen der Systemtakt und er läuft nicht an, oder man bekommt auf der seriellen Schnittstelle Nonsens, oder die Timer bzw. Zeitschleifen im Programm laufen zu langsam oder zu schnell.&lt;br /&gt;
&lt;br /&gt;
Eine andere Fuse (JTAGEN) schaltet auf einem Port (z.B. PORTC auf ATMega32) die JTAG-Unterstützung ein bzw. aus. Wenn sie eingeschaltet ist, funktionieren vier Bits dieses Ports nicht wie gewohnt, da sie für die JTAG-Schnittstelle reserviert werden.&lt;br /&gt;
&lt;br /&gt;
In dem zum STK500 gehörenden Entwicklungstool &#039;AVR Studio&#039; gibt es in der Programmer-Dialogbox einen Tab &#039;Fuses&#039;, der controllerabhängig den Status der Fusebits anzeigt und Änderungen ermöglicht.&lt;br /&gt;
Siehe auch: [[AVR Fuses]].&lt;br /&gt;
&lt;br /&gt;
=== ISP-Adapter ===&lt;br /&gt;
&lt;br /&gt;
Bei ISP-Programmieradaptern für den Parallelport kann es zu Inkompatibilitäten mit manchen Ports kommen. Tritt das Problem auch auf, wenn der ISP-Adapter an einem anderen Rechner angeschlossen ist? Funktioniert es vielleicht mit einer anderen Software? Siehe auch: [[AVR In System Programmer]]).&lt;br /&gt;
&lt;br /&gt;
Bei seriellem Programmer mit Controller (STK500, Atmel AVRISP etc.): Programmieren dauert sehr lange, es gibt Fehler. Abhilfe: ISP Taktrate richtig einstellen (&amp;lt;1/4 F_CPU).&lt;br /&gt;
&lt;br /&gt;
Beim Programmieren mit dem usbasp Programmieradapter muss die Geschwindigkeit richtig eingestellt werden. Bei einem AVR der auf den eingebauten 1 Mhz läuft muss mit langsamer Geschwindigkeit (Jumper offen) programmiert werden.&lt;br /&gt;
&lt;br /&gt;
=== Spannungsversorgung richtig angeschlossen? ===&lt;br /&gt;
&lt;br /&gt;
Der AVCC-Pin ist der Versorgungsanschluss für den AD-Wandler und den zugehörigen Port. Er ist nicht an allen AVRs vorhanden; wenn er aber vorhanden ist, so muss er auf jeden Fall angeschlossen sein, auch wenn der AD-Wandler nicht benutzt wird. Wird der AD-Wandler verwendet, sollte zur Verbesserung der Genauigkeit der AVCC-Pin über einen Lowpass-Filter angeschlossen werden (siehe Datenblatt).&lt;br /&gt;
Oft funktioniert die Programmierung des Controllers auch, wenn Vcc oder GND nicht richtig angeschlossen ist. Zur Sicherheit kann man mit einem Messgerät direkt an den Anschlüssen des AVRs kontrollieren (VCC-GND, AVCC-GND) prüfen, ob die Verbindungen korrekt sind. Es empfiehlt sich, vor dem Einsetzen bzw. Einlöten des Controllers die Versorgungsanschlüsse nochmals zu prüfen, um sicherzustellen, dass man den IC nicht durch eine zu hohe Spannung aufgrund eines Fehlers in der Versorgung zerstört.&lt;br /&gt;
&lt;br /&gt;
=== Reset-Pin korrekt beschaltet? ===&lt;br /&gt;
&lt;br /&gt;
Der Reset-Anschluss am AVR ist &#039;active-low&#039;, d. h. wenn man den Pin mit GND (Masse) verbindet, wird der Controller resettet. Zwar haben AVRs einen internen Pullup-Widerstand, der den Reset-Pin gegen VCC &amp;quot;zieht&amp;quot;, dieser ist jedoch relativ hochohmig (ca. 50 kOhm, vgl. Datenblatt) und reicht unter Umständen nicht aus, um den Reset-Pin sicher &amp;quot;hochzuhalten&amp;quot;. Als Mindestbeschaltung empfiehlt sich dringend, einen externen Pullup-Widerstand vorzusehen (typisch 10 kOhm), der den Reset-Pin mit VCC verbindet. Er sollte nicht kleiner als 4,7 kOhm sein, da der Programmieradapter sonst eventuell den Reset-Pin während des Programmiervorgangs nicht sicher auf &amp;quot;low&amp;quot; ziehen kann. Zusätzlich sollte man auch noch einen Kondensator 47 nF oder 100 nF zwischen Reset-Pin und GND anordnen. Dieses RC-Glied sorgt dafür, dass der Controller beim Einschalten der Versorgungsspannung für eine definierte Zeitspanne im Reset gehalten wird. Im laufenden Betrieb sorgt der Kondensator dafür, dass der Reseteingang unempfindlich gegenüber Spikes und Glitches wird. Er sollte deshalb unmittelbar in Pin-Nähe beim Prozessor untergebracht werden. Dieser Kondensator darf jedoch nicht verwendet werden, wenn DebugWire möglich sein soll.&lt;br /&gt;
&lt;br /&gt;
Atmel empfiehlt zusätzlich noch zum Schutz vor Überspannungen eine externe Diode nach VCC (&amp;quot;Clamp-Diode&amp;quot;), da für den Reset-Pin keine interne vorhanden ist. Diese Diode bereitet jedoch bei manchen Programmieradaptern Schwierigkeiten.&lt;br /&gt;
&lt;br /&gt;
=== Abblockkondensator(en) ordnungsgemäß installiert? ===&lt;br /&gt;
&lt;br /&gt;
Abblockkondensatoren (&amp;quot;Bunker-Kondensatoren&amp;quot;) dienen dazu, sehr kurze Versorgungsspannungseinbrüche, die durch Schaltvorgänge verursacht werden können, zu kompensieren. Diesen Zweck erfüllen sie optimal, wenn folgende Regeln eingehalten werden: &lt;br /&gt;
&lt;br /&gt;
* Ein Abblockkondensator sollte möglichst dicht am IC sitzen.&lt;br /&gt;
&lt;br /&gt;
* Jedes IC in einer Schaltung sollte einen Abblockkondensator besitzen.&lt;br /&gt;
&lt;br /&gt;
* Bei ICs mit mehreren Anschlüssen für VCC und GND sollte jedes VCC-GND-Paar mit einem eigenen Abblockkondensator beschaltet werden (z. B. AVRs in SMD-Bauform wie dem ATmega16A also mit vier Kondensatoren).&lt;br /&gt;
&lt;br /&gt;
* Es sollten keramische Kondensatoren mit einer Kapazität von 100 nF verwendet werden. Größere Kondensatoren, etwa 10 µF-Elkos, sind für diese Aufgabe &#039;&#039;nicht&#039;&#039; geeignet, weil sie &amp;quot;zu langsam&amp;quot; sind!&lt;br /&gt;
&lt;br /&gt;
=== Quarz oder Quarzoszillator angeschlossen? ===&lt;br /&gt;
&lt;br /&gt;
Die neueren AVRs haben einen internen [[Oszillator]], der im Auslieferungszustand über die entsprechenden Fuses eingeschaltet ist. In diesem Fall muss kein externer [[Quarz]] mehr angeschlossen werden. Man kann in den [[AVR Fuses|Fuse-Bits]] aber einstellen, dass man einen externen Taktgenerator (&#039;&#039;external clock&#039;&#039;, z. B. Quarzoszillator) oder externen Quarz (&#039;&#039;external crystal&#039;&#039;) verwenden möchte.&lt;br /&gt;
&lt;br /&gt;
Dann, oder wenn der AVR keinen internen Takt hat, wird an die entsprechenden Pins des Controllers ein Quarz (&#039;&#039;external crystal&#039;&#039;, Bauelement mit zwei &amp;quot;Beinchen&amp;quot;) oder Quarzoszillator (&#039;&#039;external clock&#039;&#039;, Bauelement mit vier &amp;quot;Beinchen&amp;quot;) angeschlossen. Im Falle eines Quarzes werden die XTAL-Pins mit den beiden Anschlüssen des Quarzes und jeweils mit einem Kondensator (ca. 22 bis 27 pF) gegen Masse angeschlossen. Im Falle eines Quarzoszillators reicht es aus, den Taktausgang mit dem XTAL1-Pin zu verbinden, und den XTAL2-Pin unbeschaltet zu lassen. Die Fuses sind entsprechend einzustellen.&lt;br /&gt;
&lt;br /&gt;
=== Alle Ground-Anschlüsse beschaltet? ===&lt;br /&gt;
&lt;br /&gt;
Bei AVRs mit mehreren Ground-Anschlüssen müssen alle Anschlüsse beschaltet werden. Siehe http://www.mikrocontroller.net/forum/read-1-107259.html&lt;br /&gt;
&lt;br /&gt;
=== Alle Lötstellen in Ordnung? ===&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Kalte&amp;quot;, d.h. schlechte Lötstellen erkennt man an ihrer matten Oberfläche (bei bleihaltigem Lot). Bei beschädigten Lötstellen erkennt man oft einen Riss, der sich kreisförmig um die Mitte des Lötpunktes herum gebildet hat. Solche Stellen verursachen oft erst bei mechanischer Beanspruchung Probleme.&lt;br /&gt;
&lt;br /&gt;
Bei kleinen Abständen (SMD-Bauteile) müssen besonders Verbindungen zwischen benachbarten Lötungen kontrolliert werden.&lt;br /&gt;
&lt;br /&gt;
Bei Lochrasterplatinen kann man mit einem spitzen Messer (Bastelmesser) die Zwischenräume von möglichen leitenden Verbindungen befreien. &lt;br /&gt;
&lt;br /&gt;
=== Eingänge ===&lt;br /&gt;
&lt;br /&gt;
Taster müssen:&lt;br /&gt;
&lt;br /&gt;
* entprellt werden ([[Entprellung]])&lt;br /&gt;
&lt;br /&gt;
* einen [[AVR-GCC-Tutorial#Tasten_und_Schalter|Pullup-Widerstand]] besitzen, so sie &#039;&#039;active-low&#039;&#039; betrieben werden, d.h. wenn beim Tastendruck der Pin mit GND (Masse) verbunden wird (dies ist die übliche Anschaltung). Man kann einen externen Pull-Up Widerstand (typ. 10 kOhm) benutzen oder den internen aktivieren (DDR als Eingang also &amp;quot;0&amp;quot;, PORT auf &amp;quot;1&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
Will man einen Taster &#039;&#039;active-high&#039;&#039; betreiben, soll also bei Tastendruck eine &amp;quot;1&amp;quot; in PIN gelesen werden, ist ein externer Pull-Down-Widerstand (typ. 10 kOhm) gegen GND anzuschließen, denn interne Pull-Downs sind nicht verfügbar.&lt;br /&gt;
&lt;br /&gt;
Symptome: Aufgrund des Prellens bekommt man bei einem Tastendruck statt eines Signals mehrere, und beim fehlenden Pullup fängt man sich Störungen (z.B. das 50 Hz-Netzbrummen) ein, da der Pin nicht auf einem &amp;quot;definierten Pegel&amp;quot; liegt, wenn der Taster nicht geschlossen ist. Soll z.B. bei einem Tastendruck eine LED angehen, dann leuchtet die LED durch das Netzbrummen plötzlich mit 50 Hz anstatt aus zu sein.&lt;br /&gt;
&lt;br /&gt;
* active low: ein Anschluss des Tasters an den Port-Pin, den anderen Taster-Anschluss an GND; internen Pull-Up-Widerstand aktivieren oder externen Widerstand zwischen Port-Pin und VCC.&lt;br /&gt;
&lt;br /&gt;
* active high: Taster zwischen Port-Pin und VCC; externen Widerstand zwischen Port-Pin und GND.&lt;br /&gt;
&lt;br /&gt;
=== Ausgänge ===&lt;br /&gt;
&lt;br /&gt;
Man sollte darauf achten, das &amp;quot;kritische&amp;quot; Ausgänge, d.h. Ausgänge, über die nicht &amp;quot;nur&amp;quot; eine LED geschaltet wird, einen definierten Zustand haben, wenn der Portpin auf &amp;quot;Eingang&amp;quot; und damit hochohmig geschaltet ist. Dadurch wird sichergestellt, dass beim Einschalten nicht kurz ein Verbraucher geschaltet wird (z.B. &amp;quot;Zucken&amp;quot; eines Motors). Dies kann man bewerkstelligen, indem man extern Widerstände (auch hier Pull-Up bzw. Pull-Down genannt, typ. 10 kOhm) an den Ausgangs-Pins vorsieht, die den Ausgang auf den gewünschten Zustand ziehen.&lt;br /&gt;
&lt;br /&gt;
=== Besonderheiten bei ATmega64 / ATmega128 ===&lt;br /&gt;
&lt;br /&gt;
Der ATmega64 und der ATmega128 haben zwei besondere Fallstricke, über die man bei nicht ausreichendem Datenblattstudium leicht stolpert. &lt;br /&gt;
&lt;br /&gt;
* Der erste betrifft den Anschluss der ISP-Signale (MISO, MOSI, SCK, RESET). Dieser erfolgt nicht wie bei den meisten anderen AVR-Controllern an den gleichnamigen Pins, sondern an PDI, PDO, SCK und RESET. Die Pinzuordnung ist:  MOSI-&amp;gt;PE0 (Pin 2), MISO-&amp;gt;PE1 (Pin 3), SCK-&amp;gt;PB1 (Pin 11) und RESET-&amp;gt;RESET (Pin 20). PEN (Pin 1) hat für normale ISP-Adapter keine Bedeutung und kann offen gelassen oder direkt mit Vcc verbunden werden. Die Benutzung der Pins PDI und PDO anstelle von MOSI und MISO gilt zusätzlich für einige ATMega128-Derivate im 64-Pin-TQFP-Gehäuse (darunter AT90CAN128, ATMega1281/2561)! Im Zweifelsfall im Datenblatt (Pin Configuration) nachsehen, ob PE0 und PE1 mit &amp;quot;PDI&amp;quot; bzw. &amp;quot;PDO&amp;quot; beschriftet sind.&lt;br /&gt;
&lt;br /&gt;
* Die zweite kleine &amp;quot;Gemeinheit&amp;quot; betrifft die &#039;&#039;&#039;M103C-Fuse&#039;&#039;&#039; (Atmega103 Compatibility Mode). Diese ist bei fabrikneuen Atmega64 und Atmega128 gesetzt und sorgt dafür, dass sich diese wie ein Atmega103 verhalten.&lt;br /&gt;
** Andererseits hat dies zur Folge, dass ein für den Atmega64 oder Atmega128 geschriebenes Programm beim ersten &amp;quot;ret&amp;quot; abstürzt, da der SRAM an einer anderen Stelle liegt als erwartet und somit der Prozessor keine gültige Rücksprungadresse vom Stack holen kann. &lt;br /&gt;
** Außerdem funktionieren einige IO-Pins an PORTC, PORTF und PORTG anders.&lt;br /&gt;
** Für weitere Infos bzgl. [[TWI]], [[UART]], [[Timer]], [[Bootloader]] und Kalibrierung des internen RC-Oszillators unbedingt das Datenblatt lesen.&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
&lt;br /&gt;
=== Alle Interruptvektoren definiert? ===&lt;br /&gt;
&lt;br /&gt;
Wenn man irgendwelche [[Interrupt]]vektoren verwendet, sollte man alle definieren, auch die nicht benutzten. Passiert es dann aufgrund eines Fehlers, dass ein Interrupt unbeabsichtigt ausgeführt wird, so führt der Controller dann eine definierte Aktion aus. Benutzt man eine Hochsprache wie C oder Basic, nimmt einem der Compiler diese Arbeit ab.&lt;br /&gt;
&lt;br /&gt;
In einem komplett &amp;quot;interrupt-losen&amp;quot; Programm (erkennbar daran, dass nirgendwo im Code Interrupts mittels Assembler-Befehl &#039;&#039;&#039;sei&#039;&#039;&#039; eingeschaltet werden), kann man auf die Interrupttabelle selbstverständlich verzichten.&lt;br /&gt;
&lt;br /&gt;
=== Alle Konfigurationsregister korrekt initialisiert? ===&lt;br /&gt;
&lt;br /&gt;
Alle benötigten Konfigurationsregister (auch &amp;quot;I/O-Register&amp;quot; genannt) eines Mikrocontrollers müssen korrekt initialisiert werden. Bei Fehlfunktionen sollten diese Konfigurationen noch einmal mit dem Datenblatt abgeglichen werden. &lt;br /&gt;
Manchmal ist es auch sinnvoll, bestimmte Funktionen explizit abzuwählen. Ein Beispiel hierfür ist der [[Analog-Komparator]] des AVR: Schaltet man diesen ab, wenn man ihn nicht benötigt, kann man dadurch ein wenig Strom sparen. &lt;br /&gt;
Wenn man besonders &amp;quot;sauber&amp;quot; programmieren möchte, initialisiert man Konfigurationsregister immer, d.h. auch wenn sie nicht im Programm verwendet werden. Dies verhindert mögliche zufällige Fehlkonfigurationen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Stackpointer initialisiert? (Nur in Assembler relevant) ===&lt;br /&gt;
&lt;br /&gt;
Fehlerbeschreibung: &#039;&#039;Das Programm lief, bis ein &amp;quot;rcall&amp;quot; oder ein Interrupt eingefügt wurde. Danach ging plötzlich gar nichts mehr.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wahrscheinliche Ursache: Der Stack ist ein spezieller Bereich im RAM, der von Sprungbefehlen und Interruptaufrufen dazu verwendet wird, die Rücksprungadresse ins Hauptprogramm zu speichern.  Da der Stack bei den AVRs nach &amp;quot;unten&amp;quot; wächst, d.h. in Richtung Anfang des RAMs, wird er üblicherweise ans Ende des RAMs gelegt. Der Stack muss vor der ersten Benutzung, am besten direkt am Anfang des Programms, initialisiert werden (sonst ist nach einem Sprung in ein Unterprogramm die Rücksprungadresse undefiniert und das Programm wird an einer unvorhersehbaren Stelle weiter ausgeführt, was in der Regel einen Absturz zur Folge hat). &amp;quot;Den Stack initialisieren&amp;quot; bedeutet, den Stackpointer auf den gewünschten &amp;quot;Startwert&amp;quot; zu setzen. Meistens wird dafür die letzte RAM-Adresse gewählt. &lt;br /&gt;
&lt;br /&gt;
Die Initialisierung unterscheidet sich geringfügig je nach verwendetem AVR. Bei den alten AT90xxxx und den ATtinys ist sie mit zwei Zeilen erledigt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
       ldi r16, RAMEND   ;Die Adresse der letzten Stelle im RAM in r16 laden&lt;br /&gt;
       out SPL, r16      ;Die Adresse in das Register SPL ausgeben&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 &lt;br /&gt;
Da die ATmegas mehr RAM haben, reicht das 8 bit-Register SPL nicht mehr, und es ist ein zweites (SPH) dazugekommen.  Die Initialisierung des Stacks erfordert hier vier Zeilen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
       ldi r16, LOW(RAMEND)    ;Untere 8 bit des 16 bit-Wertes RAMEND laden&lt;br /&gt;
       out SPL, r16&lt;br /&gt;
       ldi r16, HIGH(RAMEND)   ;Obere 8 bit laden&lt;br /&gt;
       out SPH, r16&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 16bit-Register in richtiger Reihenfolge geladen/gelesen? (Nur in Assembler relevant) ===&lt;br /&gt;
&lt;br /&gt;
Bei den 16-bit Registern (z.B. Timer1) genau die Hinweise im Kapitel &amp;quot;Accessing 16-bit Registers&amp;quot; beachten!&lt;br /&gt;
&lt;br /&gt;
So muss z.B. das High-Byte VOR dem Low-Byte geschrieben werden, weil mit dem Schreiben des Low Byte das gesamte Register &amp;quot;übernommen&amp;quot; wird.&lt;br /&gt;
Beim Lesen muss zuerst das Low-Byte gelesen werden, dann das High-Byte.&lt;br /&gt;
Es wird dadurch garantiert, dass sich zwischen den beiden einzelnen Befehlen nicht noch das Register weiter verändert, z.B. beim 16bit Counter.&lt;br /&gt;
Möglich wird das durch ein &amp;quot;temporary Register&amp;quot;, von dem es aber nur eines gibt - was beachtet werden muss, da zwischen diesen beiden einzelnen Lese-/Schreib-Befehlen kein Interrupt auftreten darf, der selber das temporary Rgegister benutzt.&lt;br /&gt;
&lt;br /&gt;
In C oder Basic kümmert sich der Compiler um das Problem - man liest oder beschreibt dann einfach z.B. TCNT1 anstatt TCNT1H und TCNT1L einzeln.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Flag richtig gelöscht? ===&lt;br /&gt;
&lt;br /&gt;
Ein beliebter Fehler ist, dass man überliest, dass gesetzte Flags (z.B. die Interrupt-Flags) durch beschreiben mit einer &#039;1&#039; und nicht mit einer &#039;0&#039; gelöscht werden! &lt;br /&gt;
&lt;br /&gt;
Beispiel: &lt;br /&gt;
* das Flag ist zuerst &#039;0&#039;&lt;br /&gt;
* das Ereignis (z.B. Zählerüberlauf, also Bit TOV0 in TIFR) tritt auf und setzt das jeweilige Bit im Register auf &#039;1&#039;&lt;br /&gt;
* wir haben auf die &#039;1&#039; gewartet und wollen das Bit nun wieder löschen und müssen dafür eine &#039;1&#039; (eins!) in das Register schreiben, &#039;&#039;&#039;keine&#039;&#039;&#039; &#039;0&#039;. Trotzdem wird das Bit dadurch &#039;0&#039; z.B.:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
    TIFR = (1&amp;lt;&amp;lt;TOV0);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das ganze ist kein Fehler, sondern hat seine guten Gründe.&lt;br /&gt;
&lt;br /&gt;
Wenn Interrupts zugelassen sind (z.B. in TIMSK) und die Interruptroutine aufgerufen wird, werden diese Flags zumeist automatisch gelöscht.&lt;br /&gt;
&lt;br /&gt;
Der UART-Empfangs-Interrupt (RXC in UCSRA) jedoch nicht! Der wird gelöscht durch Auslesen des Empfangsregisters (UDR). Hier liegt wiederum ein beliebter Stolperstein: Man prüft oft zuerst in der Interruptroutine die Fehlerflags (z.B. Parity) und macht dann manchmal den Fehler das empfangene Zeichen im Fehlerfall nicht auszulesen. Das führt dann zum Absturz (der IRQ wird immer wieder aufgerufen) - man muss also immer das UDR lesen auch wenn etwas Fehlerhaftes drinsteht.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich ist zu beachten, dass in C die Interrupt-Flags &#039;&#039;&#039;nicht&#039;&#039;&#039; mit einer Veroderung des Registers (z.B. TIFR |= (1 &amp;lt;&amp;lt; TOV0)) gelöscht werden sollten, da bei dieser Operation alle anderen evtl. gesetzten Flags im betreffenden Register ebenfalls gelöscht werden. Es ist die Schreibweise von oben zu benutzen (also TIFR = (1 &amp;lt;&amp;lt; TOV0))!&lt;br /&gt;
&lt;br /&gt;
== Serielle Verbindungen ==&lt;br /&gt;
&lt;br /&gt;
=== I²C/TWI ===&lt;br /&gt;
&lt;br /&gt;
Sind die Leitungen SCL und SDA mit einem Pullup-Widerstand ausgestattet? Die I²C-Bus-Leitungen SCL und SDA müssen über einen Pullup-Widerstand mit einem Wert von 4,7 kOhm bis 10 kOhm mit der Versorgungsspannung (+5 V) verbunden sein.&lt;br /&gt;
&lt;br /&gt;
=== [[UART]]/USART ===&lt;br /&gt;
&lt;br /&gt;
==== Übertragungsprobleme wegen falschem Takt? ====&lt;br /&gt;
&lt;br /&gt;
* Der interne [[Oszillator]] ist recht ungenau und nicht [[temperaturstabil]]. Daher kann die Umgebungstemperatur auch den [[USART]]-Takt verändern. Für schnelle serielle Kommunikation sollte man deshalb immer einen Quarz(oszillator) verwenden. Falls doch der interne Oszillator verwendet wird, wurde er für die richtige Frequenz kalibriert?&lt;br /&gt;
&lt;br /&gt;
* Nicht mit allen Quarzen kann man alle Baudraten exakt erzeugen; deswegen gibt es [[Baudratenquarz]]e wie 3,6864 MHz. Näheres steht im Datenblatt.&lt;br /&gt;
&lt;br /&gt;
* Geschieht die Konfiguration des U(S)ART automatisch durch die Programmiersprache (z.B. in [[BASCOM]]), dann muss dort der Takt &#039;&#039;genau&#039;&#039; angegeben werden. Setzt man z.B. einen 3,6864 MHz-Quarz ein, darf man dort nicht einfach &amp;quot;4 MHz&amp;quot; angeben, weil dann die Abweichung mit ca. 8% viel zu hoch wäre. Damit funktioniert die Übertragung nicht mehr.&lt;br /&gt;
&lt;br /&gt;
* Wenn ein externer Oszillator oder Quarz angeschlossen ist: Sind die Fuses des Controllers so gesetzt, dass er auch verwendet wird?&lt;br /&gt;
&lt;br /&gt;
==== Sonstige Fehlerquellen bei UART/USART ====&lt;br /&gt;
&lt;br /&gt;
* Funktioniert die Datenübertragung zum PC nur solange der Programmieradapter eingesteckt ist, deutet dies auf ein Problem mit der Masse hin (z.B. GND-Anschluss am RS232-Stecker nicht belegt oder dergleichen).&lt;br /&gt;
&lt;br /&gt;
* Der Pegelwandler/Inverter (z.B. MAX232/HIN232) muss mit Kondensatoren für die internen Ladungspumpen beschaltet werden. Beim MAX232 sind dies mindestens vier Kondensatoren &amp;gt;= 1 µF (Polung beachten!), beim MAX202 und MAX3232 vier Kondensatoren &amp;gt;= 100 nF. Hinzu kommt der obligatorische Abblockkondensator (100 nF keramisch) zwischen VCC und GND des ICs. Das jeweilige Datenblatt gibt Auskunft über die Beschaltung bei &amp;quot;typischer Anwendung&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
* TX/RX vertauscht?&lt;br /&gt;
&lt;br /&gt;
== Analog-Digital-Wandler ==&lt;br /&gt;
&lt;br /&gt;
* Sind die Pullup-Widerstände deaktiviert?&lt;br /&gt;
&lt;br /&gt;
== Web-Links ==&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc2521.pdf Application Note AVR042: AVR Hardware Design Considerations]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc1619.pdf Application Note AVR040: EMC Design Considerations]&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Standardbauelemente&amp;diff=21574</id>
		<title>Standardbauelemente</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Standardbauelemente&amp;diff=21574"/>
		<updated>2007-05-14T12:39:53Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: /* Speicher */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Gerade Neulinge kennen das Problem: Man hat eine tolle Schaltung mit vielen Operationsverstärkern, Spannungsreglern, Logikbausteinen, ADCs, was auch immer entwickelt und jetzt geht&#039;s an die Realisierung.&lt;br /&gt;
&lt;br /&gt;
Aber welche Bausteine nehmen unter dem Wust der Angebote? Also erstmal auf die Seiten der Hersteller und die Produktpalette durchforsten. Nach einigen Stunden gewissenhafter Recherche hat man dann endlich alle Bauteile beisammen und will bestellen. Und dann kommt das böse Erwachen: Einige Bauelemente gibt&#039;s nur bei Reichelt, andere nur bei Conrad. Farnell hat zwar das meiste, aber da kann man als Privatperson leider nicht bestellen. Manche ICs bekommt man nur in 1000er Stückzahlen oder sind halt einfach nur viel zu teuer.&lt;br /&gt;
&lt;br /&gt;
Nach einigen Jahren praktischer Erfahrung hat man dann seine &amp;quot;Standardbauelemente&amp;quot;, die man immer wieder verwendet. Dieser Artikel soll helfen andere von dieser Erfahrung profitieren zu lassen. Ähnliche Anregungen findet man auch in der de.sci.electronics-FAQ: Grundausstattung des Bastlers [[http://dse-faq.elektronik-kompendium.de/dse-faq.htm#F.2]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= !Hinweise! =&lt;br /&gt;
Hier soll eine Liste von häufig anzutreffenden, preiswerten und verfügbaren Standardbauelementen entstehen. Diese Liste soll knapp und bündig sein, für technische Daten wird auf die Datenblätter verwiesen. Hier gilt: &amp;quot;weniger ist mehr&amp;quot;, exotische Bauelemente sind also unerwünscht. Für hier gelistete Typen sollte gelten:&lt;br /&gt;
* für Privatpersonen verfügbar&lt;br /&gt;
* preiswert (nicht billig)&lt;br /&gt;
&lt;br /&gt;
Nicht gelistet werden sollen:&lt;br /&gt;
* hunderte Typen, die alle den gleichen Zweck erfüllen, aber keinen Mehrwert bringen. Stattdessen auf die bekanntesten / preiswertesten beschränken.&lt;br /&gt;
* Details. Stattdessen die Felder &amp;quot;Besonderheiten&amp;quot; und &amp;quot;Anwendungen&amp;quot; benutzen, z.B. &amp;quot;I²C, 12bit&amp;quot; bei Besonderheiten für einen ADC oder &amp;quot;Präzision, Audio&amp;quot; bei Anwendungen für einen OpAmp.&lt;br /&gt;
&lt;br /&gt;
Wer eine Sparte, oder eine Anwendung vermisst, aber selber nichts dazu beitragen kann: Einfach hinzufügen. Wer z.B. einen HF OpAmp sucht und hier nicht fündig wird sollte also eine neue Zeile einfügen und in die Spalte Anwendungen &amp;quot;HF&amp;quot; eintragen. Villeicht kann ja jemand den Rest der Zeile füllen.&lt;br /&gt;
&lt;br /&gt;
Immer den Grundtypen listen und nicht eine der Varianten, und schon gar nicht alle Varianten einzeln! Also z.B. &amp;quot;LM324&amp;quot; statt &amp;quot;LM324N&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Wenn möglich Direktlinks auf Datenblätter vermeiden und eine Suchmaschine befragen: &amp;quot;http://www.datasheetarchive.com/search.php?q=lm324&amp;quot;&lt;br /&gt;
* so werden alle Varianten gefunden&lt;br /&gt;
* und tote Links vermieden&lt;br /&gt;
&lt;br /&gt;
Die wichtigsten, allgemeinen Standard-Typen ganz oben in der Tabelle listen, danach erst die Spezialtypen für bestimmte Anwendungen.&lt;br /&gt;
&lt;br /&gt;
Und weil es mir so wichtig ist nochmal: Ich rufe geradezu dazu auf, überflüssige, unverfügbare Typen zu löschen!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Aktive Bauelemente =&lt;br /&gt;
== Analog ==&lt;br /&gt;
&lt;br /&gt;
=== Transistoren ===&lt;br /&gt;
NPN&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;transistors-npn&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| BC 337&lt;br /&gt;
| 0,04&lt;br /&gt;
| Standardtyp&lt;br /&gt;
| bis ~300mA sinnvoll&lt;br /&gt;
| R,D&lt;br /&gt;
| [http://www.google.de/search?num=100&amp;amp;hl=de&amp;amp;q=datasheet+bc337+filetype%3Apdf&amp;amp;btnG=Suche&amp;amp;meta=lr%3Dlang_de%7Clang_en PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BC 547/847&lt;br /&gt;
| 0,03&lt;br /&gt;
| Standardtyp, BC847 in SMD&lt;br /&gt;
| bis ~50mA sinnvoll&lt;br /&gt;
| R,D&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat_download/datasheets/BC847_BC547_SER_6.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BC 635/639&lt;br /&gt;
| 0,07&lt;br /&gt;
| andere Pinbelegung als BC547 (= BD135 in anderem Gehäuse)&lt;br /&gt;
| bis ~500mA sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat/datasheets/BC635_BCP54_BCX54_6.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BD 433/437&lt;br /&gt;
| 0,19&lt;br /&gt;
| niedrige Sättigungsspannung&lt;br /&gt;
| bis ~2A sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.fairchildsemi.com/ds/BD%2FBD435.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| TIP102&lt;br /&gt;
| 0,42&lt;br /&gt;
| Ptot bis 80W mit Kühlkörper, hohe Stromverstärkung von über 1000 über einen sehr großen Bereich.&lt;br /&gt;
| Grenzwert 8A&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.fairchildsemi.com/ds/TI%2FTIP102.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| TIP 3055&lt;br /&gt;
| 0,75&lt;br /&gt;
| Ptot bis 90W mit Kühlkörper, Stromverstärkung sehr niedrig (bei großen Strömen &amp;lt;&amp;lt; 100)&lt;br /&gt;
| Grenzwert 15A &lt;br /&gt;
| R&lt;br /&gt;
| [http://www.ortodoxism.ro/datasheets/PowerInnovations/mXvutwr.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
PNP&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;transistors-pnp&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| BC 327&lt;br /&gt;
| 0,04&lt;br /&gt;
| Komplementärtyp zu BC337&lt;br /&gt;
| bis ~300mA sinnvoll&lt;br /&gt;
| R,D&lt;br /&gt;
| [http://www.google.de/search?num=100&amp;amp;hl=de&amp;amp;q=datasheet+bc327+filetype%3Apdf&amp;amp;btnG=Suche&amp;amp;meta=lr%3Dlang_de%7Clang_en PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BC 557&lt;br /&gt;
| 0,03&lt;br /&gt;
| Komplementärtyp zu BC547C&lt;br /&gt;
| bis ~50mA sinnvoll&lt;br /&gt;
| R,D&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat_download/datasheets/BC556_557_4.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BC 636/640&lt;br /&gt;
| 0,07&lt;br /&gt;
| Komplementärtyp zu BC635&lt;br /&gt;
| bis ~500mA sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat/datasheets/BC640_BCP53_BCX53_6.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| TIP 2955&lt;br /&gt;
| 0,75&lt;br /&gt;
| Ptot bis 90W mit Kühlkörper&lt;br /&gt;
| Grenzwert 15A&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.ortodoxism.ro/datasheets/motorola/TIP2955.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eigene Seite für MOSFETs: [[Mosfet-Übersicht]]&lt;br /&gt;
&lt;br /&gt;
N-MOSFET&lt;br /&gt;
&lt;br /&gt;
BUZ10, BUZ11 etc. sind wie alle BUZ Typen ziemlich veraltet. Bitte nicht listen; es gibt fast immer was besseres von IRF.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;mosfet-n&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| IRF1010N&lt;br /&gt;
| 0,87&lt;br /&gt;
| max 50V, max 85A, 11 mOhm On-Widerstand&lt;br /&gt;
| Alles, was mit POWER zu tun hat ...&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.irf.com/product-info/datasheets/data/irf1010n.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| IRLZ34N&lt;br /&gt;
| 0,42&lt;br /&gt;
| max 55V, max 30A, 35 mOhm On-Widerstand&lt;br /&gt;
| Gatespannung kompatibel mit 5V-Controllern.&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.irf.com/product-info/datasheets/data/irlz34n.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BS170&lt;br /&gt;
| 0,13&lt;br /&gt;
| max 60V, bis 500mA, 5 Ohm On-Widerstand&lt;br /&gt;
| veraltete Technik aber in bastelfreundlichem TO-92 Gehäuse von R lieferbar &lt;br /&gt;
| R&lt;br /&gt;
| [http://www.fairchildsemi.com/ds/BS/BS170.pdf PDF] (Fairchild)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
P-MOSFET&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;mosfet-p&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| IRF7220&lt;br /&gt;
| 1,10&lt;br /&gt;
| max -14V, ca -10A (cont.), ca. 0,02 Ohm On-Widerstand&lt;br /&gt;
| Gehäuse SO-8, brauchbar in 3,3V Systemen&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.irf.com/product-info/datasheets/data/irf7220.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BS250&lt;br /&gt;
| 0,18&lt;br /&gt;
| max -45V, bis -230mA (cont.), 14 (und mehr) Ohm On-Widerstand&lt;br /&gt;
| veraltete Technik aber in bastelfreundlichem TO-92 Gehäuse von R lieferbar &lt;br /&gt;
| R&lt;br /&gt;
| [http://www.vishay.com/docs/70209/70209.pdf PDF] (Vishay)&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
MOSFET-Pärchen&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;mosfet-n-p&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| IRF7389&lt;br /&gt;
| 0,51&lt;br /&gt;
| 30 V, &amp;gt;2,5 A, 30/60 mOhm On-Widerstand&lt;br /&gt;
| Gehäuse SO-8&lt;br /&gt;
| D,R&lt;br /&gt;
| [http://www.irf.com/product-info/datasheets/data/irf7389.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dioden ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;mosfet-p&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| 1N4148&lt;br /&gt;
| 0,02&lt;br /&gt;
| Kleinsignal-Gleichrichterdiode&lt;br /&gt;
| &lt;br /&gt;
| R,D&lt;br /&gt;
| [http://www.fairchildsemi.com/ds/1N%2F1N4148.pdf D]&lt;br /&gt;
|-&lt;br /&gt;
| 1N4001..1N4007&lt;br /&gt;
| 0,02&lt;br /&gt;
| Mehrzweck-Gleichrichterdiode, 1N4001..1N4007 mit gestaffelter Sperrspannung&lt;br /&gt;
| 1A&lt;br /&gt;
| R,D&lt;br /&gt;
| [http://www.fairchildsemi.com/ds/1N/1N4001.pdf D]&lt;br /&gt;
|-&lt;br /&gt;
| 1N5400..1N5408&lt;br /&gt;
| 0,06&lt;br /&gt;
| Mehrzweck-Gleichrichterdiode, 1N5400..1N5408 mit gestaffelter Sperrspannung&lt;br /&gt;
| 3A, 50..1000V&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.ortodoxism.ro/datasheets/fairchild/1N5401.pdf D]&lt;br /&gt;
|-&lt;br /&gt;
| BAT46&lt;br /&gt;
| 0,10&lt;br /&gt;
| Kleinsignal-Schottky-Diode&lt;br /&gt;
|&lt;br /&gt;
| D,R&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| SB140&lt;br /&gt;
|&lt;br /&gt;
| Schottky-Diode&lt;br /&gt;
| 1A 40V&lt;br /&gt;
| R&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| BA159&lt;br /&gt;
| 0,051&lt;br /&gt;
| Standard-Diode&lt;br /&gt;
| HF 1A 1000V&lt;br /&gt;
| R&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| BAV99&lt;br /&gt;
| 0,041&lt;br /&gt;
| Standard-Doppeldiode, SOT-23&lt;br /&gt;
| ESD-Schutz&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.alldatasheet.com/view.jsp?Searchword=BAV99 D]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Instrumentenverstärker ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| INA128&lt;br /&gt;
| 6,15 (R)&lt;br /&gt;
| Verstärkung über 1 Widerstand einstellbar&lt;br /&gt;
| Brückenverstärker , Datenerfassung&lt;br /&gt;
| R,F&lt;br /&gt;
| [http://focus.ti.com/lit/ds/symlink/ina128.pdf#search=%22ina128%22 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| ??????&lt;br /&gt;
| &amp;lt; 2&lt;br /&gt;
| Standardtyp&lt;br /&gt;
| billig&lt;br /&gt;
| ??????&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=????? PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Operationsverstärker ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| LM358&lt;br /&gt;
| 0,09&lt;br /&gt;
| Single Supply&lt;br /&gt;
| 2-fach Standard-OP&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=lm358 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM324&lt;br /&gt;
| 0,13&lt;br /&gt;
| Single Supply&lt;br /&gt;
| 4-fach Standard-OP&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=lm324 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM393&lt;br /&gt;
| 0,10&lt;br /&gt;
| Single Supply&lt;br /&gt;
| 2-fach Standard-Komparator&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=lm393 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM339&lt;br /&gt;
| 0,10&lt;br /&gt;
| Single Supply&lt;br /&gt;
| 4-fach Standard-Komparator&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=lm339 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| NE5532&lt;br /&gt;
| 0,23&lt;br /&gt;
| 2 * Audio OP&lt;br /&gt;
| kann 600 Ohm treiben&lt;br /&gt;
| alle?&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=NE5532 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LMC6484&lt;br /&gt;
| 2,35&lt;br /&gt;
| R2R in/out&lt;br /&gt;
| 4-fach OP&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.national.com/ds.cgi/LM/LMC6484.pdf D]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Spannungsregler ===&lt;br /&gt;
Linearregler&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;linearregler&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| LP2950&lt;br /&gt;
| 0,39 - 0,53&lt;br /&gt;
| Festspannungsregler Low-Dropout&lt;br /&gt;
| 3 - 5V 100mA, TO-92&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LP2950 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM317&lt;br /&gt;
| 0,22&lt;br /&gt;
| Linearer einstellbarer Spannungsregler&lt;br /&gt;
| max 40V -&amp;gt; 1,2 - 37V, max 1.5A, TO220&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LM317 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| MAX663&lt;br /&gt;
| 1,80&lt;br /&gt;
| Linearer, einstellbarer Spannungsregler&lt;br /&gt;
| sehr niedriger Eigenstromverbrauch&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=MAX663 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM78xx&lt;br /&gt;
| &amp;lt;1,00&lt;br /&gt;
| Festspannungregeler (xx=05: 5V, xx=12: 12V ...)&lt;br /&gt;
| &lt;br /&gt;
| alle&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
Schaltregler&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;schaltregler&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| LM2576&lt;br /&gt;
| 1,60&lt;br /&gt;
| Step-Down&lt;br /&gt;
| max 40V -&amp;gt; 1,2 - 37V, max 3A, TO220-5&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LM2576 PDF] - [http://www.mikrocontroller.net/topic/58094#450561 mit Funk-Entstördrossel FED100µ (Reichelt...) bis 3 A]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Digital ==&lt;br /&gt;
=== CAN ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;can&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| MCP2515&lt;br /&gt;
| 1,95&lt;br /&gt;
| SPI-CAN 2.0B Baustein&lt;br /&gt;
| &lt;br /&gt;
| Reichelt&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
| SJA1000&lt;br /&gt;
| 4,55&lt;br /&gt;
| PellCAN 2.0B 1Mbit/s&lt;br /&gt;
|&lt;br /&gt;
| Reichelt&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Logik ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (€)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| 74HC4050&lt;br /&gt;
| 0,27&lt;br /&gt;
| z.B. 5V =&amp;gt; 3V&lt;br /&gt;
| Pegelwandler unidirektional abwärts&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=74hc4050 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| HEF4104B&lt;br /&gt;
| 0,77&lt;br /&gt;
| z.B. 5V =&amp;gt; 12V&lt;br /&gt;
| Pegelwandler unidirektional aufwärts&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=HEF4104B PDF]&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== USB ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;usb&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| FT232&lt;br /&gt;
| 5,65&lt;br /&gt;
| USB &amp;lt;-&amp;gt; RS232 Wandler&lt;br /&gt;
| Zugriff über virtuellen COM Port&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=ft232 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| FT245&lt;br /&gt;
| 6,35&lt;br /&gt;
| USB &amp;lt;-&amp;gt; Seriell Wandler mit paralleler Schnittstelle&lt;br /&gt;
| Zugriff über virtuellen COM Port&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=ft245 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Treiber ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| ULN2003A&lt;br /&gt;
| 0,17&lt;br /&gt;
| 7-fach Low-Side Treiber&lt;br /&gt;
| 50V/500mA&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=ULN2003 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| ULN2803A&lt;br /&gt;
| 0,44&lt;br /&gt;
| 8-fach Low-Side Treiber&lt;br /&gt;
| 50V/500mA&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=ULN2803 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| UDN2981&lt;br /&gt;
| 1,50&lt;br /&gt;
| 8-fach High-Side Treiber&lt;br /&gt;
| 50V/500mA&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=UDN2981 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| ICL7667&lt;br /&gt;
| 1&lt;br /&gt;
| Dual inverting FET Treiber&lt;br /&gt;
| 18V, 20ns@1nF&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=ICL7667 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Galvanische Trennelemente ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| CNY17&lt;br /&gt;
| 0,17&lt;br /&gt;
| Optisch, Standardtyp&lt;br /&gt;
| billig&lt;br /&gt;
| R,C&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=CNY17 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| 6N137&lt;br /&gt;
| 0,49&lt;br /&gt;
| Optisch, Logikausgang&lt;br /&gt;
| sehr schnell&lt;br /&gt;
| R,D&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=6N137 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| ADUM240*&lt;br /&gt;
| 10&lt;br /&gt;
| Induktiv, 3V/5V Logik&lt;br /&gt;
| extrem schnell, EN90650, 5kV&lt;br /&gt;
| F&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=adum240 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Displays ===&lt;br /&gt;
Bei den Textdisplays eignet sich praktisch jedes HD44780 konforme Display.&lt;br /&gt;
Praktisch jeder Elektronikversender hat eine Auswahl an verschiedenen Größen zu bieten. &lt;br /&gt;
Wer keinen besonderen Anspruch auf die Größe der Displays hat sollte sich bei Pollin und in Ebay umschauen.&lt;br /&gt;
&lt;br /&gt;
=== Speicher ===&lt;br /&gt;
&lt;br /&gt;
==== [[EEPROM]] ====&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;EEPROMmemory&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| ST 24C01 BN6, ST 24C02 BN6, ST 24C256 BN6&lt;br /&gt;
| 0,14€ - 1,40€&lt;br /&gt;
| EEPROM Speicher mit seriellem (I2C) Interface, 1kbit bis 256 kbit Speicher&lt;br /&gt;
| Speichern von Konfigurationsdaten &lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Converter ==&lt;br /&gt;
=== ADC ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
=== DAC ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
== Sensoren (aktiv) ==&lt;br /&gt;
=== [[Temperatursensor|Temperatur]] ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| LM75&lt;br /&gt;
| ~2,10&lt;br /&gt;
| Temperatursensor mit I²C (TWI) Bus Interface (3.3V und 5V Version) (SMD)&lt;br /&gt;
| &lt;br /&gt;
| R D&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LM75 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| DS1621&lt;br /&gt;
| ~5&lt;br /&gt;
| Temperatursensor mit I²C (TWI) Bus Interface (wie LM75, kein SMD)&lt;br /&gt;
| &lt;br /&gt;
| C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| DS18B20&lt;br /&gt;
| 4,30&lt;br /&gt;
| Temperatursensor mit 1-Wire Interface&lt;br /&gt;
|&lt;br /&gt;
| R D&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=DS18B20 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM35&lt;br /&gt;
| 1,49&lt;br /&gt;
| Analoger Temperatursensor&lt;br /&gt;
| 10mV/°C absolut&lt;br /&gt;
| D&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LM35 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM335&lt;br /&gt;
| 0,87&lt;br /&gt;
| Analoger Temperatursensor&lt;br /&gt;
| 10mV/K absolut&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LM335 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
Wenn man z.B. einen Übertemperaturschutz (oder eine andere Schaltung, bei der es nur eine Schaltschwelle gibt) bauen will, dann empfiehlt sich die Verwendung eines NTCs. Dessen Kennlinie ist gegenüber den Kennlinien von z.B. LM335 dahingehend im Vorteil, dass eine geringe Temperaturänderung besser messbar ist.&lt;br /&gt;
&lt;br /&gt;
= Passive Bauelemente =&lt;br /&gt;
== Sensoren (passiv) ==&lt;br /&gt;
=== Licht ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
=== [[Temperatursensor|Temperatur]] ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| KTY81&lt;br /&gt;
| ~0,50&lt;br /&gt;
| nichtlinear, bis 150°C&lt;br /&gt;
| in &amp;amp;#956;C Schaltungen&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat/datasheets/KTY84_SERIES_5.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| KTY84&lt;br /&gt;
| 0,72&lt;br /&gt;
| nichtlinear, bis 300°C&lt;br /&gt;
| in &amp;amp;#956;C Schaltungen&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat/datasheets/KTY84_SERIES_5.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| PT100&lt;br /&gt;
| ab 3,00&lt;br /&gt;
| lineare Kennlinie&lt;br /&gt;
| analoge Messschaltungen&lt;br /&gt;
| F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Widerstände ===&lt;br /&gt;
Mit einem Widerstandssortiment, welches die E12-Werte enthält, kann man normalerweise nicht falsch liegen. Denn früher oder später benötigt man jeden Widerstandswert der E12-Reihe einmal.&lt;br /&gt;
&lt;br /&gt;
Für einen Einstieg eignen sich die Sortimente vom Pollin. Auch ein Blick in Ebay kann sich lohnen um ein Einstiegssortiment zu bekommen.&lt;br /&gt;
&lt;br /&gt;
=== Kondensatoren ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| 100nF Keramik&lt;br /&gt;
| ~0.05&lt;br /&gt;
| &lt;br /&gt;
| Als sogenannter Abblockkondensator zwischen VCC und GND vor allem bei Digital-ICs zwingend erforderlich, schadet aber auch bei den meisten Analog-ICs nicht.&lt;br /&gt;
| &lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
| 100nF Keramik SMD 0603&lt;br /&gt;
| ~0.01 (bei 100 Stück)&lt;br /&gt;
| SMD 0603&lt;br /&gt;
| Als sogenannter Abblockkondensator zwischen VCC und GND vor allem bei Digital-ICs zwingend erforderlich, schadet aber auch bei den meisten Analog-ICs nicht.&lt;br /&gt;
| D&lt;br /&gt;
| [http://www.google.de/search?num=100&amp;amp;hl=de&amp;amp;q=datasheet+0603+chip-capacitors+filetype%3Apdf&amp;amp;btnG=Suche&amp;amp;meta=lr%3Dlang_de%7Clang_en PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Lieferanten =&lt;br /&gt;
&lt;br /&gt;
Allgemeine Lieferantenliste: [http://www.mikrocontroller.net/articles/Elektronik-Versender Elektronik-Versender]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Kürzel&lt;br /&gt;
! Name&lt;br /&gt;
! Webseite&lt;br /&gt;
! Kommentar&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;b&amp;gt;B&amp;lt;/b&amp;gt;&lt;br /&gt;
|Bürklin&lt;br /&gt;
|[http://www.buerklin.de www.buerklin.de]&lt;br /&gt;
|Versand nur Firmen &amp;amp; Studenten, Ladengeschäft in München und Düsseldorf&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;b&amp;gt;C&amp;lt;/b&amp;gt;&lt;br /&gt;
|Conrad&lt;br /&gt;
|[http://www.conrad.de www.conrad.de]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;b&amp;gt;D&amp;lt;/b&amp;gt;&lt;br /&gt;
|CSD-Electronics&lt;br /&gt;
|[http://www.csd-electronics.de www.csd-electronics.de]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;b&amp;gt;F&amp;lt;/b&amp;gt;&lt;br /&gt;
|Farnell&lt;br /&gt;
|[http://www.farnell.de www.farnell.de]&lt;br /&gt;
|Versand nur Firmen &amp;amp; Studenten&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;b&amp;gt;M&amp;lt;/b&amp;gt;&lt;br /&gt;
|Meilhaus&lt;br /&gt;
|[http://www.meilhaus.de www.meilhaus.de]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;b&amp;gt;P&amp;lt;/b&amp;gt;&lt;br /&gt;
|Pollin&lt;br /&gt;
|[http://www.pollin.de www.pollin.de]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;b&amp;gt;R&amp;lt;/b&amp;gt;&lt;br /&gt;
|Reichelt&lt;br /&gt;
|[http://www.reichelt.de www.reichelt.de]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Bauteile]]&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Standardbauelemente&amp;diff=21573</id>
		<title>Standardbauelemente</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Standardbauelemente&amp;diff=21573"/>
		<updated>2007-05-14T12:31:59Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: /* Digital */ Menüpunkt Speicher dazugefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Gerade Neulinge kennen das Problem: Man hat eine tolle Schaltung mit vielen Operationsverstärkern, Spannungsreglern, Logikbausteinen, ADCs, was auch immer entwickelt und jetzt geht&#039;s an die Realisierung.&lt;br /&gt;
&lt;br /&gt;
Aber welche Bausteine nehmen unter dem Wust der Angebote? Also erstmal auf die Seiten der Hersteller und die Produktpalette durchforsten. Nach einigen Stunden gewissenhafter Recherche hat man dann endlich alle Bauteile beisammen und will bestellen. Und dann kommt das böse Erwachen: Einige Bauelemente gibt&#039;s nur bei Reichelt, andere nur bei Conrad. Farnell hat zwar das meiste, aber da kann man als Privatperson leider nicht bestellen. Manche ICs bekommt man nur in 1000er Stückzahlen oder sind halt einfach nur viel zu teuer.&lt;br /&gt;
&lt;br /&gt;
Nach einigen Jahren praktischer Erfahrung hat man dann seine &amp;quot;Standardbauelemente&amp;quot;, die man immer wieder verwendet. Dieser Artikel soll helfen andere von dieser Erfahrung profitieren zu lassen. Ähnliche Anregungen findet man auch in der de.sci.electronics-FAQ: Grundausstattung des Bastlers [[http://dse-faq.elektronik-kompendium.de/dse-faq.htm#F.2]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= !Hinweise! =&lt;br /&gt;
Hier soll eine Liste von häufig anzutreffenden, preiswerten und verfügbaren Standardbauelementen entstehen. Diese Liste soll knapp und bündig sein, für technische Daten wird auf die Datenblätter verwiesen. Hier gilt: &amp;quot;weniger ist mehr&amp;quot;, exotische Bauelemente sind also unerwünscht. Für hier gelistete Typen sollte gelten:&lt;br /&gt;
* für Privatpersonen verfügbar&lt;br /&gt;
* preiswert (nicht billig)&lt;br /&gt;
&lt;br /&gt;
Nicht gelistet werden sollen:&lt;br /&gt;
* hunderte Typen, die alle den gleichen Zweck erfüllen, aber keinen Mehrwert bringen. Stattdessen auf die bekanntesten / preiswertesten beschränken.&lt;br /&gt;
* Details. Stattdessen die Felder &amp;quot;Besonderheiten&amp;quot; und &amp;quot;Anwendungen&amp;quot; benutzen, z.B. &amp;quot;I²C, 12bit&amp;quot; bei Besonderheiten für einen ADC oder &amp;quot;Präzision, Audio&amp;quot; bei Anwendungen für einen OpAmp.&lt;br /&gt;
&lt;br /&gt;
Wer eine Sparte, oder eine Anwendung vermisst, aber selber nichts dazu beitragen kann: Einfach hinzufügen. Wer z.B. einen HF OpAmp sucht und hier nicht fündig wird sollte also eine neue Zeile einfügen und in die Spalte Anwendungen &amp;quot;HF&amp;quot; eintragen. Villeicht kann ja jemand den Rest der Zeile füllen.&lt;br /&gt;
&lt;br /&gt;
Immer den Grundtypen listen und nicht eine der Varianten, und schon gar nicht alle Varianten einzeln! Also z.B. &amp;quot;LM324&amp;quot; statt &amp;quot;LM324N&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Wenn möglich Direktlinks auf Datenblätter vermeiden und eine Suchmaschine befragen: &amp;quot;http://www.datasheetarchive.com/search.php?q=lm324&amp;quot;&lt;br /&gt;
* so werden alle Varianten gefunden&lt;br /&gt;
* und tote Links vermieden&lt;br /&gt;
&lt;br /&gt;
Die wichtigsten, allgemeinen Standard-Typen ganz oben in der Tabelle listen, danach erst die Spezialtypen für bestimmte Anwendungen.&lt;br /&gt;
&lt;br /&gt;
Und weil es mir so wichtig ist nochmal: Ich rufe geradezu dazu auf, überflüssige, unverfügbare Typen zu löschen!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Aktive Bauelemente =&lt;br /&gt;
== Analog ==&lt;br /&gt;
&lt;br /&gt;
=== Transistoren ===&lt;br /&gt;
NPN&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;transistors-npn&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| BC 337&lt;br /&gt;
| 0,04&lt;br /&gt;
| Standardtyp&lt;br /&gt;
| bis ~300mA sinnvoll&lt;br /&gt;
| R,D&lt;br /&gt;
| [http://www.google.de/search?num=100&amp;amp;hl=de&amp;amp;q=datasheet+bc337+filetype%3Apdf&amp;amp;btnG=Suche&amp;amp;meta=lr%3Dlang_de%7Clang_en PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BC 547/847&lt;br /&gt;
| 0,03&lt;br /&gt;
| Standardtyp, BC847 in SMD&lt;br /&gt;
| bis ~50mA sinnvoll&lt;br /&gt;
| R,D&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat_download/datasheets/BC847_BC547_SER_6.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BC 635/639&lt;br /&gt;
| 0,07&lt;br /&gt;
| andere Pinbelegung als BC547 (= BD135 in anderem Gehäuse)&lt;br /&gt;
| bis ~500mA sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat/datasheets/BC635_BCP54_BCX54_6.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BD 433/437&lt;br /&gt;
| 0,19&lt;br /&gt;
| niedrige Sättigungsspannung&lt;br /&gt;
| bis ~2A sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.fairchildsemi.com/ds/BD%2FBD435.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| TIP102&lt;br /&gt;
| 0,42&lt;br /&gt;
| Ptot bis 80W mit Kühlkörper, hohe Stromverstärkung von über 1000 über einen sehr großen Bereich.&lt;br /&gt;
| Grenzwert 8A&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.fairchildsemi.com/ds/TI%2FTIP102.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| TIP 3055&lt;br /&gt;
| 0,75&lt;br /&gt;
| Ptot bis 90W mit Kühlkörper, Stromverstärkung sehr niedrig (bei großen Strömen &amp;lt;&amp;lt; 100)&lt;br /&gt;
| Grenzwert 15A &lt;br /&gt;
| R&lt;br /&gt;
| [http://www.ortodoxism.ro/datasheets/PowerInnovations/mXvutwr.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
PNP&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;transistors-pnp&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| BC 327&lt;br /&gt;
| 0,04&lt;br /&gt;
| Komplementärtyp zu BC337&lt;br /&gt;
| bis ~300mA sinnvoll&lt;br /&gt;
| R,D&lt;br /&gt;
| [http://www.google.de/search?num=100&amp;amp;hl=de&amp;amp;q=datasheet+bc327+filetype%3Apdf&amp;amp;btnG=Suche&amp;amp;meta=lr%3Dlang_de%7Clang_en PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BC 557&lt;br /&gt;
| 0,03&lt;br /&gt;
| Komplementärtyp zu BC547C&lt;br /&gt;
| bis ~50mA sinnvoll&lt;br /&gt;
| R,D&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat_download/datasheets/BC556_557_4.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BC 636/640&lt;br /&gt;
| 0,07&lt;br /&gt;
| Komplementärtyp zu BC635&lt;br /&gt;
| bis ~500mA sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat/datasheets/BC640_BCP53_BCX53_6.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| TIP 2955&lt;br /&gt;
| 0,75&lt;br /&gt;
| Ptot bis 90W mit Kühlkörper&lt;br /&gt;
| Grenzwert 15A&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.ortodoxism.ro/datasheets/motorola/TIP2955.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eigene Seite für MOSFETs: [[Mosfet-Übersicht]]&lt;br /&gt;
&lt;br /&gt;
N-MOSFET&lt;br /&gt;
&lt;br /&gt;
BUZ10, BUZ11 etc. sind wie alle BUZ Typen ziemlich veraltet. Bitte nicht listen; es gibt fast immer was besseres von IRF.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;mosfet-n&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| IRF1010N&lt;br /&gt;
| 0,87&lt;br /&gt;
| max 50V, max 85A, 11 mOhm On-Widerstand&lt;br /&gt;
| Alles, was mit POWER zu tun hat ...&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.irf.com/product-info/datasheets/data/irf1010n.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| IRLZ34N&lt;br /&gt;
| 0,42&lt;br /&gt;
| max 55V, max 30A, 35 mOhm On-Widerstand&lt;br /&gt;
| Gatespannung kompatibel mit 5V-Controllern.&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.irf.com/product-info/datasheets/data/irlz34n.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BS170&lt;br /&gt;
| 0,13&lt;br /&gt;
| max 60V, bis 500mA, 5 Ohm On-Widerstand&lt;br /&gt;
| veraltete Technik aber in bastelfreundlichem TO-92 Gehäuse von R lieferbar &lt;br /&gt;
| R&lt;br /&gt;
| [http://www.fairchildsemi.com/ds/BS/BS170.pdf PDF] (Fairchild)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
P-MOSFET&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;mosfet-p&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| IRF7220&lt;br /&gt;
| 1,10&lt;br /&gt;
| max -14V, ca -10A (cont.), ca. 0,02 Ohm On-Widerstand&lt;br /&gt;
| Gehäuse SO-8, brauchbar in 3,3V Systemen&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.irf.com/product-info/datasheets/data/irf7220.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BS250&lt;br /&gt;
| 0,18&lt;br /&gt;
| max -45V, bis -230mA (cont.), 14 (und mehr) Ohm On-Widerstand&lt;br /&gt;
| veraltete Technik aber in bastelfreundlichem TO-92 Gehäuse von R lieferbar &lt;br /&gt;
| R&lt;br /&gt;
| [http://www.vishay.com/docs/70209/70209.pdf PDF] (Vishay)&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
MOSFET-Pärchen&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;mosfet-n-p&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| IRF7389&lt;br /&gt;
| 0,51&lt;br /&gt;
| 30 V, &amp;gt;2,5 A, 30/60 mOhm On-Widerstand&lt;br /&gt;
| Gehäuse SO-8&lt;br /&gt;
| D,R&lt;br /&gt;
| [http://www.irf.com/product-info/datasheets/data/irf7389.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dioden ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;mosfet-p&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| 1N4148&lt;br /&gt;
| 0,02&lt;br /&gt;
| Kleinsignal-Gleichrichterdiode&lt;br /&gt;
| &lt;br /&gt;
| R,D&lt;br /&gt;
| [http://www.fairchildsemi.com/ds/1N%2F1N4148.pdf D]&lt;br /&gt;
|-&lt;br /&gt;
| 1N4001..1N4007&lt;br /&gt;
| 0,02&lt;br /&gt;
| Mehrzweck-Gleichrichterdiode, 1N4001..1N4007 mit gestaffelter Sperrspannung&lt;br /&gt;
| 1A&lt;br /&gt;
| R,D&lt;br /&gt;
| [http://www.fairchildsemi.com/ds/1N/1N4001.pdf D]&lt;br /&gt;
|-&lt;br /&gt;
| 1N5400..1N5408&lt;br /&gt;
| 0,06&lt;br /&gt;
| Mehrzweck-Gleichrichterdiode, 1N5400..1N5408 mit gestaffelter Sperrspannung&lt;br /&gt;
| 3A, 50..1000V&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.ortodoxism.ro/datasheets/fairchild/1N5401.pdf D]&lt;br /&gt;
|-&lt;br /&gt;
| BAT46&lt;br /&gt;
| 0,10&lt;br /&gt;
| Kleinsignal-Schottky-Diode&lt;br /&gt;
|&lt;br /&gt;
| D,R&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| SB140&lt;br /&gt;
|&lt;br /&gt;
| Schottky-Diode&lt;br /&gt;
| 1A 40V&lt;br /&gt;
| R&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| BA159&lt;br /&gt;
| 0,051&lt;br /&gt;
| Standard-Diode&lt;br /&gt;
| HF 1A 1000V&lt;br /&gt;
| R&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| BAV99&lt;br /&gt;
| 0,041&lt;br /&gt;
| Standard-Doppeldiode, SOT-23&lt;br /&gt;
| ESD-Schutz&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.alldatasheet.com/view.jsp?Searchword=BAV99 D]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Instrumentenverstärker ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| INA128&lt;br /&gt;
| 6,15 (R)&lt;br /&gt;
| Verstärkung über 1 Widerstand einstellbar&lt;br /&gt;
| Brückenverstärker , Datenerfassung&lt;br /&gt;
| R,F&lt;br /&gt;
| [http://focus.ti.com/lit/ds/symlink/ina128.pdf#search=%22ina128%22 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| ??????&lt;br /&gt;
| &amp;lt; 2&lt;br /&gt;
| Standardtyp&lt;br /&gt;
| billig&lt;br /&gt;
| ??????&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=????? PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Operationsverstärker ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| LM358&lt;br /&gt;
| 0,09&lt;br /&gt;
| Single Supply&lt;br /&gt;
| 2-fach Standard-OP&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=lm358 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM324&lt;br /&gt;
| 0,13&lt;br /&gt;
| Single Supply&lt;br /&gt;
| 4-fach Standard-OP&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=lm324 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM393&lt;br /&gt;
| 0,10&lt;br /&gt;
| Single Supply&lt;br /&gt;
| 2-fach Standard-Komparator&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=lm393 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM339&lt;br /&gt;
| 0,10&lt;br /&gt;
| Single Supply&lt;br /&gt;
| 4-fach Standard-Komparator&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=lm339 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| NE5532&lt;br /&gt;
| 0,23&lt;br /&gt;
| 2 * Audio OP&lt;br /&gt;
| kann 600 Ohm treiben&lt;br /&gt;
| alle?&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=NE5532 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LMC6484&lt;br /&gt;
| 2,35&lt;br /&gt;
| R2R in/out&lt;br /&gt;
| 4-fach OP&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.national.com/ds.cgi/LM/LMC6484.pdf D]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Spannungsregler ===&lt;br /&gt;
Linearregler&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;linearregler&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| LP2950&lt;br /&gt;
| 0,39 - 0,53&lt;br /&gt;
| Festspannungsregler Low-Dropout&lt;br /&gt;
| 3 - 5V 100mA, TO-92&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LP2950 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM317&lt;br /&gt;
| 0,22&lt;br /&gt;
| Linearer einstellbarer Spannungsregler&lt;br /&gt;
| max 40V -&amp;gt; 1,2 - 37V, max 1.5A, TO220&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LM317 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| MAX663&lt;br /&gt;
| 1,80&lt;br /&gt;
| Linearer, einstellbarer Spannungsregler&lt;br /&gt;
| sehr niedriger Eigenstromverbrauch&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=MAX663 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM78xx&lt;br /&gt;
| &amp;lt;1,00&lt;br /&gt;
| Festspannungregeler (xx=05: 5V, xx=12: 12V ...)&lt;br /&gt;
| &lt;br /&gt;
| alle&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
Schaltregler&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;schaltregler&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| LM2576&lt;br /&gt;
| 1,60&lt;br /&gt;
| Step-Down&lt;br /&gt;
| max 40V -&amp;gt; 1,2 - 37V, max 3A, TO220-5&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LM2576 PDF] - [http://www.mikrocontroller.net/topic/58094#450561 mit Funk-Entstördrossel FED100µ (Reichelt...) bis 3 A]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Digital ==&lt;br /&gt;
=== CAN ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;can&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| MCP2515&lt;br /&gt;
| 1,95&lt;br /&gt;
| SPI-CAN 2.0B Baustein&lt;br /&gt;
| &lt;br /&gt;
| Reichelt&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
| SJA1000&lt;br /&gt;
| 4,55&lt;br /&gt;
| PellCAN 2.0B 1Mbit/s&lt;br /&gt;
|&lt;br /&gt;
| Reichelt&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Logik ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (€)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| 74HC4050&lt;br /&gt;
| 0,27&lt;br /&gt;
| z.B. 5V =&amp;gt; 3V&lt;br /&gt;
| Pegelwandler unidirektional abwärts&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=74hc4050 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| HEF4104B&lt;br /&gt;
| 0,77&lt;br /&gt;
| z.B. 5V =&amp;gt; 12V&lt;br /&gt;
| Pegelwandler unidirektional aufwärts&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=HEF4104B PDF]&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== USB ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;usb&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| FT232&lt;br /&gt;
| 5,65&lt;br /&gt;
| USB &amp;lt;-&amp;gt; RS232 Wandler&lt;br /&gt;
| Zugriff über virtuellen COM Port&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=ft232 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| FT245&lt;br /&gt;
| 6,35&lt;br /&gt;
| USB &amp;lt;-&amp;gt; Seriell Wandler mit paralleler Schnittstelle&lt;br /&gt;
| Zugriff über virtuellen COM Port&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=ft245 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Treiber ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| ULN2003A&lt;br /&gt;
| 0,17&lt;br /&gt;
| 7-fach Low-Side Treiber&lt;br /&gt;
| 50V/500mA&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=ULN2003 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| ULN2803A&lt;br /&gt;
| 0,44&lt;br /&gt;
| 8-fach Low-Side Treiber&lt;br /&gt;
| 50V/500mA&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=ULN2803 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| UDN2981&lt;br /&gt;
| 1,50&lt;br /&gt;
| 8-fach High-Side Treiber&lt;br /&gt;
| 50V/500mA&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=UDN2981 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| ICL7667&lt;br /&gt;
| 1&lt;br /&gt;
| Dual inverting FET Treiber&lt;br /&gt;
| 18V, 20ns@1nF&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=ICL7667 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Galvanische Trennelemente ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| CNY17&lt;br /&gt;
| 0,17&lt;br /&gt;
| Optisch, Standardtyp&lt;br /&gt;
| billig&lt;br /&gt;
| R,C&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=CNY17 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| 6N137&lt;br /&gt;
| 0,49&lt;br /&gt;
| Optisch, Logikausgang&lt;br /&gt;
| sehr schnell&lt;br /&gt;
| R,D&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=6N137 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| ADUM240*&lt;br /&gt;
| 10&lt;br /&gt;
| Induktiv, 3V/5V Logik&lt;br /&gt;
| extrem schnell, EN90650, 5kV&lt;br /&gt;
| F&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=adum240 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Displays ===&lt;br /&gt;
Bei den Textdisplays eignet sich praktisch jedes HD44780 konforme Display.&lt;br /&gt;
Praktisch jeder Elektronikversender hat eine Auswahl an verschiedenen Größen zu bieten. &lt;br /&gt;
Wer keinen besonderen Anspruch auf die Größe der Displays hat sollte sich bei Pollin und in Ebay umschauen.&lt;br /&gt;
&lt;br /&gt;
=== Speicher ===&lt;br /&gt;
&lt;br /&gt;
== Converter ==&lt;br /&gt;
=== ADC ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
=== DAC ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
== Sensoren (aktiv) ==&lt;br /&gt;
=== [[Temperatursensor|Temperatur]] ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| LM75&lt;br /&gt;
| ~2,10&lt;br /&gt;
| Temperatursensor mit I²C (TWI) Bus Interface (3.3V und 5V Version) (SMD)&lt;br /&gt;
| &lt;br /&gt;
| R D&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LM75 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| DS1621&lt;br /&gt;
| ~5&lt;br /&gt;
| Temperatursensor mit I²C (TWI) Bus Interface (wie LM75, kein SMD)&lt;br /&gt;
| &lt;br /&gt;
| C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| DS18B20&lt;br /&gt;
| 4,30&lt;br /&gt;
| Temperatursensor mit 1-Wire Interface&lt;br /&gt;
|&lt;br /&gt;
| R D&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=DS18B20 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM35&lt;br /&gt;
| 1,49&lt;br /&gt;
| Analoger Temperatursensor&lt;br /&gt;
| 10mV/°C absolut&lt;br /&gt;
| D&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LM35 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM335&lt;br /&gt;
| 0,87&lt;br /&gt;
| Analoger Temperatursensor&lt;br /&gt;
| 10mV/K absolut&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LM335 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
Wenn man z.B. einen Übertemperaturschutz (oder eine andere Schaltung, bei der es nur eine Schaltschwelle gibt) bauen will, dann empfiehlt sich die Verwendung eines NTCs. Dessen Kennlinie ist gegenüber den Kennlinien von z.B. LM335 dahingehend im Vorteil, dass eine geringe Temperaturänderung besser messbar ist.&lt;br /&gt;
&lt;br /&gt;
= Passive Bauelemente =&lt;br /&gt;
== Sensoren (passiv) ==&lt;br /&gt;
=== Licht ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
=== [[Temperatursensor|Temperatur]] ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| KTY81&lt;br /&gt;
| ~0,50&lt;br /&gt;
| nichtlinear, bis 150°C&lt;br /&gt;
| in &amp;amp;#956;C Schaltungen&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat/datasheets/KTY84_SERIES_5.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| KTY84&lt;br /&gt;
| 0,72&lt;br /&gt;
| nichtlinear, bis 300°C&lt;br /&gt;
| in &amp;amp;#956;C Schaltungen&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat/datasheets/KTY84_SERIES_5.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| PT100&lt;br /&gt;
| ab 3,00&lt;br /&gt;
| lineare Kennlinie&lt;br /&gt;
| analoge Messschaltungen&lt;br /&gt;
| F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Widerstände ===&lt;br /&gt;
Mit einem Widerstandssortiment, welches die E12-Werte enthält, kann man normalerweise nicht falsch liegen. Denn früher oder später benötigt man jeden Widerstandswert der E12-Reihe einmal.&lt;br /&gt;
&lt;br /&gt;
Für einen Einstieg eignen sich die Sortimente vom Pollin. Auch ein Blick in Ebay kann sich lohnen um ein Einstiegssortiment zu bekommen.&lt;br /&gt;
&lt;br /&gt;
=== Kondensatoren ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| 100nF Keramik&lt;br /&gt;
| ~0.05&lt;br /&gt;
| &lt;br /&gt;
| Als sogenannter Abblockkondensator zwischen VCC und GND vor allem bei Digital-ICs zwingend erforderlich, schadet aber auch bei den meisten Analog-ICs nicht.&lt;br /&gt;
| &lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
| 100nF Keramik SMD 0603&lt;br /&gt;
| ~0.01 (bei 100 Stück)&lt;br /&gt;
| SMD 0603&lt;br /&gt;
| Als sogenannter Abblockkondensator zwischen VCC und GND vor allem bei Digital-ICs zwingend erforderlich, schadet aber auch bei den meisten Analog-ICs nicht.&lt;br /&gt;
| D&lt;br /&gt;
| [http://www.google.de/search?num=100&amp;amp;hl=de&amp;amp;q=datasheet+0603+chip-capacitors+filetype%3Apdf&amp;amp;btnG=Suche&amp;amp;meta=lr%3Dlang_de%7Clang_en PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Lieferanten =&lt;br /&gt;
&lt;br /&gt;
Allgemeine Lieferantenliste: [http://www.mikrocontroller.net/articles/Elektronik-Versender Elektronik-Versender]&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Kürzel&lt;br /&gt;
! Name&lt;br /&gt;
! Webseite&lt;br /&gt;
! Kommentar&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;b&amp;gt;B&amp;lt;/b&amp;gt;&lt;br /&gt;
|Bürklin&lt;br /&gt;
|[http://www.buerklin.de www.buerklin.de]&lt;br /&gt;
|Versand nur Firmen &amp;amp; Studenten, Ladengeschäft in München und Düsseldorf&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;b&amp;gt;C&amp;lt;/b&amp;gt;&lt;br /&gt;
|Conrad&lt;br /&gt;
|[http://www.conrad.de www.conrad.de]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;b&amp;gt;D&amp;lt;/b&amp;gt;&lt;br /&gt;
|CSD-Electronics&lt;br /&gt;
|[http://www.csd-electronics.de www.csd-electronics.de]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;b&amp;gt;F&amp;lt;/b&amp;gt;&lt;br /&gt;
|Farnell&lt;br /&gt;
|[http://www.farnell.de www.farnell.de]&lt;br /&gt;
|Versand nur Firmen &amp;amp; Studenten&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;b&amp;gt;M&amp;lt;/b&amp;gt;&lt;br /&gt;
|Meilhaus&lt;br /&gt;
|[http://www.meilhaus.de www.meilhaus.de]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;b&amp;gt;P&amp;lt;/b&amp;gt;&lt;br /&gt;
|Pollin&lt;br /&gt;
|[http://www.pollin.de www.pollin.de]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;b&amp;gt;R&amp;lt;/b&amp;gt;&lt;br /&gt;
|Reichelt&lt;br /&gt;
|[http://www.reichelt.de www.reichelt.de]&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Bauteile]]&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Standardbauelemente&amp;diff=18986</id>
		<title>Standardbauelemente</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Standardbauelemente&amp;diff=18986"/>
		<updated>2007-01-04T11:36:51Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: /* Digital */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Gerade Neulinge kennen das Problem: Man hat eine tolle Schaltung mit vielen Operationsverstärkern, Spannungsreglern, Logikbausteinen, ADCs, was auch immer entwickelt und jetzt geht&#039;s an die Realisierung.&lt;br /&gt;
&lt;br /&gt;
Aber welche Bausteine nehmen unter dem Wust der Angebote? Also erstmal auf die Seiten der Hersteller und die Produktpalette durchforsten. Nach einigen Stunden gewissenhafter Recherche hat man dann endlich alle Bauteile beisammen und will bestellen. Und dann kommt das böse Erwachen: Einige Bauelemente gibt&#039;s nur bei Reichelt, andere nur bei Conrad. Farnell hat zwar das meiste, aber da kann man als Privatperson leider nicht bestellen. Manche ICs bekommt man nur in 1000er Stückzahlen oder sind halt einfach nur viel zu teuer.&lt;br /&gt;
&lt;br /&gt;
Nach einigen Jahren praktischer Erfahrung hat man dann seine &amp;quot;Standardbauelemente&amp;quot;, die man immer wieder verwendet. Dieser Artikel soll helfen andere von dieser Erfahrung profitieren zu lassen. Ähnliche Anregungen findet man auch in der de.sci.electronics-FAQ: Grundausstattung des Bastlers [[http://dse-faq.elektronik-kompendium.de/dse-faq.htm#F.2]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= !Hinweise! =&lt;br /&gt;
Hier soll eine Liste von häufig anzutreffenden, preiswerten und verfügbaren Standardbauelementen entstehen. Diese Liste soll knapp und bündig sein, für technische Daten wird auf die Datenblätter verwiesen. Hier gilt: &amp;quot;weniger ist mehr&amp;quot;, exotische Bauelemente sind also unerwünscht. Für hier gelistete Typen sollte gelten:&lt;br /&gt;
* für Privatpersonen verfügbar&lt;br /&gt;
* preiswert (nicht billig)&lt;br /&gt;
&lt;br /&gt;
Nicht gelistet werden sollen:&lt;br /&gt;
* hunderte Typen, die alle den gleichen Zweck erfüllen, aber keinen Mehrwert bringen. Stattdessen auf die bekanntesten / preiswertesten beschränken.&lt;br /&gt;
* Details. Stattdessen die Felder &amp;quot;Besonderheiten&amp;quot; und &amp;quot;Anwendungen&amp;quot; benutzen, z.B. &amp;quot;I²C, 12bit&amp;quot; bei Besonderheiten für einen ADC oder &amp;quot;Präzision, Audio&amp;quot; bei Anwendungen für einen OpAmp.&lt;br /&gt;
&lt;br /&gt;
Wer eine Sparte, oder eine Anwendung vermisst, aber selber nichts dazu beitragen kann: Einfach hinzufügen. Wer z.B. einen HF OpAmp sucht und hier nicht fündig wird sollte also eine neue Zeile einfügen und in die Spalte Anwendungen &amp;quot;HF&amp;quot; eintragen. Villeicht kann ja jemand den Rest der Zeile füllen.&lt;br /&gt;
&lt;br /&gt;
Immer den Grundtypen listen und nicht eine der Varianten, und schon gar nicht alle Varianten einzeln! Also z.B. &amp;quot;LM324&amp;quot; statt &amp;quot;LM324N&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Wenn möglich Direktlinks auf Datenblätter vermeiden und eine Suchmaschine befragen: &amp;quot;http://www.datasheetarchive.com/search.php?q=lm324&amp;quot;&lt;br /&gt;
* so werden alle Varianten gefunden&lt;br /&gt;
* und tote Links vermieden&lt;br /&gt;
&lt;br /&gt;
Die wichtigsten, allgemeinen Standard-Typen ganz oben in der Tabelle listen, danach erst die Spezialtypen für bestimmte Anwendungen.&lt;br /&gt;
&lt;br /&gt;
Und weil es mir so wichtig ist nochmal: Ich rufe geradezu dazu auf, überflüssige, unverfügbare Typen zu löschen!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Aktive Bauelemente =&lt;br /&gt;
== Analog ==&lt;br /&gt;
&lt;br /&gt;
=== Transistoren ===&lt;br /&gt;
NPN&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;transistors-npn&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| BC 337&lt;br /&gt;
| 0,04&lt;br /&gt;
| Standardtyp&lt;br /&gt;
| bis ~300mA sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.google.de/search?num=100&amp;amp;hl=de&amp;amp;q=datasheet+bc337+filetype%3Apdf&amp;amp;btnG=Suche&amp;amp;meta=lr%3Dlang_de%7Clang_en PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BC 547/847&lt;br /&gt;
| 0,03&lt;br /&gt;
| Standardtyp, BC847 in SMD&lt;br /&gt;
| bis ~50mA sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat_download/datasheets/BC847_BC547_SER_6.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BC 635/639&lt;br /&gt;
| 0,07&lt;br /&gt;
| andere Pinbelegung als BC547 (= BD135 in anderem Gehäuse)&lt;br /&gt;
| bis ~500mA sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat/datasheets/BC635_BCP54_BCX54_6.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BD 433/437&lt;br /&gt;
| 0,19&lt;br /&gt;
| niedrige Sättigungsspannung&lt;br /&gt;
| bis ~2A sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.fairchildsemi.com/ds/BD%2FBD435.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| TIP102&lt;br /&gt;
| 0,42&lt;br /&gt;
| Ptot bis 80W mit Kühlkörper, hohe Stromverstärkung von über 1000 über einen sehr großen Bereich.&lt;br /&gt;
| Grenzwert 8A&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.fairchildsemi.com/ds/TI%2FTIP102.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| TIP 3055&lt;br /&gt;
| 0,75&lt;br /&gt;
| Ptot bis 90W mit Kühlkörper, Stromverstärkung sehr niedrig (bei großen Strömen &amp;lt;&amp;lt; 100)&lt;br /&gt;
| Grenzwert 15A &lt;br /&gt;
| R&lt;br /&gt;
| [http://www.ortodoxism.ro/datasheets/PowerInnovations/mXvutwr.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
PNP&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;transistors-pnp&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| BC 327&lt;br /&gt;
| 0,04&lt;br /&gt;
| Komplementärtyp zu BC337&lt;br /&gt;
| bis ~300mA sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.google.de/search?num=100&amp;amp;hl=de&amp;amp;q=datasheet+bc327+filetype%3Apdf&amp;amp;btnG=Suche&amp;amp;meta=lr%3Dlang_de%7Clang_en PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BC 557C&lt;br /&gt;
| 0,03&lt;br /&gt;
| Komplementärtyp zu BC547C&lt;br /&gt;
| bis ~50mA sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat_download/datasheets/BC556_557_4.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BC 636/640&lt;br /&gt;
| 0,07&lt;br /&gt;
| Komplementärtyp zu BC635&lt;br /&gt;
| bis ~500mA sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat/datasheets/BC640_BCP53_BCX53_6.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| TIP 2955&lt;br /&gt;
| 0,75&lt;br /&gt;
| Ptot bis 90W mit Kühlkörper&lt;br /&gt;
| Grenzwert 15A&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.ortodoxism.ro/datasheets/motorola/TIP2955.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eigene Seite für MOSFETs: [[Mosfet-Übersicht]]&lt;br /&gt;
&lt;br /&gt;
N-MOSFET&lt;br /&gt;
&lt;br /&gt;
BUZ10, BUZ11 etc. sind wie alle BUZ Typen ziemlich veraltet. Bitte nicht listen; es gibt fast immer was besseres von IRF.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;mosfet-n&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| IRF1010N&lt;br /&gt;
| 0,87&lt;br /&gt;
| max 50V, max 85A, 11 mOhm On-Widerstand&lt;br /&gt;
| Alles, was mit POWER zu tun hat ...&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.irf.com/product-info/datasheets/data/irf1010n.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| IRLZ34N&lt;br /&gt;
| 0,42&lt;br /&gt;
| max 55V, max 30A, 35 mOhm On-Widerstand&lt;br /&gt;
| Gatespannung kompatibel mit 5V-Controllern.&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.irf.com/product-info/datasheets/data/irlz34n.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BS170&lt;br /&gt;
| 0,13&lt;br /&gt;
| max 60V, bis 500mA, 5 Ohm On-Widerstand&lt;br /&gt;
| veraltete Technik aber in bastelfreundlichem TO-92 Gehäuse von R lieferbar &lt;br /&gt;
| R&lt;br /&gt;
| [http://www.fairchildsemi.com/ds/BS/BS170.pdf PDF] (Fairchild)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
P-MOSFET&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;mosfet-p&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| IRF7220&lt;br /&gt;
| 1,10&lt;br /&gt;
| max -14V, ca -10A (cont.), ca. 0,02 Ohm On-Widerstand&lt;br /&gt;
| Gehäuse SO-8, brauchbar in 3,3V Systemen&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.irf.com/product-info/datasheets/data/irf7220.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BS250&lt;br /&gt;
| 0,18&lt;br /&gt;
| max -45V, bis -230mA (cont.), 14 (und mehr) Ohm On-Widerstand&lt;br /&gt;
| veraltete Technik aber in bastelfreundlichem TO-92 Gehäuse von R lieferbar &lt;br /&gt;
| R&lt;br /&gt;
| [http://www.vishay.com/docs/70209/70209.pdf PDF] (Vishay)&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
MOSFET-Pärchen&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;mosfet-n-p&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| IRF7389&lt;br /&gt;
| 0,56&lt;br /&gt;
| 30 V, &amp;gt;2,5 A, 30/60 mOhm On-Widerstand&lt;br /&gt;
| Gehäuse SO-8&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.irf.com/product-info/datasheets/data/irf7389.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dioden ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;mosfet-p&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| 1N4148&lt;br /&gt;
| 0,02&lt;br /&gt;
| Kleinsignal-Gleichrichterdiode&lt;br /&gt;
| &lt;br /&gt;
| R&lt;br /&gt;
| [http://www.fairchildsemi.com/ds/1N%2F1N4148.pdf D]&lt;br /&gt;
|-&lt;br /&gt;
| 1N4001..1N4007&lt;br /&gt;
| 0,02&lt;br /&gt;
| Mehrzweck-Gleichrichterdiode, 1N4001..1N4007 mit gestaffelter Sperrspannung&lt;br /&gt;
| &lt;br /&gt;
| R&lt;br /&gt;
| [http://www.fairchildsemi.com/ds/1N/1N4001.pdf D]&lt;br /&gt;
|-&lt;br /&gt;
| BAT46&lt;br /&gt;
| 0,11&lt;br /&gt;
| Kleinsignal-Schottky-Diode&lt;br /&gt;
|&lt;br /&gt;
| R&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| SB140&lt;br /&gt;
|&lt;br /&gt;
| Schottky-Diode&lt;br /&gt;
| 1A 40V&lt;br /&gt;
| R&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| BA159&lt;br /&gt;
| 0,051&lt;br /&gt;
| Standard-Diode&lt;br /&gt;
| HF 1A 1000V&lt;br /&gt;
| R&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Instrumentenverstärker ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| INA128&lt;br /&gt;
| 6,15 (R)&lt;br /&gt;
| Verstärkung über 1 Widerstand einstellbar&lt;br /&gt;
| Brückenverstärker , Datenerfassung&lt;br /&gt;
| R,F&lt;br /&gt;
| [http://focus.ti.com/lit/ds/symlink/ina128.pdf#search=%22ina128%22 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Operationsverstärker ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| LM358&lt;br /&gt;
| 0,09&lt;br /&gt;
| Single Supply&lt;br /&gt;
| 2-fach Standard-OP&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=lm358 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM324&lt;br /&gt;
| 0,13&lt;br /&gt;
| Single Supply&lt;br /&gt;
| 4-fach Standard-OP&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=lm324 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM393&lt;br /&gt;
| 0,10&lt;br /&gt;
| Single Supply&lt;br /&gt;
| 2-fach Standard-Komparator&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=lm393 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM339&lt;br /&gt;
| 0,10&lt;br /&gt;
| Single Supply&lt;br /&gt;
| 4-fach Standard-Komparator&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=lm339 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| NE5532&lt;br /&gt;
| 0,23&lt;br /&gt;
| 2 * Audio OP&lt;br /&gt;
| kann 600 Ohm treiben&lt;br /&gt;
| alle?&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=NE5532 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Spannungsregler ===&lt;br /&gt;
Linearregler&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;linearregler&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| LP2950&lt;br /&gt;
| 0,39 - 0,53&lt;br /&gt;
| Festspannungsregler Low-Dropout&lt;br /&gt;
| 3 - 5V 100mA, TO-92&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LP2950 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM317&lt;br /&gt;
| 0,22&lt;br /&gt;
| Linearer einstellbarer Spannungsregler&lt;br /&gt;
| max 40V -&amp;gt; 1,2 - 37V, max 1.5A, TO220&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LM317 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| MAX663&lt;br /&gt;
| 1,80&lt;br /&gt;
| Linearer, einstellbarer Spannungsregler&lt;br /&gt;
| sehr niedriger Eigenstromverbrauch&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=MAX663 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
Schaltregler&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;schaltregler&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| LM2576&lt;br /&gt;
| 1,60&lt;br /&gt;
| Step-Down&lt;br /&gt;
| max 40V -&amp;gt; 1,2 - 37V, max 3A, TO220-5&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LM2576 PDF] - [http://www.mikrocontroller.net/topic/58094#450561 mit Funk-Entstördrossel FED100µ (Reichelt...) bis 3 A]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Digital ==&lt;br /&gt;
=== CAN ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;can&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| MCP2515&lt;br /&gt;
| 1,95&lt;br /&gt;
| SPI-CAN 2.0B Baustein&lt;br /&gt;
| &lt;br /&gt;
| Reichelt&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
| SJA1000&lt;br /&gt;
| 4,55&lt;br /&gt;
| PellCAN 2.0B 1Mbit/s&lt;br /&gt;
|&lt;br /&gt;
| Reichelt&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Logik ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| 74HC4050&lt;br /&gt;
| 0,27&lt;br /&gt;
| z.B. 5V =&amp;gt; 3V&lt;br /&gt;
| Pegelwandler unidirektional abwärts&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=74hc4050 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== USB ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;usb&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| FT232&lt;br /&gt;
| 5,65&lt;br /&gt;
| USB &amp;lt;-&amp;gt; RS232 Wandler&lt;br /&gt;
| Zugriff über virtuellen COM Port&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=ft232 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| FT245&lt;br /&gt;
| 6,35&lt;br /&gt;
| USB &amp;lt;-&amp;gt; Seriell Wandler mit paralleler Schnittstelle&lt;br /&gt;
| Zugriff über virtuellen COM Port&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=ft245 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Treiber ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| ULN2003A&lt;br /&gt;
| 0,17&lt;br /&gt;
| 7-fach Low-Side Treiber&lt;br /&gt;
| 50V/500mA&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=ULN2003 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| ULN2803A&lt;br /&gt;
| 0,44&lt;br /&gt;
| 8-fach Low-Side Treiber&lt;br /&gt;
| 50V/500mA&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=ULN2803 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| UDN2981&lt;br /&gt;
| 1,50&lt;br /&gt;
| 8-fach High-Side Treiber&lt;br /&gt;
| 50V/500mA&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=UDN2981 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| ICL7667&lt;br /&gt;
| 1&lt;br /&gt;
| Dual inverting FET Treiber&lt;br /&gt;
| 18V, 20ns@1nF&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=ICL7667 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Optokoppler ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| CNY17&lt;br /&gt;
| 0,17&lt;br /&gt;
| billig&lt;br /&gt;
| Standardtyp&lt;br /&gt;
| R,C&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=CNY17 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| 6N137&lt;br /&gt;
| 0,49&lt;br /&gt;
| Logikausgang&lt;br /&gt;
| sehr schnell&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=6N137 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
=== Displays ===&lt;br /&gt;
Bei den Textdisplays eignet sich praktisch jedes HD44780 konforme Display.&lt;br /&gt;
Praktisch jeder Elektronikversender hat eine Auswahl an verschiedenen Größen zu bieten. &lt;br /&gt;
Wer keinen besonderen Anspruch auf die Größe der Displays hat sollte sich bei Pollin und in Ebay umschauen.&lt;br /&gt;
&lt;br /&gt;
== Converter ==&lt;br /&gt;
=== ADC ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
=== DAC ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
== Sensoren (aktiv) ==&lt;br /&gt;
=== [[Temperatursensor|Temperatur]] ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| LM75&lt;br /&gt;
| ~2,10&lt;br /&gt;
| Temperatursensor mit I²C (TWI) Bus Interface (3.3V und 5V Version) (SMD)&lt;br /&gt;
| &lt;br /&gt;
| R D&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LM75 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| DS1621&lt;br /&gt;
| ~5&lt;br /&gt;
| Temperatursensor mit I²C (TWI) Bus Interface (wie LM75, kein SMD)&lt;br /&gt;
| &lt;br /&gt;
| C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| DS18B20&lt;br /&gt;
| 4,30&lt;br /&gt;
| Temperatursensor mit 1-Wire Interface&lt;br /&gt;
|&lt;br /&gt;
| R D&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=DS18B20 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM35&lt;br /&gt;
| 1,49&lt;br /&gt;
| Analoger Temperatursensor&lt;br /&gt;
| 10mV/°C absolut&lt;br /&gt;
| D&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LM35 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM335&lt;br /&gt;
| 0,87&lt;br /&gt;
| Analoger Temperatursensor&lt;br /&gt;
| 10mV/K absolut&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LM335 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
Wenn man z.B. einen Übertemperaturschutz (oder eine andere Schaltung, bei der es nur eine Schaltschwelle gibt) bauen will, dann empfiehlt sich die Verwendung eines NTCs. Dessen Kennlinie ist gegenüber den Kennlinien von z.B. LM335 dahingehend im Vorteil, dass eine geringe Temperaturänderung besser messbar ist.&lt;br /&gt;
&lt;br /&gt;
= Passive Bauelemente =&lt;br /&gt;
== Sensoren (passiv) ==&lt;br /&gt;
=== Licht ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
=== [[Temperatursensor|Temperatur]] ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| KTY81&lt;br /&gt;
| ~0,50&lt;br /&gt;
| nichtlinear, bis 150°C&lt;br /&gt;
| in &amp;amp;#956;C Schaltungen&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat/datasheets/KTY84_SERIES_5.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| KTY84&lt;br /&gt;
| 0,72&lt;br /&gt;
| nichtlinear, bis 300°C&lt;br /&gt;
| in &amp;amp;#956;C Schaltungen&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat/datasheets/KTY84_SERIES_5.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| PT100&lt;br /&gt;
| ab 3,00&lt;br /&gt;
| lineare Kennlinie&lt;br /&gt;
| analoge Messschaltungen&lt;br /&gt;
| F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Widerstände ===&lt;br /&gt;
Mit einem Widerstandssortiment, welches die E12-Werte enthält, kann man normalerweise nicht falsch liegen. Denn früher oder später benötigt man jeden Widerstandswert der E12-Reihe einmal.&lt;br /&gt;
&lt;br /&gt;
Für einen Einstieg eignen sich die Sortimente vom Pollin. Auch ein Blick in Ebay kann sich lohnen um ein Einstiegssortiment zu bekommen.&lt;br /&gt;
&lt;br /&gt;
=== Kondensatoren ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| 100nF Keramik&lt;br /&gt;
| ~0.05&lt;br /&gt;
| &lt;br /&gt;
| Als sogenannter Abblockkondensator zwischen VCC und GND vor allem bei Digital-ICs zwingend erforderlich, schadet aber auch bei den meisten Analog-ICs nicht.&lt;br /&gt;
| &lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
| 100nF Keramik SMD 0603&lt;br /&gt;
| ~0.01 (bei 100 Stück)&lt;br /&gt;
| SMD 0603&lt;br /&gt;
| Als sogenannter Abblockkondensator zwischen VCC und GND vor allem bei Digital-ICs zwingend erforderlich, schadet aber auch bei den meisten Analog-ICs nicht.&lt;br /&gt;
| D&lt;br /&gt;
| [http://www.google.de/search?num=100&amp;amp;hl=de&amp;amp;q=datasheet+0603+chip-capacitors+filetype%3Apdf&amp;amp;btnG=Suche&amp;amp;meta=lr%3Dlang_de%7Clang_en PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Lieferanten =&lt;br /&gt;
C: Conrad [http://www.conrad.de www.conrad.de]&lt;br /&gt;
&lt;br /&gt;
D: CSD-Electronics [http://www.csd-electronics.de www.csd-electronics.de] &lt;br /&gt;
&lt;br /&gt;
F: Farnell (nur Firmen &amp;amp; Studenten) [http://www.farnell.de www.farnell.de]&lt;br /&gt;
&lt;br /&gt;
P: Pollin [http://www.pollin.de www.pollin.de]&lt;br /&gt;
&lt;br /&gt;
R: Reichelt [http://www.reichelt.de www.reichelt.de]&lt;br /&gt;
&lt;br /&gt;
Allgemeine Lieferantenliste: [http://www.mikrocontroller.net/articles/Elektronik-Versender Elektronik-Versender]&lt;br /&gt;
&lt;br /&gt;
[[Category:Bauteile]]&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Standardbauelemente&amp;diff=18985</id>
		<title>Standardbauelemente</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Standardbauelemente&amp;diff=18985"/>
		<updated>2007-01-04T11:33:21Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: /* Widerstände */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Gerade Neulinge kennen das Problem: Man hat eine tolle Schaltung mit vielen Operationsverstärkern, Spannungsreglern, Logikbausteinen, ADCs, was auch immer entwickelt und jetzt geht&#039;s an die Realisierung.&lt;br /&gt;
&lt;br /&gt;
Aber welche Bausteine nehmen unter dem Wust der Angebote? Also erstmal auf die Seiten der Hersteller und die Produktpalette durchforsten. Nach einigen Stunden gewissenhafter Recherche hat man dann endlich alle Bauteile beisammen und will bestellen. Und dann kommt das böse Erwachen: Einige Bauelemente gibt&#039;s nur bei Reichelt, andere nur bei Conrad. Farnell hat zwar das meiste, aber da kann man als Privatperson leider nicht bestellen. Manche ICs bekommt man nur in 1000er Stückzahlen oder sind halt einfach nur viel zu teuer.&lt;br /&gt;
&lt;br /&gt;
Nach einigen Jahren praktischer Erfahrung hat man dann seine &amp;quot;Standardbauelemente&amp;quot;, die man immer wieder verwendet. Dieser Artikel soll helfen andere von dieser Erfahrung profitieren zu lassen. Ähnliche Anregungen findet man auch in der de.sci.electronics-FAQ: Grundausstattung des Bastlers [[http://dse-faq.elektronik-kompendium.de/dse-faq.htm#F.2]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= !Hinweise! =&lt;br /&gt;
Hier soll eine Liste von häufig anzutreffenden, preiswerten und verfügbaren Standardbauelementen entstehen. Diese Liste soll knapp und bündig sein, für technische Daten wird auf die Datenblätter verwiesen. Hier gilt: &amp;quot;weniger ist mehr&amp;quot;, exotische Bauelemente sind also unerwünscht. Für hier gelistete Typen sollte gelten:&lt;br /&gt;
* für Privatpersonen verfügbar&lt;br /&gt;
* preiswert (nicht billig)&lt;br /&gt;
&lt;br /&gt;
Nicht gelistet werden sollen:&lt;br /&gt;
* hunderte Typen, die alle den gleichen Zweck erfüllen, aber keinen Mehrwert bringen. Stattdessen auf die bekanntesten / preiswertesten beschränken.&lt;br /&gt;
* Details. Stattdessen die Felder &amp;quot;Besonderheiten&amp;quot; und &amp;quot;Anwendungen&amp;quot; benutzen, z.B. &amp;quot;I²C, 12bit&amp;quot; bei Besonderheiten für einen ADC oder &amp;quot;Präzision, Audio&amp;quot; bei Anwendungen für einen OpAmp.&lt;br /&gt;
&lt;br /&gt;
Wer eine Sparte, oder eine Anwendung vermisst, aber selber nichts dazu beitragen kann: Einfach hinzufügen. Wer z.B. einen HF OpAmp sucht und hier nicht fündig wird sollte also eine neue Zeile einfügen und in die Spalte Anwendungen &amp;quot;HF&amp;quot; eintragen. Villeicht kann ja jemand den Rest der Zeile füllen.&lt;br /&gt;
&lt;br /&gt;
Immer den Grundtypen listen und nicht eine der Varianten, und schon gar nicht alle Varianten einzeln! Also z.B. &amp;quot;LM324&amp;quot; statt &amp;quot;LM324N&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Wenn möglich Direktlinks auf Datenblätter vermeiden und eine Suchmaschine befragen: &amp;quot;http://www.datasheetarchive.com/search.php?q=lm324&amp;quot;&lt;br /&gt;
* so werden alle Varianten gefunden&lt;br /&gt;
* und tote Links vermieden&lt;br /&gt;
&lt;br /&gt;
Die wichtigsten, allgemeinen Standard-Typen ganz oben in der Tabelle listen, danach erst die Spezialtypen für bestimmte Anwendungen.&lt;br /&gt;
&lt;br /&gt;
Und weil es mir so wichtig ist nochmal: Ich rufe geradezu dazu auf, überflüssige, unverfügbare Typen zu löschen!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Aktive Bauelemente =&lt;br /&gt;
== Analog ==&lt;br /&gt;
&lt;br /&gt;
=== Transistoren ===&lt;br /&gt;
NPN&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;transistors-npn&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| BC 337&lt;br /&gt;
| 0,04&lt;br /&gt;
| Standardtyp&lt;br /&gt;
| bis ~300mA sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.google.de/search?num=100&amp;amp;hl=de&amp;amp;q=datasheet+bc337+filetype%3Apdf&amp;amp;btnG=Suche&amp;amp;meta=lr%3Dlang_de%7Clang_en PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BC 547/847&lt;br /&gt;
| 0,03&lt;br /&gt;
| Standardtyp, BC847 in SMD&lt;br /&gt;
| bis ~50mA sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat_download/datasheets/BC847_BC547_SER_6.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BC 635/639&lt;br /&gt;
| 0,07&lt;br /&gt;
| andere Pinbelegung als BC547 (= BD135 in anderem Gehäuse)&lt;br /&gt;
| bis ~500mA sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat/datasheets/BC635_BCP54_BCX54_6.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BD 433/437&lt;br /&gt;
| 0,19&lt;br /&gt;
| niedrige Sättigungsspannung&lt;br /&gt;
| bis ~2A sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.fairchildsemi.com/ds/BD%2FBD435.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| TIP102&lt;br /&gt;
| 0,42&lt;br /&gt;
| Ptot bis 80W mit Kühlkörper, hohe Stromverstärkung von über 1000 über einen sehr großen Bereich.&lt;br /&gt;
| Grenzwert 8A&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.fairchildsemi.com/ds/TI%2FTIP102.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| TIP 3055&lt;br /&gt;
| 0,75&lt;br /&gt;
| Ptot bis 90W mit Kühlkörper, Stromverstärkung sehr niedrig (bei großen Strömen &amp;lt;&amp;lt; 100)&lt;br /&gt;
| Grenzwert 15A &lt;br /&gt;
| R&lt;br /&gt;
| [http://www.ortodoxism.ro/datasheets/PowerInnovations/mXvutwr.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
PNP&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;transistors-pnp&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| BC 327&lt;br /&gt;
| 0,04&lt;br /&gt;
| Komplementärtyp zu BC337&lt;br /&gt;
| bis ~300mA sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.google.de/search?num=100&amp;amp;hl=de&amp;amp;q=datasheet+bc327+filetype%3Apdf&amp;amp;btnG=Suche&amp;amp;meta=lr%3Dlang_de%7Clang_en PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BC 557C&lt;br /&gt;
| 0,03&lt;br /&gt;
| Komplementärtyp zu BC547C&lt;br /&gt;
| bis ~50mA sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat_download/datasheets/BC556_557_4.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BC 636/640&lt;br /&gt;
| 0,07&lt;br /&gt;
| Komplementärtyp zu BC635&lt;br /&gt;
| bis ~500mA sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat/datasheets/BC640_BCP53_BCX53_6.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| TIP 2955&lt;br /&gt;
| 0,75&lt;br /&gt;
| Ptot bis 90W mit Kühlkörper&lt;br /&gt;
| Grenzwert 15A&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.ortodoxism.ro/datasheets/motorola/TIP2955.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eigene Seite für MOSFETs: [[Mosfet-Übersicht]]&lt;br /&gt;
&lt;br /&gt;
N-MOSFET&lt;br /&gt;
&lt;br /&gt;
BUZ10, BUZ11 etc. sind wie alle BUZ Typen ziemlich veraltet. Bitte nicht listen; es gibt fast immer was besseres von IRF.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;mosfet-n&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| IRF1010N&lt;br /&gt;
| 0,87&lt;br /&gt;
| max 50V, max 85A, 11 mOhm On-Widerstand&lt;br /&gt;
| Alles, was mit POWER zu tun hat ...&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.irf.com/product-info/datasheets/data/irf1010n.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| IRLZ34N&lt;br /&gt;
| 0,42&lt;br /&gt;
| max 55V, max 30A, 35 mOhm On-Widerstand&lt;br /&gt;
| Gatespannung kompatibel mit 5V-Controllern.&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.irf.com/product-info/datasheets/data/irlz34n.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BS170&lt;br /&gt;
| 0,13&lt;br /&gt;
| max 60V, bis 500mA, 5 Ohm On-Widerstand&lt;br /&gt;
| veraltete Technik aber in bastelfreundlichem TO-92 Gehäuse von R lieferbar &lt;br /&gt;
| R&lt;br /&gt;
| [http://www.fairchildsemi.com/ds/BS/BS170.pdf PDF] (Fairchild)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
P-MOSFET&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;mosfet-p&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| IRF7220&lt;br /&gt;
| 1,10&lt;br /&gt;
| max -14V, ca -10A (cont.), ca. 0,02 Ohm On-Widerstand&lt;br /&gt;
| Gehäuse SO-8, brauchbar in 3,3V Systemen&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.irf.com/product-info/datasheets/data/irf7220.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BS250&lt;br /&gt;
| 0,18&lt;br /&gt;
| max -45V, bis -230mA (cont.), 14 (und mehr) Ohm On-Widerstand&lt;br /&gt;
| veraltete Technik aber in bastelfreundlichem TO-92 Gehäuse von R lieferbar &lt;br /&gt;
| R&lt;br /&gt;
| [http://www.vishay.com/docs/70209/70209.pdf PDF] (Vishay)&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
MOSFET-Pärchen&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;mosfet-n-p&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| IRF7389&lt;br /&gt;
| 0,56&lt;br /&gt;
| 30 V, &amp;gt;2,5 A, 30/60 mOhm On-Widerstand&lt;br /&gt;
| Gehäuse SO-8&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.irf.com/product-info/datasheets/data/irf7389.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dioden ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;mosfet-p&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| 1N4148&lt;br /&gt;
| 0,02&lt;br /&gt;
| Kleinsignal-Gleichrichterdiode&lt;br /&gt;
| &lt;br /&gt;
| R&lt;br /&gt;
| [http://www.fairchildsemi.com/ds/1N%2F1N4148.pdf D]&lt;br /&gt;
|-&lt;br /&gt;
| 1N4001..1N4007&lt;br /&gt;
| 0,02&lt;br /&gt;
| Mehrzweck-Gleichrichterdiode, 1N4001..1N4007 mit gestaffelter Sperrspannung&lt;br /&gt;
| &lt;br /&gt;
| R&lt;br /&gt;
| [http://www.fairchildsemi.com/ds/1N/1N4001.pdf D]&lt;br /&gt;
|-&lt;br /&gt;
| BAT46&lt;br /&gt;
| 0,11&lt;br /&gt;
| Kleinsignal-Schottky-Diode&lt;br /&gt;
|&lt;br /&gt;
| R&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| SB140&lt;br /&gt;
|&lt;br /&gt;
| Schottky-Diode&lt;br /&gt;
| 1A 40V&lt;br /&gt;
| R&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| BA159&lt;br /&gt;
| 0,051&lt;br /&gt;
| Standard-Diode&lt;br /&gt;
| HF 1A 1000V&lt;br /&gt;
| R&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Instrumentenverstärker ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| INA128&lt;br /&gt;
| 6,15 (R)&lt;br /&gt;
| Verstärkung über 1 Widerstand einstellbar&lt;br /&gt;
| Brückenverstärker , Datenerfassung&lt;br /&gt;
| R,F&lt;br /&gt;
| [http://focus.ti.com/lit/ds/symlink/ina128.pdf#search=%22ina128%22 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Operationsverstärker ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| LM358&lt;br /&gt;
| 0,09&lt;br /&gt;
| Single Supply&lt;br /&gt;
| 2-fach Standard-OP&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=lm358 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM324&lt;br /&gt;
| 0,13&lt;br /&gt;
| Single Supply&lt;br /&gt;
| 4-fach Standard-OP&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=lm324 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM393&lt;br /&gt;
| 0,10&lt;br /&gt;
| Single Supply&lt;br /&gt;
| 2-fach Standard-Komparator&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=lm393 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM339&lt;br /&gt;
| 0,10&lt;br /&gt;
| Single Supply&lt;br /&gt;
| 4-fach Standard-Komparator&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=lm339 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| NE5532&lt;br /&gt;
| 0,23&lt;br /&gt;
| 2 * Audio OP&lt;br /&gt;
| kann 600 Ohm treiben&lt;br /&gt;
| alle?&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=NE5532 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Spannungsregler ===&lt;br /&gt;
Linearregler&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;linearregler&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| LP2950&lt;br /&gt;
| 0,39 - 0,53&lt;br /&gt;
| Festspannungsregler Low-Dropout&lt;br /&gt;
| 3 - 5V 100mA, TO-92&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LP2950 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM317&lt;br /&gt;
| 0,22&lt;br /&gt;
| Linearer einstellbarer Spannungsregler&lt;br /&gt;
| max 40V -&amp;gt; 1,2 - 37V, max 1.5A, TO220&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LM317 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| MAX663&lt;br /&gt;
| 1,80&lt;br /&gt;
| Linearer, einstellbarer Spannungsregler&lt;br /&gt;
| sehr niedriger Eigenstromverbrauch&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=MAX663 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
Schaltregler&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;schaltregler&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| LM2576&lt;br /&gt;
| 1,60&lt;br /&gt;
| Step-Down&lt;br /&gt;
| max 40V -&amp;gt; 1,2 - 37V, max 3A, TO220-5&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LM2576 PDF] - [http://www.mikrocontroller.net/topic/58094#450561 mit Funk-Entstördrossel FED100µ (Reichelt...) bis 3 A]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Digital ==&lt;br /&gt;
=== CAN ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;can&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| MCP2515&lt;br /&gt;
| 1,95&lt;br /&gt;
| SPI-CAN 2.0B Baustein&lt;br /&gt;
| &lt;br /&gt;
| Reichelt&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
| SJA1000&lt;br /&gt;
| 4,55&lt;br /&gt;
| PellCAN 2.0B 1Mbit/s&lt;br /&gt;
|&lt;br /&gt;
| Reichelt&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Logik ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| 74HC4050&lt;br /&gt;
| 0,27&lt;br /&gt;
| z.B. 5V =&amp;gt; 3V&lt;br /&gt;
| Pegelwandler unidirektional abwärts&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=74hc4050 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== USB ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;usb&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| FT232&lt;br /&gt;
| 5,65&lt;br /&gt;
| USB &amp;lt;-&amp;gt; RS232 Wandler&lt;br /&gt;
| Zugriff über virtuellen COM Port&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=ft232 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| FT245&lt;br /&gt;
| 6,35&lt;br /&gt;
| USB &amp;lt;-&amp;gt; Seriell Wandler mit paralleler Schnittstelle&lt;br /&gt;
| Zugriff über virtuellen COM Port&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=ft245 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Treiber ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| ULN2003A&lt;br /&gt;
| 0,17&lt;br /&gt;
| 7-fach Low-Side Treiber&lt;br /&gt;
| 50V/500mA&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=ULN2003 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| ULN2803A&lt;br /&gt;
| 0,44&lt;br /&gt;
| 8-fach Low-Side Treiber&lt;br /&gt;
| 50V/500mA&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=ULN2803 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| UDN2981&lt;br /&gt;
| 1,50&lt;br /&gt;
| 8-fach High-Side Treiber&lt;br /&gt;
| 50V/500mA&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=UDN2981 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| ICL7667&lt;br /&gt;
| 1&lt;br /&gt;
| Dual inverting FET Treiber&lt;br /&gt;
| 18V, 20ns@1nF&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=ICL7667 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Optokoppler ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| CNY17&lt;br /&gt;
| 0,17&lt;br /&gt;
| billig&lt;br /&gt;
| Standardtyp&lt;br /&gt;
| R,C&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=CNY17 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| 6N137&lt;br /&gt;
| 0,49&lt;br /&gt;
| Logikausgang&lt;br /&gt;
| sehr schnell&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=6N137 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Converter ==&lt;br /&gt;
=== ADC ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
=== DAC ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
== Sensoren (aktiv) ==&lt;br /&gt;
=== [[Temperatursensor|Temperatur]] ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| LM75&lt;br /&gt;
| ~2,10&lt;br /&gt;
| Temperatursensor mit I²C (TWI) Bus Interface (3.3V und 5V Version) (SMD)&lt;br /&gt;
| &lt;br /&gt;
| R D&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LM75 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| DS1621&lt;br /&gt;
| ~5&lt;br /&gt;
| Temperatursensor mit I²C (TWI) Bus Interface (wie LM75, kein SMD)&lt;br /&gt;
| &lt;br /&gt;
| C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| DS18B20&lt;br /&gt;
| 4,30&lt;br /&gt;
| Temperatursensor mit 1-Wire Interface&lt;br /&gt;
|&lt;br /&gt;
| R D&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=DS18B20 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM35&lt;br /&gt;
| 1,49&lt;br /&gt;
| Analoger Temperatursensor&lt;br /&gt;
| 10mV/°C absolut&lt;br /&gt;
| D&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LM35 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM335&lt;br /&gt;
| 0,87&lt;br /&gt;
| Analoger Temperatursensor&lt;br /&gt;
| 10mV/K absolut&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LM335 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
Wenn man z.B. einen Übertemperaturschutz (oder eine andere Schaltung, bei der es nur eine Schaltschwelle gibt) bauen will, dann empfiehlt sich die Verwendung eines NTCs. Dessen Kennlinie ist gegenüber den Kennlinien von z.B. LM335 dahingehend im Vorteil, dass eine geringe Temperaturänderung besser messbar ist.&lt;br /&gt;
&lt;br /&gt;
= Passive Bauelemente =&lt;br /&gt;
== Sensoren (passiv) ==&lt;br /&gt;
=== Licht ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
=== [[Temperatursensor|Temperatur]] ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| KTY81&lt;br /&gt;
| ~0,50&lt;br /&gt;
| nichtlinear, bis 150°C&lt;br /&gt;
| in &amp;amp;#956;C Schaltungen&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat/datasheets/KTY84_SERIES_5.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| KTY84&lt;br /&gt;
| 0,72&lt;br /&gt;
| nichtlinear, bis 300°C&lt;br /&gt;
| in &amp;amp;#956;C Schaltungen&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat/datasheets/KTY84_SERIES_5.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| PT100&lt;br /&gt;
| ab 3,00&lt;br /&gt;
| lineare Kennlinie&lt;br /&gt;
| analoge Messschaltungen&lt;br /&gt;
| F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Widerstände ===&lt;br /&gt;
Mit einem Widerstandssortiment, welches die E12-Werte enthält, kann man normalerweise nicht falsch liegen. Denn früher oder später benötigt man jeden Widerstandswert der E12-Reihe einmal.&lt;br /&gt;
&lt;br /&gt;
Für einen Einstieg eignen sich die Sortimente vom Pollin. Auch ein Blick in Ebay kann sich lohnen um ein Einstiegssortiment zu bekommen.&lt;br /&gt;
&lt;br /&gt;
=== Kondensatoren ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| 100nF Keramik&lt;br /&gt;
| ~0.05&lt;br /&gt;
| &lt;br /&gt;
| Als sogenannter Abblockkondensator zwischen VCC und GND vor allem bei Digital-ICs zwingend erforderlich, schadet aber auch bei den meisten Analog-ICs nicht.&lt;br /&gt;
| &lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
| 100nF Keramik SMD 0603&lt;br /&gt;
| ~0.01 (bei 100 Stück)&lt;br /&gt;
| SMD 0603&lt;br /&gt;
| Als sogenannter Abblockkondensator zwischen VCC und GND vor allem bei Digital-ICs zwingend erforderlich, schadet aber auch bei den meisten Analog-ICs nicht.&lt;br /&gt;
| D&lt;br /&gt;
| [http://www.google.de/search?num=100&amp;amp;hl=de&amp;amp;q=datasheet+0603+chip-capacitors+filetype%3Apdf&amp;amp;btnG=Suche&amp;amp;meta=lr%3Dlang_de%7Clang_en PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Lieferanten =&lt;br /&gt;
C: Conrad [http://www.conrad.de www.conrad.de]&lt;br /&gt;
&lt;br /&gt;
D: CSD-Electronics [http://www.csd-electronics.de www.csd-electronics.de] &lt;br /&gt;
&lt;br /&gt;
F: Farnell (nur Firmen &amp;amp; Studenten) [http://www.farnell.de www.farnell.de]&lt;br /&gt;
&lt;br /&gt;
P: Pollin [http://www.pollin.de www.pollin.de]&lt;br /&gt;
&lt;br /&gt;
R: Reichelt [http://www.reichelt.de www.reichelt.de]&lt;br /&gt;
&lt;br /&gt;
Allgemeine Lieferantenliste: [http://www.mikrocontroller.net/articles/Elektronik-Versender Elektronik-Versender]&lt;br /&gt;
&lt;br /&gt;
[[Category:Bauteile]]&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Platinenherstellung_mit_der_Photo-Positiv-Methode&amp;diff=18984</id>
		<title>Platinenherstellung mit der Photo-Positiv-Methode</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Platinenherstellung_mit_der_Photo-Positiv-Methode&amp;diff=18984"/>
		<updated>2007-01-04T11:29:20Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: /* Inkjet-Folie */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welche Software man zum Zeichnen nimmt ist Geschmackssache. Darum gehts gleich zum Drucken ;)&lt;br /&gt;
&lt;br /&gt;
= Drucken =&lt;br /&gt;
&lt;br /&gt;
Generell muss so gedruckt werden, dass die bedruckte Seite am Kupfer aufliegt. Sonst bekommt man keine schönen Bahnen hin.&lt;br /&gt;
&lt;br /&gt;
Am Besten druckt man sich das ganze mit niedriger Qualität auf Papier aus und schaut ob alles wie gewünscht erscheint (Masseflächen, Beschriftung, Pass-Marken,...) &lt;br /&gt;
&lt;br /&gt;
Weiters noch die Einstellungen um schöne, schwarze Ausdrucke zu bekommen.&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
&lt;br /&gt;
=== Target ===&lt;br /&gt;
In Target sollte man folgendes einschalten...&lt;br /&gt;
&lt;br /&gt;
* hart schwarz-weiß&lt;br /&gt;
&lt;br /&gt;
===Eagle===&lt;br /&gt;
&lt;br /&gt;
* black&lt;br /&gt;
* solid&lt;br /&gt;
&lt;br /&gt;
== Drucksorten ==&lt;br /&gt;
&lt;br /&gt;
=== Transparentpapier ===&lt;br /&gt;
&lt;br /&gt;
Wenn die Tinte passt, bekommt man auch auf Transparentpapier gute Ergebnisse (zumindest mit meinem alten HP).&lt;br /&gt;
&lt;br /&gt;
Mit einem Laserdrucker (Kyocera-Mita FS1020D, Auflösung 1200x1200 dpi) sind auf Transparentpapier Leiterbahnen mit 0.4mm Breite problemlos möglich&lt;br /&gt;
&lt;br /&gt;
=== Normalpapier ===&lt;br /&gt;
&lt;br /&gt;
Wenn nur bedrahtete Bauteile auf dem PCB und die Leiterbahnen auch schön breit sind, gibt es keinen Grund nicht normales Papier zu verwenden... man muss nur eine lange Belichtungszeite einplanen... ggf. dünneres Papier probieren (&amp;lt;math&amp;gt;40g/m^2&amp;lt;/math&amp;gt;) ;)&lt;br /&gt;
&lt;br /&gt;
=== Inkjet-Folie ===&lt;br /&gt;
&lt;br /&gt;
Für feine Layouts mit Tintenstrahl-Drucker meiner Meinung nach am Besten geeignet.&lt;br /&gt;
&lt;br /&gt;
Epson C44Ux mit Nachbau-Tinte von Conrad auf Zweckform-Folie 2503 und 2304 (hat einen weißen Streifen damit der Ducker die Folie erkennt) gibts keine Probleme.&lt;br /&gt;
&lt;br /&gt;
Unter Windows ist der Drucker auf &#039;&#039;Premium Glossy Photo Paper&#039;&#039; Foto zu stellen - unter Linux &#039;&#039;Premium Glossy Photo Paper&#039;&#039; und die Auflösung auf &#039;&#039;1440x720&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Das Layout muss 2-3 mal ausgedruckt und übereinander gelegt werden, damit man keine kleinen Löcher hat.&lt;br /&gt;
&lt;br /&gt;
Mit Laserdruck auf Klarsichtfolie erzielt man schlechte Ergebnisse, auf matter Folie hingegen reicht schon ein Ausdruck auf einer Folie.&lt;br /&gt;
&lt;br /&gt;
Eventuell ist es besser in den Druckereinstellungen als Druckmedium Photopapier statt Inkjet Folie auszuwählen um eine bessere Deckung zu erreichen.&lt;br /&gt;
&lt;br /&gt;
= Fertigung =&lt;br /&gt;
&lt;br /&gt;
Das Ätzen teilt sich auf in Belichten, Entwickeln und  das Ätzen... Naturgemäß muss man dabei teilweise mit gefährlichen Chemikalien umgehen. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;firebrick&amp;quot;&amp;gt;&#039;&#039;&#039;Bitte informiert Euch vorher genau über die verwendeten Chemikalien und den sicheren Umgang damit!&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eine gute Quelle dafür ist die [http://www.hvbg.de/d/bia/fac/stoffdb/ GESTIS-Stoffdatenbank] (Gefahrstoffinformationssystem der gewerblichen Berufsgenossenschaften).&lt;br /&gt;
&lt;br /&gt;
Vielleicht hat jemand mehr Lust, das jetzt ausführlich zu beschreiben.. ich beschreibe mal alles ganz grob...&lt;br /&gt;
&lt;br /&gt;
== Belichten ==&lt;br /&gt;
&lt;br /&gt;
=== UV-Lampe ===&lt;br /&gt;
&lt;br /&gt;
Es gibt sogenannte &#039;&#039;Nitraphot&#039;&#039;-Lampen die 250-300W haben. Damit hab ich&#039;s anfangs gemacht. Das Hauptproblem dabei ist die erzeugte Wärme... Wo gibts denn vernünftige Fassungen für 300W-Birnen :)&lt;br /&gt;
&lt;br /&gt;
=== UV-Röhren ===&lt;br /&gt;
&lt;br /&gt;
Ich persönlich habe mir den Luxus gegönnt und mir Ersatzlampen für die Isel Geräte besorgt. (Conrad)&lt;br /&gt;
&lt;br /&gt;
* 2 x 8W Philips Röhren - ca 10cm Abstand - 3 x Overhead-Folie übereinander =&amp;gt; ca 5 Minuten&lt;br /&gt;
* 4 x 8W Ersatzröhren für die Reichelt-Belichtungsgeräte - ca 12 cm - Transparentpapier =&amp;gt; 7-8 Minuten&lt;br /&gt;
&lt;br /&gt;
=== Baustrahler ===&lt;br /&gt;
&lt;br /&gt;
Geht angeblich ganz gut, habe aber keine Erfahrung damit gemacht.&lt;br /&gt;
&lt;br /&gt;
=== Leuchtstoffröhren ===&lt;br /&gt;
Auch Leuchtstoffröhren können benutzt werden um Platinen zu belichten. Bei einem Abstand von 10 cm benötigt man rund eine Belichtungszeit von einer halben Stunde. Zur Not kann es auch kurz die Schreibtischlampe sein oder für Massenbelichtungen auch eine 1m Stablampe.&lt;br /&gt;
&lt;br /&gt;
== Entwickeln ==&lt;br /&gt;
&lt;br /&gt;
Entwickeln kann man mit Ätznatron (um die 10g/l eher darunter, falls man die Zeit übersehen sollte und man etwas unterentwickeln muss).&lt;br /&gt;
&lt;br /&gt;
Die Luxus-Variante gibts bei Conrad in Form von Bungard-Entwickler. 1 Säckchen für 1l Entwickler.&lt;br /&gt;
Laut Bungard ist die unbelichtete Beschichtung einige Minuten gegen den Entwickler resistent... Der Entwickler muss aber mindestens Zimmertemperatur haben... sonst dauert&#039;s ewig :)&lt;br /&gt;
&lt;br /&gt;
== Ätzen ==&lt;br /&gt;
==Ammoniumpersulfat/Natriumpersulfat==&lt;br /&gt;
&lt;br /&gt;
Wohl das am weitesten verbreitete Ätzmittel, liefert gute Ergebnisse ist im Vergleich zu Salzsäure/Salpetersäure nicht so aggressiv und sauberer als Eisen-3-Chlorid.&lt;br /&gt;
&lt;br /&gt;
Natriumpersulfat sollte aufgrund seiner Gewässertoxizität der Vorzug gegenüber Ammoniumpersulfat gegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Salpetersäure ===&lt;br /&gt;
&lt;br /&gt;
Geht ähnlich gut wie mit Salzsäure, nur will nicht jeder einem das Zeug in die Hand geben... =&amp;gt; lieber Salzsäure!&lt;br /&gt;
&lt;br /&gt;
Möglich sind Zeiten von &amp;lt;1min bis 10min.. je nach Konzentration&lt;br /&gt;
&lt;br /&gt;
=== Salzsäure ===&lt;br /&gt;
&lt;br /&gt;
Mischung 1 Teil HCl, 1 Teil H2O2, 2Teile H2O geht suppi (würd ich mir nicht traun mit hochkonzentrierter.. lieber die Säure unter 20% bringen und nach Bedarf H2O2 dazu tun) &lt;br /&gt;
&lt;br /&gt;
=== Eisen-3-Chlorid ===&lt;br /&gt;
&lt;br /&gt;
Mit Eisen-3-Chlorid ätzt es sich gut. Nach etwa 10 Minuten ist die Platine fertig. Hier ist gut entwickeltes Material nötig, sonst sind die dünnen Konturen schnell weggeätzt.&lt;br /&gt;
&lt;br /&gt;
= Nachbehandlung =&lt;br /&gt;
&lt;br /&gt;
Die Platine ist also soweit fertig. Jetzt noch mit Stahlwolle reinigen (ist das Einfachste meiner Meinung nach) und mit Lötlack einsprühen... Kolophonium (oder auch Saupech genannt) in Nitro-Verdünnung gelöst soll billiger sein und die gleiche Wirkung erzielen.&lt;br /&gt;
&lt;br /&gt;
Der Fotolack lässt sich auch entfernen, indem man die fertig geätzte Platine noch einmal für längere Zeit belichtet und nochmals entwickelt, sodass der restliche Lack abgelöst wird. Eine halbe Stunde Tageslicht klappt gut. &lt;br /&gt;
&lt;br /&gt;
Um schön glänzende Platinen zu bekommen, kann man die Platine auch mit Lötpaste einschmieren und mit einem Heißluft-Fön bearbeiten. Dafür braucht man aber etwas Übung um die Platine nicht zu heiß zu machen und die richtige Menge Paste aufzutragen. Die teurere aber einfachere Möglichkeit sind chemische Verzinnungsbäder: Platine reinlegen, einige Minuten warten, abspülen, fertig. &lt;br /&gt;
&lt;br /&gt;
Alternativ zur Stahlwolle geht Spiritus, Isopropanol, ... auch ganz gut.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ursprünglich von OE6JWF / Hans&lt;br /&gt;
&lt;br /&gt;
edited by: Clemens Helfmeier&lt;br /&gt;
&lt;br /&gt;
Umformatiert von --[[Benutzer:Hans|Hans]] 00:38, 5. Jan 2006 (CET)&lt;br /&gt;
&lt;br /&gt;
[[Category:Platinen]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ebenfalls zur Nachbearbeitung geeignet ist Nagellackentferner oder Aceton (Bestandteil von Nagellackentferner), um den verbleibenden Fotolackrest zu entfernen und die Platine zu entfetten, bevor man sie lackiert.&lt;br /&gt;
Damit ist es ebenfalls möglich, den schlecht durchlötbaren Fotolack von den  Bungard-Platinen abzulösen.&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Platinenherstellung_mit_der_Photo-Positiv-Methode&amp;diff=18983</id>
		<title>Platinenherstellung mit der Photo-Positiv-Methode</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Platinenherstellung_mit_der_Photo-Positiv-Methode&amp;diff=18983"/>
		<updated>2007-01-04T11:27:46Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: /* Belichten */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Welche Software man zum Zeichnen nimmt ist Geschmackssache. Darum gehts gleich zum Drucken ;)&lt;br /&gt;
&lt;br /&gt;
= Drucken =&lt;br /&gt;
&lt;br /&gt;
Generell muss so gedruckt werden, dass die bedruckte Seite am Kupfer aufliegt. Sonst bekommt man keine schönen Bahnen hin.&lt;br /&gt;
&lt;br /&gt;
Am Besten druckt man sich das ganze mit niedriger Qualität auf Papier aus und schaut ob alles wie gewünscht erscheint (Masseflächen, Beschriftung, Pass-Marken,...) &lt;br /&gt;
&lt;br /&gt;
Weiters noch die Einstellungen um schöne, schwarze Ausdrucke zu bekommen.&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
&lt;br /&gt;
=== Target ===&lt;br /&gt;
In Target sollte man folgendes einschalten...&lt;br /&gt;
&lt;br /&gt;
* hart schwarz-weiß&lt;br /&gt;
&lt;br /&gt;
===Eagle===&lt;br /&gt;
&lt;br /&gt;
* black&lt;br /&gt;
* solid&lt;br /&gt;
&lt;br /&gt;
== Drucksorten ==&lt;br /&gt;
&lt;br /&gt;
=== Transparentpapier ===&lt;br /&gt;
&lt;br /&gt;
Wenn die Tinte passt, bekommt man auch auf Transparentpapier gute Ergebnisse (zumindest mit meinem alten HP).&lt;br /&gt;
&lt;br /&gt;
Mit einem Laserdrucker (Kyocera-Mita FS1020D, Auflösung 1200x1200 dpi) sind auf Transparentpapier Leiterbahnen mit 0.4mm Breite problemlos möglich&lt;br /&gt;
&lt;br /&gt;
=== Normalpapier ===&lt;br /&gt;
&lt;br /&gt;
Wenn nur bedrahtete Bauteile auf dem PCB und die Leiterbahnen auch schön breit sind, gibt es keinen Grund nicht normales Papier zu verwenden... man muss nur eine lange Belichtungszeite einplanen... ggf. dünneres Papier probieren (&amp;lt;math&amp;gt;40g/m^2&amp;lt;/math&amp;gt;) ;)&lt;br /&gt;
&lt;br /&gt;
=== Inkjet-Folie ===&lt;br /&gt;
&lt;br /&gt;
Für feine Layouts mit Tintenstrahl-Drucker meiner Meinung nach am Besten geeignet.&lt;br /&gt;
&lt;br /&gt;
Epson C44Ux mit Nachbau-Tinte von Conrad auf Zweckform-Folie 2503 und 2304 (hat einen weißen Streifen damit der Ducker die Folie erkennt) gibts keine Probleme.&lt;br /&gt;
&lt;br /&gt;
Unter Windows ist der Drucker auf &#039;&#039;Premium Glossy Photo Paper&#039;&#039; Foto zu stellen - unter Linux &#039;&#039;Premium Glossy Photo Paper&#039;&#039; und die Auflösung auf &#039;&#039;1440x720&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Das Layout muss 2-3 mal ausgedruckt und übereinander gelegt werden, damit man keine kleinen Löcher hat.&lt;br /&gt;
&lt;br /&gt;
Mit Laserdruck auf Klarsichtfolie erzielt man schlechte Ergebnisse, auf matter Folie hingegen reicht schon ein Ausdruck auf einer Folie.&lt;br /&gt;
&lt;br /&gt;
= Fertigung =&lt;br /&gt;
&lt;br /&gt;
Das Ätzen teilt sich auf in Belichten, Entwickeln und  das Ätzen... Naturgemäß muss man dabei teilweise mit gefährlichen Chemikalien umgehen. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;firebrick&amp;quot;&amp;gt;&#039;&#039;&#039;Bitte informiert Euch vorher genau über die verwendeten Chemikalien und den sicheren Umgang damit!&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eine gute Quelle dafür ist die [http://www.hvbg.de/d/bia/fac/stoffdb/ GESTIS-Stoffdatenbank] (Gefahrstoffinformationssystem der gewerblichen Berufsgenossenschaften).&lt;br /&gt;
&lt;br /&gt;
Vielleicht hat jemand mehr Lust, das jetzt ausführlich zu beschreiben.. ich beschreibe mal alles ganz grob...&lt;br /&gt;
&lt;br /&gt;
== Belichten ==&lt;br /&gt;
&lt;br /&gt;
=== UV-Lampe ===&lt;br /&gt;
&lt;br /&gt;
Es gibt sogenannte &#039;&#039;Nitraphot&#039;&#039;-Lampen die 250-300W haben. Damit hab ich&#039;s anfangs gemacht. Das Hauptproblem dabei ist die erzeugte Wärme... Wo gibts denn vernünftige Fassungen für 300W-Birnen :)&lt;br /&gt;
&lt;br /&gt;
=== UV-Röhren ===&lt;br /&gt;
&lt;br /&gt;
Ich persönlich habe mir den Luxus gegönnt und mir Ersatzlampen für die Isel Geräte besorgt. (Conrad)&lt;br /&gt;
&lt;br /&gt;
* 2 x 8W Philips Röhren - ca 10cm Abstand - 3 x Overhead-Folie übereinander =&amp;gt; ca 5 Minuten&lt;br /&gt;
* 4 x 8W Ersatzröhren für die Reichelt-Belichtungsgeräte - ca 12 cm - Transparentpapier =&amp;gt; 7-8 Minuten&lt;br /&gt;
&lt;br /&gt;
=== Baustrahler ===&lt;br /&gt;
&lt;br /&gt;
Geht angeblich ganz gut, habe aber keine Erfahrung damit gemacht.&lt;br /&gt;
&lt;br /&gt;
=== Leuchtstoffröhren ===&lt;br /&gt;
Auch Leuchtstoffröhren können benutzt werden um Platinen zu belichten. Bei einem Abstand von 10 cm benötigt man rund eine Belichtungszeit von einer halben Stunde. Zur Not kann es auch kurz die Schreibtischlampe sein oder für Massenbelichtungen auch eine 1m Stablampe.&lt;br /&gt;
&lt;br /&gt;
== Entwickeln ==&lt;br /&gt;
&lt;br /&gt;
Entwickeln kann man mit Ätznatron (um die 10g/l eher darunter, falls man die Zeit übersehen sollte und man etwas unterentwickeln muss).&lt;br /&gt;
&lt;br /&gt;
Die Luxus-Variante gibts bei Conrad in Form von Bungard-Entwickler. 1 Säckchen für 1l Entwickler.&lt;br /&gt;
Laut Bungard ist die unbelichtete Beschichtung einige Minuten gegen den Entwickler resistent... Der Entwickler muss aber mindestens Zimmertemperatur haben... sonst dauert&#039;s ewig :)&lt;br /&gt;
&lt;br /&gt;
== Ätzen ==&lt;br /&gt;
==Ammoniumpersulfat/Natriumpersulfat==&lt;br /&gt;
&lt;br /&gt;
Wohl das am weitesten verbreitete Ätzmittel, liefert gute Ergebnisse ist im Vergleich zu Salzsäure/Salpetersäure nicht so aggressiv und sauberer als Eisen-3-Chlorid.&lt;br /&gt;
&lt;br /&gt;
Natriumpersulfat sollte aufgrund seiner Gewässertoxizität der Vorzug gegenüber Ammoniumpersulfat gegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Salpetersäure ===&lt;br /&gt;
&lt;br /&gt;
Geht ähnlich gut wie mit Salzsäure, nur will nicht jeder einem das Zeug in die Hand geben... =&amp;gt; lieber Salzsäure!&lt;br /&gt;
&lt;br /&gt;
Möglich sind Zeiten von &amp;lt;1min bis 10min.. je nach Konzentration&lt;br /&gt;
&lt;br /&gt;
=== Salzsäure ===&lt;br /&gt;
&lt;br /&gt;
Mischung 1 Teil HCl, 1 Teil H2O2, 2Teile H2O geht suppi (würd ich mir nicht traun mit hochkonzentrierter.. lieber die Säure unter 20% bringen und nach Bedarf H2O2 dazu tun) &lt;br /&gt;
&lt;br /&gt;
=== Eisen-3-Chlorid ===&lt;br /&gt;
&lt;br /&gt;
Mit Eisen-3-Chlorid ätzt es sich gut. Nach etwa 10 Minuten ist die Platine fertig. Hier ist gut entwickeltes Material nötig, sonst sind die dünnen Konturen schnell weggeätzt.&lt;br /&gt;
&lt;br /&gt;
= Nachbehandlung =&lt;br /&gt;
&lt;br /&gt;
Die Platine ist also soweit fertig. Jetzt noch mit Stahlwolle reinigen (ist das Einfachste meiner Meinung nach) und mit Lötlack einsprühen... Kolophonium (oder auch Saupech genannt) in Nitro-Verdünnung gelöst soll billiger sein und die gleiche Wirkung erzielen.&lt;br /&gt;
&lt;br /&gt;
Der Fotolack lässt sich auch entfernen, indem man die fertig geätzte Platine noch einmal für längere Zeit belichtet und nochmals entwickelt, sodass der restliche Lack abgelöst wird. Eine halbe Stunde Tageslicht klappt gut. &lt;br /&gt;
&lt;br /&gt;
Um schön glänzende Platinen zu bekommen, kann man die Platine auch mit Lötpaste einschmieren und mit einem Heißluft-Fön bearbeiten. Dafür braucht man aber etwas Übung um die Platine nicht zu heiß zu machen und die richtige Menge Paste aufzutragen. Die teurere aber einfachere Möglichkeit sind chemische Verzinnungsbäder: Platine reinlegen, einige Minuten warten, abspülen, fertig. &lt;br /&gt;
&lt;br /&gt;
Alternativ zur Stahlwolle geht Spiritus, Isopropanol, ... auch ganz gut.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ursprünglich von OE6JWF / Hans&lt;br /&gt;
&lt;br /&gt;
edited by: Clemens Helfmeier&lt;br /&gt;
&lt;br /&gt;
Umformatiert von --[[Benutzer:Hans|Hans]] 00:38, 5. Jan 2006 (CET)&lt;br /&gt;
&lt;br /&gt;
[[Category:Platinen]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ebenfalls zur Nachbearbeitung geeignet ist Nagellackentferner oder Aceton (Bestandteil von Nagellackentferner), um den verbleibenden Fotolackrest zu entfernen und die Platine zu entfetten, bevor man sie lackiert.&lt;br /&gt;
Damit ist es ebenfalls möglich, den schlecht durchlötbaren Fotolack von den  Bungard-Platinen abzulösen.&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Standardbauelemente&amp;diff=18911</id>
		<title>Standardbauelemente</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Standardbauelemente&amp;diff=18911"/>
		<updated>2006-12-30T13:37:26Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: /* Temperatur */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Gerade Neulinge kennen das Problem: Man hat eine tolle Schaltung mit vielen Operationsverstärkern, Spannungsreglern, Logikbausteinen, ADCs, was auch immer entwickelt und jetzt geht&#039;s an die Realisierung.&lt;br /&gt;
&lt;br /&gt;
Aber welche Bausteine nehmen unter dem Wust der Angebote? Also erstmal auf die Seiten der Hersteller und die Produktpalette durchforsten. Nach einigen Stunden gewissenhafter Recherche hat man dann endlich alle Bauteile beisammen und will bestellen. Und dann kommt das böse Erwachen: Einige Bauelemente gibt&#039;s nur bei Reichelt, andere nur bei Conrad. Farnell hat zwar das meiste, aber da kann man als Privatperson leider nicht bestellen. Manche ICs bekommt man nur in 1000er Stückzahlen oder sind halt einfach nur viel zu teuer.&lt;br /&gt;
&lt;br /&gt;
Nach einigen Jahren praktischer Erfahrung hat man dann seine &amp;quot;Standardbauelemente&amp;quot;, die man immer wieder verwendet. Dieser Artikel soll helfen andere von dieser Erfahrung profitieren zu lassen. Ähnliche Anregungen findet man auch in der de.sci.electronics-FAQ: Grundausstattung des Bastlers [[http://dse-faq.elektronik-kompendium.de/dse-faq.htm#F.2]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= !Hinweise! =&lt;br /&gt;
Hier soll eine Liste von häufig anzutreffenden, preiswerten und verfügbaren Standardbauelementen entstehen. Diese Liste soll knapp und bündig sein, für technische Daten wird auf die Datenblätter verwiesen. Hier gilt: &amp;quot;weniger ist mehr&amp;quot;, exotische Bauelemente sind also unerwünscht. Für hier gelistete Typen sollte gelten:&lt;br /&gt;
* für Privatpersonen verfügbar&lt;br /&gt;
* preiswert (nicht billig)&lt;br /&gt;
&lt;br /&gt;
Nicht gelistet werden sollen:&lt;br /&gt;
* hunderte Typen, die alle den gleichen Zweck erfüllen, aber keinen Mehrwert bringen. Stattdessen auf die bekanntesten / preiswertesten beschränken.&lt;br /&gt;
* Details. Stattdessen die Felder &amp;quot;Besonderheiten&amp;quot; und &amp;quot;Anwendungen&amp;quot; benutzen, z.B. &amp;quot;I²C, 12bit&amp;quot; bei Besonderheiten für einen ADC oder &amp;quot;Präzision, Audio&amp;quot; bei Anwendungen für einen OpAmp.&lt;br /&gt;
&lt;br /&gt;
Wer eine Sparte, oder eine Anwendung vermisst, aber selber nichts dazu beitragen kann: Einfach hinzufügen. Wer z.B. einen HF OpAmp sucht und hier nicht fündig wird sollte also eine neue Zeile einfügen und in die Spalte Anwendungen &amp;quot;HF&amp;quot; eintragen. Villeicht kann ja jemand den Rest der Zeile füllen.&lt;br /&gt;
&lt;br /&gt;
Immer den Grundtypen listen und nicht eine der Varianten, und schon gar nicht alle Varianten einzeln! Also z.B. &amp;quot;LM324&amp;quot; statt &amp;quot;LM324N&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Wenn möglich Direktlinks auf Datenblätter vermeiden und eine Suchmaschine befragen: &amp;quot;http://www.datasheetarchive.com/search.php?q=lm324&amp;quot;&lt;br /&gt;
* so werden alle Varianten gefunden&lt;br /&gt;
* und tote Links vermieden&lt;br /&gt;
&lt;br /&gt;
Die wichtigsten, allgemeinen Standard-Typen ganz oben in der Tabelle listen, danach erst die Spezialtypen für bestimmte Anwendungen.&lt;br /&gt;
&lt;br /&gt;
Und weil es mir so wichtig ist nochmal: Ich rufe geradezu dazu auf, überflüssige, unverfügbare Typen zu löschen!&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Aktive Bauelemente =&lt;br /&gt;
== Analog ==&lt;br /&gt;
&lt;br /&gt;
=== Transistoren ===&lt;br /&gt;
NPN&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;transistors-npn&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| BC 337&lt;br /&gt;
| 0,04&lt;br /&gt;
| Standardtyp&lt;br /&gt;
| bis ~300mA sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.google.de/search?num=100&amp;amp;hl=de&amp;amp;q=datasheet+bc337+filetype%3Apdf&amp;amp;btnG=Suche&amp;amp;meta=lr%3Dlang_de%7Clang_en PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BC 547/847&lt;br /&gt;
| 0,03&lt;br /&gt;
| Standardtyp, BC847 in SMD&lt;br /&gt;
| bis ~50mA sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat_download/datasheets/BC847_BC547_SER_6.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BC 635/639&lt;br /&gt;
| 0,07&lt;br /&gt;
| andere Pinbelegung als BC547 (= BD135 in anderem Gehäuse)&lt;br /&gt;
| bis ~500mA sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat/datasheets/BC635_BCP54_BCX54_6.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BD 433/437&lt;br /&gt;
| 0,19&lt;br /&gt;
| niedrige Sättigungsspannung&lt;br /&gt;
| bis ~2A sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.fairchildsemi.com/ds/BD%2FBD435.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| TIP102&lt;br /&gt;
| 0,42&lt;br /&gt;
| Ptot bis 80W mit Kühlkörper, hohe Stromverstärkung von über 1000 über einen sehr großen Bereich.&lt;br /&gt;
| Grenzwert 8A&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.fairchildsemi.com/ds/TI%2FTIP102.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| TIP 3055&lt;br /&gt;
| 0,75&lt;br /&gt;
| Ptot bis 90W mit Kühlkörper, Stromverstärkung sehr niedrig (bei großen Strömen &amp;lt;&amp;lt; 100)&lt;br /&gt;
| Grenzwert 15A &lt;br /&gt;
| R&lt;br /&gt;
| [http://www.ortodoxism.ro/datasheets/PowerInnovations/mXvutwr.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
PNP&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;transistors-pnp&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| BC 327&lt;br /&gt;
| 0,04&lt;br /&gt;
| Komplementärtyp zu BC337&lt;br /&gt;
| bis ~300mA sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.google.de/search?num=100&amp;amp;hl=de&amp;amp;q=datasheet+bc327+filetype%3Apdf&amp;amp;btnG=Suche&amp;amp;meta=lr%3Dlang_de%7Clang_en PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BC 557C&lt;br /&gt;
| 0,03&lt;br /&gt;
| Komplementärtyp zu BC547C&lt;br /&gt;
| bis ~50mA sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat_download/datasheets/BC556_557_4.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BC 636/640&lt;br /&gt;
| 0,07&lt;br /&gt;
| Komplementärtyp zu BC635&lt;br /&gt;
| bis ~500mA sinnvoll&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat/datasheets/BC640_BCP53_BCX53_6.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| TIP 2955&lt;br /&gt;
| 0,75&lt;br /&gt;
| Ptot bis 90W mit Kühlkörper&lt;br /&gt;
| Grenzwert 15A&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.ortodoxism.ro/datasheets/motorola/TIP2955.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eigene Seite für MOSFETs: [[Mosfet-Übersicht]]&lt;br /&gt;
&lt;br /&gt;
N-MOSFET&lt;br /&gt;
&lt;br /&gt;
BUZ10, BUZ11 etc. sind wie alle BUZ Typen ziemlich veraltet. Bitte nicht listen; es gibt fast immer was besseres von IRF.&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;mosfet-n&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| IRF1010N&lt;br /&gt;
| 0,87&lt;br /&gt;
| max 50V, max 85A, 11 mOhm On-Widerstand&lt;br /&gt;
| Alles, was mit POWER zu tun hat ...&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.irf.com/product-info/datasheets/data/irf1010n.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| IRLZ34N&lt;br /&gt;
| 0,42&lt;br /&gt;
| max 55V, max 30A, 35 mOhm On-Widerstand&lt;br /&gt;
| Gatespannung kompatibel mit 5V-Controllern.&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.irf.com/product-info/datasheets/data/irlz34n.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BS170&lt;br /&gt;
| 0,13&lt;br /&gt;
| max 60V, bis 500mA, 5 Ohm On-Widerstand&lt;br /&gt;
| veraltete Technik aber in bastelfreundlichem TO-92 Gehäuse von R lieferbar &lt;br /&gt;
| R&lt;br /&gt;
| [http://www.fairchildsemi.com/ds/BS/BS170.pdf PDF] (Fairchild)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
P-MOSFET&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;mosfet-p&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| IRF7220&lt;br /&gt;
| 1,10&lt;br /&gt;
| max -14V, ca -10A (cont.), ca. 0,02 Ohm On-Widerstand&lt;br /&gt;
| Gehäuse SO-8, brauchbar in 3,3V Systemen&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.irf.com/product-info/datasheets/data/irf7220.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| BS250&lt;br /&gt;
| 0,18&lt;br /&gt;
| max -45V, bis -230mA (cont.), 14 (und mehr) Ohm On-Widerstand&lt;br /&gt;
| veraltete Technik aber in bastelfreundlichem TO-92 Gehäuse von R lieferbar &lt;br /&gt;
| R&lt;br /&gt;
| [http://www.vishay.com/docs/70209/70209.pdf PDF] (Vishay)&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
MOSFET-Pärchen&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;mosfet-n-p&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| IRF7389&lt;br /&gt;
| 0,56&lt;br /&gt;
| 30 V, &amp;gt;2,5 A, 30/60 mOhm On-Widerstand&lt;br /&gt;
| Gehäuse SO-8&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.irf.com/product-info/datasheets/data/irf7389.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Dioden ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;mosfet-p&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| 1N4148&lt;br /&gt;
| 0,02&lt;br /&gt;
| Kleinsignal-Gleichrichterdiode&lt;br /&gt;
| &lt;br /&gt;
| R&lt;br /&gt;
| [http://www.fairchildsemi.com/ds/1N%2F1N4148.pdf D]&lt;br /&gt;
|-&lt;br /&gt;
| 1N4001..1N4007&lt;br /&gt;
| 0,02&lt;br /&gt;
| Mehrzweck-Gleichrichterdiode, 1N4001..1N4007 mit gestaffelter Sperrspannung&lt;br /&gt;
| &lt;br /&gt;
| R&lt;br /&gt;
| [http://www.fairchildsemi.com/ds/1N%2F1N4148.pdf D]&lt;br /&gt;
|-&lt;br /&gt;
| BAT46&lt;br /&gt;
| 0,11&lt;br /&gt;
| Kleinsignal-Schottky-Diode&lt;br /&gt;
|&lt;br /&gt;
| R&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| SB140&lt;br /&gt;
|&lt;br /&gt;
| Schottky-Diode&lt;br /&gt;
| 1A 40V&lt;br /&gt;
| R&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| BA159&lt;br /&gt;
| 0,02&lt;br /&gt;
| Standard-Diode&lt;br /&gt;
| HF 1A 1000V&lt;br /&gt;
| R&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Instrumentenverstärker ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| INA128&lt;br /&gt;
| 6,15 (R)&lt;br /&gt;
| Verstärkung über 1 Widerstand einstellbar&lt;br /&gt;
| Brückenverstärker , Datenerfassung&lt;br /&gt;
| R,F&lt;br /&gt;
| [http://focus.ti.com/lit/ds/symlink/ina128.pdf#search=%22ina128%22 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Operationsverstärker ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| LM358&lt;br /&gt;
| 0,09&lt;br /&gt;
| Single Supply&lt;br /&gt;
| 2-fach Standard-OP&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=lm358 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM324&lt;br /&gt;
| 0,13&lt;br /&gt;
| Single Supply&lt;br /&gt;
| 4-fach Standard-OP&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=lm324 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM393&lt;br /&gt;
| 0,10&lt;br /&gt;
| Single Supply&lt;br /&gt;
| 2-fach Standard-Komparator&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=lm393 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM339&lt;br /&gt;
| 0,10&lt;br /&gt;
| Single Supply&lt;br /&gt;
| 4-fach Standard-Komparator&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=lm339 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| NE5532&lt;br /&gt;
| 0,23&lt;br /&gt;
| 2 * Audio OP&lt;br /&gt;
| kann 600 Ohm treiben&lt;br /&gt;
| alle?&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=NE5532 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Spannungsregler ===&lt;br /&gt;
Linearregler&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;linearregler&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| LP2950&lt;br /&gt;
| 0,39 - 0,53&lt;br /&gt;
| Festspannungsregler Low-Dropout&lt;br /&gt;
| 3 - 5V 100mA, TO-92&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LP2950 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM317&lt;br /&gt;
| 0,22&lt;br /&gt;
| Linearer einstellbarer Spannungsregler&lt;br /&gt;
| max 40V -&amp;gt; 1,2 - 37V, max 1.5A, TO220&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LM317 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| MAX663&lt;br /&gt;
| 1,80&lt;br /&gt;
| Linearer, einstellbarer Spannungsregler&lt;br /&gt;
| sehr niedriger Eigenstromverbrauch&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=MAX663 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
Schaltregler&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;schaltregler&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| LM2576&lt;br /&gt;
| 1,60&lt;br /&gt;
| Step-Down&lt;br /&gt;
| max 40V -&amp;gt; 1,2 - 37V, max 3A, TO220-5&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LM2576 PDF] - [http://www.mikrocontroller.net/topic/58094#450561 mit Funk-Entstördrossel FED100µ (Reichelt...) bis 3 A]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Digital ==&lt;br /&gt;
=== CAN ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;can&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| MCP2515&lt;br /&gt;
| 1,95&lt;br /&gt;
| SPI-CAN 2.0B Baustein&lt;br /&gt;
| &lt;br /&gt;
| Reichelt&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
| SJA1000&lt;br /&gt;
| 4,55&lt;br /&gt;
| PellCAN 2.0B 1Mbit/s&lt;br /&gt;
|&lt;br /&gt;
| Reichelt&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Logik ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| 74HC4050&lt;br /&gt;
| 0,27&lt;br /&gt;
| z.B. 5V =&amp;gt; 3V&lt;br /&gt;
| Pegelwandler unidirektional abwärts&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=74hc4050 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== USB ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;usb&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| FT232&lt;br /&gt;
| 5,65&lt;br /&gt;
| USB &amp;lt;-&amp;gt; RS232 Wandler&lt;br /&gt;
| Zugriff über virtuellen COM Port&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=ft232 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| FT245&lt;br /&gt;
| 6,35&lt;br /&gt;
| USB &amp;lt;-&amp;gt; Seriell Wandler mit paralleler Schnittstelle&lt;br /&gt;
| Zugriff über virtuellen COM Port&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=ft245 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Treiber ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| ULN2003A&lt;br /&gt;
| 0,17&lt;br /&gt;
| 7-fach Low-Side Treiber&lt;br /&gt;
| 50V/500mA&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=ULN2003 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| ULN2803A&lt;br /&gt;
| 0,44&lt;br /&gt;
| 8-fach Low-Side Treiber&lt;br /&gt;
| 50V/500mA&lt;br /&gt;
| alle&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=ULN2803 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| UDN2981&lt;br /&gt;
| 1,50&lt;br /&gt;
| 8-fach High-Side Treiber&lt;br /&gt;
| 50V/500mA&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=UDN2981 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| ICL7667&lt;br /&gt;
| 1&lt;br /&gt;
| Dual inverting FET Treiber&lt;br /&gt;
| 18V, 20ns@1nF&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=ICL7667 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Optokoppler ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| CNY17&lt;br /&gt;
| 0,17&lt;br /&gt;
| billig&lt;br /&gt;
| Standardtyp&lt;br /&gt;
| R,C&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=CNY17 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| 6N137&lt;br /&gt;
| 0,49&lt;br /&gt;
| Logikausgang&lt;br /&gt;
| sehr schnell&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=6N137 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Converter ==&lt;br /&gt;
=== ADC ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
=== DAC ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
== Sensoren (aktiv) ==&lt;br /&gt;
=== [[Temperatursensor|Temperatur]] ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| LM75&lt;br /&gt;
| ~2,10&lt;br /&gt;
| Temperatursensor mit I²C (TWI) Bus Interface (3.3V und 5V Version) (SMD)&lt;br /&gt;
| &lt;br /&gt;
| R D&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LM75 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| DS1621&lt;br /&gt;
| ~5&lt;br /&gt;
| Temperatursensor mit I²C (TWI) Bus Interface (wie LM75, kein SMD)&lt;br /&gt;
| &lt;br /&gt;
| C&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
| DS18B20&lt;br /&gt;
| 4,30&lt;br /&gt;
| Temperatursensor mit 1-Wire Interface&lt;br /&gt;
|&lt;br /&gt;
| R D&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=DS18B20 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM35&lt;br /&gt;
| 1,49&lt;br /&gt;
| Analoger Temperatursensor&lt;br /&gt;
| 10mV/°C absolut&lt;br /&gt;
| D&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LM35 PDF]&lt;br /&gt;
|-&lt;br /&gt;
| LM335&lt;br /&gt;
| 0,87&lt;br /&gt;
| Analoger Temperatursensor&lt;br /&gt;
| 10mV/K absolut&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q=LM335 PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
Wenn man z.B. einen Übertemperaturschutz (oder eine andere Schaltung, bei der es nur eine Schaltschwelle gibt) bauen will, dann empfiehlt sich die Verwendung eines NTCs. Dessen Kennlinie ist gegenüber den Kennlinien von z.B. LM335 dahingehend im Vorteil, dass eine geringe Temperaturänderung besser messbar ist.&lt;br /&gt;
&lt;br /&gt;
= Passive Bauelemente =&lt;br /&gt;
== Sensoren (passiv) ==&lt;br /&gt;
=== Licht ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
=== [[Temperatursensor|Temperatur]] ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| KTY81&lt;br /&gt;
| ~0,50&lt;br /&gt;
| nichtlinear, bis 150°C&lt;br /&gt;
| in &amp;amp;#956;C Schaltungen&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat/datasheets/KTY84_SERIES_5.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| KTY84&lt;br /&gt;
| 0,72&lt;br /&gt;
| nichtlinear, bis 300°C&lt;br /&gt;
| in &amp;amp;#956;C Schaltungen&lt;br /&gt;
| R&lt;br /&gt;
| [http://www.semiconductors.philips.com/acrobat/datasheets/KTY84_SERIES_5.pdf PDF]&lt;br /&gt;
|-&lt;br /&gt;
| PT100&lt;br /&gt;
| ab 3,00&lt;br /&gt;
| lineare Kennlinie&lt;br /&gt;
| analoge Messschaltungen&lt;br /&gt;
| F&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Widerstände ===&lt;br /&gt;
Mit einem Widerstandssortiment, welches die E12-Werte enthält, kann man normalerweise nicht falsch liegen. Denn früher oder später benötigt man jeden Widerstandswert der E12-Reihe einmal.&lt;br /&gt;
&lt;br /&gt;
=== Kondensatoren ===&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;sortable&amp;quot; id=&amp;quot;opamps&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Preis (&amp;amp;euro;)&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anwendungen&lt;br /&gt;
! Lieferant&lt;br /&gt;
! Datenblatt&lt;br /&gt;
|-&lt;br /&gt;
| 100nF Keramik&lt;br /&gt;
| ~0.05&lt;br /&gt;
| &lt;br /&gt;
| Als sogenannter Abblockkondensator zwischen VCC und GND vor allem bei Digital-ICs zwingend erforderlich, schadet aber auch bei den meisten Analog-ICs nicht.&lt;br /&gt;
| &lt;br /&gt;
| [http://www.datasheetarchive.com/search.php?q= PDF]&lt;br /&gt;
|-&lt;br /&gt;
| 100nF Keramik SMD 0603&lt;br /&gt;
| ~0.01 (bei 100 Stück)&lt;br /&gt;
| SMD 0603&lt;br /&gt;
| Als sogenannter Abblockkondensator zwischen VCC und GND vor allem bei Digital-ICs zwingend erforderlich, schadet aber auch bei den meisten Analog-ICs nicht.&lt;br /&gt;
| D&lt;br /&gt;
| [http://www.google.de/search?num=100&amp;amp;hl=de&amp;amp;q=datasheet+0603+chip-capacitors+filetype%3Apdf&amp;amp;btnG=Suche&amp;amp;meta=lr%3Dlang_de%7Clang_en PDF]&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Lieferanten =&lt;br /&gt;
C: Conrad [http://www.conrad.de www.conrad.de]&lt;br /&gt;
&lt;br /&gt;
D: CSD-Electronics [http://www.csd-electronics.de www.csd-electronics.de] &lt;br /&gt;
&lt;br /&gt;
F: Farnell (nur Firmen &amp;amp; Studenten) [http://www.farnell.de www.farnell.de]&lt;br /&gt;
&lt;br /&gt;
P: Pollin [http://www.pollin.de www.pollin.de]&lt;br /&gt;
&lt;br /&gt;
R: Reichelt [http://www.reichelt.de www.reichelt.de]&lt;br /&gt;
&lt;br /&gt;
Allgemeine Lieferantenliste: [http://www.mikrocontroller.net/articles/Elektronik-Versender Elektronik-Versender]&lt;br /&gt;
&lt;br /&gt;
[[Category:Bauteile]]&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Diskussion:SMD_L%C3%B6ten&amp;diff=16321</id>
		<title>Diskussion:SMD Löten</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Diskussion:SMD_L%C3%B6ten&amp;diff=16321"/>
		<updated>2006-08-02T14:31:34Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: Alternative zu Entlötlitze&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Diskussion:Part-db_Lagerverwaltung&amp;diff=11617</id>
		<title>Diskussion:Part-db Lagerverwaltung</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Diskussion:Part-db_Lagerverwaltung&amp;diff=11617"/>
		<updated>2006-03-03T15:21:50Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;hi,&lt;br /&gt;
&lt;br /&gt;
ich weiß nicht ob dieser beitrag hier so sinnvoll ist, &lt;br /&gt;
auf http://www.roboternetz.de/wissen/index.php/Part-DB_%28Lagerverwaltung%29 wurde er auch so gepostet und steht zur löschung in frage&lt;br /&gt;
&lt;br /&gt;
die qualität der software ist sehr fraglich, sie kommt nicht einmal mit anführungszeichen richtig zurecht. ein impressum gibts nicht auf der quellseite seite auch nicht, nur ein totes bild&lt;br /&gt;
&lt;br /&gt;
--[[Benutzer:Nollsen|Nollsen]] 16:21, 3. M?2006 (CET)&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=HD44780&amp;diff=6110</id>
		<title>HD44780</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=HD44780&amp;diff=6110"/>
		<updated>2005-04-09T08:18:16Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Der HD44780 ist ein Displaytreiber für Text-Displays. Praktisch alle Text-Displays werden mit diesem oder einem kompatiblen Controller angesteuert. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=allgemeine Ansteuerung=&lt;br /&gt;
==Pinbelegung==&lt;br /&gt;
{|&lt;br /&gt;
!Pin || Funktion || Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
|1 || | VSS || Versorgungsspannung GND&lt;br /&gt;
|-&lt;br /&gt;
|2 || | VCC || Versorungsspannung, meistens 5V, je nach genauem Typ unterschiedlich&lt;br /&gt;
|-&lt;br /&gt;
|3 || | Kontrastspannung ||Spannung zwischen VSS und VCC, kann auf &lt;br /&gt;
|-&lt;br /&gt;
|4 || | RS || Registerauswahl; 0 = Befehlsregister, 1 = Datenregister &lt;br /&gt;
|-&lt;br /&gt;
|5 || | R/W || Lese oder Schreibzugriff, 0 = Schreiben, 1 = Lesen, kann meistens auf GND gezogen werden&lt;br /&gt;
|-&lt;br /&gt;
|6 || | E || Taktleitung&lt;br /&gt;
|-&lt;br /&gt;
|7 || | DB0 || Datenleitung&lt;br /&gt;
|-&lt;br /&gt;
|8 || |DB1 || Datenleitung&lt;br /&gt;
|-&lt;br /&gt;
|9 || |DB2 || Datenleitung&lt;br /&gt;
|-&lt;br /&gt;
|10 || |DB3 || Datenleitung&lt;br /&gt;
|-&lt;br /&gt;
|11 || |DB4 || Datenleitung&lt;br /&gt;
|-&lt;br /&gt;
|12 || |DB5 || Datenleitung&lt;br /&gt;
|-&lt;br /&gt;
|13 || |DB6 || Datenleitung&lt;br /&gt;
|-&lt;br /&gt;
|14 || |DB7 || Datenleitung&lt;br /&gt;
|}&lt;br /&gt;
==Speicher==&lt;br /&gt;
Ein HD44780 besitzt mehrere Speicher:&lt;br /&gt;
===DDRAM (Display Data RAM)===&lt;br /&gt;
In das DDRAM werden die anzuzeigenden Daten eingeschrieben. &lt;br /&gt;
&lt;br /&gt;
===CGROM (Character Generator ROM)===&lt;br /&gt;
Dieser ROM enthält die Zeichen in Form von 5x8 oder 5x10 Punktmatrizen. Er kann nicht geändert werden, außer man sendet einen EEPROM zu Hitachi für eine Massenproduktion.&lt;br /&gt;
&lt;br /&gt;
===CGRAM (Character Generator RAM)===&lt;br /&gt;
In diesem RAM können acht 5x8 Pixel oder vier 5x10 Pixel große benutzerdefinierte Zeichen abgelegt werden. &lt;br /&gt;
Wenn keine benutzerdefinierte Zeichen gebraucht werden, kann dieser Bereich als Auslagerungsspeicher benutzt werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Kommandos==&lt;br /&gt;
=Ansteuerung durch den AVR=&lt;br /&gt;
==Fertige Projekte oder Bibliotheken==&lt;br /&gt;
* Peter Fleurys [http://homepage.sunrise.ch/mysunrise/peterfleury/avr-software.html LCD library for HD44870 based LCDs]&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=HD44780&amp;diff=6048</id>
		<title>HD44780</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=HD44780&amp;diff=6048"/>
		<updated>2005-04-07T12:49:22Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Der HD44780 ist ein Displaytreiber für Text-Displays. Praktisch alle Text-Displays werden mit diesem Controller angesteuert. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=allgemeine Ansteuerung=&lt;br /&gt;
==Pinbelegung==&lt;br /&gt;
{|&lt;br /&gt;
!Pin || Funktion || Beschreibung&lt;br /&gt;
|-&lt;br /&gt;
|1 || | VSS || Versorgungsspannung GND&lt;br /&gt;
|-&lt;br /&gt;
|2 || | VCC || Versorungsspannung, meistens 5V, je nach genauem Typ unterschiedlich&lt;br /&gt;
|-&lt;br /&gt;
|3 || | Kontrastspannung ||Spannung zwischen VSS und VCC, kann auf &lt;br /&gt;
|-&lt;br /&gt;
|4 || | RS || Registerauswahl; 0 = Befehlsregister, 1 = Datenregister &lt;br /&gt;
|-&lt;br /&gt;
|5 || | R/W || Lese oder Schreibzugriff, 0 = Schreiben, 1 = Lesen, kann meistens auf GND gezogen werden&lt;br /&gt;
|-&lt;br /&gt;
|6 || | E || Taktleitung&lt;br /&gt;
|-&lt;br /&gt;
|7 || | DB0 || Datenleitung&lt;br /&gt;
|-&lt;br /&gt;
|8 || |DB1 || Datenleitung&lt;br /&gt;
|-&lt;br /&gt;
|9 || |DB2 || Datenleitung&lt;br /&gt;
|-&lt;br /&gt;
|10 || |DB3 || Datenleitung&lt;br /&gt;
|-&lt;br /&gt;
|11 || |DB4 || Datenleitung&lt;br /&gt;
|-&lt;br /&gt;
|12 || |DB5 || Datenleitung&lt;br /&gt;
|-&lt;br /&gt;
|13 || |DB6 || Datenleitung&lt;br /&gt;
|-&lt;br /&gt;
|14 || |DB7 || Datenleitung&lt;br /&gt;
|}&lt;br /&gt;
==Kommandos==&lt;br /&gt;
=Ansteuerung durch den AVR=&lt;br /&gt;
==Fertige Projekte oder Bibliotheken==&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Drehgeber&amp;diff=14344</id>
		<title>Drehgeber</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Drehgeber&amp;diff=14344"/>
		<updated>2005-04-02T11:37:11Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: Link für Gray-Code erstellt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Drehgeber (auch Inkrementaldrehgeber, Quadraturencoder, Drehencoder, Drehimpulsgeber genannt) erzeugen bei Drehung der Achse an den zwei Datenleitungen am Ausgang ein sogenanntes [[Gray-Code]]-Signal. Der Vorteil dieser Codierung ist, dass ein [[Entprellung|Entprellen]] in der Regel überflüssig ist.&lt;br /&gt;
&lt;br /&gt;
== Signalauswertung ==&lt;br /&gt;
&lt;br /&gt;
Die Auswertung eines Drehgebers macht man am besten in einem Timer-Interrupt, der mit einer festen Frequenz ausgeführt wird (je höher, desto besser).&lt;br /&gt;
&lt;br /&gt;
=== Beispielcode in C ===&lt;br /&gt;
&lt;br /&gt;
* http://dse-faq.elektronik-kompendium.de/dse-faq.htm#F.29&lt;br /&gt;
* http://www.mikrocontroller.net/forum/read-4-37992.html&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR-GCC-Tutorial&amp;diff=5724</id>
		<title>AVR-GCC-Tutorial</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR-GCC-Tutorial&amp;diff=5724"/>
		<updated>2005-03-06T07:56:47Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: /* Wie funktioniert nun der Watchdog */Timeoutwerte eingetragen&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:AVR]]&lt;br /&gt;
&lt;br /&gt;
= Vorwort =&lt;br /&gt;
&lt;br /&gt;
Dieses Tutorial soll den Einstieg in die Programmierung von Atmel AVR-Mikrocontroller in der Programmiersprache [[C]] mit dem freien (&amp;quot;kostenlosen&amp;quot;) C-Compiler avr-gcc erleichtern.&lt;br /&gt;
&lt;br /&gt;
Die ursprüngliche Version stammt von Christian Schifferle, die meisten aktuellen Anpassungen von [[Benutzer:Mthomas]]. Viele der im Original-Dokument verwendeten Funktionen (z.B. sbi(), cbi(), outp(), inp()) sind in aktuellen Versionen des [[AVR-GCC|avr-gcc]] C-Compilers und der Laufzeitbibliothek avr-libc nicht mehr enthalten. &lt;br /&gt;
Dieses Tutorial wurde an die neuen Funktionen/Methoden angepasst. &lt;br /&gt;
&lt;br /&gt;
In diesem Text wird häufig auf die Standardbibliothek für den avr-gcc-Compiler, die avr-libc, verwiesen. Die online-Version der &#039;&#039;&#039;avr-libc Dokumentation&#039;&#039;&#039; findet sich [http://www.nongnu.org/avr-libc/user-manual/index.html hier]. Bei [[WinAVR]] gehört die Dokumentation zum Lieferumfang und wird mitinstalliert. &amp;lt;!-- Sollte die Dokumentation zeitweise nicht online verfügbar sein, kann diese &#039;&#039;&#039;[[Media:avr-libc User Manual PDF|hier als PDF-Datei]]&#039;&#039;&#039; (Stand Version 1.0.4) heruntergeladen werden.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Benötigte Werkzeuge =&lt;br /&gt;
&lt;br /&gt;
Um eigene Programme für AVRs mittels avr-gcc/avr-libc zu erstellen und zu testen, wird folgende Hard- und Software benötigt:&lt;br /&gt;
&lt;br /&gt;
* Testboard für die Aufnahme eines AVR Controllers, der vom avr-gcc Compiler unterstützt wird (alle ATmegas und die meisten AT90, siehe Dokumentation der avr-libc für unterstütze Typen). Dieses Testboard kann durchaus auch selbst gelötet oder auf einem Steckbrett aufgebaut werden. Einige Registerbeschreibungen dieses Tutorials beziehen sich auf den inzwischen veralteten AT90S2313. Der weitaus größte Teil des Textes ist aber für alle Controller der AVR-Familie gültig. Brauchbare Testplattform sind auch das [[STK500]] und der [[AVR Butterfly]] von Atmel.&lt;br /&gt;
* Der avr-gcc Compiler und die avr-libc. Kostenlos erhältlich für nahezu alle Plattformen/Betriebssysteme. Für MS-Windows im Paket [[WinAVR]]; für Unix/Linux siehe auch Hinweise im Artikel [[AVR-GCC]].&lt;br /&gt;
* Programmiersoftware und -hardware z.B. PonyProg (siehe auch: [[Pony-Prog Tutorial]]) oder [[AVRDUDE]] mit [[STK200]]-Dongle oder die von Atmel verfügbare Hard- und Software ([[STK500]], Atmel AVRISP, [[AVR-Studio]]). &lt;br /&gt;
* Nicht unbedingt erforderlich, aber zur Simulation und zum Debuggen unter MS-Windows recht nützlich: [[AVR-Studio]] (siehe Abschnitt [[AVR-GCC-Tutorial#Exkurs: makefiles|Exkurs: makefiles]]).&lt;br /&gt;
&lt;br /&gt;
= Was tun, wenn&#039;s nicht &amp;quot;klappt&amp;quot;? =&lt;br /&gt;
&lt;br /&gt;
* Herausfinden, ob es tatsächlich ein avr(-gcc) spezifisches Problem ist oder die C-Kenntnisse einer Auffrischung bedürfen. Allgemeine C-Fragen kann man eventuell &amp;quot;beim freundlichen Programmierer zwei Büro-, Zimmer- oder Haustüren weiter&amp;quot; loswerden. Ansonsten: [[C]]-Buch (gibt&#039;s auch &amp;quot;gratis&amp;quot; online) lesen.&lt;br /&gt;
* Die [http://www.nongnu.org/avr-libc/user-manual/index.html Dokumentation der avr-libc] lesen, vor allem (aber nicht nur) den Abschnitt Related Pages/Frequently Asked Questions = Oft gestellte Fragen (und Antworten dazu). Z.Zt leider nur in englischer Sprache verfügbar.&lt;br /&gt;
* Den Artikel [[AVR-GCC]] in diesem Wiki lesen.&lt;br /&gt;
* Das gcc-Forum auf [http://www.mikrocontroller.net www.mikrocontroller.net] nach vergleichbaren Problemen absuchen.&lt;br /&gt;
* Das avr-gcc-Forum bei [http://www.avrfreaks.net avrfreaks] nach vergleichbaren Problemen absuchen.&lt;br /&gt;
* Das [http://lists.gnu.org/archive/html/avr-gcc-list/ Archiv der avr-gcc Mailing-Liste] nach vergleichbaren Problemen absuchen.&lt;br /&gt;
* Nach Beispielcode suchen. Vor allem in der Academy von [http://www.avrfreaks.net AVRFREAKS] (anmelden).&lt;br /&gt;
* Google oder alltheweb befragen schadet nie.&lt;br /&gt;
* Bei Problemen mit der Ansteuerung interner AVR-Funktionen mit C-Code: das Datenblatt des Controllers lesen (ganz und am Besten zweimal)&lt;br /&gt;
* einen Beitrag in eines der Foren oder eine Mail an die Mailing-Liste schreiben. Dabei möglichst viel Information geben: Controller, Compilerversion, genutzte Bibliotheken, Ausschnitte aus dem Quellcode, genaue Fehlermeldungen bzw. Beschreibung des Fehlverhaltens. Bei Ansteuerung externer Geräte die Beschaltung beschreiben oder skizzieren (z.B. mit [http://www.tech-chat.de/ Andys ASCII Circuit]). Siehe dazu auch: [http://www.lugbz.org/documents/smart-questions_de.html &amp;quot;Wie man Fragen stellt&amp;quot;].&lt;br /&gt;
&lt;br /&gt;
= Exkurs: makefiles =&lt;br /&gt;
&lt;br /&gt;
Wenn man bisher gewohnt ist, mit integrierten Entwicklungsumgebung à la Visual-C Programme zu erstellen, wirkt das makefile-Konzept auf den ersten Blick etwas kryptisch. Nach kurzer Einarbeitung ist diese Vorgehensweise jedoch sehr praktisch. Diese Dateien (üblicher Name: &#039;Makefile&#039; ohne Dateiendung) dienen der Ablaufsteuerung des Programms make, das auf allen Unix/Linux-Systemen installiert sein sollte, und in einer Fassung fuer MS-Windows auch in [[WinAVR]] (Unterverzeichnis utils/bin) enthalten ist.&lt;br /&gt;
&lt;br /&gt;
Im Unterverzeichnis &#039;&#039;sample&#039;&#039; einer WinAVR-Installation findet man eine sehr brauchbare Vorlage, die sich einfach an das eigene Projekt anpassen lässt ([[Media:Makefile|lokale Kopie Stand Sept. 2004]]). Wahlweise kann man auch [http://www.sax.de/~joerg/mfile/ mfile] von Jörg Wunsch nutzen. mfile erzeugt ein makefile nach Einstellungen in einer grafischen Nutzeroberfläche, wird bei WinAVR mitinstalliert, ist aber als TCL/TK-Programm auf nahezu allen Platformen lauffähig.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Die folgenden Ausführungen beziehen sich auf das WinAVR Beispiel-Makefile.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Ist im Makefile alles richtig eingestellt genügt es, sich drei Parameter zu merken, die über die shell bzw. die Windows-Kommandozeile (cmd.exe/command.com) als Parameter an &amp;quot;make&amp;quot; übergeben werden. Das Programm make sucht sich &amp;quot;automatisch&amp;quot; das makefile im aktuellen Arbeitsverzeichnis und führt die darin definierten Operationen für den entsprechenden Aufrufparameter durch.&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
| &#039;&#039;make all&#039;&#039;&lt;br /&gt;
| Erstellt aus den in im makefile angegebenen Quellcodes eine &#039;&#039;hex&#039;&#039;-Datei (und ggf. auch &#039;&#039;eep&#039;&#039;-Datei).&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;make program&#039;&#039;&lt;br /&gt;
| Überträgt die hex-Datei (und wahlweise auch die eep-Datei für den EEPROM) zum AVR. &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;make clean&#039;&#039;&lt;br /&gt;
| löscht alle temporären Dateien, also auch die hex-Datei&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Diese Aufrufe können in die allermeisten Editoren in &amp;quot;Tool-Menüs&amp;quot; eingebunden werden. Dies erspart den Kontakt mit der Kommandozeile. (Bei WinAVR sind die Aufrufe bereits im Tools-Menü des mitgelieferten Editors Programmers-Notepad eingefügt.)&lt;br /&gt;
&lt;br /&gt;
Üblicherweise sind folgende Daten im makefile anzupassen:&lt;br /&gt;
* Controllertyp&lt;br /&gt;
* Quellcode-Dateien (c-Dateien)&lt;br /&gt;
* Typ und Anschluss des Programmiergeräts&lt;br /&gt;
&lt;br /&gt;
seltener sind folgende Einstellungen durchzuführen:&lt;br /&gt;
* Grad der Optimierung&lt;br /&gt;
* Methode zur Erzeugung der Debug-Symbole (Debug-Format)&lt;br /&gt;
* Assembler-Quellcode-Dateien (S-Dateien)&lt;br /&gt;
&lt;br /&gt;
Die in den folgenden Unterabschnitten gezeigten makefile-Ausschnitte sind für ein Programm, das auf einem ATmega8 ausgeführt werden soll. Der Quellcode besteht aus den c-Dateien superprog.c (darin main()), uart.c, lcd.c und 1wire.c. Im Quellcodeverzeichnis befinden sich diese Dateien: superprog.c, uart.h, uart.c, lcd.h, lcd.c, 1wire.h, 1wire.c und das makefile (die angepasste Kopie des WinAVR-Beispiels).&lt;br /&gt;
&lt;br /&gt;
Der Controller wird mittels [[AVRDUDE]] über ein [[STK200]]-Programmierdongle an der Schnittstelle lpt1 (bzw. /dev/lp0) programmiert. Im Quellcode sind auch Daten für die &#039;&#039;section .eeprom&#039;&#039; definiert (siehe Abschnitt Speicherzugriffe TODO: nach unten verlinken), diese sollen beim Programmieren gleich mit ins EEPROM geschrieben werden. &lt;br /&gt;
&lt;br /&gt;
== Controllertyp setzen ==&lt;br /&gt;
&lt;br /&gt;
Dazu wird die &amp;quot;make-Variable&amp;quot; MCU entsprechend dem Namen des verwendeten Controllers gesetzt. Ein Liste der von avr-gcc und der avr-libc untersützten Typen findet sich in der [http://www.nongnu.org/avr-libc/user-manual/index.html Dokumentation der avr-libc].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
# Kommentare in Makefiles beginnen mit einem Doppelkreuz &lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# ATmega8 at work&lt;br /&gt;
MCU = atmega8&lt;br /&gt;
# oder MCU = atmega16 &lt;br /&gt;
# oder MCU = at90s8535&lt;br /&gt;
# oder ...&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Quellcode-Dateien einstellen ==&lt;br /&gt;
&lt;br /&gt;
Den Namen der Quellcodedatei welche die Funktion main enthält, wird hinter TARGET eingetragen. Dies jedoch ohne die Endung &#039;&#039;.c&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
TARGET = superprog&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Besteht das Projekt wie im Beispiel aus mehr als einer Quellcodedatei, sind die weiteren c-Dateien (nicht die Header-Dateien, vgl. [[Include-Files (C)]]) durch Leerzeichen getrennt bei SRC einzutragen. Die bei TARGET definierte Datei ist schon in der SRC-Liste enthalten. Diesen Eintrag nicht löschen!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
SRC = $(TARGET).c uart.c lcd.c 1wire.c &lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternativ kann man die Liste der Quellcodedateien auch mit dem Operator += erweitern.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
SRC = $(TARGET).c uart.c 1wire.c&lt;br /&gt;
# lcd-Code fuer Controller xyz123 (auskommentiert)&lt;br /&gt;
# SRC += lcd_xyz.c&lt;br /&gt;
# lcd-Code fuer &amp;quot;Standard-Controller&amp;quot; (genutzt)&lt;br /&gt;
SRC += lcd.c&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmiergerät einstellen ==&lt;br /&gt;
&lt;br /&gt;
Die Vorlagen sind auf die Programmiersoftware [[AVRDUDE]] angepasst, jedoch lässt sich auch andere Programmiersoftware einbinden, sofern diese über Kommandozeile gesteuert werden kann (z.B. stk500.exe, uisp, sp12).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
# Einstellung fuer STK500 an com1 (auskommentiert)&lt;br /&gt;
# AVRDUDE_PROGRAMMER = stk500&lt;br /&gt;
# com1 = serial port. Use lpt1 to connect to parallel port.&lt;br /&gt;
# AVRDUDE_PORT = com1    # programmer connected to serial device&lt;br /&gt;
&lt;br /&gt;
# Einstellung fuer STK200-Dongle an lpt1&lt;br /&gt;
AVRDUDE_PROGRAMMER = stk200&lt;br /&gt;
AVRDUDE_PORT = lpt1&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sollen Flash(=.hex) und EEPROM(=.eep) zusammen auf den Controller programmiert werden, ist das Kommentarzeichen vor AVRDUDE_WRITE_EEPROM zu löschen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
#Auskommentiert: EERPOM-Inhalt wird nicht mitgeschrieben&lt;br /&gt;
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep&lt;br /&gt;
&lt;br /&gt;
#Nich-auskommentiert EERPOM-Inhalt wird mitgeschrieben&lt;br /&gt;
AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
&lt;br /&gt;
Die Eingabe von &#039;&#039;make all&#039;&#039; im Arbeitsverzeichnis mit dem makefile und den Quellcodedateien erzeugt (unter anderem) die Dateien superprog.hex und superprog.eep. Abhängigkeiten zwischen den einzelnen c-Dateien werden dabei automatisch berücksichtigt. Die &#039;&#039;superprog.hex&#039;&#039; und &#039;&#039;superprog.eep&#039;&#039; werden mit &#039;&#039;make program&#039;&#039; zum Controller  übertragen. Mit &#039;&#039;make clean&#039;&#039; werden alle temporären Dateien gelöscht (=&amp;quot;aufgeräumt&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
== Sonstige Einstellungen ==&lt;br /&gt;
&lt;br /&gt;
=== Optimierungsgrad ===&lt;br /&gt;
&lt;br /&gt;
Der gcc-Compiler kennt verschiedene Stufen der Optimierung. Nur zu Testzwecken sollte die Optimierung ganz deaktiviert werden (&#039;&#039;OPT = 0&#039;&#039;). Die weiteren möglichen Optionen weisen den Compiler an, möglichst kompakten oder möglichst schnellen Code zu erzeugen. In den weitaus meisten Fällen ist &#039;&#039;OPT = s&#039;&#039; die optimale (sic) Einstellung, damit wird kompakter und oft auch der &amp;quot;schnellste&amp;quot; Maschinencode erzeugt.&lt;br /&gt;
&lt;br /&gt;
=== Debug-Format ===&lt;br /&gt;
&lt;br /&gt;
Unterstützt werden die Formate stabs und dwarf-2. Das Format wir hinter &#039;&#039;DEBUG =&#039;&#039; eingestellt. Siehe dazu Abschnitt &#039;&#039;Eingabedateien zur Simulation&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Assembler-Dateien ===&lt;br /&gt;
&lt;br /&gt;
Die im Projekt genutzten Assembler-Dateien werden hinter ASRC durch Leerzeichen getrennt aufgelistet. Assembler-Dateien haben immer die Endung .S (grosses S). Ist zum Beispiel der Assembler-Quellcode eines Software-UARTs in einer Datei softuart.S enthalten lautet die Zeile: &#039;&#039;ASRC = softuart.S&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Eingabedateien zur Simulation in AVR-Studio ==&lt;br /&gt;
&lt;br /&gt;
Mit älteren AVR-Studio-Versionen kann man nur auf Grundlage sogenannter &#039;&#039;coff&#039;&#039;-Dateien simulieren. Neuere Versionen von AVR-Studio (ab 4.10.356) unterstützen zudem das modernere aber noch experimentelle dwarf-2-Format, das ab WinAVR 20040722 (avr-gcc 3.4.1/Binutils inkl. Atmel add-ons) &amp;quot;direkt&amp;quot; vom Compiler erzeugt wird.&lt;br /&gt;
&lt;br /&gt;
; Vorgehensweise bei extcoff:&lt;br /&gt;
* im Makefile bei DEBUG: &amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;DEBUG=stabs&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;make extcoff&#039;&#039; (evtl. vorher &#039;&#039;make clean&#039;&#039;)&lt;br /&gt;
* die erzeugte &#039;&#039;cof&#039;&#039;-Datei (im Beispiel oben &#039;&#039;superprog.cof&#039;&#039;) in AVR-Studio laden&lt;br /&gt;
* AVR-Simulator und zu simulierenden Controller wählen, &amp;quot;Finish&amp;quot;&lt;br /&gt;
* weiteres siehe AVR-Studio Online-Hilfe&lt;br /&gt;
&lt;br /&gt;
; Vorgehensweise bei dwarf-2:&lt;br /&gt;
* im Makefile bei DEBUG: &amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;DEBUG=dwarf-2&amp;lt;/pre&amp;gt;&lt;br /&gt;
* &#039;&#039;make all&#039;&#039; (evtl. vorher &#039;&#039;make clean&#039;&#039;)&lt;br /&gt;
* die erzeugte &#039;&#039;elf&#039;&#039;-Datei (im Beispiel oben &#039;&#039;superprog.elf&#039;&#039;) in AVR-Studio laden&lt;br /&gt;
* AVR-Simulator und zu simulierenden Controller wählen, &amp;quot;Finish&amp;quot;&lt;br /&gt;
* weiteres siehe AVR-Studio Online-Hilfe&lt;br /&gt;
&lt;br /&gt;
Beim Simulieren scheinen oft &amp;quot;Variablen zu fehlen&amp;quot;. Ursache dafür ist, dass der Compiler die &amp;quot;Variablen&amp;quot; direkt Registern zuweist. Dies kann vermieden werden, indem die Optimierung abgeschaltet wird (im makefile). Man simuliert dann jedoch ein vom optimierten Code stark abweichendes Programm. Das Abschalten der Optimierung wird nicht empfohlen.&lt;br /&gt;
&lt;br /&gt;
Statt des Software-Simulators kann das AVR-Studio auch genutzt werden, um mit dem ATMEL JTAGICE, ein Nachbau davon (BootICE, Evertool o.ä.) oder dem ATMEL JTAGICE MKII &amp;quot;im System&amp;quot; zu debuggen. Dazu sind keine speziellen Einstellungen im makefile erforderlich. Debugging bzw. &amp;quot;In-System-Emulation&amp;quot; mit dem JTAGICE und JTAGICE MKII sind in der AVR-Studio Online-Hilfe beschrieben.&lt;br /&gt;
&lt;br /&gt;
= Ganzzahlige (Integer) Datentypen =&lt;br /&gt;
&lt;br /&gt;
Bei der Programmierung von Mikrokontrollern ist die Definition einiger ganzzahliger Datentypen sinnvoll, an denen eindeutig die Bit-Länge abgelesen werden kann.&lt;br /&gt;
&lt;br /&gt;
== Selbstdefinierte (nicht-standardisierte) ganzzahlige Datentypen ==&lt;br /&gt;
&lt;br /&gt;
Bei den im folgenden genannten Typdefinitionen ist zu beachten, dass die Bezeichnungen für &amp;quot;Worte&amp;quot; teilweise je nach Prozessorplattform unterschiedlich verwendet werden. Die angegebenen Definitionen beziehen sich auf die im Zusammenhang mit AVR/8-bit-Controllern üblichen &amp;quot;Bit-Breiten&amp;quot; (In Erläuterungen zum ARM7TDMI z.B. werden oft 32-bit Integer mit &amp;quot;Wort&amp;quot; ohne weitere Ergänzung bezeichnet). Es empfiehlt sich daher, die im nachfolgenden Abschnitt beschriebenen &#039;&#039;standardisierten ganzzahligen Datentypen&#039;&#039; zu nutzen und damit &amp;quot;Missverständnissen&amp;quot; vorzubeugen, die z.B. bei der Portierung von C-Code zwischen verschiedenen Plattformen auftreten können.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
typedef unsigned char      BYTE;       // besser: uint8_t  aus &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
typedef unsigned short     WORD;       // besser: uint16_t aus &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
typedef unsigned long      DWORD;      // besser: uint32_t aus &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
typedef unsigned long long QWORD;      // besser: uint64_t aus &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; BYTE : Der Datentyp BYTE definiert eine Variable mit 8 Bit Breite zur Darstellung von ganzen Zahlen im Bereich zwischen 0 ... 255.&lt;br /&gt;
&lt;br /&gt;
; WORD : Der Datentyp WORD definiert eine Variable mit 16 Bit Breite zur Darstellung von ganzen Zahlen im Bereich zwischen 0 ... 65535.&lt;br /&gt;
&lt;br /&gt;
; DWORD : Der Datentyp DWORD (gesprochen: Double-Word) definiert eine Variable mit 32 Bit Breite zur Darstellung von ganzen Zahlen im Bereich zwischen 0 ... 4294967295.&lt;br /&gt;
&lt;br /&gt;
; QWORD : Der Datentyp QWORD (gesprochen: Quad-Word) definiert eine Variable mit 64 Bit Breite zur Darstellung von ganzen Zahlen im Bereich zwischen 0 ... 18446744073709551615.&lt;br /&gt;
&lt;br /&gt;
== Standardisierte Integer(Ganzzahl)-Typen ==&lt;br /&gt;
&lt;br /&gt;
Standardisierte Datentypen werden in der Header-Datei inttypes.h definiert. In neueren Version der avr-libc (ab V1.2.0) heisst die Datei C99-standardkonform stdint.h. inttypes.h existiert aus Kompatibiltätsgründen weiterhin und enthält ein &#039;&#039;#include &amp;lt;stdint.h&amp;gt;&#039;&#039;.&lt;br /&gt;
Zur Nutzung der standardisierte Typen bindet man die &amp;quot;Definitionsdatei&amp;quot; wie folgt ein:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// oder - ab avr-libc Version 1.2.0 möglich und empfohlen:&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Einige der dort definierten Typen (avr-libc Version 1.0.4):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
typedef signed char        int8_t;&lt;br /&gt;
typedef unsigned char      uint8_t;&lt;br /&gt;
&lt;br /&gt;
typedef short              int16_t;&lt;br /&gt;
typedef unsigned short     uint16_t;&lt;br /&gt;
&lt;br /&gt;
typedef long               int32_t;&lt;br /&gt;
typedef unsigned long      uint32_t;&lt;br /&gt;
&lt;br /&gt;
typedef long long          int64_t;&lt;br /&gt;
typedef unsigned long long uint64_t;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ein Vierfach-Wort (64Bit) entspricht beim AVR &#039;&#039;uint64_t&#039;&#039;, ein Doppel-[[Word|Wort]] (32bit) entspricht &#039;&#039;uint32_t&#039;&#039;, ein Wort (16bit) entspricht &#039;&#039;uint16_t&#039;&#039; und ein [[Byte]] (8bit) entspricht &#039;&#039;uint8_t&#039;&#039;. &lt;br /&gt;
Die Typen ohne vorangestelltes &#039;&#039;u&#039;&#039; können auch vorzeichenbehaftete Zahlen speichern. &#039;&#039;int8_t&#039;&#039; geht also von -128 bis 127, &#039;&#039;uint8_t&#039;&#039; dagegen geht von 0 bis 255.&lt;br /&gt;
&lt;br /&gt;
* siehe auch: [http://www.nongnu.org/avr-libc/user-manual/index.html Dokumentation der avr-libc] Abschnitt Modules/(Standard) Integer Types&lt;br /&gt;
&lt;br /&gt;
= Bitfelder =&lt;br /&gt;
&lt;br /&gt;
Beim Programmieren von Mikrocontrollern muss auf jedes Byte oder sogar auf&lt;br /&gt;
jedes Bit geachtet werden. Oft müssen wir in einer Variablen lediglich den&lt;br /&gt;
Zustand 0 oder 1 speichern. Wenn wir nun zur Speicherung eines einzelnen Wertes&lt;br /&gt;
den kleinsten bekannten Datentypen, nämlich &#039;&#039;&#039;unsigned char&#039;&#039;&#039;, nehmen, dann&lt;br /&gt;
verschwenden wir 7 Bits, da ein &#039;&#039;&#039;unsigned char&#039;&#039;&#039; ja 8 Bit breit ist.&amp;lt;br /&amp;gt;&lt;br /&gt;
Hier bietet uns die Programmiersprache C ein mächtiges Werkzeug an, mit dessen&lt;br /&gt;
Hilfe wir 8 Bits in einer einzelnen Bytevariable zusammen fassen und (fast) wie&lt;br /&gt;
8 einzelne Variablen ansprechen können.&amp;lt;br /&amp;gt;&lt;br /&gt;
Die Rede ist von sogenannten Bitfeldern. Diese werden als Strukturelemente&lt;br /&gt;
definiert. Sehen wir uns dazu doch am besten gleich ein Beispiel an:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
struct {&lt;br /&gt;
   unsigned char bStatus_1:1; // 1 Bit für bStatus_1&lt;br /&gt;
   unsigned char bStatus_2:1; // 1 Bit für bStatus_2&lt;br /&gt;
   unsigned char bNochNBit:1; // Und hier noch mal ein Bit&lt;br /&gt;
   unsigned char b2Bits:2;    // Dieses Feld ist 2 Bits breit&lt;br /&gt;
   // All das hat in einer einzigen Byte-Variable Platz.&lt;br /&gt;
   // die 3 verbleibenden Bits bleiben ungenutzt&lt;br /&gt;
} x;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Zugriff auf ein solches Feld erfolgt nun wie beim Strukturzugriff bekannt&lt;br /&gt;
über den Punkt- oder den Dereferenzierungs-Operator:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
x.bStatus_1 = 1;&lt;br /&gt;
x.bStatus_2 = 0;&lt;br /&gt;
x.b2Bits = 3;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(mt Empfehlung: Bitfelder sparen zwar Platz, verschlechtern aber unter&lt;br /&gt;
Umständen die Les- und Wartbarkeit des Codes. Anfängern wird geraten,&lt;br /&gt;
ein &amp;quot;ganzes&amp;quot; Byte (uint8_t) zu nutzen auch wenn nur ein Bitwert gespeichert &lt;br /&gt;
werden soll.)&lt;br /&gt;
&lt;br /&gt;
= Grundsätzlicher Programmaufbau eines &amp;amp;micro;C-Programms =&lt;br /&gt;
&lt;br /&gt;
Wir unterscheiden zwischen 2 verschiedenen Methoden, um ein&lt;br /&gt;
Mikrocontroller-Programm zu schreiben, und zwar völlig unabhängig davon, in&lt;br /&gt;
welcher Programmiersprache das Programm geschrieben wird.&lt;br /&gt;
&lt;br /&gt;
== Sequentieller Programmablauf ==&lt;br /&gt;
&lt;br /&gt;
Bei dieser Programmiertechnik wird eine Endlosschleife programmiert, welche im&lt;br /&gt;
Wesentlichen immer den gleichen Aufbau hat:&lt;br /&gt;
&lt;br /&gt;
[[Image:Sequentielle Programme.gif]]&lt;br /&gt;
&lt;br /&gt;
== Interruptgesteuerter Programmablauf ==&lt;br /&gt;
&lt;br /&gt;
Bei dieser Methode werden beim Programmstart zuerst die gewünschten&lt;br /&gt;
Interruptquellen aktiviert und dann in eine Endlosschleife gegangen, in welcher&lt;br /&gt;
Dinge erledigt werden können, welche nicht zeitkritisch sind.&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn ein Interrupt ausgelöst wird so wird automatisch die zugeordnete&lt;br /&gt;
Interruptfunktion ausgeführt.&lt;br /&gt;
&lt;br /&gt;
[[Image:Interrupt Programme.gif]]&lt;br /&gt;
&lt;br /&gt;
= Allgemeiner Zugriff auf Register =&lt;br /&gt;
&lt;br /&gt;
Die AVR-Controller verfügen über eine Vielzahl von Registern. Die meisten&lt;br /&gt;
davon sind sogenannte Schreib-/Leseregister. Das heißt, das Programm kann die&lt;br /&gt;
Inhalte der Register auslesen und beschreiben.&amp;lt;br /&amp;gt;&lt;br /&gt;
Einige Register haben spezielle Funktionen, andere wiederum könne für&lt;br /&gt;
allgemeine Zwecke (Speichern von Datenwerten) verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Einzelne Register sind bei allen AVRs vorhanden, andere wiederum nur bei&lt;br /&gt;
bestimmten Typen. So sind beispielsweise die Register, welche für den Zugriff&lt;br /&gt;
auf den UART notwendig sind selbstverständlich nur bei denjenigen Modellen&lt;br /&gt;
vorhanden, welche über einen integrierten Hardware UART bzw. USART verfügen.&lt;br /&gt;
&lt;br /&gt;
Die Namen der Register sind in den Headerdateien zu den entsprechenden&lt;br /&gt;
AVR-Typen definiert.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;!--Wenn im Makefile der MCU-Typ definiert ist so bindet das System automatisch die&lt;br /&gt;
richtige Headerdatei ein.&amp;lt;br /&amp;gt; --&amp;gt;&lt;br /&gt;
Wenn im Makefile der MCU-Typ definiert ist, wird vom System automatisch die&lt;br /&gt;
zum Typen passende Definitionsdatei genutzt, sobald man im Code die allgemeine &lt;br /&gt;
&amp;quot;io.h&amp;quot; Header-Datei einbindet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ist im Makefile der MCU Type z.B. mit dem Inhalt atmega8 definiert,&lt;br /&gt;
wird beim einlesen der io.h-Datei implizit (&amp;quot;automatisch&amp;quot;) auch die iom8.h-Datei mit&lt;br /&gt;
den Register-Definitionen für den ATmega8 eingelesen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Man kann der MCU-Typ aber selbstverständlich auch noch in der C-Quelldatei&lt;br /&gt;
definieren, wenn man Freude daran hat. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O-Register ==&lt;br /&gt;
&lt;br /&gt;
Die I/O-Register haben einen besonderen Stellenwert bei den AVR Controllern.&lt;br /&gt;
Sie dienen dem Zugriff auf die Ports und die Schnittstellen des Controllers.&amp;lt;br /&amp;gt;&lt;br /&gt;
Wir unterscheiden zwischen 8-Bit und 16-Bit Registern. Vorerst behandeln wir mal&lt;br /&gt;
die 8-Bit Register.&lt;br /&gt;
&amp;lt;!-- &lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Hinweis:&#039;&#039;&#039;&lt;br /&gt;
| Die folgenden Funktionen erwarten als Argument&lt;br /&gt;
für das jeweilige Portregister konstante Werte. Am besten verwenden wir&lt;br /&gt;
die entsprechenden defines aus der Headerdatei . Wenn die&lt;br /&gt;
Portadresse über eine 8-Bit Variable übergeben quittiert der Inline&lt;br /&gt;
Assembler dies jeweils mit 2 Fehlermeldungen folgender Form:&lt;br /&gt;
&lt;br /&gt;
:: warning: asm operand 0 probably&lt;br /&gt;
doesn&#039;t match constraints&amp;lt;br /&amp;gt;:: warning: asm operand 1 probably&lt;br /&gt;
doesn&#039;t match constraints&lt;br /&gt;
&lt;br /&gt;
Offensichtlich läuft das Programm so auch tatsächlich nicht korrekt&lt;br /&gt;
ab. Wenn wir also Ports über Variablen ansprechen wollen müssen wir auf&lt;br /&gt;
die Low Level-Funktion &#039;&#039;&#039;[http://en.wikipedia.org#Speicherbezogener%20Portzugriff __mmio]&#039;&#039;&#039;&lt;br /&gt;
ausweichen.&lt;br /&gt;
|} --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Lesen eines I/O-Registers ===&lt;br /&gt;
&lt;br /&gt;
Zum Lesen kann man auf I/O Register einfach wie auf eine&lt;br /&gt;
Variable zugreifen. Die spezielle Funktion inp() ist nicht mehr &lt;br /&gt;
notwendig und veraltet.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
uint8_t foo;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
int&lt;br /&gt;
main(void)&lt;br /&gt;
{&lt;br /&gt;
    foo = PINB;    /* kopiert den Status der Eingabepins an PortB in die Variable foo */&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen eines Bits ====&lt;br /&gt;
&lt;br /&gt;
Die AVR-Bibliothek stellt auch Funktionen zur Abfrage eines einzelnen Bits&lt;br /&gt;
eines Registers zur Verfügung:&lt;br /&gt;
&lt;br /&gt;
;bit_is_set (&amp;lt;Register&amp;gt;,&amp;lt;Bitnummer&amp;gt;) : Die Funktion &#039;&#039;bit_is_set&#039;&#039; prüft, ob ein Bit gesetzt ist. Wenn das Bit gesetzt ist wird ein Wert ungleich 0 zurückgegeben. Genau genommen ist es die Wertigkeit des abgefragten Bits, also 1 für Bit0, 2 für Bit1, 4 für Bit2 etc.&lt;br /&gt;
&lt;br /&gt;
;bit_is_clear (&amp;lt;Register&amp;gt;,&amp;lt;Bitnummer&amp;gt;) : Die Funktion &#039;&#039;bit_is_clear&#039;&#039; prüft, ob ein Bit gelöscht ist. Wenn das Bit gelöscht ist, also auf 0 ist, wird ein Wert ungleich 0 zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
Die Funktionen bit_is_clear bzw. bit_is_set sind &#039;&#039;nicht erforderlich&#039;&#039;, man kann auch &amp;quot;einfache&amp;quot; C-Syntax verwenden, die universell verwendbar ist. &#039;&#039;bit_is_set&#039;&#039; entspricht dabei z.B. (Variable &amp;amp; (1 &amp;lt;&amp;lt; Bitnummer)). Das Ergebnis ist &amp;lt;&amp;gt;0 wenn das Bit gesetzt und 0 wenn es nicht gesetzt ist. &lt;br /&gt;
&lt;br /&gt;
* siehe auch [[Bitmanipulation]]&lt;br /&gt;
&lt;br /&gt;
=== Schreiben eines I/O-Registers ===&lt;br /&gt;
&lt;br /&gt;
Zum Schreiben kann man I/O Register einfach wie eine&lt;br /&gt;
Variable setzen. Die spezielle Funktion outp() ist nicht mehr &lt;br /&gt;
notwendig, veraltet und sollte nicht mehr genutzt werden.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
int&lt;br /&gt;
main(void)&lt;br /&gt;
{&lt;br /&gt;
    DDRA = 0xff;    /* Setzt das Richtungsregister des Ports A auf 0xff (alle Pins als Ausgang) */&lt;br /&gt;
    PORTA = 0x03;   /* Setzt PortA auf 0x03, Bit 0 und 1 &amp;quot;high&amp;quot;, restliche &amp;quot;low&amp;quot; */&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Schreiben eines Bits ====&lt;br /&gt;
&lt;br /&gt;
Einzelne Bits setzt man &amp;quot;Standard-C-Konform&amp;quot; mittels logischer (bit-) Operationen.&lt;br /&gt;
&lt;br /&gt;
mit dem Ausdruck:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
 x |= (1 &amp;lt;&amp;lt; Bitnummer)  // wird ein Bit in x gesetzt&lt;br /&gt;
 x &amp;amp;= ~(1 &amp;lt;&amp;lt; Bitnummer) // wird ein Bit in x geloescht&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Die Funktionen sbi und cbi sind dazu nicht notwendig, veraltet und sollten nicht mehr genutzt werden.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
#define MEINBIT 2&lt;br /&gt;
...&lt;br /&gt;
PORTA |= (1 &amp;lt;&amp;lt; MEINBIT);    /* setzt Bit 2 an PortA auf 1 */&lt;br /&gt;
PORTA &amp;amp;= ~(1 &amp;lt;&amp;lt; MEINBIT);   /* loescht Bit 2 an PortA */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* siehe auch:&lt;br /&gt;
** [[Bitmanipulation]]&lt;br /&gt;
** [http://www.nongnu.org/avr-libc/user-manual/index.html Dokumentation der avr-libc] Abschnitt Modules/Special Function Registers&lt;br /&gt;
&lt;br /&gt;
=== Warten auf einen bestimmten Zustand ===&lt;br /&gt;
&lt;br /&gt;
Es gibt in der Bibliothek sogar Funktionen, die warten, bis ein bestimmter&lt;br /&gt;
Zustand auf einem Bit erreicht ist.&amp;lt;br /&amp;gt;&lt;br /&gt;
Es ist allerdings normalerweise eine eher unschöne Programmiertechnik, da in diesen Funktionen &amp;quot;blockierend gewartet&amp;quot; wird. D.h., der Programmablauf bleibt an dieser Stelle stehen, bis das maskierte Ereignis erfolgt ist. Setzt man den Watchdog ein, muss man darauf achten, dass dieser auch noch getriggert wird.&lt;br /&gt;
&lt;br /&gt;
Die Funktion &#039;&#039;&#039;loop_until_bit_is_set&#039;&#039;&#039; wartet in einer Schleife, bis das&lt;br /&gt;
definierte Bit gesetzt ist. Wenn das Bit beim Aufruf der Funktion bereits&lt;br /&gt;
gesetzt ist, wird die Funktion sofort wieder verlassen. Das niederwertigste Bit hat die Bitnummer 0. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
/* Warten bis Bit Nr. 2 (das dritte Bit) in Register PINA gesetzt (1) ist */&lt;br /&gt;
&lt;br /&gt;
#define WARTEPIN PINA&lt;br /&gt;
#define WARTEBIT 2&lt;br /&gt;
&lt;br /&gt;
// mit der avr-libc Funktion:&lt;br /&gt;
loop_until_bit_is_set(WARTEPIN, WARTEBIT);&lt;br /&gt;
&lt;br /&gt;
// dito in &amp;quot;C-Standard&amp;quot;:&lt;br /&gt;
// Durchlaufe (die leere) Schleife solange das WARTEBIT in Register WARTEPIN&lt;br /&gt;
// _nicht_ ungleich 0 (also 0) ist.&lt;br /&gt;
while ( !(WARTEPIN &amp;amp; (1 &amp;lt;&amp;lt; WARTEBIT)) ) ;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Funktion &#039;&#039;&#039;loop_until_bit_is_clear&#039;&#039;&#039; wartet in einer Schleife, bis das&lt;br /&gt;
definierte Bit gelöscht ist. Wenn das Bit beim Aufruf der Funktion bereits&lt;br /&gt;
gelöscht ist, wird die Funktion sofort wieder verlassen.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das niederwertigste Bit hat die Bitnummer 0.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
/* Warten bis Bit Nr. 4 (das fuenfte Bit) in Register PINB geloescht (0) ist */&lt;br /&gt;
#define WARTEPIN PINB&lt;br /&gt;
#define WARTEBIT 4&lt;br /&gt;
&lt;br /&gt;
// avr-libc-Funktion:&lt;br /&gt;
loop_until_bit_is_clear(WARTEPIN, WARTEBIT);&lt;br /&gt;
&lt;br /&gt;
// dito in &amp;quot;C-Standard&amp;quot;:&lt;br /&gt;
// Durchlaufe (die leere) Schleife solange das WARTEBIT in Register WARTEPIN&lt;br /&gt;
// ungleich 0 ist &lt;br /&gt;
while ( WARTEPIN &amp;amp; (1&amp;lt;&amp;lt;WARTEBIT) ) ;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Universeller und auch auf andere Platformen besser übertragbar ist die Verwendung von C-Standardoperationen.&lt;br /&gt;
&lt;br /&gt;
siehe auch: &lt;br /&gt;
* [http://www.nongnu.org/avr-libc/user-manual/index.html Dokumentation der avr-libc] Abschnitt Modules/Special Function Registers&lt;br /&gt;
* [[Bitmanipulation]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- mt: noch notwendig? &lt;br /&gt;
=== Speicherbezogener Portzugriff ===&lt;br /&gt;
&lt;br /&gt;
In der Regel sind die weiter oben erwähnten Funktionen zu bevorzugen. Es&lt;br /&gt;
kann aber auch sein, dass wird mal eine Stufe tiefer einsteigen müssen. Dann&lt;br /&gt;
verwenden wir für den Portzugriff das Synonym &#039;&#039;&#039;__mmio&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;__mmio()&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Diese Funktion dient dem speicherbasierten Zugriff auf die Ports (Memory&lt;br /&gt;
Mapped I/O).&amp;lt;br /&amp;gt;&lt;br /&gt;
Die Funktion kann sowohl zum Lesen als auch zum Schreiben eines Ports verwendet&lt;br /&gt;
werden.&lt;br /&gt;
&lt;br /&gt;
Um ein einzelnes Bit in einem Port zu setzen bzw. zu löschen kann also ein&lt;br /&gt;
der folgenden Befehlszeilen verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;__mmio () = __mmio () | (1&lt;br /&gt;
&amp;lt;&amp;lt; )&amp;amp;nbsp;&amp;amp;nbsp; // Setzt ein Bit&amp;lt;br /&amp;gt;&lt;br /&gt;
__mmio () = __mmio () &amp;amp; ~(1 &amp;lt;&amp;lt; )&amp;amp;nbsp;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
// Löscht ein Bit&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die anderen Bits des Ports bleiben unverändert.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Zugriff auf Ports =&lt;br /&gt;
&lt;br /&gt;
Alle Ports der AVR-Controller werden über Register gesteuert. Dazu sind&lt;br /&gt;
jedem Port 3 Register zugeordnet:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;DDRx&#039;&#039;&#039; &lt;br /&gt;
| Datenrichtungsregister für Port&#039;&#039;&#039;x&#039;&#039;&#039;. &lt;br /&gt;
&#039;&#039;&#039;x&#039;&#039;&#039; entspricht &#039;&#039;&#039;A&#039;&#039;&#039;, &#039;&#039;&#039;B&#039;&#039;&#039;, &#039;&#039;&#039; C&#039;&#039;&#039;, &#039;&#039;&#039;D&#039;&#039;&#039; usw. (abhängig von der Anzahl der Ports des verwendeten AVR). Bit im Register gesetzt (1) für Ausgang, Bit gelöscht (0) für Eingang.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;PORTx&#039;&#039;&#039;&lt;br /&gt;
| Datenregister für Port&#039;&#039;&#039;x&#039;&#039;&#039;. &lt;br /&gt;
Dieses Register wird verwendet, um die Ausgänge eines Ports anzusteuern. Wird ein Port als Eingang geschaltet, so können mit diesem Register&lt;br /&gt;
die internen Pull-Up Widerstände aktiviert oder deaktiviert werden (1 = aktiv).&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;PINx&#039;&#039;&#039;&lt;br /&gt;
| Eingangadresse für Port&#039;&#039;&#039;x&#039;&#039;&#039;. &lt;br /&gt;
&amp;lt;!-- TODO: Erläuterung eher weiter unten nicht in der &amp;quot;Kurzzusammenfassung - Dies ist kein eigentliches Register, sondern definiert lediglich eine Adresse, in welcher der aktuelle Zustand der Eingangspins eines Ports vom&lt;br /&gt;
Controller abgelegt werden. Nichtsdestotrotz erfolgt der Zugriff auf den Zustand der Pins genau so, wie wenn &#039;&#039;&#039;PINx&#039;&#039;&#039; ein normales Register wäre. Die Adresse kann nur gelesen und nicht beschrieben werden.--&amp;gt;&lt;br /&gt;
Zustand des Ports. Die Bits in PINx entsprechen dem Zustand der Portspins. Bit gesetzt (1) wenn Pin &amp;quot;high/an&amp;quot;, Bit gelöscht (0) wenn Portpin &amp;quot;low/aus&amp;quot;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Datenrichtung bestimmen ==&lt;br /&gt;
&lt;br /&gt;
Zuerst muss die Datenrichtung der verwendeten Pins bestimmt werden. Um dies zu erreichen, wird das Datenrichtungsregister des entsprechenden Ports beschrieben.&lt;br /&gt;
&lt;br /&gt;
Für jeden Pin, der als Ausgang verwendet werden soll, muss dabei das&lt;br /&gt;
entsprechende Bit auf dem Port gesetzt werden. Soll der Pin als Eingang&lt;br /&gt;
verwendet werden, muss das entsprechende Bit gelöscht sein.&lt;br /&gt;
&lt;br /&gt;
Wollen wir also beispielsweise Pin 0 bis 4 von Port B als Ausgänge&lt;br /&gt;
definieren so schreiben wir folgende Zeile:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
// Setzen der Bits 0,1,2,3 und 4&lt;br /&gt;
// Binär 00011111 = Hexadezimal 1F&lt;br /&gt;
&lt;br /&gt;
DDRB = 0x1F;    /* direkte Zuweisung - unuebersichtlich */&lt;br /&gt;
&lt;br /&gt;
/* mehr Tipparbeit aber uebersichtlicher: */&lt;br /&gt;
DDRB = (1 &amp;lt;&amp;lt; DDB0) | (1 &amp;lt;&amp;lt; DDB1) | (1 &amp;lt;&amp;lt; DDB2) | (1 &amp;lt;&amp;lt; DDB3) | (1 &amp;lt;&amp;lt; DDB4); &lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Pins 5 bis 7 werden (da 0) als Eingänge geschaltet.&lt;br /&gt;
&lt;br /&gt;
=== Ganze Ports ===&lt;br /&gt;
&lt;br /&gt;
Um einen ganzen Port als Ausgang zu definieren, kann der folgende Befehl&lt;br /&gt;
verwendet werden:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
DDRB = 0xff;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Beispiel wird der Port B als Ganzes als Ausgang geschaltet.&lt;br /&gt;
&lt;br /&gt;
== Digitale Signale ==&lt;br /&gt;
&lt;br /&gt;
Am einfachsten ist es, digitale Signale mit dem Mikrocontroller zu erfassen&lt;br /&gt;
bzw. auszugeben.&lt;br /&gt;
&lt;br /&gt;
== Ausgänge ==&lt;br /&gt;
&lt;br /&gt;
Wir wollen nun einen als Ausgang definierten Pin auf Logisch 1 setzen. Dazu schreiben wir den entsprechenden Wert in das Portregister des entsprechenden Ports.&lt;br /&gt;
&lt;br /&gt;
Mit dem Befehl&lt;br /&gt;
&amp;lt;!-- &#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;outp (0x04, PORTB);&amp;lt;/font&amp;gt;&#039;&#039;&#039; --&amp;gt;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
PORTB=0x04; /* besser PORTB=(1&amp;lt;&amp;lt;DDB2) */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
wird also der Ausgang an Pin 2 gesetzt (Beachte, dass die Bits immer &#039;&#039;von 0 an&#039;&#039;&lt;br /&gt;
gezählt werden, das niederwertigste Bit ist also Bit 0 und nicht etwa Bit 1).&lt;br /&gt;
&lt;br /&gt;
Man beachte bitte, dass bei der Zuweisung mittels &#039;&#039;&#039;=&#039;&#039;&#039; &amp;lt;!-- Verwendung der &#039;&#039;&#039;outp&#039;&#039;&#039;-Funktion--&amp;gt; immer alle Pins gleichzeitig angegeben werden. Man sollte also zuerst den aktuellen Wert des Ports einlesen und das Bit des gewünschten Ports in diesen Wert einfliessen lassen. Will man also nur den dritten Pin (Bit Nr. 2) an PortB auf &amp;quot;high&amp;quot; setzen und den Status der anderen Ausgänge unverändert lassen, nutze man diese Form:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
PORTB = PORTB | 0x04; /* besser: PORTB = PORTB | ( 1&amp;lt;&amp;lt;DDB2 ) */&lt;br /&gt;
/* vereinfacht durch Nutzung des |= Operators : */&lt;br /&gt;
PORTB |= (1&amp;lt;&amp;lt;DDB2)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Es gibt jedoch in der AVRGCC-Bibliothek Funktionen, welche dies selbständig&lt;br /&gt;
machen.&amp;lt;br /&amp;gt;&lt;br /&gt;
Die Funktionen lassen sich wie folgt verwenden:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;sbi (PORTB, 2);&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; // Setzt Pin 2 auf Logisch 1 (EIN)&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
cbi (PORTB, 2);&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; // Setzt Pin 2 auf Logisch 0 (AUS)&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
Die Funktionen cbi und sbi sind dazu nicht notwendig, veraltet und sollten &lt;br /&gt;
nicht mehr genutzt werden.&lt;br /&gt;
&lt;br /&gt;
== Eingänge (Wie kommen Signale in den &amp;amp;micro;C) ==&lt;br /&gt;
&lt;br /&gt;
Die digitalen Eingangssignale können auf verschiedene Arten zu unserer Logik gelangen.&lt;br /&gt;
&lt;br /&gt;
=== Signalkopplung ===&lt;br /&gt;
&lt;br /&gt;
Am einfachsten ist es, wenn die Signale direkt aus einer anderen digitalen Schaltung übernommen werden können. Hat der Ausgang der entsprechenden Schaltung TTL-Pegel dann können wir sogar direkt den Ausgang der Schaltung mit einem Eingangspin von unserem Controller verbinden.&lt;br /&gt;
&lt;br /&gt;
Hat der Ausgang der anderen Schaltung keinen TTL-Pegel so müssen wir den Pegel über entsprechende Hardware (z.B. Optokoppler, Spannungsteiler &amp;quot;Levelshifter&amp;quot;) anpassen.&lt;br /&gt;
&lt;br /&gt;
Die Masse der beiden Schaltungen muss selbstverständlich miteinander verbunden werden. Der Software selber ist es natürlich letztendlich egal, wie das Signal eingespeist wird. Wir können ja ohnehin lediglich prüfen, ob an einem Pin unserer Controllers eine logische 1 (Vcc) oder eine logische 0 (Masse) anliegt.&lt;br /&gt;
&lt;br /&gt;
Die Abfrage der Zustände der Portpins erfolgt direkt über den Registernamen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- &#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;inp ()&amp;lt;/font&amp;gt;&#039;&#039;&#039; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;#FF0000&amp;quot;&amp;gt;Wobei es hier sehr wichtig ist, zur Abfrage der Eingänge nicht etwa das Portregister &#039;&#039;&#039;PORTx&#039;&#039;&#039; zu verwenden, sondern die Porteingangsadresse &#039;&#039;&#039;PINx&#039;&#039;&#039;. Dies ist&lt;br /&gt;
ein oft gemachter Fehler!&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wollen wir also die aktuellen Signalzustände von Port D abfragen und in einer Variable namens bPortD abspeichern so schreiben wir dazu folgende Befehlszeile:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
bPortD = PIND;&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit den C-Bitoperationen kann man den Status einzelner Bits abfragen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
/* Fuehre Aktion aus, wenn Bit1 in PINC gesetzt (1) */&lt;br /&gt;
if ( PINC &amp;amp; (1&amp;lt;&amp;lt;1) ) {&lt;br /&gt;
  /* Aktion */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Fuehre Aktion aus, wenn Bit 2 in PINB geloescht (0) */&lt;br /&gt;
if ( !(PINB &amp;amp; (1&amp;lt;&amp;lt;2)) ) {&lt;br /&gt;
  /* Aktion */&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tasten und Schalter ===&lt;br /&gt;
&lt;br /&gt;
Der Anschluss mechanischer Kontakte an den Mikrocontroller gestaltet sich ebenfalls ganz einfach, wobei wir zwei unterschiedliche Methoden unterscheiden müssen (&#039;&#039;Active Low&#039;&#039; und &#039;&#039;Active High&#039;&#039;):&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Active Low&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Active High&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| [[Image:Active Low.gif]]&lt;br /&gt;
| [[Image:Active High.gif]]&lt;br /&gt;
|- &lt;br /&gt;
| Bei dieser Methode wird der Kontakt zwischen den Eingangspin des Controllers und Masse geschaltet.&lt;br /&gt;
&lt;br /&gt;
Damit bei offenem Schalter der Controller kein undefiniertes Signal&lt;br /&gt;
bekommt wird zwischen die Versorgungsspannung und den Eingangspin ein&lt;br /&gt;
sogenannter Pull-Up Widerstand geschaltet. Dieser dient dazu, den Pegel&lt;br /&gt;
bei geöffnetem Schalter auf logisch 1 zu ziehen.&amp;lt;br /&amp;gt;&lt;br /&gt;
Der Widerstandswert des Pull-Up Widerstands ist an sich nicht kritisch. Es&lt;br /&gt;
muss jedoch beachtet werden, dass über den Widerstand ein Strom in den&lt;br /&gt;
Eingang fliesst, also sollte er nicht zu klein gewählt werden um den&lt;br /&gt;
Controller nicht zu zerstören. Wird er allerdings zu hoch gewählt ist&lt;br /&gt;
die Wirkung eventuell nicht gegeben. Als üblicher Wert haben sich 10&lt;br /&gt;
Kiloohm eingebürgert.&lt;br /&gt;
&lt;br /&gt;
Die AVRs haben sogar an den meisten Pins softwaremässig zuschaltbare&lt;br /&gt;
interne Pull-Up Widerstände, welche wir natürlich auch verwenden&lt;br /&gt;
können.&lt;br /&gt;
| Hier wird der Kontakt zwischen die Versorgungsspannung und Masse geschaltet.&lt;br /&gt;
&lt;br /&gt;
Damit bei offener Schalterstellung kein undefiniertes Signal am Controller&lt;br /&gt;
ansteht, wird zwischen den Eingangspin und die Masse ein Pull-Down&lt;br /&gt;
Widerstand geschaltet. Dieser dient dazu, den Pegel bei geöffneter&lt;br /&gt;
Schalterstellung auf logisch 0 zu halten.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Pull-Up Widerstände aktivieren ====&lt;br /&gt;
&lt;br /&gt;
Die internen Pull-Up Widerstände von Vcc zu den einzelnen Portpins werden&lt;br /&gt;
über das Register &#039;&#039;&#039; PORTx&#039;&#039;&#039; aktiviert bzw. deaktiviert, wenn ein Pin als &#039;&#039;&#039; Eingang&#039;&#039;&#039;&lt;br /&gt;
geschaltet ist.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wird der Wert des entsprechenden Portpins auf 1 gesetzt so ist&lt;br /&gt;
der Pull-Up Widerstand aktiviert. Bei einem Wert von 0 ist der Pull-Up&lt;br /&gt;
Widerstand nicht aktiv.&amp;lt;br /&amp;gt;&lt;br /&gt;
Man sollte jeweils entweder den internen oder einen externen Pull-Up Widerstand&lt;br /&gt;
verwenden, aber nicht beide zusammen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- &#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;outp (0x00, DDRD);&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; // Port D als&lt;br /&gt;
Eingang schalten&amp;lt;br /&amp;gt;&lt;br /&gt;
outp (0x00, PORTD);&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; // Interne Pull-Up Widerstände aus&amp;lt;/font&amp;gt;&#039;&#039;&#039; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
DDRD=0x00; /* alle Pins von Port D als Eingang */&lt;br /&gt;
PORTD=0xff: /* interer Pull-Up an allen Port-Pins aktivieren */&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Beispiel wird der gesamte Port D als Eingang geschaltet und alle Pull-Up&lt;br /&gt;
Widerstände aktiviert.&lt;br /&gt;
&lt;br /&gt;
===== Tastenentprellung =====&lt;br /&gt;
&lt;br /&gt;
Nun haben alle mechanischen Kontakte, sei es von Schaltern, Tastern oder auch von&lt;br /&gt;
Relais, die unangenehme Eigenschaft zu prellen. Dies bedeutet, dass beim&lt;br /&gt;
Schliessen des Kontaktes derselbe nicht direkt Kontakt herstellt, sondern&lt;br /&gt;
mehrfach ein- und ausschaltet bis zum endgültigen Herstellen des Kontaktes.&amp;lt;br /&amp;gt;&lt;br /&gt;
Soll nun mit einem schnellen Mikrocontroller gezählt werden, wie oft ein&lt;br /&gt;
solcher Kontakt geschaltet wird, dann haben wir ein Problem, weil das Prellen&lt;br /&gt;
als mehrfache Impulse gezählt wird. Diesem Phänomen muss beim Schreiben des Programms unbedingt Rechnung getragen&lt;br /&gt;
werden.&amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
#define F_CPU 3686400UL               /* Quarz mit 3.6854 Mhz  */&lt;br /&gt;
#include &amp;lt;avr/delay.h&amp;gt;                /* definiert _delay_ms() */&lt;br /&gt;
&lt;br /&gt;
/* Einfache Funktion zum Entprellen eines Tasters */&lt;br /&gt;
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)&lt;br /&gt;
{&lt;br /&gt;
        if ( ! (*port &amp;amp; (1 &amp;lt;&amp;lt; pin)) )&lt;br /&gt;
        {&lt;br /&gt;
                /* Pin wurde auf Masse gezogen, 100ms warten   */&lt;br /&gt;
                _delay_ms(100);&lt;br /&gt;
                if ( ! (*port &amp;amp; (1 &amp;lt;&amp;lt; pin)) )&lt;br /&gt;
                {&lt;br /&gt;
                        /* Anwender Zeit zum Loslassen des Tasters geben */&lt;br /&gt;
                        _delay_ms(100);&lt;br /&gt;
                        return 1;&lt;br /&gt;
                }&lt;br /&gt;
        }&lt;br /&gt;
        return 0;&lt;br /&gt;
}&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
        DDRB &amp;amp;= ~( 1 &amp;lt;&amp;lt; PB0 )                 /* PIN PB0 auf Eingang (Taster)            */&lt;br /&gt;
        PORTB |= ( 1 &amp;lt;&amp;lt; PB0 )                 /* Pullup-Widerstand aktivieren            */&lt;br /&gt;
        ...&lt;br /&gt;
        if (debounce(&amp;amp;PINB, PB0))             /* Falls Taster an PIN PB0 gedrueckt ..    */&lt;br /&gt;
                PORTD = PIND ^ ( 1 &amp;lt;&amp;lt; PD7 );  /* .. LED an Port PD7 an- bzw. ausschalten */&lt;br /&gt;
        ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Bei diesem Beispiel ist zu beachten, dass der AVR im Falle eines Tastendrucks 200ms wartet, also brach liegt. Zeitkritische Anwendungen sollten ein anderes Verfahren w&amp;amp;auml;hlen.&lt;br /&gt;
&lt;br /&gt;
== Analog ==&lt;br /&gt;
&lt;br /&gt;
Leider können wir mit unseren Controllern keine analogen Werte direkt&lt;br /&gt;
ausgeben oder einlesen. Dazu müssen wir Umwege gehen, doch dies wird in einem späteren&lt;br /&gt;
Kapitel behandelt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== 16-Bit Portregister (ADC, ICR1, OCR1, TCNT1, UBRR) ==&lt;br /&gt;
&lt;br /&gt;
Einige der Portregister in den AVR-Controllern sind 16 Bit breit. Im Datenblatt sind diese Register üblicherweise mit dem Suffix &amp;quot;L&amp;quot; (LSB) und &amp;quot;H&amp;quot; (MSB) versehen. Die avr-libc definiert zusätzlich die meisten dieser Variablen die Bezeichnung ohne &amp;quot;L&amp;quot; oder &amp;quot;H&amp;quot;. Auf diese kann direkt zugewiesen bzw. zugegriffen werden. Die Konvertierung von 16-bit Wort nach 2*8-bit Byte erfolgt intern.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint16_t foo;&lt;br /&gt;
&lt;br /&gt;
foo=ADC; /* setzt die Wort-Variable foo auf den Wert der letzten AD-Wandlung */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Falls ben&amp;amp;ouml;tigt, kann eine 16-Bit Variable auch recht einfach manuell in ihre zwei 8-Bit Bestandteile zerlegt werden. Folgendes Beispiel demonstriert dies anhand des pseudo- 16-Bit Registers UBRR.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#define F_CPU 3686400&lt;br /&gt;
#define UART_BAUD_RATE 9600&lt;br /&gt;
&lt;br /&gt;
typedef union {&lt;br /&gt;
        uint16_t i16;&lt;br /&gt;
        struct {&lt;br /&gt;
                uint8_t i8l;&lt;br /&gt;
                uint8_t i8h;&lt;br /&gt;
        };&lt;br /&gt;
} convert16to8;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
convert16to8 baud;&lt;br /&gt;
baud.i16 = F_CPU / (UART_BAUD_RATE * 16L) -1;&lt;br /&gt;
UBRRH = baud.i8h;&lt;br /&gt;
UBRRL = baud.i8l;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
/*alternativ:*/&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
uint16_t wFoo16;&lt;br /&gt;
uint8_t bFooLow, bFooHigh;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
wFoo16   = 0xAA55;                 /* zu &amp;quot;zerlegende&amp;quot; 16Bit-Integer */&lt;br /&gt;
bFooLow  = (uint8_t)(wFoo16);      /* LS-Byte */&lt;br /&gt;
bFooHigh = (uint8_t)(wFoo16 &amp;gt;&amp;gt; 8); /* MS-Byte */&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei einigen AVR-Typen (z.B. ATmega8) teilen sich UBRRH und UCSRC die gleiche Memory-Adresse. Damit der AVR trotzdem zwischen den beiden Registern unterscheiden kann, bestimmt das Bit7 (URSEL) welches Register tats&amp;amp;auml;chlich beschrieben werden soll. &#039;&#039;1000 0011&#039;&#039; (0x83) adressiert demnach UCSRC und &amp;amp;uuml;bergibt den Wert &#039;&#039;3&#039;&#039; und &#039;&#039;0000 0011&#039;&#039; (0x3) adressiert UBRRH und &amp;amp;uuml;bergibt ebenfalls den Wert &#039;&#039;3&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Im Umgang mit 16-Bit Registern siehe auch:&lt;br /&gt;
* [http://www.nongnu.org/avr-libc/user-manual/index.html Dokumentation der avr-libc] Abschnitt Related Pages/Frequently Asked Questions/Nr. 8&lt;br /&gt;
&lt;br /&gt;
= Der UART =&lt;br /&gt;
&lt;br /&gt;
== Allgemeines zum UART ==&lt;br /&gt;
&lt;br /&gt;
Über den UART kann ein AVR leicht mit einer RS232-Schnittstelle eines PC oder sonstiger Geräte mit &amp;quot;serieller Schnittstelle&amp;quot; verbunden werden. &lt;br /&gt;
&lt;br /&gt;
Mögliche Anwendungen des UART:&lt;br /&gt;
&lt;br /&gt;
* Debug-Schnittstelle: z.B. zur Anzeige von Zwischenergebnissen (&amp;quot;printf-debugging&amp;quot; - hier besser &amp;quot;UART-debugging&amp;quot;) auf einem PC. Auf dem Rechner reicht dazu eine Terminal-Software (MS-Windows: Hyperterm oder besser Bray-Terminal). Ein direkter Anschluss ist aufgrund unterschiedlicher Pegel nicht möglich, jedoch sind entsprechende Schnittstellen-ICs wie z.B. ein MAX232 günstig und leicht zu integrieren. Rechner ohne serielle Schnittstelle können über fertige USB-seriell-Adapter angeschlossen werden. &lt;br /&gt;
* &amp;quot;Mensch-Maschine Schnittstelle&amp;quot;: z.B. Konfiguration und Statusabfrage über eine &amp;quot;Kommandozeile&amp;quot; oder Menüs&lt;br /&gt;
* Übertragen von gespeicherten Werten: z.B. bei einem Datenlogger&lt;br /&gt;
* Anschluss von Geräten mit serieller Schnittstelle (z.B. (Funk-)Modems, Mobiltelefone, Drucker, Sensoren, &amp;quot;intelligente&amp;quot; LC-Displays). &lt;br /&gt;
* &amp;quot;Feldbusse&amp;quot; auf RS485/RS422-Basis mittels entsprechenden Bustreiberbausteinen (z.B. MAX485)&lt;br /&gt;
* DMX, Midi etc.&lt;br /&gt;
&lt;br /&gt;
Einige AVR-Controller haben ein bis zwei vollduplexfähigen UART (&#039;&#039;&#039;U&#039;&#039;&#039;niversal &#039;&#039;&#039;A&#039;&#039;&#039;synchronous &#039;&#039;&#039;R&#039;&#039;&#039;eceiver and &#039;&#039;&#039;T&#039;&#039;&#039;ransmitter) schon eingebaut (&amp;quot;Hardware-UART&amp;quot;). &lt;br /&gt;
Übrigens: Vollduplex heisst nichts anderes, als dass der Baustein gleichzeitig senden und empfangen kann.&lt;br /&gt;
&lt;br /&gt;
Neuere AVRs (ATmega) verfügen über einen oder zwei U&#039;&#039;&#039;S&#039;&#039;&#039;ART(s), dieser unterschiedet sich vom UART häuptsächlich durch interne FIFO-Puffer für Ein- und Ausgabe und erweiterte Konfigurationsmöglichkeiten. Die Puffergröße ist allerdings nur 1 Byte.&lt;br /&gt;
&lt;br /&gt;
Der UART wird über vier separate Register angesprochen. USARTs der ATMEGAs verfügen über mehrere zusätzliche Konfigurations/Datenregister. Das Datenblatt gibt darüber Auskunft. Die Folgende Tabelle gibt nur die Register für die (veralteten) UARTs wieder.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;UCR&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;U&#039;&#039;&#039;ART &#039;&#039;&#039;C&#039;&#039;&#039;ontrol &#039;&#039;&#039;R&#039;&#039;&#039;egister.&amp;lt;br /&amp;gt;&lt;br /&gt;
In diesem Register stellen wir ein, wie wir den UART verwenden möchten.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Register ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;RXCIE&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;TXCIE&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;UDRIE&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;RXEN&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;TXEN&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;CHR9&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;RXB8&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;TXB8&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | W&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RXCIE&#039;&#039;&#039; (&#039;&#039;&#039;RX&#039;&#039;&#039; &#039;&#039;&#039;C&#039;&#039;&#039;omplete &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;E&#039;&#039;&#039;nable)&lt;br /&gt;
:Wenn dieses Bit gesetzt ist, wird ein UART RX Complete Interrupt ausgelöst, wenn ein Zeichen vom UART empfangen wurde. Das Global Enable Interrupt Flag muss selbstverständlich auch gesetzt sein.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TXCIE&#039;&#039;&#039; (&#039;&#039;&#039;TX&#039;&#039;&#039; &#039;&#039;&#039;C&#039;&#039;&#039;omplete &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;E&#039;&#039;&#039;nable)&lt;br /&gt;
:Wenn dieses Bit gesetzt ist, wird ein UART TX Complete Interrupt ausgelöst, wenn ein Zeichen vom UART gesendet wurde. Das Global Enable Interrupt Flag muss selbstverständlich auch gesetzt sein.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UDRIE&#039;&#039;&#039; (&#039;&#039;&#039;U&#039;&#039;&#039;ART &#039;&#039;&#039;D&#039;&#039;&#039;ata &#039;&#039;&#039;R&#039;&#039;&#039;egister &#039;&#039;&#039;E&#039;&#039;&#039;mpty &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;E&#039;&#039;&#039;nable)&lt;br /&gt;
:Wenn dieses Bit gesetzt ist, wird ein UART Datenregister Leer Interrupt ausgelöst, wenn der UART wieder bereit ist um ein neues zu sendendes Zeichen zu übernehmen. Das Global Enable Interrupt Flag muss selbstverständlich auch gesetzt sein.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RXEN&#039;&#039;&#039; (&#039;&#039;&#039;R&#039;&#039;&#039;eceiver &#039;&#039;&#039;E&#039;&#039;&#039;nable)&lt;br /&gt;
:Nur wenn dieses Bit gesetzt ist, arbeitet der Empfänger des UART überhaupt. Wenn das Bit nicht gesetzt ist, kann der entsprechende Pin des AVR als normaler I/O-Pin verwendet werden. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TXEN&#039;&#039;&#039; (&#039;&#039;&#039;T&#039;&#039;&#039;ransmitter &#039;&#039;&#039;E&#039;&#039;&#039;nable)&lt;br /&gt;
:Nur wenn dieses Bit gesetzt ist, arbeitet der Sender des UART überhaupt. Wenn das Bit nicht gesetzt ist, kann der entsprechende Pin des AVR als normaler I/O-Pin verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CHR9&#039;&#039;&#039; (9 Bit Characters)&lt;br /&gt;
:Wenn dieses Bit gesetzt ist, können 9 Bit lange Zeichen übertragen und empfangen werden. Das 9. Bit kann bei Bedarf als zusätzliches Stopbit oder als Paritätsbit verwendet werden. Man spricht dann von einem 11-Bit Zeichenrahmen:&lt;br /&gt;
:1 Startbit + 8 Datenbits + 1 Stopbit + 1 Paritätsbit = 11 Bits&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RXB8&#039;&#039;&#039; (Receive Data Bit 8)&lt;br /&gt;
:Wenn das vorher erwähnte CHR9-Bit gesetzt ist, dann enthält dieses Bit das 9. Datenbit eines empfangenen Zeichens.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TXB8&#039;&#039;&#039; (Transmit Data Bit 8)&lt;br /&gt;
:Wenn das vorher erwähnte CHR9-Bit gesetzt ist, dann muss in dieses Bit das 9. Bit des zu sendenden Zeichens eingeschrieben werden bevor das eigentliche Datenbyte in das Datenregister geschrieben wird.&lt;br /&gt;
&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;USR&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;U&#039;&#039;&#039;ART &#039;&#039;&#039;S&#039;&#039;&#039;tatus &#039;&#039;&#039;R&#039;&#039;&#039;egister.&amp;lt;br /&amp;gt;&lt;br /&gt;
Hier teilt uns der UART mit, was er gerade so macht.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;RXC&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;TXC&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;UDRE&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;FE&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;OR&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RXC&#039;&#039;&#039; (UART Receive Complete)&lt;br /&gt;
:Dieses Bit wird vom AVR gesetzt, wenn ein empfangenes Zeichen vom Empfangs-Schieberegister in das Empfangs-Datenregister transferiert wurde.&lt;br /&gt;
:Das Zeichen muss nun schnellstmöglich aus dem Datenregister ausgelesen werden. Falls dies nicht erfolgt bevor ein weiteres Zeichen komplett empfangen wurde wird eine Überlauf-Fehlersituation eintreffen. Mit dem Auslesen des Datenregisters wird das Bit automatisch gelöscht.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TXC&#039;&#039;&#039; (UART Transmit Complete)&lt;br /&gt;
:Dieses Bit wird vom AVR gesetzt, wenn das im Sende-Schieberegister befindliche Zeichen vollständig ausgegeben wurde und kein weiteres Zeichen im Sendedatenregister ansteht. Dies bedeutet also, wenn die Kommunikation vollumfänglich abgeschlossen ist.&lt;br /&gt;
:Dieses Bit ist wichtig bei Halbduplex-Verbindungen, wenn das Programm nach dem Senden von Daten auf Empfang schalten muss. Im Vollduplexbetrieb brauchen wir dieses Bit nicht zu beachten.&lt;br /&gt;
:Das Bit wird nur dann automatisch gelöscht, wenn der entsprechende Interrupthandler aufgerufen wird, ansonsten müssen wir das Bit selber löschen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UDRE&#039;&#039;&#039; (&#039;&#039;&#039;U&#039;&#039;&#039;ART &#039;&#039;&#039;D&#039;&#039;&#039;ata &#039;&#039;&#039;R&#039;&#039;&#039;egister &#039;&#039;&#039;E&#039;&#039;&#039;mpty)&lt;br /&gt;
:Dieses Bit wird vom AVR gesetzt, wenn ein Zeichen vom Sendedatenregister in das Send-Schieberegister übernommen wurde und der UART nun wieder bereit ist, ein neues Zeichen zum Senden aufzunehmen.&lt;br /&gt;
:Das Bit wird automatisch gelöscht, wenn ein Zeichen in das Sendedatenregister geschrieben wird.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;FE&#039;&#039;&#039; (&#039;&#039;&#039;F&#039;&#039;&#039;raming &#039;&#039;&#039;E&#039;&#039;&#039;rror)&lt;br /&gt;
:Dieses Bit wird vom AVR gesetzt, wenn der UART einen Zeichenrahmenfehler detektiert, d.h. wenn das Stopbit eines empfangenen Zeichens 0 ist.&lt;br /&gt;
:Das Bit wird automatisch gelöscht, wenn das Stopbit des empfangenen Zeichens 1 ist.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;OR&#039;&#039;&#039; (&#039;&#039;&#039;O&#039;&#039;&#039;ver&#039;&#039;&#039;R&#039;&#039;&#039;un)&amp;lt;br /&amp;gt;&lt;br /&gt;
:Dieses Bit wird vom AVR gesetzt, wenn unser Programm das im Empfangsdatenregister bereit liegende Zeichen nicht abholt bevor das nachfolgende Zeichen komplett empfangen wurde.&lt;br /&gt;
:Das nachfolgende Zeichen wird verworfen.&lt;br /&gt;
:Das Bit wird automatisch gelöscht, wenn das empfangene Zeichen in das Empfangsdatenregister transferiert werden konnte.&lt;br /&gt;
&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;UDR&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;U&#039;&#039;&#039;ART &#039;&#039;&#039;D&#039;&#039;&#039;ata &#039;&#039;&#039;R&#039;&#039;&#039;egister.&amp;lt;br /&amp;gt;&lt;br /&gt;
Hier werden Daten zwischen UART und CPU übertragen. Da der UART im&lt;br /&gt;
Vollduplexbetrieb gleichzeitig empfangen und senden kann, handelt es sich&lt;br /&gt;
hier physikalisch um 2 Register, die aber über die gleiche I/O-Adresse&lt;br /&gt;
angesprochen werden. Je nachdem, ob ein Lese- oder ein Schreibzugriff auf&lt;br /&gt;
den UART erfolgt wird automatisch das richtige UDR angesprochen.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;UBRR&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;U&#039;&#039;&#039;ART &#039;&#039;&#039;B&#039;&#039;&#039;aud &#039;&#039;&#039;R&#039;&#039;&#039;ate &#039;&#039;&#039;R&#039;&#039;&#039;egister.&amp;lt;br /&amp;gt;&lt;br /&gt;
In diesem Register müssen wir dem UART mitteilen, wie schnell wir gerne&lt;br /&gt;
kommunizieren möchten. Der Wert, der in dieses Register geschrieben&lt;br /&gt;
werden muss, errechnet sich nach folgender Formel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{matrix}&lt;br /&gt;
UBRR = \frac{Taktfrequenz}{Baudrate * 16} - 1&lt;br /&gt;
\end{matrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind Baudraten bis zu 115200 Baud und höher möglich.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Die Hardware ==&lt;br /&gt;
&lt;br /&gt;
Der UART basiert auf normalem TTL-Pegel mit 0V (LOW) und 5V (HIGH). Die&lt;br /&gt;
Schnittstellenspezifikation für RS232 definiert jedoch -3V ... -12V (LOW) und&lt;br /&gt;
+3 ... +12V (HIGH). Zudem muss der Signalaustausch zwischen AVR und&lt;br /&gt;
Partnergerät invertiert werden. Für die Anpassung der Pegel und das&lt;br /&gt;
Invertieren der Signale gibt es fertige Schnittstellenbausteine. Der bekannteste&lt;br /&gt;
davon ist wohl der MAX232. &lt;br /&gt;
&amp;lt;!-- &amp;quot;Hackerloesung&amp;quot; auskommentiert - nicht so gut in einem &amp;quot;Einsteiger-Tutorial&amp;quot; - mthomas&lt;br /&gt;
Allerdings kostet der auch wieder Geld und benötigt&lt;br /&gt;
zusätzlich immerhin 4 externe Elkos.&lt;br /&gt;
&lt;br /&gt;
Die in den PC eingebauten Schnittstellen vertragen ohne Klagen auch den&lt;br /&gt;
TTL-Pegel vom AVR. Allerdings müssen wir immer noch die Signale invertieren. Im&lt;br /&gt;
einfachtesn Fall verwenden wir dazu jeweils einen einfachen NPN-Transistor und 2&lt;br /&gt;
Widerstände. Näheres dazu erfahrt ihr in den folgenden Übungen.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Streikt die Kommunikation per UART, so ist oft eine fehlerhafte Einstellung der Baudrate die Ursache. Die Konfiguration auf eine bestimmte Baudrate ist abhängig von der Taktfrequenz des Controllers. Gerade bei neu aufgebauten Schaltungen (bzw. neu gekauften Controllern) sollte man sich daher noch einmal vergewissern, dass der Controller auch tatsächlich mit der vermuteten Taktrate arbeitet und nicht z.B. den bei einigen Modellen werksseitig eingestellten internen [[Oszillator]] statt eines externen Quarzes nutzt. Die Werte der verschiedenen fuse-bits im Fehlerfall also beispielsweise mit &#039;&#039;[[AVRDUDE]]&#039;&#039; kontrollieren und falls nötig anpassen. Grundsätzlich empfielt sich auch immer ein Blick in die [[AVR_Checkliste]].&lt;br /&gt;
&lt;br /&gt;
== Senden mit dem UART ==&lt;br /&gt;
&lt;br /&gt;
Wir wollen nun Daten mit dem UART auf die serielle Schnittstelle ausgeben.&lt;br /&gt;
&lt;br /&gt;
Dazu müssen wir den UART zuerst mal initialisieren. Dazu setzen wir je nach&lt;br /&gt;
gewünschter Funktionsweise die benötigten Bits im &#039;&#039;&#039;U&#039;&#039;&#039;ART &#039;&#039;&#039;C&#039;&#039;&#039;ontrol &#039;&#039;&#039;R&#039;&#039;&#039;egister.&lt;br /&gt;
&lt;br /&gt;
Da wir vorerst nur senden möchten und (noch) keine Interrupts auswerten wollen, gestaltet sich die Initialisierung wirklich sehr einfach, da wir lediglich das &#039;&#039;&#039;Transmitter Enable&#039;&#039;&#039; Bit setzen müssen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
UCR |= (1&amp;lt;&amp;lt;TXEN);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Atmega16 hat mehrere Konfigurationsregister für USART und erfordert eine etwas andere Konfiguration&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
  UCSRB |= (1&amp;lt;&amp;lt;TXEN);			//UART TX einschalten&lt;br /&gt;
  UCSRC |= (1&amp;lt;&amp;lt;URSEL)|(3&amp;lt;&amp;lt;UCSZ0);	//Asynchron 8N1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nun müssen wir noch die Baudrate festlegen. Gemäß unserer Formel brauchen&lt;br /&gt;
wir dazu die Taktfrequenz des angeschlossenen Oszillators bzw. Quarz in die&lt;br /&gt;
Formel einzufügen und das Resultat der Berechnung in das Baudratenregister des&lt;br /&gt;
UART einzuschreiben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
/* UART-Init beim AT90S2313 */&lt;br /&gt;
#define F_CPU 4000000;       // Zum Beispiel 4Mhz-Quarz&lt;br /&gt;
#define UART_BAUD_RATE 9600  // Wir versuchen mal mit 9600 Baud&lt;br /&gt;
UBRR = F_CPU / (UART_BAUD_RATE * 16L) - 1;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Teilweise kann man im Datenblatt der jeweiligen CPU&#039;s auch den entsprechenden Wert&lt;br /&gt;
nachschlagen. Beispiel Mega32, Mit 16MHz und für 19200 Baud lesen wir den Wert 51 &lt;br /&gt;
aus der Tabelle ab. Dieser wird nun auf die Register UBRRH und UBRRL verteilt.&lt;br /&gt;
&lt;br /&gt;
Die Initialisisierung für den USART könnte dann so aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
  /* USART-Init 19200 Baud bei 16MHz für Mega32 */&lt;br /&gt;
  UCSRB |= ( 1 &amp;lt;&amp;lt; TXEN );			// UART TX einschalten&lt;br /&gt;
  UCSRC |= ( 1 &amp;lt;&amp;lt; URSEL )|( 3&amp;lt;&amp;lt;UCSZ0 );	        // Asynchron 8N1&lt;br /&gt;
  UBRRH  = 0;                                   // Highbyte ist 0&lt;br /&gt;
  UBRRL  = 51;                                  // Lowbyte ist 51 ( dezimal )&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der obige Code ist gegenüber den Versionen mit &#039;#define ...&#039; nicht so Portabel,&lt;br /&gt;
dafür aber etwas übersichtlicher.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wieder für den Mega16 mit einem 16bit-Register eine andere Programmierung.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
  /* USART-Init beim ATmegaXX */&lt;br /&gt;
  #define F_OSC 3686400           /* Oszillator-Frequenz in Hz */&lt;br /&gt;
  #define UART_BAUD_RATE 9600&lt;br /&gt;
  #define UART_BAUD_CALC(UART_BAUD_RATE,F_OSC) ((F_OSC)/((UART_BAUD_RATE)*16)-1)&lt;br /&gt;
&lt;br /&gt;
  UBRRH=(uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F_OSC)&amp;gt;&amp;gt;8);&lt;br /&gt;
  UBRRL=(uint8_t)UART_BAUD_CALC(UART_BAUD_RATE,F_OSC);&lt;br /&gt;
&lt;br /&gt;
  /* alternativ bei der avr-libc &amp;quot;direkt 16bit&amp;quot; : */&lt;br /&gt;
  UBRR=UART_BAUD_CALC(UART_BAUD_RATE,F_OSC);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Senden einzelner Zeichen ===&lt;br /&gt;
&lt;br /&gt;
Um nun ein Zeichen auf die Schnittstelle auszugeben, müssen wir dasselbe&lt;br /&gt;
lediglich in das &#039;&#039;&#039;U&#039;&#039;&#039;ART &#039;&#039;&#039;D&#039;&#039;&#039;ata &#039;&#039;&#039;R&#039;&#039;&#039;egister schreiben. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
    while (!(USR &amp;amp; (1&amp;lt;&amp;lt;UDRE))); /* warten bis Senden moeglich                   */&lt;br /&gt;
    UDR = &#039;x&#039;;                  /* Schreibt das Zeichen x auf die Schnittstelle */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Schreiben einer Zeichenkette (String) ===&lt;br /&gt;
&lt;br /&gt;
Es ist darauf zu achten, dass vor dem Senden geprüft wird, ob der UART bereit ist den &amp;quot;Sendeauftrag&amp;quot; entgegenzunehmen. &lt;br /&gt;
&amp;lt;!-- Wenn wir nun mehrere, aufeinanderfolgende Zeichen auf die Schnittstelle&lt;br /&gt;
ausgeben wollen, dann müssen wir mit dem nächsten Zeichen warten, bis das&lt;br /&gt;
vorhergehende jeweils aus dem Datenregister in das Sende-Schieberegister&lt;br /&gt;
übernommen wurde. MT: oben allgemeiner Formuliert wg. UART&amp;lt;-&amp;gt;USART) --&amp;gt;&lt;br /&gt;
Zu diesem Zweck können wir uns für&#039;s Erste eine einfache Funktion basteln:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
void&lt;br /&gt;
uart_putc(unsigned char c)&lt;br /&gt;
{&lt;br /&gt;
    while(!(USR &amp;amp; (1 &amp;lt;&amp;lt; UDRE)))&lt;br /&gt;
    ;   /* warte, bis UDR bereit */&lt;br /&gt;
&lt;br /&gt;
    UDR = c;    /* sende Zeichen */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void&lt;br /&gt;
uart_puts (char *s)&lt;br /&gt;
{&lt;br /&gt;
    while (*s)&lt;br /&gt;
    {   /* so lange *s != NULL */&lt;br /&gt;
        uart_putc(*s);&lt;br /&gt;
        s++;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Warteschleifen sind insofern etwas kritisch, da während des Sendens eines Strings nicht mehr auf andere Ereignisse reagieren werden kann. Universeller ist die Nutzung von FIFO(first-in first-out)-Puffern, in denen die zu sendenden bzw. emfangenen Zeichen/Bytes zwischengespeichert und mittels Interruptroutinen an den U(S)ART weitergebgen bzw. ausgelesen werden. Dazu existieren fertige Komponenten (Bibliotheken, Libraries), die man recht einfach in eigene Entwicklungen integrieren kann. Es empfiehlt sich, diese Komponenten zu nutzen und das Rad nicht neu zu erfinden.&amp;lt;!--Dies wird aber ohnehin erst dann ein Thema, wenn wir mit unserem Programm gleichzeitig Senden&lt;br /&gt;
und Empfangen wollen. Wir werden zu einem späteren Zeitpunkt Lösung für dieses Problem finden (Interrupt).--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Zeichen Empfangen ==&lt;br /&gt;
&lt;br /&gt;
Zum Empfang von Zeichen muss der Empfangsteil des UART bei der Initialisierung aktiviert werden, indem das RXEN-Bit im jeweiligen Konfigurationsregister (UCSRB beim USART) gesetzt wird. Im einfachsten Fall wird solange gewartet, bis ein Zeichen empfangen wurde, dieses steht dann im UART-Datenregister (UDR) zur Verfügung (sogn. &amp;quot;Polling-Betrieb&amp;quot;). Ein Beispiel für AVRs mit USART (hier ATmega16):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* Zusaetzlich zur Baudrateneinstellung und der weiteren Initialisierung: */&lt;br /&gt;
void Usart_EnableRX()&lt;br /&gt;
{&lt;br /&gt;
    UCSRB |= ( 1 &amp;lt;&amp;lt; RXEN );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Zeichen empfangen */&lt;br /&gt;
uint8_t Usart_Rx(void)&lt;br /&gt;
{&lt;br /&gt;
    while (!(UCSRA &amp;amp; (1&amp;lt;&amp;lt;RXC)));  // warten bis Zeichen verfuegbar&lt;br /&gt;
    return UDR;                   // Zeichen aus UDR an Aufrufer zurueckgeben&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Funktion blockiert den Programmablauf. Alternativ kann das RXC-Bit in einer Programmschliefe abgefragt werden und dann nur bei gesetztem RXC-Bit UDR ausgelesen werden. Eleganter und in den meisten Anwendungsfällen &amp;quot;stabiler&amp;quot; ist die Vorgehensweise, die empfangenen Zeichen in einer Interrupt-Routine einzulesen und zur späteren Verarbeitung in einem Eingangsbuffer (FIFO-Buffer) zwischenzuspeichern. Dazu existieren fertige und gut getestete Bibliotheken (z.B. UART-Library von P. Fleury, procyon-avrlib und einige in der &amp;quot;Academy&amp;quot; von avrfreaks.net).&lt;br /&gt;
&lt;br /&gt;
TODO: 9bit&lt;br /&gt;
&lt;br /&gt;
== Software-UART ==&lt;br /&gt;
&lt;br /&gt;
Falls die Zahl der vorhandenen Hardware-UARTs nicht ausreicht, können weitere Schnittstellen über sogennante Software-UARTs ergänzt werden. Im Prinzip wird dazu ein externer Interrupt-Pin für den Emfang genutzt (&amp;quot;RX&amp;quot;). Das Startbit löst den Interrupt aus, in der ISR wird der externe Interrupt deaktiviert und ein Timer aktiviert und der Zustand des Empfangs-Pins entsprechend der Baudrate abtastet. Nach Empfang des Stop-Bits wird der externe Interrupt wieder aktiviert. Senden kann über einen beliebigen Pin erfolgen (&amp;quot;TX&amp;quot;), der entsprechend der Baudrate und dem zu sendenden Zeichen auf 0 oder 1 gesetzt wird. Die Implementierung ist nicht ganz einfach, es existieren dazu aber fertige Bibliotheken (z.B. bei avrfreaks oder in der Procyon avrlib).&lt;br /&gt;
&lt;br /&gt;
Neuere AVRs (z.B. ATtiny26 oder ATmega48,88,168,169) verfügen über ein Universal Serial Interface (USI), das teilweise UART-Funktion übernehmen kann. Atmel stellt eine Application-Note bereit, in der die Nutzung des USI als UART erläutert wird (im Prinzip &amp;quot;Hardware-unterstützter Software-UART&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
* siehe auch: Weiterführende Informationen inkl. Beispielen für die Nutzung von stdio-Funktionen (prinf etc.) im [[AVR-Tutorial - UART]].&lt;br /&gt;
* [http://homepage.sunrise.ch/mysunrise/peterfleury/ Peter Fleurys] UART-Bibiliothek fuer avr-gcc/avr-libc&lt;br /&gt;
&lt;br /&gt;
= Analoge Ein- und Ausgabe =&lt;br /&gt;
&lt;br /&gt;
Leider können wir mit unseren Controllern keine analogen Werte direkt&lt;br /&gt;
verarbeiten. Dazu bedarf es jeweils einer Umwandlung des analogen Signals in&lt;br /&gt;
einen digitalen Zahlenwert. Je nachdem, ob wir Daten einlesen oder ausgeben&lt;br /&gt;
wollen reden wir dabei von &#039;&#039;&#039;ADC&#039;&#039;&#039; oder &#039;&#039;&#039;DAC&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== ADC (Analog Digital Converter) ==&lt;br /&gt;
&lt;br /&gt;
Der &#039;&#039;&#039;ADC&#039;&#039;&#039; wandelt analoge Signale in digitale Werte um, welche vom Controller&lt;br /&gt;
interpretiert werden können. Einige AVR-Typen haben bereits einen oder mehrere&lt;br /&gt;
solcher &#039;&#039;&#039;ADC&#039;&#039;&#039;&#039;s eingebaut, bei den kleineren AVR&#039;s müssen wir uns anders aus der&lt;br /&gt;
Affäre ziehen. Die Genauigkeit, mit welcher ein analoges Signal aufgelöst&lt;br /&gt;
werden kann, wird durch die Auflösung des &#039;&#039;&#039;ADC&#039;&#039;&#039; in Anzahl Bits angegeben, man&lt;br /&gt;
hört bzw. liest jeweils von 8-Bit &#039;&#039;&#039;ADC&#039;&#039;&#039; oder 10-Bit &#039;&#039;&#039; ADC&#039;&#039;&#039; oder noch höher.&amp;lt;br /&amp;gt;&lt;br /&gt;
Ein &#039;&#039;&#039;ADC&#039;&#039;&#039; mit 8 Bit Auflösung kann somit das analoge Signal mit einer Genauigkeit&lt;br /&gt;
von 1/256 des Maximalwertes darstellen. Wenn wir nun mal annehmen, wir hätten&lt;br /&gt;
eine Spannung zwischen 0 und 5 Volt und eine Auflösung von 3 Bit, dann könnten&lt;br /&gt;
die Werte 0V, 0.625V, 1.25, 1.875V, 2.5V, 3.125V, 3.75, 4.375, 5V&lt;br /&gt;
daherkommen, siehe dazu folgende Tabelle:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;Eingangsspannung am ADC&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;Entsprechender Messwert&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0...&amp;lt;0.625V&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0.625...&amp;lt;1.25V&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1.25...&amp;lt;1.875V&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1.875...&amp;lt;2.5V&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2.5...&amp;lt;3.125V&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3.125...&amp;lt;3.75V&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3.75...&amp;lt;4.375V&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4.375...5V&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Angaben sind natürlich nur ungefähr. Je höher nun die Auflösung des &#039;&#039;&#039;&lt;br /&gt;
ADC&#039;&#039;&#039; ist, also je mehr Bits er hat, um so genauer kann der Wert erfasst werden.&lt;br /&gt;
&lt;br /&gt;
=== Messen eines Widerstandes ===&lt;br /&gt;
&lt;br /&gt;
Wir wollen hier einmal die wohl einfachste Methode zur Erfassung eines&lt;br /&gt;
analogen Wertes realisieren und zwar das Messen eines veränderlichen&lt;br /&gt;
Widerstandes wie z.B. eines Potentiometers.&lt;br /&gt;
&lt;br /&gt;
Man stelle sich vor, wir schalten einen Kondensator in Reihe zu einem&lt;br /&gt;
Widerstand zwischen die Versorgungsspannung und Masse und dazwischen nehmen wir&lt;br /&gt;
das Signal ab und führen es auf einen der Pins an unserem Controller, genau so&lt;br /&gt;
wie es in folgender Grafik dargestellt ist.&lt;br /&gt;
&lt;br /&gt;
[[Image:Poti.gif]]&lt;br /&gt;
&lt;br /&gt;
Wenn wir nun den Pin des AVR als Ausgang schalten und auf&lt;br /&gt;
Logisch 1 (HIGH) legen, dann liegt an beiden Platten des Kondensators &#039;&#039;&#039; Vcc&#039;&#039;&#039; an und&lt;br /&gt;
dieser wird entladen (Klingt komisch, mit &#039;&#039;&#039; Vcc&#039;&#039;&#039; entladen, ist aber so, da an beiden Seiten des Kondensators das gleiche Potential anliegt und somit eine Potentialdifferenz von 0V besteht =&amp;gt; Kondensator ist entladen).&amp;lt;br /&amp;gt;&lt;br /&gt;
Nachdem nun der Kondensator genügend entladen ist schalten wir einfach den Pin&lt;br /&gt;
als Eingang wodurch dieser hochohmig wird. Der Kondensator lädt sich jetzt&lt;br /&gt;
über das Poti auf, dabei steigt der Spannungsabfall über dem Kondensator und&lt;br /&gt;
derjenige über dem Poti sinkt. Fällt nun der Spannungsabfall über dem Poti&lt;br /&gt;
unter die Thresholdspannung des Eingangspins (2/5 Vcc, also ca. 2V), dann schaltet der&lt;br /&gt;
Eingang von HIGH auf LOW um. Wenn wir nun messen (zählen), wie lange es dauert,&lt;br /&gt;
bis der Kondensator so weit geladen ist, dann haben wir einen ungefähren Wert&lt;br /&gt;
der Potentiometerstellung.&amp;lt;br /&amp;gt;&lt;br /&gt;
Der 220 Ohm Widerstand dient dem Schutz des Controllers. Wenn nämlich sonst die&lt;br /&gt;
Potentiometerstellung auf Maximum steht (0 Ohm), dann würde in den Eingang des&lt;br /&gt;
Controllers ein viel zu hoher Strom fliessen und der AVR würde in Rauch&lt;br /&gt;
aufgehen.&lt;br /&gt;
&lt;br /&gt;
Dies ist meines Wissens die einzige Schaltung zur Erfassung von&lt;br /&gt;
Analogwerten, welche mit nur einem einzigen Pin auskommt.&amp;lt;br /&amp;gt;&lt;br /&gt;
Mit einem weiteren Eingangspin und ein wenig Software können wir auch eine&lt;br /&gt;
Kalibrierung realisieren, um den Messwert in einen vernünftigen Bereich (z.B:&lt;br /&gt;
0...100 % oder so) umzurechnen.&lt;br /&gt;
&lt;br /&gt;
Wer Lust hat, sich selber mal an ein solches Programm&lt;br /&gt;
heranzuwagen, der sollte das jetzt tun. Für diejenigen, die es gern schnell&lt;br /&gt;
mögen, hier das Beispielprogramm, welches den UART-Printf aus den&lt;br /&gt;
vorangegangenen Kapiteln benötigt, inkl. Makefile:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| [http://www.mypage.bluewin.ch/ch_schifferle/AtmelC/Uebungen/Poti/Poti.c Poti.c ]&lt;br /&gt;
| Hauptprogramm.&lt;br /&gt;
|- &lt;br /&gt;
| [http://www.mypage.bluewin.ch/ch_schifferle/AtmelC/Uebungen/Poti/Pot.c Pot.c]&lt;br /&gt;
| Separate Routine zur Ermittlung des Messwertes.&lt;br /&gt;
|- &lt;br /&gt;
| [http://www.mypage.bluewin.ch/ch_schifferle/AtmelC/Uebungen/Poti/Pot.h Pot.h]&lt;br /&gt;
| Zugehörige Headerdatei.&lt;br /&gt;
|- &lt;br /&gt;
| [http://www.mypage.bluewin.ch/ch_schifferle/AtmelC/Uebungen/Allgemein/UartPrintF.c UartPrintF.c]&lt;br /&gt;
| Für die Debugausgabe auf den UART.&lt;br /&gt;
|- &lt;br /&gt;
| [http://www.mypage.bluewin.ch/ch_schifferle/AtmelC/Uebungen/Allgemein/UartPrintF.h UartPrintF.h]&lt;br /&gt;
| Zugehörige Headerdatei.&lt;br /&gt;
|- &lt;br /&gt;
| [http://www.mypage.bluewin.ch/ch_schifferle/AtmelC/Uebungen/Poti/makefile Makefile]&lt;br /&gt;
| Makefile.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Nachdem das Programm auf den AVR geladen wurde, muss dieser&lt;br /&gt;
kalibriert werden. Dazu wird der Kalibrierungsschalter geschlossen und das Poti&lt;br /&gt;
einige Male zwischen minimaler und maximaler Stellung hin und her gedreht. Dabei&lt;br /&gt;
werden die jeweiligen Maximalwerte bestimmt. Wenn der Kalibrierschalter wieder&lt;br /&gt;
geöffnet wird werden die Kalibrierungsdaten in&#039;s EEPROM des AVR geschrieben,&lt;br /&gt;
damit die Prozedur nicht nach jedem Reset wiederholt werden muss.&lt;br /&gt;
&lt;br /&gt;
Auf Pin 4 habe ich noch ein Triggersignal gelegt, welches auf&lt;br /&gt;
HIGH geht wenn die Messung beginnt und auf LOW, wenn der Messvorgang beendet&lt;br /&gt;
wird. Mit Hilfe dieses Signals kann der Vorgang wunderschön auf einem&lt;br /&gt;
Oszillographen dargestellt werden.&lt;br /&gt;
&lt;br /&gt;
=== ADC über Komparator ===&lt;br /&gt;
&lt;br /&gt;
Es gibt einen weiteren Weg, eine analoge Spannung mit Hilfe des&lt;br /&gt;
Komparators, welcher in fast jedem AVR integriert ist, zu messen. Siehe dazu&lt;br /&gt;
auch die Application Note AVR400 von Atmel.&lt;br /&gt;
&lt;br /&gt;
Dabei wird das zu messende Signal auf den invertierenden Eingang&lt;br /&gt;
des Komparators geführt. Zusätzlich wird ein Referenzsignal an den nicht&lt;br /&gt;
invertierenden Eingang des Komparators angeschlossen. Das Referenzsignal wird&lt;br /&gt;
hier auch wieder über ein RC-Glied erzeugt, allerdings mit festen Werten für R&lt;br /&gt;
und C.&lt;br /&gt;
&lt;br /&gt;
[[Image:ADC ueber Komparator.gif]]&lt;br /&gt;
&lt;br /&gt;
Das Prinzip der Messung ist nun dem vorhergehenden recht&lt;br /&gt;
ähnlich. Durch Anlegen eines LOW-Pegels an Pin 2 wird der Kondensator zuerst&lt;br /&gt;
einmal entladen. Auch hier muss darauf geachtet werden, dass der Entladevorgang&lt;br /&gt;
genügend lang dauert.&amp;lt;br /&amp;gt;&lt;br /&gt;
Nun wird Pin 2 auf HIGH gelegt. Der Kondensator wird geladen. Wenn die Spannung&lt;br /&gt;
über dem Kondensator die am Eingangspin anliegende Spannung erreicht hat&lt;br /&gt;
schaltet der Komparator durch. Die Zeit, welche benötigt wird, um den&lt;br /&gt;
Kondensator zu laden kann nun auch wieder als Maß für die Spannung an Pin 1&lt;br /&gt;
herangezogen werden.&lt;br /&gt;
&lt;br /&gt;
Ich habe es mir gespart, diese Schaltung auch aufzubauen und&lt;br /&gt;
zwar aus mehreren Gründen:&lt;br /&gt;
&lt;br /&gt;
# 3 Pins notwendig.&lt;br /&gt;
# Genauigkeit vergleichbar mit einfacherer Lösung.&lt;br /&gt;
# War einfach zu faul.&lt;br /&gt;
&lt;br /&gt;
Der Vorteil dieser Schaltung liegt allerdings darin, dass damit&lt;br /&gt;
direkt Spannungen gemessen werden können.&lt;br /&gt;
&lt;br /&gt;
=== Der ADC im AVR ===&lt;br /&gt;
&lt;br /&gt;
Wenn es einmal etwas genauer sein soll, dann müssen wir auf einen AVR mit eingebautem &#039;&#039;&#039;ADC-Wandler&#039;&#039;&#039; zurückgreifen. Wir wollen hier einmal den AT90S8535 besprechen, welcher über 8 ADC-Kanäle verfügt. (TODO: nur ein Wandler, Mulitiplexbetrieb, nur eine Pin zur gleichen Zeit)&lt;br /&gt;
&lt;br /&gt;
Die Umwandlung innerhalb des AVR basiert auf der schrittweisen Näherung. Beim AVR müssen die Pins &#039;&#039;&#039;AGND&#039;&#039;&#039; und &#039;&#039;&#039;AVCC&#039;&#039;&#039; beschaltet werden. Für genaue Messungen sollte AVCC über ein L-C Netzwerk mit VCC verbunden werden, um Spannungsspitzen und -einbrüche vom Analog-Digital-Wandler fernzuhalten. Im Datenblatt findet sich dazu eine Schaltung.  &lt;br /&gt;
&lt;br /&gt;
Verfügt der AVR über eine interne Referenzspannung (Datenblatt typisch 2,56 oder 1,1V je nach AVR), bleibt der &#039;&#039;Anschluss AREF&#039;&#039; unbeschaltet und man stellt die ADC-Register so ein, dass die interne Referenzspannung als &amp;quot;AREF&amp;quot; genutzt wird. Ansonsten ist eine externe Referenzspannung von maximal &#039;&#039;&#039;Vcc&#039;&#039;&#039; an den Abschluss &#039;&#039;&#039;AREF&#039;&#039;&#039; anzulegen. Die zu messende Spannung muss im Bereich zwischen &#039;&#039;&#039;AGND&#039;&#039;&#039; und &#039;&#039;&#039;AREF&#039;&#039;&#039; (egal ob intern oder extern) liegen. &lt;br /&gt;
&lt;br /&gt;
Der &#039;&#039;&#039;ADC&#039;&#039;&#039; kann in zwei verschiedenen Betriebsarten verwendet werden.&lt;br /&gt;
&lt;br /&gt;
==== Einfache Wandlung (Single Conversion) ====&lt;br /&gt;
&lt;br /&gt;
In dieser Betriebsart wird der Wandler bei Bedarf vom Programm angestossen für jeweils eine Messung.&lt;br /&gt;
&lt;br /&gt;
==== Frei laufend (Free Running) ====&lt;br /&gt;
&lt;br /&gt;
In dieser Betriebsart erfasst der Wandler permanent die anliegende Spannung und schreibt diese in das &#039;&#039;&#039;ADC Data Register&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Die Register des ADC ====&lt;br /&gt;
&lt;br /&gt;
Der &#039;&#039;&#039;ADC&#039;&#039;&#039; verfügt über eigene Register, welche hier aufgelistet werden.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;ADCSR&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;ADC&#039;&#039;&#039; &#039;&#039;&#039;C&#039;&#039;&#039;ontrol and &#039;&#039;&#039;S&#039;&#039;&#039;tatus &#039;&#039;&#039;R&#039;&#039;&#039;egister.&amp;lt;br /&amp;gt;&lt;br /&gt;
In diesem Register stellen wir ein, wie wir den &#039;&#039;&#039;ADC&#039;&#039;&#039; verwenden möchten.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Register ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ADEN&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ADSC&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ADFR&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ADIF&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ADIE&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ADPS2&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ADPS1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ADPS0&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | W&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ADEN&#039;&#039;&#039; (&#039;&#039;&#039;AD&#039;&#039;&#039;C &#039;&#039;&#039;En&#039;&#039;&#039;able)&lt;br /&gt;
:Dieses Bit muss gesetzt werden, um den &#039;&#039;&#039; ADC&#039;&#039;&#039; überhaupt zu aktivieren. Wenn das Bit nicht gesetzt, ist können die Pins wie normale I/O-Pins verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ADSC&#039;&#039;&#039; (&#039;&#039;&#039;AD&#039;&#039;&#039;C &#039;&#039;&#039;S&#039;&#039;&#039;tart &#039;&#039;&#039;C&#039;&#039;&#039;onversion)&lt;br /&gt;
:Mit diesem Bit wird ein Messvorgang gestartet. In der frei laufenden Betriebsart muss das Bit gesetzt werden, um die kontinuierliche Messung zu aktivieren.&lt;br /&gt;
:Wenn das Bit nach dem Setzen des &#039;&#039;&#039;ADEN&#039;&#039;&#039;-Bits zum ersten Mal gesetzt wird, führt der Controller zuerst eine zusätzliche Wandlung und erst dann die eigentliche Wandlung aus. Diese zusätzliche Wandlung wird zu Initialisierungszwecken durchgeführt.&lt;br /&gt;
:Das Bit bleibt nun so lange auf 1, bis die Umwandlung abgeschlossen ist, im Initialisierungsfall entsprechend bis die zweite Umwandlung erfolgt ist und geht danach auf 0.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ADFR&#039;&#039;&#039; (&#039;&#039;&#039;AD&#039;&#039;&#039;C &#039;&#039;&#039;Fr&#039;&#039;&#039;ee Running Select)&lt;br /&gt;
:Mit diesem Bit wird die Betriebsart eingestellt.&lt;br /&gt;
:Eine logische 1 aktiviert den frei laufenden Modus. Der &#039;&#039;&#039; ADC&#039;&#039;&#039; misst nun ständig den ausgewählten Kanal und schreibt den gemessenen Wert in das &#039;&#039;&#039;ADC Data Register&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ADIF&#039;&#039;&#039; (&#039;&#039;&#039;AD&#039;&#039;&#039;C &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;F&#039;&#039;&#039;lag)&lt;br /&gt;
:Dieses Bit wird vom &#039;&#039;&#039; ADC&#039;&#039;&#039; gesetzt, wenn eine Umwandlung erfolgt und das &#039;&#039;&#039;ADC Data Register&#039;&#039;&#039; aktualisiert ist.&lt;br /&gt;
:Wenn das &#039;&#039;&#039;ADIE&#039;&#039;&#039; Bit sowie das &#039;&#039;&#039;I-Bit&#039;&#039;&#039; im AVR &#039;&#039;&#039;Statusregister&#039;&#039;&#039; gesetzt ist, wird der &#039;&#039;&#039;ADC Interrupt&#039;&#039;&#039; ausgelöst und die Interrupt-Behandlungsroutine aufgerufen.&lt;br /&gt;
:Das Bit wird automatisch gelöscht, wenn die Interrupt-Behandlungsroutine aufgerufen wird. Es kann jedoch auch gelöscht werden, indem eine logische 1 in das Register geschrieben wird (So steht es in der AVR-Dokumentation).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ADIE&#039;&#039;&#039; (&#039;&#039;&#039;AD&#039;&#039;&#039;C &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;E&#039;&#039;&#039;nable)&lt;br /&gt;
:Wenn dieses Bit gesetzt ist und ebenso das &#039;&#039;&#039; I-Bit&#039;&#039;&#039; im Statusregister &#039;&#039;&#039;SREG&#039;&#039;&#039;, dann wird der &#039;&#039;&#039; ADC-Interrupt&#039;&#039;&#039; aktiviert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ADPS2...ADPS0&#039;&#039;&#039; (&#039;&#039;&#039;AD&#039;&#039;&#039;C &#039;&#039;&#039;P&#039;&#039;&#039;rescaler &#039;&#039;&#039;S&#039;&#039;&#039;elect Bits)&lt;br /&gt;
:Diese Bits bestimmen den Teilungsfaktor zwischen der Taktfrequenz und dem Eingangstakt des &#039;&#039;&#039;ADC&#039;&#039;&#039;.&lt;br /&gt;
:Der &#039;&#039;&#039;ADC&#039;&#039;&#039; benötigt einen eigenen Takt, welchen er sich selber aus der CPU-Taktfreqenz erzeugt. Der &#039;&#039;&#039;ADC&#039;&#039;&#039;-Takt sollte zwischen 50 und 200kHz sein.&lt;br /&gt;
:Der Vorteiler muss also so eingestellt werden, dass die CPU-Taktfrequenz dividiert durch den Teilungsfaktor einen Wert zwischen 50-200kHz ergibt.&lt;br /&gt;
:Bei einer CPU-Taktfrequenz von 4MHz beispielsweise rechnen wir&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{matrix}&lt;br /&gt;
TF_{min}=\frac{CLK}{200kHz}=\frac{4000000}{200000}=\mathbf{20}&lt;br /&gt;
\\&lt;br /&gt;
\\&lt;br /&gt;
TF_{max}=\frac{CLK}{50kHz}=\frac{4000000}{50000}=\mathbf{80}&lt;br /&gt;
\end{matrix}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:Somit kann hier der Teilungsfaktor 32 oder 64 verwendet werden. Im Interesse der schnelleren Wandlungszeit werden wir hier den Faktor 32 einstellen.&lt;br /&gt;
&amp;lt;dl&amp;gt;&amp;lt;dd&amp;gt;&lt;br /&gt;
{| style=&amp;quot;&amp;quot; border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ADPS2&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ADPS1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ADPS0&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;Teilungsfaktor&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 8&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 16&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 32&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 64&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 128&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/dd&amp;gt;&amp;lt;/dl&amp;gt;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;ADCL&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;ADCH&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;ADC &#039;&#039;&#039; Data Register&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn eine Umwandlung abgeschlossen ist, befindet sich der gemessene Wert in&lt;br /&gt;
diesen beiden Registern. Von &#039;&#039;&#039;ADCH&#039;&#039;&#039; werden nur die beiden niederwertigsten Bits verwendet. Es müssen immer beide Register ausgelesen werden und zwar immer &#039;&#039;&#039;in der Reihenfolge: ADCL, ADCH&#039;&#039;&#039;. &lt;br /&gt;
Der effektive Messwert ergibt sich dann zu:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
x = ADCL;       // mit uint16_t x&lt;br /&gt;
x += (ADCH&amp;lt;&amp;lt;8); // in zwei Zeilen (LSB/MSB-Reihenfolge und &lt;br /&gt;
                   C-Operatorprioritaet sichergestellt)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
oder &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
x = ADCW; // je nach AVR auch x = ADC (siehe avr/ioxxx.h)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;ADMUX&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;AD&#039;&#039;&#039;C &#039;&#039;&#039;Mu&#039;&#039;&#039;ltiple&#039;&#039;&#039;x&#039;&#039;&#039;er Select Register&amp;lt;br /&amp;gt;&lt;br /&gt;
Mit diesem Register wird der zu messende Kanal ausgewählt. Beim 90S8535&lt;br /&gt;
kann jeder Pin von Port A als &#039;&#039;&#039;ADC&#039;&#039;&#039;-Eingang verwendet werden (=8 Kanäle).&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Register ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;MUX2&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;MUX1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;MUX0&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MUX2...MUX0&#039;&#039;&#039;&lt;br /&gt;
:Mit diesem 3 Bits wird der zu messende Kanal bestimmt. Es wird einfach die entsprechende Pinnummer des Ports eingeschrieben.&lt;br /&gt;
:Wenn das Register beschrieben wird, während dem eine Umwandlung läuft, so wird zuerst die aktuelle Umwandlung auf dem bisherigen Kanal beendet. Dies ist vor allem beim frei laufenden Betrieb zu berücksichtigen.&lt;br /&gt;
&lt;br /&gt;
:Meine Empfehlung ist deswegen klar diese, dass der frei laufende Betrieb nur bei einem einzelnen zu verwendenden Analogeingang verwendet werden sollte, wenn man sich Probleme bei der Umschalterei ersparen will.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Aktivieren des ADC ====&lt;br /&gt;
&lt;br /&gt;
Um den &#039;&#039;&#039; ADC&#039;&#039;&#039; zu aktivieren, müssen wir das &#039;&#039;&#039;ADEN&#039;&#039;&#039;-Bit im &#039;&#039;&#039;ADCSR&#039;&#039;&#039;-Register&lt;br /&gt;
setzen. Im gleichen Schritt legen wir auch gleich die Betriebsart fest. &lt;br /&gt;
&lt;br /&gt;
Ein kleines Beispiel für den &amp;quot;single conversion&amp;quot;-Mode bei einem ATmega169 und Nutzung der internen Referenzspannung (beim &#039;169 1,1V bei anderen AVRs auch 2,56V). D.h. das Eingangssignal darf diese Spannung nicht überschreiten, gegebenenfalls mit Spannungsteiler konditionieren. Ergebnis der Routine ist der ADC-Wert, also 0 für 0-Volt und 1024 für V_ref-Volt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define CHANNELOFFSET 4&lt;br /&gt;
&lt;br /&gt;
uint16_t ReadChannel(uint8_t channel)&lt;br /&gt;
{&lt;br /&gt;
  uint8_t i;&lt;br /&gt;
  uint16_t result;&lt;br /&gt;
  &lt;br /&gt;
  ADCSRA = (1&amp;lt;&amp;lt;ADEN) | (1&amp;lt;&amp;lt;ADPS1) | (1&amp;lt;&amp;lt;ADPS0);    // Frequenzvorteiler &lt;br /&gt;
                               // setzen auf 8 (1) und ADC aktivieren (1)&lt;br /&gt;
&lt;br /&gt;
  ADMUX = CHANNELOFFSET+channel;    // Kanal waehlen&lt;br /&gt;
  ADMUX |= (1&amp;lt;&amp;lt;REFS1) | (1&amp;lt;&amp;lt;REFS0); // interne Referenzspannung nutzen &lt;br /&gt;
&lt;br /&gt;
  /* nach Aktivieren des ADC wird ein &amp;quot;Dummy-Readout&amp;quot; empfohlen, man liest&lt;br /&gt;
     also einen Wert und verwirft diesen, um den ADC &amp;quot;warmlaufen zu lassen&amp;quot; */&lt;br /&gt;
  ADCSRA |= (1&amp;lt;&amp;lt;ADSC);              // eine ADC-Wandlung &lt;br /&gt;
  &amp;lt;!--while(!(ADCSRA &amp;amp; 0x10));      // auf Abschluss der Konvertierung warten (ADIF-bit) --&amp;gt;&lt;br /&gt;
  while(!(ADCSRA &amp;amp; (1&amp;lt;&amp;lt;ADIF)));     // auf Abschluss der Konvertierung warten (ADIF-bit)&lt;br /&gt;
        &lt;br /&gt;
  result = 0;&lt;br /&gt;
&lt;br /&gt;
  /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */&lt;br /&gt;
  for(i=0;i&amp;lt;4;i++)&lt;br /&gt;
  {&lt;br /&gt;
    ADCSRA |= (1&amp;lt;&amp;lt;ADSC);            // eine Wandlung &amp;quot;single conversion&amp;quot;&lt;br /&gt;
    while(!(ADCSRA &amp;amp; (1&amp;lt;&amp;lt;ADIF)));   // auf Abschluss der Konvertierung warten (ADIF-bit)&lt;br /&gt;
    result += ADC;		    // Wandlungsergebnisse aufaddieren&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  ADCSRA &amp;amp;= ~(1&amp;lt;&amp;lt;ADEN);             // ADC deaktivieren (2)&lt;br /&gt;
&lt;br /&gt;
  result &amp;gt;&amp;gt;= 2;                     // Summe durch vier teilen = arithm. Mittelwert&lt;br /&gt;
&lt;br /&gt;
  return result;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Beispiel wird bei jedem Aufruf der ADC aktiviert und nach der Wandlung wieder abgeschaltet, das spart Strom. Will man dies nicht, verschiebt man die mit (1) gekenntzeichneten Zeilen in eine Funktion adc_init() o.ä. und löscht die mit (2) markierten Zeilen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Wenn wir frei laufend arbeiten wollen setzen wir zusätzlich das &#039;&#039;&#039;ADFR&#039;&#039;&#039;-Bit. Bei&lt;br /&gt;
Bedarf wird auch gleich der Teilungsfaktor eingestellt.&lt;br /&gt;
&lt;br /&gt;
TODO: fix&lt;br /&gt;
&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;&#039;&#039;&#039;// Teilungsfaktor auf 8 und ADC aktivieren&amp;lt;br /&amp;gt;&lt;br /&gt;
// Nicht frei laufend&amp;lt;br /&amp;gt;&lt;br /&gt;
outp ((1&amp;lt;&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um nun eine einzelne Messung, sagen wir mal an Pin 3, durchzuführen schalten wir den Kanal ein, starten die Wandlung und warten, bis der &#039;&#039;&#039;ADC&#039;&#039;&#039; die Beendigung meldet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;&#039;&#039;&#039;outp ((1&amp;lt;&lt;br /&gt;
sbi (ADCSR, ADSC);&amp;lt;br /&amp;gt;&lt;br /&gt;
while (bit_is_set (ADCSR, ADSC)) /* Nur warten */;&amp;lt;br /&amp;gt;&lt;br /&gt;
x = __inw (ADCL);  ODER x=ADCW        // Wert auslesen&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;#FF0000&amp;quot;&amp;gt;Da ich leider bisher noch kein Experimentierboard für&lt;br /&gt;
den 8535 gebastelt habe kann ich euch auch keine erprobte Übung anbieten.&amp;lt;/font&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== DAC (Digital Analog Converter) ==&lt;br /&gt;
&lt;br /&gt;
Mit Hilfe eines &#039;&#039;&#039; DAC&#039;&#039;&#039; können wir nun auch Analogsignale ausgeben. Es gibt hier&lt;br /&gt;
mehrere Verfahren. Wenn wir beim &#039;&#039;&#039; ADC&#039;&#039;&#039; die Möglichkeit haben, mit externen&lt;br /&gt;
Komponenten zu operieren, müssen wir bei der &#039;&#039;&#039;DAC&#039;&#039;&#039;-Wandlung mit dem auskommen, was&lt;br /&gt;
der Controller selber zu bieten hat.&lt;br /&gt;
&lt;br /&gt;
=== DAC über mehrere digitale Ausgänge ===&lt;br /&gt;
&lt;br /&gt;
Wenn wir an den Ausgängen des Controllers ein entsprechendes&lt;br /&gt;
Widerstandsnetzwerk aufbauen haben wir die Möglichkeit, durch die Ansteuerung&lt;br /&gt;
der Ausgänge über den Widerständen einen Addierer aufzubauen, mit dessen&lt;br /&gt;
Hilfe wir eine dem Zahlenwert proportionale Spannung erzeugen können. Das&lt;br /&gt;
Schaltbild dazu kann etwa so aussehen:&lt;br /&gt;
&lt;br /&gt;
[[Image:DAC R2R.gif]]&lt;br /&gt;
&lt;br /&gt;
Es sollten selbstverständlich möglichst genaue Widerstände verwendet&lt;br /&gt;
werden, also nicht unbedingt solche mit einer Toleranz von 10% oder mehr.&lt;br /&gt;
Weiterhin empfiehlt es sich, je nach Anwendung den Ausgangsstrom über einen&lt;br /&gt;
Operationsverstärker zu verstärken.&lt;br /&gt;
&lt;br /&gt;
=== PWM (Pulsweitenmodulation) ===&lt;br /&gt;
&lt;br /&gt;
Wir kommen nun zu einem Thema, welches in aller Munde ist, aber viele&lt;br /&gt;
Anwender verstehen nicht ganz, wie &#039;&#039;&#039; PWM&#039;&#039;&#039; eigentlich funktioniert.&lt;br /&gt;
&lt;br /&gt;
Wie wir alle wissen ist ein Mikrocontroller ein rein digitales Bauteil.&lt;br /&gt;
Definieren wir einen Pin als Ausgang, dann können wir diesen Ausgang entweder&lt;br /&gt;
auf HIGH setzen, worauf am Ausgang die Versorgungsspannung &#039;&#039;&#039; Vcc&#039;&#039;&#039; anliegt, oder aber&lt;br /&gt;
wir setzen den Ausgang auf LOW, wonach dann &#039;&#039;&#039; 0V&#039;&#039;&#039; am Ausgang liegt.&amp;lt;br /&amp;gt;&lt;br /&gt;
Was passiert aber nun, wenn wir periodisch mit einer festen Frequenz zwischen&lt;br /&gt;
HIGH und LOW umschalten?&amp;lt;br /&amp;gt;&lt;br /&gt;
Richtig, wir erhalten eine Rechteckspannung, wie die folgende Abbildung zeigt:&lt;br /&gt;
&lt;br /&gt;
[[Image:PWM Theorie 1.gif]]&lt;br /&gt;
&lt;br /&gt;
Diese Rechteckspannung hat nun einen geometrischen Mittelwert, der je nach Pulsbreite&lt;br /&gt;
kleiner oder grösser ist.&lt;br /&gt;
&lt;br /&gt;
[[Image:PWM Theorie 2.gif]]&lt;br /&gt;
&lt;br /&gt;
Wenn wir nun diese pulsierende Ausgangsspannung noch über ein&lt;br /&gt;
RC-Glied filtern dann haben wir schon eine entsprechende Gleichspannung erzeugt.&lt;br /&gt;
&lt;br /&gt;
Mit den AVR&#039;s können wir direkt &#039;&#039;&#039;PWM&#039;&#039;&#039;-Signale erzeugen. Dazu&lt;br /&gt;
dient der 16-Bit Zähler, welcher im sogenannten &#039;&#039;&#039;PWM&#039;&#039;&#039;-Modus betrieben werden&lt;br /&gt;
kann.&lt;br /&gt;
&lt;br /&gt;
Hinweis:&lt;br /&gt;
:In den folgenden Überlegungen wird als Controller der 90S2313 vorausgesetzt. Die Theorie ist allerdings bei anderen AVR-Controllern vergleichbar, die Pinbelegung allerdings nicht unbedingt.&lt;br /&gt;
&lt;br /&gt;
Um den &#039;&#039;&#039;PWM&#039;&#039;&#039;-Modus zu aktivieren müssen im Timer/Counter1 Control&lt;br /&gt;
Register A &#039;&#039;&#039;TCCR1A&#039;&#039;&#039; die Pulsweiten-Modulatorbits &#039;&#039;&#039;PWM10&#039;&#039;&#039; bzw. &#039;&#039;&#039;PWM11&#039;&#039;&#039; entsprechend&lt;br /&gt;
nachfolgender Tabelle gesetzt werden:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;PWM11&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;PWM10&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Bedeutung&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| PWM-Modus des Timers ist nicht aktiv.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| 8-Bit PWM.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| 9-Bit PWM.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| 10-Bit PWM.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Der Timer/Counter zählt nun permanent von 0 bis zur Obergrenze&lt;br /&gt;
und wieder zurück, er wird also als sogenannter Auf-/Ab Zähler betrieben. Die&lt;br /&gt;
Obergrenze hängt davon ab, ob wir mit 8, 9 oder 10-Bit PWM arbeiten wollen:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;Auflösung&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;Obergrenze&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Frequenz&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 8&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 255&lt;br /&gt;
| f&amp;lt;sub&amp;gt;TC1&amp;lt;/sub&amp;gt; / 510&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 9&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 511&lt;br /&gt;
| f&amp;lt;sub&amp;gt;TC1&amp;lt;/sub&amp;gt; / 1022&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 10&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1023&lt;br /&gt;
| f&amp;lt;sub&amp;gt;TC1&amp;lt;/sub&amp;gt; / 2046&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Zusätzlich muss mit den Bits &#039;&#039;&#039;COM1A1&#039;&#039;&#039; und &#039;&#039;&#039;COM1A0&#039;&#039;&#039; desselben&lt;br /&gt;
Registers die gewünschte Ausgabeart des Signals definiert werden:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;COM1A1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;COM1A0&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Bedeutung&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Keine Wirkung, Pin wird nicht geschaltet.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Keine Wirkung, Pin wird nicht geschaltet.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Nicht invertierende PWM.&amp;lt;br /&amp;gt;&lt;br /&gt;
Der Ausgangspin wird gelöscht beim Hochzählen und gesetzt beim&lt;br /&gt;
Herunterzählen.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Invertierende PWM.&amp;lt;br /&amp;gt;&lt;br /&gt;
Der Ausgangspin wird gelöscht beim Herunterzählen und gesetzt beim&lt;br /&gt;
Hochzählen.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Der entsprechende Befehl um beispielsweise den Timer/Counter als&lt;br /&gt;
nicht invertierenden 10-Bit PWM zu verwenden heisst dann:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
TCCR1A = (1&amp;lt;&amp;lt;PWM11)|(1&amp;lt;&amp;lt;PWM10)|(1&amp;lt;&amp;lt;COM1A1);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit der Timer/Counter überhaupt läuft müssen wir im Control&lt;br /&gt;
Register B &#039;&#039;&#039;TCCR1B&#039;&#039;&#039; noch den gewünschten Takt (Vorzähler) einstellen, und&lt;br /&gt;
somit auch die Frequenz des &#039;&#039;&#039;PWM&#039;&#039;&#039;-Signals bestimmen.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;CS12&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;CS11&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;CS10&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Bedeutung&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Stop. Der Timer/Counter wird gestoppt.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| CK&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| CK / 8&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| CK / 64&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| CK / 256&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| CK / 1024&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Externer Pin 1, negative Flanke&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Externer Pin 1, positive Flanke&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Also um einen Takt von CK / 1024 zu generieren, verwenden wir&lt;br /&gt;
folgenden Befehl:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
TCCR1B = (1&amp;lt;&amp;lt;CS12) | (1&amp;lt;&amp;lt;CS10);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Jetzt muss nur noch der Vergleichswert festgelegt werden. Diesen&lt;br /&gt;
schreiben wir in das 16-Bit Timer/Counter Output Compare Register &#039;&#039;&#039;OCR1A&#039;&#039;&#039;.&lt;br /&gt;
&amp;lt;!--Wir können dazu den von der Bibliothek zur Verfügung gestellten Befehl zum&lt;br /&gt;
Schreiben von 16-Bit Registern verwenden, als Portadresse wird das Low-Byte des&lt;br /&gt;
Ports verwendet. [oxygene: Dieser Absatz trifft wohl nur auf __outw zu]&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- &amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;&#039;&#039;&#039;__outw (xxx, OCR1AL);&#039;&#039;&#039;&amp;lt;/font&amp;gt; --&amp;gt;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
OCR1A = xxx;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die folgende Grafik soll den Zusammenhang zwischen dem&lt;br /&gt;
Vergleichswert und dem generierten &#039;&#039;&#039;PWM&#039;&#039;&#039;-Signal aufzeigen.&lt;br /&gt;
&lt;br /&gt;
[[Image:PWM Theorie 3.gif]]&lt;br /&gt;
&lt;br /&gt;
[[Image:PWM Theorie 4.gif]]&lt;br /&gt;
&lt;br /&gt;
Ach ja, fast hätte ich&#039;s vergessen. Das generierte &#039;&#039;&#039;PWM&#039;&#039;&#039;-Signal&lt;br /&gt;
wird am Output Compare Pin &#039;&#039;&#039;OC1&#039;&#039;&#039; des Timers ausgegeben und leider können wir&lt;br /&gt;
deshalb auch nur ein einzelnes &#039;&#039;&#039;PWM&#039;&#039;&#039;-Signal mit dieser Methode generieren.&lt;br /&gt;
&lt;br /&gt;
= Die Timer/Counter des AVR =&lt;br /&gt;
&lt;br /&gt;
Die heutigen Mikrocontroller und insbesondere die RISC-AVR&#039;s sind für viele&lt;br /&gt;
Steuerungsaufgaben natürlich viel zu schnell. Wenn wir beispielsweise eine LED&lt;br /&gt;
oder Lampe blinken lassen wollen, können wir selbstverständlich nicht die&lt;br /&gt;
CPU-Frequenz verwenden da ja dann nichts mehr vom Blinken zu bemerken wäre.&lt;br /&gt;
&lt;br /&gt;
Wir brauchen also eine Möglichkeit, die Taktfrequenz auf vernünftige Werte&lt;br /&gt;
herunter zu brechen. Selbstverständlich sollte die resultierende Frequenz dann&lt;br /&gt;
auch noch einigermassen genau und stabil sein.&lt;br /&gt;
&lt;br /&gt;
Hier kommen die im AVR vorhandenen Timer/Counter zum Einsatz.&lt;br /&gt;
&lt;br /&gt;
Ein anderes Anwendungsgebiet ist die Zählung von Signalen, welche über&lt;br /&gt;
einen I/O-Pin zugeführt werden können.&lt;br /&gt;
&lt;br /&gt;
Die folgenden Ausführungen beziehen sich auch den AT90S2313. Für andere&lt;br /&gt;
Modelltypen müsst ihr euch die allenfalls notwendigen Anpassungen aus den&lt;br /&gt;
Datenblättern der entsprechenden Controller herauslesen.&lt;br /&gt;
&lt;br /&gt;
Wir unterscheiden grundsätzlich zwischen 8-Bit Timern, welche eine&lt;br /&gt;
Auflösung von 256 aufweisen und 16-Bit Timern mit (logischerweise) einer&lt;br /&gt;
Auflösung von 65536.&lt;br /&gt;
&lt;br /&gt;
Als Eingangstakt für die Timer/Counter kann entweder die CPU-Taktfrequenz,&lt;br /&gt;
der Vorteiler-Ausgang oder ein an einen I/O-Pin angelegtes Signal verwendet&lt;br /&gt;
werden. Wenn ein externes Signal verwendet wird, so darf dessen Frequenz nicht&lt;br /&gt;
höher sein als die Hälfte des CPU-Taktes.&lt;br /&gt;
&lt;br /&gt;
=== Der Vorzähler (Prescaler) ===&lt;br /&gt;
&lt;br /&gt;
Beide Timer/Counter werden im Timerbetrieb über den gleichen Vorzähler&lt;br /&gt;
versorgt.&lt;br /&gt;
&lt;br /&gt;
Der Vorzähler dient dazu, den CPU-Takt vorerst mal runter zu brechen auf eine&lt;br /&gt;
wählbare Teilung. Die so geteilte Frequenz wird den Eingängen der Timer&lt;br /&gt;
zugeführt.&lt;br /&gt;
&lt;br /&gt;
Wenn wir mit einer einem CPU-Takt von 4 MHz arbeiten und den Vorteiler auf 1024&lt;br /&gt;
einstellen wird also der Timer mit einer Frequenz von 4 MHz / 1024, also mit ca.&lt;br /&gt;
4 kHz versorgt. Wenn also der Timer läuft, so wird das Daten- bzw.&lt;br /&gt;
Zählregister mit dieser Frequenz inkrementiert.&lt;br /&gt;
&lt;br /&gt;
== 8-Bit Timer/Counter ==&lt;br /&gt;
&lt;br /&gt;
Alle AVR-Modelle weisen mindestens einen, teilweise sogar zwei, 8-Bit Timer&lt;br /&gt;
auf.&lt;br /&gt;
&lt;br /&gt;
Der 8-Bit Timer wird über folgende Register angesprochen:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;TCCR0&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;T&#039;&#039;&#039;imer/&#039;&#039;&#039;C&#039;&#039;&#039;ounter &#039;&#039;&#039;C&#039;&#039;&#039;ontrol &#039;&#039;&#039;R&#039;&#039;&#039;egister&lt;br /&gt;
Timer &#039;&#039;&#039;0&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
In diesem Register stellen wir ein, wie wir den Timer/Counter verwenden möchten.&lt;br /&gt;
&lt;br /&gt;
Das Register ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;CS02&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;CS01&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;CS00&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CS02, CS01, CS00&#039;&#039;&#039; (&#039;&#039;&#039;C&#039;&#039;&#039;lock &#039;&#039;&#039;S&#039;&#039;&#039;elect Bits)&lt;br /&gt;
:Diese 3 Bits bestimmen die Quelle für den Timer/Counter:&lt;br /&gt;
&amp;lt;dl&amp;gt;&amp;lt;dd&amp;gt;&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | CS02&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | CS01&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | CS00&lt;br /&gt;
| Resultat&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Stopp, Der Timer/Counter wird angehalten.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| CPU-Takt&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| CPU-Takt / 8&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| CPU-Takt / 64&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| CPU-Takt / 256&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| CPU-Takt / 1024&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Externer Pin &#039;&#039;&#039;TO&#039;&#039;&#039;, fallende Flanke&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Externer Pin &#039;&#039;&#039;TO&#039;&#039;&#039;, steigende Flanke&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/dd&amp;gt;&lt;br /&gt;
&amp;lt;/dl&amp;gt;&lt;br /&gt;
:Wenn als Quelle der externe Pin &#039;&#039;&#039;TO&#039;&#039;&#039; verwendet wird, so wird ein Flankenwechsel auch erkannt, wenn der Pin &#039;&#039;&#039;TO&#039;&#039;&#039; als Ausgang geschaltet ist.&lt;br /&gt;
&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;TCNT0&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;T&#039;&#039;&#039;imer/&#039;&#039;&#039;C&#039;&#039;&#039;ou&#039;&#039;&#039;nt&#039;&#039;&#039;er Daten Register Timer &#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Dieses ist als 8-Bit Aufwärtszähler mit Schreib- und Lesezugriff&lt;br /&gt;
realisiert. Wenn der Zähler den Wert 255 erreicht hat beginnt er beim&lt;br /&gt;
nächsten Zyklus wieder bei 0.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;MSB&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;LSB&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Um nun also den Timer0 in Betrieb zu setzen und ihn mit einer Frequenz von 1/1024-tel des CPU-Taktes zählen zu lassen, schreiben wir die folgende Befehlszeile:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
TCCR0 = (1&amp;lt;&amp;lt;CS00)|(1&amp;lt;&amp;lt;CS02);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Zähler zählt nun aufwärts bis 255, um dann wieder bei 0 zu beginnen. Der aktuelle Zählerstand steht in TCNT0. Bei jedem Überlauf von 255 auf 0 wird das Timer Overflow Flag &#039;&#039;&#039;TOV0&#039;&#039;&#039; im Timer Interrupt Flag &#039;&#039;&#039;TIFR&#039;&#039;&#039;-Register gesetzt und, falls so konfiguriert, ein entsprechender Timer-Overflow-Interrupt ausgelöst.&lt;br /&gt;
&lt;br /&gt;
== 16-Bit Timer/Counter ==&lt;br /&gt;
&lt;br /&gt;
Viele AVR-Modelle besitzen ausser den 8-Bit Timers auch einen oder sogar zwei&lt;br /&gt;
(einige ATmega-Modelle) 16-Bit Timer.&lt;br /&gt;
&lt;br /&gt;
Die 16-Bit Timer/Counter sind wesentlich komplexer aufgebaut als die 8-Bit&lt;br /&gt;
Timer/Counter, bieten dafür aber auch viel mehr Möglichkeiten, als da sind:&lt;br /&gt;
&lt;br /&gt;
* Die [[PWM]]-Betriebsart Erzeugung eines pulsweitenmodulierten Ausgangssignals. &lt;br /&gt;
* Vergleichswert-Überprüfung mit Erzeugung eines Ausgangssignals (Output Compare Match).&lt;br /&gt;
* Einfangen eines Eingangssignals mit Speicherung des aktuellen Zählerwertes (Input Capturing), mit zuschaltbarer Rauschunterdrückung (Noise Filtering).&lt;br /&gt;
&lt;br /&gt;
Folgende Register sind dem Timer/Counter 1 zugeordnet:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;TCCR1A&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;T&#039;&#039;&#039;imer/&#039;&#039;&#039;C&#039;&#039;&#039;ounter &#039;&#039;&#039;C&#039;&#039;&#039;ontrol &#039;&#039;&#039;R&#039;&#039;&#039;egister &#039;&#039;&#039;A&#039;&#039;&#039; Timer &#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
In diesem und dem folgenden Register stellen wir ein, wie wir den Timer/Counter verwenden möchten.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Register ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;COM1A1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;COM1A0&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;PWM11&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;PWM10&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;COM1A1&#039;&#039;&#039;, &#039;&#039;&#039;COM1A0&#039;&#039;&#039; (&#039;&#039;&#039;Co&#039;&#039;&#039;mpare &#039;&#039;&#039;M&#039;&#039;&#039;atch Control Bits)&lt;br /&gt;
:Diese 2 Bits bestimmen die Aktion, welche am Output-Pin &#039;&#039;&#039;OC1&#039;&#039;&#039; ausgeführt werden soll, wenn der Wert des Datenregisters des Timer/Counter 1 den Wert des Vergleichsregisters erreicht, also ein so genannter Compare Match auftritt.&lt;br /&gt;
:Der Pin &#039;&#039;&#039;OC1&#039;&#039;&#039; (&#039;&#039;&#039;PB3&#039;&#039;&#039; beim 2313) muss mit dem Datenrichtungsregister als Ausgang konfiguriert werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dl&amp;gt;&amp;lt;dd&amp;gt;&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | COM1A1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | COM1A0&lt;br /&gt;
| Resultat&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Output-Pin &#039;&#039;&#039;OC1&#039;&#039;&#039; wird nicht angesteuert.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Das Signal am Pin &#039;&#039;&#039;OC1&#039;&#039;&#039; wird invertiert (Toggle).&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Der Output Pin &#039;&#039;&#039;OC1&#039;&#039;&#039; wird auf 0 gesetzt.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Der Output Pin &#039;&#039;&#039;OC1&#039;&#039;&#039; wird auf 1 gesetzt.&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/dd&amp;gt;&amp;lt;/dl&amp;gt;&lt;br /&gt;
:In der PWM-Betriebsart haben diese Bits eine andere Funktion.&lt;br /&gt;
&amp;lt;dl&amp;gt;&amp;lt;dd&amp;gt;&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | COM1A1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | COM1A0&lt;br /&gt;
| Resultat&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Output-Pin &#039;&#039;&#039;OC1&#039;&#039;&#039; wird nicht angesteuert.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Output-Pin &#039;&#039;&#039;OC1&#039;&#039;&#039; wird nicht angesteuert.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Wird beim Hochzählen der Wert im Vergleichsregister erreicht, so wird der Pin &#039;&#039;&#039;OC1&#039;&#039;&#039; auf 0 gesetzt.&lt;br /&gt;
Wird beim Herunterzählen der Wert im Vergleichsregister erreicht, so wird der Pin auf 1 gesetzt.&lt;br /&gt;
&lt;br /&gt;
Man nennt dies &#039;&#039;nicht invertierende PWM&#039;&#039;.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Wird beim Hochzählen der Wert im Vergleichsregister erreicht, so wird der Pin &#039;&#039;&#039;OC1&#039;&#039;&#039; auf 1 gesetzt.&lt;br /&gt;
Wird beim Herunterzählen der Wert im Vergleichsregister erreicht, so wird der Pin auf 0 gesetzt.&lt;br /&gt;
&lt;br /&gt;
Man nennt dies &#039;&#039;invertierende PWM&#039;&#039;.&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/dd&amp;gt;&amp;lt;/dl&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;PWM11&#039;&#039;&#039;, &#039;&#039;&#039;PWM10&#039;&#039;&#039; (&#039;&#039;&#039;PWM&#039;&#039;&#039; Mode Select Bits)&lt;br /&gt;
:Mit diesen 2 Bits wird die PWM-Betriebsart des Timer/Counter 1 gesteuert.&lt;br /&gt;
&amp;lt;dl&amp;gt;&amp;lt;dd&amp;gt;&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | PWM11&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | PWM10&lt;br /&gt;
| Resultat&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Die PWM-Betriebsart ist nicht aktiviert. Timer/Counter 1 arbeitet als normaler Timer bzw. Zähler.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| 8-Bit PWM Betriebsart aktivieren.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| 9-Bit PWM Betriebsart aktivieren.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| 10-Bit PWM Betriebsart aktivieren.&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/dd&amp;gt;&amp;lt;/dl&amp;gt;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;TCCR1B&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;T&#039;&#039;&#039;imer/&#039;&#039;&#039;C&#039;&#039;&#039;ounter &#039;&#039;&#039;C&#039;&#039;&#039;ontrol &#039;&#039;&#039;R&#039;&#039;&#039;egister &#039;&#039;&#039;B&#039;&#039;&#039; Timer &#039;&#039;&#039;1&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ICNC1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ICES1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;CTC1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;CS12&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;CS11&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;CS10&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ICNC1&#039;&#039;&#039; (&#039;&#039;&#039;I&#039;&#039;&#039;nput &#039;&#039;&#039;C&#039;&#039;&#039;apture &#039;&#039;&#039;N&#039;&#039;&#039;oise &#039;&#039;&#039;C&#039;&#039;&#039;anceler (4 CKs) Timer/Counter 1&lt;br /&gt;
:oder auf Deutsch Rauschunterdrückung des Eingangssignals.&lt;br /&gt;
:Wenn dieses Bit gesetzt ist und mit dem Input Capture Signal gearbeitet wird so werden nach der Triggerung des Signals mit der entsprechenden Flanke (steigend oder fallend) am Input Capture Pin &#039;&#039;&#039;ICP&#039;&#039;&#039; jeweils 4 Messungen mit der CPU-Frequenz des Eingangssignals abgefragt. Nur dann, wenn alle 4 Messungen den gleichen Zustand aufweisen gilt das Signal als erkannt.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ICES1&#039;&#039;&#039; (&#039;&#039;&#039;I&#039;&#039;&#039;nput &#039;&#039;&#039;C&#039;&#039;&#039;apture &#039;&#039;&#039;E&#039;&#039;&#039;dge &#039;&#039;&#039;S&#039;&#039;&#039;elect Timer/Counter &#039;&#039;&#039;1&#039;&#039;&#039;)&lt;br /&gt;
:Mit diesem Bit wird bestimmt, ob die steigende (&#039;&#039;&#039;ICES1&#039;&#039;&#039;=1) oder fallende (&#039;&#039;&#039;ICES1&#039;&#039;&#039;=0) Flanke zur Auswertung des Input Capture Signals an Pin &#039;&#039;&#039;ICP&#039;&#039;&#039; heran gezogen wird.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CTC1&#039;&#039;&#039; (&#039;&#039;&#039;C&#039;&#039;&#039;lear &#039;&#039;&#039;T&#039;&#039;&#039;imer/&#039;&#039;&#039;C&#039;&#039;&#039;ounter on Compare Match Timer/Counter &#039;&#039;&#039;1&#039;&#039;&#039;)&lt;br /&gt;
:Wenn dieses Bit gesetzt ist, so wird nach einer Übereinstimmung des Datenregisters &#039;&#039;&#039;TCNT1H&#039;&#039;&#039;/&#039;&#039;&#039;TCNT1L&#039;&#039;&#039; mit dem Vergleichswert in &#039;&#039;&#039;OCR1H&#039;&#039;&#039;/&#039;&#039;&#039;OCR1L&#039;&#039;&#039; das Datenregister &#039;&#039;&#039;TCNT1H&#039;&#039;&#039;/&#039;&#039;&#039;TCNT1L&#039;&#039;&#039; auf 0 gesetzt.&lt;br /&gt;
:Da die Übereinstimmung im Takt nach dem Vergleich behandelt wird, ergibt sich je nach eingestelltem Vorzähler ein etwas anderes Zählverhalten:&lt;br /&gt;
:Wenn der Vorteiler auf 1 gestellt ist und C der jeweilige Zählerwert ist, dann nimmt das Datenregister, im CPU-Takt betrachtet, folgende Werte an:&lt;br /&gt;
:... | C-2 | C-1 | C | 0 | 1 |...&lt;br /&gt;
:Wenn der Vorteiler z.B. auf 8 eingestellt ist, dann nimmt das Datenregister folgende Werte an:&lt;br /&gt;
:... | C-2, C-2, C-2, C-2, C-2, C-2, C-2, C-2 | C-1, C-1, C-1, C-1, C-1, C-1, C-1, C-1 | C, 0, 0, 0, 0, 0, 0, 0 |...&lt;br /&gt;
:In der PWM-Betriebsart hat dieses Bit keine Funktion.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;CS12&#039;&#039;&#039;, &#039;&#039;&#039;CS11&#039;&#039;&#039;, &#039;&#039;&#039;CS10&#039;&#039;&#039; (&#039;&#039;&#039;C&#039;&#039;&#039;lock &#039;&#039;&#039;S&#039;&#039;&#039;elect Bits)&lt;br /&gt;
:Diese 3 Bits bestimmen die Quelle für den Timer/Counter:&lt;br /&gt;
&amp;lt;dl&amp;gt;&amp;lt;dd&amp;gt;&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | CS12&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | CS11&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | CS10&lt;br /&gt;
| Resultat&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Stopp, Der Timer/Counter wird angehalten.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| CPU-Takt&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| CPU-Takt / 8&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| CPU-Takt / 64&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| CPU-Takt / 256&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| CPU-Takt / 1024&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Externer Pin TO, fallende Flanke&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Externer Pin T0, steigende Flanke&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/dd&amp;gt;&amp;lt;/dl&amp;gt;&lt;br /&gt;
:Wenn als Quelle der externe Pin T0 verwendet wird, so wird ein Flankenwechsel auch erkannt, wenn der Pin T0 als Ausgang geschaltet ist.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;TCNT1H&#039;&#039;&#039;&amp;lt;br /&amp;gt;&#039;&#039;&#039;TCNT1L&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;T&#039;&#039;&#039;imer/&#039;&#039;&#039;C&#039;&#039;&#039;ou&#039;&#039;&#039;nt&#039;&#039;&#039;er Daten Register Timer/Counter &#039;&#039;&#039;1&#039;&#039;&#039;&lt;br /&gt;
Dieses ist als 16-Bit Aufwärtszähler mit Schreib- und Lesezugriff realisiert. Wenn der Zähler den Wert 65535 erreicht hat, beginnt er beim nächsten Zyklus wieder bei 0.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;MSB&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;TCNT1H&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;LSB&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;TCNT1L&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In der PWM-Betriebsart wird das Register als Auf/Ab-Zähler verwendet, d.h. der Wert steigt zuerst von 0 bis er den Überlauf von 65535 auf 0 erreicht hat. Dann zählt das Register rückwärts wiederum bis 0.&lt;br /&gt;
&lt;br /&gt;
Zum Auslesen des Registers wird von der CPU ein internes TEMP-Register verwendet. Das gleiche Register wird auch verwendet, wenn auf &#039;&#039;&#039;OCR1&#039;&#039;&#039; oder &#039;&#039;&#039;ICR1&#039;&#039;&#039; zugegriffen wird.&lt;br /&gt;
&lt;br /&gt;
Deshalb müssen vor dem Zugriff auf eines dieser Register alle Interrupts gesperrt werden, weil sonst die Möglichkeit des gleichzeitigen Zugriffs auf das Temporärregister gegeben ist, was natürlich zu fehlerhaftem Verhalten des Programms führt.. Zudem muss zuerst &#039;&#039;&#039;TCNT1L&#039;&#039;&#039; und erst danach &#039;&#039;&#039;TCNT1H&#039;&#039;&#039; ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Wenn in das Register geschrieben werden soll, müssen ebenfalls alle Interrrupts gesperrt werden. Dann muss zuerst das &#039;&#039;&#039;TCNT1H&#039;&#039;&#039;-Register und erst danach das &#039;&#039;&#039;TCNT1L&#039;&#039;&#039;-Register geschrieben werden, also genau die umgekehrte Reihenfolge wie beim Lesen des Registers.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;OCR1H&#039;&#039;&#039;&amp;lt;br /&amp;gt;&#039;&#039;&#039;OCR1L&#039;&#039;&#039;&lt;br /&gt;
| Timer/Counter &#039;&#039;&#039;O&#039;&#039;&#039;utput &#039;&#039;&#039;C&#039;&#039;&#039;ompare &#039;&#039;&#039;R&#039;&#039;&#039;egister Timer/Counter &#039;&#039;&#039;1&#039;&#039;&#039;&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;MSB&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;OCR1H&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;LSB&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;OCR1L&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Der Wert im Output Compare Register wird ständig mit dem aktuellen Wert im Datenregister TCNT1H/TCNT1L verglichen. Stimmen die beiden Werte überein, so wird ein sogenannter Output Compare Match ausgelöst. Die entsprechenden Aktionen werden über die Timer/Counter 1 Control und Status Register eingestellt.&lt;br /&gt;
&lt;br /&gt;
Zum Auslesen des Registers wird von der CPU ein internes TEMP-Register verwendet. Das gleiche Register wird auch verwendet, wenn auf &#039;&#039;&#039;OCR1&#039;&#039;&#039; oder &#039;&#039;&#039;ICR1&#039;&#039;&#039; zugegriffen wird.&lt;br /&gt;
Deshalb müssen vor dem Zugriff auf eines dieser Register alle Interrupts gesperrt werden, weil sonst die Möglichkeit des gleichzeitigen Zugriffs auf das Temporärregister gegeben ist, was natürlich zu fehlerhaftem Verhalten des Programms führt.. Zudem muss zuerst &#039;&#039;&#039;TCNT1L&#039;&#039;&#039; und erst danach &#039;&#039;&#039;TCNT1H&#039;&#039;&#039; ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Wenn in das Register geschrieben werden soll, müssen ebenfalls alle Interrupts gesperrt werden. Dann muss zuerst das &#039;&#039;&#039;TCNT1H&#039;&#039;&#039;-Register und erst danach das &#039;&#039;&#039;TCNT1L&#039;&#039;&#039;-Register geschrieben werden, also genau die umgekehrte Reihenfolge wie beim Lesen des Registers.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;ICR1H&#039;&#039;&#039;&amp;lt;br /&amp;gt;&#039;&#039;&#039;ICR1L&#039;&#039;&#039;&lt;br /&gt;
| Timer/Counter &#039;&#039;&#039;I&#039;&#039;&#039;nput &#039;&#039;&#039;C&#039;&#039;&#039;apture &#039;&#039;&#039;R&#039;&#039;&#039;egister Timer/Counter &#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;MSB&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ICR1&#039;&#039;&#039;&#039;&#039;&#039;H&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;LSB&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ICR1&#039;&#039;&#039;&#039;&#039;&#039;L&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Das Input Capture Register ist ein 16-Bit Register mit Lesezugriff. Es kann nicht beschrieben werden.&lt;br /&gt;
&lt;br /&gt;
Wenn am Input Capture Pin &#039;&#039;&#039;ICP&#039;&#039;&#039; die gemäß Einstellungen im &#039;&#039;&#039;TCCR1B&#039;&#039;&#039; definierte Flanke erkannt wird, so wird der aktuelle Inhalt des Datenregisters &#039;&#039;&#039;TCNT1H&#039;&#039;&#039;/&#039;&#039;&#039;TCNT1L&#039;&#039;&#039; sofort in dieses Register kopiert und das Input Capture Flag &#039;&#039;&#039;ICF1&#039;&#039;&#039; im Timer Interrupt Flag Register &#039;&#039;&#039;TIFR&#039;&#039;&#039; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Wie bereits oben erwähnt, müssen vor dem Zugriff auf dieses Register alle Interrupts gesperrt werden. Zudem müssen Low- und Highbyte des Registers in der richtigen Reihenfolge bearbeitet werden:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| Lesen:&lt;br /&gt;
| &#039;&#039;&#039;ICR1L&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;ICR1H&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| Schreiben:&lt;br /&gt;
| &#039;&#039;&#039;ICR1H&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;ICR1L&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Die PWM-Betriebsart ===&lt;br /&gt;
&lt;br /&gt;
Wenn der Timer/Counter 1 in der PWM-Betriebsart betrieben wird, so bilden das Datenregister &#039;&#039;&#039;TCNT1H&#039;&#039;&#039;/&#039;&#039;&#039;TCNT1L&#039;&#039;&#039; und das Vergleichsregister &#039;&#039;&#039;OCR1H&#039;&#039;&#039;/&#039;&#039;&#039;OCR1L&#039;&#039;&#039; einen 8-, 9- oder 10-Bit, frei laufenden PWM-Modulator, welcher als PWM-Signal am &#039;&#039;&#039;OC1&#039;&#039;&#039;-Pin (&#039;&#039;&#039;PB3&#039;&#039;&#039; beim 2313) abgegriffen werden kann. Das Datenregister &#039;&#039;&#039;TCNT1H&#039;&#039;&#039;/&#039;&#039;&#039;TCNT1L&#039;&#039;&#039; wird dabei als Auf-/Ab-Zähler betrieben, welcher von 0 an aufwärts zählt bis zur Obergrenze und danach wieder zurück auf 0.&lt;br /&gt;
Die Obergrenze ergibt sich daraus, ob 8-, 9- oder 10-Bit PWM verwendet wird, und zwar gemäss folgender Tabelle:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;Auflösung&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;Obergrenze&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Frequenz&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 8&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 255&lt;br /&gt;
| f&amp;lt;sub&amp;gt;TC1&amp;lt;/sub&amp;gt; / 510&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 9&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 511&lt;br /&gt;
| f&amp;lt;sub&amp;gt;TC1&amp;lt;/sub&amp;gt; / 1022&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 10&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1023&lt;br /&gt;
| f&amp;lt;sub&amp;gt;TC1&amp;lt;/sub&amp;gt; / 2046&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Wenn nun der Zählerwert im Datenregister den in &#039;&#039;&#039;OCR1H&#039;&#039;&#039;/&#039;&#039;&#039;OCR1L&#039;&#039;&#039; gespeicherten Wert erreicht, wird der Ausgabepin &#039;&#039;&#039;OC1&#039;&#039;&#039; gesetzt bzw. gelöscht, je nach Einstellung von &#039;&#039;&#039;COM1A1&#039;&#039;&#039; und &#039;&#039;&#039;COM1A0&#039;&#039;&#039; im &#039;&#039;&#039;TCCR1A&#039;&#039;&#039;-Register.&lt;br /&gt;
&lt;br /&gt;
Ich habe versucht, die entsprechenden Signale in der folgenden Grafik zusammenzufassen&lt;br /&gt;
&lt;br /&gt;
[[Image:PWM Theorie 3.gif]]&lt;br /&gt;
&lt;br /&gt;
[[Image:PWM Theorie 4.gif]]&lt;br /&gt;
&lt;br /&gt;
=== Vergleichswert-Überprüfung ===&lt;br /&gt;
&lt;br /&gt;
Hier wird in ein spezielles Vergleichswertregister (&#039;&#039;&#039;OCR1H&#039;&#039;&#039;/&#039;&#039;&#039;OCR1L&#039;&#039;&#039;) ein Wert eingeschrieben, welcher ständig mit dem aktuellen Zählerwert verglichen wird.&lt;br /&gt;
Erreicht der Zähler den in diesem Register eingetragenen Wert, so kann ein Signal (0 oder 1) am Pin &#039;&#039;&#039;OC1&#039;&#039;&#039; erzeugt und/oder ein Interrupt ausgelöst werden.&lt;br /&gt;
&lt;br /&gt;
=== Einfangen eines Eingangssignals (Input Capturing) ===&lt;br /&gt;
&lt;br /&gt;
Bei dieser Betriebsart wird an den Input Capturing Pin (ICP) des Controllers eine Signalquelle angeschlossen.&lt;br /&gt;
Nun kann je nach Konfiguration entweder ein Signalwechsel von 0 nach 1 (steigende Flanke) oder von 1 nach 0 (fallende Flanke) erkannt werden und der zu diesem Zeitpunkt aktuelle Zählerstand in ein spezielles Register abgelegt werden. Gleichzeitig kann auch ein entsprechender Interrupt ausgelöst werden.&lt;br /&gt;
Wenn die Signalquelle ein starkes Rauschen beinhaltet, kann die Rauschunterdrückung eingeschaltet werden. Dann wird beim Erkennen der konfigurierten Flanke über 4 Taktzyklen das Signal überwacht und nur dann, wenn alle 4 Messungen gleich sind, wird die entsprechende Aktion ausgelöst.&lt;br /&gt;
&lt;br /&gt;
== Gemeinsame Register ==&lt;br /&gt;
&lt;br /&gt;
Verschiedene Register beinhalten Zustände und Einstellungen, welche sowohl&lt;br /&gt;
für den 8-Bit, als auch für den 16-Bit Timer/Counter in ein und demselben&lt;br /&gt;
Register zu finden sind.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;TIMSK&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;T&#039;&#039;&#039;imer/Counter &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;M&#039;&#039;&#039;a&#039;&#039;&#039;sk&#039;&#039;&#039;&lt;br /&gt;
Register&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;TOIE1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;OCIE1A&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;TICIE&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;TOIE0&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TOIE1&#039;&#039;&#039; (&#039;&#039;&#039;T&#039;&#039;&#039;imer/Counter &#039;&#039;&#039;O&#039;&#039;&#039;verflow &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;E&#039;&#039;&#039;nable Timer/Counter &#039;&#039;&#039;1&#039;&#039;&#039;)&lt;br /&gt;
:Wenn dieses Bit gesetzt ist, wird bei einem Überlauf des Datenregisters des Timer/Counter 1 ein Timer Overflow 1 Interrupt ausgelöst. Das Global Enable Interrupt Flag muss selbstverständlich auch gesetzt sein.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;OCIE1A&#039;&#039;&#039; (&#039;&#039;&#039;O&#039;&#039;&#039;utput &#039;&#039;&#039;C&#039;&#039;&#039;ompare Match &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;E&#039;&#039;&#039;nable Timer/Counter &#039;&#039;&#039;1&#039;&#039;&#039;)&lt;br /&gt;
:Beim Timer/Counter 1 kann zusätzlich zum Überlauf ein Vergleichswert definiert werden.&lt;br /&gt;
&lt;br /&gt;
:Wenn dieses Bit gesetzt ist, wird beim Erreichen des Vergleichswertes ein Compare Match Interrupt ausgelöst. Das Global Enable Interrupt Flag muss selbstverständlich auch gesetzt sein.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TICIE&#039;&#039;&#039; (&#039;&#039;&#039;T&#039;&#039;&#039;imer/Counter &#039;&#039;&#039;I&#039;&#039;&#039;nput &#039;&#039;&#039;C&#039;&#039;&#039;apture &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;E&#039;&#039;&#039;nable)&lt;br /&gt;
:Wenn dieses Bit gesetzt ist, wird ein Capture Event Interrupt ausgelöst, wenn ein entsprechendes Signalereignis am Pin PD6(ICP) auftritt. Das Global Enable Interrupt Flag muss selbstverständlich auch gesetzt sein, wenn auch ein entsprechender Interrupt ausgelöst werden soll.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TOIE0&#039;&#039;&#039; (&#039;&#039;&#039;T&#039;&#039;&#039;imer/Counter &#039;&#039;&#039;O&#039;&#039;&#039;verflow &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;E&#039;&#039;&#039;nable Timer/Counter &#039;&#039;&#039;0&#039;&#039;&#039;)&lt;br /&gt;
:Wenn dieses Bit gesetzt ist, wird bei einem Überlauf des Datenregisters des Timer/Counter 0 ein Timer Overflow 0 Interrupt ausgelöst. Das Global Enable Interrupt Flag muss selbstverständlich auch gesetzt sein.&lt;br /&gt;
&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;TIFR&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;T&#039;&#039;&#039;imer/Counter &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;F&#039;&#039;&#039;lag &#039;&#039;&#039;R&#039;&#039;&#039;egister&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;TOV1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;OCF1A&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ICF1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;TOV0&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TOV1&#039;&#039;&#039; (&#039;&#039;&#039;T&#039;&#039;&#039;imer/Counter &#039;&#039;&#039;O&#039;&#039;&#039;verflow Flag Timer/Counter &#039;&#039;&#039;1&#039;&#039;&#039;)&lt;br /&gt;
:Dieses Bit wird vom Controller gesetzt, wenn beim Timer 1 ein Überlauf des Datenregisters stattfindet.&lt;br /&gt;
&lt;br /&gt;
:In der PWM-Betriebsart wird das Bit gesetzt, wenn die Zählrichtung von auf- zu abwärts und umgekehrt geändert wird (Zählerwert = 0).&lt;br /&gt;
&lt;br /&gt;
:Das Flag wird automatisch gelöscht, wenn der zugehörige Interrupt-Vektor aufgerufen wird. Es kann jedoch auch gelöscht werden, indem eine logische 1 (!) in das entsprechende Bit geschrieben wird.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;OCF1A&#039;&#039;&#039; (&#039;&#039;&#039;O&#039;&#039;&#039;utput &#039;&#039;&#039;C&#039;&#039;&#039;ompare &#039;&#039;&#039;F&#039;&#039;&#039;lag Timer/Counter &#039;&#039;&#039;1&#039;&#039;&#039;)&lt;br /&gt;
:Dieses Bit wird gesetzt, wenn der aktuelle Wert des Datenregisters von Timer/Counter 1 mit demjenigen im Vergleichsregister &#039;&#039;&#039;OCR1&#039;&#039;&#039; übereinstimmt.&lt;br /&gt;
&lt;br /&gt;
:Das Flag wird automatisch gelöscht, wenn der zugehörige Interrupt-Vektor aufgerufen wird. Es kann jedoch auch gelöscht werden, indem eine logische 1 (!) in das entsprechende Bit geschrieben wird.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ICF1&#039;&#039;&#039; (&#039;&#039;&#039;I&#039;&#039;&#039;nput &#039;&#039;&#039;C&#039;&#039;&#039;apture &#039;&#039;&#039;F&#039;&#039;&#039;lag Timer/Counter &#039;&#039;&#039;1&#039;&#039;&#039;)&lt;br /&gt;
:Dieses Bit wird gesetzt, wenn ein Capture-Ereignis aufgetreten ist, welches anzeigt, dass der Wert des Datenregisters des  Timer/Counter 1 in das Input Capture Register ICR1 übertragen wurde.&lt;br /&gt;
&lt;br /&gt;
:Das Flag wird automatisch gelöscht, wenn der zugehörige Interrupt-Vektor aufgerufen wird. Es kann jedoch auch gelöscht werden, indem eine logische 1 (!) in das entsprechende Bit geschrieben wird.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TOV0&#039;&#039;&#039; (&#039;&#039;&#039;T&#039;&#039;&#039;imer/Counter &#039;&#039;&#039;O&#039;&#039;&#039;verflow Flag Timer/Counter &#039;&#039;&#039;0&#039;&#039;&#039;)&lt;br /&gt;
:Dieses Bit wird vom Controller gesetzt, wenn beim Timer 0 ein Überlauf des Datenregisters stattfindet.&lt;br /&gt;
&lt;br /&gt;
:Das Flag wird automatisch gelöscht, wenn der zugehörige Interrupt-Vektor aufgerufen wird. Es kann jedoch auch gelöscht werden, indem eine logische 1 (!) in das entsprechende Bit geschrieben wird.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
= Sleep-Modes =&lt;br /&gt;
&lt;br /&gt;
AVR Controller verfügen über eine Reihe von sog. &#039;&#039;Sleep-Modes&#039;&#039; (&amp;quot;Schlaf-Modi&amp;quot;). Diese ermöglichen es, Teile des Controllers abzuschalten. Zum Einen kann damit besonders bei Batteriebetrieb Strom gespart werden, zum Anderen können Komponenten des Controllers deaktiviert werden, die die Genauigkeit des Analog-Digital-Wandlers bzw. des Analog-Comperators negativ beeinflussen. Der Controller wird durch Interrupts aus dem Schlaf geweckt. Welche Interrups den jeweiligen Schlafmodus beenden, ist einer Tabelle im Datenblatt des jeweiligen Controllers zu entnehmen.&lt;br /&gt;
Die Funktionen der avr-libc stehen nach Einbinden der header-Datei &#039;&#039;sleep.h&#039;&#039; zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;set_sleep_mode(uint8_t mode)&#039;&#039;&#039;&lt;br /&gt;
:Setzt den Schlafmodus, der bei Aufruf von sleep() aktiviert wird. In sleep.h sind einige Konstanten definiert (z.B. SLEEP_MODE_PWR_DOWN). Die definierten Modi werden jedoch nicht alle von sämtlichten AVR-Controllern unterstützt.&lt;br /&gt;
* &#039;&#039;&#039;sleep_mode()&#039;&#039;&#039;&lt;br /&gt;
:Versetzt den Controller in den mit set_sleep_mode gewählten Schlafmodus.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
   set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
   sleep_mode();&lt;br /&gt;
   &lt;br /&gt;
   // Code hier wird erst nach auftreten eines entsprechenden &amp;quot;Aufwach-Interrupts&amp;quot; verarbeitet&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vorsicht: Nicht alle AVR-Controller (v.a. nicht die &amp;quot;Brandneuen&amp;quot;) werden von den avr-libc sleep-Funktionen richtig angesteuert. Bei nicht-untersützten Typen erreicht man die gewollte Funktionalität durch direkte &amp;quot;Bitmanipulation&amp;quot; der ensprechenden Register (vgl. Datenblatt) und Aufruf des Sleep-Befehls via Inline-Assembler:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
   // Sleep-Mode &amp;quot;Power-Save&amp;quot; beim ATmega169 aktivieren&lt;br /&gt;
   SMCR = (3&amp;lt;&amp;lt;SM0) | (1&amp;lt;&amp;lt;SE);&lt;br /&gt;
   asm volatile (&amp;quot;sleep&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* siehe auch: [http://www.nongnu.org/avr-libc/user-manual/index.html Dokumentation der avr-libc] Abschnitt Modules/Power Management and Sleep-Modes&lt;br /&gt;
&lt;br /&gt;
= Der Watchdog =&lt;br /&gt;
&lt;br /&gt;
Und hier kommt das ultimative Mittel gegen die Unvollkommenheit von uns&lt;br /&gt;
Programmierern, der Watchdog.&lt;br /&gt;
&lt;br /&gt;
So sehr wir uns auch anstrengen, es wird uns kaum je gelingen, das absolut&lt;br /&gt;
perfekte und fehlerfreie Programm zu entwickeln.&lt;br /&gt;
&lt;br /&gt;
Der Watchdog kann uns zwar auch nicht zu besseren Programmen verhelfen aber er&lt;br /&gt;
kann dafür sorgen, dass unser Programm, wenn es sich wieder mal in&#039;s Nirwana&lt;br /&gt;
verabschiedet hat, neu gestartet wird, indem ein Reset des Controllers&lt;br /&gt;
ausgelöst wird.&lt;br /&gt;
&lt;br /&gt;
Betrachten wir doch einmal folgende Codesequenz:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t x;&lt;br /&gt;
&lt;br /&gt;
x = 10;&lt;br /&gt;
&lt;br /&gt;
while (x &amp;gt;= 0) {&lt;br /&gt;
   // tu was&lt;br /&gt;
&lt;br /&gt;
   x--;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn wir die Schleife mal genau anschauen sollte uns auffallen, dass dieselbe niemals beendet wird. Warum nicht? Ganz einfach, weil eine als &#039;&#039;&#039;&#039;&#039;unsigned&#039;&#039;&#039;&#039;&#039; deklarierte Variable niemals kleiner als Null werden kann (der Compiler sollte jedoch eine ensprechende Warnung ausgeben).&lt;br /&gt;
Das Programm würde sich also hier aufhängen und auf ewig in der Schleife drehen.&lt;br /&gt;
Und hier genau kommt der Watchdog zum Zug.&lt;br /&gt;
&lt;br /&gt;
== Wie funktioniert nun der Watchdog ==&lt;br /&gt;
&lt;br /&gt;
Der Watchdog enthält einen separaten Timer/Counter, welcher mit einem intern erzeugten Takt von 1 MHz bei 5V Vcc getaktet wird. Nachdem der Watchdog aktiviert und der gewünschte Vorteiler eingestellt wurde beginnt der Counter von 0 an hochzuzählen. Wenn nun die je nach Vorteiler eingestellte Anzahl Zyklen erreicht wurde, löst der Watchdog einen Reset aus. Um nun also im Normalbetrieb den Reset zu verhindern müssen wir den Watchdog regelmässig wieder neu starten bzw. Rücksetzen (Watchdog Reset). Dies sollte innerehalb unserer Hauptschleife passieren.&lt;br /&gt;
&lt;br /&gt;
Um ein unbeabsichtigtes Ausschalten des Watchdogs zu verhindern muss ein spezielles Prozedere verwendet werden, um den WD auszuschalten und zwar müssen zuerst die beiden Bits WDTOE und WDE in einer einzelnen Operation (also nicht mit sbi) auf 1 gesetzt werden. Dann muss innerhalb der nächsten 4 Taktzyklen das Bit WDE auf 0 gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
Das Watchdog Control Register:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;WDTCR&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;W&#039;&#039;&#039;atchog &#039;&#039;&#039;T&#039;&#039;&#039;imer&amp;amp;nbsp; &#039;&#039;&#039;C&#039;&#039;&#039;ontrol &#039;&#039;&#039;R&#039;&#039;&#039;egister&lt;br /&gt;
&lt;br /&gt;
In diesem Register stellen wir ein, wie wir den Watchdog verwenden möchten.&lt;br /&gt;
&lt;br /&gt;
Das Register ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;WDTOE&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;WDE&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;WDP2&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;WDP1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;WDP0&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WDTOE&#039;&#039;&#039; (&#039;&#039;&#039;W&#039;&#039;&#039;atch&#039;&#039;&#039;d&#039;&#039;&#039;og &#039;&#039;&#039;T&#039;&#039;&#039;urn &#039;&#039;&#039;O&#039;&#039;&#039;ff &#039;&#039;&#039;E&#039;&#039;&#039;nable)&lt;br /&gt;
:Dieses Bit muss gesetzt sein, wenn das Bit &#039;&#039;&#039;WDE&#039;&#039;&#039; gelöscht wird, andernfalls wird der Watchdog nicht ausgeschaltet.&lt;br /&gt;
:Wenn das Bit einmal gesetzt ist wird es von der Hardware nach 4 Taktzyklen automatisch wieder gelöscht.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WDE&#039;&#039;&#039; (&#039;&#039;&#039;W&#039;&#039;&#039;atch&#039;&#039;&#039;d&#039;&#039;&#039;og &#039;&#039;&#039;E&#039;&#039;&#039;nable)&lt;br /&gt;
:Wenn dieses Bit gesetzt wird, so wird der Watchdog aktiviert.&lt;br /&gt;
:Das Bit kann nur gelöscht werden, solange das Bit &#039;&#039;&#039;WDTOE&#039;&#039;&#039; auf 1 steht.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WDP2&#039;&#039;&#039;, &#039;&#039;&#039;WDP1&#039;&#039;&#039;, &#039;&#039;&#039;WDP0&#039;&#039;&#039; (&#039;&#039;&#039;W&#039;&#039;&#039;atch&#039;&#039;&#039;d&#039;&#039;&#039;og Timer &#039;&#039;&#039;P&#039;&#039;&#039;rescaler Bits)&lt;br /&gt;
:Diese 3 Bits bestimmen die Anzahl Oszillatorzyklen für den Watchdog, also, wie lange es dauert, bis ein Reset ausgelöst wird:&lt;br /&gt;
&amp;lt;dl&amp;gt;&amp;lt;dd&amp;gt;&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | WDP2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | WDP1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | WDP0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | Anzahl Zyklen&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | Typ. Timeoutzeit bei Vcc = 3V&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | Typ. Timeoutzeit bei Vcc = 5V&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 16K&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 47ms&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 15ms&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 32K&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 94ms&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 30ms&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 64K&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0.19s&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 60ms&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 128K&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0.38s&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0.12s&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 256K&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0.75s&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0.24s&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 512K&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1.5s&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0.49s&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1024K&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3s&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0.97s&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2048K&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6s&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1.9s&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/dd&amp;gt;&amp;lt;/dl&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Um den Watchdog mit dem AVR-GCC Compiler zu verwenden, muss die Headerdatei wdt.h in die Quelldatei eingebunden werden. &lt;br /&gt;
&amp;lt;!-- mt: das stimmt wohl nicht mehr?!:&lt;br /&gt;
Dadurch wird auch der Startup-Code&lt;br /&gt;
entsprechend angepasst, so dass der Watchdog nach einem Reset automatisch&lt;br /&gt;
gestartet wird. Das WDTCR-Register wird dabei mit dem Wert 0 beschrieben. Falls&lt;br /&gt;
ein anderer Wert gewünscht ist so kann dies im Makfile in den Linker-Optionen&lt;br /&gt;
eingetragen werden. Dazu muss in der Zeile LDFLAGS folgende Option angefügt&lt;br /&gt;
werden:&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; --defsym __init_wdtcr__=0x1f&amp;lt;br /&amp;gt;&lt;br /&gt;
wenn beispielsweise der Wert des Registers auf 0x1f gestellt werden soll.&amp;lt;br /&amp;gt; --&amp;gt;&lt;br /&gt;
Danach können die folgenden Funktionen verwendet werden:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;wdt_enable(uint8_t timeout)&#039;&#039;&#039;&lt;br /&gt;
:Aktiviert den Watchdog und stellt den Vorteiler auf den gewünschten Wert ein bzw. der in timeout übergebene Wert wird in das WDTCR-Register eingetragen. Einige Timeout-Werte sind als Konstanten vordefiniert&lt;br /&gt;
:Mögliche Timeoutwerte:&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Konstante&lt;br /&gt;
! Wert&lt;br /&gt;
! TimeOut&lt;br /&gt;
|- &lt;br /&gt;
| WDTO_15MS   &lt;br /&gt;
| 0&lt;br /&gt;
| 15 ms&lt;br /&gt;
|-&lt;br /&gt;
| WDTO_30MS   &lt;br /&gt;
| 1&lt;br /&gt;
| 30 ms&lt;br /&gt;
|-&lt;br /&gt;
| WDTO_60MS   &lt;br /&gt;
| 2&lt;br /&gt;
| 60 ms&lt;br /&gt;
|-&lt;br /&gt;
| WDTO_120MS   &lt;br /&gt;
| 3&lt;br /&gt;
| 120 ms&lt;br /&gt;
|-&lt;br /&gt;
| WDTO_250MS   &lt;br /&gt;
| 4&lt;br /&gt;
| 250 ms&lt;br /&gt;
|-&lt;br /&gt;
| WDTO_500MS   &lt;br /&gt;
| 5&lt;br /&gt;
| 500 ms&lt;br /&gt;
|-&lt;br /&gt;
| WDTO_1S   &lt;br /&gt;
| 6&lt;br /&gt;
| 1 S&lt;br /&gt;
|-&lt;br /&gt;
| WDTO_2S   &lt;br /&gt;
| 7&lt;br /&gt;
| 2s&lt;br /&gt;
|}&lt;br /&gt;
* &#039;&#039;&#039;wdt_disable()&#039;&#039;&#039;&lt;br /&gt;
:Mit dieser Funktion kann der Watchdog ausgeschaltet werden. Dabei wird das notwendige Prozedere, wie oben beschrieben, automatisch ausgeführt.&lt;br /&gt;
* &#039;&#039;&#039;wdt_reset()&#039;&#039;&#039;&lt;br /&gt;
:Dies ist wohl die wichtigste der Watchdog-Funktionen. Sie erzeugt einen Watchdog-Reset, welcher periodisch, und zwar vor Ablauf der Timeoutzeit, ausgeführt werden muss, damit der Watchdog nicht den AVR zurücksetzt.&lt;br /&gt;
&lt;br /&gt;
Selbstverständlich kann das &#039;&#039;&#039;WDTCR&#039;&#039;&#039;-Register auch mit den uns bereits bekannten Funktionen für den Zugriff auf Register programmiert werden.&lt;br /&gt;
&lt;br /&gt;
== Watchdog-Anwendungshinweise ==&lt;br /&gt;
&lt;br /&gt;
Ob nun der Watchdog als Schutzfunktion überhaupt verwendet werden soll, hängt stark von der Anwendung, der genutzten Peripherie und dem Umfang und der Qualitätssicherung des Codes ab. Will man sicher gehen, dass ein Programm sich nicht in einer Endlosschleife verfängt, ist der Wachdog das geeignete Mittel dies zu verhindern. Weiterhin kann bei geschickter Programmierung der Watchdog dazu genutzt werden, bestimmte Stromsparfunktionen zu implementieren. Ausserdem bietet der WD die einzige Möglichkeit einen beabsichtigten System-Reset (ein &amp;quot;richtiger Reset&amp;quot;, kein &amp;quot;jmp 0x0000&amp;quot;) ohne externe Beschaltung auszulösen, was z.B. bei der Implementierung eines Bootloaders nützlich ist. Bei bestimmten Anwendungen kann die Nutzung des WD als &amp;quot;ultimative Deadlock-Sicherung für nicht bedachte Zustände&amp;quot; natürlich immer als zusätzliche Sicherung dienen. &lt;br /&gt;
&lt;br /&gt;
Es besteht die Möglichkeit herauszufinden, ob ein Reset durch den Watchdog ausgelöst wurde (beim ATmega16 z.B. Bit WDRF in MCUCSR). Diese Information sollte auch genutzt werden, falls ein WD-Reset in der Anwendung nicht planmässig implementiert wurde. Zum Beispiel kann man eine LED an einen freien Pin hängen, die nur bei einem Reset durch den WD aufleuchtet oder aber das &amp;quot;Ereignis WD-Reset&amp;quot; im internen EEPROM des AVR absichern, um die Information später z.B. über UART oder ein Display auszugeben (oder einfach den EEPROM-Inhalt über die ISP/JTAG-Schnittstelle auslesen).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* siehe auch: [http://www.nongnu.org/avr-libc/user-manual/index.html Dokumentation der avr-libc] Abschnitt Modules/Watchdog timer handling&lt;br /&gt;
&lt;br /&gt;
= Programmieren mit Interrupts =&lt;br /&gt;
&lt;br /&gt;
Nachdem wir nun alles Wissenswerte für die serielle Programmerstellung&lt;br /&gt;
gelernt haben nehmen wir jetzt ein völlig anderes Thema in Angriff, nämlich&lt;br /&gt;
die Programmierung unter Zuhilfenahme der Interrupts des AVR.&lt;br /&gt;
&lt;br /&gt;
Als erstes wollen wir uns noch einmal den allgemeinen Programmablauf bei der&lt;br /&gt;
Interrupt-Programmierung zu Gemüte führen.&lt;br /&gt;
&lt;br /&gt;
[[Image:Interrupt Programme.gif]]&lt;br /&gt;
&lt;br /&gt;
Man sieht, dass die Interruptroutine quasi parallel zum Hauptprogramm&lt;br /&gt;
abläuft. Da wir nur eine CPU haben ist es natürlich keine echte Parallelität,&lt;br /&gt;
sondern das Hauptprogramm wird beim Eintreffen eines Interrupts unterbrochen,&lt;br /&gt;
die Interruptroutine wird ausgeführt und danach erst wieder zum Hauptprogramm&lt;br /&gt;
zurückgekehrt.&lt;br /&gt;
&lt;br /&gt;
== Anforderungen an die Interrupt-Routine ==&lt;br /&gt;
&lt;br /&gt;
Um unliebsamen Überraschungen vorzubeugen sollten einige Grundregeln bei&lt;br /&gt;
der Gestaltung der Interruptroutinen beachtet werden.&lt;br /&gt;
&lt;br /&gt;
* Die Interruptroutine soll möglichst kurz und schnell abarbeitbar sein, daraus folgt:&lt;br /&gt;
* Keine unfangreichen Berechnungen innerhalb der Interruptroutine.&lt;br /&gt;
* Keine endlos langen Programmschleifen.&lt;br /&gt;
* Obschon es möglich ist, während der Abarbeitung einer Interruptroutine andere oder sogar den gleichen Interrupt wieder zuzulassen rate ich dringend von solchen Spielen ab.&lt;br /&gt;
&lt;br /&gt;
== Interrupt-Quellen ==&lt;br /&gt;
&lt;br /&gt;
Die folgenden Ereignisse können einen Interrupt auf dem AVR auslösen, wobei&lt;br /&gt;
die Reihenfolge der Auflistung auch die Priorität der Interrupts aufzeigt.&lt;br /&gt;
&lt;br /&gt;
* Reset&lt;br /&gt;
* Externer Interrupt 0&lt;br /&gt;
* Externer Interrupt 1&lt;br /&gt;
* Timer/Counter 1 Capture Ereignis&lt;br /&gt;
* Timer/Counter 1 Compare Match&lt;br /&gt;
* Timer/Counter 1 Überlauf&lt;br /&gt;
* Timer/Counter 0 Überlauf&lt;br /&gt;
* UART Zeichen empfangen&lt;br /&gt;
* UART Datenregister leer&lt;br /&gt;
* UART Zeichen gesendet&lt;br /&gt;
* Analoger Komparator&lt;br /&gt;
&lt;br /&gt;
== Register ==&lt;br /&gt;
&lt;br /&gt;
Der AT90S2313 verfügt über 2 Register welche mit den&lt;br /&gt;
Interrupts zusammen hängen.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;GIMSK&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;G&#039;&#039;&#039;eneral &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;M&#039;&#039;&#039;ask &#039;&#039;&#039;R&#039;&#039;&#039;egister.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;INT1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;INT0&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;INT1&#039;&#039;&#039; (External &#039;&#039;&#039;Int&#039;&#039;&#039;errupt Request &#039;&#039;&#039;1&#039;&#039;&#039; Enable)&lt;br /&gt;
:Wenn dieses Bit gesetzt ist, wird ein Interrupt ausgelöst, wenn am &#039;&#039;&#039;INT1&#039;&#039;&#039;-Pin eine steigende oder fallende (je nach Konfiguration im &#039;&#039;&#039;MCUCR&#039;&#039;&#039;) Flanke erkannt wird.&lt;br /&gt;
:Das Global Enable Interrupt Flag muss selbstverständlich auch gesetzt sein.&lt;br /&gt;
:Der Interrupt wird auch ausgelöst, wenn der Pin als Ausgang geschaltet ist. Auf diese Weise bietet sich die Möglichkeit, Software-Interrupts zu realisieren.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;INT0&#039;&#039;&#039; (External &#039;&#039;&#039;Int&#039;&#039;&#039;errupt Request &#039;&#039;&#039;0&#039;&#039;&#039; Enable)&lt;br /&gt;
:Wenn dieses Bit gesetzt ist, wird ein Interrupt ausgelöst, wenn am &#039;&#039;&#039;INT0&#039;&#039;&#039;-Pin eine steigende oder fallende (je nach Konfiguration im &#039;&#039;&#039;MCUCR&#039;&#039;&#039;) Flanke erkannt wird.&lt;br /&gt;
:Das Global Enable Interrupt Flag muss selbstverständlich auch gesetzt sein.&lt;br /&gt;
:Der Interrupt wird auch ausgelöst, wenn der Pin als Ausgang geschaltet ist. Auf diese Weise bietet sich die Möglichkeit, Software-Interrupts zu realisieren.&lt;br /&gt;
&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;GIFR&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;G&#039;&#039;&#039;eneral &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;F&#039;&#039;&#039;lag &#039;&#039;&#039;R&#039;&#039;&#039;egister.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;INTF1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;INTF0&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;INTF1&#039;&#039;&#039; (External &#039;&#039;&#039;Int&#039;&#039;&#039;errupt Flag &#039;&#039;&#039;1&#039;&#039;&#039;)&lt;br /&gt;
:Dieses Bit wird gesetzt, wenn am &#039;&#039;&#039;INT1&#039;&#039;&#039;-Pin eine Interrupt-Kondition, entsprechend der Konfiguration, erkannt wird. Wenn das Global Enable Interrupt Flag gesetzt ist, wird die Interruptroutine angesprungen.&lt;br /&gt;
:Das Flag wird automatisch gelöscht, wenn die Interruptroutine beendet ist. Alternativ kann das Flag gelöscht werden, indem der Wert &#039;&#039;&#039;1(!)&#039;&#039;&#039; eingeschrieben wird.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;INTF0&#039;&#039;&#039; (External &#039;&#039;&#039;Int&#039;&#039;&#039;errupt Flag &#039;&#039;&#039;0&#039;&#039;&#039;)&lt;br /&gt;
:Dieses Bit wird gesetzt, wenn am &#039;&#039;&#039;INT0&#039;&#039;&#039;-Pin eine Interrupt-Kondition, entsprechend der Konfiguration, erkannt wird. Wenn das Global Enable Interrupt Flag gesetzt ist, wird die Interruptroutine angesprungen.&lt;br /&gt;
:Das Flag wird automatisch gelöscht, wenn die Interruptroutine beendet ist. Alternativ kann das Flag gelöscht werden, indem der Wert &#039;&#039;&#039;1(!)&#039;&#039;&#039; eingeschrieben wird.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;MCUCR&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;MCU&#039;&#039;&#039; &#039;&#039;&#039;C&#039;&#039;&#039;ontrol &#039;&#039;&#039;R&#039;&#039;&#039;egister.&lt;br /&gt;
&lt;br /&gt;
Das MCU Control Register enthält Kontrollbits für allgemeine&lt;br /&gt;
MCU-Funktionen.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;SE&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;SM&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ISC11&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ISC10&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ISC01&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ISC00&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SE&#039;&#039;&#039; (&#039;&#039;&#039;S&#039;&#039;&#039;leep &#039;&#039;&#039;E&#039;&#039;&#039;nable)&lt;br /&gt;
:Dieses Bit muss gesetzt sein, um den Controller mit dem &#039;&#039;&#039;SLEEP&#039;&#039;&#039;-Befehl in den Schlafzustand versetzen zu können.&lt;br /&gt;
:Um den Schlafmodus nicht irrtümlich einzuschalten, wird empfohlen, das Bit erst unmittelbar vor Ausführung des &#039;&#039;&#039;SLEEP&#039;&#039;&#039;-Befehls zu setzen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;SM&#039;&#039;&#039; (&#039;&#039;&#039;S&#039;&#039;&#039;leep &#039;&#039;&#039;M&#039;&#039;&#039;ode)&lt;br /&gt;
:Dieses Bit bestimmt der Schlafmodus.&lt;br /&gt;
:Ist das Bit gelöscht, so wird der &#039;&#039;&#039;Idle&#039;&#039;&#039;-Modus ausgeführt. Ist das Bit gesetzt, so wird der &#039;&#039;&#039;Power-Down&#039;&#039;&#039;-Modus ausgeführt. (für andere AVR Controller siehe Abschnitt &amp;quot;Sleep-Mode&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;ISC11&#039;&#039;&#039;, &#039;&#039;&#039;ISC10&#039;&#039;&#039; (&#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;S&#039;&#039;&#039;ense &#039;&#039;&#039;C&#039;&#039;&#039;ontrol &#039;&#039;&#039;1&#039;&#039;&#039; Bits)&lt;br /&gt;
:Diese beiden Bits bestimmen, ob die steigende oder die fallende Flanke für die Interrupterkennung am &#039;&#039;&#039;INT1&#039;&#039;&#039;-Pin ausgewertet wird.&lt;br /&gt;
&amp;lt;dl&amp;gt;&amp;lt;dd&amp;gt;&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ISC11&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ISC10&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Bedeutung&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Low Level an &#039;&#039;&#039;INT1&#039;&#039;&#039; erzeugt einen Interrupt.&lt;br /&gt;
&lt;br /&gt;
In der Beschreibung heisst es, der Interrupt wird getriggert, solange der Pin auf 0 bleibt, also eigentlich unbrauchbar.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Reserviert&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Die fallende Flanke an &#039;&#039;&#039;INT1&#039;&#039;&#039; erzeugt einen Interrupt.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Die steigende Flanke an &#039;&#039;&#039;INT1&#039;&#039;&#039; erzeugt einen Interrupt.&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/dd&amp;gt;&amp;lt;/dl&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;ISC01&#039;&#039;&#039;, &#039;&#039;&#039;ISC00&#039;&#039;&#039; (&#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;S&#039;&#039;&#039;ense &#039;&#039;&#039;C&#039;&#039;&#039;ontrol &#039;&#039;&#039;0&#039;&#039;&#039; Bits)&lt;br /&gt;
:Diese beiden Bits bestimmen, ob die steigende oder die fallende Flanke für die Interrupterkennung am &#039;&#039;&#039;INT0&#039;&#039;&#039;-Pin ausgewertet wird.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;dl&amp;gt;&amp;lt;dd&amp;gt;&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ISC01&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ISC00&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Bedeutung&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Low Level an &#039;&#039;&#039;INT0&#039;&#039;&#039; erzeugt einen Interrupt.&lt;br /&gt;
&lt;br /&gt;
In der Beschreibung heisst es, der Interrupt wird getriggert, solange der Pin auf 0 bleibt, also eigentlich unbrauchbar.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Reserviert&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Die fallende Flank an &#039;&#039;&#039;INT0&#039;&#039;&#039; erzeugt einen Interrupt.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Die steigende Flanke an &#039;&#039;&#039;INT0&#039;&#039;&#039; erzeugt einen Interrupt.&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/dd&amp;gt;&amp;lt;/dl&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Allgemeines über die Interrupt-Abarbeitung ==&lt;br /&gt;
&lt;br /&gt;
Wenn ein Interrupt eintrifft, wird automatisch das &#039;&#039;&#039;Global&lt;br /&gt;
Interrupt Enable&#039;&#039;&#039; Bit im Status Register &#039;&#039;&#039;SREG&#039;&#039;&#039; gelöscht und alle&lt;br /&gt;
weiteren Interrupts unterbunden. Obwohl es möglich ist, zu diesem&lt;br /&gt;
Zeitpunkt bereits wieder das GIE-bit zu setzen, rate ich dringend davon ab. Dieses&lt;br /&gt;
wird nämlich automatisch gesetzt, wenn die Interruptroutine beendet wird. Wenn&lt;br /&gt;
in der Zwischenzeit weitere Interrupts eintreffen, werden die zugehörigen&lt;br /&gt;
Interrupt-Bits gesetzt und die Interrupts bei Beendigung der laufenden&lt;br /&gt;
Interrupt-Routine in der Reihenfolge ihrer Priorität ausgeführt. Dies kann&lt;br /&gt;
eigentlich nur dann zu Problemen führen, wenn ein hoch priorisierter Interrupt&lt;br /&gt;
ständig und in kurzer Folge auftritt. Dieser sperrt dann möglicherweise alle&lt;br /&gt;
anderen Interrupts mit niedrigerer Priorität. Dies ist einer der Gründe,&lt;br /&gt;
weshalb die Interrupt-Routinen sehr kurz gehalten werden sollen.&lt;br /&gt;
&lt;br /&gt;
=== Das Status-Register ===&lt;br /&gt;
&lt;br /&gt;
Es gilt auch zu beachten, dass das Status-Register während der Abarbeitung&lt;br /&gt;
einer Interruptroutine nicht automatisch gesichert wird. Falls notwendig, muss dies vom&lt;br /&gt;
Programmierer selber vorgesehen werden.&lt;br /&gt;
&lt;br /&gt;
== Interrupts mit dem AVR GCC Compiler (WinAVR) ==&lt;br /&gt;
&lt;br /&gt;
Selbstverständlich können alle Interruptspezifischen Registerzugriffe wie gewohnt über I/O-Adressierung vorgenommen werden. Etwas einfacher geht es jedoch, wenn wir die vom Compiler zur Verfügung gestellten Mittel einsetzen.&lt;br /&gt;
&lt;br /&gt;
Damit diese Mittel zur Verfügung stehen, müssen wir die Includedatei &#039;&#039;interrupt.h&#039;&#039; und evtl. &#039;&#039;signal.h&#039;&#039; einbinden mittels:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
// fuer sei(), cli() und INTERRUPT():&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// fuer SIGNAL() auch:&lt;br /&gt;
#include &amp;lt;avr/signal.h&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Makro &#039;&#039;&#039;sei()&#039;&#039;&#039; schaltet die Interrupts ein. Eigentlich wird&lt;br /&gt;
nichts anderes gemacht, als das &#039;&#039;&#039;Global Interrupt Enable&#039;&#039;&#039; Bit im Status&lt;br /&gt;
Register gesetzt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
    sei();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Makro &#039;&#039;&#039;cli()&#039;&#039;&#039; schaltet die Interrupts aus, oder anders&lt;br /&gt;
gesagt, das &#039;&#039;&#039;Global Interrupt Enable&#039;&#039;&#039; Bit im Status Register wird&lt;br /&gt;
gelöscht.&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
    cli();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oft steht man vor der Aufgabe, dass eine Codesequenz nicht unterbrochen werden darf.&lt;br /&gt;
Es liegt dann nahe, zu Beginn dieser Sequenz ein cli() und am Ende ein sei() einzufügen.&lt;br /&gt;
Dies ist jedoch ungünstig, wenn die Interrupts vor Aufruf der Sequenz deaktiviert waren&lt;br /&gt;
und danach auch weiterhin deaktiviert bleiben sollen. Ein sei() würde ungeachtet des vorherigen &lt;br /&gt;
Zustands die Interrups aktivieren, was zu unerwünschten Seiteneffekten führen kann.&lt;br /&gt;
Die aus dem folgenden Beispiel ersichtliche Vorgehensweise ist in solchen Fällen vorzuziehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
void NichtUnterbrechenBitte(void)&lt;br /&gt;
{&lt;br /&gt;
   uint8_t tmp_sreg;  // temporaerer Speicher fuer das Statusregister&lt;br /&gt;
&lt;br /&gt;
   tmp_sreg = SREG;   // Statusregister (also auch das I-Flag darin) sichern&lt;br /&gt;
   cli();             // Interrupts global deaktivieren&lt;br /&gt;
&lt;br /&gt;
   /* hier &amp;quot;unterbrechnungsfreier&amp;quot; Code */&lt;br /&gt;
&lt;br /&gt;
   /* Beispiel Anfang&lt;br /&gt;
     JTAG-Interface eines ATmega16 per Software deaktivieren &lt;br /&gt;
     und damit die JTAG-Pins an PORTC für &amp;quot;general I/O&amp;quot; nutzbar machen&lt;br /&gt;
     ohne die JTAG-Fuse-Bit zu aendern. Dazu ist eine &amp;quot;timed sequence&amp;quot;&lt;br /&gt;
     einzuhalten (vgl Datenblatt ATmega16, Stand 10/04, S. 229): &lt;br /&gt;
     Das JTD-Bit muss zweimal innerhalb von 4 Taktzyklen geschrieben &lt;br /&gt;
     werden. Ein Interrupt zwischen den beiden Schreibzugriffen wuerde &lt;br /&gt;
     die erforderliche Sequenz &amp;quot;brechen&amp;quot;, das JTAG interface bliebe&lt;br /&gt;
     weiterhin aktiv und die IO-Pins weiterhin für JTAG reserviert. */&lt;br /&gt;
&lt;br /&gt;
   MCUCSR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
   MCUCSR |= (1&amp;lt;&amp;lt;JTD); // 2 mal in Folge ,vgl. Datenblatt fuer mehr Information&lt;br /&gt;
&lt;br /&gt;
   /* Beispiel Ende */&lt;br /&gt;
  &lt;br /&gt;
   SREG = tmp_sreg;     // Status-Register wieder herstellen &lt;br /&gt;
                      // somit auch das I-Flag auf gesicherten Zustand setzen&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void NichtSoGut(void)&lt;br /&gt;
{&lt;br /&gt;
   cli();&lt;br /&gt;
   &lt;br /&gt;
   /* hier &amp;quot;unterbrechnungsfreier&amp;quot; Code */&lt;br /&gt;
   &lt;br /&gt;
   sei();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
   cli();  &lt;br /&gt;
   // Interrupts global deaktiviert &lt;br /&gt;
&lt;br /&gt;
   NichtUnterbrechenBitte();&lt;br /&gt;
   // auch nach Aufruf der Funktion deaktiviert&lt;br /&gt;
&lt;br /&gt;
   sei();&lt;br /&gt;
   // Interrupts global aktiviert &lt;br /&gt;
&lt;br /&gt;
   NichtUnterbrechenBitte();&lt;br /&gt;
   // weiterhin aktiviert&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
   /* Verdeutlichung der unguenstigen Vorgehensweise mit cli/sei: */&lt;br /&gt;
   cli();  &lt;br /&gt;
   // Interrupts jetzt global deaktiviert &lt;br /&gt;
&lt;br /&gt;
   NichSoGut();&lt;br /&gt;
   // nach Aufruf der Funktion sind Interrupts global aktiviert &lt;br /&gt;
   // dies ist mglw. ungewollt!&lt;br /&gt;
   ...&lt;br /&gt;
   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- mt: besser so nicht(?), lieber &amp;quot;datenblattkonform&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;&#039;&#039;&#039;timer_enable_int (unsigned char ints);&amp;lt;br /&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;/font&amp;gt;Schaltet Timerbezogene Interrupts ein bzw. aus.&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn als Argument &#039;&#039;&#039;ints&#039;&#039;&#039; der Wert 0 übergeben wird so werden alle&lt;br /&gt;
Timerinterrupts ausgeschaltet, ansonsten muss in &#039;&#039;&#039;ints&#039;&#039;&#039; angegeben werden,&lt;br /&gt;
welche Interrupts zu aktivieren sind. Dabei müssen einfach die entsprechend zu&lt;br /&gt;
setzenden Bits definiert werden.&amp;lt;br /&amp;gt;&lt;br /&gt;
Beispiel: &#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;timer_enable_int (1 &amp;lt;&amp;lt; TOIE1));&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;/font&amp;gt;&#039;&#039;&#039;Achtung: Wenn ein Timerinterrupt eingeschaltet wird während ein&lt;br /&gt;
anderer Timerinterrupt bereits läuft, dann müssen beide Bits angegeben werden&lt;br /&gt;
sonst wird der andere Timerinterrupt versehentlich ausgeschaltet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;&#039;&#039;&#039;enable_external_int (unsigned char ints);&amp;lt;br /&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;/font&amp;gt;Schaltet die externen Interrupts ein bzw. aus.&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn als Argument &#039;&#039;&#039;ints&#039;&#039;&#039; der Wert 0 übergeben wird so werden alle externen&lt;br /&gt;
Interrrups ausgeschaltet, ansonsten muss in &#039;&#039;&#039;ints&#039;&#039;&#039; angegeben werden, welche&lt;br /&gt;
Interrupts zu aktivieren sind. Dabei müssen einfach die entsprechend zu&lt;br /&gt;
setzenden Bits definiert werden.&amp;lt;br /&amp;gt;&lt;br /&gt;
Beispiel: &#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;enable_external_int ((1&amp;lt;&lt;br /&gt;
&amp;lt;/font&amp;gt;&#039;&#039;&#039;Schaltet die externen Interrupts 0 und 1 ein.&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nachdem nun die Interrupts aktiviert sind, braucht es selbstverständlich noch den auszuführenden Code, der ablaufen soll, wenn ein Interrupt eintrifft. Dazu gibt es zwei Definitionen: &#039;&#039;&#039;SIGNAL&#039;&#039;&#039; und &#039;&#039;&#039;INTERRUPT&#039;&#039;&#039;, welche allerdings AVR-GCC spezifisch sind und bei anderen Compilern womöglich anders heissen können.&lt;br /&gt;
&lt;br /&gt;
=== SIGNAL ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/signal.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
SIGNAL (siglabel)&lt;br /&gt;
{&lt;br /&gt;
    /* Interrupt Code */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit &#039;&#039;SIGNAL&#039;&#039; wird eine Funktion für die Bearbeitung eines Interrupts eingeleitet. Als Argument muss dabei die Benennung des entsprechenden Interruptvektoren angegeben werden. Diese sind in den jeweiligen Includedateien IOxxxx.h zu finden. Auf die korrekte Schreibweise ist zu achten, der Compiler prüft diese nicht (vgl. [[AVR-GCC]]). Als Beispiel ein Ausschnitt aus der Datei für den ATmega8 (bei WinAVR Standardinstallation in C:\WinAVR\avr\include\avr\iom8.h): &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
[...]&lt;br /&gt;
/* $Id: iom8.h,v 1.8 2003/02/17 09:57:28 marekm Exp $ */&lt;br /&gt;
&lt;br /&gt;
/* avr/iom8.h - definitions for ATmega8 */&lt;br /&gt;
[...]&lt;br /&gt;
&lt;br /&gt;
/* Interrupt vectors */&lt;br /&gt;
&lt;br /&gt;
#define SIG_INTERRUPT0		_VECTOR(1)&lt;br /&gt;
#define SIG_INTERRUPT1		_VECTOR(2)&lt;br /&gt;
#define SIG_OUTPUT_COMPARE2	_VECTOR(3)&lt;br /&gt;
#define SIG_OVERFLOW2		_VECTOR(4)&lt;br /&gt;
#define SIG_INPUT_CAPTURE1	_VECTOR(5)&lt;br /&gt;
#define SIG_OUTPUT_COMPARE1A	_VECTOR(6)&lt;br /&gt;
#define SIG_OUTPUT_COMPARE1B	_VECTOR(7)&lt;br /&gt;
#define SIG_OVERFLOW1		_VECTOR(8)&lt;br /&gt;
#define SIG_OVERFLOW0		_VECTOR(9)&lt;br /&gt;
#define SIG_SPI			_VECTOR(10)&lt;br /&gt;
#define SIG_UART_RECV		_VECTOR(11)&lt;br /&gt;
#define SIG_UART_DATA		_VECTOR(12)&lt;br /&gt;
#define SIG_UART_TRANS		_VECTOR(13)&lt;br /&gt;
#define SIG_ADC			_VECTOR(14)&lt;br /&gt;
#define SIG_EEPROM_READY	_VECTOR(15)&lt;br /&gt;
#define SIG_COMPARATOR		_VECTOR(16)&lt;br /&gt;
#define SIG_2WIRE_SERIAL	_VECTOR(17)&lt;br /&gt;
#define SIG_SPM_READY		_VECTOR(18)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vor Nutzung von SIGNAL muss ebenfalls die Header-Datei signal.h eingebunden werden. Mögliche Funktionsrümpfe für solche Interruptfunktionen sind zum Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/signal.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
SIGNAL (SIG_INTERRUPT0)&lt;br /&gt;
{&lt;br /&gt;
    /* Interrupt Code */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
SIGNAL (SIG_OVERFLOW1)&lt;br /&gt;
{&lt;br /&gt;
    /* Interrupt Code */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
SIGNAL (SIG_UART_RECV)&lt;br /&gt;
{&lt;br /&gt;
    /* Interrupt Code */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// und so weiter und so fort...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Während der Ausführung der Funktion sind alle weiteren Interrupts automatisch gesperrt. Beim Verlassen der Funktion werden die Interrupts wieder zugelassen.&lt;br /&gt;
&lt;br /&gt;
Sollte während der Abarbeitung der Interruptroutine ein weiterer Interrupt (gleiche oder andere Interruptquelle) auftreten, so wird das entsprechende Bit im zugeordneten Interrupt Flag Register gesetzt und die entsprechende Interruptroutine automatisch nach dem Beenden der aktuellen Funktion aufgerufen.&lt;br /&gt;
&lt;br /&gt;
Ein Problem ergibt sich eigentlich nur dann, wenn während der Abarbeitung der aktuellen Interruptroutine mehrere gleichartige Interrupts auftreten. Die entsprechende Interruptroutine wird im Nachhinein zwar aufgerufen jedoch wissen wir nicht, ob nun der entsprechende Interrupt einmal, zweimal oder gar noch öfter aufgetreten ist. Deshalb soll hier noch einmal betont werden, dass Interruptroutinen so schnell wie nur irgend möglich wieder verlassen werden sollten.&lt;br /&gt;
&lt;br /&gt;
=== INTERRUPT ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
INTERRUPT (signame)&lt;br /&gt;
{&lt;br /&gt;
    /* Interrupt Code */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit INTERRUPT wird genau gleich gearbeitet wie mit SIGNAL. Der Unterschied ist derjenige, dass bei INTERRUPT beim Aufrufen der Funktion das &#039;&#039;&#039;Global Enable Interrupt&#039;&#039;&#039; Bit automatisch wieder gesetzt und somit weitere Interrupts zugelassen werden. Dies kann zu nicht unerheblichen Problemen von im einfachsten Fall einem Stack overflow bis zu sonstigen unerwarteten Effekten führen und sollte wirklich &#039;&#039;&#039;nur dann&#039;&#039;&#039; angewendet werden, wenn man sich absolut sicher ist, das Ganze auch im Griff zu haben. Vor Nutzung von INTERRUPT muss die Header-Datei interrupt.h eingebunden werden.&lt;br /&gt;
&lt;br /&gt;
Interruptroutinen (ISRs) sollten möglichst kurz sein und keine Schleifen mit vielen Durchläufen enthalten. Längere Operationen können meist in einen &amp;quot;Interrupt-Teil&amp;quot; in einer ISR und einen &amp;quot;Arbeitsteil&amp;quot; im Hauptprogramm aufgetrennt werden. Z.B. Speichern des Zustands aller Eingänge im EEPROM in bestimmten Zeitabständen: ISR-Teil: Zeitvergleich (Timer,RTC) mit Logzeit/-intervall. Bei Übereinstimmung ein globales Flag setzen (volatile bei Flag-Deklaration nicht vergessen, s.u.). Dann im Hauptprogramm prüfen, ob das Flag gesetzt ist. Wenn ja: die Daten im EEPROM ablegen und Flag löschen.&lt;br /&gt;
&lt;br /&gt;
siehe auch: Hinweise in [[AVR-GCC]]&lt;br /&gt;
&lt;br /&gt;
== Datenaustausch mit Interrupt-Routinen ==&lt;br /&gt;
&lt;br /&gt;
Variablen auf die sowohl in Interrupt-Routinen (ISR = Interrupt Service Routine(s)), als auch vom übrigen Programmcode geschrieben oder gelesen werden, müssen mit einem &#039;&#039;&#039;volatile&#039;&#039;&#039; deklariert werden. Damit wird dem Compiler mitgeteilt, dass der Inhalt der Variablen vor jedem Lesezugriff aus dem Speicher gelesen wird und nach jedem Schreibzugriff in den Speicher geschrieben wird. Ansonsten könnte die Code-Optimierung &amp;quot;greifen&amp;quot; und der Wert der Variablen nur in Prozessorregistern zwischenspeichert werden, die &amp;quot;nichts von der Änderung woanders mitbekommen&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Zur Veranschaulichung ein Codefragment für eine Tastenentprellung mit Erkennung einer &amp;quot;lange gedrückten&amp;quot; Taste.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/signal.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
// Schwellwerte&lt;br /&gt;
// Entprellung: &lt;br /&gt;
#define CNTDEBOUNCE 10&lt;br /&gt;
// &amp;quot;lange gedrueckt:&amp;quot;&lt;br /&gt;
#define CNTREPEAT 200&lt;br /&gt;
&lt;br /&gt;
// hier z.B. Taste an Pin2 PortA &amp;quot;active low&amp;quot; = 0 wenn gedrueckt&lt;br /&gt;
#define KEY_PIN  PINA&lt;br /&gt;
#define KEY_PINNO PA2&lt;br /&gt;
&lt;br /&gt;
// beachte: volatile! &lt;br /&gt;
volatile uint8_t gKeyCounter;&lt;br /&gt;
&lt;br /&gt;
// Timer-Compare Interrupt z.B. alle 10ms&lt;br /&gt;
SIGNAL(SIG_OUTPUT_COMPARE1A)&lt;br /&gt;
{&lt;br /&gt;
   // hier wird gKeyCounter veraendert, die uebrigen&lt;br /&gt;
   // Programmteile muessen diese Aenderung &amp;quot;sehen&amp;quot;&lt;br /&gt;
   // (volatile -&amp;gt; aktuellen Wert immer in den Speicher schreiben)&lt;br /&gt;
   if ( !(KEY_PIN &amp;amp; (1&amp;lt;&amp;lt;KEY_PINNO)) )&lt;br /&gt;
      if (gKeyCouter &amp;lt; CNTREPEAT) gKeyCounter++;&lt;br /&gt;
   else gKeyCounter = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
    /* hier: Initialisierung der Ports und des Timer-Interrupts */&lt;br /&gt;
... &lt;br /&gt;
   // hier wird auf gKeyCounter zugegriffen, dazu muss der in der&lt;br /&gt;
   // ISR geschrieben Wert bekannt sein.&lt;br /&gt;
   // (volatile -&amp;gt; aktuellen Wert immer aus dem Speicher lesen)&lt;br /&gt;
   if ( gKeyCounter &amp;gt; CNTDEBOUNCE ) { // Taste mind. 10*10 ms &amp;quot;prellfrei&amp;quot;&lt;br /&gt;
       if (gKeyCounter == CNTREPEAT) {&lt;br /&gt;
          /* hier: Code fuer &amp;quot;Taste lange gedrueckt&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
       else {&lt;br /&gt;
          /* hier: Code fuer &amp;quot;Taste kurz gedrueckt&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei Variablen größer ein Byte muss darauf geachtet werden, dass die Zugriffe auf die einzelnen Bytes ausserhalb der ISR nicht durch einen Interrupt unterbrochen werden. (Allgemeinplatz: AVRs sind 8-bit Controller). Zur Veranschaulichung ein Codefragment:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
volatile uint16_t gMyCounter16bit&lt;br /&gt;
...&lt;br /&gt;
SIGNAL(...)&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
   gMyCounter16Bit++;&lt;br /&gt;
...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
   uint16_t tmpCnt;&lt;br /&gt;
...&lt;br /&gt;
   // nicht gut: mglw. hier ein Fehler wenn ein Byte von MyCounter &lt;br /&gt;
   // schon in tmpCnt kopiert ist aber vor Kopieren des zweiten Bytes &lt;br /&gt;
   // ein Interrupt auftritt der den Inhalt von MyCounter veraendert&lt;br /&gt;
   tmpCnt = gMyCounter16bit; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   // besser: Aenderungen &amp;quot;ausserhalb&amp;quot; verhindern, alle &amp;quot;Teilbytes&amp;quot;&lt;br /&gt;
   // bleiben konsistent&lt;br /&gt;
   cli();  // Interupts deaktivieren&lt;br /&gt;
   tmpCnt = gMyCounter16Bit;&lt;br /&gt;
   sei();  // wieder aktivieren&lt;br /&gt;
...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* siehe auch: [http://www.nongnu.org/avr-libc/user-manual/index.html Dokumentation der avr-libc] Frequently asked Questions/Fragen Nr. 1 und 8 (Stand: avr-libc Vers. 1.0.4)&lt;br /&gt;
&lt;br /&gt;
== Was macht das Hauptprogramm ==&lt;br /&gt;
&lt;br /&gt;
Im einfachsten Fall gar nichts mehr.&lt;br /&gt;
&lt;br /&gt;
Es ist also durchaus denkbar, ein Programm zu schreiben, welches in der&lt;br /&gt;
main-Funktion lediglich noch die Interrupts aktiviert und dann in eine&lt;br /&gt;
Endlosschleife folgender Art verzweigt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    for (;;) {}&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Normalerweise wird man allerdings in den Interruptroutinen die Interrupts&lt;br /&gt;
erfassen und im Hauptprogramm dann gemütlich auswerten.&lt;br /&gt;
&lt;br /&gt;
Wie wir im bisherigen Kursverlauf gesehen haben ist es ohnehin mit so&lt;br /&gt;
schnellen Controller meistens gar nicht unbedingt notwendig mit&lt;br /&gt;
Interruptfunktionen zu arbeiten.&amp;lt;br /&amp;gt;&lt;br /&gt;
Es ist allerdings auch zu bemerken, dass mit den Interruptroutinen ein Programm&lt;br /&gt;
sehr schön strukturiert werden kann, wenn man es richtig macht.&lt;br /&gt;
&lt;br /&gt;
* siehe auch: [http://www.nongnu.org/avr-libc/user-manual/index.html Dokumentation der avr-libc] Abschnitt Modules/Interrupts and Signals&lt;br /&gt;
&lt;br /&gt;
= Speicherzugriffe =&lt;br /&gt;
&lt;br /&gt;
Atmel AVR-Controller verfügen typisch über drei Speicher:&lt;br /&gt;
&lt;br /&gt;
* [[RAM]]: Im RAM (eigentlich [[SRAM]]) wird vom gcc-Compiler Platz für Variablen reserviert. Auch der Stack befindet sich im RAM. Dieser Speicher ist &amp;quot;flüchtig&amp;quot;, d.h. der Inhalt der Variablen geht beim Ausschalten oder einem Zusammenbruch der Spannungsversorgung verloren.&lt;br /&gt;
&lt;br /&gt;
* Programmspeicher: Ausgeführt als [[FLASH]]-Speicher, seitenweise wiederbeschreibbar. Darin ist das Anwendungsprogramm abgelegt.&lt;br /&gt;
&lt;br /&gt;
* [[EEPROM]]: Nichtflüchtiger Speicher, d.h. der einmal geschriebene Inhalt bleibt auch ohne Stromversorgung erhalten. Byte-weise schreib/lesbar. Im EEPROM werden typischerweise gerätespezifische Werte wie z.B. Kalibrierungswerte von Sensoren abgelegt.&lt;br /&gt;
&lt;br /&gt;
Einige AVRs besitzen keinen RAM-Speicher, lediglich die Register können als &amp;quot;Arbeitsvariablen&amp;quot;&lt;br /&gt;
genutzt werden. Da die Anwendung des avr-gcc auf solch &amp;quot;kleinen&amp;quot; Controllern ohnehin wenig Sinn macht und auch nur bei einigen RAM-losen Typen nach &amp;quot;Bastelarbeiten&amp;quot; möglich ist, werden diese Controller hier nicht weiter berücksichtigt. Auch EEPROM-Speicher ist nicht auf allen Typen verfügbar. Generell sollten die nachfolgenden Erläuterungen auf alle ATmega-Controller und die größeren AT90-Typen übertragbar sein.&lt;br /&gt;
&lt;br /&gt;
== RAM ==&lt;br /&gt;
&lt;br /&gt;
Die Verwaltung des RAM-Speichers erfolgt durch den Compiler, im Regelfall ist beim Zugriff auf Variablen im RAM nichts besonderes zu beachten. Die Erläuterungen in jedem brauchbaren C-Buch gelten auch für den vom avr-gcc-Compiler erzeugten Code.&lt;br /&gt;
&lt;br /&gt;
== Programmspeicher (Flash) ==&lt;br /&gt;
&lt;br /&gt;
Ein Zugriff auf Konstanten im Programmspeicher ist mittels avr-gcc nicht &amp;quot;transparent&amp;quot; möglich. D.h. es sind besondere Zugriffsfunktionen erforderlich um Daten aus diesem Speicher zu lesen. Grundsätzlich basieren alle Zugriffsfunktionen auf der Assembler-Anweisung lpm (load program memory). Die Standard-Laufzeitbibliothek des avr-gcc, die [[avr-libc]], stellt diese Funktionen nach einbinden der Header-Datei pgmspace.h zur Verfügung. Mit diesen Funktionen können einzelne Bytes, Datenworte (16bit) und Datenblöcke gelesen werden. &lt;br /&gt;
&lt;br /&gt;
Deklarationen von Variablen im Flash-Speicher werden durch das &amp;quot;Attribut&amp;quot; PROGMEM ergänzt. Lokale Variablen (eigentlich Konstanten) innerhalb von Funktionen können ebenfalls im Programmspeicher abgelegt werden. Dazu ist bei der Definition jedoch ein &#039;&#039;static&#039;&#039; voranzustellen, da solche &amp;quot;Variablen&amp;quot; nicht auf dem Stack bzw. (bei Optimierung) in Registern verwaltet werden können. Der Compiler &amp;quot;wirft&amp;quot; eine Warnung falls static fehlt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/pgmspace.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
/* Byte */&lt;br /&gt;
const uint8_t pgmFooByte PROGMEM = 123;&lt;br /&gt;
&lt;br /&gt;
/* Wort */&lt;br /&gt;
const uint16_t pgmFooWort PROGMEM = 12345;&lt;br /&gt;
&lt;br /&gt;
/* Byte-Feld */&lt;br /&gt;
const uint8_t pgmFooByteArray1[] PROGMEM = { 18, 3 ,70 };&lt;br /&gt;
const uint8_t pgmFooByteArray2[] PROGMEM = { 30, 7 ,79 };&lt;br /&gt;
&lt;br /&gt;
/* Zeiger */&lt;br /&gt;
const uint8_t *pgmPointerToArray1 PROGMEM = pgmFooByteArray1;&lt;br /&gt;
const uint8_t *pgmPointerArray[] PROGMEM = { pgmFooByteArray1, pgmFooByteArray1 };&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
void foo(void)&lt;br /&gt;
{&lt;br /&gt;
  static /*const*/ uint8_t pgmTestByteLocal PROGMEM = 0x55;&lt;br /&gt;
  static /*const*/ char pgmTestStringLocal[] PROGMEM = &amp;quot;im Flash&amp;quot;;&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Byte lesen ===&lt;br /&gt;
&lt;br /&gt;
Mit der Funktion pgm_read_byte aus pgmspace.h erfolgt der Zugriff auf die Daten. Parameter der Funktion ist die Adresse des Bytes im Flash-Speicher.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
    // Wert der Ram-Variablen myByte auf den Wert von pgmFooByte setzen:&lt;br /&gt;
    uint8_t myByte;&lt;br /&gt;
&lt;br /&gt;
    myByte = pgm_read_byte(&amp;amp;pgmFooByte);&lt;br /&gt;
    // myByte hat nun den Wert 123&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
    // Schleife ueber ein Array aus Byte-Werten im Flash&lt;br /&gt;
    uint8_t i;&lt;br /&gt;
&lt;br /&gt;
    for (i=0;i&amp;lt;3;i++) {&lt;br /&gt;
        myByte = pgm_read_byte(&amp;amp;pgmFooByteArray1[i]);&lt;br /&gt;
        // mach&#039; was mit myByte...&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wort lesen ===&lt;br /&gt;
&lt;br /&gt;
Für &amp;quot;einfache&amp;quot; 16-bit breite Variablen erfolgt der Zugriff analog zum Byte-Beispiel, jedoch mit der Funktion pgm_read_word.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
    uint16_t myWord;&lt;br /&gt;
&lt;br /&gt;
    myWord = pgm_read_word(&amp;amp;pgmFooWord);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zeiger auf Werte im Flash sind ebenfalls 16 Bits &amp;quot;gross&amp;quot;. (Die avr-libc pgmspace-Funktionen unterstützen nur die unteren 64kB Flash bei Controllern mit mehr als 64kB.) Pointer müssen gegebenenfalls &amp;quot;gecastet&amp;quot; werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
    uint8_t *ptrToArray;&lt;br /&gt;
&lt;br /&gt;
    ptrToArray = (uint8_t*)(pgm_read_word(&amp;amp;pgmPointerToArray1));&lt;br /&gt;
    // ptrToArray zeigt nun auf das erste Element des Byte-Arrays pgmPointerToArray1&lt;br /&gt;
&lt;br /&gt;
    for (i=0;i&amp;lt;3;i++) {&lt;br /&gt;
        myByte = pgm_read_byte(ptrToArray+i);&lt;br /&gt;
        // mach&#039; was mit myByte... (18, 3, 70)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    ptrToArray = (uint8_t*)(pgm_read_word(&amp;amp;pgmPointerArray[1]));&lt;br /&gt;
    &lt;br /&gt;
    // ptrToArray zeigt nun auf das erste Element des Byte-Arrays pgmPointerToArray2&lt;br /&gt;
    // da im zweiteb Element des Pointer-Arrays pgmPointerArray die Adresse&lt;br /&gt;
    // von pgmPointerToArray2 abgelegt ist&lt;br /&gt;
&lt;br /&gt;
    for (i=0;i&amp;lt;3;i++) {&lt;br /&gt;
        myByte = pgm_read_byte(ptrToArray+i);&lt;br /&gt;
        // mach&#039; was mit myByte... (30, 7, 79)&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Floats und Structs lesen ===&lt;br /&gt;
&lt;br /&gt;
Um komplexe Datentypen (structs), nicht-integer Datentypen (floats) aus dem Flash auszulesen, sind Hilfsfunktionen erforderlich. Einige Beispiele:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* Beispiel float aus Flash */&lt;br /&gt;
&lt;br /&gt;
float pgmFloatArray[3] PROGMEM = {1.1, 2.2, 3.3};&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
/* liest float von Flash-Addresse addr und gibt diese als return-value zurueck */&lt;br /&gt;
inline float pgm_read_float(const float *addr)&lt;br /&gt;
{	&lt;br /&gt;
	union&lt;br /&gt;
	{&lt;br /&gt;
		uint16_t i[2];	// 2 16-bit-Worte&lt;br /&gt;
		float f;&lt;br /&gt;
	} u;&lt;br /&gt;
	&lt;br /&gt;
	u.i[0]=pgm_read_word((PGM_P)addr);&lt;br /&gt;
	u.i[1]=pgm_read_word((PGM_P)addr+2);&lt;br /&gt;
	&lt;br /&gt;
	return u.f;&lt;br /&gt;
} &lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
void egal(void)&lt;br /&gt;
{&lt;br /&gt;
   int i;&lt;br /&gt;
   float f;&lt;br /&gt;
&lt;br /&gt;
   for (i=0;i&amp;lt;3;i++) {&lt;br /&gt;
      f = pgm_read_float(&amp;amp;pgmFloatArray[i]); // entspr. &amp;quot;f = pgmFloatArray[i];&amp;quot;&lt;br /&gt;
      // mach&#039; was mit f &lt;br /&gt;
   }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
TODO: Beispiele fuer structs und pointer aus flash auf struct im flash (menues, state-machines etc.)&lt;br /&gt;
&lt;br /&gt;
=== Vereinfachung für Zeichenketten (Strings) im Flash ===&lt;br /&gt;
&lt;br /&gt;
Zeichenketten können innerhalb des Quellcodes als &amp;quot;Flash-Konstanten&amp;quot; ausgewiesen werden. Dazu dient das Makro PSTR aus pgmspace.h. Dies erspart die getrennte Deklaration mit PROGMEM-Attribut.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/pgmspace.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define MAXLEN 30&lt;br /&gt;
&lt;br /&gt;
char StringImFlash[] PROGMEM = &amp;quot;Erwin Lindemann&amp;quot;; // im &amp;quot;Flash&amp;quot;&lt;br /&gt;
char StringImRam[MAXLEN];&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
    strcpy(StringImRam, &amp;quot;Mueller-Luedenscheidt&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    if (!strncmp_P(StringImRam, StringImFlash, 5) { &lt;br /&gt;
        // mach&#039; was, wenn die ersten 5 Zeichen identisch - hier nicht&lt;br /&gt;
    }&lt;br /&gt;
    else {&lt;br /&gt;
        // der Code hier wuerde ausgefuehrt &lt;br /&gt;
    } &lt;br /&gt;
&lt;br /&gt;
    if (!strncmp_P(StringImRam, PSTR(&amp;quot;Mueller-Schmitt&amp;quot;), 5)) {&lt;br /&gt;
        // der Code hier wuerde ausgefuehrt, die ersten 5 Zeichen stimmen ueberein&lt;br /&gt;
    }&lt;br /&gt;
    else {&lt;br /&gt;
        // wuerde bei nicht-Uebereinstimmung ausgefuehrt&lt;br /&gt;
    }&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aber Vorsicht: Ersetzt man zum Beispiel&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
const char textImFlashOK[] PROGMEM = &amp;quot;mit[]&amp;quot;; &lt;br /&gt;
// = Daten im &amp;quot;Flash&amp;quot;, textImFlashOK* zeigt auf Flashadresse&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
durch&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
const char* textImFlashProblem PROGMEM = &amp;quot;mit*&amp;quot;;&lt;br /&gt;
// Konflikt: Daten im BSS (lies: RAM), textImFlashFAIL* zeigt auf Flashadresse&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
dann kann es zu Problemen mit AVR-GCC kommen. Zu erkennen daran, dass der Initialisierungsstring von &amp;quot;textInFlashProblem&amp;quot; zu den Konstanten ans Ende des Programmcodes gelegt wird (BSS), von dem aus er zur Benutzung eigentlich ins RAM kopiert werden sollte (und wird). Da der lesende Code (mittels pgm_read*) trotzdem an einer Stelle vorne im Flash sucht, wird Unsinn gelesen. Dies scheint ein weiters Problem des AVR-GCC (gesehen bei avr-gcc 3.4.1 und 3.4.2) bei der Anpassung an die Harvard-Architektur zu sein (konstanter Pointer auf variable Daten?!). Abhilfe (&amp;quot;Workaround&amp;quot;): Initialisierung bei Zeichenketten mit [] oder gleich im Code PSTR(&amp;quot;...&amp;quot;) nutzen.&lt;br /&gt;
&lt;br /&gt;
Übergibt man Zeichenketten (genauer: die Adresse des ersten Zeichens), die im Flash abglegt sind an eine Funktion, muss diese entsprechend programmiert sein. Die Funktion selbst hat keine Möglichkeit zu unterscheiden ob es sich um eine Adresse im Flash  oder im RAM handelt. Die avr-libc und viele andere avr-gcc-Bibliotheken halten sich an die Konvention, dass Namen von Funktionen die Flash-Adressen erwarten mit dem Suffix _p (oder _P) versehen sind. &lt;br /&gt;
&lt;br /&gt;
Von einigen Bibliotheken werden Makros definiert, die &amp;quot;automatisch&amp;quot; ein PSTR bei Verwendung einer Funktion einfügen. Ein Blick in den Header-File der Bibliothek zeigt, ob dies der Fall ist. Ein Beispiel aus P. Fleurys lcd-Library:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
// Ausschnitt aus dem Header-File lcd.h der &amp;quot;Fleury-LCD-Lib.&amp;quot;&lt;br /&gt;
...&lt;br /&gt;
extern void lcd_puts_p(const char *progmem_s);&lt;br /&gt;
#define lcd_puts_P(__s) lcd_puts_p(PSTR(__s))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
// in einer Anwendung (wieauchimmmer.c)&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/pgmspace.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;quot;lcd.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
char StringImFlash[] PROGMEM = &amp;quot;Erwin Lindemann&amp;quot;; // im &amp;quot;Flash&amp;quot;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
    lcd_puts_p(StringImFlash); &lt;br /&gt;
    lcd_puts_P(&amp;quot;Dr. Kloebner&amp;quot;); &lt;br /&gt;
    // daraus wird wg. #define lcd_put_P...:  lcd_puts_p( PSTR(&amp;quot;Dr. Kloebner&amp;quot;) );&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Flash in der Anwendung schreiben ===&lt;br /&gt;
&lt;br /&gt;
Bei AVRs mit &amp;quot;self-programming&amp;quot;-Option (auch bekannt als Bootloader-Support) können Teile des Flash-Speichers auch vom Anwendungsprogramm selbst beschrieben werden. Dies ist nur möglich, wenn die Schreibfunktionen in einem besonderen Speicherbereich (boot-section) des Programmspeichers/Flash abgelegt sind. Für Details sei hier auf das jeweilige Controller-Datenblatt und die Erläuterungen zum Modul boot.h der avr-libc verwiesen. Es existieren auch Application-Notes dazu bei atmel.com, die auf avr-gcc-Code übertragbar sind.&lt;br /&gt;
&lt;br /&gt;
=== Warum so kompliziert? ===&lt;br /&gt;
&lt;br /&gt;
Zu dem Thema, warum die Verabeitung von Werten aus dem Flash-Speicher so &amp;quot;kompliziert&amp;quot; ist, sei hier nur kurz erläutert: Die Harvard-Architektur des AVR weist getrennte Adressräume für Programm(Flash)- und Datenspeicher(RAM) auf. Der C-Standard und der gcc-Compiler sehen keine unterschiedlichen Adressräume vor. &lt;br /&gt;
Hat man zum Beispiel eine Funktion string_an_uart(const char* s) und übergibt an diese Funktion die Adresse einer Zeichenkette (einen Pointer, z.B. 0x01fe), &amp;quot;weiss&amp;quot; die Funktion nicht, ob die Adresse auf den Flash-Speicher oder den/das RAM zeigt. Allein aus dem Pointer-Wert (der Zahl) kann nicht geschlossen werden, ob ein &amp;quot;einfaches&amp;quot; zeichen_an_uart(s[i]) oder zeichen_an_uart(pgm_read_byte(&amp;amp;s[i]) genutzt werden muss, um das i-te Zeichen auszugeben.&lt;br /&gt;
&lt;br /&gt;
Einige AVR-Compiler &amp;quot;tricksen&amp;quot; etwas, in dem sie für einen Pointer nicht nur die Adresse anlegen, sondern zusätzlich zu jedem Pointer den Ablageort (Flash oder RAM) intern sichern. Bei Aufruf einer Funktion wird dann bei Pointer-Parametern neben der Adresse auch der Speicherbereich, auf den der Pointer zeigt, übergeben. Dies hat jedoch nicht nur Vorteile; Erläuterungen warum dies so ist, führen an dieser Stelle zu weit.&lt;br /&gt;
&lt;br /&gt;
* siehe auch: [http://www.nongnu.org/avr-libc/user-manual/index.html Dokumentation der avr-libc] Abschnitte Modules/Program Space String Utilities und Abschnitt Modules/Bootloader Support Utilities&lt;br /&gt;
&lt;br /&gt;
== EEPROM ==&lt;br /&gt;
&lt;br /&gt;
Man beachte, dass der EEPROM-Speicher nur eine begrenzte Anzahl von Schreibzugriffen zulässt. Beschreibt man eine EEPROM-Zelle öfter als die im Datenblatt zugesicherte Anzahl (typisch 100.000), wird die Funktion der Zelle nicht mehr garantiert. &lt;br /&gt;
Dies gilt für jede einzelne Zelle. Bei geschickter Programmierung (z.B. Ring-Puffer), bei der die zu beschreibenden Zellen regelmässig gewechselt werden, kann man eine deutlich höhere Anzahl an Schreibzugriffen, bezogen auf den Gesamtspeicher, erreichen.&lt;br /&gt;
&lt;br /&gt;
Schreib- und Lesezugriffe auf den EEPROM-Speicher erfolgen über die im Modul eeprom.h definierten Funktionen. Mit diesen Funktionen können einzelne Bytes, Datenworte (16bit) und Datenblöcke geschrieben und gelesen werden. &lt;br /&gt;
&lt;br /&gt;
Bei Nutzung des EEPROMs ist zu beachten, dass vor dem Zugriff auf diesen Speicher abgefragt wird, ob der Controller die vorherige EEPROM-Operation abgeschlossen hat. Die avr-libc-Funktionen beinhalten diese Prüfung, man muss sie nicht selbst implementieren. Man sollte auch verhindern, dass der Zugriff durch die Abarbeitung einer Interrupt-Routine unterbrochen wird, da bestimme Befehlsabfolgen vorgegeben sind, die innerhalb weniger Taktzyklen aufeinanderfolgen müssen (&amp;quot;timed sequence&amp;quot;). Auch dies muss bei Nutzung der Funktionen aus der avr-libc/eeprom.h-Datei nicht selbst implementiert werden. Innerhalb der Funktionen werden Interrupts vor der &amp;quot;EEPROM-Sequenz&amp;quot; global deaktiviert und im Anschluss, falls vorher auch schon eingeschaltet, wieder aktiviert.&lt;br /&gt;
&amp;lt;!-- kann bald geloescht werden:&lt;br /&gt;
Diese Prüfung wird nicht implizit durchgeführt. Im Zweifel kann man Sicherheitshalber bei EEPROM-Zugriffen die Interrupts global deaktivieren, z.B. so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    uint8_t sreg;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
    sreg = SREG;&lt;br /&gt;
    cli();&lt;br /&gt;
&lt;br /&gt;
/* hier die eeprom-Zugriffe */&lt;br /&gt;
&lt;br /&gt;
    SREG = sreg;&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei der Deklaration einer Variable im EEPROM, ist das Attribut für die Section &amp;quot;.eeprom&amp;quot; zu ergänzen. Die Nutzung einer [[C-Präprozessor]]-Ersetzung bringt etwas Bequemlichkeit. Siehe dazu folgendes Beispiel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/eeprom.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// alle Textstellen EEPROM im Quellcode durch __attribute__ ... ersetzen&lt;br /&gt;
#define EEPROM  __attribute__ ((section (&amp;quot;.eeprom&amp;quot;)))&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
/* Byte */&lt;br /&gt;
uint8_t eeFooByte EEPROM = 123;&lt;br /&gt;
&lt;br /&gt;
/* Wort */&lt;br /&gt;
uint16_t eeFooWort EEPROM = 12345;&lt;br /&gt;
&lt;br /&gt;
/* float */&lt;br /&gt;
float eeFooFloat EEPROM;&lt;br /&gt;
&lt;br /&gt;
/* Byte-Feld */&lt;br /&gt;
uint8_t eeFooByteArray1[] EEPROM = { 18, 3 ,70 };&lt;br /&gt;
uint8_t eeFooByteArray2[] EEPROM = { 30, 7 ,79 };&lt;br /&gt;
&lt;br /&gt;
/* 16-bit unsigned short feld */&lt;br /&gt;
 &amp;lt;!-- #define MAXELEM wo wird das hier verwendet? hab ich was übersehen? Nein, keine Ahnung warum ich das da rein geschreiben hatte. --&amp;gt;&lt;br /&gt;
uint16_t eeFooWordArray1[4] EEPROM;&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bytes lesen/schreiben ===&lt;br /&gt;
&lt;br /&gt;
Die avr-libc Funktion zum Lesen eines Bytes heisst eeprom_read_byte. Parameter ist die Adresse des Bytes im EEPROM. Geschrieben wird über die Funktion eeprom_write_byte mit den Parametern Adresse und Inhalt. Anwendungsbeispiel:&lt;br /&gt;
&amp;lt;!-- altes Beispiel&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    uint8_t myByte;&lt;br /&gt;
    uint8_t sreg;&lt;br /&gt;
&lt;br /&gt;
    sreg = SREG; // (1)&lt;br /&gt;
    cli();       // (1)&lt;br /&gt;
&lt;br /&gt;
    myByte = eeprom_read_byte(&amp;amp;eeFooByte); // lesen&lt;br /&gt;
    // myByte hat nun den Wert 123&lt;br /&gt;
...&lt;br /&gt;
    myByte = 99;&lt;br /&gt;
    eeprom_write_byte(&amp;amp;eeFooByte, myByte); // schreiben&lt;br /&gt;
...&lt;br /&gt;
    myByte = eeprom_read_byte(&amp;amp;eeFooByteArray1[1]); &lt;br /&gt;
    // myByte hat nun den Wert 3&lt;br /&gt;
...&lt;br /&gt;
    SREG = sreg; // (1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die mit (1) markierten Zeilen dienen hierbei dem (möglicherweise übertriebenen) Schutz vor Unterbrechnungen durch Interrupts.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    uint8_t myByte;&lt;br /&gt;
&lt;br /&gt;
    myByte = eeprom_read_byte(&amp;amp;eeFooByte); // lesen&lt;br /&gt;
    // myByte hat nun den Wert 123&lt;br /&gt;
...&lt;br /&gt;
    myByte = 99;&lt;br /&gt;
    eeprom_write_byte(&amp;amp;eeFooByte, myByte); // schreiben&lt;br /&gt;
...&lt;br /&gt;
    myByte = eeprom_read_byte(&amp;amp;eeFooByteArray1[1]); &lt;br /&gt;
    // myByte hat nun den Wert 3&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wort lesen/schreiben ===&lt;br /&gt;
&lt;br /&gt;
Schreiben und Lesen von Datenworten erfolgt analog zur Vorgehensweise bei Bytes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    uint16_t myWord;&lt;br /&gt;
&lt;br /&gt;
    myWord = eeprom_read_word(&amp;amp;eeFooWord); // lesen&lt;br /&gt;
    // myWord hat nun den Wert 12345&lt;br /&gt;
...&lt;br /&gt;
    myWord = 2222;&lt;br /&gt;
    eeprom_write_word(&amp;amp;eeFooWord, myWord); // schreiben&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Block lesen/schreiben ===&lt;br /&gt;
&lt;br /&gt;
Lesen und Schreiben von Datenblöcken erfolgt über die Funktionen &#039;&#039;eeprom_read_block()&#039;&#039; bzw. &#039;&#039;eeprom_write_block()&#039;&#039;. Die Funktionen erwarten drei Parameter: die Adresse der Quell- bzw. Zieldaten im RAM, die EEPROM-Addresse und die Länge des Datenblocks in Bytes (size_t).&lt;br /&gt;
&lt;br /&gt;
TODO: &#039;&#039;&#039;Vorsicht!&#039;&#039;&#039; die folgenden Beispiele sind noch nicht geprueft, erstmal nur als Hinweis auf &amp;quot;das Prinzip&amp;quot;. Evtl. fehlen &amp;quot;casts&amp;quot; und mglw. noch mehr.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    unit8_t  myByteBuffer[3];&lt;br /&gt;
    uint16_t myWordBuffer[4];&lt;br /&gt;
&lt;br /&gt;
    /* Datenblock aus EEPROM LESEN  */&lt;br /&gt;
&lt;br /&gt;
    /* liest 3 Bytes aber der von eeFooByteArray1 definierten EEPROM-Adresse&lt;br /&gt;
       in das RAM-Array myByteBuffer */&lt;br /&gt;
    eeprom_read_block(myByteBuffer,eeFooByteArray1,3);&lt;br /&gt;
&lt;br /&gt;
    /* dito etwas anschaulicher aber &amp;quot;unnuetze Tipparbeit&amp;quot;: */&lt;br /&gt;
    eeprom_read_block(&amp;amp;myByteBuffer[0],&amp;amp;eeFooByteArray[0],3);&lt;br /&gt;
&lt;br /&gt;
    /* dito mit etwas Absicherung betr. der Laenge */&lt;br /&gt;
    eeprom_read_block(myByteBuffer,eeFooByteArray1,sizeof(myByteBuffer));&lt;br /&gt;
&lt;br /&gt;
    /* und nun mit &amp;quot;16bit&amp;quot; */&lt;br /&gt;
    eeprom_read_block(myWordBuffer,eeFooWordArray,sizeof(myWordBuffer));&lt;br /&gt;
&lt;br /&gt;
    /* Datenlock in EEPROM SCHREIBEN */&lt;br /&gt;
    eeprom_write_block(myByteBuffer,eeFooByteArray1,sizeof(myByteBuffer));&lt;br /&gt;
    eeprom_write_block(myWordBuffer,eeFooWordArray,sizeof(myWordBuffer));&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Nicht-Integer&amp;quot;-Datentypen wie z.B. Fliesskommazahlen lassen sich recht praktisch ueber eine &#039;&#039;union&#039;&#039; in &amp;quot;Byte-Arrays&amp;quot; konvertieren und wieder &amp;quot;zurückwandeln&amp;quot;. Dies erweist sich hier (aber nicht nur hier) als nützlich.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
   float myFloat = 12.34;&lt;br /&gt;
&lt;br /&gt;
   union {&lt;br /&gt;
      float r;&lt;br /&gt;
      uint8_t n[sizeof(float)];&lt;br /&gt;
   } u;&lt;br /&gt;
&lt;br /&gt;
   u.r = myFloat;&lt;br /&gt;
   &lt;br /&gt;
   /* float in EEPROM */&lt;br /&gt;
   eeprom_write_block(&amp;amp;(u.i),&amp;amp;eeFooFloat,sizeof(float));&lt;br /&gt;
&lt;br /&gt;
   /* float aus EEPROM */&lt;br /&gt;
   eeprom_read_block(&amp;amp;(u.i),&amp;amp;eeFooFloat,sizeof(float));&lt;br /&gt;
   /* u.r wieder 12.34 */&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auch zusammengesetzte Typen lassen sich mit den Block-Routinen verarbeiten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
typedef struct {&lt;br /&gt;
    uint8_t   label[8];&lt;br /&gt;
    unin8_t   rom_code[8];&lt;br /&gt;
} tMyStruct;&lt;br /&gt;
&lt;br /&gt;
#define MAXSENSORS 3&lt;br /&gt;
tMyStruct eeMyStruct[MAXSENSORS] EEPROM;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
void egal(void)&lt;br /&gt;
{&lt;br /&gt;
   tMyStruct work;&lt;br /&gt;
   &lt;br /&gt;
   strcpy(work.label,&amp;quot;Flur&amp;quot;);&lt;br /&gt;
   GetRomCode(work.rom_code);     // Dummy zur Veranschaulichung - setzt rom-code&lt;br /&gt;
&lt;br /&gt;
   /* Sichern von &amp;quot;work&amp;quot; im EEPROM */&lt;br /&gt;
   eeprom_write_block(&amp;amp;work,&amp;amp;eeMyStruct[0],sizeof(tMyStruct)); // f. Index 0&lt;br /&gt;
   strcpy(work.label,&amp;quot;Bad&amp;quot;);&lt;br /&gt;
   GetRomCode(work.rom_code);&lt;br /&gt;
   eeprom_write_block(&amp;amp;work,&amp;amp;eeMyStruct[1],sizeof(tMyStruct)); // f. Index 1&lt;br /&gt;
...&lt;br /&gt;
   /* Lesen der Daten EEPROM Index 0 in &amp;quot;work&amp;quot; */&lt;br /&gt;
   eeprom_read_block(&amp;amp;work,&amp;amp;eeMyStruct[0],sizeof(tMyStruct));&lt;br /&gt;
   // work.label hat nun den Inhalt &amp;quot;Flur&amp;quot;&lt;br /&gt;
...&lt;br /&gt;
}&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== EEPROM-Speicherabbild in .eep-Datei ===&lt;br /&gt;
&lt;br /&gt;
Eine besondere Funktion des avr-gcc ist, dass mit einem entsprechenden makefile aus den Initialisierungswerten der Variablen im Quellcode eine Datei erzeugt werden kann, die man auf den Controller programmieren kann (.eep-Datei). Damit können sehr elegant Standardwerte für den EEPROM-Inhalt im Quellcode definiert werden. Die Vorgehensweise wird aus dem WinAVR-Beispielmakefile ersichtlich. Siehe dazu die Erläuterungen im Abschnitt Exkurs: Makefiles.&lt;br /&gt;
&lt;br /&gt;
=== Bekannte Probleme bei den EEPROM-Funktionen ===&lt;br /&gt;
&lt;br /&gt;
Vorsicht: Nicht alle neuen AVR Controller werden von avr-libc/eeprom.h untersützt (Stand Version 1.0.4). Insbesondere beim ATMega169 funktionieren die Funktionen nicht korrekt (Ursache: unterschiedliche Speicheradressen der EEPROM-Register) Etwas ältere Typen, oder zu den &amp;quot;etablierten&amp;quot; Controllern kompatible, bereiten jedoch hier keine Proleme. Im Zweifel hilft ein Blick in den vom Compiler erzeugten Assembler-Code (lst/lss-Dateien). &lt;br /&gt;
&lt;br /&gt;
In jedem Datenblatt zu AVR-Controllern mit EEPROM sind kurze Beispielecodes für den Schreib- und Lesezugriff enthalten. Der dort gezeigt Code kann direkt auch mit dem avr-gcc (ohne avr-libc/eeprom.h) genutzt werden (&amp;quot;copy/paste&amp;quot;, gegebenfalls Schutz vor Unterbrechnung/Interrupt ergänzen &#039;&#039;uint8_t sreg; sreg=SREG; [EEPROM-Code] ; SREG=sreg; return;&#039;&#039;, siehe Abschnitt Interrupts).&lt;br /&gt;
&lt;br /&gt;
* siehe auch: [http://www.nongnu.org/avr-libc/user-manual/index.html Dokumentation der avr-libc] Abschnitt Modules/EEPROM handling&lt;br /&gt;
&lt;br /&gt;
= Assembler und Inline-Assembler =&lt;br /&gt;
&lt;br /&gt;
Gelegentlich erweist es sich als nützlich, C und Assembler-Code in einer Anwendung zu nutzen. Typischerweise wird das Hauptprogramm in C verfasst und wenige, extrem zeitkritische oder hardwarenahe Operationen in Assembler.&lt;br /&gt;
&lt;br /&gt;
Die &amp;quot;gcc-Toolchain&amp;quot; bietet dazu zwei Möglichkeiten:&lt;br /&gt;
&lt;br /&gt;
;Inline-Assembler: &lt;br /&gt;
Die Assembleranweisungen werden in direkt in den C-Code integriert. Eine Quellcode-Datei enhält somit C- und Assembleranweisungen&lt;br /&gt;
&lt;br /&gt;
;Assembler-Dateien: &lt;br /&gt;
Der Assembler-Codecode befindet sich in eigenen Quellcodedateien. Dieser werden vom gnu-Assembler (avr-as) zu Object-Dateien assembliert (&amp;quot;compiliert&amp;quot;) und mit den aus dem C-Code erstellten Object-Dateien zusammengebunden (gelinkt).&lt;br /&gt;
&lt;br /&gt;
== Inline-Assembler ==&lt;br /&gt;
&lt;br /&gt;
Inline-Assembler bietet sich an, wenn nur wenig Assembleranweisungen benötigt werden. Typische Anwendung sind kurze Codesequenzen für zeitkritische Operationen in Interrupt-Routinen oder sehr präzise Warteschleifen (z.B. 1-Wire). Inline-Assembler wird mit &#039;&#039;&#039;asm volatile&#039;&#039;&#039; eingeleitet, die Assembler-Anweisungen werden in einer Zeichenkette zusammengefasst, die als &amp;quot;Parameter&amp;quot; übergeben wird. Durch Doppelpunkte getrennt werden die Ein- und Ausgaben sowie die &amp;quot;Clobber-Liste&amp;quot; angegeben.&lt;br /&gt;
&lt;br /&gt;
Ein einfaches Beispiel für Inline-Assembler ist das Einfügen einer NOP-Anweisung. NOP steht für &#039;&#039;&#039;NO&#039;&#039;&#039;-O&#039;&#039;&#039;P&#039;&#039;&#039;eration. Dieser Assembler-Befehl benötigt genau einen Taktzyklus, ansonsten &amp;quot;tut sich nichts&amp;quot;. Sinnvolle Anwendungen für NOP sind genaue Delay(=warte)-Funktionen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
/* Verzoegern der weiteren Programmausfuehrung um&lt;br /&gt;
   genau 3 Taktzyklen */&lt;br /&gt;
asm volatile (&amp;quot;nop&amp;quot;::);&lt;br /&gt;
asm volatile (&amp;quot;nop&amp;quot;::);&lt;br /&gt;
asm volatile (&amp;quot;nop&amp;quot;::);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Weiterhin kann mit einem NOP verhindert werden, dass leere Schleifen, die als Warteschleifen gedacht sind, wegoptimiert werden. Der Compiler erkennt ansonsten die vermeindlich nutzlose Schleife und erzeugt dafür keinen Code im ausführbaren Programm.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint16_t i;&lt;br /&gt;
&lt;br /&gt;
/* leere Schleife - wird bei eingeschalteter Compiler-Optimierung wegoptimiert */&lt;br /&gt;
for (i=0;i&amp;lt;1000;i++);&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
/* Schleife erzwingen (keine Optimierung): &amp;quot;NOP-Methode&amp;quot; */&lt;br /&gt;
for (i=0;i&amp;lt;1000;i++) asm volatile(&amp;quot;NOP&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
/* alternative Methode (keine Optimierung): */&lt;br /&gt;
volatile uint16_t j;&lt;br /&gt;
for (j=0;j&amp;lt;1000;j++);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ein weiterer nützliche &amp;quot;Assembler-Einzeiler&amp;quot; ist der Auruf von sleep (&#039;&#039;asm volatile (&amp;quot;sleep&amp;quot;::);&#039;&#039;), da hierzu keine eigene Funktion in der avr-libc existiert.&lt;br /&gt;
&lt;br /&gt;
Als Beispiel für mehrzeiligen Inline-Assembler eine präzise delay-Funktion. Die Funktion erhält ein 16-bit Wort als Parameter, prüft den Parameter auf 0 und beendet die Funktion in diesem Fall oder durchläuft die folgende Schleife sooft wie im Wert des Parameters angegeben. Inline-Assembler hat hier den Vorteil des die Laufzeit unabhängig von der Optimierungsstufe (Parameter -O, vgl. makefile) und der Compiler-Version ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
static inline void delayloop16(uint16_t count)&lt;br /&gt;
{&lt;br /&gt;
	asm volatile (  &amp;quot;cp  %A0,__zero_reg__ \n\t&amp;quot;  \&lt;br /&gt;
                     &amp;quot;cpc %B0,__zero_reg__ \n\t&amp;quot;  \&lt;br /&gt;
                     &amp;quot;breq L_Exit_%=       \n\t&amp;quot;  \&lt;br /&gt;
                     &amp;quot;L_LOOP_%=:           \n\t&amp;quot;  \&lt;br /&gt;
                     &amp;quot;sbiw %0,1            \n\t&amp;quot;  \&lt;br /&gt;
                     &amp;quot;brne L_LOOP_%=       \n\t&amp;quot;  \&lt;br /&gt;
                     &amp;quot;L_Exit_%=:           \n\t&amp;quot;  \&lt;br /&gt;
                     : &amp;quot;=w&amp;quot; (count)&lt;br /&gt;
		     : &amp;quot;0&amp;quot;  (count)&lt;br /&gt;
                   );                            &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Jede Anweisung wird mit &#039;&#039;&#039;\n\t&#039;&#039;&#039; abgeschlossen, alle Zeilen mit &#039;&#039;&#039;\&#039;&#039;&#039; zu einer &amp;quot;langen Zeichenkette&amp;quot; verbunden.&lt;br /&gt;
* Sprung-Marken (labels) werden mit einem Prozentzeichen abgeschlossen, der Präprozessor (Assembler?) setzt an dieser Stelle eine laufende Nummer ein, die Doppelbezeichnungen bei mehrmaliger Verwendung wird somit verhindert.&lt;br /&gt;
&lt;br /&gt;
Das Resultat zeigt ein Blick in die .lss-Datei. Aus delayloop16(20); erzeugt der Preprozessor/Assembler/Linker z.B.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
 13a:	84 e1       	ldi	r24, 0x14	; 20&lt;br /&gt;
 13c:	90 e0       	ldi	r25, 0x00	; 0&lt;br /&gt;
 13e:	81 15       	cp	r24, r1&lt;br /&gt;
 140:	91 05       	cpc	r25, r1&lt;br /&gt;
 142:	11 f0       	breq	.+4      	; 0x148&lt;br /&gt;
00000144 &amp;lt;L_LOOP_121&amp;gt;:&lt;br /&gt;
 144:	01 97       	sbiw	r24, 0x01	; 1&lt;br /&gt;
 146:	f1 f7       	brne	.-4      	; 0x144&lt;br /&gt;
00000148 &amp;lt;L_Exit_121&amp;gt;:&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Detaillierte Ausführungen zum Thema Inline-Assembler finden sich in der Dokumentation der avr-libc.&lt;br /&gt;
&lt;br /&gt;
* siehe auch: Dokumentation der avr-libc/Related Pages/Inline Asm&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc0856.pdf AVR Assembler-Anweisungsliste]&lt;br /&gt;
&lt;br /&gt;
== Assembler-Dateien ==&lt;br /&gt;
&lt;br /&gt;
Assembler-Dateien erhalten die Endung .S (&#039;&#039;grosses&#039;&#039; S) und werden im makefile nach WinAVR/mfile-Vorlage hinter &#039;&#039;ASRC=&#039;&#039; durch Leerzeichen getrennt aufgelistet.&lt;br /&gt;
&lt;br /&gt;
Im Beispiel eine Funktion &#039;&#039;superFunc&#039;&#039; die alle Pins des Ports D auf &amp;quot;Ausgang&amp;quot; schaltet, eine Funktion &#039;&#039;ultraFunc&#039;&#039;, die die Ausgänge entsprechend des übergebenen Parameters schaltet, eine Funktion &#039;&#039;gigaFunc&#039;&#039;, die den Status von Port A zurückgibt und eine Funktion addFunc, die zwei Bytes zu einem 16-bit-Wort addiert. Die Zuweisungen im C-Code (PORTx = ) verhindern, dass der Compiler die Aufrufe wegoptimiert und dienen nur zur Veranschaulichung der Parameterübergaben.&lt;br /&gt;
&lt;br /&gt;
Zuerst der Assembler-Code. Der Dateiname sei useful.S:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;quot;avr/io.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
// Arbeitsregister (ohne &amp;quot;r&amp;quot;)&lt;br /&gt;
workreg  = 16&lt;br /&gt;
workreg2 = 17&lt;br /&gt;
&lt;br /&gt;
// Konstante:&lt;br /&gt;
ALLOUT = 0xff&lt;br /&gt;
&lt;br /&gt;
// ** Setze alle Pins von PortD auf Ausgang **&lt;br /&gt;
// keine Parameter, keine Rueckgabe&lt;br /&gt;
.global superFunc&lt;br /&gt;
.func superFunc&lt;br /&gt;
superFunc:&lt;br /&gt;
   push workreg&lt;br /&gt;
   ldi workreg, ALLOUT&lt;br /&gt;
   out  _SFR_IO_ADDR(DDRD), workreg  // beachte: _SFR_IO_ADDR()&lt;br /&gt;
   pop workreg&lt;br /&gt;
   ret&lt;br /&gt;
.endfunc&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// ** Setze PORTD auf uebergebenen Wert **&lt;br /&gt;
// Parameter in r24 (LSB immer bei &amp;quot;graden&amp;quot; Nummern)&lt;br /&gt;
.global ultraFunc&lt;br /&gt;
.func ultraFunc&lt;br /&gt;
ultraFunc:&lt;br /&gt;
   out  _SFR_IO_ADDR(PORTD), 24&lt;br /&gt;
   ret&lt;br /&gt;
.endfunc&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// ** Zustand von PINA zurueckgeben **&lt;br /&gt;
// Rueckgabewerte in r24:r25 (LSB:MSB), hier nur LSB genutzt&lt;br /&gt;
.global gigaFunc&lt;br /&gt;
.func gigaFunc&lt;br /&gt;
gigaFunc:&lt;br /&gt;
   in 24, _SFR_IO_ADDR(PINA)&lt;br /&gt;
   ret&lt;br /&gt;
.endfunc&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// ** Zwei Bytes addieren und 16-bit-Wort zurueckgeben **&lt;br /&gt;
// Parameter in r24 (Summand1) und r22 (Summand2) -&lt;br /&gt;
//  Parameter sind Word-&amp;quot;aligned&amp;quot; d.h. LSB immer auf &amp;quot;graden&amp;quot;&lt;br /&gt;
//  Registernummern. Bei 8-Bit und 16-Bit Paramtern somit &lt;br /&gt;
//  beginnend bei r24 dann r22 dann r20 etc.&lt;br /&gt;
// Rueckgabewert in r24:r25&lt;br /&gt;
.global addFunc&lt;br /&gt;
.func addFunc&lt;br /&gt;
addFunc:&lt;br /&gt;
   push workreg&lt;br /&gt;
   push workreg2&lt;br /&gt;
   clr workreg2&lt;br /&gt;
   mov workreg, 22&lt;br /&gt;
   add workreg, 24&lt;br /&gt;
   adc workreg2, 1    // r1 - assumed to be always zero ...&lt;br /&gt;
   movw r24, workreg&lt;br /&gt;
   pop workreg2&lt;br /&gt;
   pop workreg&lt;br /&gt;
   ret&lt;br /&gt;
.endfunc&lt;br /&gt;
&lt;br /&gt;
// oh je - sorry - Mein AVR-Assembler ist eingerostet, hoffe das stimmt so...&lt;br /&gt;
&lt;br /&gt;
.end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Makefile ist der Name der Assembler-Quellcodedatei einzutragen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
ASRC = useful.S&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Aufruf erfolgt dann im C-Code so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
extern void superFunc(void);&lt;br /&gt;
extern void ultraFunc(uint8_t setVal);&lt;br /&gt;
extern uint8_t gigaFunc(void);&lt;br /&gt;
extern uint16_t addFunc(uint8_t w1, uint8_t w2);&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
[...]&lt;br /&gt;
  superFunc();&lt;br /&gt;
  &lt;br /&gt;
  ultraFunc(0x55);&lt;br /&gt;
  &lt;br /&gt;
  PORTD = gigaFunc();&lt;br /&gt;
&lt;br /&gt;
  PORTA = (addFunc(0xF0, 0x11) &amp;amp; 0xff);&lt;br /&gt;
  PORTB = (addFunc(0xF0, 0x11) &amp;gt;&amp;gt; 8);&lt;br /&gt;
[...]&lt;br /&gt;
} &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Ergebnis wird wieder in der lss-Datei ersichtlich:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
[...]&lt;br /&gt;
   superFunc();&lt;br /&gt;
 148:	0e 94 f6 00 	call	0x1ec&lt;br /&gt;
  &lt;br /&gt;
  ultraFunc(0x55);&lt;br /&gt;
 14c:	85 e5       	ldi	r24, 0x55	; 85&lt;br /&gt;
 14e:	0e 94 fb 00 	call	0x1f6&lt;br /&gt;
  &lt;br /&gt;
  PORTD = gigaFunc();&lt;br /&gt;
 152:	0e 94 fd 00 	call	0x1fa&lt;br /&gt;
 156:	82 bb       	out	0x12, r24	; 18&lt;br /&gt;
  &lt;br /&gt;
  PORTA = (addFunc(0xF0, 0x11) &amp;amp; 0xff);&lt;br /&gt;
 158:	61 e1       	ldi	r22, 0x11	; 17&lt;br /&gt;
 15a:	80 ef       	ldi	r24, 0xF0	; 240&lt;br /&gt;
 15c:	0e 94 ff 00 	call	0x1fe&lt;br /&gt;
 160:	8b bb       	out	0x1b, r24	; 27&lt;br /&gt;
  PORTB = (addFunc(0xF0, 0x11) &amp;gt;&amp;gt; 8);&lt;br /&gt;
 162:	61 e1       	ldi	r22, 0x11	; 17&lt;br /&gt;
 164:	80 ef       	ldi	r24, 0xF0	; 240&lt;br /&gt;
 166:	0e 94 fc 00 	call	0x1f8&lt;br /&gt;
 16a:	89 2f       	mov	r24, r25&lt;br /&gt;
 16c:	99 27       	eor	r25, r25&lt;br /&gt;
 16e:	88 bb       	out	0x18, r24	; 24&lt;br /&gt;
&lt;br /&gt;
[...]&lt;br /&gt;
000001ec &amp;lt;superFunc&amp;gt;:&lt;br /&gt;
// setze alle Pins von PortD auf Ausgang&lt;br /&gt;
.global superFunc&lt;br /&gt;
.func superFunc&lt;br /&gt;
superFunc:&lt;br /&gt;
   push workreg&lt;br /&gt;
 1ec:	0f 93       	push	r16&lt;br /&gt;
   ldi workreg, ALLOUT&lt;br /&gt;
 1ee:	0f ef       	ldi	r16, 0xFF	; 255&lt;br /&gt;
   out  _SFR_IO_ADDR(DDRD), workreg&lt;br /&gt;
 1f0:	01 bb       	out	0x11, r16	; 17&lt;br /&gt;
   pop workreg&lt;br /&gt;
 1f2:	0f 91       	pop	r16&lt;br /&gt;
   ret&lt;br /&gt;
 1f4:	08 95       	ret&lt;br /&gt;
&lt;br /&gt;
000001f6 &amp;lt;ultraFunc&amp;gt;:&lt;br /&gt;
.endfunc&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// setze PORTD auf uebergebenen Wert&lt;br /&gt;
.global ultraFunc&lt;br /&gt;
.func ultraFunc&lt;br /&gt;
ultraFunc:&lt;br /&gt;
   out  _SFR_IO_ADDR(PORTD), 24&lt;br /&gt;
 1f6:	82 bb       	out	0x12, r24	; 18&lt;br /&gt;
   ret&lt;br /&gt;
 1f8:	08 95       	ret&lt;br /&gt;
&lt;br /&gt;
000001fa &amp;lt;gigaFunc&amp;gt;:&lt;br /&gt;
.endfunc&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// Zustand von PINA zurueckgeben&lt;br /&gt;
.global gigaFunc&lt;br /&gt;
.func gigaFunc&lt;br /&gt;
gigaFunc:&lt;br /&gt;
   in 24, _SFR_IO_ADDR(PINA)&lt;br /&gt;
 1fa:	89 b3       	in	r24, 0x19	; 25&lt;br /&gt;
   ret&lt;br /&gt;
 1fc:	08 95       	ret&lt;br /&gt;
&lt;br /&gt;
000001fe &amp;lt;addFunc&amp;gt;:&lt;br /&gt;
.endfunc&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// zwei Bytes addieren und 16-bit-Wort zurueckgeben&lt;br /&gt;
.global addFunc&lt;br /&gt;
.func addFunc&lt;br /&gt;
addFunc:&lt;br /&gt;
   push workreg&lt;br /&gt;
 1fe:	0f 93       	push	r16&lt;br /&gt;
   push workreg2&lt;br /&gt;
 200:	1f 93       	push	r17&lt;br /&gt;
   clr workreg2&lt;br /&gt;
 202:	11 27       	eor	r17, r17&lt;br /&gt;
   mov workreg, 22&lt;br /&gt;
 204:	06 2f       	mov	r16, r22&lt;br /&gt;
   add workreg, 24&lt;br /&gt;
 206:	08 0f       	add	r16, r24&lt;br /&gt;
   adc workreg2, 1    // r1 - assumed to be always zero ...&lt;br /&gt;
 208:	11 1d       	adc	r17, r1&lt;br /&gt;
   movw r24, workreg&lt;br /&gt;
 20a:	c8 01       	movw	r24, r16&lt;br /&gt;
   pop workreg2&lt;br /&gt;
 20c:	1f 91       	pop	r17&lt;br /&gt;
   pop workreg&lt;br /&gt;
 20e:	0f 91       	pop	r16&lt;br /&gt;
   ret&lt;br /&gt;
 210:	08 95       	ret&lt;br /&gt;
&lt;br /&gt;
[...]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zuweisung von Registern zu Parameternummer und die Register für die Rückgabewerte sind in den &amp;quot;Register Usage Guidelines&amp;quot; der avr-libc-Dokumentation erläutert.&lt;br /&gt;
&lt;br /&gt;
siehe auch:&lt;br /&gt;
* [http://www.nongnu.org/avr-libc/user-manual/assembler.html avr-libc-Dokumentation: Related Pages/avr-libc and assembler programs]&lt;br /&gt;
* [http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_reg_usage avr-libc-Dokumentation: Related Pages/FAQ/&amp;quot;What registers are used by the C compiler?&amp;quot;]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
...TODO: globale Variablen für Datenaustausch&lt;br /&gt;
&lt;br /&gt;
= TODO =&lt;br /&gt;
&lt;br /&gt;
stdio.h, malloc() ???, Code-Optimierungen (&amp;quot;tricks&amp;quot;), &amp;quot;naked&amp;quot;-Functionen ??, IO-Register als Parameter/&amp;quot;Variablen&amp;quot; (volatile uint8_t *mybusport; mybusport=&amp;amp;PORTB; void sendbus(uint8_t *parm)...)&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Diskussion:I2C-Schaltmodul&amp;diff=14535</id>
		<title>Diskussion:I2C-Schaltmodul</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Diskussion:I2C-Schaltmodul&amp;diff=14535"/>
		<updated>2005-02-05T11:49:44Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;---------------&lt;br /&gt;
Was für ein &amp;quot;Spezialist&amp;quot; hat denn den Erfahrungsbericht verbrochen?&lt;br /&gt;
&lt;br /&gt;
Der Optokoppler wird, wie man sieht, über einen Schalttransistor betrieben, somit ist das o.g. Argument der Überlastung des PCF-IC&#039;s nicht gegeben, da hier vom PCF-IC nur ein geringer Basisstrom benötigt wird.&lt;br /&gt;
&lt;br /&gt;
Bei einem Stromausfall (vermutlich sind hier die 5V gemeint) gibt es keinen High-Pegel mehr, wo soll der auch herkommen? Somit fliesst auch kein Basisstrom durch den Schalttransistor und der Verbraucher ist &amp;quot;tot&amp;quot;. Gemeint ist wohl der Zustand nach einem Stromausfall.&lt;br /&gt;
&lt;br /&gt;
Wie können Netzstörungen über einen Optokoppler durchschlagen? Vielleicht, wenn der Blitz einschlägt...&lt;br /&gt;
&lt;br /&gt;
-----------------&lt;br /&gt;
hi,&lt;br /&gt;
hab mal die diskussion in die diskussion verlegt&lt;br /&gt;
zu 1. der spezialist bin ich, wenn ihr den artikel nicht wollt dann löscht ihn bitte.&lt;br /&gt;
zu 2. es wird ein schalttransistor benötigt, es wäre allerdings einfacher wenn der pcf-ic genug spannung liefern würde um eine led zu betreiben.&lt;br /&gt;
zu 3. richtig, es war &amp;quot;Nach&amp;quot; gemeint, aber wenn du das so klug erkannt hast warum hast du es nicht geändert? &lt;br /&gt;
zu 4. wie gesagt, es ist ein &amp;quot;Erfahrungsbericht&amp;quot;. ich habe die schaltung so aufgebaut und es kommt mitunter vor, dass der pcf ic nach dem einschalten der 250v sicherung wieder alle ports auf high setzt. kommt wahrscheinlich durch irgendwelche induktiven effekte ... &lt;br /&gt;
&lt;br /&gt;
gruß&lt;br /&gt;
--[[Benutzer:Nollsen|Nollsen]] 12:49, 5. Feb 2005 (CET)&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=I2C-Schaltmodul&amp;diff=8028</id>
		<title>I2C-Schaltmodul</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=I2C-Schaltmodul&amp;diff=8028"/>
		<updated>2005-02-05T11:45:25Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: /* Erfahrungen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:I2C]]&lt;br /&gt;
=Einleitung=&lt;br /&gt;
Das Schaltmodul ist eine Applikation für den I2C Bus, um 8 220V Geräte zu steuern. Hauptbestandteil ist der IC [[PCF8574]]. Dieser IC wird direkt an den I2C Bus angeschlossen und besitzt 8 digitale Ein-/Ausgänge. Bei dem Schaltmodul steuert jeder Ausgang des ICs einen Optokoppler (MOC3040) an, welcher wiederum einen Thyristor (TIC206) schaltet. Eine kleine Zusatzschaltung (LED mit Vorwiderständen) zeigt noch den Status des Ausgangs optisch an. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Schaltplan=&lt;br /&gt;
[[bild:I2C-Schaltmodul.png]]&lt;br /&gt;
&lt;br /&gt;
=Erklärung=&lt;br /&gt;
Der obere Teil zeigt die Ansteuerung des PCFs8574 an. &lt;br /&gt;
Die untere Schaltung muss für jeden der 8 Ausgabepins gebaut werden. &lt;br /&gt;
Zunächst wird durch einen Optokoppler ein kleiner Triac ein und ausgeschaltet, der &lt;br /&gt;
über einen Vorwiderstand einen Leistungsstarken Triac steuert. &lt;br /&gt;
&lt;br /&gt;
=Erfahrungen=&lt;br /&gt;
Diese Schaltung stellt einen billigen Weg dar, 8 Geräte zu steuern. Allerdings hat diese Schaltung einige Nachteile: &lt;br /&gt;
* Der PCF-IC ist eventuell nicht in der Lage, genug Strom für 8 LEDs zu liefern. Eine Schaltstufe wäre empfehlenswert&lt;br /&gt;
* Netzstörungen können trotz des Optokopplers durchschlagen&lt;br /&gt;
* Nach einem Stromausfall liegen alle Ausgänge des PCFs auf HIGH, d.h. alle Geräte laufen bis der IC zum ersten Mal beschrieben wird.&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=I2C-Schaltmodul&amp;diff=5373</id>
		<title>I2C-Schaltmodul</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=I2C-Schaltmodul&amp;diff=5373"/>
		<updated>2005-02-05T11:42:57Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: diskussion in diskussion verschoben&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:I2C]]&lt;br /&gt;
=Einleitung=&lt;br /&gt;
Das Schaltmodul ist eine Applikation für den I2C Bus, um 8 220V Geräte zu steuern. Hauptbestandteil ist der IC [[PCF8574]]. Dieser IC wird direkt an den I2C Bus angeschlossen und besitzt 8 digitale Ein-/Ausgänge. Bei dem Schaltmodul steuert jeder Ausgang des ICs einen Optokoppler (MOC3040) an, welcher wiederum einen Thyristor (TIC206) schaltet. Eine kleine Zusatzschaltung (LED mit Vorwiderständen) zeigt noch den Status des Ausgangs optisch an. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Schaltplan=&lt;br /&gt;
[[bild:I2C-Schaltmodul.png]]&lt;br /&gt;
&lt;br /&gt;
=Erklärung=&lt;br /&gt;
Der obere Teil zeigt die Ansteuerung des PCFs8574 an. &lt;br /&gt;
Die untere Schaltung muss für jeden der 8 Ausgabepins gebaut werden. &lt;br /&gt;
Zunächst wird durch einen Optokoppler ein kleiner Triac ein und ausgeschaltet, der &lt;br /&gt;
über einen Vorwiderstand einen Leistungsstarken Triac steuert. &lt;br /&gt;
&lt;br /&gt;
=Erfahrungen=&lt;br /&gt;
Diese Schaltung stellt einen billigen Weg dar, 8 Geräte zu steuern. Allerdings hat diese Schaltung einige Nachteile: &lt;br /&gt;
* Der PCF-IC ist eventuell nicht in der Lage, genug Strom für 8 LEDs zu liefern. Eine Schaltstufe wäre empfehlenswert&lt;br /&gt;
* Netzstörungen können trotz des Optokopplers durchschlagen&lt;br /&gt;
* Bei einem Stromausfall liegen alle Ausgänge des PCFs auf HIGH, d.h. alle Geräte laufen bis der IC zum ersten Mal beschrieben wird.&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Hausbus&amp;diff=5167</id>
		<title>Hausbus</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Hausbus&amp;diff=5167"/>
		<updated>2005-01-07T20:05:18Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: /* Vergleich von Hausbussystemen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.mikrocontroller.net/forum/read-1-66019.html#136169 Forum ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Anforderungen=&lt;br /&gt;
==Zentral/Dezentral==&lt;br /&gt;
Grundsätzlich kann so eine Steuerung zentral oder dezentral arbeiten (wobei natürlich auch Mischformen denkbar sind). &lt;br /&gt;
===Zentral===&lt;br /&gt;
Beim zentralen Ansatz gibt es einen Master, der zyklisch alle Sensoren (Thermometer, Lichtschalter, usw.) abfrägt und dann die entsprechenden Aktionen auslöst.&lt;br /&gt;
  + wenig Intelligenz bei den Sensoren/Aktoren nötig&lt;br /&gt;
  + bei Konfigurationsänderungen keine Änderungen bei den Sensoren/Aktoren nötig. &lt;br /&gt;
  + keine Multimasterfähigkeit nötig&lt;br /&gt;
  - je mehr Sensoren vorhanden sind, desto länger dauert ein Abfragezyklus. &lt;br /&gt;
    Da so ein selbst gebauter Hausbus ja auch Raum für Erweiterungen bieten soll, &lt;br /&gt;
    sollte man schon mit 100-200 Sensoren rechnen (Lichtschalter, Thermometer, &lt;br /&gt;
    Glasbruchsensoren, Rauchmelder usw. usf)&lt;br /&gt;
  - Wenn die Zentrale ausfällt, dann fällt die gesamte Steuerung auf einmal aus&lt;br /&gt;
===Dezentral===&lt;br /&gt;
Beim dezentralen Ansatz senden die Sensoren (z.B. Lichtschalter) Botschaften an die Aktoren (z.B. die Glühlampe).&lt;br /&gt;
  + Die Buslast hängt von der Anzahl Ereignisse ab und nicht von der Anzahl Sensoren. &lt;br /&gt;
    Ein Glasbruchsensor der nie aktiv wird verursacht auch keine Buslast.&lt;br /&gt;
  + Keine Schaltzentrale nötig (also kein Single Point of Failure)&lt;br /&gt;
  - Multimasterfähigkeit bei allen Sendern (also allen Sensoren) nötig.&lt;br /&gt;
  - Konfigurationsänderungen müssen immer an den entsprechenden Aktoren/Sensoren gemacht &lt;br /&gt;
    werden. Dazu muß man sie entweder fernkonfigurieren können oder mit dem Konfigurationsgerät &lt;br /&gt;
    direkt an die jeweiligen Geräte.&lt;br /&gt;
&lt;br /&gt;
==Geschwindigkeit==&lt;br /&gt;
Solange man nur ein einzelnes Wohnhaus (und nicht etwa eine Schule oder eine Fabrik) ausrüsten will und nur die üblichen Sensoren/Aktoren hat, ist praktisch jeder Bus schnell genug. Andererseits erlauben RS485 und der CAN-Bus bei den in einem Haus vorkommenden Kabellängen auch durchaus Geschwindigkeiten von 1 MBit/s, wodurch man auch andere Anwendungen damit realisieren könnte.&lt;br /&gt;
&lt;br /&gt;
--&amp;gt; Hohe Geschwindigkeit heißt höherer Aufwand und höhere Kosten &amp;lt;---&lt;br /&gt;
Ein Hausbus sollte deshalb in der Geschwindigkeit auf die notwendigen Bedürfnisse abgestimmt sein. Folgende Rechnung läßt sich aufmachen:&lt;br /&gt;
Ein Frame mit einem einfachen Event z.B. &amp;quot;Taste 4 des Modul 0x2007 gedrueckt&amp;quot; läßt sich mit allem Nötigen wie Priorität, Parity-Bits Anzahl Datenbytes und Checksumme in 6 &amp;quot;Byte&amp;quot; a 10Bit verpacken. Bei einer Geschwindigkeit von nur 10 KHz dauert die Übertragung ca. 6 ms. Erlaubt man pro Frame max. 12 Datenbyte ergeben sich 18ms. Wobei 12 Datenbyte eigentlich nur zu Konfiguration der Knoten nötig sind. Uhrzeit, Datum Temperaturen usw. kann man meistens mit 2 - 4 Datenbyte melden. Da mit der CAN-Topologie kollisionsfrei die Daten übertragen werden und ein Hausbus im allgemeinen keiner hohen Belatung unterliegt, ist es realistisch sonstige Verzoegerungen zu vernachlässigen. Ich habe in meinem 5 Personenhaushalt den Bus nach &amp;quot;Bus-belegt-Verzögerungen&amp;quot; gescannt und in drei Monat vier dieser Ereignisse festgestellt. Das bedeutete 12 ms anstatt der erwähnten 6 ms. &lt;br /&gt;
Warum sollten man schneller werden, wenn eine Verzögerung von 200 ms in der Realität nicht fegestellt wird. Die Verzögerung einer Leuchtstofflampe empfinde ich da schon eher als störend.&lt;br /&gt;
Sollten wir eine Schule mit solch einem Bus betreiben und 166 Kinder stürmen in die Pause und betätigen dann alle einen Taster, verzögert sich das letzte Ereignis um nicht ganz eine Sekunde.&lt;br /&gt;
&lt;br /&gt;
=Vergleich von Hausbussystemen=&lt;br /&gt;
&lt;br /&gt;
EIB&lt;br /&gt;
  + nur 2 Leitungen für Daten, Power und GND&lt;br /&gt;
  + kein Abschluss-R nötig, alle Bustopologien&lt;br /&gt;
  + multimasterfähig&lt;br /&gt;
  - Chips nur schwer erhältlich und teuer&lt;br /&gt;
&lt;br /&gt;
CAN&lt;br /&gt;
  + Protokoll bereits im Chip&lt;br /&gt;
  + multimasterfähig&lt;br /&gt;
  + übertragunssicher (d.h. bei Übertragungsfehler werden Daten automatisch wiederholt)&lt;br /&gt;
  O Preis ist ausgewogen&lt;br /&gt;
  - es werden 2 Leitungen Daten + Power + GND benötigt&lt;br /&gt;
  - Abzweigungen vom Bus sind problematisch (max. 1m?)&lt;br /&gt;
  - Abschluss-R notwendig&lt;br /&gt;
&lt;br /&gt;
RS485&lt;br /&gt;
  + sehr günstig&lt;br /&gt;
  + Schnittstellenbausteine können direkt an den USART eines MCs angeschlossen werden&lt;br /&gt;
  - von Haus aus nicht multimasterfähig, muß per Software realisiert werden&lt;br /&gt;
&lt;br /&gt;
I2C&lt;br /&gt;
  + billig&lt;br /&gt;
  + multimasterfähig&lt;br /&gt;
  + viele direkt anschließbare Sensoren vorhanden&lt;br /&gt;
  - keine differentielle Übertragung, dadurch deutlich störanfälliger&lt;br /&gt;
  - ohne &amp;quot;größeren&amp;quot; Aufwand nur Kabellängen &amp;lt;10m möglich&lt;br /&gt;
&lt;br /&gt;
Ethernet&lt;br /&gt;
  + multimasterfähig&lt;br /&gt;
  + sehr schnell&lt;br /&gt;
  - beim heute üblichen TP-Kabel nur Sternstruktur möglich&lt;br /&gt;
  - aufwendig anzusteuern (hohen Hardware- und Softwareaufwand)&lt;br /&gt;
  - teuer&lt;br /&gt;
&lt;br /&gt;
=Links=&lt;br /&gt;
==CAN==&lt;br /&gt;
[[CAN als Hausbus]]&lt;br /&gt;
&lt;br /&gt;
==Ethernet==&lt;br /&gt;
[http://www.ifas.htwk-leipzig.de/easytoweb/php/download/Verwendung%20eines%208-bit%20Microcontrollers%20zur%20Ethernet%20Vernetzung%20in%20der%20Hausautomation.pdf  Diplomarbeit]&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=I2C-Schaltmodul&amp;diff=5161</id>
		<title>I2C-Schaltmodul</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=I2C-Schaltmodul&amp;diff=5161"/>
		<updated>2005-01-07T19:56:34Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Einleitung=&lt;br /&gt;
Das Schaltmodul ist eine Applikation für den I2C Bus, um 8 220V Geräte zu steuern. Hauptbestandteil ist der IC [[PCF8574]]. Dieser IC wird direkt an den I2C Bus angeschlossen und besitzt 8 digitale Ein-/Ausgänge. Bei dem Schaltmodul steuert jeder Ausgang des ICs einen Optokoppler (MOC3040) an, welcher wiederum einen Thyristor (TIC206) schaltet. Eine kleine Zusatzschaltung (LED mit Vorwiderständen) zeigt noch den Status des Ausgangs optisch an. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Schaltplan=&lt;br /&gt;
[[bild:I2C-Schaltmodul.png]]&lt;br /&gt;
&lt;br /&gt;
=Erklärung=&lt;br /&gt;
Der obere Teil zeigt die Ansteuerung des PCFs8574 an. &lt;br /&gt;
Die untere Schaltung muss für jeden der 8 Ausgabepins gebaut werden. &lt;br /&gt;
Zunächst wird durch einen Optokoppler ein kleiner Triac ein und ausgeschaltet, der &lt;br /&gt;
über einen Vorwiderstand einen Leistungsstarken Triac steuert. &lt;br /&gt;
&lt;br /&gt;
=Erfahrungen=&lt;br /&gt;
Diese Schaltung stellt einen billigen Weg dar, 8 Geräte zu steuern. Allerdings hat diese Schaltung einige Nachteile: &lt;br /&gt;
* Der PCF-IC ist eventuell nicht in der Lage, genug Strom für 8 LEDs zu liefern. Eine Schaltstufe wäre empfehlenswert&lt;br /&gt;
* Netzstörungen können trotz des Optokopplers durchschlagen&lt;br /&gt;
* Bei einem Stromausfall liegen alle Ausgänge des PCFs auf HIGH, d.h. alle Geräte laufen bis der IC zum ersten Mal beschrieben wird.&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Datei:I2C-Schaltmodul.png&amp;diff=14523</id>
		<title>Datei:I2C-Schaltmodul.png</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Datei:I2C-Schaltmodul.png&amp;diff=14523"/>
		<updated>2005-01-07T19:50:10Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: Schaltplan des I2C Schaltmoduls&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Schaltplan des I2C Schaltmoduls&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=I2C_als_Hausbus&amp;diff=5166</id>
		<title>I2C als Hausbus</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=I2C_als_Hausbus&amp;diff=5166"/>
		<updated>2005-01-07T19:45:00Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Category:Projekte]]&lt;br /&gt;
[[Category:avr]]&lt;br /&gt;
[[Category:I2C]]&lt;br /&gt;
&lt;br /&gt;
=Infos=&lt;br /&gt;
&lt;br /&gt;
Infos allgemein zu [[Hausbus]] [[I2C]].&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Verkabelung=&lt;br /&gt;
&lt;br /&gt;
=offizielle Spezifikationen=&lt;br /&gt;
Die beiden Leitungen dürfen eine maximale Kapazität von 400pF nicht übersteigen. Dies sind in der praxis einige Meter. &lt;br /&gt;
&lt;br /&gt;
=eigene Erfahrungen=&lt;br /&gt;
Wenn die Busgeschwindigkeit angepasst wird, sind große Strecken und umfangreiche Verzweigungen möglich. &lt;br /&gt;
Ein 30 Meter Bus funktioniert zum Beispiel noch mit rund 20kHz fast ohne Probleme.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=passende Sensoren / Module=&lt;br /&gt;
* Temperatursensor mit dem [[DS1621]]&lt;br /&gt;
* [[I2C-Schaltmodul]] mit dem [[PCF8574]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Links=&lt;br /&gt;
http://www.semiconductors.philips.com/markets/mms/protocols/i2c/&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Hausbus&amp;diff=5159</id>
		<title>Hausbus</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Hausbus&amp;diff=5159"/>
		<updated>2005-01-07T19:35:55Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: /* Vergleich von Hausbussystemen */  eintrag zu I2C hinzugefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://www.mikrocontroller.net/forum/read-1-66019.html#136169 Forum ]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Anforderungen=&lt;br /&gt;
==Zentral/Dezentral==&lt;br /&gt;
Grundsätzlich kann so eine Steuerung zentral oder dezentral arbeiten (wobei natürlich auch Mischformen denkbar sind). &lt;br /&gt;
===Zentral===&lt;br /&gt;
Beim zentralen Ansatz gibt es einen Master, der zyklisch alle Sensoren (Thermometer, Lichtschalter, usw.) abfrägt und dann die entsprechenden Aktionen auslöst.&lt;br /&gt;
  + wenig Intelligenz bei den Sensoren/Aktoren nötig&lt;br /&gt;
  + bei Konfigurationsänderungen keine Änderungen bei den Sensoren/Aktoren nötig. &lt;br /&gt;
  + keine Multimasterfähigkeit nötig&lt;br /&gt;
  - je mehr Sensoren vorhanden sind, desto länger dauert ein Abfragezyklus. &lt;br /&gt;
    Da so ein selbst gebauter Hausbus ja auch Raum für Erweiterungen bieten soll, &lt;br /&gt;
    sollte man schon mit 100-200 Sensoren rechnen (Lichtschalter, Thermometer, &lt;br /&gt;
    Glasbruchsensoren, Rauchmelder usw. usf)&lt;br /&gt;
  - Wenn die Zentrale ausfällt, dann fällt die gesamte Steuerung auf einmal aus&lt;br /&gt;
===Dezentral===&lt;br /&gt;
Beim dezentralen Ansatz senden die Sensoren (z.B. Lichtschalter) Botschaften an die Aktoren (z.B. die Glühlampe).&lt;br /&gt;
  + Die Buslast hängt von der Anzahl Ereignisse ab und nicht von der Anzahl Sensoren. &lt;br /&gt;
    Ein Glasbruchsensor der nie aktiv wird verursacht auch keine Buslast.&lt;br /&gt;
  + Keine Schaltzentrale nötig (also kein Single Point of Failure)&lt;br /&gt;
  - Multimasterfähigkeit bei allen Sendern (also allen Sensoren) nötig.&lt;br /&gt;
  - Konfigurationsänderungen müssen immer an den entsprechenden Aktoren/Sensoren gemacht &lt;br /&gt;
    werden. Dazu muß man sie entweder fernkonfigurieren können oder mit dem Konfigurationsgerät &lt;br /&gt;
    direkt an die jeweiligen Geräte.&lt;br /&gt;
&lt;br /&gt;
==Geschwindigkeit==&lt;br /&gt;
Solange man nur ein einzelnes Wohnhaus (und nicht etwa eine Schule oder eine Fabrik) ausrüsten will und nur die üblichen Sensoren/Aktoren hat, ist praktisch jeder Bus schnell genug. Andererseits erlauben RS485 und der CAN-Bus bei den in einem Haus vorkommenden Kabellängen auch durchaus Geschwindigkeiten von 1 MBit/s, wodurch man auch andere Anwendungen damit realisieren könnte.&lt;br /&gt;
&lt;br /&gt;
--&amp;gt; Hohe Geschwindigkeit heißt höherer Aufwand und höhere Kosten &amp;lt;---&lt;br /&gt;
Ein Hausbus sollte deshalb in der Geschwindigkeit auf die notwendigen Bedürfnisse abgestimmt sein. Folgende Rechnung läßt sich aufmachen:&lt;br /&gt;
Ein Frame mit einem einfachen Event z.B. &amp;quot;Taste 4 des Modul 0x2007 gedrueckt&amp;quot; läßt sich mit allem Nötigen wie Priorität, Parity-Bits Anzahl Datenbytes und Checksumme in 6 &amp;quot;Byte&amp;quot; a 10Bit verpacken. Bei einer Geschwindigkeit von nur 10 KHz dauert die Übertragung ca. 6 ms. Erlaubt man pro Frame max. 12 Datenbyte ergeben sich 18ms. Wobei 12 Datenbyte eigentlich nur zu Konfiguration der Knoten nötig sind. Uhrzeit, Datum Temperaturen usw. kann man meistens mit 2 - 4 Datenbyte melden. Da mit der CAN-Topologie kollisionsfrei die Daten übertragen werden und ein Hausbus im allgemeinen keiner hohen Belatung unterliegt, ist es realistisch sonstige Verzoegerungen zu vernachlässigen. Ich habe in meinem 5 Personenhaushalt den Bus nach &amp;quot;Bus-belegt-Verzögerungen&amp;quot; gescannt und in drei Monat vier dieser Ereignisse festgestellt. Das bedeutete 12 ms anstatt der erwähnten 6 ms. &lt;br /&gt;
Warum sollten man schneller werden, wenn eine Verzögerung von 200 ms in der Realität nicht fegestellt wird. Die Verzögerung einer Leuchtstofflampe empfinde ich da schon eher als störend.&lt;br /&gt;
Sollten wir eine Schule mit solch einem Bus betreiben und 166 Kinder stürmen in die Pause und betätigen dann alle einen Taster, verzögert sich das letzte Ereignis um nicht ganz eine Sekunde.&lt;br /&gt;
&lt;br /&gt;
=Vergleich von Hausbussystemen=&lt;br /&gt;
&lt;br /&gt;
EIB&lt;br /&gt;
  + nur 2 Leitungen für Daten, Power und GND&lt;br /&gt;
  + kein Abschluss-R nötig, alle Bustopologien&lt;br /&gt;
  + multimasterfähig&lt;br /&gt;
  - Chips nur schwer erhältlich und teuer&lt;br /&gt;
&lt;br /&gt;
CAN&lt;br /&gt;
  + Protokoll bereits im Chip&lt;br /&gt;
  + multimasterfähig&lt;br /&gt;
  + übertragunssicher (d.h. bei Übertragungsfehler werden Daten automatisch wiederholt)&lt;br /&gt;
  O Preis ist ausgewogen&lt;br /&gt;
  - es werden 2 Leitungen Daten + Power + GND benötigt&lt;br /&gt;
  - Abzweigungen vom Bus sind problematisch (max. 1m?)&lt;br /&gt;
  - Abschluss-R notwendig&lt;br /&gt;
&lt;br /&gt;
RS485&lt;br /&gt;
  + sehr günstig&lt;br /&gt;
  + Schnittstellenbausteine können direkt an den USART eines MCs angeschlossen werden&lt;br /&gt;
  - von Haus aus nicht multimasterfähig, muß per Software realisiert werden&lt;br /&gt;
&lt;br /&gt;
I2C&lt;br /&gt;
  + billig&lt;br /&gt;
  + multimasterfähig&lt;br /&gt;
  - keine differentielle Übertragung, dadurch deutlich störanfälliger&lt;br /&gt;
  - ohne &amp;quot;größeren&amp;quot; Aufwand nur Kabellängen &amp;lt;10m möglich&lt;br /&gt;
  - viele direkt anschließbare Sensoren vorhanden&lt;br /&gt;
&lt;br /&gt;
Ethernet&lt;br /&gt;
  + multimasterfähig&lt;br /&gt;
  + sehr schnell&lt;br /&gt;
  - beim heute üblichen TP-Kabel nur Sternstruktur möglich&lt;br /&gt;
  - aufwendig anzusteuern (hohen Hardware- und Softwareaufwand)&lt;br /&gt;
  - teuer&lt;br /&gt;
&lt;br /&gt;
=Links=&lt;br /&gt;
==CAN==&lt;br /&gt;
[[CAN als Hausbus]]&lt;br /&gt;
&lt;br /&gt;
==Ethernet==&lt;br /&gt;
[http://www.ifas.htwk-leipzig.de/easytoweb/php/download/Verwendung%20eines%208-bit%20Microcontrollers%20zur%20Ethernet%20Vernetzung%20in%20der%20Hausautomation.pdf  Diplomarbeit]&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=I%C2%B2C&amp;diff=5160</id>
		<title>I²C</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=I%C2%B2C&amp;diff=5160"/>
		<updated>2005-01-07T19:32:26Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: /* Bausteine */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;I2C&#039;&#039;&#039; ist ein synchroner serieller Zweidraht-[[Bus]] (eine Daten- und eine Taktleitung), der für die Kommunikation zwischen [[IC]]s über kleine Distanzen geeignet ist. Entwickelt wurde er Anfang der 80er Jahre von Philips.&lt;br /&gt;
Gesprochen &amp;quot;I quadrat C&amp;quot; steht für IIC = Inter [[IC]] Bus. Aus Lizenzgünden heißt der I²C Bus bei manchen Herstellern auch &#039;&#039;&#039;TWI&#039;&#039;&#039;, two wire interface.&lt;br /&gt;
&lt;br /&gt;
In einem I2C-Bus gibt es mindestens einen Master und eine beliebige Anzahl Slaves (max. 128). Ein I2C-Bus mit mehreren Mastern wird als &amp;quot;Multi-Master-Bus&amp;quot; bezeichnet.&lt;br /&gt;
Der (oder die) Master sprechen die Slaves an; ein Slave kann NIE selbstständig Daten senden. Dazu übernimmt der Master, der Daten senden oder empfangen möchte, den Bus und gibt die (7-bit- bzw. 10-bit-)Adresse des Slaves aus, mit dem er kommunizieren möchte. Nach der Adresse teilt der Master dem entsprechenden Slave mit, ob er Daten senden oder empfangen möchte. Danach werden die eigentlichen Daten (entweder vom Master oder Slave) auf den Bus gelegt. Hat der Master den Lese- oder Schreibvorgang abgeschlossen, so gibt er den Bus wieder frei.&lt;br /&gt;
Sofern mehrere Master vorhanden sind, stellt ein Protokoll sicher, dass sich diese nicht gegenseitig stören.&lt;br /&gt;
&lt;br /&gt;
Die Übertragungsrate beträgt beim Standard mode bis zu 100 kbit/s, beim Fast mode bis zu 400 kbit/s und beim High-speed mode bis zu 3,4 MBit/s. Falls die Taktrate für einen Slave zu hoch ist, kann er die Clock-Leitung auf Null ziehen und die Übertragung damit verlangsamen. Dies ist auf Bit- wie auf Byte-Ebene möglich, Ersteres allerdings nicht im High-speed mode.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Bausteine ==&lt;br /&gt;
&lt;br /&gt;
Neben Mikrocontrollern gibt es eine Reihe von Peripheriebausteinen, die per I2C angeschlossen werden können. Eine gute Anlaufstelle bei der Suche ist die unten angegebene Seite des &amp;quot;Erfinders&amp;quot; Philips.&lt;br /&gt;
&lt;br /&gt;
* serielle [[EEPROM]]s (24Cxx)&lt;br /&gt;
* I/O-Portexpander&lt;br /&gt;
** [[PCF8574]]&lt;br /&gt;
* [[AD-Wandler]]&lt;br /&gt;
* Uhrenbausteine&lt;br /&gt;
* [[LCD]]-Treiber&lt;br /&gt;
* Temperatursensoren&lt;br /&gt;
** [[DS1621]], [[LM75]]&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.semiconductors.philips.com/buses/i2c/ Philips Produktseite]&lt;br /&gt;
* [http://www.the-starbearer.de/Roboterelektronik/i%B2c/I2C_Index.htm I2C Kommunikation]&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Diskussion:CAN_als_Hausbus&amp;diff=14521</id>
		<title>Diskussion:CAN als Hausbus</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Diskussion:CAN_als_Hausbus&amp;diff=14521"/>
		<updated>2005-01-07T19:21:46Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;hi,&lt;br /&gt;
vielleicht wäre es nicht schlecht wenn man den relevanten teil vom forum hierherein kopieren würde&lt;br /&gt;
--[[Benutzer:Nollsen|Nollsen]] 20:21, 7. Jan 2005 (CET)&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Diskussion:Snippets&amp;diff=4309</id>
		<title>Diskussion:Snippets</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Diskussion:Snippets&amp;diff=4309"/>
		<updated>2004-09-26T08:22:29Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Zum ADC-Code:&lt;br /&gt;
* Unter welchen Bedingungen anwendbar? (// Kommentar?)&lt;br /&gt;
* ADC-Wandler immer wieder von neuem &amp;quot;einschalten&amp;quot;? Trennung ADC_init(), ADC_read(channel) oder verglb. duerfte in Snippetsammlung besser sein&lt;br /&gt;
* Welcher ADC-Modus? Welche Wandlerfrequenz? Prescaler? Evtl. Prescaler-&amp;quot;Rechen&amp;quot;-Macro oder #defines(// Kommentar?)&lt;br /&gt;
* &#039;&#039;&#039;Kommentare fehlen&#039;&#039;&#039;. Bei einem &amp;quot;ueberall reinkopier-Snippet&amp;quot; eigentlich obligatorisch (ist ja keine Libray mit entspr. Dokumentation).&lt;br /&gt;
* Portabilitaet zw. AVRs?&lt;br /&gt;
* uint32_t in einem Snippet zum &amp;quot;schnell mal reinkopieren&amp;quot;? bei 10-bit Wandlern? Die Variable &amp;quot;schnell mal zwischendurch&amp;quot; zu deklarieren ist wenn recht erinnert auch kein &amp;quot;Standard-C&amp;quot;&lt;br /&gt;
Nichts fuer Ungut und es ist ja nur eine Einzelmeinung: Code erstmal wieder von der Seite löschen und nochmal überarbeiten. Keine Ahnung wieviel Leute die Schnippsel nutzen, aber mit dem jetzigen Stand ist das eher ein &amp;quot;friss oder stirb&amp;quot;, das auch &amp;quot;meistens&amp;quot; halbwegs funktioniert.  Ein &amp;quot;funktioniert bei mir&amp;quot; ohne Erläuterung was das &amp;quot;bei mir&amp;quot; ist, macht noch keinen &amp;quot;guten&amp;quot; Quellcodeschnippsel. Wie waere es mit einem Artikel &amp;quot;AVR-Tutorial: ADC in C&amp;quot; vergleichbar mit dem UART-Teil im avr-Tutorial von dl8dt? Darin koennte man vergleichbaren Code nach ein paar Erläuterungen einfügen. Dann könnte der entspr. Abschnitt im gcc-Tutorial stark gekuerzt werden und auf diesen neuen Artikel verwiesen werden und die &amp;quot;Schnippselsammlungsseite&amp;quot; verweist dann ebenfalls darauf. MfG M. Thomas&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ich halte nicht viel von einer allgemeinen &amp;quot;Snippets&amp;quot;-Seite. Welchen praktischen Nutzen soll das haben? Man geht üblicherweise nicht auf die Suche nach &#039;&#039;irgend einem&#039;&#039; Snippet, sondern man braucht Informationen für eine bestimmte Anwendung und einen bestimmten Controller. Deshalb denke ich dass jeweils eine Seite zu AD-Wandlung mit AVR, LCD-Ansteuerung usw. viel mehr Sinn macht.&lt;br /&gt;
--[[Benutzer:Andreas|Andreas]] 09:09, 23. Sep 2004 (CEST)&lt;br /&gt;
&lt;br /&gt;
hi!&lt;br /&gt;
&lt;br /&gt;
zum quelltext:&lt;br /&gt;
selbstverständlich sind die beiden snippets verbesserungswürdig, aber dafür ist ja auch ein wiki da; wenn ich zeit hab verbessere ich die quelltexte.&lt;br /&gt;
&lt;br /&gt;
@andreas:&lt;br /&gt;
&lt;br /&gt;
ich sehe in einer snippetsammlung den vorteil, die sachen schnell zu finden die man regelmäßig braucht und sich nicht immer im kopf behalten kann.&lt;br /&gt;
daher sollte die snippetsammlung auch eventuell quelltextteile von anderen artikeln enthalten.&lt;br /&gt;
&lt;br /&gt;
-- &lt;br /&gt;
&lt;br /&gt;
Halbgaren Code reinschreiben der dann irgendwann mal von irgendjemand (mit &amp;quot;Zeit&amp;quot;) verbessern/korrigieren wird? Diejenigen, die den Code - wie beabsichtigt - jetzt als Snippet nutzen weil&#039;s gar so praktisch ist erstmal Kommentar-los und kommentarlos &amp;quot;machen&amp;quot; lassen. Super Ansatz! Schoen vereinfachte Ausfuehrung zu &amp;quot;Mosfets&amp;quot;. Logic-Level oder nicht?, &amp;quot;Lampe o.ae.?&amp;quot;, N-Channel P-Channel? etwas Strombegrenzung am Gate? evtl. auch Frequenzen und Verluste?. Wenn irgend jemand die jetzige Information einfach auf irgendwelche Fets anwendet, die grad&#039; vom Laster gefallen sind? Egal, vielleicht hat er/sie Glueck. Super Ansatz! Mein Verstandis von diesem Wikki war bisher, dass man Informationen knapp aber vollstaendig und richtig einbringt. Irgendwie hatte ich gehofft, der Ursprungsautor wuerde seine Beitraege erstmal zurueckziehen und spaeter erweitert/korrigiert wieder reinschieben. So What, fuer die paar Leute, die sich in das Wikki hier verirren, wohl zu viel Aufwand. mth&lt;br /&gt;
&lt;br /&gt;
hi,&lt;br /&gt;
&lt;br /&gt;
wenn dir den teil von den mosfets nicht gefällt, schreibe doch einen eigenen großen artikel über MOSFETs wenn du so viel drüber weißt. um einfache Schaltungen zu realisieren reicht das allerdings vollständig aus (eine Pinbelegung wäre eventuell noch möglich). ich hab damals für die AD conversation trotz avrgcc tutorial und datenblatt ziemlich lange gebraucht, um die betroffenen register und flags zu bekommen. gestern wollte ich einen pwm ausgang nutzen, aber weder das gcc tutorial noch das datenblatt haben richtig darüber informationen gegeben. durch versuch + irrtum hab ich dann einen fehler gefunden, so dass es dann halbwegs funktionierte.&lt;br /&gt;
--[[Benutzer:Nollsen|Nollsen]] 10:22, 26. Sep 2004 (CEST)&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR-GCC-Tutorial&amp;diff=4317</id>
		<title>AVR-GCC-Tutorial</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR-GCC-Tutorial&amp;diff=4317"/>
		<updated>2004-09-25T21:08:27Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: /* Die Register des ADC */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Programmierung der AVR-Mikrocontroller mit C =&lt;br /&gt;
&lt;br /&gt;
Dieses Tutorial soll dem Einsteiger helfen, mit der Programmiersprache &#039;&#039;&#039;C&#039;&#039;&#039;&lt;br /&gt;
die Mikrocontroller der Atmel AVR-Reihe zu programmieren.&amp;lt;br /&amp;gt;&lt;br /&gt;
Es gibt einige Gründe, weshalb eine höhere Programmiersprache der reinen&lt;br /&gt;
Assembler-Programmierung vorgezogen werden kann. So kann mit &#039;&#039;&#039;C&#039;&#039;&#039; das&lt;br /&gt;
Programm wesentlich lesbarer geschrieben werden als in Assembler.&amp;lt;br /&amp;gt;&lt;br /&gt;
Es soll allerdings auch nicht verheimlicht werden, dass in Assembler in der&lt;br /&gt;
Regel schnellerer Programmcode entwickelt werden kann als mit &#039;&#039;&#039;C&#039;&#039;&#039;. Meiner&lt;br /&gt;
Meinung nach jedoch können wir 99 Prozent aller Aufgaben problemlos mit &#039;&#039;&#039;C&#039;&#039;&#039;&lt;br /&gt;
meistern und für die ganz krassen Fälle kann sogar Assembler-Code direkt in&lt;br /&gt;
ein &#039;&#039;&#039;C&#039;&#039;&#039;-Programm eingebunden werden.&lt;br /&gt;
&lt;br /&gt;
Der Autor hat sich alle Mühe gegeben, sein Wissen hier fehlerfrei wiederzugeben. Fehler können jedoch nicht ausgeschlossen werden.&amp;lt;br /&amp;gt;&lt;br /&gt;
Fehlermeldungen bitte an christian.schifferle@bluewin.ch&lt;br /&gt;
&lt;br /&gt;
Der Autor übernimmt keinerlei Haftung für etwaige Schäden wie&lt;br /&gt;
z.B. durchgeknallte Sicherungen,&lt;br /&gt;
welche durch die Verwendung dieses Dokuments entstehen könnten.&lt;br /&gt;
&lt;br /&gt;
Die deutschen Leser mögen mir verzeihen, dass ich, wie es in&lt;br /&gt;
der Schweiz üblich ist, kein scharfes &amp;amp;szlig; verwendet habe.&lt;br /&gt;
&lt;br /&gt;
Die vorliegende Dokumentation ist und bleibt geistiges Machwerk&lt;br /&gt;
von Christian Schifferle und darf nicht als Eigenproduktion angepriesen werden.&lt;br /&gt;
&lt;br /&gt;
Das Dokument darf nach Belieben an Dritte weiter gegeben werden,&lt;br /&gt;
sofern der Copyright-Hinweis auf den Autor nicht verändert oder gelöscht wird.&lt;br /&gt;
&lt;br /&gt;
Der Autor, nämlich ich, das ist:&lt;br /&gt;
&lt;br /&gt;
Christian Schifferle&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Risweg 7&amp;lt;br /&amp;gt;&lt;br /&gt;
CH-4624 Härkingen&amp;lt;br /&amp;gt;&lt;br /&gt;
E-Mail: [mailto:christian.schifferle@bluewin.ch christian.schifferle@bluewin.ch]&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| style=&amp;quot;border-style: solid; border-color: #FF0000&amp;quot; bgcolor=&amp;quot;#FFFF00&amp;quot; | &amp;lt;font color=&amp;quot;#FF0000&amp;quot;&amp;gt;Achtung:&amp;lt;/font&amp;gt;&lt;br /&gt;
| style=&amp;quot;border-style: solid; border-color: #FF0000&amp;quot; bgcolor=&amp;quot;#FFFF00&amp;quot; | Der gesamte Kurs als ZIP-Datei kann&lt;br /&gt;
[http://www.mypage.bluewin.ch/ch_schifferle/Atmel.zip hier]&lt;br /&gt;
&lt;br /&gt;
herunter geladen werden.&amp;lt;br /&amp;gt;&lt;br /&gt;
Die ZIP-Datei muss dann auf dem eigenen Rechner in ein beliebiges&lt;br /&gt;
Verzeichnis entpackt werden. Die Startdatei heisst dann Index.htm.&lt;br /&gt;
&lt;br /&gt;
Für diejenigen, welche neu in die Programmiersprache C einsteigen,&lt;br /&gt;
empfiehlt es sich, zuvor die ebenfalls [http://www.mypage.bluewin.ch/ch_schifferle/C-Kurs.zip hier]&lt;br /&gt;
erhältliche Einführung in die Programmiersprache C durchzuarbeiten.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
= Aktualisierung =&lt;br /&gt;
&lt;br /&gt;
Viele der im Original-Dokument von C. Schifferle verwendeten Funktionen sind in &lt;br /&gt;
aktuellen Versionen des avr-gcc C-Compilers und der avr-libc zwar noch enthalten, &lt;br /&gt;
aber als deprecated ausgewiesen. D.h. diese Funktionen sollten nicht mehr verwendet &lt;br /&gt;
werden und existieren in zukünftigen Versionen des Compilers/der Library nicht mehr&lt;br /&gt;
(z.B. sbi(), cbi(), outp(), inp()). Der Artikel wurde auf die neuen Funktionen/Methoden &lt;br /&gt;
angepasst und stimmt somit nicht mehr mit den Informationen im zip-Achiv überein.&lt;br /&gt;
Einige Textpassagen entsprechen nicht mehr dem Originaldokument, einige Codebeispiele wurden hinzugefügt oder erweitert, der Abschnitt &amp;quot;Speicher&amp;quot; ist neu.&lt;br /&gt;
&lt;br /&gt;
In diesem Text wird häufig auf die Standardbibliothek für den avr-gcc-Compiler, die avr-libc, verwiesen. Die &#039;&#039;&#039;Dokumentation der avr-libc&#039;&#039;&#039; findet sich &lt;br /&gt;
[http://www.nongnu.org/avr-libc/user-manual/index.html hier]. Bei WinAVR gehört diese Dokumentation zum Lieferumfang und wird mitinstalliert. &lt;br /&gt;
&lt;br /&gt;
(M. Thomas Sept./04)&lt;br /&gt;
&lt;br /&gt;
= Benötigte Werkzeuge =&lt;br /&gt;
&lt;br /&gt;
Um die Übungen in diesem Tutorial nachvollziehen zu können benötigen wir folgende Hard- und Software:&lt;br /&gt;
&lt;br /&gt;
* Testboard für die Aufnahme eines AVR Controllers Ihrer Wahl. Dieses Testboard kann durchaus auch selber zusammen gelötet werden. So arbeite ich mit einem Testboard, welches ich mir auf einer Veroboard-Platine zusammen gestellt habe. Für die Versuche bzw. Übungen in diesem Tutorial habe ich jeweils einen AT90S2313 verwendet. &amp;lt;!-- veraltet: Dieser Controller weist meiner Meinung nach das beste Preis-/Leistungsverhältnis auf. --&amp;gt;&lt;br /&gt;
* AVRGCC-Compiler&amp;lt;br /&amp;gt; Ich beschränke mich hier auf den GCC Compiler, weil ich diesen selber verwende und weil er kostenlos zu haben und weit verbreitet ist. Siehe auch: [[AVR-GCC]]&lt;br /&gt;
* Programmiersoftware und Hardware z.B. PonyProg (siehe auch: [[Pony-Prog Tutorial]]) oder [[AVRDUDE]] mit [[STK200]]-Dongle oder die von Atmel verfügbare Hard- und Software ([[STK500]], [[AVR-Studio]]). &lt;br /&gt;
&amp;lt;!--, und natürlich ein passendes Kabel, um die Programme auf den Atmel übertragen zu können.--&amp;gt;&lt;br /&gt;
* Wenn man debuggen will eventuell [[AVR-Studio]]&lt;br /&gt;
&lt;br /&gt;
= Was tun, wenn&#039;s nicht &amp;quot;klappt&amp;quot;? =&lt;br /&gt;
&lt;br /&gt;
* Herausfinden, ob es tatsächlich ein avr(-gcc) spezifisches Problem ist oder die C-Kenntnisse einer Auffrischung bedürfen. Allgemeine C-Fragen kann man eventuell &amp;quot;beim freundlichen Programmierer zwei Büro-, Zimmer- oder Haustüren weiter&amp;quot; loswerden. Ansonsten: [[C]]-Buch (gibt&#039;s auch &amp;quot;gratis&amp;quot; online) lesen.&lt;br /&gt;
* Die [http://www.nongnu.org/avr-libc/user-manual/index.html Dokumentation der avr-libc] lesen, vor allem (aber nicht nur) den Abschnitt Related Pages/Frequently Asked Questions = Oft gestellte Fragen (und Antworten dazu). Z.Zt leider nur in englischer Sprache verfügbar.&lt;br /&gt;
* Den Artikel [[AVR-GCC]] in diesem Wiki lesen.&lt;br /&gt;
* Das gcc-Forum auf [http://www.mikrocontroller.net www.mikrocontroller.net] nach vergleichbaren Problemen absuchen.&lt;br /&gt;
* Das avr-gcc-Forum bei [http://www.avrfreaks.net avrfreaks] nach vergleichbaren Problemen absuchen.&lt;br /&gt;
* Das [http://www.avr1.org/pipermail/avr-gcc-list/ Archiv der avr-gcc Mailing-Liste] nach vergleichbaren Problemen absuchen.&lt;br /&gt;
* Nach Beispielcode suchen. Vor allem in der Academy von [http://www.avrfreaks.net AVRFREAKS] (anmelden).&lt;br /&gt;
* Google oder alltheweb befragen schadet nie.&lt;br /&gt;
* Bei Problemen mit der Ansteuerung interner AVR-Funktionen mit C-Code: das Datenblatt des Controllers lesen (ganz und am Besten zweimal)&lt;br /&gt;
* einen Beitrag in eines der Foren oder eine Mail an die Mailing-Liste schreiben. Dabei mgl. viel Information geben: Controller, Compilerversion, genutzte Bibliotheken, Ausschnitte aus dem Quellcode, genaue Fehlermeldungen bzw. Beschreibung des Fehlverhaltens. Bei Ansteuerung externer Geräte die Beschaltung beschreiben oder skizzieren (z.B. mit [http://www.tech-chat.de/ Andys ASCII Circuit]). Siehe dazu auch: [http://www.lugbz.org/documents/smart-questions_de.html &amp;quot;Wie man Fragen stellt&amp;quot;].&lt;br /&gt;
&lt;br /&gt;
= Exkurs: makefiles =&lt;br /&gt;
&lt;br /&gt;
Wenn man bisher gewohnt ist, mit integrierten Entwicklungsumgebung à la Visual-C Programme zu erstellen, wirkt das makefile-Konzept auf den ersten Blick etwas kryptisch. Nach kurzer Einarbeitung ist diese Vorgehensweise jedoch sehr praktisch. Diese Dateien (üblicher Name: &#039;makefile&#039; ohne Dateiendung) dienen der Ablaufsteuerung des Programms make, das auf allen Unix/Linux-Systemen installiert sein sollte, und in einer Fassung fuer MS-Windows auch in [[WinAVR]] (Unterverzeichnis utils/bin) enthalten ist.&lt;br /&gt;
&lt;br /&gt;
Im Unterverzeichnis &#039;&#039;sample&#039;&#039; einer WinAVR-Installation findet man eine sehr brauchbare Vorlage, die sich einfach an das eigene Projekt anpassen lässt ([[Media:Makefile|lokale Kopie Stand Sept. 2004]]). Wahlweise kann man auch [http://www.sax.de/~joerg/mfile/ mfile] von Jörg Wunsch nutzen. mfile erzeugt ein makefile nach Einstellungen in einer grafischen Nutzeroberfläche, wird bei WinAVR mitinstalliert, ist aber als TCL/TK-Programm auf nahezu allen Platformen lauffähig.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Die folgenden Ausführungen beziehen sich auf das WinAVR Beispiel-Makefile.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Ist im Makefile alles richtig eingestellt genügt es, sich drei Parameter zu merken, die über die shell bzw. die Windows-Kommandozeile (cmd.exe/command.exe) als Parameter an &amp;quot;make&amp;quot; übergeben werden. Das Programm make sucht sich &amp;quot;automatisch&amp;quot; das makefile im aktuellen Arbeitsverzeichnis und führt die darin definierten Operationen für den entsprechenden Aufrufparameter durch.&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
| &#039;&#039;make all&#039;&#039;&lt;br /&gt;
| Erstellt aus den in im makefile angegebenen Quellcodes eine &#039;&#039;hex&#039;&#039;-Datei (und ggf. auch &#039;&#039;eep&#039;&#039;-Datei).&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;make program&#039;&#039;&lt;br /&gt;
| Überträgt die hex-Datei (und wahlweise auch die eep-Datei für den EEPROM) zum AVR. &lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;make clean&#039;&#039;&lt;br /&gt;
| löscht alle temporären Dateien, also auch die hex-Datei&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Diese Aufrufe können in die allermeisten Editoren in &amp;quot;Tool-Menüs&amp;quot; eingebunden werden. Dies erspart den Kontakt mit der Kommandozeile. (Bei WinAVR sind die Einträge schon im Tools-Menü des mitgelieferten Editors Programmers-Notepad eingetragen.)&lt;br /&gt;
&lt;br /&gt;
Üblicherweise sind folgende Daten im makefile anzupassen:&lt;br /&gt;
* Controllertyp&lt;br /&gt;
* Quellcode-Dateien (c-Dateien)&lt;br /&gt;
* Typ und Anschluss des Programmiergeräts&lt;br /&gt;
&lt;br /&gt;
Die in den folgenden Unterabschnitten gezeigten makefile-Auschnitte sind für ein Programm, das auf einem ATmega8 ausgeführt werden soll. Der Quellcode besteht aus den c-Dateien superprog.c (darin main()), uart.c, lcd.c und 1wire.c. Im Quellcodeverzeichnis befinden sich diese Dateien: superprog.c, uart.h, uart.c, lcd.h, lcd.c, 1wire.h, 1wire.c und das makefile (die angepasste Kopie des WinAVR-Beispiels).&lt;br /&gt;
&lt;br /&gt;
Der Controller wird mittels [[avrdude]] über ein [[STK200]]-Programmierdongle an der Schnittstelle lpt1 (bzw. /dev/lp0) programmiert. Im Quellcode sind auch Daten für die &#039;&#039;section .eeprom&#039;&#039; definiert (siehe Abschnitt Speicherzugriffe TODO: nach unten verlinken), diese sollen beim Programmieren gleich mit ins EEPROM geschrieben werden. &lt;br /&gt;
&lt;br /&gt;
== Controllertyp setzen ==&lt;br /&gt;
&lt;br /&gt;
Dazu wird die &amp;quot;make-Variable&amp;quot; MCU ensprechend dem Namen des verwendenten Controllers gesetzt. Ein Liste der von avr-gcc und der avr-libc untersützten Typen findet sich in der [http://www.nongnu.org/avr-libc/user-manual/index.html Dokumentation der avr-libc].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
# Kommentare in Makefiles beginnen mit einem Doppelkreuz &lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
# ATmega8 at work&lt;br /&gt;
MCU = atmega8&lt;br /&gt;
# oder MCU = atmega16 &lt;br /&gt;
# oder MCU = at90s8535&lt;br /&gt;
# oder ...&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Quellcode-Dateien einstellen ==&lt;br /&gt;
&lt;br /&gt;
Den Namen der Quellcodedatei welche die Funktion main enthält, wird hinter TARGET eingetragen. Dies jedoch ohne die Endung &#039;&#039;.c&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
TARGET = superprog&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Besteht das Projekt wie im Beispiel aus mehr als einer Quellcodedatei, sind die weiteren c-Dateien (nicht die Header-Dateien) durch Leerzeichen getrennt bei SRC einzutragen. Die bei TARGET definierte Datei ist schon eingetragen. Diesen Eintrag nicht löschen!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
SRC = $(TARGET).c uart.c lcd.c 1wire.c &lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternativ kann man die Liste der Quellcodedateien auch mit dem Operator += erweitern.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
SRC = $(TARGET).c uart.c 1wire.c&lt;br /&gt;
# lcd-Code fuer Controller xyz123 (auskommentiert)&lt;br /&gt;
# SRC += lcd_xyz.c&lt;br /&gt;
# lcd-Code fuer &amp;quot;Standard-Controller&amp;quot; (genutzt)&lt;br /&gt;
SRC += lcd.c&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmiergerät einstellen ==&lt;br /&gt;
&lt;br /&gt;
Die Vorlagen sind auf die Programmiersoftware avrdude angepasst, jedoch lässt sich auch andere Programmiersoftware einbinden, sofern diese über Kommandozeile gesteuert werden kann (z.B. stk500.exe, uisp, sp12).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
# Einstellung fuer STK500 an com1 (auskommentiert)&lt;br /&gt;
# AVRDUDE_PROGRAMMER = stk500&lt;br /&gt;
# com1 = serial port. Use lpt1 to connect to parallel port.&lt;br /&gt;
# AVRDUDE_PORT = com1    # programmer connected to serial device&lt;br /&gt;
&lt;br /&gt;
# Einstellung fuer STK200-Dongle an lpt1&lt;br /&gt;
AVRDUDE_PROGRAMMER = stk200&lt;br /&gt;
AVRDUDE_PORT = lpt1&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sollen Flash(=.hex) und EEPROM(=.eep) zusammen auf den Controller programmiert werden, ist das Kommentarzeichen vor AVRDUDE_WRITE_EEPROM zu löschen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
#Auskommentiert: EERPOM-Inhalt wird nicht mitgeschrieben&lt;br /&gt;
#AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep&lt;br /&gt;
&lt;br /&gt;
#Nich-auskommentiert EERPOM-Inhalt wird mitgeschrieben&lt;br /&gt;
AVRDUDE_WRITE_EEPROM = -U eeprom:w:$(TARGET).eep&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Anwendung ==&lt;br /&gt;
&lt;br /&gt;
Die Eingabe von &#039;&#039;make all&#039;&#039; im Arbeitsverzeichnis mit dem makefile und den Quellcodedateien erzeugt (unter anderem) die Dateien superprog.hex und superprog.eep. Abhängigkeiten zwischen den einzelnen c-Dateien werden dabei automatisch berücksichtigt. Die &#039;&#039;superprog.hex&#039;&#039; und &#039;&#039;superprog.eep&#039;&#039; werden mit &#039;&#039;make program&#039;&#039; zum Controller  übertragen. Mit &#039;&#039;make clean&#039;&#039; werden alle temporären Dateien gelöscht (=&amp;quot;aufgeräumt&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
= Definition einiger Datentypen =&lt;br /&gt;
&lt;br /&gt;
Für die Programmierung von Mikrocontrollern ist es sinnvoll, dass wir uns&lt;br /&gt;
vorerst einige Datentypen definieren, welche den Zugriff auf die verschiedenen&lt;br /&gt;
Komponenten des Controllers vereinfachen oder wenigstens das Programm lesbarer&lt;br /&gt;
machen können.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
typedef unsigned char BYTE;&lt;br /&gt;
typedef unsigned short WORD;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== BYTE ==&lt;br /&gt;
&lt;br /&gt;
Der Datentyp BYTE definiert eine Variable mit 8 Bit Breite zur Darstellung&lt;br /&gt;
von ganzen Zahlen im Bereich zwischen 0 ... 255.&lt;br /&gt;
&lt;br /&gt;
== WORD ==&lt;br /&gt;
&lt;br /&gt;
Der Datentyp WORD definiert eine Variable mit 16 Bit Breite zur Darstellung&lt;br /&gt;
von ganzen Zahlen im Bereich zwischen 0 ... 65535.&lt;br /&gt;
&lt;br /&gt;
= Standardisierte Typen =&lt;br /&gt;
&lt;br /&gt;
Standardisierte Datentypen werden in der Header-Datei inttypes.h definiert.&lt;br /&gt;
Will man diese Typen benutzen, bindet man die &amp;quot;Definitionsdatei&amp;quot; wie folgt ein:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Einige der dort definierte Typen (avr-libc Version 1.0.4):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
typedef signed char int8_t;&lt;br /&gt;
typedef unsigned char uint8_t;&lt;br /&gt;
typedef short int16_t;&lt;br /&gt;
typedef unsigned short uint16_t;&lt;br /&gt;
typedef long int32_t;&lt;br /&gt;
typedef unsigned long uint32_t;&lt;br /&gt;
typedef long long int64_t;&lt;br /&gt;
typedef unsigned long long uint64_t;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ein Wort (16bit) entspricht beim AVR uint16_t, ein Byte (8bit)uint8_t. &lt;br /&gt;
&lt;br /&gt;
* siehe auch: [http://www.nongnu.org/avr-libc/user-manual/index.html Dokumentation der avr-libc] Abschnitt Modules/Integer Types&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;typedef signed char int8_t;&amp;lt;br /&amp;gt;&lt;br /&gt;
typedef unsigned char uint8_t;&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;typedef int int16_t;&amp;lt;br /&amp;gt;&lt;br /&gt;
typedef unsigned int uint16_t;&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;typedef long int32_t;&amp;lt;br /&amp;gt;&lt;br /&gt;
typedef unsigned long uint32_t;&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;typedef long long int64_t;&amp;lt;br /&amp;gt;&lt;br /&gt;
typedef unsigned long long uint64_t;&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;typedef int16_t intptr_t;&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
typedef uint16_t uintptr_t;&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;&#039;Bitfelder&#039;&#039;&#039; ==&lt;br /&gt;
&lt;br /&gt;
Beim Programmieren von Mikrocontrollern muss auf jedes Byte oder sogar auf&lt;br /&gt;
jedes Bit geachtet werden. Oft müssen wir in einer Variablen lediglich den&lt;br /&gt;
Zustand 0 oder 1 speichern. Wenn wir nun zur Speicherung eines einzelnen Wertes&lt;br /&gt;
den kleinsten bekannten Datentypen, nämlich &#039;&#039;&#039;unsigned char&#039;&#039;&#039;, nehmen, dann&lt;br /&gt;
verschwenden wir 7 Bits, da ein &#039;&#039;&#039;unsigned char&#039;&#039;&#039; ja 8 Bit breit ist.&amp;lt;br /&amp;gt;&lt;br /&gt;
Hier bietet uns die Programmiersprache C ein mächtiges Werkzeug an, mit dessen&lt;br /&gt;
Hilfe wir 8 Bits in einer einzelnen Bytevariable zusammen fassen und (fast) wie&lt;br /&gt;
8 einzelne Variablen ansprechen können.&amp;lt;br /&amp;gt;&lt;br /&gt;
Die Rede ist von sogenannten Bitfeldern. Diese werden als Strukturelemente&lt;br /&gt;
definiert. Sehen wir uns dazu doch am besten gleich ein Beispiel an:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
struct {&lt;br /&gt;
   unsigned char bStatus_1:1; // 1 Bit für bStatus_1&lt;br /&gt;
   unsigned char bStatus_2:1; // 1 Bit für bStatus_2&lt;br /&gt;
   unsigned char bNochNBit:1; // Und hier noch mal ein Bit&lt;br /&gt;
   unsigned char b2Bits:2;    // Dieses Feld ist 2 Bits breit&lt;br /&gt;
   // All das hat in einer einzigen Byte-Variable Platz.&lt;br /&gt;
   // die 3 verbleibenden Bits bleiben ungenutzt&lt;br /&gt;
} x;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Zugriff auf ein solches Feld erfolgt nun wie beim Strukturzugriff bekannt&lt;br /&gt;
über den Punkt- oder den Dereferenzierungs-Operator:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
x.bStatus_1 = 1;&lt;br /&gt;
x.bStatus_2 = 0;&lt;br /&gt;
x.b2Bits = 3;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
(mt Empfehlung: Bitfelder sparen zwar Platz, verschlechtern aber unter&lt;br /&gt;
Umständen die Les- und Wartbarkeit des Codes. Anfängern wird geraten,&lt;br /&gt;
ein &amp;quot;ganzes&amp;quot; ein Byte (uint8_t) zu nutzen auch wenn nur ein Bitwert gespeichert &lt;br /&gt;
werden soll.)&lt;br /&gt;
&lt;br /&gt;
= Grundsätzlicher Programmaufbau eines &amp;amp;micro;C-Programms =&lt;br /&gt;
&lt;br /&gt;
Wir unterscheiden zwischen 2 verschiedenen Methoden, um ein&lt;br /&gt;
Mikrocontroller-Programm zu schreiben, und zwar völlig unabhängig davon, in&lt;br /&gt;
welcher Programmiersprache das Programm geschrieben wird.&lt;br /&gt;
&lt;br /&gt;
== Sequentieller Programmablauf ==&lt;br /&gt;
&lt;br /&gt;
Bei dieser Programmiertechnik wird eine Endlosschleife programmiert, welche im&lt;br /&gt;
Wesentlichen immer den gleichen Aufbau hat:&lt;br /&gt;
&lt;br /&gt;
[[Image:Sequentielle Programme.gif]]&lt;br /&gt;
&lt;br /&gt;
== Interruptgesteuerter Programmablauf ==&lt;br /&gt;
&lt;br /&gt;
Bei dieser Methode werden beim Programmstart zuerst die gewünschten&lt;br /&gt;
Interruptquellen aktiviert und dann in eine Endlosschleife gegangen, in welcher&lt;br /&gt;
Dinge erledigt werden können, welche nicht zeitkritisch sind.&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn ein Interrupt ausgelöst wird so wird automatisch die zugeordnete&lt;br /&gt;
Interruptfunktion ausgeführt.&lt;br /&gt;
&lt;br /&gt;
[[Image:Interrupt Programme.gif]]&lt;br /&gt;
&lt;br /&gt;
= Allgemeiner Zugriff auf Register =&lt;br /&gt;
&lt;br /&gt;
Die AVR-Controller verfügen über eine Vielzahl von Registern. Die meisten&lt;br /&gt;
davon sind sogenannte Schreib-/Leseregister. Das heisst, das Programm kann die&lt;br /&gt;
Inhalte der Register auslesen und beschreiben.&amp;lt;br /&amp;gt;&lt;br /&gt;
Einige Register haben spezielle Funktionen, andere wiederum könne für&lt;br /&gt;
allgemeine Zwecke (Speichern von Datenwerten) verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Einzelne Register sind bei allen AVR&#039;s vorhanden, andere wiederum nur bei&lt;br /&gt;
bestimmten Typen. So sind beispielsweise die Register, welche für den Zugriff&lt;br /&gt;
auf den UART notwendig sind selbstverständlich nur bei denjenigen Modellen&lt;br /&gt;
vorhanden, welche über einen integrierten Hardware UART bzw. USART verfügen.&lt;br /&gt;
&lt;br /&gt;
Die Namen der Register sind in den Headerdateien zu den entsprechenden&lt;br /&gt;
AVR-Typen definiert.&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;!--Wenn im Makefile der MCU-Typ definiert ist so bindet das System automatisch die&lt;br /&gt;
richtige Headerdatei ein.&amp;lt;br /&amp;gt; --&amp;gt;&lt;br /&gt;
Wenn im Makefile der MCU-Typ definiert ist, wird vom System automatisch die&lt;br /&gt;
zum Typen passende Definitionsdatei genutzt, sobald man im Code die allgemeine &lt;br /&gt;
&amp;quot;io.h&amp;quot; Header-Datei einbinden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ist im Makefile der MCU Type z.B. mit dem Inhalt atmega8 definiert,&lt;br /&gt;
wird beim einlesen der io.h-Datei implizit (&amp;quot;automatisch&amp;quot;) auch die iom8.h-Datei mit&lt;br /&gt;
den Register-Definitionen für den ATmega8 eingelesen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Man kann der MCU-Typ aber selbstverständlich auch noch in der C-Quelldatei&lt;br /&gt;
definieren, wenn man Freude daran hat. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== I/O-Register ==&lt;br /&gt;
&lt;br /&gt;
Die I/O-Register haben einen besonderen Stellenwert bei den AVR Controllern.&lt;br /&gt;
Sie dienen dem Zugriff auf die Ports und die Schnittstellen des Controllers.&amp;lt;br /&amp;gt;&lt;br /&gt;
Wir unterscheiden zwischen 8-Bit und 16-Bit Registern. Vorerst behandeln wir mal&lt;br /&gt;
die 8-Bit Register.&lt;br /&gt;
&amp;lt;!-- &lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Hinweis:&#039;&#039;&#039;&lt;br /&gt;
| Die folgenden Funktionen erwarten als Argument&lt;br /&gt;
für das jeweilige Portregister konstante Werte. Am besten verwenden wir&lt;br /&gt;
die entsprechenden defines aus der Headerdatei . Wenn die&lt;br /&gt;
Portadresse über eine 8-Bit Variable übergeben quittiert der Inline&lt;br /&gt;
Assembler dies jeweils mit 2 Fehlermeldungen folgender Form:&lt;br /&gt;
&lt;br /&gt;
:: warning: asm operand 0 probably&lt;br /&gt;
doesn&#039;t match constraints&amp;lt;br /&amp;gt;:: warning: asm operand 1 probably&lt;br /&gt;
doesn&#039;t match constraints&lt;br /&gt;
&lt;br /&gt;
Offensichtlich läuft das Programm so auch tatsächlich nicht korrekt&lt;br /&gt;
ab. Wenn wir also Ports über Variablen ansprechen wollen müssen wir auf&lt;br /&gt;
die Low Level-Funktion &#039;&#039;&#039;[http://en.wikipedia.org#Speicherbezogener%20Portzugriff __mmio]&#039;&#039;&#039;&lt;br /&gt;
ausweichen.&lt;br /&gt;
|} --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Lesen eines I/O-Registers ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Der gesamte Inhalt eines Registers kann einfach mit dem Befehl&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;inp();&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
ausgelesen werden. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zum Lesen kann man auf I/O Register einfach wie auf eine&lt;br /&gt;
Variable zugreifen. Die spezielle Funktion inp() ist nicht mehr &lt;br /&gt;
notwendig und veraltet.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
uint8_t foo;&lt;br /&gt;
...&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
  foo=PINB; /* kopiert den Status der Eingabepins an PortB in die Variable foo */&lt;br /&gt;
  ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Lesen eines Bits ====&lt;br /&gt;
&lt;br /&gt;
Die AVR-Bibliothek stellt auch Funktionen zur Abfrage eines einzelnen Bits&lt;br /&gt;
eines Registers zur Verfügung:&lt;br /&gt;
&lt;br /&gt;
;bit_is_set (&amp;lt;Register&amp;gt;,&amp;lt;Bitnummer&amp;gt;) : Die Funktion &#039;&#039;bit_is_set&#039;&#039; prüft, ob ein Bit gesetzt ist. Wenn das Bit gesetzt ist wird ein Wert ungleich 0 zurückgegeben. Genau genommen ist es die Wertigkeit des abgefragten Bits, also 1 für Bit0, 2 für Bit1, 4 für Bit2 etc.&lt;br /&gt;
&lt;br /&gt;
;bit_is_clear (&amp;lt;Register&amp;gt;,&amp;lt;Bitnummer&amp;gt;) : Die Funktion &#039;&#039;bit_is_clear&#039;&#039; prüft, ob ein Bit gelöscht ist. Wenn das Bit gelöscht ist, also auf 0 ist, wird ein Wert ungleich 0 zurückgegeben.&lt;br /&gt;
&lt;br /&gt;
Die Funktionen bit_is_clear bzw. bit_is_set sind nicht unbedingt erfoderlich, man kann auch &amp;quot;einfachen&amp;quot; C-Syntax verwenden. Der universell verwendbar ist. &#039;&#039;bit_is_set&#039;&#039; entspricht dabei z.B. (Variable &amp;amp; (1&amp;lt;&amp;lt;Bitnummer)). Das Ergebnis ist &amp;lt;&amp;gt;0 wenn das Bit gesetzt und 0 wenn nicht gesetzt ist. &lt;br /&gt;
&lt;br /&gt;
* siehe auch [[Bitmanipulation]]&lt;br /&gt;
&lt;br /&gt;
=== Schreiben eines I/O-Registers ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Zum Beschreiben eines I/O-Registers verwendet man allgemein den Befehl&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;outp (, );&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Als Wert muss die Bitmaske mit den Werten aller Pins angegeben werden. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zum Schreiben kann man I/O Register einfach wie eine&lt;br /&gt;
Variable setzen. Die spezielle Funktion outp() ist nicht mehr &lt;br /&gt;
notwendig, veraltet und sollte nicht mehr genutzt werden.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
  DDRA=0xff; /* Setzt das Richtungsregister des Ports A auf 0xff (alle Pins als Ausgang) */&lt;br /&gt;
  PORTA=0x03; /* Setzt PortA auf 0x03, Bit 0 und 1 &amp;quot;high&amp;quot;, restliche &amp;quot;low&amp;quot; */&lt;br /&gt;
  ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==== Schreiben eines Bits ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Auch für das Setzen bzw. Löschen eines einzelnen Bits eines I/O-Registers&lt;br /&gt;
stellt die AVR-Bibliothek entsprechende Funktionen zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;sbi (, );&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Die Funktion &#039;&#039;&#039;sbi&#039;&#039;&#039; setzt ein beliebiges Bit eines Registers, das heisst,&lt;br /&gt;
es wird der logische Wert 1 in das Bit geschrieben. Die anderen Bits des Ports&lt;br /&gt;
werden nicht verändert.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das niederwertigste Bit hat die Bitnummer 0.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;cbi (, );&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Die Funktion &#039;&#039;&#039;cbi&#039;&#039;&#039; löscht ein beliebiges Bit eines Registers, das&lt;br /&gt;
heisst, es wird der logische Wert 0 in das Bit geschrieben. Die anderen Bits des&lt;br /&gt;
Ports werden nicht verändert.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das niederwertigste Bit hat die Bitnummer 0. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Einzelne Bits setzt man &amp;quot;Standard-C-Konform&amp;quot; mittels logischen (bit-) Operationen.&lt;br /&gt;
&lt;br /&gt;
mit dem Ausduck |=(1&amp;lt;&amp;lt;Bitnummer) wird ein Bit gesetzt, mit dem Ausdruck&lt;br /&gt;
&amp;amp;=~(1&amp;lt;&amp;lt;Bitnummer) wird ein Bit geloescht. Die Funktionen sbi und cbi sind&lt;br /&gt;
dazu nicht notwendig, veraltet und sollten nicht mehr genutzt werden.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
#define MEINBIT 2&lt;br /&gt;
...&lt;br /&gt;
PORTA |= (1&amp;lt;&amp;lt;MEINBIT); /* setzt Bit 2 an PortA auf 1 */&lt;br /&gt;
PORTA &amp;amp;= ~(1&amp;lt;&amp;lt;MEINBIT); /* loescht Bit 2 an PortA */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* siehe auch:&lt;br /&gt;
** [[Bitmanipulation]]&lt;br /&gt;
** [http://www.nongnu.org/avr-libc/user-manual/index.html Dokumentation der avr-libc] Abschnitt Modules/Special Function Registers&lt;br /&gt;
&lt;br /&gt;
=== Warten auf einen bestimmten Zustand ===&lt;br /&gt;
&lt;br /&gt;
Es gibt in der Bibliothek sogar Funktionen, die Warten, bis ein bestimmter&lt;br /&gt;
Zustand auf einem Bit erreicht ist.&amp;lt;br /&amp;gt;&lt;br /&gt;
Es ist allerdings normalerweise eine eher unschöne Programmiertechnik.&lt;br /&gt;
&lt;br /&gt;
Die Funktion &#039;&#039;&#039;loop_until_bit_is_set&#039;&#039;&#039; wartet in einer Schleife, bis das&lt;br /&gt;
definierte Bit gesetzt ist. Wenn das Bit beim Aufruf der Funktion bereits&lt;br /&gt;
gesetzt ist wird die Funktion sofort wieder verlassen. Das niederwertigste Bit hat die Bitnummer 0. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
/* Warten bis Bit Nr. 2 (das dritte Bit) in Register PINA gesetzt (1) ist */&lt;br /&gt;
&lt;br /&gt;
#define WARTEPIN PINA&lt;br /&gt;
#define WARTEBIT 2&lt;br /&gt;
&lt;br /&gt;
// mit der avr-libc Funktion:&lt;br /&gt;
loop_until_bit_is_set(WARTEPIN, WARTEBIT);&lt;br /&gt;
&lt;br /&gt;
// dito in &amp;quot;C-Standard&amp;quot;:&lt;br /&gt;
// Durchlaufe (die leere) Schleife solange das WARTEBIT in Register WARTEPIN&lt;br /&gt;
// _nicht_ ungleich 0 (also 0) ist.&lt;br /&gt;
while ( !(WARTEPIN &amp;amp; (1&amp;lt;&amp;lt;WARTEBIT)) ) ;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Funktion &#039;&#039;&#039;loop_until_bit_is_clear&#039;&#039;&#039; wartet in einer Schleife, bis das&lt;br /&gt;
definierte Bit gelöscht ist. Wenn das Bit beim Aufruf der Funktion bereits&lt;br /&gt;
gelöscht ist wird die Funktion sofort wieder verlassen.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das niederwertigste Bit hat die Bitnummer 0.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
/* Warten bis Bit Nr. 4 (das fuenfte Bit) in Register PINB geloescht (0) ist */&lt;br /&gt;
#define WARTEPIN PINB&lt;br /&gt;
#define WARTEBIT 4&lt;br /&gt;
&lt;br /&gt;
// avr-libc-Funktion:&lt;br /&gt;
loop_until_bit_is_clear(WARTEPIN, WARTEBIT);&lt;br /&gt;
&lt;br /&gt;
// dito in &amp;quot;C-Standard&amp;quot;:&lt;br /&gt;
// Durchlaufe (die leere) Schleife solange das WARTEBIT in Register WARTEPIN&lt;br /&gt;
// ungleich 0 ist &lt;br /&gt;
while ( WARTEPIN &amp;amp; (1&amp;lt;&amp;lt;WARTEBIT) ) ;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Universeller und auch auf andere Platformen besser übertragbar ist die Verwendung von C-Standardoperationen.&lt;br /&gt;
&lt;br /&gt;
siehe auch: &lt;br /&gt;
* [http://www.nongnu.org/avr-libc/user-manual/index.html Dokumentation der avr-libc] Abschnitt Modules/Special Function Registers&lt;br /&gt;
* [[Bitmanipulation]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- mt: noch notwendig? &lt;br /&gt;
=== Speicherbezogener Portzugriff ===&lt;br /&gt;
&lt;br /&gt;
In der Regel sind die weiter oben erwähnten Funktionen zu bevorzugen. Es&lt;br /&gt;
kann aber auch sein, dass wird mal eine Stufe tiefer einsteigen müssen. Dann&lt;br /&gt;
verwenden wir für den Portzugriff das Synonym &#039;&#039;&#039;__mmio&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;__mmio()&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Diese Funktion dient dem speicherbasierten Zugriff auf die Ports (Memory&lt;br /&gt;
Mapped I/O).&amp;lt;br /&amp;gt;&lt;br /&gt;
Die Funktion kann sowohl zum Lesen als auch zum Schreiben eines Ports verwendet&lt;br /&gt;
werden.&lt;br /&gt;
&lt;br /&gt;
Um ein einzelnes Bit in einem Port zu setzen bzw. zu löschen kann also ein&lt;br /&gt;
der folgenden Befehlszeilen verwendet werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;__mmio () = __mmio () | (1&lt;br /&gt;
&amp;lt;&amp;lt; )&amp;amp;nbsp;&amp;amp;nbsp; // Setzt ein Bit&amp;lt;br /&amp;gt;&lt;br /&gt;
__mmio () = __mmio () &amp;amp; ~(1 &amp;lt;&amp;lt; )&amp;amp;nbsp;&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
// Löscht ein Bit&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die anderen Bits des Ports bleiben unverändert.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Zugriff auf Ports =&lt;br /&gt;
&lt;br /&gt;
Alle Ports der AVR-Controller werden über Register gesteuert. Dazu sind&lt;br /&gt;
jedem Port 3 Register zugeordnet:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;DDRx&#039;&#039;&#039; &lt;br /&gt;
| Datenrichtungsregister für Port&#039;&#039;&#039;x&#039;&#039;&#039;. &lt;br /&gt;
&#039;&#039;&#039;x&#039;&#039;&#039; entspricht &#039;&#039;&#039;A&#039;&#039;&#039;, &#039;&#039;&#039;B&#039;&#039;&#039;, &#039;&#039;&#039; C&#039;&#039;&#039;, &#039;&#039;&#039;D&#039;&#039;&#039; usw. (anhängig von der Anzahl der Ports des verwendeten AVR). Bit im Register gesetzt (1) für Ausgang, Bit gelöscht (0) für Eingang.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;PORTx&#039;&#039;&#039;&lt;br /&gt;
| Datenregister für Port&#039;&#039;&#039;x&#039;&#039;&#039;. &lt;br /&gt;
Dieses Register wird verwendet, um die Ausgänge eines Ports anzusteuern. Wird ein Port als Eingang geschaltet, so können mit diesem Register&lt;br /&gt;
die internen Pull-Up Widerstände aktiviert oder deaktiviert werden (1 = aktiv).&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;PINx&#039;&#039;&#039;&lt;br /&gt;
| Eingangadresse für Port&#039;&#039;&#039;x&#039;&#039;&#039;. &lt;br /&gt;
&amp;lt;!-- TODO: Erläuterung eher weiter unten nicht in der &amp;quot;Kurzzusammenfassung - Dies ist kein eigentliches Register, sondern definiert lediglich eine Adresse, in welcher der aktuelle Zustand der Eingangspins eines Ports vom&lt;br /&gt;
Controller abgelegt werden. Nichtsdestotrotz erfolgt der Zugriff auf den Zustand der Pins genau so, wie wenn &#039;&#039;&#039;PINx&#039;&#039;&#039; ein normales Register wäre. Die Adresse kann nur gelesen und nicht beschrieben werden.--&amp;gt;&lt;br /&gt;
Zustand des Ports. Die Bits in PINx entsprechen dem Zustand der Portspins. Bit gesetzt (1) wenn Pin &amp;quot;high/an&amp;quot;, Bit gelöscht (0) wenn Portpin &amp;quot;low/aus&amp;quot;.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Datenrichtung bestimmen ==&lt;br /&gt;
&lt;br /&gt;
Zuerst muss die Datenrichtung der verwendeten Pins bestimmt werden. Um dies zu erreichen, wird das Datenrichtungsregister des entsprechenden Ports beschrieben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- &#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;outp (, );&amp;lt;/font&amp;gt;&#039;&#039;&#039; --&amp;gt;&lt;br /&gt;
Für jeden Pin, der als Ausgang verwendet werden soll, muss dabei das&lt;br /&gt;
entsprechende Bit auf dem Port gesetzt werden. Soll der Pin als Eingang&lt;br /&gt;
verwendet werden, muss das entsprechende Bit gelöscht sein.&lt;br /&gt;
&lt;br /&gt;
Wollen wir also beispielsweise Pin 0 bis 4 von Port B als Ausgänge&lt;br /&gt;
definieren so schreiben wir folgende Zeile:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- &amp;gt;&#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;outp (0x1F, DDRB);&amp;lt;/font&amp;gt;&#039;&#039;&#039; --&amp;gt;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
// Setzen der Bits 0,1,2,3 und 4&lt;br /&gt;
// Binär 00011111 = Hexadezimal 1F&lt;br /&gt;
&lt;br /&gt;
DDRB=0x1F; /* direkte Zuweisung - unuebersichtlich */&lt;br /&gt;
/* mehr Tipparbeit aber uebersichtlicher: */&lt;br /&gt;
DDRB=(1&amp;lt;&amp;lt;DDB0)|(1&amp;lt;&amp;lt;DDB1)|(1&amp;lt;&amp;lt;DDB2)|(1&amp;lt;&amp;lt;DDB3)|(1&amp;lt;&amp;lt;DDB4); &lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Pins 5 bis 7 werden (da 0) als Eingänge geschaltet.&lt;br /&gt;
&lt;br /&gt;
=== Ganze Ports ===&lt;br /&gt;
&lt;br /&gt;
Um einen ganzen Port als Ausgang zu definieren, kann der folgende Befehl&lt;br /&gt;
verwendet werden:&lt;br /&gt;
&amp;lt;!-- &#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;outp (0xFF, DDRB);&amp;lt;/font&amp;gt;&#039;&#039;&#039; --&amp;gt;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
DDRB=0xff;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Beispiel wird der Port B als Ganzes als Ausgang geschaltet.&lt;br /&gt;
&lt;br /&gt;
== Digitale Signale ==&lt;br /&gt;
&lt;br /&gt;
Am einfachsten ist es, digitale Signale mit dem Mikrocontroller zu erfassen&lt;br /&gt;
bzw. auszugeben.&lt;br /&gt;
&lt;br /&gt;
== Ausgänge ==&lt;br /&gt;
&lt;br /&gt;
Wir wollen nun einen als Ausgang definierten Pin auf Logisch 1 setzen. Dazu schreiben wir den entsprechenden Wert in das Portregister des entsprechenden Ports.&lt;br /&gt;
&lt;br /&gt;
Mit dem Befehl&lt;br /&gt;
&amp;lt;!-- &#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;outp (0x04, PORTB);&amp;lt;/font&amp;gt;&#039;&#039;&#039; --&amp;gt;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
PORTB=0x04; /* besser PORTB=(1&amp;lt;&amp;lt;DDB2) */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
wird also der Ausgang an Pin 2 gesetzt (Beachte, dass die Bits immer &#039;&#039;von 0 an&#039;&#039;&lt;br /&gt;
gezählt werden, das niederwertigste Bit ist also Bit 0 und nicht etwa Bit 1).&lt;br /&gt;
&lt;br /&gt;
Man beachte bitte, dass bei der Zuweisung mittels &#039;&#039;&#039;=&#039;&#039;&#039; &amp;lt;!-- Verwendung der &#039;&#039;&#039;outp&#039;&#039;&#039;-Funktion--&amp;gt; immer alle Pins gleichzeitig angegeben werden. Man sollte also zuerst den aktuellen Wert des Ports einlesen und das Bit des gewünschten Ports in diesen Wert einfliessen lassen. Will man also nur den dritten Pin (Bit Nr. 2) an PortB auf &amp;quot;high&amp;quot; setzen und den Status der anderen Ausgänge unverändert lassen, nutze man diese Form:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
PORTB = PORTB | 0x04; /* besser: PORTB = PORTB | ( 1&amp;lt;&amp;lt;DDB2 ) */&lt;br /&gt;
/* vereinfacht durch Nutzung des |= Operators : */&lt;br /&gt;
PORTB |= (1&amp;lt;&amp;lt;DDB2)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Es gibt jedoch in der AVRGCC-Bibliothek Funktionen, welche dies selbständig&lt;br /&gt;
machen.&amp;lt;br /&amp;gt;&lt;br /&gt;
Die Funktionen lassen sich wie folgt verwenden:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;sbi (PORTB, 2);&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; // Setzt Pin 2 auf Logisch 1 (EIN)&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
cbi (PORTB, 2);&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; // Setzt Pin 2 auf Logisch 0 (AUS)&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
Die Funktionen cbi und sbi sind dazu nicht notwendig, veraltet und sollten &lt;br /&gt;
nicht mehr genutzt werden.&lt;br /&gt;
&lt;br /&gt;
== Eingänge (Wie kommen Signale in den &amp;amp;micro;C) ==&lt;br /&gt;
&lt;br /&gt;
Die digitalen Eingangssignale können auf verschiedene Arten zu unserer Logik gelangen.&lt;br /&gt;
&lt;br /&gt;
=== Signalkopplung ===&lt;br /&gt;
&lt;br /&gt;
Am einfachsten ist es, wenn die Signale direkt aus einer anderen digitalen Schaltung übernommen werden können. Hat der Ausgang der entsprechenden Schaltung TTL-Pegel dann können wir sogar direkt den Ausgang der Schaltung mit einem Eingangspin von unserem Controller verbinden.&lt;br /&gt;
&lt;br /&gt;
Hat der Ausgang der anderen Schaltung keinen TTL-Pegel so müssen wird den Pegel über entsprechende Hardware (z.B. Optokoppler, Spannunsteiler &amp;quot;Levelshifter&amp;quot;) anpassen.&lt;br /&gt;
&lt;br /&gt;
Die Masse der beiden Schaltungen muss selbstverständlich miteinander verbunden werden. Der Software selber ist es natürlich letztendlich egal, wie das Signal eingespeist wird. Wir können ja ohnehin lediglich prüfen, ob an einem Pin unserer Controllers eine logische 1 (Vcc) oder eine logische 0 (Masse) anliegt.&lt;br /&gt;
&lt;br /&gt;
Die Abfrage der Zustände der Portpins erfolgt direkt über den Registernamen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- &#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;inp ()&amp;lt;/font&amp;gt;&#039;&#039;&#039; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;#FF0000&amp;quot;&amp;gt;Wobei es hier sehr wichtig ist, zur Abfrage der Eingänge nicht etwa das Portregister &#039;&#039;&#039;PORTx&#039;&#039;&#039; zu verwenden, sondern die Porteingangsadresse &#039;&#039;&#039;PINx&#039;&#039;&#039;. Dies ist&lt;br /&gt;
ein oft gemachter Fehler!&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wollen wir also die aktuellen Signalzustände von Port D abfragen und in einer&lt;br /&gt;
Variable namens bPortD abspeichern so schreiben wir dazu folgende Befehlszeile:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
bPortD = PIND;&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;!-- &#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;bPortD = inp (PIND);&amp;lt;/font&amp;gt;&#039;&#039;&#039; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Tasten und Schalter ===&lt;br /&gt;
&lt;br /&gt;
Der Anschluss mechanischer Kontakte an den Mikrocontroller gestaltet sich ebenfalls ganz einfach, wobei wir zwei unterschiedliche Methoden unterscheiden müssen (&#039;&#039;Active Low&#039;&#039; und &#039;&#039;Active High&#039;&#039;):&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Active Low&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Active High&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| [[Image:Active Low.gif]]&lt;br /&gt;
| [[Image:Active High.gif]]&lt;br /&gt;
|- &lt;br /&gt;
| Bei dieser Methode wird der Kontakt zwischen&lt;br /&gt;
den Eingangspin des Controllers und Masse geschaltet.&amp;lt;br /&amp;gt;&lt;br /&gt;
Damit bei offenem Schalter der Controller kein undefiniertes Signal&lt;br /&gt;
bekommt wird zwischen die Versorgungsspannung und den Eingangspin ein&lt;br /&gt;
sogenannter Pull-Up Widerstand geschaltet. Dieser dient dazu, den Pegel&lt;br /&gt;
bei geöffnetem Schalter auf logisch 1 zu ziehen.&amp;lt;br /&amp;gt;&lt;br /&gt;
Der Widerstandswert des Pull-Up Widerstands ist an sich nicht kritisch. Es&lt;br /&gt;
muss jedoch beachtet werden, dass über den Widerstand ein Strom in den&lt;br /&gt;
Eingang fliesst, also sollte er nicht zu klein gewählt werden um den&lt;br /&gt;
Controller nicht zu zerstören. Wird er allerdings zu hoch gewählt ist&lt;br /&gt;
die Wirkung eventuell nicht gegeben. Als üblicher Wert haben sich 10&lt;br /&gt;
Kiloohm eingebürgert.&lt;br /&gt;
&lt;br /&gt;
Die AVR&#039;s haben sogar an den meisten Pins softwaremässig zuschaltbare&lt;br /&gt;
interne Pull-Up Widerstände, welche wir natürlich auch verwenden&lt;br /&gt;
können.&lt;br /&gt;
| Hier wird der Kontakt zwischen die&lt;br /&gt;
Versorgungsspannung und Masse geschaltet.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit bei offener Schalterstellung kein undefiniertes Signal am Controller&lt;br /&gt;
ansteht wird zwischen den Eingangspin und die Masse ein Pull-Down&lt;br /&gt;
Widerstand geschaltet. Dieser dient dazu, den Pegel bei geöffneter&lt;br /&gt;
Schalterstellung auf logisch 0 zu halten,&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Pull-Up Widerstände aktivieren ====&lt;br /&gt;
&lt;br /&gt;
Die internen Pull-Up Widerstände von Vcc zu den einzelnen Portpins werden&lt;br /&gt;
über das Register &#039;&#039;&#039; PORTx&#039;&#039;&#039; aktiviert bzw. deaktiviert, wenn ein Pin als &#039;&#039;&#039; Eingang&#039;&#039;&#039;&lt;br /&gt;
geschaltet ist.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wird der Wert des entsprechenden Portpins auf 1 gesetzt so ist&lt;br /&gt;
der Pull-Up Widerstand aktiviert. Bei einem Wert von 0 ist der Pull-Up&lt;br /&gt;
Widerstand nicht aktiv.&amp;lt;br /&amp;gt;&lt;br /&gt;
Man sollte jeweils entweder den internen oder einen externen Pull-Up Widerstand&lt;br /&gt;
verwenden, aber nicht beide zusammen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- &#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;outp (0x00, DDRD);&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; // Port D als&lt;br /&gt;
Eingang schalten&amp;lt;br /&amp;gt;&lt;br /&gt;
outp (0x00, PORTD);&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; // Interne Pull-Up Widerstände aus&amp;lt;/font&amp;gt;&#039;&#039;&#039; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
DDRD=0x00; /* alle Pins von Port D als Eingang */&lt;br /&gt;
PORTD=0xff: /* interer Pull-Up an allen Port-Pins aktivieren */&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Beispiel wird der gesamte Port D als Eingang geschaltet und alle Pull-Up&lt;br /&gt;
Widerstände aktiviert.&lt;br /&gt;
&lt;br /&gt;
===== Tastenentprellung =====&lt;br /&gt;
&lt;br /&gt;
Nun haben alle mechanischen Kontakte, sei es von Schaltern, Tastern oder auch von&lt;br /&gt;
Relais, die unangenehme Eigenschaft zu prellen. Dies bedeutet, dass beim&lt;br /&gt;
Schliessen des Kontaktes derselbe nicht direkt Kontakt herstellt, sondern&lt;br /&gt;
mehrfach ein- und ausschaltet bis zum endgültigen Herstellen des Kontaktes.&amp;lt;br /&amp;gt;&lt;br /&gt;
Soll nun mit einem schnellen Mikrocontroller gezählt werden, wie oft ein&lt;br /&gt;
solcher Kontakt geschaltet wird, dann haben wir ein Problem, weil das Prellen&lt;br /&gt;
als mehrfache Impulse gezählt wird.&amp;lt;br /&amp;gt;&lt;br /&gt;
Diesem Phänomen muss beim Schreiben des Programms unbedingt Rechnung getragen&lt;br /&gt;
werden.&lt;br /&gt;
&lt;br /&gt;
== Analog ==&lt;br /&gt;
&lt;br /&gt;
Leider können wir mit unseren Controllern keine analogen Werte direkt&lt;br /&gt;
ausgeben oder einlesen. Dazu müssen wir Umwege gehen, doch dies wird in einem späteren&lt;br /&gt;
Kapitel behandelt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== 16-Bit Portregister (ADC, ICR1, OCR1, TCNT1) ===&lt;br /&gt;
&lt;br /&gt;
Einige der Portregister in den AVR-Controllern sind 16 Bit breit, Man spricht&lt;br /&gt;
dann von einem &#039;&#039;&#039;Wort&#039;&#039;&#039;. &lt;br /&gt;
&amp;lt;!--Für den Zugriff auf diese Register stellt die&lt;br /&gt;
Funktionsbibliothek zwei spezielle Befehle zur Verfügung:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;__inw ();&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Liest den aktuellen Wert eines 16-Bit Portregisters ein.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;__outw (, );&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Schreibt einen Wert in ein 16-Bit Portregister. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Datenblatt sind diese Register üblicherweise mit dem Suffix &amp;quot;L&amp;quot; (LSB) und &amp;quot;H&amp;quot; (MSB) versehen. Die avr-libc definiert zusätzlich die meisten dieser Variablen die Bezeichnung ohne &amp;quot;L&amp;quot; oder &amp;quot;H&amp;quot;. Auf diese kann direkt zugewiesen bzw. zugegriffen werden. Die Konvertierung von 16-bit Wort nach 2*8-bit Byte erfolgt intern.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
uint16_t foo;&lt;br /&gt;
&lt;br /&gt;
foo=ADC; /* setzt die Wort-Variable foo auf den Wert der letzten AD-Wandlung */&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* siehe auch: [http://www.nongnu.org/avr-libc/user-manual/index.html Dokumentation der avr-libc] Abschnitt Related Pages/Frequently Asked Questions/Nr. 8&lt;br /&gt;
&lt;br /&gt;
= Der UART, Teil 1 =&lt;br /&gt;
&lt;br /&gt;
Wir werden in zukünftigen Übungen in die Situation kommen, dass wir&lt;br /&gt;
Informationen vom Controller auswerten bzw. anzeigen müssen wobei es vielleicht&lt;br /&gt;
dann nicht mehr reicht, ein paar Leuchtdioden anzusteuern.&amp;lt;br /&amp;gt;&lt;br /&gt;
Somit brauchen wir eine Verbindung vom AVR zu unserem PC, und dies am besten&lt;br /&gt;
über die serielle Schnittstelle.&lt;br /&gt;
&lt;br /&gt;
== Allgemeines zum UART ==&lt;br /&gt;
&lt;br /&gt;
Einige AVR-Controller haben einen vollduplexfähigen UART (&#039;&#039;&#039;U&#039;&#039;&#039;niversal&lt;br /&gt;
&#039;&#039;&#039;A&#039;&#039;&#039;synchronous &#039;&#039;&#039;R&#039;&#039;&#039;eceiver and &#039;&#039;&#039;T&#039;&#039;&#039;ransmitter) schon eingebaut.&lt;br /&gt;
Dies ist eine wirklich feine Sache, haben wir doch damit schon das nötige&lt;br /&gt;
Werkzeug, um mit anderen Geräten, welche über eine serielle Schnittstelle&lt;br /&gt;
verfügen (insbesondere mit unserem PC), zu kommunizieren.&lt;br /&gt;
&lt;br /&gt;
Übrigens: Vollduplex heisst nichts anderes, als dass der Baustein gleichzeitig&lt;br /&gt;
senden und empfangen kann.&lt;br /&gt;
&lt;br /&gt;
Neuere AVRs (ATmega) verfügen über einen oder zwei U&#039;&#039;&#039;S&#039;&#039;&#039;ART(s), dieser unterschiedet sich vom UART häuptsächlich durch interne FIFO-Puffer für Ein- und Ausgabe und erweiterte Konfigurationsmöglichkeiten. Die Puffergröße ist allerdings nur 1 Byte.&lt;br /&gt;
&lt;br /&gt;
Der UART wird über vier separate Register angesprochen. USARTs der ATMEGAs verfügen über mehr als zusätzliche Konfigurations/Datenregister. Das Datenblatt gibt darüber Auskunft. Die Folgende Tabelle gibt nur die Register für die (veralteten) UARTs wieder.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;UCR&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;U&#039;&#039;&#039;ART &#039;&#039;&#039;C&#039;&#039;&#039;ontrol &#039;&#039;&#039;R&#039;&#039;&#039;egister.&amp;lt;br /&amp;gt;&lt;br /&gt;
In diesem Register stellen wir ein, wie wir den UART verwenden möchten.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Register ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;RXCIE&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;TXCIE&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;UDRIE&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;RXEN&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;TXEN&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;CHR9&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;RXB8&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;TXB8&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | W&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;RXCIE&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;RX&#039;&#039;&#039; &#039;&#039;&#039;C&#039;&#039;&#039;omplete &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;E&#039;&#039;&#039;nable&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn dieses Bit gesetzt ist wird ein UART RX Complete Interrupt&lt;br /&gt;
ausgelöst wenn ein Zeichen vom UART empfangen wurde. Das Global&lt;br /&gt;
Enable Interrupt Flag muss selbstverständlich auch gesetzt sein.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;TXCIE&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;TX&#039;&#039;&#039; &#039;&#039;&#039;C&#039;&#039;&#039;omplete &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;E&#039;&#039;&#039;nable&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn dieses Bit gesetzt ist wird ein UART TX Complete Interrupt&lt;br /&gt;
ausgelöst wenn ein Zeichen vom UART gesendet wurde. Das Global&lt;br /&gt;
Enable Interrupt Flag muss selbstverständlich auch gesetzt sein.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;UDRIE&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;U&#039;&#039;&#039;ART &#039;&#039;&#039;D&#039;&#039;&#039;ata &#039;&#039;&#039;R&#039;&#039;&#039;egister &#039;&#039;&#039;E&#039;&#039;&#039;mpty &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt&lt;br /&gt;
&#039;&#039;&#039;E&#039;&#039;&#039;nable&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn dieses Bit gesetzt ist wird ein UART Datenregister Leer&lt;br /&gt;
Interrupt ausgelöst, wenn der UART wieder bereit ist um ein neues&lt;br /&gt;
zu sendendes Zeichen zu übernehmen. Das Global Enable Interrupt&lt;br /&gt;
Flag muss selbstverständlich auch gesetzt sein.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;RXEN&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;R&#039;&#039;&#039;eceiver &#039;&#039;&#039;E&#039;&#039;&#039;nable&amp;lt;br /&amp;gt;&lt;br /&gt;
Nur wenn dieses Bit gesetzt ist arbeitet der Empfänger des UART&lt;br /&gt;
überhaupt. Wenn das Bit nicht gesetzt ist kann der entsprechende&lt;br /&gt;
Pin des AVR als normaler I/O-Pin verwendet werden.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;TXEN&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;T&#039;&#039;&#039;ransmitter &#039;&#039;&#039;E&#039;&#039;&#039;nable&amp;lt;br /&amp;gt;&lt;br /&gt;
Nur wenn dieses Bit gesetzt ist arbeitet der Sender des UART&lt;br /&gt;
überhaupt. Wenn das Bit nicht gesetzt ist kann der entsprechende&lt;br /&gt;
Pin des AVR als normaler I/O-Pin verwendet werden.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;CHR9&#039;&#039;&#039;&lt;br /&gt;
| 9 Bit Characters&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn dieses Bit gesetzt ist können 9 Bit lange Zeichen übertragen&lt;br /&gt;
und empfangen werden. Das 9. Bit kann bei Bedarf als zusätzliches&lt;br /&gt;
Stopbit oder als Paritätsbit verwendet werden. Man spricht dann von&lt;br /&gt;
einem 11-Bit Zeichenrahmen:&amp;lt;br /&amp;gt;&lt;br /&gt;
1 Startbit + 8 Datenbits + 1 Stopbit + 1 Paritätsbit = 11 Bits&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;RXB8&#039;&#039;&#039;&lt;br /&gt;
| Receive Data Bit 8&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn das vorher erwähnte CHR9-Bit gesetzt ist, dann enthält dieses&lt;br /&gt;
Bit das 9. Datenbit eines empfangenen Zeichens.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;TXB8&#039;&#039;&#039;&lt;br /&gt;
| Transmit Data Bit 8&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn das vorher erwähnte CHR9-Bit gesetzt ist, dann muss in dieses&lt;br /&gt;
Bit das 9. Bit des zu sendenden Zeichens eingeschrieben werden bevor&lt;br /&gt;
das eigentliche Datenbyte in das Datenregister geschrieben wird.&lt;br /&gt;
|}&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;USR&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;U&#039;&#039;&#039;ART &#039;&#039;&#039;S&#039;&#039;&#039;tatus &#039;&#039;&#039;R&#039;&#039;&#039;egister.&amp;lt;br /&amp;gt;&lt;br /&gt;
Hier teilt uns der UART mit, was er gerade so macht.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;RXC&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;TXC&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;UDRE&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;FE&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;OR&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;amp;amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;RXC&#039;&#039;&#039;&lt;br /&gt;
| UART Receive Complete&amp;lt;br /&amp;gt;&lt;br /&gt;
Dieses Bit wird vom AVR gesetzt, wenn ein empfangenes Zeichen vom&lt;br /&gt;
Empfangs-Schieberegister in das Empfangs-Datenregister transferiert&lt;br /&gt;
wurde.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Zeichen muss nun schnellstmöglich aus dem Datenregister&lt;br /&gt;
ausgelesen werden. Falls dies nicht erfolgt bevor ein weiteres&lt;br /&gt;
Zeichen komplett empfangen wurde wird eine Überlauf-Fehlersituation&lt;br /&gt;
eintreffen. Mit dem Auslesen des Datenregisters wird das Bit&lt;br /&gt;
automatisch gelöscht.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;TXC&#039;&#039;&#039;&lt;br /&gt;
| UART Transmit Complete&amp;lt;br /&amp;gt;&lt;br /&gt;
Dieses Bit wird vom AVR gesetzt, wenn das im Sende-Schieberegister&lt;br /&gt;
befindliche Zeichen vollständig ausgegeben wurde und kein weiteres&lt;br /&gt;
Zeichen im Sendedatenregister ansteht. Dies bedeutet also, wenn die&lt;br /&gt;
Kommunikation vollumfänglich abgeschlossen ist.&amp;lt;br /&amp;gt;&lt;br /&gt;
Dieses Bit ist wichtig bei Halbduplex-Verbindungen, wenn das&lt;br /&gt;
Programm nach dem Senden von Daten auf Empfang schalten muss. Im&lt;br /&gt;
Vollduplexbetrieb brauchen wir dieses Bit nicht zu beachten.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Bit nur dann automatisch gelöscht, wenn der entsprechende&lt;br /&gt;
Interrupthandler aufgerufen wird, ansonsten müssen wir das Bit&lt;br /&gt;
selber löschen.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;UDRE&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;U&#039;&#039;&#039;ART &#039;&#039;&#039;D&#039;&#039;&#039;ata &#039;&#039;&#039;R&#039;&#039;&#039;egister &#039;&#039;&#039;E&#039;&#039;&#039;mpty&amp;lt;br /&amp;gt;&lt;br /&gt;
Dieses Bit wird vom AVR gesetzt, wenn ein Zeichen vom&lt;br /&gt;
Sendedatenregister in das Send-Schieberegister übernommen wurde und&lt;br /&gt;
der UART nun wieder bereit ist, ein neues Zeichen zum Senden&lt;br /&gt;
aufzunehmen.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Bit wird automatisch gelöscht, wenn ein Zeichen in das&lt;br /&gt;
Sendedatenregister geschrieben wird.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;FE&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;F&#039;&#039;&#039;raming &#039;&#039;&#039;E&#039;&#039;&#039;rror&amp;lt;br /&amp;gt;&lt;br /&gt;
Dieses Bit wird vom AVR gesetzt, wenn der UART einen&lt;br /&gt;
Zeichenrahmenfehler detektiert, d.h. wenn das Stopbit eines&lt;br /&gt;
empfangenen Zeichens 0 ist.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Bit wird automatisch gelöscht, wenn das Stopbit des empfangenen&lt;br /&gt;
Zeichens 1 ist.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;OR&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;O&#039;&#039;&#039;ver&#039;&#039;&#039;R&#039;&#039;&#039;un&amp;lt;br /&amp;gt;&lt;br /&gt;
Dieses Bit wird vom AVR gesetzt, wenn unser Programm das im&lt;br /&gt;
Empfangsdatenregister bereit liegende Zeichen nicht abholt bevor das&lt;br /&gt;
nachfolgende Zeichen komplett empfangen wurde.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das nachfolgende Zeichen wird verworfen.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Bit wird automatisch gelöscht, wenn das empfangene Zeichen in&lt;br /&gt;
das Empfangsdatenregister transferiert werden konnte.&lt;br /&gt;
|}&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;UDR&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;U&#039;&#039;&#039;ART &#039;&#039;&#039;D&#039;&#039;&#039;ata &#039;&#039;&#039;R&#039;&#039;&#039;egister.&amp;lt;br /&amp;gt;&lt;br /&gt;
Hier werden Daten zwischen UART und CPU übertragen. Da der UART im&lt;br /&gt;
Vollduplexbetrieb gleichzeitig empfangen und senden kann handelt es sich&lt;br /&gt;
hier physikalisch um 2 Register, die aber über die gleiche I/O-Adresse&lt;br /&gt;
angesprochen werden. Je nachdem, ob ein Lese- oder ein Schreibzugriff auf&lt;br /&gt;
den UART erfolgt wird automatisch das richtige UDR angesprochen.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;UBRR&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;U&#039;&#039;&#039;ART &#039;&#039;&#039;B&#039;&#039;&#039;aud &#039;&#039;&#039;R&#039;&#039;&#039;ate &#039;&#039;&#039;R&#039;&#039;&#039;egister.&amp;lt;br /&amp;gt;&lt;br /&gt;
In diesem Register müssen wir dem UART mitteilen, wie schnell wir gerne&lt;br /&gt;
kommunizieren möchten. Der Wert, der in dieses Register geschrieben&lt;br /&gt;
werden muss, errechnet sich nach folgender Formel:&lt;br /&gt;
&lt;br /&gt;
UBRR = Taktfrequenz / (Baudrate * 16) - 1&lt;br /&gt;
&lt;br /&gt;
Es sind Baudraten bis zu 115200 Baud und höher möglich.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Die Hardware ==&lt;br /&gt;
&lt;br /&gt;
Der UART basiert auf normalem TTL-Pegel mit 0V (LOW) und 5V (HIGH). Die&lt;br /&gt;
Schnittstellenspezifikation für RS232 definiert jedoch -3V ... -12V (LOW) und&lt;br /&gt;
+3 ... +12V (HIGH). Zudem muss der Signalaustausch zwischen AVR und&lt;br /&gt;
Partnergerät invertiert werden. Für die Anpassung der Pegel und das&lt;br /&gt;
Invertieren der Signale gibt es fertige Schnittstellenbausteine. Der bekannteste&lt;br /&gt;
davon ist wohl der MAX232. Allerdings kostet der auch wieder Geld und benötigt&lt;br /&gt;
zusätzlich immerhin 4 externe Elkos.&lt;br /&gt;
&lt;br /&gt;
Die in den PC eingebauten Schnittstellen vertragen ohne Klagen auch den&lt;br /&gt;
TTL-Pegel vom AVR. Allerdings müssen wir immer noch die Signale invertieren. Im&lt;br /&gt;
einfachtesn Fall verwenden wir dazu jeweils einen einfachen NPN-Transistor und 2&lt;br /&gt;
Widerstände. Näheres dazu erfahrt ihr in den folgenden Übungen.&lt;br /&gt;
&lt;br /&gt;
== Senden mit dem UART ==&lt;br /&gt;
&lt;br /&gt;
Wir wollen nun Daten mit dem UART auf die serielle Schnittstelle ausgeben.&amp;lt;br /&amp;gt;&lt;br /&gt;
Dazu müssen wir den UART zuerst mal initialisieren. Dazu setzen wir je nach&lt;br /&gt;
gewünschter Funkstionsweise die&lt;br /&gt;
benötigten Bits im &#039;&#039;&#039;U&#039;&#039;&#039;ART &#039;&#039;&#039;C&#039;&#039;&#039;ontrol &#039;&#039;&#039;R&#039;&#039;&#039;egister.&amp;lt;br /&amp;gt;&lt;br /&gt;
Da wir vorerst nur senden möchten und (noch) keine Interrupts auswerten wollen&lt;br /&gt;
gestaltet sich die Initialisierung wirklich sehr einfach, da wir lediglich das &#039;&#039;&#039;Transmitter&lt;br /&gt;
Enable&#039;&#039;&#039; Bit setzen müssen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- &#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;outp ((1 &amp;lt;&amp;lt; TXEN), UCR);&amp;lt;/font&amp;gt;&#039;&#039;&#039; --&amp;gt;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
UCR |= (1&amp;lt;&amp;lt;TXEN);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nun müssen wir noch die Baudrate festlegen. Gemäss unserer Formel brauchen&lt;br /&gt;
wir dazu die Taktfrequenz des angeschlossenen Oszillators bzw. Quarz in die&lt;br /&gt;
Formel einzufügen und das Resultat der Berechnung in das Baudratenregister des&lt;br /&gt;
UART einzuschreiben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#define F_CPU 4000000; // Zum Beispiel 4Mhz-Quarz&lt;br /&gt;
#define UART_BAUD_RATE 9600 // Wir versuchen mal mit 9600 Baud&lt;br /&gt;
UBRR = F_CPU / (UART_BAUD_RATE * 16L) - 1;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- &#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;#define F_CPU 4000000&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&lt;br /&gt;
// Zum Beispiel 4Mhz-Quarz&amp;lt;br /&amp;gt;&lt;br /&gt;
#define UART_BAUD_RATE 9600 // Wir versuchen mal mit 9600 Baud&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;outp (F_CPU / (UART_BAUD_RATE * 16L) - 1, UBRR);&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um nun ein Zeichen auf die Schnittstelle auszugeben müssen wir dasselbe&lt;br /&gt;
lediglich in das &#039;&#039;&#039;U&#039;&#039;&#039;ART &#039;&#039;&#039;D&#039;&#039;&#039;aten &#039;&#039;&#039;R&#039;&#039;&#039;egister schreiben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- &#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;outp (&#039;x&#039;, UDR);&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; // Schreibt das Zeichen x auf die Schnittstelle&amp;lt;/font&amp;gt;&#039;&#039;&#039; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
UDR = &#039;x&#039;; // Schreibt das Zeichen x auf die Schnittstelle&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Schreiben einer Zeichenkette (String) ===&lt;br /&gt;
&lt;br /&gt;
Wenn wir nun mehrere, aufeinanderfolgende Zeichen auf die Schnittstelle&lt;br /&gt;
ausgeben wollen, dann müssen wir mit dem nächsten Zeichen warten, bis das&lt;br /&gt;
vorhergehende jeweils aus dem Datenregister in das Sende-Schieberegister&lt;br /&gt;
übernommen wurde.&amp;lt;br /&amp;gt;&lt;br /&gt;
Zu diesem Zweck können wir uns für&#039;s Erste eine einfache Funktion basteln:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
void SendeString (char *szBuf)&lt;br /&gt;
{&lt;br /&gt;
  while (*szBuf++) {&lt;br /&gt;
     UDR=*szBuf;&lt;br /&gt;
     loop_until_bit_is_set (USR, UDRE);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das ist jetzt insofern etwas kritisch, dass wir während dem Senden des&lt;br /&gt;
Strings nicht mehr auf andere Ereignisse reagieren können. Dies wird aber&lt;br /&gt;
ohnehin erst dann ein Thema, wenn wir mit unserem Programm gleichzeitig Senden&lt;br /&gt;
und Empfangen wollen.&amp;lt;br /&amp;gt;&lt;br /&gt;
Wir werden zu einem späteren Zeitpunkt Lösung für dieses Problem finden (Interrupt).&lt;br /&gt;
&lt;br /&gt;
* siehe auch: Weiterführende Informationen inkl. Beispielen für die Nutzung von stdio-Funktionen (prinf etc.) im [[AVR-Tutorial - UART]].&lt;br /&gt;
* [http://homepage.sunrise.ch/mysunrise/pfleury/ Peter Fleurys] UART-Bibiliothek fuer avr-gcc/avr-libc&lt;br /&gt;
&lt;br /&gt;
= Analoge Ein- und Ausgabe =&lt;br /&gt;
&lt;br /&gt;
Leider können wir mit unseren Controllern keine analogen Werte direkt&lt;br /&gt;
verarbeiten. Dazu bedarf es jeweils einer Umwandlung des analogen Signals in&lt;br /&gt;
einen digitalen Zahlenwert. Je nachdem, ob wir Daten einlesen oder ausgeben&lt;br /&gt;
wollen reden wir dabei von &#039;&#039;&#039; DAC&#039;&#039;&#039; oder &#039;&#039;&#039;ADC&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
== ADC (Analog Digital Converter) ==&lt;br /&gt;
&lt;br /&gt;
Der &#039;&#039;&#039; ADC&#039;&#039;&#039; wandelt analoge Signale in digitale Werte um welche vom Controller&lt;br /&gt;
interpretiert werden können. Einige AVR-Typen haben bereits einen oder mehrere&lt;br /&gt;
solcher &#039;&#039;&#039;ADC&#039;&#039;&#039;&#039;s eingebaut, bei den kleineren AVR&#039;s müssen wir uns anders aus der&lt;br /&gt;
Affäre ziehen. Die Genauigkeit, mit welcher ein analoges Signal aufgelöst&lt;br /&gt;
werden kann wird durch die Auflösung des &#039;&#039;&#039; ADC&#039;&#039;&#039; in Anzahl Bits angegeben, man&lt;br /&gt;
hört bzw. liest jeweils von 8-Bit &#039;&#039;&#039; ADC&#039;&#039;&#039; oder 10-Bit &#039;&#039;&#039; ADC&#039;&#039;&#039; oder noch höher.&amp;lt;br /&amp;gt;&lt;br /&gt;
Ein &#039;&#039;&#039; ADC&#039;&#039;&#039; mit 8 Bit Auflösung kann somit das analoge Signal mit einer Genauigkeit&lt;br /&gt;
von 1/255 des Maximalwertes darstellen. Wenn wir nun mal annehmen, wir hätten&lt;br /&gt;
eine Spannung zwischen 0 und 5 Volt und eine Auflösung von 3 Bit, dann könnten&lt;br /&gt;
die Werte 0V, 0.625V, 1.25, 1.875V, 2.5V, 3.125V, 3.75, 4.375,&amp;amp;nbsp; 5V&lt;br /&gt;
daherkommen, siehe dazu folgende Tabelle:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&amp;lt;center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;Eingangsspannung am ADC&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;Entsprechender Messwert&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0...0.625V&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0.625...1.25V&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1.25...1.875V&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1.875...2.5V&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2.5...3.125V&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3.125...3.75V&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3.75...4.375V&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4.375...5V&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5V&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 8&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Angaben sind natürlich nur ungefähr. Je höher nun die Auflösung des &#039;&#039;&#039;&lt;br /&gt;
ADC&#039;&#039;&#039; ist, also je mehr Bits er hat, um so genauer kann der Wert erfasst werden.&lt;br /&gt;
&lt;br /&gt;
=== Messen eines Widerstandes ===&lt;br /&gt;
&lt;br /&gt;
Wir wollen hier einmal die wohl einfachste Methode zur Erfassung eines&lt;br /&gt;
analogen Wertes realisieren und zwar das Messen eines veränderlichen&lt;br /&gt;
Widerstandes wie z.B. eines Potentiometers.&lt;br /&gt;
&lt;br /&gt;
Man stelle sich vor, wir schalten einen Kondensator in Reihe zu einem&lt;br /&gt;
Widerstand zwischen die Versorgungsspannung und Masse und dazwischen nehmen wir&lt;br /&gt;
das Signal ab und führen es auf einen der Pins an unserem Controller, genau so&lt;br /&gt;
wie es in folgender Grafik dargestellt ist.&lt;br /&gt;
&lt;br /&gt;
[[Image:Poti.gif]]&lt;br /&gt;
&lt;br /&gt;
Wenn wir nun den Pin des AVR als Ausgang schalten und auf&lt;br /&gt;
Logisch 1 (HIGH) legen, dann liegt an beiden Platten des Kondensators &#039;&#039;&#039; Vcc&#039;&#039;&#039; an und&lt;br /&gt;
dieser wird entladen (Klingt komisch, mit &#039;&#039;&#039; Vcc&#039;&#039;&#039; entladen, ist aber so).&amp;lt;br /&amp;gt;&lt;br /&gt;
Nachdem nun der Kondensator genügend entladen ist schalten wir einfach den Pin&lt;br /&gt;
als Eingang wodurch dieser hochohmig wird. Der Kondensator lädt sich jetzt&lt;br /&gt;
über das Poti auf, dabei steigt der Spannungsabfall über dem Kondensator und&lt;br /&gt;
derjenige über dem Poti sinkt. Fällt nun der Spannungsabfall über dem Poti&lt;br /&gt;
unter die&amp;amp;nbsp; Thresholdspannung des Eingangspins (2/5 Vcc, also ca. 2V), dann schaltet der&lt;br /&gt;
Eingang von HIGH auf LOW um. Wenn wir nun messen (zählen), wie lange es dauert,&lt;br /&gt;
bis der Kondensator so weit geladen ist, dann haben wir einen ungefähren Wert&lt;br /&gt;
der Potentiometerstellung.&amp;lt;br /&amp;gt;&lt;br /&gt;
Der 220 Ohm Widerstand dient dem Schutz des Controllers. Wenn nämlich sonst die&lt;br /&gt;
Potentiometerstellung auf Maximum steht (0 Ohm), dann würde in den Eingang des&lt;br /&gt;
Controllers ein viel zu hoher Strom fliessen und der AVR würde in Rauch&lt;br /&gt;
aufgehen.&lt;br /&gt;
&lt;br /&gt;
Dies ist meines Wissens die einzige Schaltung zur Erfassung von&lt;br /&gt;
Analogwerten, welche mit nur einem einzigen Pin auskommt.&amp;lt;br /&amp;gt;&lt;br /&gt;
Mit einem weiteren Eingangspin und ein wenig Software können wir auch eine&lt;br /&gt;
Kalibrierung realisieren, um den Messwert in einen vernünftigen Bereich (z.B:&lt;br /&gt;
0...100 % oder so) umzurechnen.&lt;br /&gt;
&lt;br /&gt;
Wer Lust hat, sich selber mal an ein solches Programm&lt;br /&gt;
heranzuwagen, der sollte das jetzt tun. Für diejenigen, die es gern schnell&lt;br /&gt;
mögen, hier das Beispielprogramm, welches den UART-Printf aus den&lt;br /&gt;
vorangegangenen Kapiteln benötigt, inl. Makefile:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| [http://www.mypage.bluewin.ch/ch_schifferle/AtmelC/Uebungen/Poti/Poti.c Poti.c ]&lt;br /&gt;
| Hauptprogramm.&lt;br /&gt;
|- &lt;br /&gt;
| [http://www.mypage.bluewin.ch/ch_schifferle/AtmelC/Uebungen/Poti/Pot.c Pot.c]&lt;br /&gt;
| Separate Routine zur Ermittlung des Messwertes.&lt;br /&gt;
|- &lt;br /&gt;
| [http://www.mypage.bluewin.ch/ch_schifferle/AtmelC/Uebungen/Poti/Pot.h Pot.h]&lt;br /&gt;
| Zugehörige Headerdatei.&lt;br /&gt;
|- &lt;br /&gt;
| [http://www.mypage.bluewin.ch/ch_schifferle/AtmelC/Uebungen/Allgemein/UartPrintF.c UartPrintF.c]&lt;br /&gt;
| Für die Debugausgabe auf den UART.&lt;br /&gt;
|- &lt;br /&gt;
| [http://www.mypage.bluewin.ch/ch_schifferle/AtmelC/Uebungen/Allgemein/UartPrintF.h UartPrintF.h]&lt;br /&gt;
| Zugehörige Headerdatei.&lt;br /&gt;
|- &lt;br /&gt;
| [http://www.mypage.bluewin.ch/ch_schifferle/AtmelC/Uebungen/Poti/makefile Makefile]&lt;br /&gt;
| Makefile.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Nachdem das Programm auf den AVR geladen wurde muss dieser&lt;br /&gt;
kalibriert werden. Dazu wird der Kalibrierungsschalter geschlossen und das Poti&lt;br /&gt;
einige Male zwischen minimaler und maximaler Stellung hin und her gedreht. Dabei&lt;br /&gt;
werden die jeweiligen Maximalwerte bestimmt. Wenn der Kalibrierschalter wieder&lt;br /&gt;
geöffnet wird werden die Kalibrierungsdaten in&#039;s EEPROM des AVR geschrieben,&lt;br /&gt;
damit die Prozedur nicht nach jedem Reset wiederholt werden muss.&lt;br /&gt;
&lt;br /&gt;
Auf Pin 4 habe ich noch ein Triggersignal gelegt, welches auf&lt;br /&gt;
HIGH geht wenn die Messung beginnt und auf LOW, wenn der Messvorgang beendet&lt;br /&gt;
wird. Mit Hilfe dieses Signals kann der Vorgang wunderschön auf einem&lt;br /&gt;
Oszillographen dargestellt werden.&lt;br /&gt;
&lt;br /&gt;
=== ADC über Komparator ===&lt;br /&gt;
&lt;br /&gt;
Es gibt einen weiteren Weg, eine analoge Spannung mit Hilfe des&lt;br /&gt;
Komparators, welcher in fast jedem AVR integriert ist, zu messen. Siehe dazu&lt;br /&gt;
auch die Application Note AVR400 von Atmel.&lt;br /&gt;
&lt;br /&gt;
Dabei wird das zu messende Signal auf den invertierenden Eingang&lt;br /&gt;
des Komparators geführt. Zusätzlich wird ein Referenzsignal an den nicht&lt;br /&gt;
invertierenden Eingang des Komparators angeschlossen. Das Referenzsignal wird&lt;br /&gt;
hier auch wieder über ein RC-Glied erzeugt, allerdings mit festen Werten für R&lt;br /&gt;
und C.&lt;br /&gt;
&lt;br /&gt;
[[Image:ADC ueber Komparator.gif]]&lt;br /&gt;
&lt;br /&gt;
Das Prinzip der Messung ist nun dem vorhergehenden recht&lt;br /&gt;
ähnlich. Durch Anlegen eines LOW-Pegels an Pin 2 wird der Kondensator zuerst&lt;br /&gt;
einmal entladen. Auch hier muss darauf geachtet werden, dass der Entladevorgang&lt;br /&gt;
genügend lang dauert.&amp;lt;br /&amp;gt;&lt;br /&gt;
Nun wird Pin 2 auf HIGH gelegt. Der Kondensator wird geladen. Wenn die Spannung&lt;br /&gt;
über dem Kondensator die am Eingangspin anliegende Spannung erreicht hat&lt;br /&gt;
schaltet der Komparator durch. Die Zeit, welche benötigt wird, um den&lt;br /&gt;
Kondensator zu laden kann nun auch wieder als Mass für die Spannung an Pin 1&lt;br /&gt;
herangezogen werden.&lt;br /&gt;
&lt;br /&gt;
Ich habe es mir gespart, diese Schaltung auch aufzubauen und&lt;br /&gt;
zwar aus mehreren Gründen:&lt;br /&gt;
&lt;br /&gt;
# 3 Pins notwendig.&lt;br /&gt;
# Genauigkeit vergleichbar mit einfacherer Lösung.&lt;br /&gt;
# War einfach zu faul.&lt;br /&gt;
&lt;br /&gt;
Der Vorteil dieser Schaltung liegt allerdings darin, dass damit&lt;br /&gt;
direkt Spannungen gemessen werden können.&lt;br /&gt;
&lt;br /&gt;
=== Der ADC im AVR ===&lt;br /&gt;
&lt;br /&gt;
Wenn es einmal etwas genauer sein soll, dann müssen wir auf einen AVR mit eingebautem &#039;&#039;&#039;ADC-Wandler&#039;&#039;&#039; zurückgreifen. Wir wollen hier einmal den AT90S8535 besprechen, welcher über 8 ADC-Kanäle verfügt. (TODO: nur ein Wandler, Mulitiplexbetrieb, nur eine Pin zur gleichen Zeit)&lt;br /&gt;
&lt;br /&gt;
Die Umwandlung innerhalb des AVR basiert auf der schrittweisen Näherung. Beim AVR müssen die Pins &#039;&#039;&#039;AGND&#039;&#039;&#039; und &#039;&#039;&#039;AVCC&#039;&#039;&#039; beschaltet werden. Für genaue Messungen sollte AVCC über ein L-C Netzwerk mit VCC verbunden werden, um Spannungsspitzen und -einbrüche vom Analog-Digital-Wandler fernzuhalten. Im Datenblatt findet sich dazu eine Schaltung.  &lt;br /&gt;
&lt;br /&gt;
Verfügt der AVR über eine interne Referenzspannung (Datenblatt typisch 2,56 oder 1,1V je nach AVR), bleibt der &#039;&#039;Anschluss AREF&#039;&#039; unbeschaltet und man stellt die ADC-Register so ein, dass die interne Referenzspannung als &amp;quot;AREF&amp;quot; genutzt wird. Ansonsten ist eine externe Referenzspannung von maximal &#039;&#039;&#039;Vcc&#039;&#039;&#039; an den Abschluss &#039;&#039;&#039;AREF&#039;&#039;&#039; anzulegen. Die zu messende Spannung muss im Bereich zwischen &#039;&#039;&#039;AGND&#039;&#039;&#039; und &#039;&#039;&#039;AREF&#039;&#039;&#039; (egal ob intern oder extern) liegen. &lt;br /&gt;
&lt;br /&gt;
Der &#039;&#039;&#039; ADC&#039;&#039;&#039; kann in zwei verschiedenen Betriebsarten verwendet werden.&lt;br /&gt;
&lt;br /&gt;
==== Einfache Wandlung (Single Conversion) ====&lt;br /&gt;
&lt;br /&gt;
In dieser Betriebsart wird der Wandler bei Bedarf vom Programm angestossen für jeweils eine Messung.&lt;br /&gt;
&lt;br /&gt;
==== Frei laufend (Free Running) ====&lt;br /&gt;
&lt;br /&gt;
In dieser Betriebsart erfasst der Wandler permanent die anliegende Spannung und schreibt diese in das &#039;&#039;&#039;ADC Data Register&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
==== Die Register des ADC ====&lt;br /&gt;
&lt;br /&gt;
Der &#039;&#039;&#039; ADC&#039;&#039;&#039; verfügt über eigene Register, welche hier aufgelistet werden.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;ADCSR&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;ADC&#039;&#039;&#039; &#039;&#039;&#039;C&#039;&#039;&#039;ontrol and &#039;&#039;&#039;S&#039;&#039;&#039;tatus &#039;&#039;&#039;R&#039;&#039;&#039;egister.&amp;lt;br /&amp;gt;&lt;br /&gt;
In diesem Register stellen wir ein, wie wir den &#039;&#039;&#039;ADC&#039;&#039;&#039; verwenden möchten.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Register ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ADEN&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ADSC&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ADFR&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ADIF&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ADIE&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ADPS2&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ADPS1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ADPS0&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | W&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;ADEN&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;AD&#039;&#039;&#039;C &#039;&#039;&#039;En&#039;&#039;&#039;able&amp;lt;br /&amp;gt;&lt;br /&gt;
Dieses Bit muss gesetzt werden, um den &#039;&#039;&#039; ADC&#039;&#039;&#039; überhaupt zu aktivieren.&lt;br /&gt;
Wenn das Bit nicht gesetzt ist können die Pin&#039;s wie normale&lt;br /&gt;
I/O-Pins verwendet werden.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;ADSC&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;AD&#039;&#039;&#039;C &#039;&#039;&#039;S&#039;&#039;&#039;tart &#039;&#039;&#039;C&#039;&#039;&#039;onversion&amp;lt;br /&amp;gt;&lt;br /&gt;
Mit diesem Bit wird ein Messvorgang gestartet. In der frei laufenden&lt;br /&gt;
Betriebsart muss das Bit gesetzt werden, um die kontinuierliche&lt;br /&gt;
Messung zu aktivieren.&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn das Bit&amp;amp;nbsp; nach dem Setzen des &#039;&#039;&#039;ADEN&#039;&#039;&#039;-Bits zum ersten Mal&lt;br /&gt;
gesetzt wird führt der Controller zuerst eine zusätzliche Wandlung&lt;br /&gt;
und erst dann die eigentliche Wandlung aus. Diese zusätzliche&lt;br /&gt;
Wandlung wird zu Initialisierungszwecken durchgeführt.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Bit bleibt nun so lange auf 1, bis die Umwandlung abgeschlossen&lt;br /&gt;
ist, im Initialisierungsfall entsprechend bis die zweite Umwandlung&lt;br /&gt;
erfolgt ist und geht danach auf 0.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;ADFR&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;AD&#039;&#039;&#039;C &#039;&#039;&#039;Fr&#039;&#039;&#039;ee Running Select&amp;lt;br /&amp;gt;&lt;br /&gt;
Mit diesem Bit wird die Betriebsart eingestellt.&amp;lt;br /&amp;gt;&lt;br /&gt;
Eine logische 1 aktiviert den frei laufenden Modus. Der &#039;&#039;&#039; ADC&#039;&#039;&#039; misst&lt;br /&gt;
nun ständig den ausgewählten Kanal und schreibt den gemessenen&lt;br /&gt;
Wert in das &#039;&#039;&#039; ADC Data Register&#039;&#039;&#039;.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;ADIF&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;AD&#039;&#039;&#039;C &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;F&#039;&#039;&#039;lag&amp;lt;br /&amp;gt;&lt;br /&gt;
Dieses Bit wird vom &#039;&#039;&#039; ADC&#039;&#039;&#039; gesetzt wenn eine Umwandlung erfolgt und das&lt;br /&gt;
&#039;&#039;&#039;ADC Data Register&#039;&#039;&#039; aktualisiert ist.&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn das &#039;&#039;&#039; ADIE&#039;&#039;&#039; Bit sowie das &#039;&#039;&#039; I-Bit&#039;&#039;&#039; im AVR &#039;&#039;&#039; Statusregister&#039;&#039;&#039; gesetzt ist&lt;br /&gt;
wird der &#039;&#039;&#039; ADC Interrupt&#039;&#039;&#039; ausgelöst und die&lt;br /&gt;
Interrupt-Behandlungsroutine aufgerufen..&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Bit wird automatisch gelöscht wenn die&lt;br /&gt;
Interrupt-Behandlungsroutine aufgerufen wird. Es kann jedoch auch&lt;br /&gt;
gelöscht werden, indem ein logisches 1 in das Register geschrieben&lt;br /&gt;
wird (So steht&#039;s in der AVR-Doku).&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;ADIE&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;AD&#039;&#039;&#039;C &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;E&#039;&#039;&#039;nable&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn dieses Bit gesetzt ist und ebenso das &#039;&#039;&#039; I-Bit&#039;&#039;&#039; im Statusregister&lt;br /&gt;
&#039;&#039;&#039;SREG&#039;&#039;&#039;, dann wird der &#039;&#039;&#039; ADC-Interrupt&#039;&#039;&#039; aktiviert.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;ADPS2&amp;lt;br /&amp;gt;&lt;br /&gt;
...&amp;lt;br /&amp;gt;&lt;br /&gt;
ADPS0&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;AD&#039;&#039;&#039;C &#039;&#039;&#039;P&#039;&#039;&#039;rescaler &#039;&#039;&#039;S&#039;&#039;&#039;elect Bits&amp;lt;br /&amp;gt;&lt;br /&gt;
Diese Bits bestimmen den Teilungsfaktor zwischen der Taktfrequenz&lt;br /&gt;
und dem Eingangstakt des &#039;&#039;&#039;ADC&#039;&#039;&#039;.&amp;lt;br /&amp;gt;&lt;br /&gt;
Der &#039;&#039;&#039; ADC&#039;&#039;&#039; benötigt einen eigenen Takt, welchen er sich selber aus der&lt;br /&gt;
CPU-Taktfreqenz erzeugt. Der &#039;&#039;&#039;ADC&#039;&#039;&#039;-Takt sollte zwischen 50 und 200kHz&lt;br /&gt;
sein.&amp;lt;br /&amp;gt;&lt;br /&gt;
Der Vorteiler muss also so eingestellt werden, dass die&lt;br /&gt;
CPU-Taktfrequenz dividiert durch den Teilungsfaktor einen Wert&lt;br /&gt;
zwischen 50-200kHz ergibt.&amp;lt;br /&amp;gt;&lt;br /&gt;
Bei einer CPU-Taktfrequenz von 4MHz beispielsweise rechnen wir&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp; TFmin=CLK/200kHz=4000000/200000=&#039;&#039;&#039;20&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp; TFmax=CLK/50kHz=4000000/50000=&#039;&#039;&#039;80&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Somit kann hier der Teilungsfaktor 32 oder 64 verwendet werden. Im&lt;br /&gt;
Interesse der schnelleren Wandlungszeit werden wir hier den Faktor&lt;br /&gt;
32 einstellen.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ADPS2&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ADPS1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ADPS0&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;Teilungsfaktor&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 8&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 16&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 32&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 64&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 128&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;ADCL&amp;lt;br /&amp;gt;&lt;br /&gt;
ADCH&amp;amp;nbsp;&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;ADC &#039;&#039;&#039;Data Register&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn eine Umwandlung abgeschlossen ist befindet sich der gemessene Wert in&lt;br /&gt;
diesen beiden Registern.&amp;lt;br /&amp;gt;&lt;br /&gt;
Von &#039;&#039;&#039; ADCH&#039;&#039;&#039; werden nur die beiden niederwertigsten Bits verwendet.&amp;lt;br /&amp;gt;&lt;br /&gt;
Es müssen immer beide Register ausgelesen werden und zwar immer in der&lt;br /&gt;
Reihenfolge &#039;&#039;&#039;ADCL&#039;&#039;&#039;, &#039;&#039;&#039;ADCH&#039;&#039;&#039;. Der effektive Messwert ergibt sich dann zu&lt;br /&gt;
&lt;br /&gt;
 x = ADCL + ADCH &amp;lt;&amp;lt; 8  &lt;br /&gt;
&lt;br /&gt;
oder &lt;br /&gt;
 x=ADCW&lt;br /&gt;
&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;ADMUX&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;AD&#039;&#039;&#039;C &#039;&#039;&#039;Mu&#039;&#039;&#039;ltiple&#039;&#039;&#039;x&#039;&#039;&#039;er Select Register&amp;lt;br /&amp;gt;&lt;br /&gt;
Mit diesem Register wird der zu messende Kanal ausgewählt. Beim 90S8535&lt;br /&gt;
kann jeder Pin von Port A als &#039;&#039;&#039;ADC&#039;&#039;&#039;-Eingang verwendet werden (=8 Kanäle).&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Register ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;MUX2&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;MUX1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;MUX0&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;MUX2&amp;lt;br /&amp;gt;&lt;br /&gt;
...&amp;lt;br /&amp;gt;&lt;br /&gt;
MUX0&#039;&#039;&#039;&lt;br /&gt;
| Mit diesem 3 Bits wird der zu messende Kanal bestimmt.&lt;br /&gt;
Es wird einfach die entsprechende Pinnummer des Ports&lt;br /&gt;
eingeschrieben.&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn das Register beschrieben wird, während dem eine Umwandlung&lt;br /&gt;
läuft, so wird zuerst die aktuelle Umwandlung auf dem bisherigen&lt;br /&gt;
Kanal beendet. Dies ist vor allem beim frei laufenden Betrieb zu&lt;br /&gt;
berücksichtigen.&lt;br /&gt;
&lt;br /&gt;
Meine Empfehlung ist deswegen klar diese, dass der frei laufende&lt;br /&gt;
Betrieb nur bei einem einzelnen zu verwendenden Analogeingang&lt;br /&gt;
verwendet werden sollte, wenn man sich Probleme bei der Umschalterei&lt;br /&gt;
ersparen will.&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==== Aktivieren des ADC ====&lt;br /&gt;
&lt;br /&gt;
Um den &#039;&#039;&#039; ADC&#039;&#039;&#039; zu aktivieren müssen wir das &#039;&#039;&#039;ADEN&#039;&#039;&#039;-Bit im &#039;&#039;&#039;ADCSR&#039;&#039;&#039;-Register&lt;br /&gt;
setzen. Im gleichen Schritt legen wir auch gleich die Betriebsart fest. &lt;br /&gt;
&lt;br /&gt;
Ein kleines Beispiel für den &amp;quot;single conversion&amp;quot;-Mode bei einem ATmega169 und Nutzung der internen Referenzspannung (beim &#039;169 1,1V bei anderen AVRs auch 2,56V). D.h. das Eingangssignal darf diese Spannung nicht überschreiten, gegebenenfalls mit Spannungsteiler konditionieren. Ergebnis der Routine ist der ADC-Wert, also 0 für 0-Volt und 1024 für V_ref-Volt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define CHANNELOFFSET 4&lt;br /&gt;
&lt;br /&gt;
uint16_t ReadChannel(uint8_t channel)&lt;br /&gt;
{&lt;br /&gt;
  uint8_t i;&lt;br /&gt;
  uint16_t result;&lt;br /&gt;
  &lt;br /&gt;
  ADCSRA = (1&amp;lt;&amp;lt;ADEN) | (1&amp;lt;&amp;lt;ADPS1) | (1&amp;lt;&amp;lt;ADPS0);    // Frequenzvorteiler setzen auf 8 (1)&lt;br /&gt;
  ADCSRA |= (1&amp;lt;&amp;lt;ADEN);     //  ADC aktivieren (1)&lt;br /&gt;
&lt;br /&gt;
  ADMUX = CHANNELOFFSET+channel; // Kanal waehlen&lt;br /&gt;
  ADMUX |= (1&amp;lt;&amp;lt;REFS1) | (1&amp;lt;&amp;lt;REFS0); // interne Referenzspannung nutzen &lt;br /&gt;
&lt;br /&gt;
  /* nach aktivieren des ADC wird ein &amp;quot;Dummy-Readout&amp;quot; Empfohlen, man liest&lt;br /&gt;
     also einen Wert und verwirft diesen, um den ADC &amp;quot;warmlaufen zu lassen&amp;quot; */&lt;br /&gt;
  ADCSRA |= (1&amp;lt;&amp;lt;ADSC);        // eine ADC-Wandlung &lt;br /&gt;
  while(!(ADCSRA &amp;amp; 0x10));    // auf Abschluss der Konvertierung warten (ADIF-bit)&lt;br /&gt;
        &lt;br /&gt;
  result = 0;&lt;br /&gt;
&lt;br /&gt;
  /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */&lt;br /&gt;
  for(i=0;i&amp;lt;4;i++)&lt;br /&gt;
  {&lt;br /&gt;
	ADCSRA |= (1&amp;lt;&amp;lt;ADSC);        // eine Wandlung &amp;quot;single conversion&amp;quot;&lt;br /&gt;
	while(!(ADCSRA &amp;amp; (1&amp;lt;&amp;lt;ADIF)));    // auf Abschluss der Konvertierung warten (ADIF-bit)&lt;br /&gt;
	result += ADC;		    // Wandlungsergebnisse aufaddieren&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  ADCSRA &amp;amp;= ~(1&amp;lt;&amp;lt;ADEN);      // ADC deaktivieren (2)&lt;br /&gt;
&lt;br /&gt;
  result &amp;gt;&amp;gt;= 2;     // Summe durch vier teilen = arithm. Mittelwert&lt;br /&gt;
&lt;br /&gt;
  return result;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Beispiel wird bei jedem Aufruf der ADC aktiviert und nach der Wandlung wieder abgeschaltet, das spart Strom. Will man dies nicht, verschiebt man die mit (1) gekenntzeichneten Zeilen in eine Funktion adc_init() o.ä. und löscht die mit (2) markierten Zeilen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Wenn wir frei laufend arbeiten wollen setzen wir zusätzlich das &#039;&#039;&#039;ADFR&#039;&#039;&#039;-Bit. Bei&lt;br /&gt;
Bedarf wird auch gleich der Teilungsfaktor eingestellt.&lt;br /&gt;
&lt;br /&gt;
TODO: fix&lt;br /&gt;
&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;&#039;&#039;&#039;// Teilungsfaktor auf 8 und ADC aktivieren&amp;lt;br /&amp;gt;&lt;br /&gt;
// Nicht frei laufend&amp;lt;br /&amp;gt;&lt;br /&gt;
outp ((1&amp;lt;&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um nun eine einzelne Messung, sagen wir mal an Pin 3, durchzuführen schalten wir den Kanal ein, starten die Wandlung und warten, bis der &#039;&#039;&#039;ADC&#039;&#039;&#039; die Beendigung meldet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;&#039;&#039;&#039;outp ((1&amp;lt;&lt;br /&gt;
sbi (ADCSR, ADSC);&amp;lt;br /&amp;gt;&lt;br /&gt;
while (bit_is_set (ADCSR, ADSC)) /* Nur warten */;&amp;lt;br /&amp;gt;&lt;br /&gt;
x = __inw (ADCL);  ODER x=ADCW        // Wert auslesen&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;#FF0000&amp;quot;&amp;gt;Da ich leider bisher noch kein Experimentierboard für&lt;br /&gt;
den 8535 gebastelt habe kann ich euch auch keine erprobte Übung anbieten.&amp;lt;/font&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== DAC (Digital Analog Converter) ==&lt;br /&gt;
&lt;br /&gt;
Mit Hilfe eines &#039;&#039;&#039; DAC&#039;&#039;&#039; können wir nun auch Analogsignale ausgeben. Es gibt hier&lt;br /&gt;
mehrere Verfahren. Wenn wir beim &#039;&#039;&#039; ADC&#039;&#039;&#039; die Möglichkeit haben, mit externen&lt;br /&gt;
Komponenten zu operieren müssen wir bei der &#039;&#039;&#039;DAC&#039;&#039;&#039;-Wandlung mit dem auskommen, was&lt;br /&gt;
der Controller selber zu bieten hat.&lt;br /&gt;
&lt;br /&gt;
=== DAC über mehrere digitale Ausgänge ===&lt;br /&gt;
&lt;br /&gt;
Wenn wir an den Ausgängen des Controllers ein entsprechendes&lt;br /&gt;
Widerstandsnetzwerk aufbauen haben wir die Möglichkeit, durch die Ansteuerung&lt;br /&gt;
der Ausgänge über den Widerständen einen Addierer aufzubauen, mit dessen&lt;br /&gt;
Hilfe wir eine dem Zahlenwert proportionale Spannung erzeugen können. Das&lt;br /&gt;
Schaltbild dazu kann etwa so aussehen:&lt;br /&gt;
&lt;br /&gt;
[[Image:DAC R2R.gif]]&lt;br /&gt;
&lt;br /&gt;
Es sollten selbstverständlich möglichst genaue Widerstände verwendet&lt;br /&gt;
werden, also nicht unbedingt solche mit einer Toleranz von 10% oder mehr.&lt;br /&gt;
Weiterhin empfiehlt es sich, je nach Anwendung den Ausgangsstrom über einen&lt;br /&gt;
Operationsverstärker zu verstärken.&lt;br /&gt;
&lt;br /&gt;
=== PWM (Pulsweitenmodulation) ===&lt;br /&gt;
&lt;br /&gt;
Wir kommen nun zu einem Thema, welches in aller Munde ist, aber viele&lt;br /&gt;
Anwender verstehen nicht ganz, wie &#039;&#039;&#039; PWM&#039;&#039;&#039; eigentlich funktioniert.&lt;br /&gt;
&lt;br /&gt;
Wie wir alle wissen ist ein Mikrocontroller ein rein digitales Bauteil.&lt;br /&gt;
Definieren wir einen Pin als Ausgang, dann können wir diesen Ausgang entweder&lt;br /&gt;
auf HIGH setzen worauf am Ausgang die Versorgungsspannung &#039;&#039;&#039; Vcc&#039;&#039;&#039; anliegt, oder aber&lt;br /&gt;
wir setzen den Ausgang auf LOW wonach dann &#039;&#039;&#039; 0V&#039;&#039;&#039; am Ausgang liegt.&amp;lt;br /&amp;gt;&lt;br /&gt;
Was passiert aber nun, wenn wir periodisch mit einer festen Frequenz zwischen&lt;br /&gt;
HIGH und LOW umschalten?&amp;lt;br /&amp;gt;&lt;br /&gt;
Richtig, wir erhalten eine Rechteckspannung, wie die folgende Abbildung zeigt:&lt;br /&gt;
&lt;br /&gt;
[[Image:PWM Theorie 1.gif]]&lt;br /&gt;
&lt;br /&gt;
Diese Rechteckspannung hat nun einen geometrischen Mittelwert, der je nach Pulsbreite&lt;br /&gt;
kleiner oder grösser ist.&lt;br /&gt;
&lt;br /&gt;
[[Image:PWM Theorie 2.gif]]&lt;br /&gt;
&lt;br /&gt;
Wenn wir nun diese pulsierende Ausgangsspannung noch über ein&lt;br /&gt;
RC-Glied filtern dann haben wir schon eine entsprechende Gleichspannung erzeugt.&lt;br /&gt;
&lt;br /&gt;
Mit den AVR&#039;s können wir direkt &#039;&#039;&#039;PWM&#039;&#039;&#039;-Signale erzeugen. Dazu&lt;br /&gt;
dient der 16-Bit Zähler, welcher im sogenannten &#039;&#039;&#039;PWM&#039;&#039;&#039;-Modus betrieben werden&lt;br /&gt;
kann.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| Hinweis:&lt;br /&gt;
| In den folgenden Überlegungen wird als Controller der&lt;br /&gt;
90S2313 vorausgesetzt. Die Theorie ist allerdings bei anderen&lt;br /&gt;
AVR-Controllern vergleichbar, die Pinbelegung allerdings nicht unbedingt.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Um den &#039;&#039;&#039;PWM&#039;&#039;&#039;-Modus zu aktivieren müssen im Timer/Counter1 Control&lt;br /&gt;
Register A &#039;&#039;&#039;TCCR1A&#039;&#039;&#039; die Pulsweiten-Modulatorbits &#039;&#039;&#039; PWM10&#039;&#039;&#039; bzw. &#039;&#039;&#039; PWM11&#039;&#039;&#039; entsprechend&lt;br /&gt;
nachfolgender Tabelle gesetzt werden:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;PWM11&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;PWM10&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Bedeutung&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| PWM-Modus des Timers ist nicht aktiv.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| 8-Bit PWM.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| 9-Bit PWM.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| 10-Bit PWM.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Der Timer/Counter zählt nun permanent von 0 bis zur Obergrenze&lt;br /&gt;
und wieder zurück, er wird also als sogenannter Auf-/Ab Zähler betrieben. Die&lt;br /&gt;
Obergrenze hängt davon ab, ob wir mit 8, 9 oder 10-Bit PWM arbeiten wollen:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;Auflösung&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;Obergrenze&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Frequenz&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 8&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 255&lt;br /&gt;
| f&amp;lt;sub&amp;gt;TC1&amp;lt;/sub&amp;gt; / 510&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 9&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 511&lt;br /&gt;
| f&amp;lt;sub&amp;gt;TC1&amp;lt;/sub&amp;gt; / 1022&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 10&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1023&lt;br /&gt;
| f&amp;lt;sub&amp;gt;TC1&amp;lt;/sub&amp;gt; / 2046&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Zusätzlich muss mit den Bits &#039;&#039;&#039; COM1A1&#039;&#039;&#039; und &#039;&#039;&#039; COM1A0&#039;&#039;&#039; desselben&lt;br /&gt;
Registers die gewünschte Ausgabeart des Signals definiert werden:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;COM1A1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;COM1A0&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Bedeutung&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Keine Wirkung, Pin wird nicht geschaltet.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Keine Wirkung, Pin wird nicht geschaltet.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Nicht invertierende PWM.&amp;lt;br /&amp;gt;&lt;br /&gt;
Der Ausgangspin wird gelöscht beim Hochzählen und gesetzt beim&lt;br /&gt;
Herunterzählen.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Invertierende PWM.&amp;lt;br /&amp;gt;&lt;br /&gt;
Der Ausgangspin wird gelöscht beim Herunterzählen und gesetzt beim&lt;br /&gt;
Hochzählen.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Der entsprechende Befehl um beispielsweise den Timer/Counter als&lt;br /&gt;
nicht invertierenden 10-Bit PWM zu verwenden heisst dann:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- TODO: fix --&amp;gt;&lt;br /&gt;
&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;&#039;&#039;&#039;outp&lt;br /&gt;
((1&amp;lt;&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit der Timer/Counter überhaupt läuft müssen wir im Control&lt;br /&gt;
Register B &#039;&#039;&#039;TCCR1B&#039;&#039;&#039; noch den gewünschten Takt (Vorzähler) einstellen, und&lt;br /&gt;
somit auch die Frequenz des &#039;&#039;&#039;PWM&#039;&#039;&#039;-Signals bestimmen.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;CS12&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;CS11&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;CS10&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Bedeutung&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Stop. Der Timer/Counter wird gestoppt.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| CK&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| CK / 8&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| CK / 64&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| CK / 256&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| CK / 1024&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Externer Pin 1, negative Flanke&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Externer Pin 1, positive Flanke&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Also, um einen Takt von CK / 1024 zu generieren verwenden wir&lt;br /&gt;
folgenden Befehl:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- TODO: fix, irgenwas ist bei der &amp;quot;wiki-konvertierung&amp;quot; wohl schief gelaufen --&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;outp ((1&amp;lt;&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Jetzt muss nur noch der Vergleichswert festgelegt werden. Diesen&lt;br /&gt;
schreiben wir in das 16-Bit Timer/Counter Output Compare Register &#039;&#039;&#039;OCR1A&#039;&#039;&#039;.&lt;br /&gt;
Wir können dazu den von der Bibliothek zur Verfügung gestellten Befehl zum&lt;br /&gt;
Schreiben von 16-Bit Registern verwenden, als Portadresse wird das Low-Byte des&lt;br /&gt;
Ports verwendet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- &amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;&#039;&#039;&#039;__outw (xxx, OCR1AL);&#039;&#039;&#039;&amp;lt;/font&amp;gt; --&amp;gt;&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
OCR1A = xxx;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die folgende Grafik soll den Zusammenhang zwischen dem&lt;br /&gt;
Vergleichswert und dem generierten &#039;&#039;&#039;PWM&#039;&#039;&#039;-Signal aufzeigen.&lt;br /&gt;
&lt;br /&gt;
[[Image:PWM Theorie 3.gif]]&lt;br /&gt;
&lt;br /&gt;
[[Image:PWM Theorie 4.gif]]&lt;br /&gt;
&lt;br /&gt;
Ach ja, fast hätte ich&#039;s vergessen. Das generierte &#039;&#039;&#039;PWM&#039;&#039;&#039;-Signal&lt;br /&gt;
wird am Output Compare Pin &#039;&#039;&#039; OC1&#039;&#039;&#039; des Timers ausgegeben und leider können wir&lt;br /&gt;
deshalb auch nur ein einzelnes &#039;&#039;&#039;PWM&#039;&#039;&#039;-Signal mit dieser Methode generieren.&lt;br /&gt;
&lt;br /&gt;
= Die Timer/Counter des AVR =&lt;br /&gt;
&lt;br /&gt;
Die heutigen Mikrocontroller und insbesondere die RISC-AVR&#039;s sind für viele&lt;br /&gt;
Steuerungsaufgaben natürlich viel zu schnell. Wenn wir beispielsweise eine LED&lt;br /&gt;
oder Lampe blinken lassen wollen können wir selbstverständlich nicht die&lt;br /&gt;
CPU-Frequenz verwenden da ja dann nichts mehr vom Blinken zu bemerken wäre.&lt;br /&gt;
&lt;br /&gt;
Wir brauchen also eine Möglichkeit, die Taktfrequenz auf vernünftige Werte&lt;br /&gt;
herunter zu brechen. Selbstverständlich sollte die resultierende Frequenz dann&lt;br /&gt;
auch noch einigermassen genau und stabil sein.&lt;br /&gt;
&lt;br /&gt;
Hier kommen die im AVR vorhandenen Timer/Counter zum Einsatz.&lt;br /&gt;
&lt;br /&gt;
Ein anderes Anwendungsgebiet ist die Zählung von Signalen, welche über&lt;br /&gt;
einen I/O-Pin zugeführt werden können.&lt;br /&gt;
&lt;br /&gt;
Die folgenden Ausführungen beziehen sich auch den AT90S2313. Für andere&lt;br /&gt;
Modelltypen müsst ihr euch die allenfalls notwendigen Anpassungen aus den&lt;br /&gt;
Datenblättern der entsprechenden Controller raus lesen.&lt;br /&gt;
&lt;br /&gt;
Wir unterscheiden grundsätzlich zwischen 8-Bit Timern, welche eine&lt;br /&gt;
Auflösung von 256 aufweisen und 16-Bit Timern mit (logischerweise) einer&lt;br /&gt;
Auflösung von 65536.&lt;br /&gt;
&lt;br /&gt;
Als Eingangstakt für die Timer/Counter kann entweder die CPU-Taktfrequenz,&lt;br /&gt;
der Vorteiler-Ausgang oder ein an einen I/O-Pin angelegtes Signal verwendet&lt;br /&gt;
werden. Wenn ein externes Signal verwendet wird, so darf dessen Frequenz nicht&lt;br /&gt;
höher sein als die Hälfte des CPU-Taktes.&lt;br /&gt;
&lt;br /&gt;
=== Der Vorzähler (Prescaler) ===&lt;br /&gt;
&lt;br /&gt;
Beide Timer/Counter werden im Timerbetrieb über den gleichen Vorzähler&lt;br /&gt;
versorgt.&amp;lt;br /&amp;gt;&lt;br /&gt;
Der Vorzähler dient dazu, den CPU-Takt vorerst mal runter zu brechen auf eine&lt;br /&gt;
wählbare Teilung. Die so geteilte Frequenz wird den Eingängen der Timer&lt;br /&gt;
zugeführt.&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn wir mit einer einem CPU-Takt von 4 MHz arbeiten und den Vorteiler auf 1024&lt;br /&gt;
einstellen wird also der Timer mit einer Frequenz von 4 MHz / 1024, also mit ca.&lt;br /&gt;
4 kHz versorgt. Wenn also der Timer läuft, so wird das Daten- bzw.&lt;br /&gt;
Zählregister mit dieser Frequenz inkrementiert.&lt;br /&gt;
&lt;br /&gt;
== 8-Bit Timer/Counter ==&lt;br /&gt;
&lt;br /&gt;
Alle AVR-Modelle weisen mindestens einen, teilweise sogar zwei 8-Bit Timer&lt;br /&gt;
auf.&lt;br /&gt;
&lt;br /&gt;
Der 8-Bit Timer wird über folgende Register angesprochen:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;TCCR0&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;T&#039;&#039;&#039;imer/&#039;&#039;&#039;C&#039;&#039;&#039;ounter &#039;&#039;&#039;C&#039;&#039;&#039;ontrol &#039;&#039;&#039;R&#039;&#039;&#039;egister&lt;br /&gt;
Timer &#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
In diesem Register stellen wir ein, wie wir den Timer/Counter verwenden möchten.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Register ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;CS02&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;CS01&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;CS00&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;CS02&amp;lt;br /&amp;gt;&lt;br /&gt;
CS01&amp;lt;br /&amp;gt;&lt;br /&gt;
CS00&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;C&#039;&#039;&#039;lock &#039;&#039;&#039;S&#039;&#039;&#039;elect Bits&amp;lt;br /&amp;gt;&lt;br /&gt;
Diese 3 Bits bestimmen die Quelle für den Timer/Counter:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | CS02&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | CS01&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | CS00&lt;br /&gt;
| Resultat&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Stopp, Der Timer/Counter wird angehalten.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| CPU-Takt&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| CPU-Takt / 8&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| CPU-Takt / 64&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| CPU-Takt / 256&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| CPU-Takt / 1024&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Externer Pin &#039;&#039;&#039;TO&#039;&#039;&#039;, fallende Flanke&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Externer Pin &#039;&#039;&#039;TO&#039;&#039;&#039;, steigende Flanke&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Wenn als Quelle der externe Pin &#039;&#039;&#039;TO&#039;&#039;&#039; verwendet wird, so wird&lt;br /&gt;
ein Flankenwechsel auch erkannt, wenn der Pin &#039;&#039;&#039;TO&#039;&#039;&#039; als Ausgang&lt;br /&gt;
geschaltet ist.&lt;br /&gt;
|}&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;TCNT0&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;T&#039;&#039;&#039;imer/&#039;&#039;&#039;C&#039;&#039;&#039;ou&#039;&#039;&#039;nt&#039;&#039;&#039;er Daten Register Timer &#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Dieses ist als 8-Bit Aufwärtszähler mit Schreib- und Lesezugriff&lt;br /&gt;
realisiert. Wenn der Zähler den Wert 255 erreicht hat beginnt er beim&lt;br /&gt;
nächsten Zyklus wieder bei 0.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;MSB&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;LSB&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Um nun also den Timer0 in Betrieb zu setzen und ihn mit einer Frequenz von 1/1024-tel des CPU-Taktes zählen zu lassen schreiben wir die folgende&lt;br /&gt;
Befehlszeile:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- TODO: fix --&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;outp ((1&amp;lt;&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Der Zähler zählt nun von 0 an aufwärts bis 255 um dann wieder&lt;br /&gt;
bei 0 zu beginnen. Bei jedem Überlauf von 255 auf 0 wird das Timer Overflow&lt;br /&gt;
Flag &#039;&#039;&#039;[http://en.wikipedia.org#TOV0 TOV0]&#039;&#039;&#039; im Timer Interrupt Flag &#039;&#039;&#039;[http://en.wikipedia.org#TIFR TIFR]&#039;&#039;&#039;&lt;br /&gt;
Register gesetzt und, falls so konfiguriert, ein entsprechender Interrupt&lt;br /&gt;
ausgelöst.&lt;br /&gt;
&lt;br /&gt;
== 16-Bit Timer/Counter ==&lt;br /&gt;
&lt;br /&gt;
Viele AVR-Modelle besitzen ausser den 8-Bit Timers auch einen oder sogar zwei&lt;br /&gt;
(einige ATMega-Modelle) 16-Bit Timer.&lt;br /&gt;
&lt;br /&gt;
Die 16-Bit Timer/Counter sind wesentlich komplexer aufgebaut als die 8-Bit&lt;br /&gt;
Timer/Counter, bieten dafür aber auch viel mehr Möglichkeiten, als da sind:&lt;br /&gt;
&lt;br /&gt;
* [http://en.wikipedia.org#Die%20PWM-Betriebsart Erzeugung eines pulsweitenmodulierten Ausgangssignals] ([http://en.wikipedia.org/Analoge_Ein_Ausgabe.htm#PWM PWM]).&lt;br /&gt;
* [http://en.wikipedia.org#Vergleichswert-%DCberpr%FCfung Vergleichswert-Überprüfung] mit Erzeugung eines Ausgangssignals (Output Compare Match).&lt;br /&gt;
* [http://en.wikipedia.org#Einfangen%20eines%20Eingangssignals Einfangen eines Eingangssignals] mit Speicherung des aktuellen Zählerwertes (Input Capturing), mit zuschaltbarer Rauschunterdrückung (Noise Filtering).&lt;br /&gt;
&lt;br /&gt;
Folgende Register sind dem Timer/Counter 1 zugeordnet:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;TCCR1A&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;T&#039;&#039;&#039;imer/&#039;&#039;&#039;C&#039;&#039;&#039;ounter &#039;&#039;&#039;C&#039;&#039;&#039;ontrol &#039;&#039;&#039;R&#039;&#039;&#039;egister&lt;br /&gt;
&#039;&#039;&#039;A&#039;&#039;&#039; Timer &#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
In diesem und dem folgenden Register stellen wir ein, wie wir den Timer/Counter verwenden möchten.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Register ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;COM1A1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;COM1A0&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;PWM11&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;PWM10&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;COM1A1&amp;lt;br /&amp;gt;&lt;br /&gt;
COM1A0&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Co&#039;&#039;&#039;mpare &#039;&#039;&#039;M&#039;&#039;&#039;atch Control Bits&amp;lt;br /&amp;gt;&lt;br /&gt;
Diese 2 Bits bestimmen die Aktion, welche am Output-Pin &#039;&#039;&#039;OC1&#039;&#039;&#039;&lt;br /&gt;
ausgeführt werden soll, wenn der Wert des Datenregisters des Timer/Counter&lt;br /&gt;
1 den Wert des Vergleichsregisters erreicht, also ein so genannter&lt;br /&gt;
Compare Match auftritt.&amp;lt;br /&amp;gt;&lt;br /&gt;
Der Pin &#039;&#039;&#039;OC1&#039;&#039;&#039; (&#039;&#039;&#039;PB3&#039;&#039;&#039; beim 2313) muss mit dem&lt;br /&gt;
Datenrichtungsregister als Ausgang konfiguriert werden.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | COM1A1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | COM1A0&lt;br /&gt;
| Resultat&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Output-Pin &#039;&#039;&#039;OC1&#039;&#039;&#039; wird nicht angesteuert.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Das Signal am Pin &#039;&#039;&#039;OC1&#039;&#039;&#039; wird invertiert&lt;br /&gt;
(Toggle).&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Der Output Pin &#039;&#039;&#039;OC1&#039;&#039;&#039; wird auf 0 gesetzt.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Der Output Pin &#039;&#039;&#039;OC1&#039;&#039;&#039; wird auf 1 gesetzt.&lt;br /&gt;
|}&lt;br /&gt;
|- &lt;br /&gt;
| &lt;br /&gt;
| In der PWM-Betriebsart haben diese Bits eine andere&lt;br /&gt;
Funktion.&amp;lt;br /&amp;gt;&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | COM1A1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | COM1A0&lt;br /&gt;
| Resultat&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Output-Pin &#039;&#039;&#039;OC1&#039;&#039;&#039; wird nicht angesteuert.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Output-Pin &#039;&#039;&#039;OC1&#039;&#039;&#039; wird nicht angesteuert.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Wird beim Hochzählen der Wert im&lt;br /&gt;
Vergleichsregister erreicht so wird der Pin &#039;&#039;&#039;OC1&#039;&#039;&#039; auf 0&lt;br /&gt;
gesetzt.&amp;lt;br /&amp;gt;&lt;br /&gt;
Wird beim Herunterzählen der Wert im Vergleichsregister&lt;br /&gt;
erreicht so wird der Pin auf 1 gesetzt.&amp;lt;br /&amp;gt;&lt;br /&gt;
Man nennt dies nicht invertierende PWM.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Wird beim Hochzählen der Wert im&lt;br /&gt;
Vergleichsregister erreicht so wird der Pin &#039;&#039;&#039;OC1&#039;&#039;&#039; auf 1&lt;br /&gt;
gesetzt.&amp;lt;br /&amp;gt;&lt;br /&gt;
Wird beim Herunterzählen der Wert im Vergleichsregister&lt;br /&gt;
erreicht so wird der Pin auf 0 gesetzt.&amp;lt;br /&amp;gt;&lt;br /&gt;
Man nennt dies invertierende PWM.&lt;br /&gt;
|}&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;PWM11&#039;&#039;&#039;&amp;lt;br /&amp;gt;&#039;&#039;&#039;PWM10&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;PWM&#039;&#039;&#039; Mode Select Bits&amp;lt;br /&amp;gt;&lt;br /&gt;
Mit diesen 2 Bits wird die PWM-Betriebsart des Timer/Counter 1&lt;br /&gt;
gesteuert.&amp;lt;br /&amp;gt;&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | PWM11&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | PWM10&lt;br /&gt;
| Resultat&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Die PWM-Betriebsart ist nicht aktiviert. Timer/Counter&lt;br /&gt;
1 arbeitet als normaler Timer bzw. Zähler.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| 8-Bit PWM Betriebsart aktivieren.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| 9-Bit PWM Betriebsart aktivieren.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| 10-Bit PWM Betriebsart aktivieren.&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;TCCR1B&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;T&#039;&#039;&#039;imer/&#039;&#039;&#039;C&#039;&#039;&#039;ounter &#039;&#039;&#039;C&#039;&#039;&#039;ontrol &#039;&#039;&#039;R&#039;&#039;&#039;egister &#039;&#039;&#039;B&#039;&#039;&#039;&lt;br /&gt;
Timer &#039;&#039;&#039;1&amp;lt;br /&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ICNC1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ICES1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;CTC1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;CS12&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;CS11&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;CS10&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;ICNC1&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;I&#039;&#039;&#039;nput &#039;&#039;&#039;C&#039;&#039;&#039;apture &#039;&#039;&#039;N&#039;&#039;&#039;oise &#039;&#039;&#039;C&#039;&#039;&#039;anceler&lt;br /&gt;
(4 CKs) Timer/Counter 1&amp;lt;br /&amp;gt;&lt;br /&gt;
oder auf Deutsch Rauschunterdrückung des Eingangssignals.&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn dieses Bit gesetzt ist und mit dem Input Capture Signal&lt;br /&gt;
gearbeitet wird so werden nach der Triggerung des Signals mit der&lt;br /&gt;
entsprechenden Flanke (steigend oder fallend) am Input Capture Pin &#039;&#039;&#039;ICP&#039;&#039;&#039;&lt;br /&gt;
jeweils 4 Messungen mit der CPU-Frequenz des Eingangssignals&lt;br /&gt;
abgefragt. Nur dann, wenn alle 4 Messungen den gleichen Zustand&lt;br /&gt;
aufweisen gilt das Signal als erkannt.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;ICES1&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;I&#039;&#039;&#039;nput &#039;&#039;&#039;C&#039;&#039;&#039;apture &#039;&#039;&#039;E&#039;&#039;&#039;dge &#039;&#039;&#039;S&#039;&#039;&#039;elect&lt;br /&gt;
Timer/Counter &#039;&#039;&#039;1&amp;lt;br /&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Mit diesem Bit wird bestimmt, ob die steigende (&#039;&#039;&#039;ICES1&#039;&#039;&#039;=1)&lt;br /&gt;
oder fallende (&#039;&#039;&#039;ICES1&#039;&#039;&#039;=0) Flanke zur Auswertung des Input&lt;br /&gt;
Capture Signals an Pin &#039;&#039;&#039;ICP&#039;&#039;&#039; heran gezogen wird.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;CTC1&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;C&#039;&#039;&#039;lear &#039;&#039;&#039;T&#039;&#039;&#039;imer/&#039;&#039;&#039;C&#039;&#039;&#039;ounter&lt;br /&gt;
on Compare Match Timer/Counter &#039;&#039;&#039;1&amp;lt;br /&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Wenn dieses Bit gesetzt ist so wird nach einer Übereinstimmung&lt;br /&gt;
des Datenregisters &#039;&#039;&#039;TCNT1H&#039;&#039;&#039;/&#039;&#039;&#039;TCNT1L&#039;&#039;&#039; mit dem&lt;br /&gt;
Vergleichswert in &#039;&#039;&#039;OCR1H&#039;&#039;&#039;/&#039;&#039;&#039;OCR1L&#039;&#039;&#039; das Datenregister &#039;&#039;&#039;TCNT1H&#039;&#039;&#039;/&#039;&#039;&#039;TCNT1L&#039;&#039;&#039;&lt;br /&gt;
auf 0 gesetzt.&amp;lt;br /&amp;gt;&lt;br /&gt;
Da die Übereinstimmung im Takt nach dem Vergleich behandelt wird&lt;br /&gt;
ergibt sich je nach eingestelltem Vorzähler ein etwas anderes&lt;br /&gt;
Zählverhalten:&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn der Vorteiler auf 1 gestellt ist und C der jeweilige&lt;br /&gt;
Zählerwert ist, dann nimmt das Datenregister, im CPU-Takt&lt;br /&gt;
betrachtet, folgende Werte an:&amp;lt;br /&amp;gt;&lt;br /&gt;
... | C-2 | C-1 | C | 0 | 1 |...&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn der Vorteiler z.B. auf 8 eingestellt ist, dann nimmt das&lt;br /&gt;
Datenregister folgende Werte an:&amp;lt;br /&amp;gt;&lt;br /&gt;
... | C-2, C-2, C-2, C-2, C-2, C-2, C-2, C-2 | C-1, C-1, C-1, C-1,&lt;br /&gt;
C-1, C-1, C-1, C-1 | C, 0, 0, 0, 0, 0, 0, 0 |...&amp;lt;br /&amp;gt;&lt;br /&gt;
In der PWM-Betriebsart hat dieses Bit keine Funktion.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;CS12&amp;lt;br /&amp;gt;&lt;br /&gt;
CS11&amp;lt;br /&amp;gt;&lt;br /&gt;
CS10&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;C&#039;&#039;&#039;lock &#039;&#039;&#039;S&#039;&#039;&#039;elect Bits&amp;lt;br /&amp;gt;&lt;br /&gt;
Diese 3 Bits bestimmen die Quelle für den Timer/Counter:&amp;lt;br /&amp;gt;&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | CS12&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | CS11&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | CS10&lt;br /&gt;
| Resultat&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Stopp, Der Timer/Counter wird angehalten.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| CPU-Takt&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| CPU-Takt / 8&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| CPU-Takt / 64&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| CPU-Takt / 256&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| CPU-Takt / 1024&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Externer Pin TO, fallende Flanke&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Externer Pin T0, steigende Flanke&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Wenn als Quelle der externe Pin T0 verwendet wird, so wird ein&lt;br /&gt;
Flankenwechsel auch erkannt, wenn der Pin T0 als Ausgang geschaltet&lt;br /&gt;
ist.&lt;br /&gt;
|}&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;TCNT1H&amp;lt;br /&amp;gt;&lt;br /&gt;
TCNT1L&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;T&#039;&#039;&#039;imer/&#039;&#039;&#039;C&#039;&#039;&#039;ou&#039;&#039;&#039;nt&#039;&#039;&#039;er Daten Register Timer/Counter&lt;br /&gt;
&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Dieses ist als 16-Bit Aufwärtszähler mit Schreib- und Lesezugriff&lt;br /&gt;
realisiert. Wenn der Zähler den Wert 65535 erreicht hat beginnt er beim&lt;br /&gt;
nächsten Zyklus wieder bei 0.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;MSB&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;TCNT1H&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;LSB&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;TCNT1L&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
In der PWM-Betriebsart wird das Register als Auf/Ab-Zähler verwendet,&lt;br /&gt;
d.h. der Wert steigt zuerst von 0 bis er den Überlauf von 65535 auf 0&lt;br /&gt;
erreicht hat. Dann zählt das Register rückwärts wiederum bis 0.&lt;br /&gt;
&lt;br /&gt;
Zum Auslesen des Registers wird von der CPU ein internes TEMP-Register&lt;br /&gt;
verwendet. Das gleiche Register wird auch verwendet, wenn auf &#039;&#039;&#039;OCR1&#039;&#039;&#039;&lt;br /&gt;
oder &#039;&#039;&#039;ICR1&#039;&#039;&#039; zugegriffen wird.&amp;lt;br /&amp;gt;&lt;br /&gt;
Deshalb müssen vor dem Zugriff auf eines dieser Register alle Interrupts&lt;br /&gt;
gesperrt werden, weil sonst die Möglichkeit des gleichzeitigen Zugriffs&lt;br /&gt;
auf das Temporärregister gegeben ist, was natürlich zu fehlerhaftem&lt;br /&gt;
Verhalten des Programms führt.. Zudem muss zuerst &#039;&#039;&#039;TCNT1L&#039;&#039;&#039; und erst&lt;br /&gt;
danach &#039;&#039;&#039;TCNT1H&#039;&#039;&#039; ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Wenn in das Register geschrieben werden soll müssen ebenfalls alle&lt;br /&gt;
Interrrupts gesperrt werden. Dann muss zuerst das &#039;&#039;&#039;TCNT1H&#039;&#039;&#039;-Register&lt;br /&gt;
und erst danach das &#039;&#039;&#039;TCNT1L&#039;&#039;&#039;-Register geschrieben werden, also genau&lt;br /&gt;
die umgekehrte Reihenfolge wie beim Lesen des Registers.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;OCR1H&amp;lt;br /&amp;gt;&lt;br /&gt;
OCR1L&#039;&#039;&#039;&lt;br /&gt;
| Timer/Counter &#039;&#039;&#039;O&#039;&#039;&#039;utput &#039;&#039;&#039;C&#039;&#039;&#039;ompare &#039;&#039;&#039;R&#039;&#039;&#039;egister&lt;br /&gt;
Timer/Counter &#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;MSB&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;OCR1H&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;LSB&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;OCR1L&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Der Wert im Output Compare Register wird ständig mit dem aktuellen&lt;br /&gt;
Wert im Datenregister TCNT1H/TCNT1L verglichen. Stimmen die beiden Werte&lt;br /&gt;
überein so wird ein sogenannter Output Compare Match ausgelöst. Die&lt;br /&gt;
entsprechenden Aktionen werden über die Timer/Counter 1 Control und&lt;br /&gt;
Status Register eingestellt..&lt;br /&gt;
&lt;br /&gt;
Zum Auslesen des Registers wird von der CPU ein internes TEMP-Register&lt;br /&gt;
verwendet. Das gleiche Register wird auch verwendet, wenn auf &#039;&#039;&#039;OCR1&#039;&#039;&#039;&lt;br /&gt;
oder &#039;&#039;&#039;ICR1&#039;&#039;&#039; zugegriffen wird.&amp;lt;br /&amp;gt;&lt;br /&gt;
Deshalb müssen vor dem Zugriff auf eines dieser Register alle Interrupts&lt;br /&gt;
gesperrt werden, weil sonst die Möglichkeit des gleichzeitigen Zugriffs&lt;br /&gt;
auf das Temporärregister gegeben ist, was natürlich zu fehlerhaftem&lt;br /&gt;
Verhalten des Programms führt.. Zudem muss zuerst &#039;&#039;&#039;TCNT1L&#039;&#039;&#039; und erst&lt;br /&gt;
danach &#039;&#039;&#039;TCNT1H&#039;&#039;&#039; ausgelesen werden.&lt;br /&gt;
&lt;br /&gt;
Wenn in das Register geschrieben werden soll müssen ebenfalls alle&lt;br /&gt;
Interrrupts gesperrt werden. Dann muss zuerst das &#039;&#039;&#039;TCNT1H&#039;&#039;&#039;-Register&lt;br /&gt;
und erst danach das &#039;&#039;&#039;TCNT1L&#039;&#039;&#039;-Register geschrieben werden, also genau&lt;br /&gt;
die umgekehrte Reihenfolge wie beim Lesen des Registers.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;ICR1&#039;&#039;&#039;&#039;&#039;&#039;H&amp;lt;br /&amp;gt;&lt;br /&gt;
ICR1L&#039;&#039;&#039;&lt;br /&gt;
| Timer/Counter &#039;&#039;&#039;I&#039;&#039;&#039;nput &#039;&#039;&#039;C&#039;&#039;&#039;apture &#039;&#039;&#039;R&#039;&#039;&#039;egister&lt;br /&gt;
Timer/Counter &#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;MSB&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ICR1&#039;&#039;&#039;&#039;&#039;&#039;H&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;LSB&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ICR1&#039;&#039;&#039;&#039;&#039;&#039;L&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &amp;amp;nbsp;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Das Input Capture Register ist ein 16-Bit Register mit Lesezugriff. Es&lt;br /&gt;
kann nicht beschrieben werden.&lt;br /&gt;
&lt;br /&gt;
Wenn am Input Capture Pin &#039;&#039;&#039;ICP&#039;&#039;&#039; die gemäss Einstellungen im &#039;&#039;&#039;TCCR1B&#039;&#039;&#039;&lt;br /&gt;
definierte Flanke erkannt wird so wird der aktuelle Inhalt des&lt;br /&gt;
Datenregisters &#039;&#039;&#039;TCNT1H&#039;&#039;&#039;/&#039;&#039;&#039;TCNT1L&#039;&#039;&#039; sofort in dieses Register&lt;br /&gt;
kopiert und das Input Capture Flag &#039;&#039;&#039;ICF1&#039;&#039;&#039; im Timer Interrupt Flag&lt;br /&gt;
Register &#039;&#039;&#039;TIFR&#039;&#039;&#039; gesetzt.&lt;br /&gt;
&lt;br /&gt;
Wie bereits oben erwähnt müssen vor dem Zugriff auf dieses Register&lt;br /&gt;
alle Interrupts gesperrt werden. Zudem müssen Low- und Highbyte des&lt;br /&gt;
Registers in der richtigen Reihenfolge bearbeitet werden:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| Lesen:&lt;br /&gt;
| &#039;&#039;&#039;ICR1L&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;ICR1H&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| Schreiben:&lt;br /&gt;
| &#039;&#039;&#039;ICR1H&#039;&#039;&#039; -&amp;gt; &#039;&#039;&#039;ICR1L&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Die PWM-Betriebsart ===&lt;br /&gt;
&lt;br /&gt;
Wenn der Timer/Counter 1 in der PWM-Betriebsart betrieben wird so bilden das&lt;br /&gt;
Datenregister &#039;&#039;&#039;TCNT1H&#039;&#039;&#039;/&#039;&#039;&#039;TCNT1L&#039;&#039;&#039; und das Vergleichsregister &#039;&#039;&#039;OCR1H&#039;&#039;&#039;/&#039;&#039;&#039;OCR1L&#039;&#039;&#039;&lt;br /&gt;
einen 8-, 9- oder 10-Bit, frei laufenden PWM-Modulator, welcher als PWM-Signal&lt;br /&gt;
am &#039;&#039;&#039;OC1&#039;&#039;&#039;-Pin (&#039;&#039;&#039;PB3&#039;&#039;&#039; beim 2313) abgegriffen werden kann. Das&lt;br /&gt;
Datenregister &#039;&#039;&#039;TCNT1H&#039;&#039;&#039;/&#039;&#039;&#039;TCNT1L&#039;&#039;&#039; wird dabei als Auf-/Ab-Zähler&lt;br /&gt;
betrieben, welcher von 0 an aufwärts zählt bis zur Obergrenze und danach&lt;br /&gt;
wieder zurück auf 0.&amp;lt;br /&amp;gt;&lt;br /&gt;
Die Obergrenze ergibt sich daraus, ob 8- 9- oder 10-Bit PWM verwendet wird und&lt;br /&gt;
zwar gemäss folgender Tabelle:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;Auflösung&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;Obergrenze&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Frequenz&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 8&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 255&lt;br /&gt;
| f&amp;lt;sub&amp;gt;TC1&amp;lt;/sub&amp;gt; / 510&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 9&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 511&lt;br /&gt;
| f&amp;lt;sub&amp;gt;TC1&amp;lt;/sub&amp;gt; / 1022&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 10&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1023&lt;br /&gt;
| f&amp;lt;sub&amp;gt;TC1&amp;lt;/sub&amp;gt; / 2046&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Wenn nun der Zählerwert im Datenregister den in &#039;&#039;&#039;OCR1H&#039;&#039;&#039;/&#039;&#039;&#039;OCR1L&#039;&#039;&#039;&lt;br /&gt;
gespeicherten Wert erreicht wird der Ausgabepin &#039;&#039;&#039;OC1&#039;&#039;&#039; gesetzt bzw.&lt;br /&gt;
gelöscht, je nach Einstellung von &#039;&#039;&#039;COM1A1&#039;&#039;&#039; und &#039;&#039;&#039;COM1A0&#039;&#039;&#039; im &#039;&#039;&#039;TCCR1A&#039;&#039;&#039;-Register.&lt;br /&gt;
&lt;br /&gt;
Ich habe versucht, die entsprechenden Signale in der folgenden Grafik&lt;br /&gt;
zusammenzufassen&lt;br /&gt;
&lt;br /&gt;
[[Image:PWM Theorie 3.gif]]&lt;br /&gt;
&lt;br /&gt;
[[Image:PWM Theorie 4.gif]]&lt;br /&gt;
&lt;br /&gt;
=== Vergleichswert-Überprüfung ===&lt;br /&gt;
&lt;br /&gt;
Hier wird in ein spezielles Vergleichswertregister (&#039;&#039;&#039;OCR1H&#039;&#039;&#039;/&#039;&#039;&#039;OCR1L&#039;&#039;&#039;)&lt;br /&gt;
ein Wert eingeschrieben, welcher ständig mit dem aktuellen Zählerwert&lt;br /&gt;
verglichen wird.&amp;lt;br /&amp;gt;&lt;br /&gt;
Erreicht der Zähler den in diesem Register eingetragenen Wert so kann ein&lt;br /&gt;
Signal (0 oder 1) am Pin &#039;&#039;&#039;OC1&#039;&#039;&#039; erzeugt und/oder ein Interrupt ausgelöst&lt;br /&gt;
werden.&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
=== Einfangen eines Eingangssignals (Input Capturing) ===&lt;br /&gt;
&lt;br /&gt;
Bei dieser Betriebsart wird an den Input Capturing Pin (ICP) des Controllers&lt;br /&gt;
eine Signalquelle angeschlossen.&amp;lt;br /&amp;gt;&lt;br /&gt;
Nun kann je nach Konfiguration entweder ein Signalwechsel von 0 nach 1&lt;br /&gt;
(steigende Flanke) oder von 1 nach 0 (fallende Flanke) erkannt werden und der zu&lt;br /&gt;
diesem Zeitpunkt aktuelle Zählerstand in ein spezielles Register abgelegt&lt;br /&gt;
werden. Gleichzeitig kann auch ein entsprechender Interrupt ausgelöst werden.&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn die Signalquelle ein starkes Rauschen beinhaltet kann die&lt;br /&gt;
Rauschunterdrückung eingeschaltet werden. Dann wird beim Erkennen der&lt;br /&gt;
konfigurierten Flanke über 4 Taktzyklen das Signal überwacht und nur dann,&lt;br /&gt;
wenn alle 4 Messungen gleich sind wird die entsprechende Aktion ausgelöst.&lt;br /&gt;
&lt;br /&gt;
== Gemeinsame Register ==&lt;br /&gt;
&lt;br /&gt;
Verschiedene Register beinhalten Zustände und Einstellungen, welche sowohl&lt;br /&gt;
für den 8-Bit, als auch für den 16-Bit Timer/Counter in ein und demselben&lt;br /&gt;
Register zu finden sind.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;TIMSK&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;T&#039;&#039;&#039;imer/Counter &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;M&#039;&#039;&#039;a&#039;&#039;&#039;sk&#039;&#039;&#039;&lt;br /&gt;
Register&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;TOIE1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;OCIE1A&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;TICIE&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;TOIE0&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;TOIE1&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;T&#039;&#039;&#039;imer/Counter &#039;&#039;&#039;O&#039;&#039;&#039;verflow &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;E&#039;&#039;&#039;nable&lt;br /&gt;
Timer/Counter &#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn dieses Bit gesetzt ist wird bei einem Überlauf des&lt;br /&gt;
Datenregisters des Timer/Counter 1 ein Timer Overflow 1 Interrupt&lt;br /&gt;
ausgelöst. Das Global&lt;br /&gt;
Enable Interrupt Flag muss selbstverständlich auch gesetzt sein.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;OCIE1A&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;O&#039;&#039;&#039;utput &#039;&#039;&#039;C&#039;&#039;&#039;ompare Match &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;E&#039;&#039;&#039;nable&lt;br /&gt;
Timer/Counter &#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Beim Timer/Counter 1 kann zusätzlich zum Überlauf ein&lt;br /&gt;
Vergleichswert definiert werden.&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn dieses Bit gesetzt ist wird beim Erreichen des Vergleichswertes&lt;br /&gt;
ein Compare Match Interrupt ausgelöst. Das Global&lt;br /&gt;
Enable Interrupt Flag muss selbstverständlich auch gesetzt sein.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;TICIE&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;T&#039;&#039;&#039;imer/Counter &#039;&#039;&#039;I&#039;&#039;&#039;nput &#039;&#039;&#039;C&#039;&#039;&#039;apture &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt&lt;br /&gt;
&#039;&#039;&#039;E&#039;&#039;&#039;nable&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn dieses Bit gesetzt ist wird ein Capture Event Interrupt&lt;br /&gt;
ausgelöst, wenn ein entsprechendes Signalereignis am Pin PD6(ICP)&lt;br /&gt;
auftritt. Das Global&lt;br /&gt;
Enable Interrupt Flag muss selbstverständlich auch gesetzt sein,&lt;br /&gt;
wenn auch ein entsprechender Interrupt ausgelöst werden soll.&amp;lt;font face=&amp;quot;Helvetica&amp;quot; size=&amp;quot;2&amp;quot;&amp;gt;&amp;lt;/font&amp;gt;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;TOIE0&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;T&#039;&#039;&#039;imer/Counter &#039;&#039;&#039;O&#039;&#039;&#039;verflow &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;E&#039;&#039;&#039;nable&lt;br /&gt;
Timer/Counter &#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn dieses Bit gesetzt ist wird bei einem Überlauf des&lt;br /&gt;
Datenregisters des Timer/Counter 0 ein Timer Overflow 0 Interrupt&lt;br /&gt;
ausgelöst. Das Global&lt;br /&gt;
Enable Interrupt Flag muss selbstverständlich auch gesetzt sein.&lt;br /&gt;
|- &lt;br /&gt;
| &lt;br /&gt;
|&lt;br /&gt;
|}&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;TIFR&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;T&#039;&#039;&#039;imer/Counter &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;F&#039;&#039;&#039;lag &#039;&#039;&#039;R&#039;&#039;&#039;egister&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;TOV1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;OCF1A&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ICF1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;TOV0&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;TOV1&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;T&#039;&#039;&#039;imer/Counter &#039;&#039;&#039;O&#039;&#039;&#039;verflow Flag Timer/Counter&lt;br /&gt;
&#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Dieses Bit wird vom Controller gesetzt, wenn beim Timer 1 ein&lt;br /&gt;
Überlauf des Datenregisters stattfindet.&amp;lt;br /&amp;gt;&lt;br /&gt;
In der PWM-Betriebsart wird das Bit gesetzt, wenn die Zählrichtung&lt;br /&gt;
von auf- zu abwärts und umgekehrt geändert wird (Zählerwert = 0).&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Flag wird automatisch gelöscht, wenn der zugehörige&lt;br /&gt;
Interrupt-Vektor aufgerufen wird. Es kann jedoch auch gelöscht&lt;br /&gt;
werden, indem eine logische 1 (!) in das entsprechende Bit&lt;br /&gt;
geschrieben wird.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;OCF1A&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;O&#039;&#039;&#039;utput &#039;&#039;&#039;C&#039;&#039;&#039;ompare &#039;&#039;&#039;F&#039;&#039;&#039;lag&lt;br /&gt;
Timer/Counter &#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Dieses Bit wird gesetzt, wenn der aktuelle Wert des Datenregisters&lt;br /&gt;
von Timer/Counter 1 mit demjenigen im Vergleichsregister &#039;&#039;&#039;OCR1&#039;&#039;&#039;&lt;br /&gt;
übereinstimmt.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Flag wird automatisch gelöscht, wenn der zugehörige&lt;br /&gt;
Interrupt-Vektor aufgerufen wird. Es kann jedoch auch gelöscht&lt;br /&gt;
werden, indem eine logische 1 (!) in das entsprechende Bit&lt;br /&gt;
geschrieben wird.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;ICF1&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;I&#039;&#039;&#039;nput &#039;&#039;&#039;C&#039;&#039;&#039;apture &#039;&#039;&#039;F&#039;&#039;&#039;lag Timer/Counter &#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Dieses Bit wird gesetzt, wenn ein Capture-Ereignis aufgetreten ist,&lt;br /&gt;
welches anzeigt, dass der Wert des Datenregisters des Timer/Counter&lt;br /&gt;
1 in das Input Capture Register ICR1 übertragen wurde.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Flag wird automatisch gelöscht, wenn der zugehörige&lt;br /&gt;
Interrupt-Vektor aufgerufen wird. Es kann jedoch auch gelöscht&lt;br /&gt;
werden, indem eine logische 1 (!) in das entsprechende Bit&lt;br /&gt;
geschrieben wird.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;TOV0&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;T&#039;&#039;&#039;imer/Counter &#039;&#039;&#039;O&#039;&#039;&#039;verflow Flag Timer/Counter&lt;br /&gt;
&#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Dieses Bit wird vom Controller gesetzt, wenn beim Timer 0 ein&lt;br /&gt;
Überlauf des Datenregisters stattfindet.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Flag wird automatisch gelöscht, wenn der zugehörige&lt;br /&gt;
Interrupt-Vektor aufgerufen wird. Es kann jedoch auch gelöscht&lt;br /&gt;
werden, indem eine logische 1 (!) in das entsprechende Bit&lt;br /&gt;
geschrieben wird.&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
= Sleep-Modes =&lt;br /&gt;
&lt;br /&gt;
AVR Controller verfügen über eine Reihe von sogen. &#039;&#039;Sleep-Modes&#039;&#039; (&amp;quot;Schlaf-Modi&amp;quot;). Diese ermöglichen es, Teile des Controllers abzuschalten. Zum Einen kann damit besonders bei Batteriebetrieb Strom gespart werden, zum Anderen können Komponenten des Controllers deaktiviert werden, die die Genauigkeit des Analog-Digital-Wandlers bzw. des Analog-Comperators negativ beeinflussen. Der Controller wird durch Interrupts aus dem Schlaf geweckt. Welche Interrups den jeweiligen Schlafmodus beenden, ist einer Tabelle im Datenblatt des jeweiligen Controllers zu entnehmen.&lt;br /&gt;
Die Funktionen der avr-libc stehen nach Einbinden der header-Datei &#039;&#039;sleep.h&#039;&#039; zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
| set_sleep_mode(uint8_t&amp;amp;nbsp;mode)&lt;br /&gt;
|Setzt den Schlafmodus, der bei Aufruf von sleep() aktiviert wird. In sleep.h sind einige Konstanten definiert (z.B.   SLEEP_MODE_PWR_DOWN). Die definierten Modi werden jedoch nicht alle von sämtlichten AVR-Controllern unterstützt.&lt;br /&gt;
|-&lt;br /&gt;
| sleep_mode()&lt;br /&gt;
| Versetzt den Controller in den mit set_sleep_mode gewählten Schlafmodus&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
   set_sleep_mode(SLEEP_MODE_PWR_DOWN);&lt;br /&gt;
   sleep_mode();&lt;br /&gt;
   &lt;br /&gt;
   // Code hier wird erst nach auftreten eines entsprechenden &amp;quot;Aufwach-Interrupts&amp;quot; verarbeitet&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Vorsicht: Nicht alle AVR-Controller (v.a. nicht die &amp;quot;Brandneuen&amp;quot;) werden von den avr-libc sleep-Funktionen richtig angesteuert. Bei nicht-untersützten Typen erreicht man die gewollte Funktionalität durch direkte &amp;quot;Bitmanipulation&amp;quot; der ensprechenden Register (vgl. Datenblatt) und Aufruf des Sleep-Befehls via Inline-Assembler:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
   // Sleep-Mode &amp;quot;Power-Save&amp;quot; beim ATmega169 aktivieren&lt;br /&gt;
   SMCR = (3&amp;lt;&amp;lt;SM0) | (1&amp;lt;&amp;lt;SE);&lt;br /&gt;
   asm volatile (&amp;quot;sleep&amp;quot;);&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* siehe auch: [http://www.nongnu.org/avr-libc/user-manual/index.html Dokumentation der avr-libc] Abschnitt Modules/Power Management and Sleep-Modes&lt;br /&gt;
&lt;br /&gt;
= Der Watchdog =&lt;br /&gt;
&lt;br /&gt;
Und hier kommt das ultimative Mittel gegen die Unvollkommenheit von uns&lt;br /&gt;
Programmierern, der Watchdog.&lt;br /&gt;
&lt;br /&gt;
So sehr wir uns auch anstrengen, es wird uns kaum je gelingen, das absolut&lt;br /&gt;
perfekte und fehlerfreie Programm zu entwickeln.&amp;lt;br /&amp;gt;&lt;br /&gt;
Der Watchdog kann uns zwar auch nicht zu besseren Programmen verhelfen aber er&lt;br /&gt;
kann dafür sorgen, dass unser Programm, wenn es sich wieder mal in&#039;s Nirwana&lt;br /&gt;
verabschiedet hat, neu gestartet wird, indem ein Reset des Controllers&lt;br /&gt;
ausgelöst wird.&lt;br /&gt;
&lt;br /&gt;
Betrachten wir doch einmal folgende Codesequenz:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- &amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;&#039;&#039;&#039;unsigned char x;&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;&#039;&#039;&#039;x = 10;&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;&#039;&#039;&#039;while (x &amp;gt;= 0) {&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; // tu was&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; x--;&amp;lt;br /&amp;gt;&lt;br /&gt;
}&#039;&#039;&#039;&amp;lt;/font&amp;gt; --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t x;&lt;br /&gt;
&lt;br /&gt;
x = 10;&lt;br /&gt;
&lt;br /&gt;
while (x &amp;gt;= 0) {&lt;br /&gt;
   // tu was&amp;lt;br /&amp;gt;&lt;br /&gt;
   x--;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn wir die Schleife mal genau anschauen sollte uns auffallen, dass dieselbe&lt;br /&gt;
niemals beendet wird. Warum nicht? Ganz einfach, weil eine als &#039;&#039;&#039;&#039;&#039;unsigned&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
deklarierte Variable niemals kleiner als Null werden kann.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Programm würde sich also hier aufhängen und auf ewig in der Schleife&lt;br /&gt;
drehen.&amp;lt;br /&amp;gt;&lt;br /&gt;
Und hier genau kommt der Watchdog zum Zug.&lt;br /&gt;
&lt;br /&gt;
== Wie funktioniert nun der Watchdog ==&lt;br /&gt;
&lt;br /&gt;
Der Watchdog enthält einen separaten Timer/Counter, welcher mit einem intern&lt;br /&gt;
erzeugten Takt von 1 MHz bei 5V Vcc getaktet wird. Nachdem der Watchdog&lt;br /&gt;
aktiviert und der gewünschte Vorteiler eingestellt wurde beginnt der Counter&lt;br /&gt;
von 0 an hochzuzählen. Wenn nun die je nach Vorteiler eingestellte Anzahl&lt;br /&gt;
Zyklen erreicht wurde löst der Watchdog einen Reset aus. Um nun also im&lt;br /&gt;
Normalbetrieb den Reset zu verhindern müssen wir den Watchdog regelmässig&lt;br /&gt;
wieder neu starten bzw. Rücksetzen (Watchdog Reset). Dies sollte innerehalb&lt;br /&gt;
unserer Hauptschleife passieren.&lt;br /&gt;
&lt;br /&gt;
Um ein unbeabsichtigtes Ausschalten des Watchdogs zu verhindern muss ein&lt;br /&gt;
spezielles Prozedere verwendet werden um den WD auszuschalten und zwar müssen&lt;br /&gt;
zuerst die beiden Bits WDTOE und WDE in einer einzelnen Operation (also nicht&lt;br /&gt;
mit sbi) auf 1 gesetzt werden. Dann muss innerhalb der nächsten 4 Taktzyklen&lt;br /&gt;
das Bit WDE auf 0 gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
Das Watchdog Control Register:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;WDTCR&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;W&#039;&#039;&#039;atchog &#039;&#039;&#039;T&#039;&#039;&#039;imer&amp;amp;nbsp; &#039;&#039;&#039;C&#039;&#039;&#039;ontrol &#039;&#039;&#039;R&#039;&#039;&#039;egister&amp;lt;br /&amp;gt;&lt;br /&gt;
In diesem Register stellen wir ein, wie wir den Watchdog verwenden möchten.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Register ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;WDTOE&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;WDE&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;WDP2&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;WDP1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;WDP0&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;WDTOE&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;W&#039;&#039;&#039;atch&#039;&#039;&#039;d&#039;&#039;&#039;og &#039;&#039;&#039;T&#039;&#039;&#039;urn &#039;&#039;&#039;O&#039;&#039;&#039;ff &#039;&#039;&#039;E&#039;&#039;&#039;nable&amp;lt;br /&amp;gt;&lt;br /&gt;
Dieses Bit muss gesetzt sein, wenn das Bit &#039;&#039;&#039;WDE&#039;&#039;&#039; gelöscht&lt;br /&gt;
wird, andernfalls wird der Watchdog nicht ausgeschaltet.&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn das Bit einmal gesetzt ist wird es von der Hardware nach 4&lt;br /&gt;
Taktzyklen automatisch wieder gelöscht.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;WDE&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;W&#039;&#039;&#039;atch&#039;&#039;&#039;d&#039;&#039;&#039;og &#039;&#039;&#039;E&#039;&#039;&#039;nable&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn dieses Bit gesetzt wird so wird der Watchdog aktiviert.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Bit kann nur gelöscht werden solange das Bit &#039;&#039;&#039;WDTOE&#039;&#039;&#039; auf 1&lt;br /&gt;
steht.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;WDP2&amp;lt;br /&amp;gt;&lt;br /&gt;
WDP1&amp;lt;br /&amp;gt;&lt;br /&gt;
WDP0&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;W&#039;&#039;&#039;atch&#039;&#039;&#039;d&#039;&#039;&#039;og Timer &#039;&#039;&#039;P&#039;&#039;&#039;rescaler Bits&amp;lt;br /&amp;gt;&lt;br /&gt;
Diese 3 Bits bestimmen die Anzahl Oszillatorzyklen für den Watchdog,&lt;br /&gt;
also, wie lange es dauert, bis ein Reset ausgelöst wird:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | WDP2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | WDP1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | WDP0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | Anzahl Zyklen&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | Typ. Timeoutzeit bei Vcc = 3V&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | Typ. Timeoutzeit bei Vcc = 5V&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 16K&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 47ms&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 15ms&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 32K&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 94ms&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 30ms&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 64K&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0.19s&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 60ms&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 128K&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0.38s&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0.12s&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 256K&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0.75s&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0.24s&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 512K&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1.5s&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0.49s&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1024K&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3s&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0.97s&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2048K&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6s&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1.9s&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Um den Watchdog mit dem AVR-GCC Compiler zu verwenden muss die Headerdatei&lt;br /&gt;
wdt.h in die Quelldatei eingebunden werden. &lt;br /&gt;
&amp;lt;!-- mt: das stimmt wohl nicht mehr?!:&lt;br /&gt;
Dadurch wird auch der Startup-Code&lt;br /&gt;
entsprechend angepasst, so dass der Watchdog nach einem Reset automatisch&lt;br /&gt;
gestartet wird. Das WDTCR-Register wird dabei mit dem Wert 0 beschrieben. Falls&lt;br /&gt;
ein anderer Wert gewünscht ist so kann dies im Makfile in den Linker-Optionen&lt;br /&gt;
eingetragen werden. Dazu muss in der Zeile LDFLAGS folgende Option angefügt&lt;br /&gt;
werden:&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; --defsym __init_wdtcr__=0x1f&amp;lt;br /&amp;gt;&lt;br /&gt;
wenn beispielsweise der Wert des Registers auf 0x1f gestellt werden soll.&amp;lt;br /&amp;gt; --&amp;gt;&lt;br /&gt;
Danach können die folgenden Funktionen verwendet werden:&lt;br /&gt;
&lt;br /&gt;
{| border=1&lt;br /&gt;
| wdt_enable(uint8_t&amp;amp;nbsp;timeout)&lt;br /&gt;
|Aktiviert den Watchdog und stellt den Vorteiler auf den gewünschten Wert ein bzw. der in timeout übergebene Wert wird in das WDTCR-Register eingetragen. Einige Timeout-Werte sind als Konstanten vordefiniert (z.B. WDTO_30MS).&lt;br /&gt;
|-&lt;br /&gt;
| wdt_disable()&lt;br /&gt;
| Mit dieser Funktion kann der Watchdog ausgeschaltet werden. Dabei wird das notwendige Prozedere, wie oben beschrieben, automatisch ausgeführt.&lt;br /&gt;
|-&lt;br /&gt;
| wdt_reset()&lt;br /&gt;
| Dies ist wohl die wichtigste der Watchdog-Funktionen. Sie erzeugt einen Watchdog-Reset, welcher periodisch, und zwar vor Ablauf der Timeoutzeit, ausgeführt werden muss, damit der Watchdog nicht den AVR zurücksetzt.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Selbstverständlich kann das &#039;&#039;&#039;WDTCR&#039;&#039;&#039;-Register auch mit den uns bereits bekannten Funktionen für den Zugriff auf Register programmiert werden.&lt;br /&gt;
&lt;br /&gt;
* siehe auch: (TODO link to avr-libc/modules/watchdog)&lt;br /&gt;
&lt;br /&gt;
== Ein paar grundsätzliche Gedanken ==&lt;br /&gt;
&lt;br /&gt;
Ob nun so ein Watchdog überhaupt verwendet werden soll ist wohl eher eine&lt;br /&gt;
philosophische Frage und hängt vom Geschmack jedes einzelnen Entwicklers ab.&lt;br /&gt;
&lt;br /&gt;
Ich persönlich habe es lieber, wenn ich auch merke, dass in meine Programm&lt;br /&gt;
etwas noch nicht in Ordnung ist, als dass mir ein Watchdog einfach die CPU immer&lt;br /&gt;
wieder zurücksetzt, denn immerhin kann es so passieren, dass ein Programm über&lt;br /&gt;
Jahre hinweg so einigermassen läuft, obwohl noch ein voll krasser Bock drin&lt;br /&gt;
liegt.&lt;br /&gt;
&lt;br /&gt;
* siehe auch: [http://www.nongnu.org/avr-libc/user-manual/index.html Dokumentation der avr-libc] Abschnitt Modules/Watchdog timer handling&lt;br /&gt;
&lt;br /&gt;
= Programmieren mit Interrupts =&lt;br /&gt;
&lt;br /&gt;
Nachdem wir nun alles Wissenswerte für die serielle Programmerstellung&lt;br /&gt;
gelernt haben nehmen wir jetzt ein völlig anderes Thema in Angriff, nämlich&lt;br /&gt;
die Programmierung unter Zuhilfenahme der Interrupts des AVR.&lt;br /&gt;
&lt;br /&gt;
Als erstes wollen wir uns noch einmal den allgemeinen Programmablauf bei der&lt;br /&gt;
Interrupt-Programmierung zu Gemüte führen.&lt;br /&gt;
&lt;br /&gt;
[[Image:Interrupt Programme.gif]]&lt;br /&gt;
&lt;br /&gt;
Man sieht, dass die Interruptroutine quasi parallel zum Hauptprogramm&lt;br /&gt;
abläuft. Da wir nur eine CPU haben ist es natürlich keine echte Parallelität,&lt;br /&gt;
sondern das Hauptprogramm wird beim Eintreffen eines Interrupts unterbrochen,&lt;br /&gt;
die Interruptroutine wird ausgeführt und danach erst wieder zum Hauptprogramm&lt;br /&gt;
zurückgekehrt.&lt;br /&gt;
&lt;br /&gt;
== Anforderungen an die Interrupt-Routine ==&lt;br /&gt;
&lt;br /&gt;
Um unliebsamen Überraschungen vorzubeugen sollten einige Grundregeln bei&lt;br /&gt;
der Gestaltung der Interruptroutinen beachtet werden.&lt;br /&gt;
&lt;br /&gt;
* Die Interruptroutine soll möglichst kurz und schnell abarbeitbar sein, daraus folgt:&lt;br /&gt;
* Keine unfangreichen Berechnungen innerhalb der Interruptroutine.&lt;br /&gt;
* Keine endlos langen Programmschleifen.&lt;br /&gt;
* Obschon es möglich ist, während der Abarbeitung einer Interruptroutine andere oder sogar den gleichen Interrupt wieder zuzulassen rate ich dringend von solchen Spielen ab.&lt;br /&gt;
&lt;br /&gt;
== Interrupt-Quellen ==&lt;br /&gt;
&lt;br /&gt;
Die folgenden Ereignisse können einen Interrupt auf dem AVR auslösen, wobei&lt;br /&gt;
die Reihenfolge der Auflistung auch die Priorität der Interrupts aufzeigt.&lt;br /&gt;
&lt;br /&gt;
* Reset&lt;br /&gt;
* Externer Interrupt 0&lt;br /&gt;
* Externer Interrupt 1&lt;br /&gt;
* Timer/Counter 1 Capture Ereignis&lt;br /&gt;
* Timer/Counter 1 Compare Match&lt;br /&gt;
* Timer/Counter 1 Überlauf&lt;br /&gt;
* Timer/Counter 0 Überlauf&lt;br /&gt;
* UART Zeichen empfangen&lt;br /&gt;
* UART Datenregister leer&lt;br /&gt;
* UART Zeichen gesendet&lt;br /&gt;
* Analoger Komparator&lt;br /&gt;
&lt;br /&gt;
== Register ==&lt;br /&gt;
&lt;br /&gt;
Der AT90S2313 verfügt über 2 Register welche mit den&lt;br /&gt;
Interrupts zusammen hängen.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;GIMSK&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;G&#039;&#039;&#039;eneral &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;M&#039;&#039;&#039;ask &#039;&#039;&#039;R&#039;&#039;&#039;egister.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;INT1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;INT0&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;INT1&#039;&#039;&#039;&lt;br /&gt;
| External &#039;&#039;&#039;Int&#039;&#039;&#039;errupt Request &#039;&#039;&#039;1&#039;&#039;&#039; Enable&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn dieses Bit gesetzt ist wird ein Interrupt&lt;br /&gt;
ausgelöst wenn am &#039;&#039;&#039;INT1&#039;&#039;&#039;-Pin eine steigende oder fallende (je&lt;br /&gt;
nach Konfiguration im &#039;&#039;&#039;MCUCR&#039;&#039;&#039;) Flanke erkannt wird.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Global&lt;br /&gt;
Enable Interrupt Flag muss selbstverständlich auch gesetzt sein.&amp;lt;br /&amp;gt;&lt;br /&gt;
Der Interrupt wird auch ausgelöst, wenn der Pin als Ausgang&lt;br /&gt;
geschaltet ist. Auf diese Weise bietet sich die Möglichkeit,&lt;br /&gt;
Software-Interrupts zu realisieren.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;INT0&#039;&#039;&#039;&lt;br /&gt;
| External &#039;&#039;&#039;Int&#039;&#039;&#039;errupt Request &#039;&#039;&#039;0&#039;&#039;&#039; Enable&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn dieses Bit gesetzt ist wird ein Interrupt&lt;br /&gt;
ausgelöst wenn am &#039;&#039;&#039;INT0&#039;&#039;&#039;-Pin eine steigende oder fallende (je&lt;br /&gt;
nach Konfiguration im &#039;&#039;&#039;MCUCR&#039;&#039;&#039;) Flanke erkannt wird.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Global&lt;br /&gt;
Enable Interrupt Flag muss selbstverständlich auch gesetzt sein.&amp;lt;br /&amp;gt;&lt;br /&gt;
Der Interrupt wird auch ausgelöst, wenn der Pin als Ausgang&lt;br /&gt;
geschaltet ist. Auf diese Weise bietet sich die Möglichkeit,&lt;br /&gt;
Software-Interrupts zu realisieren.&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;GIFR&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;G&#039;&#039;&#039;eneral &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;F&#039;&#039;&#039;lag &#039;&#039;&#039;R&#039;&#039;&#039;egister.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;INTF1&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;INTF0&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;INTF1&#039;&#039;&#039;&lt;br /&gt;
| External &#039;&#039;&#039;Int&#039;&#039;&#039;errupt Flag &#039;&#039;&#039;1&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Dieses Bit wird gesetzt, wenn am &#039;&#039;&#039;INT1&#039;&#039;&#039;-Pin eine&lt;br /&gt;
Interrupt-Kondition, entsprechend der Konfiguration, erkannt wird.&lt;br /&gt;
Wenn das Global Enable Interrupt Flag gesetzt ist wird die&lt;br /&gt;
Interruptroutine angesprungen.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Flag wird automatisch gelöscht, wenn die Interruptroutine&lt;br /&gt;
beendet ist.&amp;lt;br /&amp;gt;&lt;br /&gt;
Alternativ kann das Flag gelöscht werden, indem der Wert &#039;&#039;&#039;1(!)&#039;&#039;&#039;&lt;br /&gt;
eingeschrieben wird.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;INTF0&#039;&#039;&#039;&lt;br /&gt;
| External &#039;&#039;&#039;Int&#039;&#039;&#039;errupt Flag &#039;&#039;&#039;0&#039;&#039;&#039;&amp;lt;br /&amp;gt;&lt;br /&gt;
Dieses Bit wird gesetzt, wenn am &#039;&#039;&#039;INT0&#039;&#039;&#039;-Pin eine&lt;br /&gt;
Interrupt-Kondition, entsprechend der Konfiguration, erkannt wird.&lt;br /&gt;
Wenn das Global Enable Interrupt Flag gesetzt ist wird die&lt;br /&gt;
Interruptroutine angesprungen.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Flag wird automatisch gelöscht, wenn die Interruptroutine&lt;br /&gt;
beendet ist.&amp;lt;br /&amp;gt;&lt;br /&gt;
Alternativ kann das Flag gelöscht werden, indem der Wert &#039;&#039;&#039;1(!)&#039;&#039;&#039;&lt;br /&gt;
eingeschrieben wird.&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;MCUCR&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;MCU&#039;&#039;&#039; &#039;&#039;&#039;C&#039;&#039;&#039;ontrol &#039;&#039;&#039;R&#039;&#039;&#039;egister.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das MCU Control Register enthält Kontrollbits für allgemeine&lt;br /&gt;
MCU-Funktionen.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Bit&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Name&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;-&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;SE&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;SM&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ISC11&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ISC10&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ISC01&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ISC00&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;R/W&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R/W&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | R&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;Initialwert&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;0&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;SE&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;S&#039;&#039;&#039;leep &#039;&#039;&#039;E&#039;&#039;&#039;nable&amp;lt;br /&amp;gt;&lt;br /&gt;
Dieses Bit muss gesetzt sein, um den Controller mit dem &#039;&#039;&#039;SLEEP&#039;&#039;&#039;-Befehl&lt;br /&gt;
in den Schlafzustand versetzen zu können.&amp;lt;br /&amp;gt;&lt;br /&gt;
Um den Schlafmodus nicht irrtümlich einzuschalten wird empfohlen,&lt;br /&gt;
das Bit erst unmittelbar vor Ausführung des &#039;&#039;&#039;SLEEP&#039;&#039;&#039;-Befehls zu&lt;br /&gt;
setzen.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;SM&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;S&#039;&#039;&#039;leep &#039;&#039;&#039;M&#039;&#039;&#039;ode&amp;lt;br /&amp;gt;&lt;br /&gt;
Dieses Bit bestimmt der Schlafmodus.&amp;lt;br /&amp;gt;&lt;br /&gt;
Ist das Bit gelöscht so wird der &#039;&#039;&#039;Idle&#039;&#039;&#039;-Modus ausgeführt.&amp;lt;br /&amp;gt;&lt;br /&gt;
Ist das Bit gesetzt so wird der &#039;&#039;&#039;Power-Down&#039;&#039;&#039;-Modus ausgeführt.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;ISC11&amp;lt;br /&amp;gt;&lt;br /&gt;
ISC10&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;S&#039;&#039;&#039;ense &#039;&#039;&#039;C&#039;&#039;&#039;ontrol &#039;&#039;&#039;1&#039;&#039;&#039;&lt;br /&gt;
Bits&amp;lt;br /&amp;gt;&lt;br /&gt;
Diese beiden Bits bestimmen, ob die steigende oder die fallende&lt;br /&gt;
Flanke für die Interrupterkennung am &#039;&#039;&#039;INT1&#039;&#039;&#039;-Pin ausgewertet&lt;br /&gt;
wird.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ISC11&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ISC10&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Bedeutung&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Low Level an &#039;&#039;&#039;INT1&#039;&#039;&#039; erzeugt einen Interrupt.&amp;lt;br /&amp;gt;&lt;br /&gt;
In der Beschreibung heisst es, der Interrupt wird getriggert,&lt;br /&gt;
solange der Pin auf 0 bleibt, also eigentlich unbrauchbar.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Reserviert&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Die fallende Flank an &#039;&#039;&#039;INT1&#039;&#039;&#039; erzeugt einen&lt;br /&gt;
Interrupt.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Die steigende Flanke an &#039;&#039;&#039;INT1&#039;&#039;&#039; erzeugt&lt;br /&gt;
einen Interrupt.&lt;br /&gt;
|}&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;ISC01&amp;lt;br /&amp;gt;&lt;br /&gt;
ISC00&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;S&#039;&#039;&#039;ense &#039;&#039;&#039;C&#039;&#039;&#039;ontrol &#039;&#039;&#039;0&#039;&#039;&#039;&lt;br /&gt;
Bits&amp;lt;br /&amp;gt;&lt;br /&gt;
Diese beiden Bits bestimmen, ob die steigende oder die fallende&lt;br /&gt;
Flanke für die Interrupterkennung am &#039;&#039;&#039;INT0&#039;&#039;&#039;-Pin ausgewertet&lt;br /&gt;
wird.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ISC01&#039;&#039;&#039;&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | &#039;&#039;&#039;ISC00&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;Bedeutung&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Low Level an &#039;&#039;&#039;INT0&#039;&#039;&#039; erzeugt einen Interrupt.&amp;lt;br /&amp;gt;&lt;br /&gt;
In der Beschreibung heisst es, der Interrupt wird getriggert,&lt;br /&gt;
solange der Pin auf 0 bleibt, also eigentlich unbrauchbar.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Reserviert&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0&lt;br /&gt;
| Die fallende Flank an &#039;&#039;&#039;INT0&#039;&#039;&#039; erzeugt einen&lt;br /&gt;
Interrupt.&lt;br /&gt;
|- &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| Die steigende Flanke an &#039;&#039;&#039;INT0&#039;&#039;&#039; erzeugt&lt;br /&gt;
einen Interrupt.&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Allgemeines über die Interrupt-Abarbeitung ==&lt;br /&gt;
&lt;br /&gt;
Wenn ein Interrupt eintrifft wird automatisch das &#039;&#039;&#039;Global&lt;br /&gt;
Interrupt Enable&#039;&#039;&#039; Bit im Status Register &#039;&#039;&#039;SREG&#039;&#039;&#039; gelöscht und alle&lt;br /&gt;
weiteren Interrupts unterbunden. Obwohl es möglich ist, zu diesem&lt;br /&gt;
Zeitpunkt bereits wieder das GIE-bit zu setzen rate ich dringend davon ab. Dieses&lt;br /&gt;
wird nämlich automatisch gesetzt, wenn die Interruptroutine beendet wird. Wenn&lt;br /&gt;
in der Zwischenzeit weitere Interrupts eintreffen werden die zugehörigen&lt;br /&gt;
Interrupt-Bits gesetzt und die Interrupts bei Beendigung der laufenden&lt;br /&gt;
Interrupt-Routine in der Reihenfolge ihrer Priorität ausgeführt. Dies kann&lt;br /&gt;
eigentlich nur dann zu Problemen führen, wenn ein hoch priorisierter Interrupt&lt;br /&gt;
ständig und in kurzer Folge auftritt. Dieser sperrt dann möglicherweise alle&lt;br /&gt;
anderen Interrupts mit niedrigerer Priorität. Dies ist einer der Gründe,&lt;br /&gt;
weshalb die Interrupt-Routinen sehr kurz gehalten werden sollen.&lt;br /&gt;
&lt;br /&gt;
=== Das Status-Register ===&lt;br /&gt;
&lt;br /&gt;
Es gilt auch zu beachten, dass das Status-Register während der Abarbeitung&lt;br /&gt;
einer Interruptroutine nicht automatisch gesichert wird. Falls notwendig muss dies vom&lt;br /&gt;
Programmierer selber vorgesehen werden.&lt;br /&gt;
&lt;br /&gt;
== Interrupts mit dem AVR GCC Compiler (WinAVR) ==&lt;br /&gt;
&lt;br /&gt;
Selbstverständlich können alle Interruptspezifischen Registerzugriffe wie&lt;br /&gt;
gewohnt über I/O-Adressierung vorgenommen werden. Etwas einfacher geht es&lt;br /&gt;
jedoch, wenn wir die vom Compiler zur Verfügung gestellten Mittel einsetzen.&amp;lt;br /&amp;gt;&lt;br /&gt;
Damit diese Mittel zur Verfügung stehen müssen wir die Includedatei&lt;br /&gt;
interrupt.h einbinden mittels&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Und dann kann&#039;s losgehen&lt;br /&gt;
&lt;br /&gt;
Das Makro &#039;&#039;&#039;sei()&#039;&#039;&#039; schaltet die Interrupts ein. Eigentlich wird&lt;br /&gt;
nichts anderes gemacht als das &#039;&#039;&#039;Global Interrupt Enable&#039;&#039;&#039; Bit im Status&lt;br /&gt;
Register gesetzt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
    sei();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Makro &#039;&#039;&#039;cli()&#039;&#039;&#039; schaltet die Interrupts aus oder anders&lt;br /&gt;
gesagt, das &#039;&#039;&#039;Global Interrupt Enable&#039;&#039;&#039; Bit im Status Register wird&lt;br /&gt;
gelöscht.&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
    cli();&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Oft steht man vor der Aufgabe, dass eine Codesequenz nicht unterbrochen werden darf.&lt;br /&gt;
Es liegt dann nahe, zu Beginn dieser Sequenz ein cli() und am Ende ein sei() einzufügen.&lt;br /&gt;
Dies ist jedoch ungünstig, wenn die Interrupts vor Aufruf der Sequenz deaktiviert waren&lt;br /&gt;
und danach auch weiterhin deaktiviert bleiben sollen. Ein sei() würde ungeachtet des vorherigen &lt;br /&gt;
Zustands die Interrups aktivieren, was zu unerwünschten Seiteneffekten führen kann.&lt;br /&gt;
Die aus dem folgenden Beispiel ersichtliche Vorgehensweise ist in solchen Fällen vorzuziehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
void NichtUnterbrechenBitte(void)&lt;br /&gt;
{&lt;br /&gt;
   uint8_t tmp_sreg;  // temporaerer Speicher fuer das Statusregister&lt;br /&gt;
&lt;br /&gt;
   tmp_sreg = SREG;   // Statusregister (also auch das I-Flag darin) sichern&lt;br /&gt;
   cli();             // Interrupts global deaktivieren&lt;br /&gt;
&lt;br /&gt;
   /* hier &amp;quot;unterbrechnungsfreier&amp;quot; Code */&lt;br /&gt;
&lt;br /&gt;
   /* Beispiel Anfang&lt;br /&gt;
     JTAG-Interface eines ATmega16 per Software deaktivieren &lt;br /&gt;
     und damit die JTAG-Pins an PORTC für &amp;quot;general I/O nutzbar machen&lt;br /&gt;
     ohne die JTAG-Fuse-Bit zu aendern */&lt;br /&gt;
&lt;br /&gt;
   MCUCR |= (1&amp;lt;&amp;lt;JTD);&lt;br /&gt;
   MCUCR |= (1&amp;lt;&amp;lt;JTD); // 2 mal in Folge , vgl. Datenblatt fuer mehr Information&lt;br /&gt;
&lt;br /&gt;
   /* Beispiel Ende */&lt;br /&gt;
  &lt;br /&gt;
   SREG = tmp_sreg;     // Status-Register wieder herstellen &lt;br /&gt;
                      // somit auch das I-Flag auf gesicherten Zustand setzen&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void NichtSoGut(void)&lt;br /&gt;
{&lt;br /&gt;
   cli();&lt;br /&gt;
   &lt;br /&gt;
   /* hier &amp;quot;unterbrechnungsfreier&amp;quot; Code */&lt;br /&gt;
   &lt;br /&gt;
   sei();&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
   cli();  &lt;br /&gt;
   // Interrupts global deaktiviert &lt;br /&gt;
&lt;br /&gt;
   NichtUnterbrechenBitte();&lt;br /&gt;
   // auch nach Aufruf der Funktion deaktiviert&lt;br /&gt;
&lt;br /&gt;
   sei();&lt;br /&gt;
   // Interrupts global aktiviert &lt;br /&gt;
&lt;br /&gt;
   NichtUnterbrechenBitte();&lt;br /&gt;
   // weiterhin aktiviert&lt;br /&gt;
   ...&lt;br /&gt;
&lt;br /&gt;
   /* Verdeutlichung der unguenstigen Vorgehensweise mit cli/sei: */&lt;br /&gt;
   cli();  &lt;br /&gt;
   // Interrupts jetzt global deaktiviert &lt;br /&gt;
&lt;br /&gt;
   NichSoGut();&lt;br /&gt;
   // nach Aufruf der Funktion sind Interrupts global aktiviert &lt;br /&gt;
   // dies ist mglw. ungewollt!&lt;br /&gt;
   ...&lt;br /&gt;
   &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- mt: besser so nicht(?), lieber &amp;quot;datenblattkonform&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;&#039;&#039;&#039;timer_enable_int (unsigned char ints);&amp;lt;br /&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;/font&amp;gt;Schaltet Timerbezogene Interrupts ein bzw. aus.&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn als Argument &#039;&#039;&#039;ints&#039;&#039;&#039; der Wert 0 übergeben wird so werden alle&lt;br /&gt;
Timerinterrupts ausgeschaltet, ansonsten muss in &#039;&#039;&#039;ints&#039;&#039;&#039; angegeben werden,&lt;br /&gt;
welche Interrupts zu aktivieren sind. Dabei müssen einfach die entsprechend zu&lt;br /&gt;
setzenden Bits definiert werden.&amp;lt;br /&amp;gt;&lt;br /&gt;
Beispiel: &#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;timer_enable_int (1 &amp;lt;&amp;lt; TOIE1));&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;lt;/font&amp;gt;&#039;&#039;&#039;Achtung: Wenn ein Timerinterrupt eingeschaltet wird während ein&lt;br /&gt;
anderer Timerinterrupt bereits läuft, dann müssen beide Bits angegeben werden&lt;br /&gt;
sonst wird der andere Timerinterrupt versehentlich ausgeschaltet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;&#039;&#039;&#039;enable_external_int (unsigned char ints);&amp;lt;br /&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;/font&amp;gt;Schaltet die externen Interrupts ein bzw. aus.&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn als Argument &#039;&#039;&#039;ints&#039;&#039;&#039; der Wert 0 übergeben wird so werden alle externen&lt;br /&gt;
Interrrups ausgeschaltet, ansonsten muss in &#039;&#039;&#039;ints&#039;&#039;&#039; angegeben werden, welche&lt;br /&gt;
Interrupts zu aktivieren sind. Dabei müssen einfach die entsprechend zu&lt;br /&gt;
setzenden Bits definiert werden.&amp;lt;br /&amp;gt;&lt;br /&gt;
Beispiel: &#039;&#039;&#039;&amp;lt;font face=&amp;quot;Courier New&amp;quot;&amp;gt;enable_external_int ((1&amp;lt;&lt;br /&gt;
&amp;lt;/font&amp;gt;&#039;&#039;&#039;Schaltet die externen Interrupts 0 und 1 ein.&lt;br /&gt;
&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nachdem nun die Interrupts aktiviert sind braucht es selbstverständlich noch&lt;br /&gt;
den auszuführenden Code, der ablaufen soll wenn ein Interrupt eintrifft.&amp;lt;br /&amp;gt;&lt;br /&gt;
Dazu gibt es zwei Definitionen welche allerdings AVR-GCC spezifisch sind und&lt;br /&gt;
bei anderen Compilern womöglich anders heissen können.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
SIGNAL (signum)&lt;br /&gt;
{&lt;br /&gt;
    /* Interrupt Code */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit SIGNAL wird eine Funktion für die Bearbeitung eines Interrupts&lt;br /&gt;
eingeleitet. Als Argument muss dabei die Benennung des entsprechenden&lt;br /&gt;
Interruptvektoren angegeben werden. Diese sind in den jeweiligen Includedateien&lt;br /&gt;
IOxxxx.h zu finden. Mögliche Funktionsrümpfe für solche Interruptfunktionen&lt;br /&gt;
sind zum Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/signal.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
SIGNAL (SIG_INTERRUPT0)&lt;br /&gt;
{&lt;br /&gt;
    /* Interrupt Code */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
SIGNAL (SIG_OVERFLOW1)&lt;br /&gt;
{&lt;br /&gt;
    /* Interrupt Code */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
SIGNAL (SIG_UART_RECV)&lt;br /&gt;
{&lt;br /&gt;
    /* Interrupt Code */&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// und so weiter und so fort...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Während der Ausführung des Funktion sind alle weiteren Interrupts&lt;br /&gt;
automatisch gesperrt. Beim Verlassen der Funktion werden die Interrupts wieder&lt;br /&gt;
zugelassen.&amp;lt;br /&amp;gt;&lt;br /&gt;
Sollte während der Abarbeitung der Interruptroutine ein weiterer Interrupt&lt;br /&gt;
(gleiche oder andere Interruptquelle) auftreten so wird das entsprechende Bit im&lt;br /&gt;
zugeordneten Interrupt Flag Register gesetzt und die entsprechende&lt;br /&gt;
Interruptroutine automatisch nach dem Beenden der aktuellen Funktion aufgerufen.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ein Problem ergibt sich eigentlich nur dann, wenn während der Abarbeitung der&lt;br /&gt;
aktuellen Interruptroutine mehrere gleichartige Interrupts auftreten. Die&lt;br /&gt;
entsprechende Interruptroutine wird im Nachhinein zwar aufgerufen jedoch wissen&lt;br /&gt;
wir nicht, ob nun der entsprechende Interrupt einmal, zweimal oder gar noch&lt;br /&gt;
öfter aufgetreten ist. Deshalb soll hier noch einmal betont werden, dass&lt;br /&gt;
Interruptroutinen so schnell wie nur irgend möglich wieder verlassen werden&lt;br /&gt;
sollten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
INTERRUPT (signame)&lt;br /&gt;
{&lt;br /&gt;
    /* Interrupt Code */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit INTERRUPT wird genau gleich gearbeitet wie mit SIGNAL. Der Unterschied&lt;br /&gt;
ist derjenige, dass bei INTERRUPT beim Aufrufen der Funktion das &#039;&#039;&#039;Global&lt;br /&gt;
Enable Interrupt&#039;&#039;&#039; Bit automatisch wieder gesetzt und somit weitere Interrupts&lt;br /&gt;
zugelassen werden. Dies kann zu nicht unerheblichen Problemen von im einfachsten&lt;br /&gt;
Fall einem Stack overflow bis zu sonstigen unerwarteten Effekten führen und&lt;br /&gt;
sollte wirklich nur dann angewendet werden wenn man sich absolut sicher ist, das&lt;br /&gt;
ganze auch im Griff zu haben.&lt;br /&gt;
&lt;br /&gt;
siehe auch: Hinweise in [[AVR-GCC]]&lt;br /&gt;
&lt;br /&gt;
== Datenaustausch mit Interrupt-Routinen ==&lt;br /&gt;
&lt;br /&gt;
Variablen auf die sowohl in Interrupt-Routinen (ISR = Interrupt Service Routine(s)), als auch vom übrigen Programmcode geschrieben oder gelesen werden, müssen mit einem &#039;&#039;&#039;volatile&#039;&#039;&#039; deklariert werden. Damit wird dem Compiler mitgeteilt, dass der Inhalt der Variablen vor jedem Lesezugriff aus dem Speicher gelesen wird und nach jedem Schreibzugriff in den Speicher geschrieben wird. Ansonsten könnte die Code-Optimierung &amp;quot;greifen&amp;quot; und der Wert der Variablen nur in Prozessorregistern zwischenspeichert werden, die &amp;quot;nichts von der Änderung woanders mitbekommen&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Zur Veranschaulichung ein Codefragment für eine Tastenentprellung mit Erkennung einer &amp;quot;lange gedrückten&amp;quot; Taste.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/signal.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
// Schwellwerte&lt;br /&gt;
// Entprellung: &lt;br /&gt;
#define CNTDEBOUNCE 10&lt;br /&gt;
// &amp;quot;lange gedrueckt:&amp;quot;&lt;br /&gt;
#define CNTREPEAT 200&lt;br /&gt;
&lt;br /&gt;
// hier z.B. Taste an Pin2 PortA &amp;quot;active low&amp;quot; = 0 wenn gedrueckt&lt;br /&gt;
#define KEY_PIN  PINA&lt;br /&gt;
#define KEY_PINNO PA2&lt;br /&gt;
&lt;br /&gt;
// beachte: volatile! &lt;br /&gt;
volatile uint8_t gKeyCounter;&lt;br /&gt;
&lt;br /&gt;
// Timer-Compare Interrupt z.B. alle 10ms&lt;br /&gt;
SIGNAL(SIG_OUTPUT_COMPARE1A)&lt;br /&gt;
{&lt;br /&gt;
   // hier wird gKeyCounter veraendert, die uebrigen&lt;br /&gt;
   // Programmteile muessen diese Aenderung &amp;quot;sehen&amp;quot;&lt;br /&gt;
   // (volatile -&amp;gt; aktuellen Wert immer in den Speicher schreiben)&lt;br /&gt;
   if ( !(KEY_PIN &amp;amp; (1&amp;lt;&amp;lt;KEY_PINNO)) )&lt;br /&gt;
      if (gKeyCouter &amp;lt; CNTREPEAT) gKeyCounter++;&lt;br /&gt;
   else gKeyCounter = 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
    /* hier: Initialisierung der Ports und des Timer-Interrupts */&lt;br /&gt;
... &lt;br /&gt;
   // hier wird auf gKeyCounter zugegriffen, dazu muss der in der&lt;br /&gt;
   // ISR geschrieben Wert bekannt sein.&lt;br /&gt;
   // (volatile -&amp;gt; aktuellen Wert immer aus dem Speicher lesen)&lt;br /&gt;
   if ( gKeyCounter &amp;gt; CNTDEBOUNCE ) { // Taste mind. 10*10 ms &amp;quot;prellfrei&amp;quot;&lt;br /&gt;
       if (gKeyCounter == CNTREPEAT) {&lt;br /&gt;
          /* hier: Code fuer &amp;quot;Taste lange gedrueckt&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
       else {&lt;br /&gt;
          /* hier: Code fuer &amp;quot;Taste kurz gedrueckt&amp;quot;&lt;br /&gt;
       }&lt;br /&gt;
...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bei Variablen größer ein Byte muss darauf geachtet werden, dass die Zugriffe auf die einzelnen Bytes ausserhalb der ISR nicht durch einen Interrupt unterbrochen werden. (Allgemeinplatz: AVRs sind 8-bit Controller). Zur Veranschaulichung ein Codefragment:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
volatile uint16_t gMyCounter16bit&lt;br /&gt;
...&lt;br /&gt;
SIGNAL(...)&lt;br /&gt;
{&lt;br /&gt;
...&lt;br /&gt;
   gMyCounter16Bit++;&lt;br /&gt;
...&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
   uint16_t tmpCnt;&lt;br /&gt;
...&lt;br /&gt;
   // nicht gut: mglw. hier ein Fehler wenn ein Byte von MyCounter &lt;br /&gt;
   // schon in tmpCnt kopiert ist aber vor Kopieren des zweiten Bytes &lt;br /&gt;
   // ein Interrupt auftritt der den Inhalt von MyCounter veraendert&lt;br /&gt;
   tmpCnt = gMyCounter16bit; &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
   // besser: Aenderungen &amp;quot;ausserhalb&amp;quot; verhindern, alle &amp;quot;Teilbytes&amp;quot;&lt;br /&gt;
   // bleiben konsistent&lt;br /&gt;
   cli();  // Interupts deaktivieren&lt;br /&gt;
   tmpCnt = gMyCounter16Bit;&lt;br /&gt;
   sei();  // wieder aktivieren&lt;br /&gt;
...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* siehe auch: [http://www.nongnu.org/avr-libc/user-manual/index.html Dokumentation der avr-libc] Frequently asked Questions/Fragen Nr. 1 und 8 (Stand: avr-libc Vers. 1.0.4)&lt;br /&gt;
&lt;br /&gt;
== Was macht das Hauptprogramm ==&lt;br /&gt;
&lt;br /&gt;
Im einfachsten Fall gar nichts mehr.&amp;lt;br /&amp;gt;&lt;br /&gt;
Es ist also durchaus denkbar, ein Programm zu schreiben, welches in der&lt;br /&gt;
main-Funktion lediglich noch die Interrupts aktiviert und dann in eine&lt;br /&gt;
Endlosschleife folgender Art verzweigt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    for (;;) {}&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Normalerweise wird man allerdings in den Interruptroutinen die Interrupts&lt;br /&gt;
erfassen und im Hauptprogramm dann gemütlich auswerten.&lt;br /&gt;
&lt;br /&gt;
Wie wir im bisherigen Kursverlauf gesehen haben ist es ohnehin mit so&lt;br /&gt;
schnellen Controller meistens gar nicht unbedingt notwendig mit&lt;br /&gt;
Interruptfunktionen zu arbeiten.&amp;lt;br /&amp;gt;&lt;br /&gt;
Es ist allerdings auch zu bemerken, dass mit den Interruptroutinen ein Programm&lt;br /&gt;
sehr schön strukturiert werden kann, wenn man es richtig macht.&lt;br /&gt;
&lt;br /&gt;
* siehe auch: [http://www.nongnu.org/avr-libc/user-manual/index.html Dokumentation der avr-libc] Abschnitt Modules/Interrupts and Signals&lt;br /&gt;
&lt;br /&gt;
= Speicherzugriffe =&lt;br /&gt;
&lt;br /&gt;
Atmel AVR-Controller verfügen typisch über drei Speicher:&lt;br /&gt;
&lt;br /&gt;
* [[RAM]]: Im RAM (eigentlich [[SRAM]]) wird vom gcc-Compiler Platz für Variablen reserviert. Auch der Stack befindet sich im RAM. Dieser Speicher ist &amp;quot;flüchtig&amp;quot;, d.h. der Inhalt der Variablen geht beim Ausschalten oder einem Zusammenbruch der Spannungsversorgung verloren.&lt;br /&gt;
&lt;br /&gt;
* Programmspeicher: Ausgeführt als [[FLASH]]-Speicher, seitenweise wiederbeschreibbar. Darin ist das Anwendungsprogramm abgelegt.&lt;br /&gt;
&lt;br /&gt;
* [[EEPROM]]: Nichtflüchtiger Speicher, d.h. der einmal geschriebene Inhalt bleibt auch ohne Stromversorgung erhalten. Byte-weise schreib/lesbar. Im EEPROM werden typischerweise gerätespezifische Werte wie z.B. Kalibrierungswerte von Sensoren abgelegt.&lt;br /&gt;
&lt;br /&gt;
Einige AVRs besitzen keinen RAM-Speicher, lediglich die Register können als &amp;quot;Arbeitsvariablen&amp;quot;&lt;br /&gt;
genutzt werden. Da die Anwendung des avr-gcc auf solch &amp;quot;kleinen&amp;quot; Controllern ohnehin wenig Sinn macht und auch nur bei einigen RAM-losen Typen nach &amp;quot;Bastelarbeiten&amp;quot; möglich ist, werden diese Controller hier nicht weiter berücksichtigt. Auch EEPROM-Speicher ist nicht auf allen Typen verfügbar. Generell sollten die nachfolgenden Erläuterungen auf alle ATmega-Controller und die größeren AT90-Typen übertragbar sein.&lt;br /&gt;
&lt;br /&gt;
== RAM ==&lt;br /&gt;
&lt;br /&gt;
Die Verwaltung des RAM-Speichers erfolgt durch den Compiler, im Regelfall ist beim Zugriff auf Variablen im RAM nichts besonderes zu beachten. Die Erläuterungen in jedem brauchbaren C-Buch gelten auch für den vom avr-gcc-Compiler erzeugten Code.&lt;br /&gt;
&lt;br /&gt;
== Programmspeicher (Flash) ==&lt;br /&gt;
&lt;br /&gt;
Ein Zugriff auf Konstanten im Programmspeicher ist mittels avr-gcc nicht &amp;quot;transparent&amp;quot; möglich. D.h. es sind besondere Zugriffsfunktionen erforderlich um Daten aus diesem Speicher zu lesen. Grundsätzlich basieren alle Zugriffsfunktionen auf der Assembler-Anweisung lpm (load program memory). Die Standard-Laufzeitbibliothek des avr-gcc, die [[avr-libc]], stellt diese Funktionen nach einbinden der Header-Datei pgmspace.h zur Verfügung. Mit diesen Funktionen können einzelne Bytes, Datenworte (16bit) und Datenblöcke geschrieben und gelesen werden. &lt;br /&gt;
&lt;br /&gt;
Deklarationen von Variablen im Flash-Speicher werden durch das &amp;quot;Attribut&amp;quot; PROGMEM ergänzt. Einige Beispiele:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/pgmspace.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
/* Byte */&lt;br /&gt;
const uint8_t pgmFooByte PROGMEM = 123;&lt;br /&gt;
&lt;br /&gt;
/* Wort */&lt;br /&gt;
const uint16_t pgmFooWort PROGMEM = 12345;&lt;br /&gt;
&lt;br /&gt;
/* Byte-Feld */&lt;br /&gt;
const uint8_t pgmFooByteArray1[] PROGMEM = { 18, 3 ,70 };&lt;br /&gt;
const uint8_t pgmFooByteArray2[] PROGMEM = { 30, 7 ,79 };&lt;br /&gt;
&lt;br /&gt;
/* Zeiger */&lt;br /&gt;
const uint8_t *pgmPointerToArray1 PROGMEM = pgmFooByteArray1;&lt;br /&gt;
const uint8_t *pgmPointerArray[] PROGMEM = { pgmFooByteArray1, pgmFooByteArray1 };&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Byte lesen ===&lt;br /&gt;
&lt;br /&gt;
Mit der Funktion pgm_read_byte aus pgmspace.h erfolgt der Zugriff auf die Daten. Parameter der Funktion ist die Adresse des Bytes im Flash-Speicher.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
    // Wert der Ram-Variablen myByte auf den Wert von pgmFooByte setzen:&lt;br /&gt;
    uint8_t myByte;&lt;br /&gt;
&lt;br /&gt;
    myByte = pgm_read_byte(&amp;amp;pgmFooByte);&lt;br /&gt;
    // myByte hat nun den Wert 123&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
    // Schleife ueber ein Array aus Byte-Werten im Flash&lt;br /&gt;
    uint8_t i;&lt;br /&gt;
&lt;br /&gt;
    for (i=0;i&amp;lt;3;i++) {&lt;br /&gt;
        myByte = pgm_read_byte(&amp;amp;pgmFooByteArray1[i]);&lt;br /&gt;
        // mach&#039; was mit myByte...&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Wort lesen ===&lt;br /&gt;
&lt;br /&gt;
Für &amp;quot;einfache&amp;quot; 16-bit breite Variablen erfolgt der Zugriff analog zum Byte-Beispiel jedoch mit der Funktion pgm_read_word.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
    uint16_t myWord;&lt;br /&gt;
&lt;br /&gt;
    myWord = pgm_read_word(&amp;amp;pgmFooWord);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zeiger auf Werte im Flash sind ebenfalls 16 Bits &amp;quot;gross&amp;quot;. (Die avr-libc pgmspace-Funktionen unterstützen nur die unteren 64kB Flash bei Controllern mit mehr als 64kB.) Pointer müssen gegebenenfalls &amp;quot;gecastet&amp;quot; werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
    uint8_t *ptrToArray;&lt;br /&gt;
&lt;br /&gt;
    ptrToArray = (uint8_t*)(pgm_read_word(&amp;amp;pgmPointerToArray1));&lt;br /&gt;
    // ptrToArray zeigt nun auf das erste Element des Byte-Arrays pgmPointerToArray1&lt;br /&gt;
&lt;br /&gt;
    for (i=0;i&amp;lt;3;i++) {&lt;br /&gt;
        myByte = pgm_read_byte(ptrToArray+i);&lt;br /&gt;
        // mach&#039; was mit myByte... (18, 3, 70)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    ptrToArray = (uint8_t*)(pgm_read_word(&amp;amp;pgmPointerArray[1]));&lt;br /&gt;
    &lt;br /&gt;
    // ptrToArray zeigt nun auf das erste Element des Byte-Arrays pgmPointerToArray2&lt;br /&gt;
    // da im zweiteb Element des Pointer-Arrays pgmPointerArray die Adresse&lt;br /&gt;
    // von pgmPointerToArray2 abgelegt ist&lt;br /&gt;
&lt;br /&gt;
    for (i=0;i&amp;lt;3;i++) {&lt;br /&gt;
        myByte = pgm_read_byte(ptrToArray+i);&lt;br /&gt;
        // mach&#039; was mit myByte... (30, 7, 79)&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Datenblock lesen ===&lt;br /&gt;
&lt;br /&gt;
TODO: Beispiele, structs, strings, union-&amp;quot;trick&amp;quot; fuer floats&lt;br /&gt;
&lt;br /&gt;
=== Vereinfachung für Zeichenketten (Strings) im Flash ===&lt;br /&gt;
&lt;br /&gt;
Zeichenketten können innerhalb des Quellcodes als &amp;quot;Flash-Variablen&amp;quot; ausgewiesen werden. Dazu dient das Makro PSTR aus pgmspace.h. Dies erspart die getrennte Deklaration mit PROGMEM-Attribut.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/pgmspace.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#define MAXLEN 30&lt;br /&gt;
&lt;br /&gt;
char StringImFlash[] PROGMEM = &amp;quot;Erwin Lindemann&amp;quot;; // im &amp;quot;Flash&amp;quot;&lt;br /&gt;
char StringImRam[MAXLEN];&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
    strcpy(StringImRam, &amp;quot;Mueller-Luedenscheidt&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
    if (!strncmp_P(StringImRam, StringImFlash, 5) { &lt;br /&gt;
        // mach&#039; was, wenn die ersten 5 Zeichen identisch - hier nicht&lt;br /&gt;
    }&lt;br /&gt;
    else {&lt;br /&gt;
        // der Code hier wuerde ausgefuehrt &lt;br /&gt;
    } &lt;br /&gt;
&lt;br /&gt;
    if (!strncmp_P(StringImRam, PSTR(&amp;quot;Mueller-Schmitt&amp;quot;), 5)) {&lt;br /&gt;
        // der Code hier wuerde ausgefuerht, die ersten 5 Zeichen stimmen ueberein&lt;br /&gt;
    }&lt;br /&gt;
    else {&lt;br /&gt;
        // wuerde bei nicht-Uebereinstimmung ausgefuehrt&lt;br /&gt;
    }&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Übergibt man Zeichenketten (genauer: die Adresse des ersten Zeichens), die im Flash abglegt sind an eine Funktion, muss diese entsprechend programmiert sein. Die Funktion selbst hat keine Möglichkeit zu unterscheiden ob es sich um eine Adresse im Flash  oder im RAM handelt. Die avr-libc und viele andere avr-gcc-Bibliotheken halten sich an die Konvention, dass Namen von Funktionen die Flash-Adressen erwarten mit dem Suffix _p (oder _P) versehen sind. &lt;br /&gt;
&lt;br /&gt;
Von einigen Bibliotheken werden Makros definiert, die &amp;quot;automatisch&amp;quot; ein PSTR bei Verwendung einer Funktion einfügen. Ein Blick in den Header-File der Bibliothek zeigt, ob dies der Fall ist. Ein Beispiel aus P. Fleurys lcd-Library:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
// Ausschnitt aus dem Header-File lcd.h der &amp;quot;Fleury-LCD-Lib.&amp;quot;&lt;br /&gt;
...&lt;br /&gt;
extern void lcd_puts_p(const char *progmem_s);&lt;br /&gt;
#define lcd_puts_P(__s) lcd_puts_p(PSTR(__s))&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
// in einer Anwendung (wieauchimmmer.c)&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/pgmspace.h&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;quot;lcd.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
char StringImFlash[] PROGMEM = &amp;quot;Erwin Lindemann&amp;quot;; // im &amp;quot;Flash&amp;quot;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
    lcd_puts_p(StringImFlash); &lt;br /&gt;
    lcd_puts_P(&amp;quot;Dr. Kloebner&amp;quot;); &lt;br /&gt;
    // daraus wird wg. #define lcd_put_P...:  lcd_puts_p( PSTR(&amp;quot;Dr. Kloebner&amp;quot;) );&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Flash in der Anwendung schreiben ===&lt;br /&gt;
&lt;br /&gt;
Bei AVRs mit &amp;quot;self-programming&amp;quot;-Option (auch bekannt als Bootloader-Support) können Teile des Flash-Speichers auch vom Anwendungsprogramm selbst beschrieben werden. Dies ist nur möglich, wenn die Schreibfunktionen in einem besonderen Speicherbereich (boot-section) des Programmspeichers/Flash abgelegt sind. Für Details sei hier auf das jeweilige Controller-Datenblatt und die Erläuterungen zum Modul boot.h der avr-libc verwiesen. Es existieren auch Application-Notes dazu bei atmel.com, die auf avr-gcc-Code übertragbar sind.&lt;br /&gt;
&lt;br /&gt;
=== Warum so kompliziert? ===&lt;br /&gt;
&lt;br /&gt;
Zu dem Thema, warum die Verabeitung von Werten aus dem Flash-Speicher so &amp;quot;kompliziert&amp;quot; ist, sei hier nur kurz erläutert: Die Harvard-Architektur des AVR weist getrennte Adressräume für Programm(Flash)- und Datenspeicher(RAM) auf. Der C-Standard und der gcc-Compiler sehen keine unterschiedlichen Adressräume vor. &lt;br /&gt;
Hat man zum Beispiel eine Funktion string_an_uart(const char* s) und übergibt an diese Funktion die Adresse einer Zeichenkette (einen Pointer, z.B. 0x01ff), &amp;quot;weiss&amp;quot; die Funktion nicht, ob die Adresse auf den Flash-Speicher oder den/das RAM zeigt. Allein aus dem Pointer-Wert (der Zahl) kann nicht geschlossen werden, ob ein &amp;quot;einfaches&amp;quot; zeichen_an_uart(s[i]) oder zeichen_an_uart(pgm_read_byte(&amp;amp;s[i]) genutzt werden muss, um das i-te Zeichen auszugeben.&lt;br /&gt;
&lt;br /&gt;
Einige AVR-Compiler &amp;quot;tricksen&amp;quot; etwas, in dem sie für einen Pointer nicht nur die Adresse anlegen, sondern zusätzlich noch den Ablageort (Flash oder RAM) sichern. Dies hat jedoch nicht nur Vorteile; Erläuterungen warum dies so ist, führen an dieser Stelle zu weit.&lt;br /&gt;
&lt;br /&gt;
* siehe auch: [http://www.nongnu.org/avr-libc/user-manual/index.html Dokumentation der avr-libc] Abschnitte Modules/Program Space String Utilities und Abschnitt Modules/Bootloader Support Utilities&lt;br /&gt;
&lt;br /&gt;
== EEPROM ==&lt;br /&gt;
&lt;br /&gt;
Man beachte, das der EEPROM-Speicher nur eine begrenzte Anzahl von Schreibzugriffen zulässt. Beschreibt man eine EEPROM-Zelle öfter als die im Datenblatt zugesicherte Anzahl (typisch 100.000) wird die Funktion der Zelle nicht mehr garantiert. &lt;br /&gt;
Dies gilt für jede einzelne Zelle. Bei geschickter Programmierung (z.B. Ring-Puffer), bei der die zu beschreibenden Zellen regelmässig gewechselt werden, kann man eine deutlich höhere Anzahl an Schreibzugriffen, bezogen auf den Gesamtspeicher, erreichen.&lt;br /&gt;
&lt;br /&gt;
Schreib- und Lesezugriffe auf den EEPROM-Speicher erfolgen über die im Modul eeprom.h definierten Funktionen. Mit diesen Funktionen können einzelne Bytes, Datenworte (16bit) und Datenblöcke geschrieben und gelesen werden. &lt;br /&gt;
&lt;br /&gt;
Bei Nutzung des EEPROMs ist zu beachten, das vor dem Zugriff auf diesen Speicher abgefragt wird, ob der Controller die vorherige EEPROM-Operation abgeschlossen hat. Die avr-libc-Funktionen beinhalten diese Prüfung, man muss sie nicht selbst implementieren. Man sollte auch verhindern, dass der Zugriff durch die Abarbeitung einer Interrupt-Routine unterbrochen wird, da bestimme Befehlsabfolgen vorgeben sind (&amp;quot;timed sequence&amp;quot;). Diese Prüfung wird nicht implizit durchgeführt. Im Zweifel kann man Sicherheitshalber bei EEPROM-Zugriffen die Interrupts global deaktivieren, z.B. so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    uint8_t sreg;&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
    sreg = SREG;&lt;br /&gt;
    cli();&lt;br /&gt;
&lt;br /&gt;
/* hier die eeprom-Zugriffe */&lt;br /&gt;
&lt;br /&gt;
    SREG = sreg;&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bei der Deklaration einer Variable im EEPROM, ist das Attribut für die Section &amp;quot;.eeprom&amp;quot; zu ergänzen. Die Nutzung einer Präprozessor-Ersetzung bringt etwas Bequemlichkeit. Siehe dazu folgendes Beispiel.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/eeprom.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// alle Textstellen EEPROM im Quellcode durch __attribute__ ... ersetzen&lt;br /&gt;
#define EEPROM  __attribute__ ((section (&amp;quot;.eeprom&amp;quot;)))&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
/* Byte */&lt;br /&gt;
uint8_t eeFooByte EEPROM = 123;&lt;br /&gt;
&lt;br /&gt;
/* Wort */&lt;br /&gt;
uint16_t eeFooWort EEPROM = 12345;&lt;br /&gt;
&lt;br /&gt;
/* Byte-Feld */&lt;br /&gt;
uint8_t eeFooByteArray1[] EEPROM = { 18, 3 ,70 };&lt;br /&gt;
uint8_t eeFooByteArray2[] EEPROM = { 30, 7 ,79 };&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
TODO: read_block erläutern &amp;quot;union-trick&amp;quot;, structs etc.&lt;br /&gt;
&lt;br /&gt;
=== Bytes lesen/schreiben ===&lt;br /&gt;
&lt;br /&gt;
Die avr-libc Funktion zum Lesen eines Bytes heisst eeprom_read_byte. Parameter ist die Adresse des Bytes im EEPROM. Geschrieben wird über die Funktion eeprom_write_byte mit den Parametern Adresse und Inhalt. Anwendungsbeispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    uint8_t myByte;&lt;br /&gt;
    uint8_t sreg;&lt;br /&gt;
&lt;br /&gt;
    sreg = SREG; // (1)&lt;br /&gt;
    cli();       // (1)&lt;br /&gt;
&lt;br /&gt;
    myByte = eeprom_read_byte(&amp;amp;eeFooByte); // lesen&lt;br /&gt;
    // myByte hat nun den Wert 123&lt;br /&gt;
...&lt;br /&gt;
    myByte = 99;&lt;br /&gt;
    eeprom_write_byte(&amp;amp;eeFooByte, myByte); // schreiben&lt;br /&gt;
...&lt;br /&gt;
    SREG = sreg; // (1)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die mit (1) markierten Zeilen dienen hierbei dem (möglicherweise übertriebenen) Schutz vor Unterbrechnungen durch Interrupts.&lt;br /&gt;
&lt;br /&gt;
=== Wort lesen/schreiben ===&lt;br /&gt;
&lt;br /&gt;
Schreiben und Lesen von Datenworten erfolgt analog zur Vorgehensweise bei Bytes:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
    uint16_t myWord;&lt;br /&gt;
&lt;br /&gt;
    myWord = eeprom_read_word(&amp;amp;eeFooWord); // lesen&lt;br /&gt;
    // myWord hat nun den Wert 12345&lt;br /&gt;
...&lt;br /&gt;
    myWord = 2222;&lt;br /&gt;
    eeprom_write_word(&amp;amp;eeFooWord, myWord); // schreiben&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Block lesen/schreiben ===&lt;br /&gt;
&lt;br /&gt;
TODO&lt;br /&gt;
&lt;br /&gt;
=== EEPROM-Speicherabbild in .eep-Datei ===&lt;br /&gt;
&lt;br /&gt;
Eine besondere Funktion des avr-gcc ist, dass mit einem entsprechenden makefile aus den Initialisierungswerten der Variablen im Quellcode eine Datei erzeugt werden kann, die man auf den Controller programmieren kann (.eep-Datei). Damit können sehr elegant Standardwerte für den EEPROM-Inhalt im Quellcode definiert werden. Die Vorgehensweise wird aus dem [[WinAVR]]-Beispielmakefile ersichtlich.&lt;br /&gt;
&lt;br /&gt;
=== Bekannte Probleme bei den EEPROM-Funktionen ===&lt;br /&gt;
&lt;br /&gt;
Vorsicht: Nicht alle neuen AVR Controller werden von avr-libc/eeprom.h untersützt (Stand Version 1.0.4). Insbesondere beim ATMega169 funktionieren die Funktionen nicht korrekt (Ursache: unterschiedliche Speicheradressen der EEPROM-Register) Etwas ältere Typen, oder zu den &amp;quot;etablierten&amp;quot; Controllern kompatible, bereiten jedoch hier keine Proleme. Im Zweifel hilft ein Blick in den vom Compiler erzeugten Assembler-Code (lst/lss-Dateien).&lt;br /&gt;
&lt;br /&gt;
* siehe auch: [http://www.nongnu.org/avr-libc/user-manual/index.html Dokumentation der avr-libc] Abschnitt Modules/EEPROM handling&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Externe Baugrupen =&lt;br /&gt;
==I2C==&lt;br /&gt;
===Master===&lt;br /&gt;
[http://homepage.sunrise.ch/mysunrise/pfleury/group__pfleury__ic2master.html I2C Master library]&lt;br /&gt;
===Slave===&lt;br /&gt;
==CAN==&lt;br /&gt;
&lt;br /&gt;
==LCD==&lt;br /&gt;
=== HD44870===&lt;br /&gt;
[http://homepage.sunrise.ch/mysunrise/pfleury/group__pfleury__lcd.html LCD]&lt;br /&gt;
=== Nokia3310===&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Diskussion:Snippets&amp;diff=4306</id>
		<title>Diskussion:Snippets</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Diskussion:Snippets&amp;diff=4306"/>
		<updated>2004-09-25T20:47:11Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Zum ADC-Code:&lt;br /&gt;
* Unter welchen Bedingungen anwendbar? (// Kommentar?)&lt;br /&gt;
* ADC-Wandler immer wieder von neuem &amp;quot;einschalten&amp;quot;? Trennung ADC_init(), ADC_read(channel) oder verglb. duerfte in Snippetsammlung besser sein&lt;br /&gt;
* Welcher ADC-Modus? Welche Wandlerfrequenz? Prescaler? Evtl. Prescaler-&amp;quot;Rechen&amp;quot;-Macro oder #defines(// Kommentar?)&lt;br /&gt;
* &#039;&#039;&#039;Kommentare fehlen&#039;&#039;&#039;. Bei einem &amp;quot;ueberall reinkopier-Snippet&amp;quot; eigentlich obligatorisch (ist ja keine Libray mit entspr. Dokumentation).&lt;br /&gt;
* Portabilitaet zw. AVRs?&lt;br /&gt;
* uint32_t in einem Snippet zum &amp;quot;schnell mal reinkopieren&amp;quot;? bei 10-bit Wandlern? Die Variable &amp;quot;schnell mal zwischendurch&amp;quot; zu deklarieren ist wenn recht erinnert auch kein &amp;quot;Standard-C&amp;quot;&lt;br /&gt;
Nichts fuer Ungut und es ist ja nur eine Einzelmeinung: Code erstmal wieder von der Seite löschen und nochmal überarbeiten. Keine Ahnung wieviel Leute die Schnippsel nutzen, aber mit dem jetzigen Stand ist das eher ein &amp;quot;friss oder stirb&amp;quot;, das auch &amp;quot;meistens&amp;quot; halbwegs funktioniert.  Ein &amp;quot;funktioniert bei mir&amp;quot; ohne Erläuterung was das &amp;quot;bei mir&amp;quot; ist, macht noch keinen &amp;quot;guten&amp;quot; Quellcodeschnippsel. Wie waere es mit einem Artikel &amp;quot;AVR-Tutorial: ADC in C&amp;quot; vergleichbar mit dem UART-Teil im avr-Tutorial von dl8dt? Darin koennte man vergleichbaren Code nach ein paar Erläuterungen einfügen. Dann könnte der entspr. Abschnitt im gcc-Tutorial stark gekuerzt werden und auf diesen neuen Artikel verwiesen werden und die &amp;quot;Schnippselsammlungsseite&amp;quot; verweist dann ebenfalls darauf. MfG M. Thomas&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ich halte nicht viel von einer allgemeinen &amp;quot;Snippets&amp;quot;-Seite. Welchen praktischen Nutzen soll das haben? Man geht üblicherweise nicht auf die Suche nach &#039;&#039;irgend einem&#039;&#039; Snippet, sondern man braucht Informationen für eine bestimmte Anwendung und einen bestimmten Controller. Deshalb denke ich dass jeweils eine Seite zu AD-Wandlung mit AVR, LCD-Ansteuerung usw. viel mehr Sinn macht.&lt;br /&gt;
--[[Benutzer:Andreas|Andreas]] 09:09, 23. Sep 2004 (CEST)&lt;br /&gt;
&lt;br /&gt;
hi!&lt;br /&gt;
&lt;br /&gt;
zum quelltext:&lt;br /&gt;
selbstverständlich sind die beiden snippets verbesserungswürdig, aber dafür ist ja auch ein wiki da; wenn ich zeit hab verbessere ich die quelltexte.&lt;br /&gt;
&lt;br /&gt;
@andreas:&lt;br /&gt;
&lt;br /&gt;
ich sehe in einer snippetsammlung den vorteil, die sachen schnell zu finden die man regelmäßig braucht und sich nicht immer im kopf behalten kann.&lt;br /&gt;
daher sollte die snippetsammlung auch eventuell quelltextteile von anderen artikeln enthalten.&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Snippets&amp;diff=4295</id>
		<title>Snippets</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Snippets&amp;diff=4295"/>
		<updated>2004-09-22T21:47:11Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Auf dieser Seite können kleine, oft verwendbare Quelltexte (Snippets) abgelegt und abgerufen werden.&lt;br /&gt;
&lt;br /&gt;
=allgemeine Probleme unterschiedlicher Programmiersprachen=&lt;br /&gt;
&lt;br /&gt;
==Assembler==&lt;br /&gt;
[[Bitmanipulation]]&lt;br /&gt;
&lt;br /&gt;
==C==&lt;br /&gt;
[[Bitmanipulation]]&lt;br /&gt;
&lt;br /&gt;
=AVR= &lt;br /&gt;
==Assembler==&lt;br /&gt;
==AVR-GCC==&lt;br /&gt;
===I/O===&lt;br /&gt;
====TWI====&lt;br /&gt;
====USART====&lt;br /&gt;
====ADC====&lt;br /&gt;
&lt;br /&gt;
===== Auslesen eines Analogports ===== &lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
 // Führt eine AD Conversation durch&lt;br /&gt;
 // Liefert den Wert (0-1023) an PORT ADC(src) zurück&lt;br /&gt;
 uint16_t ReadValue(uint8_t src)&lt;br /&gt;
 {&lt;br /&gt;
   ADMUX = src;&lt;br /&gt;
   ADCSR = _BV(ADEN)  | _BV(ADSC) | _BV(ADPS2);&lt;br /&gt;
   while (bit_is_set (ADCSR, ADSC));  &lt;br /&gt;
   return ADC;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
===== Pegelanpassung =====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre class=&amp;quot;code&amp;quot;&amp;gt;&lt;br /&gt;
 // Führt eine AD Conversation durch&lt;br /&gt;
 // Liefert die Spannung (0-5000mV) an PORT ADC(src) zurück&lt;br /&gt;
 #define ADCVCC 5000 // Spannug des AD-Converters in mV&lt;br /&gt;
 uint16_t ReadValue(uint8_t src)&lt;br /&gt;
 {&lt;br /&gt;
   ADMUX = src;&lt;br /&gt;
   ADCSR = _BV(ADEN)  | _BV(ADSC) | _BV(ADPS2);&lt;br /&gt;
   while (bit_is_set (ADCSR, ADSC)) ;  &lt;br /&gt;
 &lt;br /&gt;
   uint32_t  value = ADC;&lt;br /&gt;
   value *= ADCVCC;&lt;br /&gt;
   value &amp;gt;&amp;gt;= 10;&lt;br /&gt;
   return (uint16_t)value;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==BASCOM-AVR==&lt;br /&gt;
&lt;br /&gt;
=&amp;quot;Hardware&amp;quot;-Snippets=&lt;br /&gt;
==Sensoren==&lt;br /&gt;
===Wie schließe ich ein Display an einen Mikrokontroller===&lt;br /&gt;
Ein &amp;quot;normales&amp;quot;  Textdisplay  (HD44780 o.ä. Controller) hat schließt du folgendermaßen an:&lt;br /&gt;
{|border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Pin am LCD 	|| angeschlossen an&lt;br /&gt;
|- &lt;br /&gt;
&lt;br /&gt;
|1 (VSS)         || GND&lt;br /&gt;
|- &lt;br /&gt;
|2 (VCC)         || +5V&lt;br /&gt;
|- &lt;br /&gt;
|3 (Kontrast)    || Kontrastregelung (siehe unten)&lt;br /&gt;
|- &lt;br /&gt;
|4 (RS)          || beliebiger Port (z.B. PA4)&lt;br /&gt;
|- &lt;br /&gt;
|5 (R/W)         || beliebiger Port (z.B. PA5) oder GND (wenn das Display nicht ausgelesen werden muss) &lt;br /&gt;
|- &lt;br /&gt;
|6 (E)           || beliebiger Port (z.B. PA6)&lt;br /&gt;
|- &lt;br /&gt;
|7 (D0)          || -&lt;br /&gt;
|- &lt;br /&gt;
|8 (D1)          || -&lt;br /&gt;
|- &lt;br /&gt;
|9 (D2)          || -&lt;br /&gt;
|- &lt;br /&gt;
|10 (D3)         || -&lt;br /&gt;
|- &lt;br /&gt;
|11 (D4)         || beliebiger Port (z.B. PA0)&lt;br /&gt;
|- &lt;br /&gt;
|12 (D5)         || beliebiger Port (z.B. PA1)&lt;br /&gt;
|- &lt;br /&gt;
|13 (D6)         || beliebiger Port (z.B. PA2)&lt;br /&gt;
|- &lt;br /&gt;
|14 (D7)         || beliebiger Port (z.B. PA3)&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
an den Kontrast-Port schließt du einen Poti an:&lt;br /&gt;
&lt;br /&gt;
  VCC&lt;br /&gt;
  |&lt;br /&gt;
  |&lt;br /&gt;
  ##&lt;br /&gt;
  ##-----&amp;gt; zum Kontrast-Port&lt;br /&gt;
  ## &lt;br /&gt;
  |&lt;br /&gt;
  |&lt;br /&gt;
 GND&lt;br /&gt;
&lt;br /&gt;
==I/O==&lt;br /&gt;
===Wie schließe ich einen MOSFET an einen Mikrocontroller===&lt;br /&gt;
TODO: Pinbelegung eines typischen MOSFETS&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
{|border=&amp;quot;1&amp;quot;&lt;br /&gt;
!Pin am MOSFET  || angeschlossen an&lt;br /&gt;
|- &lt;br /&gt;
|Gate || Port des µCs&lt;br /&gt;
|- &lt;br /&gt;
|Drain || Du &amp;quot;ersetzt&amp;quot; den Masseanschluss deines Gerätes (Lampe o.ä.) durch den Drain-Anschluss&lt;br /&gt;
|- &lt;br /&gt;
|Source || GND&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Wenn der µC eine Spannung an das Gate anlegt, schaltet der MOSFET die Leitung zwicshen Drain und Source durch. Es besteht fließt kein Strom zwischen Gate und Source, d.h. es muss kein Vorwiderstand benutzt werden.&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Schaltplaneditoren&amp;diff=4262</id>
		<title>Schaltplaneditoren</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Schaltplaneditoren&amp;diff=4262"/>
		<updated>2004-09-11T09:10:47Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: gschem, Target3001 .. hinzugefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Eagle=&lt;br /&gt;
[[Bild:Eagle.png|right|thumb|Screenshot]]&lt;br /&gt;
Eagle von Cadsoft ist nicht nur ein Schaltplaneditor, sondern ein komplettes Paket mit Layoutprogramm und [[Autorouter]]. Das hat den Vorteil, dass man einen erstellten Schaltplan gleich zur Platine &amp;quot;weiterverarbeiten&amp;quot; kann.&lt;br /&gt;
&lt;br /&gt;
Mitgeliefert werden umfangreiche Bauteilbibliotheken, von [[Widerstand|Widerständen]] in allen Bauformen über [[Taster]] bis hin zu [[AVR]]s (eine Library für viele aktuelle AVRs findet sich im Dowload-Bereich von [http://www.embedit.de http://www.embedit.de]).&lt;br /&gt;
&lt;br /&gt;
Eagle läuft unter [[Linux]], [[Windows]] und [[Mac OS|Mac OS X]].&lt;br /&gt;
&lt;br /&gt;
Eine für nichtkommerzielle Anwendungen kostenlose Version ist auf http://www.cadsoft.de/ erhältlich. Diese ist auf zweilagige Platinen im halben Euro-Format (80x100mm) sowie Schaltpläne mit nur einer Seite beschränkt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=PCB=&lt;br /&gt;
&#039;&#039;&#039;PCB&#039;&#039;&#039; ist ein freies Programm zum Erstellen von Platinenlayouts. Es wurde ursprünglich für den Atari St entwickelt und später nach Unix portiert.&lt;br /&gt;
&lt;br /&gt;
PCB hat einen Autorouter. Zum Zeichnen der Schaltpläne kann [[gschem]] verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Als Ausgabeformate stehen [http://de.wikipedia.org/wiki/Postscript Postscript] und [[Gerber]] RS-274-X zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
PCB läuft hauptsächlich unter [[Linux]], kann allerdings auch unter [[Windows]] ([[cygwin]]) betrieben werden&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Gschem=&lt;br /&gt;
[[Bild:Gschem.png|right|thumb|Screenshot]]&lt;br /&gt;
gschem ist der Schaltplaneditor aus dem Open Source Projekt [[gEDA]]. gschem wird hauptsächlich auf [[Linux]] Rechnern entwickelt, läuft aber auch auf anderen [[Unix]] Betriebssystemen und unter [[Windows]]. gschem ist für die Linuxdistributionen RedHat und Debian als Packet verfügbar, für Windows ist nur eine ältere Version erhältlich und für alle anderen ist selber kompilieren angesagt.&lt;br /&gt;
&lt;br /&gt;
Die Bedienung ist nicht sonderlich anfängerfreundlich. Hat man sich aber mal daran gewöhnt, dass jeder Menupunkt mit 1 oder 2 Tasten erreichbar ist, läßt sich&#039;s mit gschem prima arbeiten. In der Symbolbibliothek (die auch online betrachtet werden kann) sind etwas mehr als 1000 Symbole.&lt;br /&gt;
&lt;br /&gt;
Die Schaltpläne lassen sich als png und als Postscript exportieren. Netzlisten (für [[PCB_(Software)| PCB]], [[BAE]], [[spice]], pads, ... ) lassen sich mit dem Programm gnetlist generieren.&lt;br /&gt;
&lt;br /&gt;
Nähere Informationen über gschem (gEDA) gibt es unter http://www.geda.seul.org.&lt;br /&gt;
&lt;br /&gt;
=BAE=&lt;br /&gt;
Bartels AutoEngineer unterstützt die Erstellung von Schaltplänen, Leiterkarten und integrierten Schaltungen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://www.bartels.de/bae_de.html BAE Homepage]&lt;br /&gt;
&lt;br /&gt;
=Target3001=&lt;br /&gt;
&lt;br /&gt;
Target bietet folgende Funktionen&lt;br /&gt;
&lt;br /&gt;
*Schaltplan&lt;br /&gt;
*Schaltungssimulation&lt;br /&gt;
*Layout mit Autoplatzierer&lt;br /&gt;
*Autorouter&lt;br /&gt;
&lt;br /&gt;
Es gibt eine für nicht kommerzielle Anwendungen kostenlose Version. Diese ist auf 100 Pins/Pads sowie auf zwei Kupferlagen beschränakt.&lt;br /&gt;
&lt;br /&gt;
Target3001 ist auf Windows beschränakt.&lt;br /&gt;
&lt;br /&gt;
[http://www.ibfriedrich.com/home.htm Target3001 Homepage]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Weblinks =&lt;br /&gt;
&lt;br /&gt;
* [http://www.cadsoft.de/ Eagle]&lt;br /&gt;
* [http://www.ibfriedrich.com/home.htm Target3001 Homepage]&lt;br /&gt;
* [http://www.bartels.de/bae_de.html BAE Homepage]&lt;br /&gt;
* [http://www.geda.seul.org gschem]&lt;br /&gt;
* [http://pcb.sourceforge.net/index.html PCB]&lt;br /&gt;
* [http://web.wt.net/~billw/gsch2pcb/tutorial.html Tutorial] über das Zusammenspiel von [[gschem]] und PCB. Inklusive Einführung in beide Programme (sehr ausführlich)!&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Target3001&amp;diff=13338</id>
		<title>Target3001</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Target3001&amp;diff=13338"/>
		<updated>2004-09-11T09:07:20Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: Weiterleitung auf Schaltplaneditoren&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Schaltplaneditoren]]&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Mikrocontroller.net_Diskussion:Aufgaben&amp;diff=12187</id>
		<title>Mikrocontroller.net Diskussion:Aufgaben</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Mikrocontroller.net_Diskussion:Aufgaben&amp;diff=12187"/>
		<updated>2004-09-11T08:45:59Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: Begriffsdefinitionen&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Die Lötseiten sollten IMHO nicht zusammengefasst werden, weil sie sonst viel zu lang werden. Sowas liest keiner. -- Markus 18.08.2004&lt;br /&gt;
&lt;br /&gt;
wenn weiterleitungen entfernt werden sollen sollte trotzdem sichergestellt sein, das man zB auch GALs in den Programmierbarenlogikbausteinen wiederfindet...&lt;br /&gt;
&lt;br /&gt;
== Weiterleitungen ==&lt;br /&gt;
&lt;br /&gt;
Ich finde, Weiterleitungen sollten NICHT entfernt werden, es müsste reichen wenn die Kategorieneinteilung keine Weiterleitungsseiten enthält&lt;br /&gt;
&lt;br /&gt;
== Begriffsdefinitionen ==&lt;br /&gt;
&lt;br /&gt;
Alle Kurzen Begriffsdefinitionen sollten wenn möglich in einer Kategorie eingeschlossen werden, aus der Kategorienseite entfernt werden und eventuell wenn möglich als popupfenster realisiert werden&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Mikrocontroller.net_Diskussion:Aufgaben&amp;diff=4115</id>
		<title>Mikrocontroller.net Diskussion:Aufgaben</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Mikrocontroller.net_Diskussion:Aufgaben&amp;diff=4115"/>
		<updated>2004-09-11T08:44:33Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: Weiterleitungen&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Die Lötseiten sollten IMHO nicht zusammengefasst werden, weil sie sonst viel zu lang werden. Sowas liest keiner. -- Markus 18.08.2004&lt;br /&gt;
&lt;br /&gt;
wenn weiterleitungen entfernt werden sollen sollte trotzdem sichergestellt sein, das man zB auch GALs in den Programmierbarenlogikbausteinen wiederfindet...&lt;br /&gt;
&lt;br /&gt;
== Weiterleitungen ==&lt;br /&gt;
&lt;br /&gt;
Ich finde, Weiterleitungen sollten NICHT entfernt werden, es müsste reichen wenn die Kategorieneinteilung keine Weiterleitungsseiten enthält&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Eagle&amp;diff=13252</id>
		<title>Eagle</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Eagle&amp;diff=13252"/>
		<updated>2004-09-11T08:12:51Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: Weiterleitung auf Schaltplaneditoren&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Schaltplaneditoren#Eagle]]&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Testseite&amp;diff=4459</id>
		<title>Testseite</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Testseite&amp;diff=4459"/>
		<updated>2004-09-11T08:12:02Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Schaltplaneditoren#PCB|PCB]]&lt;br /&gt;
&lt;br /&gt;
[[Schaltplaneditoren#Eagle|Eagle]]&lt;br /&gt;
[[Schaltplaneditoren#Weblinks|Weblinks]]&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Testseite&amp;diff=4108</id>
		<title>Testseite</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Testseite&amp;diff=4108"/>
		<updated>2004-09-11T08:10:49Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Testseite&amp;diff=4107</id>
		<title>Testseite</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Testseite&amp;diff=4107"/>
		<updated>2004-09-11T08:10:20Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#REDIRECT [[Hauptseite]]&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Schaltplaneditoren&amp;diff=4119</id>
		<title>Schaltplaneditoren</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Schaltplaneditoren&amp;diff=4119"/>
		<updated>2004-09-11T08:07:06Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: PCB und Eagle hinzugefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Eagle=&lt;br /&gt;
[[Bild:Eagle.png|right|thumb|Screenshot]]&lt;br /&gt;
Eagle von Cadsoft ist nicht nur ein Schaltplaneditor, sondern ein komplettes Paket mit Layoutprogramm und [[Autorouter]]. Das hat den Vorteil, dass man einen erstellten Schaltplan gleich zur Platine &amp;quot;weiterverarbeiten&amp;quot; kann.&lt;br /&gt;
&lt;br /&gt;
Mitgeliefert werden umfangreiche Bauteilbibliotheken, von [[Widerstand|Widerständen]] in allen Bauformen über [[Taster]] bis hin zu [[AVR]]s (eine Library für viele aktuelle AVRs findet sich im Dowload-Bereich von [http://www.embedit.de http://www.embedit.de]).&lt;br /&gt;
&lt;br /&gt;
Eagle läuft unter [[Linux]], [[Windows]] und [[Mac OS|Mac OS X]].&lt;br /&gt;
&lt;br /&gt;
Eine für nichtkommerzielle Anwendungen kostenlose Version ist auf http://www.cadsoft.de/ erhältlich. Diese ist auf zweilagige Platinen im halben Euro-Format (80x100mm) sowie Schaltpläne mit nur einer Seite beschränkt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=PCB=&lt;br /&gt;
&#039;&#039;&#039;PCB&#039;&#039;&#039; ist ein freies Programm zum Erstellen von Platinenlayouts. Es wurde ursprünglich für den Atari St entwickelt und später nach Unix portiert.&lt;br /&gt;
&lt;br /&gt;
PCB hat einen Autorouter. Zum Zeichnen der Schaltpläne kann [[gschem]] verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Als Ausgabeformate stehen [http://de.wikipedia.org/wiki/Postscript Postscript] und [[Gerber]] RS-274-X zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Weblinks =&lt;br /&gt;
&lt;br /&gt;
== Windows ==&lt;br /&gt;
&lt;br /&gt;
* [[Eagle]]&lt;br /&gt;
* [[Target3001]]&lt;br /&gt;
* [[BAE]]&lt;br /&gt;
&lt;br /&gt;
== Linux ==&lt;br /&gt;
&lt;br /&gt;
* [[Eagle]]&lt;br /&gt;
* [[BAE]]&lt;br /&gt;
* [[gEDA]]/[[Gschem]]&lt;br /&gt;
* [http://pcb.sourceforge.net/index.html PCB]&lt;br /&gt;
* [http://web.wt.net/~billw/gsch2pcb/tutorial.html Tutorial] über das Zusammenspiel von [[gschem]] und PCB. Inklusive Einführung in beide Programme (sehr ausführlich)!&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Digitaltechnik&amp;diff=5037</id>
		<title>Digitaltechnik</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Digitaltechnik&amp;diff=5037"/>
		<updated>2004-09-11T07:58:48Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Bit=&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Abkürzung für &#039;&#039;&#039;Bi&#039;&#039;&#039;nary digi&#039;&#039;&#039;t&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Ein Bit ist die kleinste [[digital]]e Einheit, und kann die Werte 0 und 1 annehmen.&lt;br /&gt;
&lt;br /&gt;
Siehe auch&lt;br /&gt;
* [[Bitmanipulation]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Byte= &lt;br /&gt;
&lt;br /&gt;
Abkürzung für &#039;&#039;&#039;B&#039;&#039;&#039;inar&#039;&#039;&#039;y&#039;&#039;&#039; &#039;&#039;&#039;Te&#039;&#039;&#039;rm.&lt;br /&gt;
&lt;br /&gt;
Ein Byte besteht aus 8 [[Bit]]s und kann damit 2^8 = 256 verschiedene Werte annehmen.&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/images/bits.gif&lt;br /&gt;
&lt;br /&gt;
In der üblichen Schreibweise werden die einzelnen [[Bit]]s von rechts nach links abgezählt. &amp;quot;MSB&amp;quot; nennt man das höchstwertige [[Bit]] (ganz links, [[Bit]] 7), &amp;quot;LSB&amp;quot; das niederwertigste (ganz rechts, [[Bit]] 0).&lt;br /&gt;
&lt;br /&gt;
*2 (oder mehr, je nach Maschine) Bytes = 1 [[Word]]&lt;br /&gt;
*1/2 Byte (4Bit) = 1 [[Nibble]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Word=&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ein Word besteht aus zwei oder mehr (2^N) aufeinanderfolgenden [[Byte|Bytes]]. Im Falle von 2 Bytes kann es somit 256*256 = 65536 Werte annehmen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== &#039;&#039;Endianess&#039;&#039; ==&lt;br /&gt;
&lt;br /&gt;
In Verbindung mit einem 16 (oder mehr) Bit [[Prozessor]] ist das Problem interessant, in welcher Reihenfolge die Bytes im Speicher angeordnet sind, also das höherwertige Byte an vorderer oder hinterer Stelle. Die unterschiedliche Art der Darstellung z.B. zwischen den [[X86]] und [[PowerPC]] Prozessoren nennt man &amp;quot;Little Endian&amp;quot; und &amp;quot;Big Endian&amp;quot;. Diese kuriose Bezeichnung lehnt an das Problem an, von welchem Ende man ein Ei aufschlagen sollte.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
 00000000  20 8f 04 08 23 00 00 00  12 00 00 00 1e 00 00 00  | ...#...........|&lt;br /&gt;
 00000010  94 8d 04 08 00 00 00 00  12 00 08 00 &#039;&#039;&#039;e6 01&#039;&#039;&#039; 00 00  |................|&lt;br /&gt;
&lt;br /&gt;
Der markierte Bereich auf Adresse 0x1c zeigt das 16-bit Word mit dem Wert&lt;br /&gt;
&lt;br /&gt;
0xe6 + 256 * 0x01 = 0x01e6 = 486&lt;br /&gt;
&lt;br /&gt;
Die jeweils größeren Adressen enthalten dabei die höherwertigen Bytes des Word.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Auf einer big-endian Maschine würde der Hexdump so aussehen:&lt;br /&gt;
&lt;br /&gt;
 00000000  8f 20 08 04 00 23 00 00  00 12 00 00 00 1e 00 00  |. ...#..........|&lt;br /&gt;
 00000010  8d 94 08 04 00 00 00 00  00 12 00 08 &#039;&#039;&#039;01 e6&#039;&#039;&#039; 00 00  |................|&lt;br /&gt;
&lt;br /&gt;
Die höheren Adressen enthalten hier die niederwertigen Bytes.  Das erscheint auf den ersten Blick unlogisch, hat aber andererseits den Vorteil, daß man die Zahl (0x1e6) &amp;quot;auf den ersten Blick&amp;quot; im Hexdump erkennen kann.&lt;br /&gt;
&lt;br /&gt;
Die little-endian Byteorder wurde zuerst von Intel eingeführt.  Motorola waren die ersten, die big-endian gearbeitet haben.  Viele [[RISC]]-Prozessoren kann man theoretisch per Hardwarebit in ihrer Byteorder umschalten, wobei dies praktisch so früh erfolgen muß, daß die gesamte Maschine (einschließlich [[BIOS]] etc.) darauf eingerichtet sein muß.&lt;br /&gt;
&lt;br /&gt;
Big-endian ist auch die sogenannte &#039;&#039;network byte order&#039;&#039;, d.h. insbesondere im IP-Bereich werden alle Daten &amp;quot;auf dem Draht&amp;quot; in dieser Anordnung übertragen.  Entsprechend müssen little-endian Maschinen in ihren Netzwerkprotokollen sehr viel zwischen beiden Anordnungen übersetzen, so daß es z.B. beim Intel Pentium einen eigenen Prozessorbefehl für diese Operation gibt.&lt;br /&gt;
&lt;br /&gt;
* Typische Vertreter für little-endian sind:&lt;br /&gt;
** [[X86]]&lt;br /&gt;
** Zilog [[Z80]], da er vom Intel 8080 abstammt&lt;br /&gt;
** DEC Alpha&lt;br /&gt;
&lt;br /&gt;
* Typische Vertreter für big-endian sind:&lt;br /&gt;
** Motorola [[MC68000]]&lt;br /&gt;
** [[PowerPC]]&lt;br /&gt;
** [[SPARC]]&lt;br /&gt;
** Zilog [[Z8]] und Z8000&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Größere Prozessoren, &#039;&#039;Alignment&#039;&#039; ==&lt;br /&gt;
&lt;br /&gt;
Prozessoren mit mehr als 16 [[Bit|Bits]] &amp;quot;natürlicher&amp;quot; Breite bezeichnen oft ihre natürliche Breite als Word (also ein 32-bit-Prozessor 4 aufeinanderfolgende Bytes, ein 64-bit-Prozessor 8 aufeinanderfolgende Bytes).  Allerdings wird dies nicht mehr durchweg einheitlich gehandhabt.  Auf einer [[X86]]-Architektur ist es oft unter [[Windows|MS-Windows]] aufgrund seiner Abstammung von einem 16-bit-Betriebssystem üblich, 2 Bytes als Word zu bezeichnen.  Wird der gleiche Prozessor unter [[Unix]] betrieben, bezeichnet ein Word dagegen 4 aufeinanderfolgende Bytes, da das Betriebssystem als 32-bit-System auf diesen Prozessor portiert worden ist (zu Zeiten, da die X86-Architektur bereits eine natürliche Wortbreite von 32 bit hatte, also i386 und höher).&lt;br /&gt;
&lt;br /&gt;
Manche (besonders [[RISC]]-) Prozessoren benötigen bei Zugriffen auf ein Word einen Zugriff, der mit der Wortgröße ausgerichtet worden ist.  Soll beispielsweise bei ihnen auf ein 32-bit Word zugegriffen werden, so muß die Adresse dann ebenfalls durch 4 (= 32 bit) teilbar sein.  Dies wird erforderlich, da der gesamte Prozessor- und Speicherbus in dieser Wortgröße organisiert ist, so daß ein &#039;&#039;unaligned access&#039;&#039; mehr als einen Buszyklus verursachen würde.  Ein solcher Zugriff generiert auf diesen Prozessoren dann einen [[Trap]].  Andere Prozessoren (z.B. [[X86]]) können diesen &#039;&#039;unaligned access&#039;&#039; zwar ausführen, indem sie die Ergebnisse von zwei Speicherzyklen zum gewünschten Word kombinieren, jedoch ist dieser Mehrfachzugriff uneffektiv, so daß [[Compiler]] sich trotzdem gern an die Ausrichtung auf ganze Wortgrenzen halten, beispielsweise beim Ausrichten von [[struct]] Elementen, oder durch Einfügen von [[NOP|NOPs]] vor Beginn einer neuen Funktion.&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Uc-wiki:Kategorieneinteilung&amp;diff=3033</id>
		<title>Uc-wiki:Kategorieneinteilung</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Uc-wiki:Kategorieneinteilung&amp;diff=3033"/>
		<updated>2004-07-29T20:15:43Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: /* Kategorien */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Ideen zur Kategorieneinteilung ==&lt;br /&gt;
&lt;br /&gt;
Es ist geplant diese Kategorieneinteilung als Navigations-Menü zu verwenden.&lt;br /&gt;
Damit sollten auch Wiki Linkseiten wie [[Compiler für MSP430]], [[Compiler für AVR]], [[AVR-Linkseite]] etc. überflüssig werden.&lt;br /&gt;
&lt;br /&gt;
Vorschläge, Diskussion über derzeitige Kategorienamen etc. bitte [[Diskussion:Uc-wiki:Kategorieneinteilung | hier]]. &lt;br /&gt;
&lt;br /&gt;
== Kategorien ==&lt;br /&gt;
Hinweis: Die, hierarchisch gesehen, jeweils niedrigsten Aufzählungspunkte stellen natürlich keine eigenen Kategorien dar. Vielmehr bilden sie den Inhalt der jeweils nächst höheren.&lt;br /&gt;
&lt;br /&gt;
* Grundlagen/Theorie&lt;br /&gt;
** logische Verknüpfungen&lt;br /&gt;
** [[PWM]]&lt;br /&gt;
&lt;br /&gt;
* Projekte &lt;br /&gt;
** [[Projekt Digitaler Funktionsgenerator]]&lt;br /&gt;
** [[Projekt LCD an Parallelport]]&lt;br /&gt;
** [[Porterweiterung mit SPI]] &lt;br /&gt;
&lt;br /&gt;
* Hardware&lt;br /&gt;
** [[Prozessor|Prozessoren]]&lt;br /&gt;
*** [[PowerPC]]&lt;br /&gt;
*** [[SPARC]]&lt;br /&gt;
*** [[X86]]&lt;br /&gt;
** [[Mikrocontroller]] (auch: Controller)&lt;br /&gt;
*** [[68HC05]] &lt;br /&gt;
*** [[68HC08]]&lt;br /&gt;
*** [[8051]] (auch: MCS51)&lt;br /&gt;
*** [[ARM]] &lt;br /&gt;
*** [[AVR]]&lt;br /&gt;
**** [[ATmega]], [[AVR-ISP FAQ]], [[AVR Butterfly]], [[AVR übertakten]]  &lt;br /&gt;
**** [[AVR-Tutorial]] &lt;br /&gt;
***** [[Entscheidung Mikrocontroller]] &lt;br /&gt;
***** [[AVR-Tutorial - Benötigte Ausrüstung]]&lt;br /&gt;
***** [[AVR-Tutorial - I/O-Grundlagen]]&lt;br /&gt;
***** [[AVR-Tutorial - Der Stack]]&lt;br /&gt;
***** [[AVR-Tutorial - LCD]]&lt;br /&gt;
***** [[AVR-Tutorial - Interrupts]]&lt;br /&gt;
***** [[AVR-Tutorial - UART]]^&lt;br /&gt;
****** [[AVR-Tutorial:UART:Assembler]]&lt;br /&gt;
****** [[AVR-Tutorial:UART:GCC]]&lt;br /&gt;
****** [[AVR-Tutorial:UART:stdio]]&lt;br /&gt;
****** [[AVR-Tutorial Bestellliste]]&lt;br /&gt;
***** [[Pony-Prog Tutorial]]&lt;br /&gt;
***** [[Hex-Dateien mittels PonyProg zum AVR-Controller übertragen]]&lt;br /&gt;
**** sonstige Features&lt;br /&gt;
***** [[Watchdog]]&lt;br /&gt;
***** [[Interrupt]]&lt;br /&gt;
***** [[Bootloader]]&lt;br /&gt;
*** [[MARC4]]&lt;br /&gt;
*** [[MSP430]]&lt;br /&gt;
*** [[Z8]]&lt;br /&gt;
*** [[C-Control]] &lt;br /&gt;
** Bussysteme&lt;br /&gt;
*** [[I2C]]&lt;br /&gt;
*** [[CAN]]&lt;br /&gt;
** Speicher&lt;br /&gt;
** &amp;quot;Peripherie&amp;quot;&lt;br /&gt;
*** [[74xx]]&lt;br /&gt;
**** [[74HC595]] &lt;br /&gt;
*** Wandler&lt;br /&gt;
**** [[AD-Wandler]]&lt;br /&gt;
**** [[DA-Wandler]]&lt;br /&gt;
&lt;br /&gt;
* Software&lt;br /&gt;
** Allgemein&lt;br /&gt;
*** Programmiersprachen&lt;br /&gt;
**** Allgemein&lt;br /&gt;
***** [[ASM vs C]], [[C vs C-Plusplus]], [[Include-Files]], [[Copy&amp;amp;Paste-Programmierung]] &lt;br /&gt;
**** [[Abel]]&lt;br /&gt;
**** [[C]]&lt;br /&gt;
***** [[C-Präprozessor]]&lt;br /&gt;
***** [[Include-Files (C)]]&lt;br /&gt;
***** [[C Makros]]&lt;br /&gt;
**** [[C-Plusplus]] &lt;br /&gt;
***** [[Inline (C-Plusplus)]]&lt;br /&gt;
***** [[Templates (C-Plusplus)]]&lt;br /&gt;
**** [[Assembler]]&lt;br /&gt;
**** [[Basic]]&lt;br /&gt;
** Tools (besserer Name, genauere Einteilung?)&lt;br /&gt;
*** [[AVR]]&lt;br /&gt;
**** [[Compiler für AVR]](Artikel sollte hiermit überflüssig werden)&lt;br /&gt;
***** [[C]]&lt;br /&gt;
****** [[AVR-GCC]]  &lt;br /&gt;
***** [[Basic]]&lt;br /&gt;
****** [[Bascom AVR]]&lt;br /&gt;
**** [[Assembler]]&lt;br /&gt;
*****  [[AVR Assembler - Makros]], [[AVR Assembler - Unterprogramme]], [[AVR Assembler Makros]]&lt;br /&gt;
**** [[AVR-Studio]] &lt;br /&gt;
***** [[AVR-Studio Bugs]]&lt;br /&gt;
**** [[AVRDUDE]]&lt;br /&gt;
** Elektronikprogramme&lt;br /&gt;
*** [[Schaltplaneditoren]]&lt;br /&gt;
**** [[Eagle]]&lt;br /&gt;
&lt;br /&gt;
* Elektronikgrundlagen&lt;br /&gt;
** [[Halbleiter]]&lt;br /&gt;
** [[Digital]]&lt;br /&gt;
&lt;br /&gt;
** [[Löten]] [[Löten (praktisch)]] [[Lötkolben]]&lt;br /&gt;
** [[SMD]]&lt;br /&gt;
*** [[SMDLöten]] &lt;br /&gt;
*** [[SMD Löten]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* [[Linksammlung]]&lt;br /&gt;
&lt;br /&gt;
==  Liste aller Artikel ==&lt;br /&gt;
&lt;br /&gt;
Erstellt um obige Einteilung leichter per cut and paste zu vervollständigen.&lt;br /&gt;
&lt;br /&gt;
Stand: 14.7.2004, 16:30 Uhr (Insgesammt 245 Seiten allerdings mit Weiterleitungen und ohne &amp;quot;Uc-wiki:&amp;quot;-Seiten)&lt;br /&gt;
&lt;br /&gt;
Alle Artikel, die noch nicht in Kategorien eingeteilt sind:&lt;br /&gt;
(Reine Weiterleitungen bitte einfach löschen!)&lt;br /&gt;
[[Akkumulator]] [[Analog]] [[Atmel]] [[Aufgaben]] [[BAE]] [[BDM]]  [[Baud]] [[Bestelliste]] [[Bit]] [[Blackfin]] [[Bps]] [[Breadboard]] [[Brownout]] [[Bus]] [[Byte]] [[C16x]] [[CISC]] [[CMOS]] [[CPLD]] [[CRC]] [[CRC16]] [[Chatregeln]] [[Code size anzeigen]]   [[Compiler für MSP430]] [[DDS]] [[DSP]] [[DataFlash]]  [[Diode]] [[DsPIC]] [[Durchlass-Spannung]] [[EEPROM]] [[EPROM]] [[EZ-Kit Lite]]  [[ElanSC520]] [[FET]] [[FPGA]] [[FastAVR]] [[Flash]] [[Flash-ROM]] [[Forth]] [[Forum-Wishlist]] [[Frequenz]] [[Funktionsgenerator]] [[GAL]] [[GCC]] [[GDB]] [[GPS]] [[Gitarreneffekte mit dem EZ-Kit Lite]] [[Gschem]] [[H8]] [[HLL]] [[Harvard-Architektur]] [[Hauptseite]] [[Heap-Fragmentierung]]  [[IC]] [[ISP]] [[Interpreter]] [[JTAG]] [[Java]] [[Jfig]] [[Kellerspeicher]] [[Kernel]] [[L293D]] [[LCD]] [[LED]] [[LPC-P1]] [[LPC-P2106]] [[LPC2100]] [[LPC210X]] [[LPC21XX]] [[LTC1257]] [[Linux]] [[Lizenzbestimmungen]] [[Lizenzumstellung]] [[Lizenzumstellung]] [[Logische Verknüpfungen]]  [[MIDI]] [[MMU]] [[MP3]] [[MRAM]] [[MSPGCC]] [[MacOS]] [[Madistor]] [[Makro]] [[Manchester]] [[Mikrocontroller]] [[Mini-Computer]] [[Multitasking]] [[Multitasking:Präemptives Multitasking]] [[NRZ]] [[Nibble]] [[OTP-ROM]] [[Optokoppler]] [[Oszillator]] [[Oszilloskop]] [[PAL]] [[PCB]] [[PCB (Software)]] [[PIC]] [[PROM]] [[Peltier-Element]] [[Platine]] [[Platinenherstellung mit der Tonertransfermethode]] [[Potentiometer]] [[Programmiersprache]] [[Programmspeicher]] [[Puls width modulation]] [[Pulsbreitenmodulation]] [[Pulsweitenmodulation]] [[QFP]] [[Quellcode]] [[RAM]] [[RISC]] [[RS-232]] [[Register]] [[SHT11]]  [[SPI]] [[STK200]] [[STK500]]  [[Schwingung]] [[Sensor]] [[Serial Peripheral Interface]] [[Seriell]] [[Simulator]] [[Spannung]] [[Spannungs-Referenz]] [[Spannungsfall]] [[Spannungsreferenz]] [[Stack]] [[Starterkit]] [[SuperH]] [[TI]] [[TM-Klausurloesungen]] [[TM-Lösungen]] [[TQFP]] [[TTL]] [[TV-out]] [[TWI]] [[Target3001]] [[Tastverhältnis]] [[Temperatursensor]]  [[Testseite]] [[Texas Instruments]] [[Texteditor]] [[Timer]] [[Transistor]] [[TriCore]] [[UART]] [[USART]] [[USB]] [[Unix]] [[VHDL]] [[VS1001]] [[Verilog]] [[Von Neumann-Architektur]] [[WIKI-Wishlist]]  [[WinAVR: Code-Größe anzeigen]] [[Windows]] [[Word]] [[Z-Diode]] [[Zahlensysteme]]&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Uc-wiki:Kategorieneinteilung&amp;diff=2950</id>
		<title>Uc-wiki:Kategorieneinteilung</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Uc-wiki:Kategorieneinteilung&amp;diff=2950"/>
		<updated>2004-07-29T20:15:27Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: /* Liste aller Artikel */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Ideen zur Kategorieneinteilung ==&lt;br /&gt;
&lt;br /&gt;
Es ist geplant diese Kategorieneinteilung als Navigations-Menü zu verwenden.&lt;br /&gt;
Damit sollten auch Wiki Linkseiten wie [[Compiler für MSP430]], [[Compiler für AVR]], [[AVR-Linkseite]] etc. überflüssig werden.&lt;br /&gt;
&lt;br /&gt;
Vorschläge, Diskussion über derzeitige Kategorienamen etc. bitte [[Diskussion:Uc-wiki:Kategorieneinteilung | hier]]. &lt;br /&gt;
&lt;br /&gt;
== Kategorien ==&lt;br /&gt;
Hinweis: Die, hierarchisch gesehen, jeweils niedrigsten Aufzählungspunkte stellen natürlich keine eigenen Kategorien dar. Vielmehr bilden sie den Inhalt der jeweils nächst höheren.&lt;br /&gt;
&lt;br /&gt;
* Grundlagen/Theorie&lt;br /&gt;
** logische Verknüpfungen&lt;br /&gt;
** [[PWM]]&lt;br /&gt;
** Elektronikgrundlagen&lt;br /&gt;
*** [[Halbleiter]]&lt;br /&gt;
&lt;br /&gt;
* Projekte &lt;br /&gt;
&lt;br /&gt;
* Hardware&lt;br /&gt;
** [[Prozessor|Prozessoren]]&lt;br /&gt;
*** [[PowerPC]]&lt;br /&gt;
*** [[SPARC]]&lt;br /&gt;
*** [[X86]]&lt;br /&gt;
** [[Mikrocontroller]] (auch: Controller)&lt;br /&gt;
*** [[68HC05]] &lt;br /&gt;
*** [[68HC08]]&lt;br /&gt;
*** [[8051]] (auch: MCS51)&lt;br /&gt;
*** [[ARM]] &lt;br /&gt;
*** [[AVR]]&lt;br /&gt;
**** [[ATmega]], [[AVR-ISP FAQ]], [[AVR Butterfly]], [[AVR übertakten]]  &lt;br /&gt;
**** [[AVR-Tutorial]] &lt;br /&gt;
***** [[Entscheidung Mikrocontroller]] &lt;br /&gt;
***** [[AVR-Tutorial - Benötigte Ausrüstung]]&lt;br /&gt;
***** [[AVR-Tutorial - I/O-Grundlagen]]&lt;br /&gt;
***** [[AVR-Tutorial - Der Stack]]&lt;br /&gt;
***** [[AVR-Tutorial - LCD]]&lt;br /&gt;
***** [[AVR-Tutorial - Interrupts]]&lt;br /&gt;
***** [[AVR-Tutorial - UART]]^&lt;br /&gt;
****** [[AVR-Tutorial:UART:Assembler]]&lt;br /&gt;
****** [[AVR-Tutorial:UART:GCC]]&lt;br /&gt;
****** [[AVR-Tutorial:UART:stdio]]&lt;br /&gt;
****** [[AVR-Tutorial Bestellliste]]&lt;br /&gt;
***** [[Pony-Prog Tutorial]]&lt;br /&gt;
***** [[Hex-Dateien mittels PonyProg zum AVR-Controller übertragen]]&lt;br /&gt;
*** [[MARC4]]&lt;br /&gt;
*** [[MSP430]]&lt;br /&gt;
*** [[Z8]]&lt;br /&gt;
*** [[C-Control]] &lt;br /&gt;
** Bussysteme&lt;br /&gt;
*** [[I2C]]&lt;br /&gt;
*** [[CAN]]&lt;br /&gt;
** Speicher&lt;br /&gt;
** &amp;quot;Peripherie&amp;quot;&lt;br /&gt;
*** [[74xx]]&lt;br /&gt;
**** [[74HC595]] &lt;br /&gt;
*** Wandler&lt;br /&gt;
**** [[AD-Wandler]]&lt;br /&gt;
**** [[DA-Wandler]]&lt;br /&gt;
&lt;br /&gt;
* Software&lt;br /&gt;
** Allgemein&lt;br /&gt;
*** Programmiersprachen&lt;br /&gt;
**** Allgemein&lt;br /&gt;
***** [[ASM vs C]], [[C vs C-Plusplus]], [[Include-Files]], [[Copy&amp;amp;Paste-Programmierung]] &lt;br /&gt;
**** [[Abel]]&lt;br /&gt;
**** [[C]]&lt;br /&gt;
***** [[C-Präprozessor]], [[Include-Files (C)]]&lt;br /&gt;
**** [[C-Plusplus]] &lt;br /&gt;
***** [[Inline (C-Plusplus)]]&lt;br /&gt;
**** [[Assembler]]&lt;br /&gt;
**** [[Basic]]&lt;br /&gt;
** Tools (besserer Name, genauere Einteilung?)&lt;br /&gt;
*** [[AVR]]&lt;br /&gt;
**** [[Compiler für AVR]](Artikel sollte hiermit überflüssig werden)&lt;br /&gt;
***** [[C]]&lt;br /&gt;
****** [[AVR-GCC]]  &lt;br /&gt;
***** [[Basic]]&lt;br /&gt;
****** [[Bascom AVR]]&lt;br /&gt;
**** [[Assembler]]&lt;br /&gt;
*****  [[AVR Assembler - Makros]], [[AVR Assembler - Unterprogramme]], [[AVR Assembler Makros]]&lt;br /&gt;
**** [[AVR-Studio]] &lt;br /&gt;
***** [[AVR-Studio Bugs]]&lt;br /&gt;
**** [[AVRDUDE]]&lt;br /&gt;
&lt;br /&gt;
* [[Linksammlung]]&lt;br /&gt;
&lt;br /&gt;
==  Liste aller Artikel ==&lt;br /&gt;
&lt;br /&gt;
Erstellt um obige Einteilung leichter per cut and paste zu vervollständigen.&lt;br /&gt;
&lt;br /&gt;
Stand: 14.7.2004, 16:30 Uhr (Insgesammt 245 Seiten allerdings mit Weiterleitungen und ohne &amp;quot;Uc-wiki:&amp;quot;-Seiten)&lt;br /&gt;
&lt;br /&gt;
Alle Artikel, die noch nicht in Kategorien eingeteilt sind:&lt;br /&gt;
(Reine Weiterleitungen bitte einfach löschen!)&lt;br /&gt;
[[Akkumulator]] [[Analog]] [[Atmel]] [[Aufgaben]] [[BAE]] [[BDM]]  [[Baud]] [[Bestelliste]] [[Bit]] [[Blackfin]] [[Bps]] [[Breadboard]] [[Brownout]] [[Bus]] [[Byte]] [[C16x]] [[CISC]] [[CMOS]] [[CPLD]] [[CRC]] [[CRC16]] [[Chatregeln]] [[Code size anzeigen]]   [[Compiler für MSP430]] [[DDS]] [[DSP]] [[DataFlash]]  [[Diode]] [[DsPIC]] [[Durchlass-Spannung]] [[EEPROM]] [[EPROM]] [[EZ-Kit Lite]]  [[ElanSC520]] [[FET]] [[FPGA]] [[FastAVR]] [[Flash]] [[Flash-ROM]] [[Forth]] [[Forum-Wishlist]] [[Frequenz]] [[Funktionsgenerator]] [[GAL]] [[GCC]] [[GDB]] [[GPS]] [[Gitarreneffekte mit dem EZ-Kit Lite]] [[Gschem]] [[H8]] [[HLL]] [[Harvard-Architektur]] [[Hauptseite]] [[Heap-Fragmentierung]]  [[IC]] [[ISP]] [[Interpreter]] [[JTAG]] [[Java]] [[Jfig]] [[Kellerspeicher]] [[Kernel]] [[L293D]] [[LCD]] [[LED]] [[LPC-P1]] [[LPC-P2106]] [[LPC2100]] [[LPC210X]] [[LPC21XX]] [[LTC1257]] [[Linux]] [[Lizenzbestimmungen]] [[Lizenzumstellung]] [[Lizenzumstellung]] [[Logische Verknüpfungen]]  [[MIDI]] [[MMU]] [[MP3]] [[MRAM]] [[MSPGCC]] [[MacOS]] [[Madistor]] [[Makro]] [[Manchester]] [[Mikrocontroller]] [[Mini-Computer]] [[Multitasking]] [[Multitasking:Präemptives Multitasking]] [[NRZ]] [[Nibble]] [[OTP-ROM]] [[Optokoppler]] [[Oszillator]] [[Oszilloskop]] [[PAL]] [[PCB]] [[PCB (Software)]] [[PIC]] [[PROM]] [[Peltier-Element]] [[Platine]] [[Platinenherstellung mit der Tonertransfermethode]] [[Potentiometer]] [[Programmiersprache]] [[Programmspeicher]] [[Puls width modulation]] [[Pulsbreitenmodulation]] [[Pulsweitenmodulation]] [[QFP]] [[Quellcode]] [[RAM]] [[RISC]] [[RS-232]] [[Register]] [[SHT11]]  [[SPI]] [[STK200]] [[STK500]]  [[Schwingung]] [[Sensor]] [[Serial Peripheral Interface]] [[Seriell]] [[Simulator]] [[Spannung]] [[Spannungs-Referenz]] [[Spannungsfall]] [[Spannungsreferenz]] [[Stack]] [[Starterkit]] [[SuperH]] [[TI]] [[TM-Klausurloesungen]] [[TM-Lösungen]] [[TQFP]] [[TTL]] [[TV-out]] [[TWI]] [[Target3001]] [[Tastverhältnis]] [[Temperatursensor]]  [[Testseite]] [[Texas Instruments]] [[Texteditor]] [[Timer]] [[Transistor]] [[TriCore]] [[UART]] [[USART]] [[USB]] [[Unix]] [[VHDL]] [[VS1001]] [[Verilog]] [[Von Neumann-Architektur]] [[WIKI-Wishlist]]  [[WinAVR: Code-Größe anzeigen]] [[Windows]] [[Word]] [[Z-Diode]] [[Zahlensysteme]]&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Uc-wiki:Kategorieneinteilung&amp;diff=2949</id>
		<title>Uc-wiki:Kategorieneinteilung</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Uc-wiki:Kategorieneinteilung&amp;diff=2949"/>
		<updated>2004-07-29T20:07:09Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: /* Liste aller Artikel */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Ideen zur Kategorieneinteilung ==&lt;br /&gt;
&lt;br /&gt;
Es ist geplant diese Kategorieneinteilung als Navigations-Menü zu verwenden.&lt;br /&gt;
Damit sollten auch Wiki Linkseiten wie [[Compiler für MSP430]], [[Compiler für AVR]], [[AVR-Linkseite]] etc. überflüssig werden.&lt;br /&gt;
&lt;br /&gt;
Vorschläge, Diskussion über derzeitige Kategorienamen etc. bitte [[Diskussion:Uc-wiki:Kategorieneinteilung | hier]]. &lt;br /&gt;
&lt;br /&gt;
== Kategorien ==&lt;br /&gt;
Hinweis: Die, hierarchisch gesehen, jeweils niedrigsten Aufzählungspunkte stellen natürlich keine eigenen Kategorien dar. Vielmehr bilden sie den Inhalt der jeweils nächst höheren.&lt;br /&gt;
&lt;br /&gt;
* Grundlagen/Theorie&lt;br /&gt;
** logische Verknüpfungen&lt;br /&gt;
** [[PWM]]&lt;br /&gt;
** Elektronikgrundlagen&lt;br /&gt;
*** [[Halbleiter]]&lt;br /&gt;
&lt;br /&gt;
* Projekte &lt;br /&gt;
&lt;br /&gt;
* Hardware&lt;br /&gt;
** [[Prozessor|Prozessoren]]&lt;br /&gt;
*** [[PowerPC]]&lt;br /&gt;
*** [[SPARC]]&lt;br /&gt;
*** [[X86]]&lt;br /&gt;
** [[Mikrocontroller]] (auch: Controller)&lt;br /&gt;
*** [[68HC05]] &lt;br /&gt;
*** [[68HC08]]&lt;br /&gt;
*** [[8051]] (auch: MCS51)&lt;br /&gt;
*** [[ARM]] &lt;br /&gt;
*** [[AVR]]&lt;br /&gt;
**** [[ATmega]], [[AVR-ISP FAQ]], [[AVR Butterfly]], [[AVR übertakten]]  &lt;br /&gt;
**** [[AVR-Tutorial]] &lt;br /&gt;
***** [[Entscheidung Mikrocontroller]] &lt;br /&gt;
***** [[AVR-Tutorial - Benötigte Ausrüstung]]&lt;br /&gt;
***** [[AVR-Tutorial - I/O-Grundlagen]]&lt;br /&gt;
***** [[AVR-Tutorial - Der Stack]]&lt;br /&gt;
***** [[AVR-Tutorial - LCD]]&lt;br /&gt;
***** [[AVR-Tutorial - Interrupts]]&lt;br /&gt;
***** [[AVR-Tutorial - UART]]^&lt;br /&gt;
****** [[AVR-Tutorial:UART:Assembler]]&lt;br /&gt;
****** [[AVR-Tutorial:UART:GCC]]&lt;br /&gt;
****** [[AVR-Tutorial:UART:stdio]]&lt;br /&gt;
****** [[AVR-Tutorial Bestellliste]]&lt;br /&gt;
***** [[Pony-Prog Tutorial]]&lt;br /&gt;
***** [[Hex-Dateien mittels PonyProg zum AVR-Controller übertragen]]&lt;br /&gt;
*** [[MARC4]]&lt;br /&gt;
*** [[MSP430]]&lt;br /&gt;
*** [[Z8]]&lt;br /&gt;
*** [[C-Control]] &lt;br /&gt;
** Bussysteme&lt;br /&gt;
*** [[I2C]]&lt;br /&gt;
*** [[CAN]]&lt;br /&gt;
** Speicher&lt;br /&gt;
** &amp;quot;Peripherie&amp;quot;&lt;br /&gt;
*** [[74xx]]&lt;br /&gt;
**** [[74HC595]] &lt;br /&gt;
*** Wandler&lt;br /&gt;
**** [[AD-Wandler]]&lt;br /&gt;
**** [[DA-Wandler]]&lt;br /&gt;
&lt;br /&gt;
* Software&lt;br /&gt;
** Allgemein&lt;br /&gt;
*** Programmiersprachen&lt;br /&gt;
**** Allgemein&lt;br /&gt;
***** [[ASM vs C]], [[C vs C-Plusplus]], [[Include-Files]], [[Copy&amp;amp;Paste-Programmierung]] &lt;br /&gt;
**** [[Abel]]&lt;br /&gt;
**** [[C]]&lt;br /&gt;
***** [[C-Präprozessor]], [[Include-Files (C)]]&lt;br /&gt;
**** [[C-Plusplus]] &lt;br /&gt;
***** [[Inline (C-Plusplus)]]&lt;br /&gt;
**** [[Assembler]]&lt;br /&gt;
**** [[Basic]]&lt;br /&gt;
** Tools (besserer Name, genauere Einteilung?)&lt;br /&gt;
*** [[AVR]]&lt;br /&gt;
**** [[Compiler für AVR]](Artikel sollte hiermit überflüssig werden)&lt;br /&gt;
***** [[C]]&lt;br /&gt;
****** [[AVR-GCC]]  &lt;br /&gt;
***** [[Basic]]&lt;br /&gt;
****** [[Bascom AVR]]&lt;br /&gt;
**** [[Assembler]]&lt;br /&gt;
*****  [[AVR Assembler - Makros]], [[AVR Assembler - Unterprogramme]], [[AVR Assembler Makros]]&lt;br /&gt;
**** [[AVR-Studio]] &lt;br /&gt;
***** [[AVR-Studio Bugs]]&lt;br /&gt;
**** [[AVRDUDE]]&lt;br /&gt;
&lt;br /&gt;
* [[Linksammlung]]&lt;br /&gt;
&lt;br /&gt;
==  Liste aller Artikel ==&lt;br /&gt;
&lt;br /&gt;
Erstellt um obige Einteilung leichter per cut and paste zu vervollständigen.&lt;br /&gt;
&lt;br /&gt;
Stand: 14.7.2004, 16:30 Uhr (Insgesammt 245 Seiten allerdings mit Weiterleitungen und ohne &amp;quot;Uc-wiki:&amp;quot;-Seiten)&lt;br /&gt;
&lt;br /&gt;
Alle Artikel, die noch nicht in Kategorien eingeteilt sind:&lt;br /&gt;
(Reine Weiterleitungen bitte einfach löschen!)&lt;br /&gt;
[[Akkumulator]] [[Analog]] [[Atmel]] [[Aufgaben]] [[BAE]] [[BDM]]  [[Baud]] [[Bestelliste]] [[Bit]] [[Blackfin]] [[Bootloader]] [[Bps]] [[Breadboard]] [[Brownout]] [[Bus]] [[Byte]] [[C16x]] [[CISC]] [[CMOS]] [[CPLD]] [[CRC]] [[CRC16]] [[C Makros]] [[Chatregeln]] [[Code size anzeigen]]   [[Compiler für MSP430]] [[DDS]] [[DSP]] [[DataFlash]] [[Digital]] [[Diode]] [[DsPIC]] [[Durchlass-Spannung]] [[EEPROM]] [[EPROM]] [[EZ-Kit Lite]] [[Eagle]] [[ElanSC520]] [[FET]] [[FPGA]] [[FastAVR]] [[Flash]] [[Flash-ROM]] [[Forth]] [[Forum-Wishlist]] [[Frequenz]] [[Funktionsgenerator]] [[GAL]] [[GCC]] [[GDB]] [[GPS]] [[Gitarreneffekte mit dem EZ-Kit Lite]] [[Gschem]] [[H8]] [[HLL]] [[Harvard-Architektur]] [[Hauptseite]] [[Heap-Fragmentierung]]  [[IC]] [[ISP]] [[Interpreter]] [[Interrupt]] [[JTAG]] [[Java]] [[Jfig]] [[Kellerspeicher]] [[Kernel]] [[L293D]] [[LCD]] [[LED]] [[LPC-P1]] [[LPC-P2106]] [[LPC2100]] [[LPC210X]] [[LPC21XX]] [[LTC1257]] [[Linux]] [[Lizenzbestimmungen]] [[Lizenzumstellung]] [[Lizenzumstellung]] [[Logische Verknüpfungen]] [[Löten]] [[Löten (praktisch)]] [[Lötkolben]] [[MIDI]] [[MMU]] [[MP3]] [[MRAM]] [[MSPGCC]] [[MacOS]] [[Madistor]] [[Makro]] [[Manchester]] [[Mikrocontroller]] [[Mini-Computer]] [[Multitasking]] [[Multitasking:Präemptives Multitasking]] [[NRZ]] [[Nibble]] [[OTP-ROM]] [[Optokoppler]] [[Oszillator]] [[Oszilloskop]] [[PAL]] [[PCB]] [[PCB (Software)]] [[PIC]] [[PROM]] [[Peltier-Element]] [[Platine]] [[Platinenherstellung mit der Tonertransfermethode]]  [[Porterweiterung mit SPI]] [[Potentiometer]] [[Programmiersprache]] [[Programmspeicher]] [[Projekt Digitaler Funktionsgenerator]] [[Projekt LCD an Parallelport]] [[Puls width modulation]] [[Pulsbreitenmodulation]] [[Pulsweitenmodulation]] [[QFP]] [[Quellcode]] [[RAM]] [[RISC]] [[RS-232]] [[Register]] [[SHT11]] [[SMD]] [[SMDLöten]] [[SMD Löten]] [[SPI]] [[STK200]] [[STK500]] [[Schaltplaneditoren]] [[Schwingung]] [[Sensor]] [[Serial Peripheral Interface]] [[Seriell]] [[Simulator]] [[Spannung]] [[Spannungs-Referenz]] [[Spannungsfall]] [[Spannungsreferenz]] [[Stack]] [[Starterkit]] [[SuperH]] [[TI]] [[TM-Klausurloesungen]] [[TM-Lösungen]] [[TQFP]] [[TTL]] [[TV-out]] [[TWI]] [[Target3001]] [[Tastverhältnis]] [[Temperatursensor]] [[Templates (C-Plusplus)]] [[Testseite]] [[Texas Instruments]] [[Texteditor]] [[Timer]] [[Transistor]] [[TriCore]] [[UART]] [[USART]] [[USB]] [[Unix]] [[VHDL]] [[VS1001]] [[Verilog]] [[Von Neumann-Architektur]] [[WIKI-Wishlist]] [[Watchdog]] [[WinAVR]] [[WinAVR: Code-Größe anzeigen]] [[Windows]] [[Word]] [[Z-Diode]] [[Zahlensysteme]]&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Uc-wiki:Kategorieneinteilung&amp;diff=2948</id>
		<title>Uc-wiki:Kategorieneinteilung</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Uc-wiki:Kategorieneinteilung&amp;diff=2948"/>
		<updated>2004-07-29T20:06:59Z</updated>

		<summary type="html">&lt;p&gt;Nollsen: /* Kategorien */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Ideen zur Kategorieneinteilung ==&lt;br /&gt;
&lt;br /&gt;
Es ist geplant diese Kategorieneinteilung als Navigations-Menü zu verwenden.&lt;br /&gt;
Damit sollten auch Wiki Linkseiten wie [[Compiler für MSP430]], [[Compiler für AVR]], [[AVR-Linkseite]] etc. überflüssig werden.&lt;br /&gt;
&lt;br /&gt;
Vorschläge, Diskussion über derzeitige Kategorienamen etc. bitte [[Diskussion:Uc-wiki:Kategorieneinteilung | hier]]. &lt;br /&gt;
&lt;br /&gt;
== Kategorien ==&lt;br /&gt;
Hinweis: Die, hierarchisch gesehen, jeweils niedrigsten Aufzählungspunkte stellen natürlich keine eigenen Kategorien dar. Vielmehr bilden sie den Inhalt der jeweils nächst höheren.&lt;br /&gt;
&lt;br /&gt;
* Grundlagen/Theorie&lt;br /&gt;
** logische Verknüpfungen&lt;br /&gt;
** [[PWM]]&lt;br /&gt;
** Elektronikgrundlagen&lt;br /&gt;
*** [[Halbleiter]]&lt;br /&gt;
&lt;br /&gt;
* Projekte &lt;br /&gt;
&lt;br /&gt;
* Hardware&lt;br /&gt;
** [[Prozessor|Prozessoren]]&lt;br /&gt;
*** [[PowerPC]]&lt;br /&gt;
*** [[SPARC]]&lt;br /&gt;
*** [[X86]]&lt;br /&gt;
** [[Mikrocontroller]] (auch: Controller)&lt;br /&gt;
*** [[68HC05]] &lt;br /&gt;
*** [[68HC08]]&lt;br /&gt;
*** [[8051]] (auch: MCS51)&lt;br /&gt;
*** [[ARM]] &lt;br /&gt;
*** [[AVR]]&lt;br /&gt;
**** [[ATmega]], [[AVR-ISP FAQ]], [[AVR Butterfly]], [[AVR übertakten]]  &lt;br /&gt;
**** [[AVR-Tutorial]] &lt;br /&gt;
***** [[Entscheidung Mikrocontroller]] &lt;br /&gt;
***** [[AVR-Tutorial - Benötigte Ausrüstung]]&lt;br /&gt;
***** [[AVR-Tutorial - I/O-Grundlagen]]&lt;br /&gt;
***** [[AVR-Tutorial - Der Stack]]&lt;br /&gt;
***** [[AVR-Tutorial - LCD]]&lt;br /&gt;
***** [[AVR-Tutorial - Interrupts]]&lt;br /&gt;
***** [[AVR-Tutorial - UART]]^&lt;br /&gt;
****** [[AVR-Tutorial:UART:Assembler]]&lt;br /&gt;
****** [[AVR-Tutorial:UART:GCC]]&lt;br /&gt;
****** [[AVR-Tutorial:UART:stdio]]&lt;br /&gt;
****** [[AVR-Tutorial Bestellliste]]&lt;br /&gt;
***** [[Pony-Prog Tutorial]]&lt;br /&gt;
***** [[Hex-Dateien mittels PonyProg zum AVR-Controller übertragen]]&lt;br /&gt;
*** [[MARC4]]&lt;br /&gt;
*** [[MSP430]]&lt;br /&gt;
*** [[Z8]]&lt;br /&gt;
*** [[C-Control]] &lt;br /&gt;
** Bussysteme&lt;br /&gt;
*** [[I2C]]&lt;br /&gt;
*** [[CAN]]&lt;br /&gt;
** Speicher&lt;br /&gt;
** &amp;quot;Peripherie&amp;quot;&lt;br /&gt;
*** [[74xx]]&lt;br /&gt;
**** [[74HC595]] &lt;br /&gt;
*** Wandler&lt;br /&gt;
**** [[AD-Wandler]]&lt;br /&gt;
**** [[DA-Wandler]]&lt;br /&gt;
&lt;br /&gt;
* Software&lt;br /&gt;
** Allgemein&lt;br /&gt;
*** Programmiersprachen&lt;br /&gt;
**** Allgemein&lt;br /&gt;
***** [[ASM vs C]], [[C vs C-Plusplus]], [[Include-Files]], [[Copy&amp;amp;Paste-Programmierung]] &lt;br /&gt;
**** [[Abel]]&lt;br /&gt;
**** [[C]]&lt;br /&gt;
***** [[C-Präprozessor]], [[Include-Files (C)]]&lt;br /&gt;
**** [[C-Plusplus]] &lt;br /&gt;
***** [[Inline (C-Plusplus)]]&lt;br /&gt;
**** [[Assembler]]&lt;br /&gt;
**** [[Basic]]&lt;br /&gt;
** Tools (besserer Name, genauere Einteilung?)&lt;br /&gt;
*** [[AVR]]&lt;br /&gt;
**** [[Compiler für AVR]](Artikel sollte hiermit überflüssig werden)&lt;br /&gt;
***** [[C]]&lt;br /&gt;
****** [[AVR-GCC]]  &lt;br /&gt;
***** [[Basic]]&lt;br /&gt;
****** [[Bascom AVR]]&lt;br /&gt;
**** [[Assembler]]&lt;br /&gt;
*****  [[AVR Assembler - Makros]], [[AVR Assembler - Unterprogramme]], [[AVR Assembler Makros]]&lt;br /&gt;
**** [[AVR-Studio]] &lt;br /&gt;
***** [[AVR-Studio Bugs]]&lt;br /&gt;
**** [[AVRDUDE]]&lt;br /&gt;
&lt;br /&gt;
* [[Linksammlung]]&lt;br /&gt;
&lt;br /&gt;
==  Liste aller Artikel ==&lt;br /&gt;
&lt;br /&gt;
Erstellt um obige Einteilung leichter per cut and paste zu vervollständigen.&lt;br /&gt;
&lt;br /&gt;
Stand: 14.7.2004, 16:30 Uhr (Insgesammt 245 Seiten allerdings mit Weiterleitungen und ohne &amp;quot;Uc-wiki:&amp;quot;-Seiten)&lt;br /&gt;
&lt;br /&gt;
Alle Artikel, die noch nicht in Kategorien eingeteilt sind:&lt;br /&gt;
(Reine Weiterleitungen bitte einfach löschen!)&lt;br /&gt;
[[Akkumulator]] [[Analog]] [[Atmel]] [[Aufgaben]] [[BAE]] [[BDM]]  [[Baud]] [[Bestelliste]] [[Bit]] [[Blackfin]] [[Bootloader]] [[Bps]] [[Breadboard]] [[Brownout]] [[Bus]] [[Byte]] [[C-Control]] [[C16x]] [[CISC]] [[CMOS]] [[CPLD]] [[CRC]] [[CRC16]] [[C Makros]] [[Chatregeln]] [[Code size anzeigen]]   [[Compiler für MSP430]] [[DDS]] [[DSP]] [[DataFlash]] [[Digital]] [[Diode]] [[DsPIC]] [[Durchlass-Spannung]] [[EEPROM]] [[EPROM]] [[EZ-Kit Lite]] [[Eagle]] [[ElanSC520]] [[Entscheidung Mikrocontroller]] [[FET]] [[FPGA]] [[FastAVR]] [[Flash]] [[Flash-ROM]] [[Forth]] [[Forum-Wishlist]] [[Frequenz]] [[Funktionsgenerator]] [[GAL]] [[GCC]] [[GDB]] [[GPS]] [[Gitarreneffekte mit dem EZ-Kit Lite]] [[Gschem]] [[H8]] [[HLL]] [[Halbleiter]] [[Harvard-Architektur]] [[Hauptseite]] [[Heap-Fragmentierung]] [[Hex-Dateien mittels PonyProg zum AVR-Controller übertragen]] [[I2C]] [[IC]] [[ISP]] [[Interpreter]] [[Interrupt]] [[I²C]] [[JTAG]] [[Java]] [[Jfig]] [[Kellerspeicher]] [[Kernel]] [[L293D]] [[LCD]] [[LED]] [[LPC-P1]] [[LPC-P2106]] [[LPC2100]] [[LPC210X]] [[LPC21XX]] [[LTC1257]] [[Linux]] [[Lizenzbestimmungen]] [[Lizenzumstellung]] [[Lizenzumstellung]] [[Logische Verknüpfungen]] [[Löten]] [[Löten (praktisch)]] [[Lötkolben]] [[MIDI]] [[MMU]] [[MP3]] [[MRAM]] [[MSPGCC]] [[MacOS]] [[Madistor]] [[Makro]] [[Manchester]] [[Mikrocontroller]] [[Mini-Computer]] [[Multitasking]] [[Multitasking:Präemptives Multitasking]] [[NRZ]] [[Nibble]] [[OTP-ROM]] [[Optokoppler]] [[Oszillator]] [[Oszilloskop]] [[PAL]] [[PCB]] [[PCB (Software)]] [[PIC]] [[PROM]] [[Peltier-Element]] [[Platine]] [[Platinenherstellung mit der Tonertransfermethode]] [[Pony-Prog Tutorial]] [[Porterweiterung mit SPI]] [[Potentiometer]] [[Programmiersprache]] [[Programmspeicher]] [[Projekt Digitaler Funktionsgenerator]] [[Projekt LCD an Parallelport]] [[Puls width modulation]] [[Pulsbreitenmodulation]] [[Pulsweitenmodulation]] [[QFP]] [[Quellcode]] [[RAM]] [[RISC]] [[RS-232]] [[Register]] [[SHT11]] [[SMD]] [[SMDLöten]] [[SMD Löten]] [[SPI]] [[STK200]] [[STK500]] [[Schaltplaneditoren]] [[Schwingung]] [[Sensor]] [[Serial Peripheral Interface]] [[Seriell]] [[Simulator]] [[Spannung]] [[Spannungs-Referenz]] [[Spannungsfall]] [[Spannungsreferenz]] [[Stack]] [[Starterkit]] [[SuperH]] [[TI]] [[TM-Klausurloesungen]] [[TM-Lösungen]] [[TQFP]] [[TTL]] [[TV-out]] [[TWI]] [[Target3001]] [[Tastverhältnis]] [[Temperatursensor]] [[Templates (C-Plusplus)]] [[Testseite]] [[Texas Instruments]] [[Texteditor]] [[Timer]] [[Transistor]] [[TriCore]] [[UART]] [[USART]] [[USB]] [[Unix]] [[VHDL]] [[VS1001]] [[Verilog]] [[Von Neumann-Architektur]] [[WIKI-Wishlist]] [[Watchdog]] [[WinAVR]] [[WinAVR: Code-Größe anzeigen]] [[Windows]] [[Word]] [[Z-Diode]] [[Zahlensysteme]]&lt;/div&gt;</summary>
		<author><name>Nollsen</name></author>
	</entry>
</feed>