<?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=80.64.189.58</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=80.64.189.58"/>
	<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/articles/Spezial:Beitr%C3%A4ge/80.64.189.58"/>
	<updated>2026-04-11T03:16:48Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.39.7</generator>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_Checkliste&amp;diff=88882</id>
		<title>AVR Checkliste</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_Checkliste&amp;diff=88882"/>
		<updated>2015-06-09T08:36:06Z</updated>

		<summary type="html">&lt;p&gt;80.64.189.58: &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 dringendsten 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.&amp;amp;nbsp;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;
=== Programmieren via SPI und angeschlossene SPI-Hardware ===&lt;br /&gt;
Wenn Peripherie über SPI angebunden ist, muss sich diese zum Programmierzeitpunkt auf dem Bus neutral verhalten. Normalerweise bedeutet dies, dass die Slave-Select/Chip-Select-Leitungen der Peripherie auf high gezogen werden müssen, wenn die Chips keinen internen Pull-Up haben. Werte von 10 kΩ bis 100 kΩ für normale Anwendungen haben sich bewährt.&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 zurückgesetzt gehalten. Zwar haben die meisten(!) AVRs einen internen Pullup-Widerstand, der den Reset-Pin gegen VCC &amp;quot;zieht&amp;quot;, dieser ist jedoch relativ hochohmig (ca. 50 kΩ, vgl. Datenblatt) und reicht in extrem stark gestörter Umgebung nicht aus, um den Reset-Pin sicher &amp;quot;hochzuhalten&amp;quot;. Als Mindestbeschaltung empfiehlt sich dringend, einen externen Pullup-Widerstand vorzusehen (typisch 10 kΩ), der den Reset-Pin mit VCC verbindet. Er sollte nicht kleiner als 4,7 kΩ sein, da der Programmieradapter sonst eventuell den Reset-Pin während des Programmiervorgangs nicht sicher auf &amp;quot;low&amp;quot; ziehen kann. Mit einem Oszilloskop kann man gut überprüfen, ob der Pegel am Reset-Pin sauber zwischen high und low wechselt. 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;
=== Flashen / Lesen / Fuse nur einmal möglich ===&lt;br /&gt;
&lt;br /&gt;
Es kann vorkommen, dass ein AVR nur einmal programmiert werden kann, danach geht es nicht mehr (z.B. Typ wird nicht mehr erkannt). Erst nachdem die Versorgungsspannung getrennt / wieder verbunden ist, geht es erneut.&lt;br /&gt;
&lt;br /&gt;
In diesem Fall ist meistens der Resetpin kurzgeschlossen, daher lässt sich der AVR einmal programmieren.&lt;br /&gt;
&lt;br /&gt;
Der Reset PIN müsste bei korrekter Beschaltung eine Spannung nahe VCC (z.B. 4.9V) aufweisen, ist die Spannung bei GND, ist der Pin kurzgeschlossen und verursacht dieses Problem.&lt;br /&gt;
&lt;br /&gt;
=== Abblockkondensator(en) ordnungsgemäß installiert? ===&lt;br /&gt;
&lt;br /&gt;
Abblockkondensatoren dienen dazu, impulsartige Einbrüche der Betriebsspannung, die durch schnelle Schaltvorgänge verursacht werden können, zu minimieren. Sie verhindern unkontrollierte Brownouts, welche durch diese Spannungseinbrüche auftreten können. 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;
* Eine niederimpedante Anbindung sollte gegeben sein - also keine Stegleitungen. Dies bedeutet, das die Versorgungsspannung erst durch das Pad des Abblockkondensators fließen MUSS und dann weiter zum IC gereicht wird&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 sollte jeder VCC-Pin mit einem eigenen Abblockkondensator beschaltet werden (z. B. AVRs in SMD-Bauform wie dem ATmega16A also mit vier Kondensatoren). Dabei ist darauf zu achten, jeder Abblockkondensator  mit einem eigenen Via auf die niederimpedante (heißt Hochfrequenz gut leiten) großflächige, nicht unterbrochene Massefläche kontaktiert wird.&lt;br /&gt;
&lt;br /&gt;
* Es sollten keramische Kondensatoren mit einer Kapazität von maximal 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 (der Widerstand=Impedanz ist bei hochfrequenten Spannungen zu groß - ein schneller (hochfrequenter) Spannungsimpuls kann so nicht abgeleitet werden)!&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 [[Quarze und AVR|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 ICs mit mehreren Ground-Anschlüssen müssen immer 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.&amp;amp;nbsp;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.&amp;amp;nbsp;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, dass &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.&amp;amp;nbsp;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;
[[Bild:isp.png|thumb|300px|right|ISP-Adapter]]&lt;br /&gt;
Der ATmega64 und der ATmega128 sowie alle vom ATMega128 abgeleiteten AVRs im 64-Pin-Gehäuse (ATMega641/1281/2561, AT90PWM2/3/2B/3B sowie AT90CAN32/64/128, Ausnahmen 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:&lt;br /&gt;
:* MOSI → PE0 (Pin 2)&lt;br /&gt;
:* MISO → PE1 (Pin 3)&lt;br /&gt;
:* SCK → PB1 (Pin 11)&lt;br /&gt;
:* RESET → RESET (Pin 20)&lt;br /&gt;
: 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 und 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 Gemeinheit betrifft die M103C-Fuse (ATmega103 Compatibility Mode, nur bei den ATmega-Typen, nicht beim AT90CAN32/64/128). Diese ist bei fabrikneuen Atmega64/128 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 RET abstürzt, da der SRAM an einer anderen Stelle endet 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;
=== Mainschleife vorhanden? ===&lt;br /&gt;
&lt;br /&gt;
Insbesondere beim Testen von Interrupts kann es passieren, dass man keine eigentliche Programmschleife vorsieht, weil ja alles in den Interrupts passiert. Das führt dazu, dass der Controller nach Abarbeiten aller Befehle in &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;int main(void) {}&amp;lt;/syntaxhighlight&amp;gt; seine Arbeit einstellt und daher auch keine Interrupts mehr funktionieren. Demnach sollte bei rein Interrupt-basierten Programmen die Funktion mindestens so aussehen: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;int main(void)&lt;br /&gt;
{&lt;br /&gt;
    // hier Interrupts definieren&lt;br /&gt;
    // und einschalten&lt;br /&gt;
    while (1){}&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&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;
Außerdem sollte man immer im Datenblatt des Controllers nachsehen, wie die Interrupttabelle aufgebaut ist. Die kleinen AVRs verwenden ein RCALL zum Anspringen der Interrupts, welches 1 Wort lang ist. Die grossen AVRs mit mehr als 8 KiBi FLASH verwenden ein CALL, 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 SEI eingeschaltet werden).&lt;br /&gt;
&lt;br /&gt;
Oft hilft es einen Catch All Interruptvektor zu definieren um herauszufinden ob ein Fehler (z.B. ein Neubeginn des Programms) vorliegt.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ISR (BADISR_vect)&lt;br /&gt;
{&lt;br /&gt;
    // Hier eine Fehlerausgabe definieren.&lt;br /&gt;
    // Z.B. UART-Ausgabe oder ein PIN toggeln&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dann findet man solche Fehler recht schnell.&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;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&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;/syntaxhighlight&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;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&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;/syntaxhighlight&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.&amp;amp;nbsp;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.&amp;amp;nbsp;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.&amp;amp;nbsp;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.&amp;amp;nbsp;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.&amp;amp;nbsp;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.&amp;amp;nbsp;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.&amp;amp;nbsp;B.:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
    TIFR = (1&amp;lt;&amp;lt;TOV0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&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.&amp;amp;nbsp;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.&amp;amp;nbsp;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.&amp;amp;nbsp;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 weist 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 [[Interrupt]]routine 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;
=== Wo nötig Variablenzugriff atomar gestaltet? ===&lt;br /&gt;
Der Zugriff auf Variablen &amp;gt;8 Bit welche in der ISR und in der Hauptfunktion genutzt werden muss [[atomar]] erfolgen. Das Vergessen dieser Regel führt selten zu Problemen, aber wenn dann zu schwer Nachvollziehbaren...&lt;br /&gt;
&lt;br /&gt;
=== Die Programmierfrequenz passend? ===&lt;br /&gt;
&lt;br /&gt;
Sollte ein Programmieren nicht möglich sein erst einmal die Programmiergeschwindigkeit bei AVR dude mit der Option&lt;br /&gt;
-B bitclock anpassen&lt;br /&gt;
wobei bitclock die Perioden dauer in Millisekunden (floating-point Zahl) ist. Normalerweise -B 1 für Controller mit &amp;gt;=4MHz daher ist bei der Erstprogrammierung ein höherer Wert zu versuchen.&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 kΩ bis 10 kΩ 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 oder einen Oszillator verwenden, egal bei welcher Baudrate: 3% Fehler sind immer 3% Fehler, 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.&amp;amp;nbsp;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.&amp;amp;nbsp;B. in [[Bascom AVR|BASCOM]], [[C]]), dann muss dort der Takt &#039;&#039;genau&#039;&#039; angegeben werden. Setzt man z.&amp;amp;nbsp;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% zu hoch wäre. Damit funktioniert die Übertragung nicht mehr.&lt;br /&gt;
&lt;br /&gt;
* Im AVR-Studio kann man die Taktfrequenz sowohl über ein &amp;lt;code&amp;gt;#define F_CPU&amp;lt;/code&amp;gt; im Quelltext als auch über das Optionsmenu oder das selbsterstellte Makefile einstellen. Es darf nur &#039;&#039;eine&#039;&#039; Variante verwendet werden!&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;nicht&#039;&#039; programmiert?&lt;br /&gt;
&lt;br /&gt;
* Es taucht auch des öfteren das Missverständnis auf, dass man nur F_CPU verändern muss, um den µC mit einem anderen Takt laufen zu lassen. Dem ist nicht so. Der µC-Takt wird durch die Fuses bzw. den eventuell angeschlossenen Quarz oder Quarzoszillator bestimmt. F_CPU dient nur dazu, die dadurch festgelegte Frequenz im C-Programm zur Verfügung zu haben. F_CPU ist nur eine Information, mit der man bei der Programmierung arbeiten kann. Aber ein anderer F_CPU-Wert führt nicht dazu, dass der µC dann magisch auf diese Frequenz umgestellt wird.&lt;br /&gt;
&lt;br /&gt;
* Um zu prüfen, ob der externe Quarz auch wirklich verwendet wird, kann man  mittels _delay_ms() testweise eine LED im Sekundentakt blinken lassen. Den Unterschied zwischen Quarz und internem RC-Oszillator kann man bei größeren Frequenzunterschieden leicht sehen. Ebenso sieht man, ob versehentlich die CLKDIV Fuse gesetzt ist: die Blinkfrequenz ist dann achtmal langsamer. Allerdings muss man auch hier aufpassen. Siehe [[AVR-GCC-Tutorial#Warteschleifen (delay.h)|AVR-GCC-Tutorial: Warteschleifen]].&lt;br /&gt;
&lt;br /&gt;
Im folgenden Programm muss angepasst werden:&lt;br /&gt;
*Die vermeintliche Taktfrequenz F_CPU&lt;br /&gt;
*der Port und der Pin, an dem eine LED angeschlossen ist.&lt;br /&gt;
&lt;br /&gt;
Wird das Programm laufen gelassen, muss die LED 1 Sekunde ein/1 Sekunde aus sein. Stimmen die Zeiten nicht, ist das ein deutlicher Hinweis darauf, dass die tatsächlich vom µC verwendete Taktfrequenz nicht mit der in F_CPU angegebenen übereinstimmt. Das Programm muss mit aktivierter Optimierung &amp;lt;code&amp;gt;-Os&amp;lt;/code&amp;gt; compiliert werden.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Testprogramm für CPU Takt&lt;br /&gt;
// Hier die vermeintliche Taktrate des µC eintragen&lt;br /&gt;
// Im Beispiel hier: 1MHz&lt;br /&gt;
&lt;br /&gt;
#define F_CPU 1000000&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Hier die tatsächlich verwendeten Parameter angeben&lt;br /&gt;
&lt;br /&gt;
#define LED_PORT    PORTB&lt;br /&gt;
#define LED_DDR     DDRB&lt;br /&gt;
#define LED_PIN     PB0&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
   LED_DDR |= 1 &amp;lt;&amp;lt; LED_PIN;&lt;br /&gt;
&lt;br /&gt;
   while (1)&lt;br /&gt;
   {&lt;br /&gt;
      LED_PORT ^= 1 &amp;lt;&amp;lt; LED_PIN;&lt;br /&gt;
      _delay_ms(1000);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Erscheinen im Terminalprogramm kryptische Zeichen anstatt ordentlichen Buchstaben (z.&amp;amp;nbsp;B. ü statt A), liegt das zu 99,9% an einer falsch eingestellten/erzeugten Baudrate im Mikrocontroller. Meistens wiederum liegt dies daran, dass der µC nicht mit der vermeintlichen Taktrate läuft und daher die Baudratenparameter falsch berechnet werden.&lt;br /&gt;
&lt;br /&gt;
* URSEL-Bit in UCSRC: Bei der Initialisierung der UART beachtet, wenn das für den verwendeten AVR notwendig ist, siehe [[AVR-GCC-Tutorial/Der_UART#Die_UART-Register|AVR-GCC-Tutorial/Der UART: Die UART-Register]].&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 erläutert.&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.&amp;amp;nbsp;B. GND-Anschluss am RS232-Stecker nicht belegt oder dergleichen).&lt;br /&gt;
&lt;br /&gt;
* Der Pegelwandler/Inverter (z.&amp;amp;nbsp;B. MAX232) muss mit Kondensatoren für die internen Ladungspumpen beschaltet werden. Beim MAX232 sind dies mindestens vier Kondensatoren ≥ 1 µF (Polung beachten!), beim MAX202, MAX232A und MAX3232 vier Kondensatoren ≥ 100 nF. Hinzu kommt der obligatorische Abblockkondensator von 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 muss stimmen (kein Hardwarehandshake bei ausschließlicher Verwendung der Pins RX/TX).&lt;br /&gt;
&lt;br /&gt;
* Wird das Signal eventuell durch zusätzliche Chips invertiert? (EEPROM von FT232 falsch Programmiert)&lt;br /&gt;
&lt;br /&gt;
* Die Hardware und Verkabelung kann man schnell prüfen, indem man den Pin R1OUT bzw. R2OUT mit T1IN bzw. T2IN am MAX232 miteinander verbindet (je nachdem welches Pinpaar verwendet wird). Dann sollte man auf dem PC ein Terminalprogramm wie Hyperterminal starten und nach dem Eingeben von Zeichen diese sofort angezeigt bekommen, egal mit welcher Baudrate. Lediglich die Flusssteuerung muss auf &amp;quot;Kein&amp;quot; eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
: Man muss aber beachten, dass T1IN bzw. T2IN für diesen Test &#039;&#039;nicht&#039;&#039; mit dem Mikrocontroller verbunden sein darf, weil sonst zwei Ausgänge miteinander verbunden sind, siehe [[Ausgangsstufen Logik-ICs]]. Wenn der µC gesockelt ist, kann man ihn dafür einfach aus dem Sockel nehmen und die RX/TX Pins direkt im µC-Sockel mit einem Stück Draht verbinden.&lt;br /&gt;
&lt;br /&gt;
* UART Ausgabe-Pin als Output-Pin deklariert?&lt;br /&gt;
&lt;br /&gt;
* Spannung an Pin 15 und 16 liegt an? (Falsche Zeichen kommen an, aber in der richtigen Reihenfolge. Beim Test durch Kurzschluss von T1IN und R1OUT kommt nichts an)&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;
* Hängen andere SPI-Devices am Bus, die undefiniertes CS haben?&lt;br /&gt;
* Sind die 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? (im allgemeinen)&lt;br /&gt;
* (im speziellen) Bei einige Controllern liegt der JTAG mit auf den ADC-Pins. Die betroffenen ADC-Kanäle werden erst richtig funktionieren, wenn der JTAG deaktiviert ist. Das geht per Fuse oder - wenn man an die Fuses nicht mehr herrankommen sollte, weil man mit einem Bootloader arbeitet - auch per Software.&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* [http://www.atmel.com/Images/Atmel-2521-AVR-Hardware-Design-Considerations_ApplicationNote_AVR042.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;br /&gt;
* [http://www.youtube.com/watch?v=AP_FSyWGpoE Youtube-Video zum Thema Abblockkondensatoren]&lt;/div&gt;</summary>
		<author><name>80.64.189.58</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_Checkliste&amp;diff=88881</id>
		<title>AVR Checkliste</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_Checkliste&amp;diff=88881"/>
		<updated>2015-06-09T08:35:30Z</updated>

		<summary type="html">&lt;p&gt;80.64.189.58: IC&amp;#039;s -&amp;gt; ICs&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 dringendsten 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.&amp;amp;nbsp;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;
=== Programmieren via SPI und angeschlossene SPI-Hardware ===&lt;br /&gt;
Wenn Peripherie über SPI angebunden ist, muss sich diese zum Programmierzeitpunkt auf dem Bus neutral verhalten. Normalerweise bedeutet dies, dass die Slave-Select/Chip-Select-Leitungen der Peripherie auf high gezogen werden müssen, wenn die Chips keinen internen Pull-Up haben. Werte von 10 kΩ bis 100 kΩ für normale Anwendungen haben sich bewährt.&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 zurückgesetzt gehalten. Zwar haben die meisten(!) AVRs einen internen Pullup-Widerstand, der den Reset-Pin gegen VCC &amp;quot;zieht&amp;quot;, dieser ist jedoch relativ hochohmig (ca. 50 kΩ, vgl. Datenblatt) und reicht in extrem stark gestörter Umgebung nicht aus, um den Reset-Pin sicher &amp;quot;hochzuhalten&amp;quot;. Als Mindestbeschaltung empfiehlt sich dringend, einen externen Pullup-Widerstand vorzusehen (typisch 10 kΩ), der den Reset-Pin mit VCC verbindet. Er sollte nicht kleiner als 4,7 kΩ sein, da der Programmieradapter sonst eventuell den Reset-Pin während des Programmiervorgangs nicht sicher auf &amp;quot;low&amp;quot; ziehen kann. Mit einem Oszilloskop kann man gut überprüfen, ob der Pegel am Reset-Pin sauber zwischen high und low wechselt. 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;
=== Flashen / Lesen / Fuse nur einmal möglich ===&lt;br /&gt;
&lt;br /&gt;
Es kann vorkommen, dass ein AVR nur einmal programmiert werden kann, danach geht es nicht mehr (z.B. Typ wird nicht mehr erkannt). Erst nachdem die Versorgungsspannung getrennt / wieder verbunden ist, geht es erneut.&lt;br /&gt;
&lt;br /&gt;
In diesem Fall ist meistens der Resetpin kurzgeschlossen, daher lässt sich der AVR einmal programmieren.&lt;br /&gt;
&lt;br /&gt;
Der Reset PIN müsste bei korrekter Beschaltung eine Spannung nahe VCC (z.B. 4.9V) aufweisen, ist die Spannung bei GND, ist der Pin kurzgeschlossen und verursacht dieses Problem.&lt;br /&gt;
&lt;br /&gt;
=== Abblockkondensator(en) ordnungsgemäß installiert? ===&lt;br /&gt;
&lt;br /&gt;
Abblockkondensatoren dienen dazu, impulsartige Einbrüche der Betriebsspannung, die durch schnelle Schaltvorgänge verursacht werden können, zu minimieren. Sie verhindern unkontrollierte Brownouts, welche durch diese Spannungseinbrüche auftreten können. 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;
* Eine niederimpedante Anbindung sollte gegeben sein - also keine Stegleitungen. Dies bedeutet, das die Versorgungsspannung erst durch das Pad des Abblockkondensators fließen MUSS und dann weiter zum IC gereicht wird&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 sollte jeder VCC-Pin mit einem eigenen Abblockkondensator beschaltet werden (z. B. AVRs in SMD-Bauform wie dem ATmega16A also mit vier Kondensatoren). Dabei ist darauf zu achten, jeder Abblockkondensator  mit einem eigenen Via auf die niederimpedante (heißt Hochfrequenz gut leiten) großflächige, nicht unterbrochene Massefläche kontaktiert wird.&lt;br /&gt;
&lt;br /&gt;
* Es sollten keramische Kondensatoren mit einer Kapazität von maximal 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 (der Widerstand=Impedanz ist bei hochfrequenten Spannungen zu groß - ein schneller (hochfrequenter) Spannungsimpuls kann so nicht abgeleitet werden)!&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 [[Quarze und AVR|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 ICs mit mehreren Ground-Anschlüssen müssen immer 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.&amp;amp;nbsp;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.&amp;amp;nbsp;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.&amp;amp;nbsp;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;
[[Bild:isp.png|thumb|300px|right|ISP-Adapter]]&lt;br /&gt;
Der ATmega64 und der ATmega128 sowie alle vom ATMega128 abgeleiteten AVRs im 64-Pin-Gehäuse (ATMega641/1281/2561, AT90PWM2/3/2B/3B sowie AT90CAN32/64/128, Ausnahmen 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:&lt;br /&gt;
:* MOSI → PE0 (Pin 2)&lt;br /&gt;
:* MISO → PE1 (Pin 3)&lt;br /&gt;
:* SCK → PB1 (Pin 11)&lt;br /&gt;
:* RESET → RESET (Pin 20)&lt;br /&gt;
: 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 und 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 Gemeinheit betrifft die M103C-Fuse (ATmega103 Compatibility Mode, nur bei den ATmega-Typen, nicht beim AT90CAN32/64/128). Diese ist bei fabrikneuen Atmega64/128 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 RET abstürzt, da der SRAM an einer anderen Stelle endet 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;
=== Mainschleife vorhanden? ===&lt;br /&gt;
&lt;br /&gt;
Insbesondere beim Testen von Interrupts kann es passieren, dass man keine eigentliche Programmschleife vorsieht, weil ja alles in den Interrupts passiert. Das führt dazu, dass der Controller nach Abarbeiten aller Befehle in &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;int main(void) {}&amp;lt;/syntaxhighlight&amp;gt; seine Arbeit einstellt und daher auch keine Interrupts mehr funktionieren. Demnach sollte bei rein Interrupt-basierten Programmen die Funktion mindestens so aussehen: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;int main(void)&lt;br /&gt;
{&lt;br /&gt;
    // hier Interrupts definieren&lt;br /&gt;
    // und einschalten&lt;br /&gt;
    while (1){}&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&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;
Außerdem sollte man immer im Datenblatt des Controllers nachsehen, wie die Interrupttabelle aufgebaut ist. Die kleinen AVRs verwenden ein RCALL zum Anspringen der Interrupts, welches 1 Wort lang ist. Die grossen AVRs mit mehr als 8 KiBi FLASH verwenden ein CALL, 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 SEI eingeschaltet werden).&lt;br /&gt;
&lt;br /&gt;
Oft hilft es einen Catch All Interruptvektor zu definieren um herauszufinden ob ein Fehler (z.B. ein Neubeginn des Programms) vorliegt.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ISR (BADISR_vect)&lt;br /&gt;
{&lt;br /&gt;
    // Hier eine Fehlerausgabe definieren.&lt;br /&gt;
    // Z.B. UART-Ausgabe oder ein PIN toggeln&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dann findet man solche Fehler recht schnell.&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;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&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;/syntaxhighlight&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;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&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;/syntaxhighlight&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.&amp;amp;nbsp;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.&amp;amp;nbsp;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.&amp;amp;nbsp;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.&amp;amp;nbsp;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.&amp;amp;nbsp;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.&amp;amp;nbsp;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.&amp;amp;nbsp;B.:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
    TIFR = (1&amp;lt;&amp;lt;TOV0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&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.&amp;amp;nbsp;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.&amp;amp;nbsp;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.&amp;amp;nbsp;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 weist 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 [[Interrupt]]routine 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;
=== Wo nötig Variablenzugriff atomar gestaltet? ===&lt;br /&gt;
Der Zugriff auf Variablen &amp;gt;8 Bit welche in der ISR und in der Hauptfunktion genutzt werden muss [[atomar]] erfolgen. Das Vergessen dieser Regel führt selten zu Problemen, aber wenn dann zu schwer Nachvollziehbaren...&lt;br /&gt;
&lt;br /&gt;
=== Die Programmierfrequenz passend? ===&lt;br /&gt;
&lt;br /&gt;
Sollte ein Programmieren nicht möglich sein erst einmal die Programmiergeschwindigkeit bei AVR dude mit der Option&lt;br /&gt;
-B bitclock anpassen&lt;br /&gt;
wobei bitclock die Perioden dauer in Millisekunden (floating-point Zahl) ist. Normalerweise -B 1 für Controller mit &amp;gt;=4MHz daher ist bei der Erstprogrammierung ein höherer Wert zu versuchen.&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 kΩ bis 10 kΩ 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 oder einen Oszillator verwenden, egal bei welcher Baudrate: 3% Fehler sind immer 3% Fehler, 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.&amp;amp;nbsp;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.&amp;amp;nbsp;B. in [[Bascom AVR|BASCOM]], [[C]]), dann muss dort der Takt &#039;&#039;genau&#039;&#039; angegeben werden. Setzt man z.&amp;amp;nbsp;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% zu hoch wäre. Damit funktioniert die Übertragung nicht mehr.&lt;br /&gt;
&lt;br /&gt;
* Im AVR-Studio kann man die Taktfrequenz sowohl über ein &amp;lt;code&amp;gt;#define F_CPU&amp;lt;/code&amp;gt; im Quelltext als auch über das Optionsmenu oder das selbsterstellte Makefile einstellen. Es darf nur &#039;&#039;eine&#039;&#039; Variante verwendet werden!&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;nicht&#039;&#039; programmiert?&lt;br /&gt;
&lt;br /&gt;
* Es taucht auch des öfteren das Missverständnis auf, dass man nur F_CPU verändern muss, um den µC mit einem anderen Takt laufen zu lassen. Dem ist nicht so. Der µC-Takt wird durch die Fuses bzw. den eventuell angeschlossenen Quarz oder Quarzoszillator bestimmt. F_CPU dient nur dazu, die dadurch festgelegte Frequenz im C-Programm zur Verfügung zu haben. F_CPU ist nur eine Information, mit der man bei der Programmierung arbeiten kann. Aber ein anderer F_CPU-Wert führt nicht dazu, dass der µC dann magisch auf diese Frequenz umgestellt wird.&lt;br /&gt;
&lt;br /&gt;
* Um zu prüfen, ob der externe Quarz auch wirklich verwendet wird, kann man  mittels _delay_ms() testweise eine LED im Sekundentakt blinken lassen. Den Unterschied zwischen Quarz und internem RC-Oszillator kann man bei größeren Frequenzunterschieden leicht sehen. Ebenso sieht man, ob versehentlich die CLKDIV Fuse gesetzt ist: die Blinkfrequenz ist dann achtmal langsamer. Allerdings muss man auch hier aufpassen. Siehe [[AVR-GCC-Tutorial#Warteschleifen (delay.h)|AVR-GCC-Tutorial: Warteschleifen]].&lt;br /&gt;
&lt;br /&gt;
Im folgenden Programm muss angepasst werden:&lt;br /&gt;
*Die vermeintliche Taktfrequenz F_CPU&lt;br /&gt;
*der Port und der Pin, an dem eine LED angeschlossen ist.&lt;br /&gt;
&lt;br /&gt;
Wird das Programm laufen gelassen, muss die LED 1 Sekunde ein/1 Sekunde aus sein. Stimmen die Zeiten nicht, ist das ein deutlicher Hinweis darauf, dass die tatsächlich vom µC verwendete Taktfrequenz nicht mit der in F_CPU angegebenen übereinstimmt. Das Programm muss mit aktivierter Optimierung &amp;lt;code&amp;gt;-Os&amp;lt;/code&amp;gt; compiliert werden.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Testprogramm für CPU Takt&lt;br /&gt;
// Hier die vermeintliche Taktrate des µC eintragen&lt;br /&gt;
// Im Beispiel hier: 1MHz&lt;br /&gt;
&lt;br /&gt;
#define F_CPU 1000000&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Hier die tatsächlich verwendeten Parameter angeben&lt;br /&gt;
&lt;br /&gt;
#define LED_PORT    PORTB&lt;br /&gt;
#define LED_DDR     DDRB&lt;br /&gt;
#define LED_PIN     PB0&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
   LED_DDR |= 1 &amp;lt;&amp;lt; LED_PIN;&lt;br /&gt;
&lt;br /&gt;
   while (1)&lt;br /&gt;
   {&lt;br /&gt;
      LED_PORT ^= 1 &amp;lt;&amp;lt; LED_PIN;&lt;br /&gt;
      _delay_ms(1000);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Erscheinen im Terminalprogramm kryptische Zeichen anstatt ordentlichen Buchstaben (z.&amp;amp;nbsp;B. ü statt A), liegt das zu 99,9% an einer falsch eingestellten/erzeugten Baudrate im Mikrocontroller. Meistens wiederum liegt dies daran, dass der µC nicht mit der vermeintlichen Taktrate läuft und daher die Baudratenparameter falsch berechnet werden.&lt;br /&gt;
&lt;br /&gt;
* URSEL-Bit in UCSRC: Bei der Initialisierung der UART beachtet, wenn das für den verwendeten AVR notwendig ist, siehe [[AVR-GCC-Tutorial/Der_UART#Die_UART-Register|AVR-GCC-Tutorial/Der UART: Die UART-Register]].&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 erläutert.&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.&amp;amp;nbsp;B. GND-Anschluss am RS232-Stecker nicht belegt oder dergleichen).&lt;br /&gt;
&lt;br /&gt;
* Der Pegelwandler/Inverter (z.&amp;amp;nbsp;B. MAX232) muss mit Kondensatoren für die internen Ladungspumpen beschaltet werden. Beim MAX232 sind dies mindestens vier Kondensatoren ≥ 1 µF (Polung beachten!), beim MAX202, MAX232A und MAX3232 vier Kondensatoren ≥ 100 nF. Hinzu kommt der obligatorische Abblockkondensator von 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 muss stimmen (kein Hardwarehandshake bei ausschließlicher Verwendung der Pins RX/TX).&lt;br /&gt;
&lt;br /&gt;
* Wird das Signal eventuell durch zusätzliche Chips invertiert? (EEPROM von FT232 falsch Programmiert)&lt;br /&gt;
&lt;br /&gt;
* Die Hardware und Verkabelung kann man schnell prüfen, indem man den Pin R1OUT bzw. R2OUT mit T1IN bzw. T2IN am MAX232 miteinander verbindet (je nachdem welches Pinpaar verwendet wird). Dann sollte man auf dem PC ein Terminalprogramm wie Hyperterminal starten und nach dem Eingeben von Zeichen diese sofort angezeigt bekommen, egal mit welcher Baudrate. Lediglich die Flusssteuerung muss auf &amp;quot;Kein&amp;quot; eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
: Man muss aber beachten, dass T1IN bzw. T2IN für diesen Test &#039;&#039;nicht&#039;&#039; mit dem Mikrocontroller verbunden sein darf, weil sonst zwei Ausgänge miteinander verbunden sind, siehe [[Ausgangsstufen Logik-ICs]]. Wenn der µC gesockelt ist, kann man ihn dafür einfach aus dem Sockel nehmen und die RX/TX Pins direkt im µC-Sockel mit einem Stück Draht verbinden.&lt;br /&gt;
&lt;br /&gt;
* UART Ausgabe-Pin als Output-Pin deklariert?&lt;br /&gt;
&lt;br /&gt;
* Spannung an Pin 15 und 16 liegt an? (Falsche Zeichen kommen an, aber in der richtigen Reihenfolge. Beim Test durch Kurzschluss von T1IN und R1OUT kommt nichts an)&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;
* Hängen andere SPI-Devices am Bus, die undefiniertes CS haben?&lt;br /&gt;
* Sind die 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? (im allgemeinen)&lt;br /&gt;
* (im speziellen) Bei einige Controllern liegt der JTAG mit auf den ADC-Pins. Die betroffenen ADC-Kanäle werden erst richtig funktionieren, wenn der JTAG deaktiviert ist. Das geht per Fuse oder - wenn man an die Fuses nicht mehr herrankommen sollte, weil man mit einem Bootloader arbeitet - auch per Software.&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* [http://www.atmel.com/Images/Atmel-2521-AVR-Hardware-Design-Considerations_ApplicationNote_AVR042.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;br /&gt;
* [http://www.youtube.com/watch?v=AP_FSyWGpoE Youtube-Video zum Thema Abblockkondensatoren]&lt;/div&gt;</summary>
		<author><name>80.64.189.58</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_Checkliste&amp;diff=88880</id>
		<title>AVR Checkliste</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_Checkliste&amp;diff=88880"/>
		<updated>2015-06-09T08:35:08Z</updated>

		<summary type="html">&lt;p&gt;80.64.189.58: Beschreibung Einsatzzweck Abblockkondensatoren korrigiert&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 dringendsten 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.&amp;amp;nbsp;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;
=== Programmieren via SPI und angeschlossene SPI-Hardware ===&lt;br /&gt;
Wenn Peripherie über SPI angebunden ist, muss sich diese zum Programmierzeitpunkt auf dem Bus neutral verhalten. Normalerweise bedeutet dies, dass die Slave-Select/Chip-Select-Leitungen der Peripherie auf high gezogen werden müssen, wenn die Chips keinen internen Pull-Up haben. Werte von 10 kΩ bis 100 kΩ für normale Anwendungen haben sich bewährt.&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 zurückgesetzt gehalten. Zwar haben die meisten(!) AVRs einen internen Pullup-Widerstand, der den Reset-Pin gegen VCC &amp;quot;zieht&amp;quot;, dieser ist jedoch relativ hochohmig (ca. 50 kΩ, vgl. Datenblatt) und reicht in extrem stark gestörter Umgebung nicht aus, um den Reset-Pin sicher &amp;quot;hochzuhalten&amp;quot;. Als Mindestbeschaltung empfiehlt sich dringend, einen externen Pullup-Widerstand vorzusehen (typisch 10 kΩ), der den Reset-Pin mit VCC verbindet. Er sollte nicht kleiner als 4,7 kΩ sein, da der Programmieradapter sonst eventuell den Reset-Pin während des Programmiervorgangs nicht sicher auf &amp;quot;low&amp;quot; ziehen kann. Mit einem Oszilloskop kann man gut überprüfen, ob der Pegel am Reset-Pin sauber zwischen high und low wechselt. 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;
=== Flashen / Lesen / Fuse nur einmal möglich ===&lt;br /&gt;
&lt;br /&gt;
Es kann vorkommen, dass ein AVR nur einmal programmiert werden kann, danach geht es nicht mehr (z.B. Typ wird nicht mehr erkannt). Erst nachdem die Versorgungsspannung getrennt / wieder verbunden ist, geht es erneut.&lt;br /&gt;
&lt;br /&gt;
In diesem Fall ist meistens der Resetpin kurzgeschlossen, daher lässt sich der AVR einmal programmieren.&lt;br /&gt;
&lt;br /&gt;
Der Reset PIN müsste bei korrekter Beschaltung eine Spannung nahe VCC (z.B. 4.9V) aufweisen, ist die Spannung bei GND, ist der Pin kurzgeschlossen und verursacht dieses Problem.&lt;br /&gt;
&lt;br /&gt;
=== Abblockkondensator(en) ordnungsgemäß installiert? ===&lt;br /&gt;
&lt;br /&gt;
Abblockkondensatoren dienen dazu, impulsartige Einbrüche der Betriebsspannung, die durch schnelle Schaltvorgänge verursacht werden können, zu minimieren. Sie verhindern unkontrollierte Brownouts, welche durch diese Spannungseinbrüche auftreten können. 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;
* Eine niederimpedante Anbindung sollte gegeben sein - also keine Stegleitungen. Dies bedeutet, das die Versorgungsspannung erst durch das Pad des Abblockkondensators fließen MUSS und dann weiter zum IC gereicht wird&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 sollte jeder VCC-Pin mit einem eigenen Abblockkondensator beschaltet werden (z. B. AVRs in SMD-Bauform wie dem ATmega16A also mit vier Kondensatoren). Dabei ist darauf zu achten, jeder Abblockkondensator  mit einem eigenen Via auf die niederimpedante (heißt Hochfrequenz gut leiten) großflächige, nicht unterbrochene Massefläche kontaktiert wird.&lt;br /&gt;
&lt;br /&gt;
* Es sollten keramische Kondensatoren mit einer Kapazität von maximal 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 (der Widerstand=Impedanz ist bei hochfrequenten Spannungen zu groß - ein schneller (hochfrequenter) Spannungsimpuls kann so nicht abgeleitet werden)!&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 [[Quarze und AVR|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 IC&#039;s mit mehreren Ground-Anschlüssen müssen immer 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.&amp;amp;nbsp;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.&amp;amp;nbsp;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.&amp;amp;nbsp;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;
[[Bild:isp.png|thumb|300px|right|ISP-Adapter]]&lt;br /&gt;
Der ATmega64 und der ATmega128 sowie alle vom ATMega128 abgeleiteten AVRs im 64-Pin-Gehäuse (ATMega641/1281/2561, AT90PWM2/3/2B/3B sowie AT90CAN32/64/128, Ausnahmen 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:&lt;br /&gt;
:* MOSI → PE0 (Pin 2)&lt;br /&gt;
:* MISO → PE1 (Pin 3)&lt;br /&gt;
:* SCK → PB1 (Pin 11)&lt;br /&gt;
:* RESET → RESET (Pin 20)&lt;br /&gt;
: 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 und 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 Gemeinheit betrifft die M103C-Fuse (ATmega103 Compatibility Mode, nur bei den ATmega-Typen, nicht beim AT90CAN32/64/128). Diese ist bei fabrikneuen Atmega64/128 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 RET abstürzt, da der SRAM an einer anderen Stelle endet 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;
=== Mainschleife vorhanden? ===&lt;br /&gt;
&lt;br /&gt;
Insbesondere beim Testen von Interrupts kann es passieren, dass man keine eigentliche Programmschleife vorsieht, weil ja alles in den Interrupts passiert. Das führt dazu, dass der Controller nach Abarbeiten aller Befehle in &amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;int main(void) {}&amp;lt;/syntaxhighlight&amp;gt; seine Arbeit einstellt und daher auch keine Interrupts mehr funktionieren. Demnach sollte bei rein Interrupt-basierten Programmen die Funktion mindestens so aussehen: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;int main(void)&lt;br /&gt;
{&lt;br /&gt;
    // hier Interrupts definieren&lt;br /&gt;
    // und einschalten&lt;br /&gt;
    while (1){}&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&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;
Außerdem sollte man immer im Datenblatt des Controllers nachsehen, wie die Interrupttabelle aufgebaut ist. Die kleinen AVRs verwenden ein RCALL zum Anspringen der Interrupts, welches 1 Wort lang ist. Die grossen AVRs mit mehr als 8 KiBi FLASH verwenden ein CALL, 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 SEI eingeschaltet werden).&lt;br /&gt;
&lt;br /&gt;
Oft hilft es einen Catch All Interruptvektor zu definieren um herauszufinden ob ein Fehler (z.B. ein Neubeginn des Programms) vorliegt.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ISR (BADISR_vect)&lt;br /&gt;
{&lt;br /&gt;
    // Hier eine Fehlerausgabe definieren.&lt;br /&gt;
    // Z.B. UART-Ausgabe oder ein PIN toggeln&lt;br /&gt;
}&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dann findet man solche Fehler recht schnell.&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;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&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;/syntaxhighlight&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;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&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;/syntaxhighlight&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.&amp;amp;nbsp;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.&amp;amp;nbsp;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.&amp;amp;nbsp;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.&amp;amp;nbsp;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.&amp;amp;nbsp;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.&amp;amp;nbsp;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.&amp;amp;nbsp;B.:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
    TIFR = (1&amp;lt;&amp;lt;TOV0);&lt;br /&gt;
&amp;lt;/syntaxhighlight&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.&amp;amp;nbsp;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.&amp;amp;nbsp;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.&amp;amp;nbsp;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 weist 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 [[Interrupt]]routine 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;
=== Wo nötig Variablenzugriff atomar gestaltet? ===&lt;br /&gt;
Der Zugriff auf Variablen &amp;gt;8 Bit welche in der ISR und in der Hauptfunktion genutzt werden muss [[atomar]] erfolgen. Das Vergessen dieser Regel führt selten zu Problemen, aber wenn dann zu schwer Nachvollziehbaren...&lt;br /&gt;
&lt;br /&gt;
=== Die Programmierfrequenz passend? ===&lt;br /&gt;
&lt;br /&gt;
Sollte ein Programmieren nicht möglich sein erst einmal die Programmiergeschwindigkeit bei AVR dude mit der Option&lt;br /&gt;
-B bitclock anpassen&lt;br /&gt;
wobei bitclock die Perioden dauer in Millisekunden (floating-point Zahl) ist. Normalerweise -B 1 für Controller mit &amp;gt;=4MHz daher ist bei der Erstprogrammierung ein höherer Wert zu versuchen.&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 kΩ bis 10 kΩ 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 oder einen Oszillator verwenden, egal bei welcher Baudrate: 3% Fehler sind immer 3% Fehler, 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.&amp;amp;nbsp;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.&amp;amp;nbsp;B. in [[Bascom AVR|BASCOM]], [[C]]), dann muss dort der Takt &#039;&#039;genau&#039;&#039; angegeben werden. Setzt man z.&amp;amp;nbsp;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% zu hoch wäre. Damit funktioniert die Übertragung nicht mehr.&lt;br /&gt;
&lt;br /&gt;
* Im AVR-Studio kann man die Taktfrequenz sowohl über ein &amp;lt;code&amp;gt;#define F_CPU&amp;lt;/code&amp;gt; im Quelltext als auch über das Optionsmenu oder das selbsterstellte Makefile einstellen. Es darf nur &#039;&#039;eine&#039;&#039; Variante verwendet werden!&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;nicht&#039;&#039; programmiert?&lt;br /&gt;
&lt;br /&gt;
* Es taucht auch des öfteren das Missverständnis auf, dass man nur F_CPU verändern muss, um den µC mit einem anderen Takt laufen zu lassen. Dem ist nicht so. Der µC-Takt wird durch die Fuses bzw. den eventuell angeschlossenen Quarz oder Quarzoszillator bestimmt. F_CPU dient nur dazu, die dadurch festgelegte Frequenz im C-Programm zur Verfügung zu haben. F_CPU ist nur eine Information, mit der man bei der Programmierung arbeiten kann. Aber ein anderer F_CPU-Wert führt nicht dazu, dass der µC dann magisch auf diese Frequenz umgestellt wird.&lt;br /&gt;
&lt;br /&gt;
* Um zu prüfen, ob der externe Quarz auch wirklich verwendet wird, kann man  mittels _delay_ms() testweise eine LED im Sekundentakt blinken lassen. Den Unterschied zwischen Quarz und internem RC-Oszillator kann man bei größeren Frequenzunterschieden leicht sehen. Ebenso sieht man, ob versehentlich die CLKDIV Fuse gesetzt ist: die Blinkfrequenz ist dann achtmal langsamer. Allerdings muss man auch hier aufpassen. Siehe [[AVR-GCC-Tutorial#Warteschleifen (delay.h)|AVR-GCC-Tutorial: Warteschleifen]].&lt;br /&gt;
&lt;br /&gt;
Im folgenden Programm muss angepasst werden:&lt;br /&gt;
*Die vermeintliche Taktfrequenz F_CPU&lt;br /&gt;
*der Port und der Pin, an dem eine LED angeschlossen ist.&lt;br /&gt;
&lt;br /&gt;
Wird das Programm laufen gelassen, muss die LED 1 Sekunde ein/1 Sekunde aus sein. Stimmen die Zeiten nicht, ist das ein deutlicher Hinweis darauf, dass die tatsächlich vom µC verwendete Taktfrequenz nicht mit der in F_CPU angegebenen übereinstimmt. Das Programm muss mit aktivierter Optimierung &amp;lt;code&amp;gt;-Os&amp;lt;/code&amp;gt; compiliert werden.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Testprogramm für CPU Takt&lt;br /&gt;
// Hier die vermeintliche Taktrate des µC eintragen&lt;br /&gt;
// Im Beispiel hier: 1MHz&lt;br /&gt;
&lt;br /&gt;
#define F_CPU 1000000&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Hier die tatsächlich verwendeten Parameter angeben&lt;br /&gt;
&lt;br /&gt;
#define LED_PORT    PORTB&lt;br /&gt;
#define LED_DDR     DDRB&lt;br /&gt;
#define LED_PIN     PB0&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
   LED_DDR |= 1 &amp;lt;&amp;lt; LED_PIN;&lt;br /&gt;
&lt;br /&gt;
   while (1)&lt;br /&gt;
   {&lt;br /&gt;
      LED_PORT ^= 1 &amp;lt;&amp;lt; LED_PIN;&lt;br /&gt;
      _delay_ms(1000);&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Erscheinen im Terminalprogramm kryptische Zeichen anstatt ordentlichen Buchstaben (z.&amp;amp;nbsp;B. ü statt A), liegt das zu 99,9% an einer falsch eingestellten/erzeugten Baudrate im Mikrocontroller. Meistens wiederum liegt dies daran, dass der µC nicht mit der vermeintlichen Taktrate läuft und daher die Baudratenparameter falsch berechnet werden.&lt;br /&gt;
&lt;br /&gt;
* URSEL-Bit in UCSRC: Bei der Initialisierung der UART beachtet, wenn das für den verwendeten AVR notwendig ist, siehe [[AVR-GCC-Tutorial/Der_UART#Die_UART-Register|AVR-GCC-Tutorial/Der UART: Die UART-Register]].&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 erläutert.&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.&amp;amp;nbsp;B. GND-Anschluss am RS232-Stecker nicht belegt oder dergleichen).&lt;br /&gt;
&lt;br /&gt;
* Der Pegelwandler/Inverter (z.&amp;amp;nbsp;B. MAX232) muss mit Kondensatoren für die internen Ladungspumpen beschaltet werden. Beim MAX232 sind dies mindestens vier Kondensatoren ≥ 1 µF (Polung beachten!), beim MAX202, MAX232A und MAX3232 vier Kondensatoren ≥ 100 nF. Hinzu kommt der obligatorische Abblockkondensator von 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 muss stimmen (kein Hardwarehandshake bei ausschließlicher Verwendung der Pins RX/TX).&lt;br /&gt;
&lt;br /&gt;
* Wird das Signal eventuell durch zusätzliche Chips invertiert? (EEPROM von FT232 falsch Programmiert)&lt;br /&gt;
&lt;br /&gt;
* Die Hardware und Verkabelung kann man schnell prüfen, indem man den Pin R1OUT bzw. R2OUT mit T1IN bzw. T2IN am MAX232 miteinander verbindet (je nachdem welches Pinpaar verwendet wird). Dann sollte man auf dem PC ein Terminalprogramm wie Hyperterminal starten und nach dem Eingeben von Zeichen diese sofort angezeigt bekommen, egal mit welcher Baudrate. Lediglich die Flusssteuerung muss auf &amp;quot;Kein&amp;quot; eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
: Man muss aber beachten, dass T1IN bzw. T2IN für diesen Test &#039;&#039;nicht&#039;&#039; mit dem Mikrocontroller verbunden sein darf, weil sonst zwei Ausgänge miteinander verbunden sind, siehe [[Ausgangsstufen Logik-ICs]]. Wenn der µC gesockelt ist, kann man ihn dafür einfach aus dem Sockel nehmen und die RX/TX Pins direkt im µC-Sockel mit einem Stück Draht verbinden.&lt;br /&gt;
&lt;br /&gt;
* UART Ausgabe-Pin als Output-Pin deklariert?&lt;br /&gt;
&lt;br /&gt;
* Spannung an Pin 15 und 16 liegt an? (Falsche Zeichen kommen an, aber in der richtigen Reihenfolge. Beim Test durch Kurzschluss von T1IN und R1OUT kommt nichts an)&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;
* Hängen andere SPI-Devices am Bus, die undefiniertes CS haben?&lt;br /&gt;
* Sind die 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? (im allgemeinen)&lt;br /&gt;
* (im speziellen) Bei einige Controllern liegt der JTAG mit auf den ADC-Pins. Die betroffenen ADC-Kanäle werden erst richtig funktionieren, wenn der JTAG deaktiviert ist. Das geht per Fuse oder - wenn man an die Fuses nicht mehr herrankommen sollte, weil man mit einem Bootloader arbeitet - auch per Software.&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* [http://www.atmel.com/Images/Atmel-2521-AVR-Hardware-Design-Considerations_ApplicationNote_AVR042.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;br /&gt;
* [http://www.youtube.com/watch?v=AP_FSyWGpoE Youtube-Video zum Thema Abblockkondensatoren]&lt;/div&gt;</summary>
		<author><name>80.64.189.58</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Low_Cost_FPGA_Konfiguration&amp;diff=88126</id>
		<title>Low Cost FPGA Konfiguration</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Low_Cost_FPGA_Konfiguration&amp;diff=88126"/>
		<updated>2015-03-30T09:26:19Z</updated>

		<summary type="html">&lt;p&gt;80.64.189.58: Orthographie&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Wenn man FPGAs auf selbst entworfenen Platinen einsetzen möchte, stellt sich oft das Problem des Konfigurationsspeichers. Die meisten FPGAs sind SRAM-basiert und haben keinen [[Speicher#NV-RAM | nichtflüchtigen]] Speicher auf dem Chip bzw. im gleichen Gehäuse (Ausnahmen sind Spartan-3N von Xilinx, XP und XP2 von Lattice und die FPGAs von Actel in Antifuse-Technologie). Also muss irgendwie ein Speicher her. Dazu gibt es mehrere Möglichkeiten.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
! Konfigurationsmethode || Vorteile || Nachteile&lt;br /&gt;
|-&lt;br /&gt;
| PC mit Programmierkabel || einfache und schnelle Programmierung || Platine kann nur mit PC genutzt werden&lt;br /&gt;
|-&lt;br /&gt;
| Spezial-PROM&amp;lt;BR/&amp;gt; z.&amp;amp;nbsp;B. Xilinx XCFxxS || einfachste Anwendung || hoher Preis&amp;lt;BR/&amp;gt;schlechte Verfügbarkeit für Hobbybastler&lt;br /&gt;
|-&lt;br /&gt;
| Standard-EEPROM mit [[SPI]] || einfache Anwendung&amp;lt;BR/&amp;gt;billig  || nur bei einigen FPGA-Familien möglich (z.&amp;amp;nbsp;B. Spartan3E)&lt;br /&gt;
|-&lt;br /&gt;
| Mikrocontroller mit &amp;lt;BR/&amp;gt;internem oder externem Flash || sehr gute Verfügbarkeit für Hobbybastler&amp;lt;BR/&amp;gt;billig || zusätzlicher Mikrocontroller nötig&amp;lt;BR/&amp;gt;wenn das FPGA allein auf der Platine betrieben wird&amp;lt;BR/&amp;gt;Zusatzaufwand für die Programmierung des EEPROMs und Mikrocontrollers &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel soll die letzte Methode näher beleuchten. Dabei wird ein FPGA vom Typ Spartan 2 von [http://www.xilinx.com Xilinx] sowie ein [[Mikrocontroller]] der [[AVR]]-Familie vom Typ Tiny12 von Atmel eingesetzt. Da die FPGAs anderer Hersteller aber sehr ähnlich konfiguriert werden, kann man das Ganze leicht anpassen.&lt;br /&gt;
&lt;br /&gt;
== FPGA Konfiguration mit Mikrocontroller ==&lt;br /&gt;
&lt;br /&gt;
Für kleine bis mittlere FPGAs wird nur verhältnismässig wenig Konfigurationsspeicher benötigt. Auf der anderen Seite gibt es kleine [[Speicher#EEPROM | EEPROMs]] im SO-8 Gehäuse mit [[I2C]] Schnittstelle. Damit kann sehr kostengünstig und platzsparend die Konfiguration gespeichert werden. Nun braucht man nur noch einen kleinen Mikrocontroller, welcher das EEPROM ausliest und die Daten zum FPGA schickt. Glücklicherweise gibt es auch die im sehr kleinen SO-8 Gehäuse. Damit ist die Lösung sehr platzsparend.&lt;br /&gt;
&lt;br /&gt;
{| border =&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot;| FPGA-Familie&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot;| Typ&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot;| Konfiguration&amp;lt;BR&amp;gt;[Bit]&lt;br /&gt;
! colspan=&amp;quot;3&amp;quot; | EEPROM-Anzahl&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; | Konfigurationszeit [s]&amp;lt;BR&amp;gt;I2C mit 400kBit/s&lt;br /&gt;
|-&lt;br /&gt;
! 24C128 || 24C256 || 24C512&lt;br /&gt;
|-&lt;br /&gt;
|rowspan=&amp;quot;6&amp;quot; | Spartan 2&lt;br /&gt;
| XC2S15    &lt;br /&gt;
| align=&amp;quot;right&amp;quot; | 197.696  &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; | 1    &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0,5&lt;br /&gt;
|-&lt;br /&gt;
| XC2S30   &lt;br /&gt;
| align=&amp;quot;right&amp;quot; | 336.768  &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,8&lt;br /&gt;
|-&lt;br /&gt;
| XC2S50   &lt;br /&gt;
| align=&amp;quot;right&amp;quot; | 559.200  &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5 &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,4&lt;br /&gt;
|-&lt;br /&gt;
| XC2S100  &lt;br /&gt;
| align=&amp;quot;right&amp;quot; | 781.216  &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6 &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; | 2&lt;br /&gt;
|-&lt;br /&gt;
| XC2S150  &lt;br /&gt;
| align=&amp;quot;right&amp;quot; | 1.040.096 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 8 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2,6&lt;br /&gt;
|-&lt;br /&gt;
| XC2S200  &lt;br /&gt;
| align=&amp;quot;right&amp;quot; | 1.335.840 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | * &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 6 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3,3&lt;br /&gt;
|-&lt;br /&gt;
| rowspan=&amp;quot;4&amp;quot; | Spartan 3&lt;br /&gt;
| XC3S50   &lt;br /&gt;
| align=&amp;quot;right&amp;quot; | 439.264  &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4 &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; | 1,1&lt;br /&gt;
|-&lt;br /&gt;
| XC3S200  &lt;br /&gt;
| align=&amp;quot;right&amp;quot; | 1.047.616 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 8 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2,6&lt;br /&gt;
|-&lt;br /&gt;
| XC3S400  &lt;br /&gt;
| align=&amp;quot;right&amp;quot; | 1.699.136 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | * &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4,2&lt;br /&gt;
|-&lt;br /&gt;
| XC3S1000 &lt;br /&gt;
| align=&amp;quot;right&amp;quot;| 3.223.488 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | * &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | * &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 8,1&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Schaltung ==&lt;br /&gt;
&lt;br /&gt;
Die Schaltung ist recht einfach. Über den [[I2C]]-[[Bus]] wird ein oder mehrere EEPROMs ausgelesen. Zur Konfiguration sind nur die vier Signale CCLK, Din, Done und PROGRAM benötigt. Der FPGA wird im &#039;&#039;Slave Serial Mode&#039;&#039; betrieben. Da der 8-polige Mikrocontroller aber nur 5 wirklich freie IO-Pins hat, müssen Reset und PROGRAM verbunden werden. Das ist aber kein Problem, im Gegenteil, hier werden FPGA und Mikrocontroller parallel in den Resetzustand versetzt, wenn die Versorgungsspannung angelegt wird oder manuell PROGAMM auf LOW gezogen wird. Es ist jeder beliebige [[AVR]] verwendbar, da das Programm sehr klein ist und keinerlei spezielle Resourcen benötigt, nicht einmal SRAM. Es können EEPROMs mit 128, 256 oder 512kbit eingesetzt werden. Allerdings müssen alle die gleiche Grösse haben. Eine LED am Signal SDA wird zur Fehleranzeige verwendet. Es sollte ein Low Current Typ mit niedriger Flusspannung sein (also keinen blauen oder weissen [[LED]]s). R5 dient der Entkopplung von DONE zur [[ISP]]-Schnittstelle. Damit kann der AVR in der Schaltung programmiert werden.&lt;br /&gt;
&lt;br /&gt;
[[bild: fpga_config.png | thumb | left | 640px| Schaltplan des FPGA Konfigurators]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Programmierung des Mikrocontrollers ==&lt;br /&gt;
&lt;br /&gt;
Die Programmierung des Konfigurationsprogramms erfolgt in Assembler. Zum einen um eine minimale Programmgröße und maximale Geschwindigkeit zu erzielen. Zum anderen, weil kleine AVRs ohne SRAM vom AVR-GCC nicht unterstützt werden. Das ist aber unkritisch, das Programm ist klein und damit überschaubar.&lt;br /&gt;
&lt;br /&gt;
Nach dem Reset wird der Oszillator auf maximalen Takt gestellt, der ist beim Tiny12 sowieso nicht so hoch, max. 2,5 MHz. Dann werden die IOs und Variablen initialisiert. Am I2C-Bus können maximal acht EEPROMs angeschlossen werden, weil diese ICs nur maximal drei konfigurierbare Adressbits besitzen, einige Typen sogar nur zwei. Wenn die Größe der Konfigurationsdatei die Größe eines einzelnen EEPROMS übersteigt, muss schrittweise aus den einzelnen EEPROMs gelesen werden. Dazu muss der jeweilige EEPROM zum Beginn adressiert werden. Danach können lückenlos die Daten aus dem EEPROM gelesen werden. Nachdem alle Bytes geladen wurden wird noch ein zusätzliches Byte geschickt, um die Startsequenz des FPGAs auszulösen. Ist die Konfiguration erfolgreich verlaufen ist danach der FPGA in Funktion. Das wird durch das Signal &#039;&#039;Done&#039;&#039; angezeigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
.include &amp;quot;tn12def.inc&amp;quot;&lt;br /&gt;
&lt;br /&gt;
;*******************************************************************************&lt;br /&gt;
;*&lt;br /&gt;
;* A small but fine FPGA configurator&lt;br /&gt;
;* using a Tiny 12 and serial EEPROMs &lt;br /&gt;
;*&lt;br /&gt;
;* Up to eigth EEPROMs can be cascaded on the I2C bus&lt;br /&gt;
;* All devices must be of same size&lt;br /&gt;
;*&lt;br /&gt;
;* theoritical limit is 8x64kB = 512 kB&lt;br /&gt;
;*&lt;br /&gt;
;* Examles for FPGA config size&lt;br /&gt;
;* Spartan-II : XC2S200(biggest family member): 166,980 Bytes&lt;br /&gt;
;* Spartan-3  : XC3S1000                      : 402,936 Bytes&lt;br /&gt;
;*&lt;br /&gt;
;* Configuration speed is ~8.5kBytes/s @ 2MHz&lt;br /&gt;
;* Top speed is ~ 43kB/s @ 10 MHz, 400kHz limit of I2C&lt;br /&gt;
;*&lt;br /&gt;
;* example uses a Xilinx XC2S30 with 42.096 bytes config size&lt;br /&gt;
;* and a ST24C512 with 64 kB&lt;br /&gt;
&lt;br /&gt;
.equ fpga_size   = 42096;           ; FPGA config file size&lt;br /&gt;
.equ EEPROM_size = 65536;           ; EEPROM size per device&lt;br /&gt;
.equ F_CPU_MHz   = 2;               ; CPU clock in MHz, 1..10&lt;br /&gt;
&lt;br /&gt;
.equ bitreverse  = 0               &lt;br /&gt;
&lt;br /&gt;
;*  = 0 , bits will be copied bit by bit from EEPROM to FPGA, faster configuration&lt;br /&gt;
;*        binary files must have same bitorder as required by FPGA (MSB first)&lt;br /&gt;
;*        For Xilinx, the bit files must be processed by bitdreher.exe!!!&lt;br /&gt;
&lt;br /&gt;
;*  = 1 , bits will be copied byte by bytes from EEPROM and written bit reversed to FPGA, slow configuration&lt;br /&gt;
;*        binary files must have reverse bitorder as required by FPGA (LSB first)&lt;br /&gt;
;*        For Xilinx, the bit files are generated this way by default&lt;br /&gt;
&lt;br /&gt;
;*******************************************************************************&lt;br /&gt;
 &lt;br /&gt;
.equ cfg_port = portb&lt;br /&gt;
.equ cfg_ddr  = ddrb&lt;br /&gt;
.equ cfg_pin  = pinb  &lt;br /&gt;
&lt;br /&gt;
.equ DIN   = PB0        ; FPGA serial configuration&lt;br /&gt;
.equ DONE  = PB1&lt;br /&gt;
.equ CCLK  = PB2&lt;br /&gt;
.equ SDA   = PB3        ; Connection to I2C EEPROM&lt;br /&gt;
.equ SCL   = PB4&lt;br /&gt;
&lt;br /&gt;
; Reset is connected to FPGA AND AVR, so we have a automatic Power-on reset&lt;br /&gt;
&lt;br /&gt;
; some marcos to support readability&lt;br /&gt;
&lt;br /&gt;
.macro SDA_LOW&lt;br /&gt;
    sbi     cfg_ddr, sda    ; open drain, low&lt;br /&gt;
.endmacro &lt;br /&gt;
&lt;br /&gt;
.macro SDA_HIGH&lt;br /&gt;
    cbi     cfg_ddr, sda    ; open drain, high&lt;br /&gt;
.endmacro&lt;br /&gt;
&lt;br /&gt;
.macro SCL_LOW&lt;br /&gt;
    sbi     cfg_ddr, scl    ; open drain, low&lt;br /&gt;
.endmacro &lt;br /&gt;
&lt;br /&gt;
.macro SCL_HIGH&lt;br /&gt;
    cbi     cfg_ddr, scl    ; open drain, high&lt;br /&gt;
.endmacro&lt;br /&gt;
&lt;br /&gt;
.macro DIN_LOW&lt;br /&gt;
    cbi     cfg_port, din   ; push pull&lt;br /&gt;
.endmacro &lt;br /&gt;
&lt;br /&gt;
.macro DIN_HIGH&lt;br /&gt;
    sbi     cfg_port, din   ; push pull&lt;br /&gt;
.endmacro&lt;br /&gt;
&lt;br /&gt;
.macro CCLK_LOW&lt;br /&gt;
    cbi     cfg_port, cclk  ; push pull&lt;br /&gt;
.endmacro &lt;br /&gt;
&lt;br /&gt;
.macro CCLK_HIGH&lt;br /&gt;
    sbi     cfg_port, cclk  ; push pull&lt;br /&gt;
.endmacro&lt;br /&gt;
&lt;br /&gt;
.macro i2c_error_check&lt;br /&gt;
    brts    PC+2&lt;br /&gt;
    rjmp    error_i2c&lt;br /&gt;
.endmacro&lt;br /&gt;
&lt;br /&gt;
; add a delay to reach given delay time&lt;br /&gt;
; usage&lt;br /&gt;
; delay_1 time [Unit 0.1us], clocks_already_done&lt;br /&gt;
.macro delay&lt;br /&gt;
&lt;br /&gt;
; calculate number of remaining clocks&lt;br /&gt;
; +1 is safety margin to account for integer truncation&lt;br /&gt;
&lt;br /&gt;
.set clks = @0*F_CPU_MHz/10-@1+1&lt;br /&gt;
&lt;br /&gt;
; use optimized delay blocks with &amp;quot;nonsense&amp;quot; commands to have maximum&lt;br /&gt;
; delay with minimum code size&lt;br /&gt;
&lt;br /&gt;
.if clks==1&lt;br /&gt;
    nop&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==2&lt;br /&gt;
    ld  null, z&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==3&lt;br /&gt;
    lpm&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==4&lt;br /&gt;
    lpm&lt;br /&gt;
    nop&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==5&lt;br /&gt;
    lpm&lt;br /&gt;
    ld  null, z&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==6&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==7&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    nop&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==8&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    ld  null,z&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==9&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==10&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    nop&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==11&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    ld  null, z&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==12&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==13&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    nop&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.if clks==14&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    lpm&lt;br /&gt;
    ld  null, z&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
.endmacro&lt;br /&gt;
&lt;br /&gt;
.def zero  = r1         ; always zero&lt;br /&gt;
.def one   = r2         ; always one&lt;br /&gt;
.def null  = r3         ; write only ;-)&lt;br /&gt;
.def tmp1  = r16        ; general purpose&lt;br /&gt;
.def tmp2  = r17&lt;br /&gt;
.def tmp3  = r18&lt;br /&gt;
.def cnt0  = r19        ; loop counter, 24 Bit&lt;br /&gt;
.def cnt1  = r20&lt;br /&gt;
.def cnt2  = r21            &lt;br /&gt;
.def i2c   = r22        ; I2C address, used for multiple devices&lt;br /&gt;
.def abs0  = r23        ; data counter, 24 Bit&lt;br /&gt;
.def abs1  = r24        ; &lt;br /&gt;
.def abs2  = r25&lt;br /&gt;
&lt;br /&gt;
;*&lt;br /&gt;
;*******************************************************************************&lt;br /&gt;
&lt;br /&gt;
.cseg&lt;br /&gt;
; lets go&lt;br /&gt;
&lt;br /&gt;
; initialize stack&lt;br /&gt;
&lt;br /&gt;
; hardware stack for Tiny12, no init necessary&lt;br /&gt;
&lt;br /&gt;
; full speed, ~2 MHz with ATtiny12&lt;br /&gt;
&lt;br /&gt;
    ldi     tmp1,0xFF&lt;br /&gt;
    out     osccal, tmp1&lt;br /&gt;
&lt;br /&gt;
; config IOs&lt;br /&gt;
&lt;br /&gt;
    ldi     tmp1, (1&amp;lt;&amp;lt;cclk) | (1&amp;lt;&amp;lt;din)&lt;br /&gt;
    out     cfg_ddr,tmp1&lt;br /&gt;
&lt;br /&gt;
    ldi     tmp1, (1&amp;lt;&amp;lt;done)&lt;br /&gt;
    out     cfg_port,tmp1           ; internal pull up for DONE&lt;br /&gt;
&lt;br /&gt;
; generate constant registers&lt;br /&gt;
&lt;br /&gt;
    sub     zero,zero&lt;br /&gt;
    ldi     tmp1,1&lt;br /&gt;
    mov     one,tmp1&lt;br /&gt;
    ldi     i2c,0xA0                ; I2C base address&lt;br /&gt;
&lt;br /&gt;
; set byte counter&lt;br /&gt;
&lt;br /&gt;
    ldi     abs0,byte1(fpga_size)&lt;br /&gt;
    ldi     abs1,byte2(fpga_size)&lt;br /&gt;
    ldi     abs2,byte3(fpga_size)&lt;br /&gt;
        &lt;br /&gt;
; wait 10ms for FPGA to finish power up and clear config space&lt;br /&gt;
&lt;br /&gt;
    ldi     tmp1,10&lt;br /&gt;
    rcall   wait&lt;br /&gt;
&lt;br /&gt;
; when using multiple EEPROMs, we must address them individual&lt;br /&gt;
&lt;br /&gt;
device_loop:&lt;br /&gt;
&lt;br /&gt;
; number of remaining bytes &amp;gt;EEPROM_size ?&lt;br /&gt;
&lt;br /&gt;
    ldi     tmp1,byte1(EEPROM_size)&lt;br /&gt;
    ldi     tmp2,byte2(EEPROM_size)&lt;br /&gt;
    ldi     tmp3,byte3(EEPROM_size)&lt;br /&gt;
&lt;br /&gt;
    cp      abs0,tmp1&lt;br /&gt;
    cpc     abs1,tmp2&lt;br /&gt;
    cpc     abs2,tmp3&lt;br /&gt;
    brge    device_loop_big     ; &amp;gt;= EEPROM_size&lt;br /&gt;
&lt;br /&gt;
    ; less than EEPROM_size, copy remaining bytes&lt;br /&gt;
    mov     cnt0,abs0       ; remaining bytes&lt;br /&gt;
    mov     cnt1,abs1&lt;br /&gt;
    mov     cnt2,abs2&lt;br /&gt;
    mov     abs0,zero       ; set zero&lt;br /&gt;
    mov     abs1,zero&lt;br /&gt;
    mov     abs2,zero&lt;br /&gt;
    rjmp    device_loop_init&lt;br /&gt;
&lt;br /&gt;
device_loop_big:&lt;br /&gt;
    mov     cnt0,tmp1       ; EEPROM_size loop&lt;br /&gt;
    mov     cnt1,tmp2&lt;br /&gt;
    mov     cnt2,tmp3&lt;br /&gt;
    sub     abs0,tmp1       ; - EEPROM_size&lt;br /&gt;
    sbc     abs1,tmp2&lt;br /&gt;
    sbc     abs2,tmp3&lt;br /&gt;
&lt;br /&gt;
device_loop_init:&lt;br /&gt;
    subi    cnt0,1          ; -1, since last byte must be read with no ACK&lt;br /&gt;
    sbci    cnt1,0          ; outside the loop&lt;br /&gt;
    sbci    cnt2,0&lt;br /&gt;
&lt;br /&gt;
; write first adress&lt;br /&gt;
&lt;br /&gt;
    rcall   i2c_start&lt;br /&gt;
    mov     tmp1, i2c       ; load i2c address&lt;br /&gt;
    rcall   i2c_write&lt;br /&gt;
    i2c_error_check&lt;br /&gt;
    ldi     tmp1, 0         ; write adress 0&lt;br /&gt;
    rcall   i2c_write&lt;br /&gt;
    i2c_error_check&lt;br /&gt;
    ldi     tmp1, 0&lt;br /&gt;
    rcall   i2c_write&lt;br /&gt;
    i2c_error_check&lt;br /&gt;
    rcall   i2c_stop&lt;br /&gt;
&lt;br /&gt;
    rcall   i2c_start&lt;br /&gt;
    mov     tmp1, i2c       ; load i2c address&lt;br /&gt;
    subi    tmp1,-1         ; +1, read access&lt;br /&gt;
    rcall   i2c_write&lt;br /&gt;
    i2c_error_check&lt;br /&gt;
    set                     ; set T-Flag, continous reading&lt;br /&gt;
&lt;br /&gt;
main_loop:&lt;br /&gt;
&lt;br /&gt;
.if bitreverse==1           &lt;br /&gt;
;   configuration uses online bit reverse, slow&lt;br /&gt;
&lt;br /&gt;
    rcall   i2c_read&lt;br /&gt;
    rcall   fpga_write&lt;br /&gt;
&lt;br /&gt;
.else&lt;br /&gt;
;   configuration uses offline bit reverse, fast (bitdreher.exe)&lt;br /&gt;
&lt;br /&gt;
; read a byte from I2C and parallel send it to the FPGA&lt;br /&gt;
; fast version&lt;br /&gt;
    ldi     tmp2, 8         ; loop counter&lt;br /&gt;
&lt;br /&gt;
main_bit_loop:&lt;br /&gt;
    scl_high                ; SCL rising edge&lt;br /&gt;
    sbic    cfg_pin,sda     ; copy SDA to Din&lt;br /&gt;
    din_high&lt;br /&gt;
    sbis    cfg_pin,sda&lt;br /&gt;
    din_low&lt;br /&gt;
    delay 7, 6              ; minimum LOW time 0,6µs + 0.1µs safty margin&lt;br /&gt;
    scl_low                 ; falling edge generates new bit&lt;br /&gt;
    cclk_high               ; LOW time min. 9 CLKs&lt;br /&gt;
    cclk_low&lt;br /&gt;
    delay 14, 9             ; minimum HIGH time 1,3µs + 0.1µs safty margin&lt;br /&gt;
    dec     tmp2&lt;br /&gt;
    brne    main_bit_loop&lt;br /&gt;
&lt;br /&gt;
; write ACK to EEPROM&lt;br /&gt;
&lt;br /&gt;
    sda_low                 ; write ACK, more to read&lt;br /&gt;
    delay  1, 0&lt;br /&gt;
    scl_high&lt;br /&gt;
    delay  7, 2&lt;br /&gt;
    scl_low&lt;br /&gt;
    sda_high&lt;br /&gt;
    delay  14, 10&lt;br /&gt;
&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
    subi    cnt0,1          ; decrement data counter&lt;br /&gt;
    sbci    cnt1,0&lt;br /&gt;
    sbci    cnt2,0&lt;br /&gt;
    brne    main_loop&lt;br /&gt;
&lt;br /&gt;
    clt                     ; no ACK for last byte of block&lt;br /&gt;
    rcall   i2c_read&lt;br /&gt;
    rcall   fpga_write&lt;br /&gt;
&lt;br /&gt;
    rcall   i2c_stop&lt;br /&gt;
    subi    i2c,-2          ; +2, increment I2C address bits&lt;br /&gt;
&lt;br /&gt;
; number of remaining data bytes = 0 ?&lt;br /&gt;
&lt;br /&gt;
    cp      abs0,zero&lt;br /&gt;
    cpc     abs1,zero&lt;br /&gt;
    cpc     abs2,zero&lt;br /&gt;
    breq    main_end        ; nothing left to copy, finish&lt;br /&gt;
&lt;br /&gt;
    rjmp    device_loop     ; process next data block&lt;br /&gt;
&lt;br /&gt;
main_end:&lt;br /&gt;
    ldi     tmp1,0&lt;br /&gt;
    rcall   fpga_write      ; one more dummy byte for FPGA startup&lt;br /&gt;
&lt;br /&gt;
    ldi     tmp1,1&lt;br /&gt;
    rcall   wait            ; wait for DONE to go HIGH (open drain)&lt;br /&gt;
    sbis    cfg_pin, done   ; check if DONE is HIGH (= FPGA config OK)&lt;br /&gt;
    rjmp    error_fpga      ; something went wrong during configuration&lt;br /&gt;
    ldi     tmp1, (1&amp;lt;&amp;lt;SE) | (1&amp;lt;&amp;lt;SM)     &lt;br /&gt;
    out     mcucr,tmp1      ; power down sleep mode&lt;br /&gt;
    sleep                   ; good night&lt;br /&gt;
    &lt;br /&gt;
;  no wake up here, only through reset&lt;br /&gt;
&lt;br /&gt;
; i2c has no ACK, fast blinking&lt;br /&gt;
&lt;br /&gt;
error_i2c:&lt;br /&gt;
    sda_low&lt;br /&gt;
    ldi     tmp1,100&lt;br /&gt;
    rcall   wait&lt;br /&gt;
    sda_high&lt;br /&gt;
    ldi     tmp1,100&lt;br /&gt;
    rcall   wait&lt;br /&gt;
    rjmp    error_i2c&lt;br /&gt;
&lt;br /&gt;
; FPGA configuration error, DONE stays low, slow blinking&lt;br /&gt;
&lt;br /&gt;
error_fpga:&lt;br /&gt;
    sda_low&lt;br /&gt;
    ldi     tmp1,250&lt;br /&gt;
    rcall   wait&lt;br /&gt;
    ldi     tmp1,250&lt;br /&gt;
    rcall   wait&lt;br /&gt;
    sda_high&lt;br /&gt;
    ldi     tmp1,250&lt;br /&gt;
    rcall   wait&lt;br /&gt;
    ldi     tmp1,250&lt;br /&gt;
    rcall   wait&lt;br /&gt;
    rjmp    error_fpga&lt;br /&gt;
&lt;br /&gt;
; *****************************************************************************&lt;br /&gt;
&lt;br /&gt;
; functions&lt;br /&gt;
&lt;br /&gt;
; *****************************************************************************&lt;br /&gt;
&lt;br /&gt;
; just wait N*1ms, N is given in tmp1&lt;br /&gt;
&lt;br /&gt;
wait:&lt;br /&gt;
    ldi     tmp2,20*F_CPU_MHz&lt;br /&gt;
wait_1:&lt;br /&gt;
    ldi     tmp3,16&lt;br /&gt;
wait_2:&lt;br /&gt;
    dec     tmp3&lt;br /&gt;
    brne    wait_2&lt;br /&gt;
    dec     tmp2&lt;br /&gt;
    brne    wait_1&lt;br /&gt;
    dec     tmp1&lt;br /&gt;
    brne    wait&lt;br /&gt;
    ret&lt;br /&gt;
&lt;br /&gt;
; *****************************************************************************&lt;br /&gt;
&lt;br /&gt;
; write a byte to I2C&lt;br /&gt;
; input  : tmp1   : data&lt;br /&gt;
; output : T-flag : ACK (0= NACK (SDA high), 1 = ACK (SDA low))&lt;br /&gt;
 &lt;br /&gt;
i2c_write:&lt;br /&gt;
    ldi     tmp2, 8     ; loop conter&lt;br /&gt;
i2c_write_loop:&lt;br /&gt;
&lt;br /&gt;
    sbrs    tmp1,7      ; copy MSB to SDA&lt;br /&gt;
    sda_low&lt;br /&gt;
    sbrc    tmp1,7&lt;br /&gt;
    sda_high&lt;br /&gt;
&lt;br /&gt;
    delay 14, 8 &lt;br /&gt;
    scl_high&lt;br /&gt;
    delay 7, 2&lt;br /&gt;
    scl_low&lt;br /&gt;
    lsl     tmp1        ; get next bit&lt;br /&gt;
    dec     tmp2&lt;br /&gt;
    brne    i2c_write_loop&lt;br /&gt;
&lt;br /&gt;
; check ACK from EEPROM&lt;br /&gt;
    sda_high&lt;br /&gt;
    delay 14, 5&lt;br /&gt;
    scl_high&lt;br /&gt;
    clt                     ; clear T-Flag, = no ACK!&lt;br /&gt;
    sbis    cfg_pin,sda     ; check SDA is ACK=0 (positive ACK)&lt;br /&gt;
    set                     ; ACK=0, OK&lt;br /&gt;
    delay 7, 5&lt;br /&gt;
    scl_low&lt;br /&gt;
    delay 14, 7     &lt;br /&gt;
    ret&lt;br /&gt;
&lt;br /&gt;
; *****************************************************************************&lt;br /&gt;
&lt;br /&gt;
; read a byte from I2C&lt;br /&gt;
; input  : T-flag : ACK, (0= NACK (SDA high), 1 = ACK (SDA low))&lt;br /&gt;
; output : tmp1   : data&lt;br /&gt;
i2c_read:&lt;br /&gt;
    ldi     tmp2, 8         ; loop conter&lt;br /&gt;
i2c_read_loop:&lt;br /&gt;
    scl_high&lt;br /&gt;
    clc                     ; copy SDA to carry&lt;br /&gt;
    sbic    cfg_pin, sda    ; read SDA&lt;br /&gt;
    sec                     ; set carry&lt;br /&gt;
    rol     tmp1            ; shift in next bit&lt;br /&gt;
    delay 7, 6&lt;br /&gt;
    scl_low                 ; minimum pulse width LOW = 1.3µs = 13 clks @10 MHz&lt;br /&gt;
    delay 14, 5&lt;br /&gt;
    dec     tmp2&lt;br /&gt;
    brne    i2c_read_loop&lt;br /&gt;
&lt;br /&gt;
; write ACK to EEPROM&lt;br /&gt;
&lt;br /&gt;
    brtc    i2c_read_no_ack&lt;br /&gt;
    sda_low                 ; write ACK, more to read&lt;br /&gt;
    rjmp    i2c_read_send_ack&lt;br /&gt;
i2c_read_no_ack:&lt;br /&gt;
    sda_high                ; no ACK, stop reading&lt;br /&gt;
i2c_read_send_ack:&lt;br /&gt;
    delay 14, 6&lt;br /&gt;
    scl_high&lt;br /&gt;
    delay 7, 2&lt;br /&gt;
    scl_low&lt;br /&gt;
    sda_high                ; release SDA&lt;br /&gt;
    ret&lt;br /&gt;
&lt;br /&gt;
; *****************************************************************************&lt;br /&gt;
&lt;br /&gt;
; Create a I2C START Condition&lt;br /&gt;
  &lt;br /&gt;
i2c_start:&lt;br /&gt;
    delay 5, 2&lt;br /&gt;
    sda_low&lt;br /&gt;
    delay 5, 2&lt;br /&gt;
    scl_low&lt;br /&gt;
    delay 30, 7&lt;br /&gt;
    ret&lt;br /&gt;
&lt;br /&gt;
; *****************************************************************************&lt;br /&gt;
&lt;br /&gt;
; Create a I2C STOP Condition&lt;br /&gt;
&lt;br /&gt;
i2c_stop:&lt;br /&gt;
    delay 5, 2&lt;br /&gt;
    sda_low&lt;br /&gt;
    delay 5,2 &lt;br /&gt;
    scl_high&lt;br /&gt;
    delay 5,2&lt;br /&gt;
    sda_high&lt;br /&gt;
    delay 30, 7&lt;br /&gt;
    ret&lt;br /&gt;
&lt;br /&gt;
; *****************************************************************************&lt;br /&gt;
&lt;br /&gt;
; write a byte to FPGA, with bit reversal&lt;br /&gt;
; input  : tmp1   : data&lt;br /&gt;
&lt;br /&gt;
.if bitreverse==1       &lt;br /&gt;
.message &amp;quot;Bit reverse ON, slow configuration.&amp;quot;  &lt;br /&gt;
; configuration uses online bit reverse, slow&lt;br /&gt;
; bit reverse, LSB first&lt;br /&gt;
fpga_write:&lt;br /&gt;
    ldi     tmp2, 8     ; loop conter&lt;br /&gt;
fpga_write_loop:&lt;br /&gt;
&lt;br /&gt;
    sbrs    tmp1,0      ; copy LSB to DIN&lt;br /&gt;
    din_low&lt;br /&gt;
    sbrc    tmp1,0&lt;br /&gt;
    din_high&lt;br /&gt;
&lt;br /&gt;
    cclk_high           ; generate cclk pulse&lt;br /&gt;
    cclk_low&lt;br /&gt;
    lsr     tmp1        ; get next bit&lt;br /&gt;
    dec     tmp2&lt;br /&gt;
    brne    fpga_write_loop&lt;br /&gt;
    ret&lt;br /&gt;
&lt;br /&gt;
; *****************************************************************************&lt;br /&gt;
.else&lt;br /&gt;
.message &amp;quot;Bit reverse OFF, fast configuration.&amp;quot; &lt;br /&gt;
; configuration uses offline bit reverse, fast (bitdreher.exe)&lt;br /&gt;
; no bit reverse, MSB first&lt;br /&gt;
fpga_write:&lt;br /&gt;
    ldi     tmp2, 8     ; loop conter&lt;br /&gt;
fpga_write_loop:&lt;br /&gt;
&lt;br /&gt;
    sbrs    tmp1,7      ; copy MSB to DIN&lt;br /&gt;
    din_low&lt;br /&gt;
    sbrc    tmp1,7&lt;br /&gt;
    din_high&lt;br /&gt;
&lt;br /&gt;
    cclk_high           ; generate cclk pulse&lt;br /&gt;
    cclk_low&lt;br /&gt;
    lsl     tmp1        ; get next bit&lt;br /&gt;
    dec     tmp2&lt;br /&gt;
    brne    fpga_write_loop&lt;br /&gt;
    ret&lt;br /&gt;
&lt;br /&gt;
; *****************************************************************************&lt;br /&gt;
.endif&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Fehlererkennung ==&lt;br /&gt;
&lt;br /&gt;
Seitens des FPGAs ist Done ein [[Ausgangsstufen Logik-ICs#Open Collector | Open Drain]] Ausgang. Im AVR wird der interne Pull-Up eingeschaltet, um das Signal auf HIGH ziehen zu können. Ist jedoch ein Fehler aufgetreten (CRC-Fehler im Datenstrom), bleibt Done auf LOW. Der AVR prüft Done am Ende der Konfiguration. Ist Done gleich HIGH, geht er in den Power Down [[Sleep Mode]] um Strom zu sparen. Ist aber ein Fehler aufgetreten und Done somit LOW, wird das durch langsames Blinken der LED an SDA angezeigt (~1 Hz). Tritt während der Adressierung des EEPROMs ein Fehler auf (kein ACK vom EEPROM), dann wird dies durch schnelles Blinken der LED angezeigt (~5 Hz). Im Normalfall treten diese Ereignisse nur sehr selten auf, z.&amp;amp;nbsp;B. bei einem EEPROM-Defekt durch Alterung/Datenverlust oder einer Störung der Datenübertragung durch starke Störimpulse. Aber zur Programmierung und zum Testen sind sie sehr nützlich.&lt;br /&gt;
&lt;br /&gt;
== Nutzung ==&lt;br /&gt;
&lt;br /&gt;
Die Nutzung der Schaltung ist recht einfach. Im Quellcode müssen nur drei Variablen an das jeweilige Projekt angepasst werden. Soll ein anderer AVR-Typ verwendet werden können auch die Pins einfach zugewiesen werden. Danach wird das Programm assembliert und per [[ISP]] in den AVR geschrieben. Abschliessend sollten die Fuses gesetzt werden. Der Takt des interen RC-Oszillators sollte möglichst hoch gewählt werden, bis ca. 10 MHz ist das Progamm ohne Änderungen nutzbar. Wenn verfügbar sollte der Brown Out Detector eingeschaltet werden und mit ca. 2,7V Schwellspannung betrieben werden. Für den hier verwendeten Tiny12 muss das Fuse-Byte mit 0x12 beschrieben werden. &#039;&#039;&#039;HALT!&#039;&#039;&#039; Wenn jetzt der Reset gelöst wird läuft der AVR sofort los und versucht die Daten aus den EEPROMs zu lesen. Da diese aber noch nicht programmiert sind werden keine sinnvollen Daten ins FPGA geladen. Das schadet dem FPGA zwar nicht, aber die Konfiguration scheitert! In der Folge wird SDA vom AVR kontinuierlich zwischen LOW und HIGH umgeschaltet, um den Fehler durch Blinken der LED zu signalisieren. Damit ist aber keine Programmierung der EEPROMs mehr möglich!&lt;br /&gt;
&lt;br /&gt;
Mögliche Auswege:&lt;br /&gt;
&lt;br /&gt;
* RESET auf LOW halten&lt;br /&gt;
* die EEPROMs &#039;&#039;&#039;vor&#039;&#039;&#039; dem AVR programmieren&lt;br /&gt;
&lt;br /&gt;
Im Normalfall wird man den zweiten Weg wählen. Denn während der Entwicklung wird man meist das FPGA über [[JTAG]] konfigurieren. Erst wenn alles komplett funktioniert wird man die Konfiguration einmalig in den EEPROM schreiben.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis!&#039;&#039;&#039; Wird während der Entwicklungsphase das FPGA über JTAG programmiert, muss in den Optionen für &amp;quot;Generate Programming File&amp;quot; unter Startup Options -&amp;gt; FPGA Start-up Clock  &amp;quot;JTAG&amp;quot; gewählt werden. &lt;br /&gt;
&lt;br /&gt;
Die Programmierung der EEPROMs erfolgt mit [http://www.lancos.com Ponyprog]. Mittels einfachem Adapter kann man direkt auf den I2C-Bus gehen, es werden nur SDA, SCL und GND benötigt, die Pull-Ups sind schon auf dem Board. Das Board muss dazu natürlich mit Spannung versorgt werden.&lt;br /&gt;
&lt;br /&gt;
[[bild:i2c_adapter.png| framed | left | I2C Adapter für Ponyprog]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Ablauf der EEPROM-Programmierung sieht wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
* In den Optionen für &amp;quot;Generate Programming File&amp;quot; muss unter Startup Options -&amp;gt; FPGA Start-up Clock &amp;quot;CCLK&amp;quot; gewählt werden. &lt;br /&gt;
* Im Xilinx ISE den kompletten Synthesezyklus inclusive &amp;quot;Generate Programming File&amp;quot; durchlaufen.&lt;br /&gt;
* IMPACT starten und eine PROM-Datei im BIN Format erzeugen.&lt;br /&gt;
* Jetzt hat man die Wahl zwischen zwei Möglichkeiten.&lt;br /&gt;
** Die Daten direkt in den EEPROM schreiben. Dann müssen sie beim Lesen und anschliessender Ausgabe zum FPGA in der Reihenfolge der Bits vertauscht werden, das kostet natürlich Zeit&lt;br /&gt;
** Die Daten mit einem kleinen Tool [[media:Bitdreher.zip | Bitdreher]] umwandeln. Dabei wird die Bitverdrehung vorher durchgeführt. Die Daten können damit ohne zusätzliche Verdrehung schnell ins FPGA geschrieben werden.&lt;br /&gt;
* Ponyprog starten, EEPROM Familie &amp;quot;IC Bus 16bit eeprom&amp;quot; auswählen, den jeweiligen Typ auch auswählen (25C128, 24C256, 24C512).&lt;br /&gt;
* Die Bin-Datei laden und &amp;quot;Write Device&amp;quot; ausführen.&lt;br /&gt;
* Das erfolgreiche Programmieren und Verifizieren wird von Ponyprog angezeigt.&lt;br /&gt;
 &lt;br /&gt;
Wenn die FPGA-Konfiguration grösser als ein EEPROM ist, muss die Datei in mehrere Stücke aufgeteilt werden. Das kann man mit IMPACT machen oder &#039;&#039;&#039;promgen&#039;&#039;&#039; direkt von der Kommandozeile aufrufen. Die Option &#039;&#039;-s &amp;lt;size&amp;gt;&#039;&#039; erlaubt das Aufteilen der Konfigurationsdaten in kleinere Dateien. Beachtet werden muss dabei, dass die einzelnen Blöcke exakt so gross sein müssen wie ein einzelner EEPROM. Ausser natürlich der letzte Block, dessen Länge ergibt sich aus (Dateigrösse MODULO EEPROM-Grösse). Die einzelnen Dateien können dann einfach per Ponyprog in die EEPROMs geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Achtung!&#039;&#039;&#039;&lt;br /&gt;
*Dabei muss man aufpassen, dass die Reihenfolge nicht verwechselt wird! Der erste Block muss in den EEPROM mit Adresse 0, der zweite in den mit Adresse 1 usw.&lt;br /&gt;
* Wenn man mit Ponyprog mehrere EEPROMs an einem Bus programmieren will, muss die Adresse der EEPROMs manuell in der Datei &#039;&#039;PONYPROG2000.INI&#039;&#039; in der Zeile&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
        I2CBaseAddress=0xA0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
: eingetragen werden (0xA0, 0xA2, 0xA4, 0xA6, 0xA8, 0xAA, 0xAC, 0xAE). Nach jeder Änderung muss Ponyprog neu gestartet werden.&lt;br /&gt;
&lt;br /&gt;
== Leistung ==&lt;br /&gt;
&lt;br /&gt;
Auf einem Tiny12 mit voll aufgedrehtem RC-Oszillator (ca. 2 MHz) und einer Online Bitverdrehung (bitreversal=1) erreicht man eine Geschwindigkeit von ca. 8,5kB/s, d.h. der im Test verwendete FPGA vom Typ XC2S30 mit 42096 Bytes Konfigurationsspeicher wird in ca. 5s konfiguriert. Nicht gerade berauschend, aber ausreichend. Der Grund dafür liegt nicht nur in der begrenzten Geschwindigkeit des I2C Busses (400kHz), sondern in einer Merkwürdigkeit der Konfigurationssoftware von Xilinx. Diese verdreht nämlich die Bits innerhalb der Bytes aus fadenscheinigen Gründen (Bit 0&amp;lt;-&amp;gt;7, Bit 1&amp;lt;-&amp;gt;6, etc.). Damit muss aber immer zunächst ein Byte vollständig gelesen werden (MSB zuerst) und dananch in umgekehrter Reihenfolge ausgegeben werden (LSB zuerst). Das kostet einiges an Zeit. Damit werden bei 2 MHz nur etwa 15% der maximalen Geschwindigkeit erreicht, dementsprechend sind die Konfigurationszeiten etwa sechs mal so lang wie in der Tabelle oben angegeben. Mit dem Parameter bitreversal=0 und der Bearbeitung der Konfigurationsdaten mit dem Tool [[media:Bitdreher.zip | Bitdreher]] erreicht man eine Konfigurationszeit von ca 3s, 40% schneller! Die erreichbaren Konfigurationszeiten sind in nachfolgender Tabelle exemplarisch angegeben, mit dem in Klammern angegebenen Faktor kann man direkt in die zweite Tabelle gehen und die reale Konfigurationszeit ausrechnen. Bei höherem Prozessortakt werden längere Pausen eingefügt, sodass die minimalen Pulszeiten für 400kHz auf dem I2C-Bus eingehalten werden. Dies wird mit dem schönen, leistungsfähigen Makro &#039;&#039;delay&#039;&#039; erreicht.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
! rowspan=&amp;quot;2&amp;quot; | Takt [MHz]  &lt;br /&gt;
! colspan=&amp;quot;2&amp;quot; | Konfigurationszeit [s] (Faktor)&lt;br /&gt;
|-&lt;br /&gt;
! bitreversal=0 || bitreversal=1   &lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2  &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3,0 (3,8)&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4,8 (6)&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 5  &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1,2 (1,5)&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2,1 (2,6)&lt;br /&gt;
|-&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 10 &lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 0,9 (1,1)&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1,4 (1,8)&lt;br /&gt;
|} &lt;br /&gt;
&lt;br /&gt;
== Zukunftsaussichten ==&lt;br /&gt;
&lt;br /&gt;
Für grössere FPGAs werden die seriellen EEPROMs irgendwann zu klein und zu langsam. Hier müssen andere Datenträger her. SD-Karten sind klein, billig und weit verbreitet. Auch wenn der Aufwand zu deren Ansteuerung plus Minimalfunktionalität für FAT12/FAT16 um einiges höher liegt, ist dies ein interessanter Ansatzpunkt, der in Zukunft einmal umgesetzt werden kann.&lt;br /&gt;
&lt;br /&gt;
Als Zwischenlösung bieten sich Flashbausteine mit [[SPI]] im SO-8 Gehäuse an, die  gibt es bis zu unglaublichen 32 Mbit zum Spottpreis, z.b. bei [[Elektronikversender#csd-electronics | CSD]]. Allerdings muss dann ein AVR mit zwei zusätzlichen Pins her, hier muss man dann auf ein 20 poliges Gehäuse wechseln. Enthusiasten nehmen das platzsparende MLF20 ;-).&lt;br /&gt;
&lt;br /&gt;
Alternativ könnte geprüft werden, ob der Dataflash eines [[AVR_Butterfly]] ausreicht. Siehe: [[FPGA_Konfiguration_mit_AVR_Butterfly]]&lt;br /&gt;
&lt;br /&gt;
== Diskussion im Forum ==&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/79844 Programm auf Spartan 3A laden]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/83026 FPGA synthetisierung]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/80275 Einsteigerfreundlicher FPGA]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/78362 Spartan 3E mit SPI-Flash]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/75954 Spartan 3e: Anfägerhilfe bei Flashspeicherung]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/39941 Programmier-Hardware Altera Cyclone-II /EPCS4]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/39947 FPGA und CPLD programmieren]&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.xilinx.com FPGAs von Xilinx]&lt;br /&gt;
* [http://www.lancos.com PonyProg]&lt;br /&gt;
* [http://www.atmel.com/products/serial/default.asp Serielle EEPROMs bei Atmel]&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc3301.pdf Configuring High-density FPGAs using Atmel’s Serial DataFlash® and an AVR® Microcontroller (2003)]&lt;br /&gt;
* [http://www.xilinx.com/publications/xcellonline/xcell_55/xc_pdf/xc_spi55.pdf XC-SPI55 Program SPI Serial Flash from Xilinx FPGAs and CPLDs (2005)]&lt;br /&gt;
* [http://www.xilinx.com/support/documentation/application_notes/xapp445.pdf XAPP445 Configuring Spartan-3E FPGAs with SPI Flash Memories (2007)]&lt;br /&gt;
* [http://www.xilinx.com/support/documentation/application_notes/xapp693.pdf XAPP693 CPLD-Based Configuration...for Xilinx Platform Flash PROMs and FPGAs (2005)]&lt;br /&gt;
* [http://www.xilinx.com/support/documentation/application_notes/xapp176.pdf XAPP176 Configuration and Readback of the Spartan-II and Spartan-IIE Families (2002)]&lt;br /&gt;
* [http://www.xilinx.com/support/documentation/application_notes/xapp098.pdf XAPP098 The Low-Cost, Efficient Serial Configuration of Spartan FPGAs (1998)]&lt;br /&gt;
&lt;br /&gt;
[[Category:FPGA-Projekte]]&lt;/div&gt;</summary>
		<author><name>80.64.189.58</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=ESP8266&amp;diff=87079</id>
		<title>ESP8266</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=ESP8266&amp;diff=87079"/>
		<updated>2015-02-04T09:22:25Z</updated>

		<summary type="html">&lt;p&gt;80.64.189.58: Orthografie&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Datei:ESP8266.jpg|thumb|300px|ESP8266, Funkmodul]]&lt;br /&gt;
Das [[ESP8266]] von dem Hersteller Espressif ist ein programmierbarer WLAN-SoC mit [[UART]]- und [[SPI]]-Schnittstelle. &#039;&#039;&#039;WLAN&#039;&#039;&#039;-Funkmodule mit ESP8266 sind ab 3€ verfügbar. Die UART-Schnitttstelle ermöglicht eine einfache Integration in Mikrocontrollerprojekte.&lt;br /&gt;
&lt;br /&gt;
== Spezifikation ==&lt;br /&gt;
Laut Hersteller &amp;lt;ref&amp;gt;[http://espressif.com/en/products/esp8266 &#039;&#039;Herstellerseite -  unter Details&#039;&#039;] Abgerufen am 26. August 2014.&amp;lt;/ref&amp;gt;. :&lt;br /&gt;
* 802.11 b/g/n&lt;br /&gt;
* Wi-Fi Direct (P2P), soft-AP&lt;br /&gt;
* Integrated TCP/IP protocol stack&lt;br /&gt;
* Integrated TR switch, balun, LNA, power amplifier and matching network&lt;br /&gt;
* Integrated PLLs, regulators, DCXO and power management units&lt;br /&gt;
* +19.5dBm output power in 802.11b mode&lt;br /&gt;
* Power down leakage current of &amp;lt;10uA&lt;br /&gt;
* Integrated low power 32-bit CPU could be used as application processor&lt;br /&gt;
* SDIO 1.1/2.0, SPI, UART&lt;br /&gt;
* STBC, 1×1 MIMO, 2×1 MIMO&lt;br /&gt;
* A-MPDU &amp;amp; A-MSDU aggregation &amp;amp; 0.4ms guard interval&lt;br /&gt;
* Wake up and transmit packets in &amp;lt; 2ms&lt;br /&gt;
* Standby power consumption of &amp;lt; 1.0mW (DTIM3)&lt;br /&gt;
* VCC: 3,3V (Achtung: Eingänge sind &#039;&#039;&#039;NICHT 5V TOLERANT&#039;&#039;&#039;!)&lt;br /&gt;
Weiterhin:&lt;br /&gt;
* GPIOs, ADC&lt;br /&gt;
&lt;br /&gt;
=== Datendurchsatz/Performanz ===&lt;br /&gt;
[https://www.mikrocontroller.net/topic/342240?page=single#3857630 Beitrag im Forum mit Tests: TCP: bis zu 7 MBit/s]&amp;lt;br/&amp;gt;&lt;br /&gt;
[http://bbs.espressif.com/viewtopic.php?f=7&amp;amp;t=24 Beitrag Espressif-Form: UART loopback: 4.5 Mbps]&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Bei den chinesischen Modulen mit Firmware 0.9.1 werden Ping Befehle unabhängig von der Paketgröße typischerweise in 30-150ms beantwortet. Datenpakete, die man vom PC aus an das Modul sendet werden unabhängig von der Paketgröße typischerweise nach 100-200ms quittiert.&lt;br /&gt;
&lt;br /&gt;
== WLAN-Module mit ESP8266 ==&lt;br /&gt;
Es existieren ca. 11 Varianten von chinesischen Herstellern. Beispielsweise mit PCB- oder Keramik-Antenne oder mit u.fl.&lt;br /&gt;
&amp;lt;br&amp;gt;&lt;br /&gt;
Die Firmware 0.9.1 unterstützt bis zu vier gleichzeitige TCP oder UDP Verbindungen. Sie kann sich in vorhandene WLAN Netze einbuchen, aber auch selbst Access-Point mit DHCP Server sein. Der Access-Point ist zu Android kompatibel (mit 4.1.2 getestet).&lt;br /&gt;
&amp;lt;br/&amp;gt;&lt;br /&gt;
Die Firmware enthält jedoch keinen Router. Mehrere Computer, die mit dem Modul als Access-Point verbunden sind, können keine Verbindung zueinander aufbauen.&lt;br /&gt;
Das Feature nennt sich AP Isolation.&lt;br /&gt;
&amp;lt;br /&amp;gt;&lt;br /&gt;
#Produktbeschreibung: [[http://playground.boxtec.ch/doku.php/wireless/esp8266]]&lt;br /&gt;
&lt;br /&gt;
=== Pinbelegung einiger ESP8266-Module ===&lt;br /&gt;
&amp;lt;gallery&amp;gt;&lt;br /&gt;
Datei:ESP8266-PinBelegung1.jpg|Pinbelegung - Groß mit PCB-Antenne&lt;br /&gt;
Datei:ESP8266-PinBelegung2.jpg|Pinbelegung - Klein mit Keramik-Antenne&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
Quelle &amp;lt;ref&amp;gt;[http://pan.baidu.com/share/link?shareid=727869034&amp;amp;uk=1900861665 &#039;&#039;Seller Information&#039;&#039;] Abgerufen am 26. August 2014.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== AT-Befehle für eine Firmware auf Basis des SDK-Beispiels &amp;quot;AT&amp;quot;==&lt;br /&gt;
&lt;br /&gt;
Einstellen des Moduls als AP&lt;br /&gt;
&lt;br /&gt;
Da wir nicht wissen, in welchem Modus sich das Modul gerade befindet, fragen wir diesen ab mit dem &lt;br /&gt;
Befehl AT+CWMODE?  Das Modul antwortet mit &lt;br /&gt;
&lt;br /&gt;
    AT+CWMODE?&amp;lt;\r&amp;gt;&amp;lt;\r&amp;gt;&amp;lt;\n&amp;gt;+CWMODE:1&amp;lt;\r&amp;gt;&amp;lt;\n&amp;gt;&lt;br /&gt;
    &amp;lt;\r&amp;gt;&amp;lt;\n&amp;gt;&lt;br /&gt;
    OK&amp;lt;\r&amp;gt;&amp;lt;\n&amp;gt;&lt;br /&gt;
In diesem Fall ist das Modul aktuell im Modus 1 ( Station) eingestellt. Also ändern wir den Modus auf 2 ( AP)&lt;br /&gt;
mit dem Befehl AT+CWMODE=2. Nach diesem Befehl ist ein Reset des Moduls erforderlich, damit die Änderung &lt;br /&gt;
sichtbar wird. Mit dem Befehl AT+RST führen wir diesen durch. Das Modul startet neu und die Stromaufnahme&lt;br /&gt;
steigt auf ca 80 mA. Das Modul ist jetzt als WLAN AP im Wireless Lan sichtbar. &lt;br /&gt;
&lt;br /&gt;
Jetzt müssen wir noch einstellen, dass wir mehrere Verbindungen gleichzeitig haben wollen und den TCP Server starten und einstellen. Mit dem Befehl AT+CIPMUX=1 sagen wir dem Modul, dass wir mehrere Verbindungen haben wollen. Und mit dem Befehl AT+CIPSERVER=1,2526 starten wir den TCP Server und lassen ihn auf Port 2526 laufen. Sobald sich ein Client verbindet, sendet das Modul &#039;Link&#039; + LF + CR. Beim Trennen einer Verbindung vom Client kommt &#039;Unlink&#039; + LF + CR.&lt;br /&gt;
&lt;br /&gt;
Ab hier können wir uns über einen TCP Socket auf Port 2526 mit dem Modul verbinden und Daten austauschen. Empfangene Daten werden folgendermaßen angezeigt. Gesendet wurde  &amp;quot;Hallo Leute&amp;quot; + LF + CR.&lt;br /&gt;
&lt;br /&gt;
     &amp;lt;\r&amp;gt;&amp;lt;\n&amp;gt;&lt;br /&gt;
     +IPD,0,11:Hallo Leute&amp;lt;\r&amp;gt;&amp;lt;\n&amp;gt;&lt;br /&gt;
     OK&amp;lt;\r&amp;gt;&amp;lt;\n&amp;gt;&lt;br /&gt;
&lt;br /&gt;
+IPD kommt immer, 0 ist die erste Verbindung. Wenn 2 Geräte gleichzeitig eine Verbindung aufgebaut haben, steht dort eine 1. 11 Zeichen wurden empfangen, dann kommen die Daten.&lt;br /&gt;
&lt;br /&gt;
Zum Senden von Daten vom Modul zum Client geht man folgenderweise vor. Erstmal sagen wir dem Modul, wieviele Daten wir an welche Verbindung schicken wollen. Mit dem Befehl AT+CIPSEND=0,5 z. B. sagen wir dem Modul wir möchten 5 Bytes an Verbindung 0 senden. Nach diesem Befehl werden die nächsten 5 Zeichen direkt an die Verbindung weitergereicht.&lt;br /&gt;
Sollte keine aktive Verbindung bestehen, sendet das Modul &lt;br /&gt;
     AT+CIPSEND=0,5&amp;lt;\r&amp;gt;&amp;lt;\r&amp;gt;&amp;lt;\n&amp;gt;link is not&amp;lt;\r&amp;gt;&amp;lt;\n&amp;gt;&lt;br /&gt;
ansonsten kommt &lt;br /&gt;
     &amp;lt;\r&amp;gt;&amp;lt;\n&amp;gt; &amp;gt;&lt;br /&gt;
und man kann Daten senden. Nach dem absenden der Daten &#039;Leute&#039; + LF + CR sendet das Modul &lt;br /&gt;
    Leute&amp;lt;\r&amp;gt;&amp;lt;\r&amp;gt;&amp;lt;\n&amp;gt;busy&amp;lt;\r&amp;gt;&amp;lt;\n&amp;gt;&lt;br /&gt;
    &amp;lt;\r&amp;gt;&amp;lt;\n&amp;gt;&lt;br /&gt;
    busy&amp;lt;\r&amp;gt;&amp;lt;\n&amp;gt;&lt;br /&gt;
    &amp;lt;\r&amp;gt;&amp;lt;\n&amp;gt;&lt;br /&gt;
    SEND OK&amp;lt;\r&amp;gt;&amp;lt;\n&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Einstellen des Moduls als Station&lt;br /&gt;
&lt;br /&gt;
== Software Development Kit (SDK) ==&lt;br /&gt;
Mit dem SDK können eigene Applikationen programmiert und die im SDK vorhandenen Beispiele &amp;quot;AT&amp;quot; und &amp;quot;IoT&amp;quot; verändert werden. Das SDK wird vom Hersteller zur Verfügung gestellt (Stand 25.10.2014). Passend zum SDK existiert eine virtuelle Maschine mit eingerichtetem gcc zum Kompilieren. Insbesondere der nun verfügbare gcc basiert auf einer Community-Entwicklung.&lt;br /&gt;
&lt;br /&gt;
[http://bbs.espressif.com/viewforum.php?f=5&amp;amp;sid=3cf7540ab17805367e6a45d2c4682fc9 SDK0.9.2 + virtuelle Linuxmaschine mit eingerichtetem gcc]&lt;br /&gt;
&lt;br /&gt;
[https://drive.google.com/folderview?id=0B5bwBE9A5dBXaExvdDExVFNrUXM&amp;amp;usp=sharing Alternativlink für die virtuelle Maschine + Anleitung/HOWTO für das Setup sowie für das Kompilieren]&lt;br /&gt;
&lt;br /&gt;
=== Firmware updaten ===&lt;br /&gt;
Typischerweise wird eine kompilierte Firmware per UART-Bootloader des ESP8266-SoC auf einen Flash-Chip eines ESP8266-Moduls geladen. Von dort startet der ESP8266-SoC anschließend die Firmware.&lt;br /&gt;
&lt;br /&gt;
[http://github.com/themadinventor/esptool Python Tool zum Flashen (von Fredrik Ahlberg)] &amp;lt;br&amp;gt;&lt;br /&gt;
[http://github.com/3s1d/esp_prog Extension zum Tool von Fredrik Ahlberg] &amp;lt;br&amp;gt;&lt;br /&gt;
[http://www.mikrocontroller.net/topic/342240?page=2#3857075 Tool zum Flashen (von Christian Klippel)] &amp;lt;br&amp;gt;&lt;br /&gt;
[http://defcon-cc.dyndns.org/wiki/ESP8266#Update Anleitung, extern] &amp;lt;br&amp;gt;&lt;br /&gt;
[http://www.mikrocontroller.net/topic/342240?page=3#3810559 Anleitung, Forum]&lt;br /&gt;
&lt;br /&gt;
=== Anmerkung ===&lt;br /&gt;
Mit dem SDK wird der Mikrocontroller progammiert, der sich direkt auf dem ESP8266-SoC-Chip befindet. Dies ist nicht zu verwechseln mit Programmieranleitungen zur UART-Ansteuerung des ESP8266-SoC (meist mit AT-Firmware) mit einem anderen Mikrocontroller.&lt;br /&gt;
&lt;br /&gt;
==Checkliste bei Problemen mit dem Modul/Compiler/SDK==&lt;br /&gt;
Bitte berücksichtige bei der Frage nach Hilfestellung zu Deinem Problem die folgende Checkliste.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Bei Problemen mit der AT-Firmware/UART-Ansteuerung mit Mikrocontroller&#039;&#039;&#039;&lt;br /&gt;
# Was nutzt Du für die Stromversorgung?&amp;lt;br/&amp;gt;(Ganz knapp benennen, so dass Rückschlüsse auf Spannung und Stromstärke möglich sind)&lt;br /&gt;
# Welche Firmware-Version verwendest Du und von woher hast Du sie?&lt;br /&gt;
# Welchen Mikrocontroller verwendest Du?&lt;br /&gt;
# Welche Baudrate verwendest Du?&lt;br /&gt;
# &amp;quot;Sieht&amp;quot; das Modul den AP, &amp;quot;sieht&amp;quot; der PC das Modul?&lt;br /&gt;
# Funktioniert ein Connect?&lt;br /&gt;
# Welche AT-Befehlssequenz verwendest Du und was antwortet das Modul?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Bei Problemen mit dem SDK/Compiler&#039;&#039;&#039;&lt;br /&gt;
# Benutzt Du die neuste, offizielle VM?&amp;lt;br/&amp;gt;(Diese ist ausgelegt für das neueste SDK)&lt;br /&gt;
# Benutzt Du das neueste, offizielle SDK? Welche Version benutzt Du?&amp;lt;br/&amp;gt;(Es werden regelmäßig Bugfixes und Erweiterungen eingepflegt)&lt;br /&gt;
# Kannst Du die SDK-Beispiele (IoT,AT) entsprechend der offiziellen Anleitung kompilieren, flashen und läuft es?&lt;br /&gt;
&lt;br /&gt;
== SDK Programmers Guide ==&lt;br /&gt;
(ggf. später in eigenen Artikel)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039; GPIO Initialisieren, Setzen, Löschen, Lesen: &#039;&#039;&#039; TODO&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;&#039; UART ECHO LOOP: &#039;&#039;&#039; TODO&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;&#039; ADC lesen: &#039;&#039;&#039; TODO&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Watchdog und Timer ===&lt;br /&gt;
&amp;lt;h4&amp;gt;&lt;br /&gt;
In der C Datei in der der Watchdog an/ausgeschaltet werden soll&lt;br /&gt;
folgendes definieren:&lt;br /&gt;
&amp;lt;/h4&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   extern void ets_wdt_enable(void);&lt;br /&gt;
   extern void ets_wdt_disable(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;h4&amp;gt;&lt;br /&gt;
Diese beiden Funktionen sind im internen ROM.&lt;br /&gt;
Dann eben diese Funktionen entsprechend aufrufen.&lt;br /&gt;
&amp;lt;/h4&amp;gt;&lt;br /&gt;
&amp;lt;h4&amp;gt;&lt;br /&gt;
Es gibt auch noch:&lt;br /&gt;
&amp;lt;/h4&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   extern void wdt_feed(void);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;h4&amp;gt;&lt;br /&gt;
Wird diese Funktion aufgerufen wird der Watchdog zurückgesetzt und&lt;br /&gt;
startet wieder bei 0.&lt;br /&gt;
&amp;lt;/h4&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039; Interrupts: &#039;&#039;&#039; TODO&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;&#039; WLAN UDP/TCP ECHO LOOP: &#039;&#039;&#039; TODO&amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;&#039; Minimalbeispiel1: GPIO/LED schalten mittels UART: &#039;&#039;&#039; TODO &amp;lt;br/&amp;gt;&lt;br /&gt;
&#039;&#039;&#039; Minimalbeispiel2: GPIO/LED schalten von einem zweiten Modul aus: &#039;&#039;&#039; TODO&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Power-/Sleep-Modes ===&lt;br /&gt;
Der Stromverbrauch des ESP8266 ist abhängig von vielen Faktoren, er läßt sich aber durch geschickte Programmierung durchaus deutlich senken.&amp;lt;br/&amp;gt;&lt;br /&gt;
So ist es nicht notwendig, dass das WIFI-Modem oder der Mikrocontroller ständig läuft um z.B. eine WLAN-Türklingel zu realisieren. Im &amp;quot;Deep-Sleep&amp;quot; würde der ESP8266 dann nur 10uA verbrauchen, bis er über einen GPI-Interrupt geweckt wird und die Meldung absetzt.&amp;lt;br/&amp;gt;&lt;br /&gt;
Zu beachten ist, dass in diesem Moment die WLAN und Netzwerkanmeldung neu startet und hierfür eine gewisse Zeit benötigt wird.&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://bbs.espressif.com/viewtopic.php?f=6&amp;amp;t=133 detailierte Übersicht der verschieden Modi und deren Stromverbrauch von Espressif]&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
[http://www.esp8266.com/ ESP8266 Community Forum]&amp;lt;br/&amp;gt;&lt;br /&gt;
[http://github.com/esp8266 ESP8266 Github mit Wiki und Source-Code Samples]&amp;lt;br/&amp;gt;&lt;br /&gt;
[http://defcon-cc.dyndns.org/wiki/ESP8266 ESP8266-Informationen]&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/topic/348772 Topic neu im mikrocontroller.net-Forum]&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/topic/342240 Topic alt im mikrocontroller.net-Forum]&amp;lt;br/&amp;gt;&lt;br /&gt;
[http://www.mikrocontroller.net/topic/342878 Sammelbestellungen im mikrocontroller.net-Forum]&lt;br /&gt;
&lt;br /&gt;
=== Dokumente === &lt;br /&gt;
[https://drive.google.com/folderview?id=0B5bwBE9A5dBXaExvdDExVFNrUXM&amp;amp;usp=sharing Anleitung/HOWTO für das Setup der virtuellen Maschine (SDK) sowie für das Kompilieren]&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://nurdspace.nl/ESP8266 Übersetztes Datenblatt]&amp;lt;br /&amp;gt;&lt;br /&gt;
[http://www.electrodragon.com/w/Wi07c AT Instructions Set (English)] und [http://www.electrodragon.com/w/Wi07c#First_time_use_guide Anleitung zum Betrieb an einem Arduino (inkl. Code)]&amp;lt;br/&amp;gt;&lt;br /&gt;
[http://thomaspfeifer.net/esp8266_wlan_seriell_modul_at_kommandos.htm Beschreibung der AT-Kommandos mit Beispielen]&amp;lt;br/&amp;gt;&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/229016/Espressif_IoT_AT____v0.1.5.906.pdf Espressif AT Instruction Set(Chinese)]&amp;lt;br/&amp;gt;&lt;br /&gt;
[http://www.seeedstudio.com/document/pdf/ESP8266%20Specifications(Chinese).pdf ESP8266 Specifications(Chinese)]&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Daten===&lt;br /&gt;
[http://bbs.espressif.com/viewforum.php?f=5&amp;amp;sid=3cf7540ab17805367e6a45d2c4682fc9 SDK0.9.2 + virtuelle Linuxmaschine mit eingerichtetem gcc]&amp;lt;br&amp;gt;&lt;br /&gt;
[https://drive.google.com/folderview?id=0B5bwBE9A5dBXaExvdDExVFNrUXM&amp;amp;usp=sharing Alternativlink für die virtuelle Maschine]&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://onedrive.live.com/#cid=C4DDF72E6EEA3826&amp;amp;id=C4DDF72E6EEA3826%21631 Dateien (Xplorer+SDK+PDF+etc.)]&amp;lt;br/&amp;gt;&lt;br /&gt;
[http://www.mikrocontroller.net/attachment/230185/esp8266_config_v050.exe Config-Tool] &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Bezugsquellen ===&lt;br /&gt;
[http://www.aliexpress.com/wholesale?SearchText=ESP8266 aliexpress.com] ~ 3€&amp;lt;br/&amp;gt;&lt;br /&gt;
[http://www.banggood.com/?zf=283997 banggood.com] ~ 3.50€&amp;lt;br/&amp;gt;&lt;br /&gt;
[http://www.ebay.de Ebay]&lt;br /&gt;
ab 3€ inkl. Versand, Einzelstückpreis: ESP-01/02/03/04/05&amp;lt;br/&amp;gt;&lt;br /&gt;
(Suchbegriff: ESP8266, Option Artikelstandort: &amp;quot;Weltweit&amp;quot;)&amp;lt;br/&amp;gt;&lt;br /&gt;
(10 Stück ab 27 EUR inkl. Versand; Suchbegriff: 10pcs ESP8266)&amp;lt;br/&amp;gt;&lt;br /&gt;
ab 3.20€ inkl. Versand, Einzelstückpreis: ESP-07/08/09/11&amp;lt;br/&amp;gt;&lt;br /&gt;
[http://www.electrodragon.com/?s=esp8266&amp;amp;post_type=product electrodragon.com] ~ 3.50€ (zzgl. Versand)&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://ex-store.de/advanced_search_result.php?keywords=esp8266&amp;amp;x=0&amp;amp;y=0 eX-store.de] (ESP-01,ESP-02, ESP-03,ESP-05,ESP-07) ab 5.49€ (zzgl. Versand)&amp;lt;br/&amp;gt;&lt;br /&gt;
[https://www.it-wns.de/themes/suche/index.php?suchekategorie=&amp;amp;sucheallgemein=esp8266 IT-WNS.de] (ESP-01,ESP-03,ESP-07,ESP-12) ab 5.49€ (zzgl. Versand)&amp;lt;br/&amp;gt;&lt;br /&gt;
[http://www.seeedstudio.com/depot/WiFi-Serial-Transceiver-Module-w-ESP8266-p-1994.html seeedstudio.com] ~ 5.50€&amp;lt;br/&amp;gt;&lt;br /&gt;
[http://shop.in-circuit.de/index.php?cPath=21 In-Circuit.de] ESP-ADC DIL Modul mit ESP8266EX - made in Germany!&amp;lt;br/&amp;gt; professioneller Support, HowTo und Videos&amp;lt;br/&amp;gt; ab 500 Stk. je 3.90€, 9.90€ Einzelpreis&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Anderes==&lt;br /&gt;
[http://www.mikrocontroller.net/articles/ESP8266-CPCB PCB für Community-Modul (Vorschlag)]&lt;br /&gt;
== Einzelnachweise ==&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
--von [[axhieb]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Bauteile]]&lt;br /&gt;
[[Kategorie:Funk]]&lt;br /&gt;
[[Kategorie:Wlan]]&lt;/div&gt;</summary>
		<author><name>80.64.189.58</name></author>
	</entry>
</feed>