www.mikrocontroller.net

AVR Checkliste

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.

Inhaltsverzeichnis

[bearbeiten] Hardware

[bearbeiten] Anderen Controller benutzt als den im Schaltplan: Pinkompatibilität sichergestellt?

Nur wenige AVR-Controller sind pinkompatibel und damit untereinander austauschbar. Manchmal liegen gar die am dringensten benötigten Funktionen (ISP-Programmierung) bei anderen Controllern auf anderen Pins. Unbedingt vorher die Belegungen anhand der Datenblätter vergleichen!

[bearbeiten] Fuses richtig gesetzt?

Die AVR-Controller haben 'Fuses' (deutsch: 'Sicherungen'), die das Verhalten des Prozessors auf grundlegender Ebene bestimmen. Ein häufiger Fehler ist beispielsweise, dass die falsche Taktquelle gewählt wurde (Fuse "CKSEL" etc.): einige AVRs können mit dem internen Oszillator (internal R/C), mit einem externen Oszillator (external clock), mit einem Quarz (external crystal) oder mit einem Resonator (external R/C) betrieben werden. Wenn die Einstellung über die Fusebits nicht dazu passt (z. B. external clock statt external crystal), 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.

Eine andere Fuse (JTAGEN) schaltet auf einem Port (z.B. PORTC auf ATMega32) die JTAG-Unterstützung ein bzw. aus. Wenn sie eingeschaltet ist, funktionieren vier Bits dieses Ports nicht wie gewohnt, da sie für die JTAG-Schnittstelle reserviert werden.

In dem zum STK500 gehörenden Entwicklungstool 'AVR Studio' gibt es in der Programmer-Dialogbox einen Tab 'Fuses', der controllerabhängig den Status der Fusebits anzeigt und Änderungen ermöglicht. Siehe auch: AVR Fuses.

[bearbeiten] ISP-Adapter

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).

Bei seriellem Programmer mit Controller (STK500, Atmel AVRISP etc.): Programmieren dauert sehr lange, es gibt Fehler. Abhilfe: ISP Taktrate richtig einstellen (<1/4 F_CPU).

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.

[bearbeiten] Spannungsversorgung richtig angeschlossen?

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). 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.

[bearbeiten] Reset-Pin korrekt beschaltet?

Der Reset-Anschluss am AVR ist 'active-low', d. h. wenn man den Pin mit GND (Masse) verbindet, wird der Controller resettet. Zwar haben AVRs einen internen Pullup-Widerstand, der den Reset-Pin gegen VCC "zieht", dieser ist jedoch relativ hochohmig (ca. 50 kOhm, vgl. Datenblatt) und reicht unter Umständen nicht aus, um den Reset-Pin sicher "hochzuhalten". Als Mindestbeschaltung empfiehlt sich dringend, einen externen Pullup-Widerstand vorzusehen (typisch 10 kOhm), der den Reset-Pin mit VCC verbindet. Er sollte nicht kleiner als 4,7 kOhm sein, da der Programmieradapter sonst eventuell den Reset-Pin während des Programmiervorgangs nicht sicher auf "low" ziehen kann. Zusätzlich sollte man auch noch einen Kondensator 47 nF oder 100 nF zwischen Reset-Pin und GND anordnen. Dieses RC-Glied sorgt dafür, dass der Controller beim Einschalten der Versorgungsspannung für eine definierte Zeitspanne im Reset gehalten wird. Im laufenden Betrieb sorgt der Kondensator dafür, dass der Reseteingang unempfindlich gegenüber Spikes und Glitches wird. Er sollte deshalb unmittelbar in Pin-Nähe beim Prozessor untergebracht werden. Dieser Kondensator darf jedoch nicht verwendet werden, wenn debugWIRE möglich sein soll.

Atmel empfiehlt zusätzlich noch zum Schutz vor Überspannungen eine externe Diode nach VCC ("Clamp-Diode"), da für den Reset-Pin keine interne vorhanden ist. Diese Diode bereitet jedoch bei manchen Programmieradaptern Schwierigkeiten.

[bearbeiten] Abblockkondensator(en) ordnungsgemäß installiert?

Abblockkondensatoren ("Bunker-Kondensatoren") dienen dazu, sehr kurze Versorgungsspannungseinbrüche, die durch Schaltvorgänge verursacht werden können, zu kompensieren. Diesen Zweck erfüllen sie optimal, wenn folgende Regeln eingehalten werden:

  • Ein Abblockkondensator sollte möglichst dicht am IC sitzen.
  • Jedes IC in einer Schaltung sollte einen Abblockkondensator besitzen.
  • Bei ICs mit mehreren Anschlüssen für VCC und GND sollte jedes VCC-GND-Paar mit einem eigenen Abblockkondensator beschaltet werden (z. B. AVRs in SMD-Bauform wie dem ATmega16A also mit vier Kondensatoren).
  • Es sollten keramische Kondensatoren mit einer Kapazität von 100 nF verwendet werden. Größere Kondensatoren, etwa 10 µF-Elkos, sind für diese Aufgabe nicht geeignet, weil sie "zu langsam" sind!

[bearbeiten] Quarz oder Quarzoszillator angeschlossen?

Die neueren AVRs haben einen internen Oszillator, der im Auslieferungszustand über die entsprechenden Fuses eingeschaltet ist. In diesem Fall muss kein externer Quarz mehr angeschlossen werden. Man kann in den Fuse-Bits aber einstellen, dass man einen externen Taktgenerator (external clock, z. B. Quarzoszillator) oder externen Quarz (external crystal) verwenden möchte.

Dann, oder wenn der AVR keinen internen Takt hat, wird an die entsprechenden Pins des Controllers ein Quarz (external crystal, Bauelement mit zwei "Beinchen") oder Quarzoszillator (external clock, Bauelement mit vier "Beinchen") angeschlossen. Im Falle eines Quarzes werden die XTAL-Pins mit den beiden Anschlüssen des Quarzes und jeweils mit einem Kondensator (ca. 22 bis 27 pF) gegen Masse angeschlossen. Im Falle eines Quarzoszillators reicht es aus, den Taktausgang mit dem XTAL1-Pin zu verbinden, und den XTAL2-Pin unbeschaltet zu lassen. Die Fuses sind entsprechend einzustellen.

[bearbeiten] Alle Ground-Anschlüsse beschaltet?

Bei AVRs mit mehreren Ground-Anschlüssen müssen alle Anschlüsse beschaltet werden. Siehe http://www.mikrocontroller.net/forum/read-1-107259.html

[bearbeiten] Alle Lötstellen in Ordnung?

"Kalte", 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.

Bei kleinen Abständen (SMD-Bauteile) müssen besonders Verbindungen zwischen benachbarten Lötungen kontrolliert werden.

Bei Lochrasterplatinen kann man mit einem spitzen Messer (Bastelmesser) die Zwischenräume von möglichen leitenden Verbindungen befreien.

[bearbeiten] Eingänge

Taster müssen:

  • einen Pullup-Widerstand besitzen, so sie active-low 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 "0", PORT auf "1").

Will man einen Taster active-high betreiben, soll also bei Tastendruck eine "1" 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.

Symptome: Aufgrund des Prellens bekommt man bei einem Tastendruck statt eines Signals mehrere, und beim fehlenden Pullup fängt man sich Störungen (z.B. das 50 Hz-Netzbrummen) ein, da der Pin nicht auf einem "definierten Pegel" liegt, wenn der Taster nicht geschlossen ist. Soll z.B. bei einem Tastendruck eine LED angehen, dann leuchtet die LED durch das Netzbrummen plötzlich mit 50 Hz anstatt aus zu sein.

  • 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.
  • active high: Taster zwischen Port-Pin und VCC; externen Widerstand zwischen Port-Pin und GND.

[bearbeiten] Ausgänge

Man sollte darauf achten, das "kritische" Ausgänge, d.h. Ausgänge, über die nicht "nur" eine LED geschaltet wird, einen definierten Zustand haben, wenn der Portpin auf "Eingang" und damit hochohmig geschaltet ist. Dadurch wird sichergestellt, dass beim Einschalten nicht kurz ein Verbraucher geschaltet wird (z.B. "Zucken" 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.

[bearbeiten] Besonderheiten bei ATmega64 / ATmega128

Der ATmega64 und der ATmega128 haben zwei besondere Fallstricke, über die man bei nicht ausreichendem Datenblattstudium leicht stolpert.

  • Der erste betrifft den Anschluss der ISP-Signale (MISO, MOSI, SCK, RESET). Dieser erfolgt nicht wie bei den meisten anderen AVR-Controllern an den gleichnamigen Pins, sondern an PDI, PDO, SCK und RESET. Die Pinzuordnung ist: MOSI->PE0 (Pin 2), MISO->PE1 (Pin 3), SCK->PB1 (Pin 11) und RESET->RESET (Pin 20). PEN (Pin 1) hat für normale ISP-Adapter keine Bedeutung und kann offen gelassen oder direkt mit Vcc verbunden werden. Die Benutzung der Pins PDI und PDO anstelle von MOSI und MISO gilt zusätzlich für einige ATMega128-Derivate im 64-Pin-TQFP-Gehäuse (darunter AT90CAN128, ATMega1281/2561)! Im Zweifelsfall im Datenblatt (Pin Configuration) nachsehen, ob PE0 und PE1 mit "PDI" bzw. "PDO" beschriftet sind.
  • Die zweite kleine "Gemeinheit" betrifft die M103C-Fuse (Atmega103 Compatibility Mode). Diese ist bei fabrikneuen Atmega64 und Atmega128 gesetzt und sorgt dafür, dass sich diese wie ein Atmega103 verhalten.
    • Andererseits hat dies zur Folge, dass ein für den Atmega64 oder Atmega128 geschriebenes Programm beim ersten "ret" abstürzt, da der SRAM an einer anderen Stelle liegt als erwartet und somit der Prozessor keine gültige Rücksprungadresse vom Stack holen kann.
    • Außerdem funktionieren einige IO-Pins an PORTC, PORTF und PORTG anders.
    • Für weitere Infos bzgl. TWI, UART, Timer, Bootloader und Kalibrierung des internen RC-Oszillators unbedingt das Datenblatt lesen.

[bearbeiten] Software

[bearbeiten] Alle Interruptvektoren definiert?

Wenn man irgendwelche Interruptvektoren 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.

Ausserdem 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.

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).

[bearbeiten] Alle Konfigurationsregister korrekt initialisiert?

Alle benötigten Konfigurationsregister (auch "I/O-Register" genannt) eines Mikrocontrollers müssen korrekt initialisiert werden. Bei Fehlfunktionen sollten diese Konfigurationen noch einmal mit dem Datenblatt abgeglichen werden. 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. Wenn man besonders "sauber" programmieren möchte, initialisiert man Konfigurationsregister immer, d.h. auch wenn sie nicht im Programm verwendet werden. Dies verhindert mögliche zufällige Fehlkonfigurationen.


[bearbeiten] Stackpointer initialisiert? (Nur in Assembler relevant)

Fehlerbeschreibung: Das Programm lief, bis ein "rcall" oder ein Interrupt eingefügt wurde. Danach ging plötzlich gar nichts mehr.

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 "unten" 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). "Den Stack initialisieren" bedeutet, den Stackpointer auf den gewünschten "Startwert" zu setzen. Meistens wird dafür die letzte RAM-Adresse gewählt.

Die Initialisierung unterscheidet sich geringfügig je nach verwendetem AVR. Bei den alten AT90xxxx und den ATtinys ist sie mit zwei Zeilen erledigt:

       ldi r16, RAMEND   ;Die Adresse der letzten Stelle im RAM in r16 laden
       out SPL, r16      ;Die Adresse in das Register SPL ausgeben 


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:

       ldi r16, LOW(RAMEND)    ;Untere 8 bit des 16 bit-Wertes RAMEND laden
       out SPL, r16
       ldi r16, HIGH(RAMEND)   ;Obere 8 bit laden
       out SPH, r16


[bearbeiten] 16bit-Register in richtiger Reihenfolge geladen/gelesen? (Nur in Assembler relevant)

Bei den 16-bit Registern (z.B. Timer1) genau die Hinweise im Kapitel "Accessing 16-bit Registers" beachten!

So muss z.B. das High-Byte VOR dem Low-Byte geschrieben werden, weil mit dem Schreiben des Low Byte das gesamte Register "übernommen" wird. Beim Lesen muss zuerst das Low-Byte gelesen werden, dann das High-Byte. Es wird dadurch garantiert, dass sich zwischen den beiden einzelnen Befehlen nicht noch das Register weiter verändert, z.B. beim 16bit Counter. Möglich wird das durch ein "temporary Register", 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.

In C oder Basic kümmert sich der Compiler um das Problem - man liest oder beschreibt dann einfach z.B. TCNT1 anstatt TCNT1H und TCNT1L einzeln.


[bearbeiten] Flag richtig gelöscht?

Ein beliebter Fehler ist, dass man überliest, dass gesetzte Flags (z.B. die Interrupt-Flags) durch beschreiben mit einer '1' und nicht mit einer '0' gelöscht werden!

Beispiel:

  • das Flag ist zuerst '0'
  • das Ereignis (z.B. Zählerüberlauf, also Bit TOV0 in TIFR) tritt auf und setzt das jeweilige Bit im Register auf '1'
  • wir haben auf die '1' gewartet und wollen das Bit nun wieder löschen und müssen dafür eine '1' (eins!) in das Register schreiben, keine '0'. Trotzdem wird das Bit dadurch '0' z.B.:
    TIFR = (1<<TOV0);

Das ganze ist kein Fehler, sondern hat seine guten Gründe.

Wenn Interrupts zugelassen sind (z.B. in TIMSK) und die Interruptroutine aufgerufen wird, werden diese Flags zumeist automatisch gelöscht.

Der UART-Empfangs-Interrupt (RXC in UCSRA) jedoch nicht! Der wird gelöscht durch Auslesen des Empfangsregisters (UDR). Hier liegt wiederum ein beliebter Stolperstein: Man prüft oft zuerst in der Interruptroutine die Fehlerflags (z.B. Parity) und macht dann manchmal den Fehler das empfangene Zeichen im Fehlerfall nicht auszulesen. Das führt dann zum Absturz (der IRQ wird immer wieder aufgerufen) - man muss also immer das UDR lesen auch wenn etwas Fehlerhaftes drinsteht.

Zusätzlich ist zu beachten, dass in C die Interrupt-Flags nicht mit einer Veroderung des Registers (z.B. TIFR |= (1 << 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 << TOV0))!

[bearbeiten] Serielle Verbindungen

[bearbeiten] I²C/TWI

Sind die Leitungen SCL und SDA mit einem Pullup-Widerstand ausgestattet? Die I²C-Bus-Leitungen SCL und SDA müssen über einen Pullup-Widerstand mit einem Wert von 4,7 kOhm bis 10 kOhm mit der Versorgungsspannung (+5 V) verbunden sein.

[bearbeiten] UART/USART

[bearbeiten] Übertragungsprobleme durch falschen oder ungenauen Takt

  • Der interne Oszillator ist recht ungenau und nicht temperaturstabil. Daher kann die Umgebungstemperatur auch den USART-Takt verändern. Für serielle, asynchrone Kommunikation per UART sollte man deshalb immer einen Quarz(oszillator) verwenden, eagl bei welcher Baudrate (3% sind immer 3%, egal ob bei 1200 oder 9600 Baud). Falls doch der interne Oszillator verwendet wird, wurde er für die richtige Frequenz und Betriebsspannung kalibriert?
  • Nicht mit allen Quarzen kann man alle Baudraten genau genug erzeugen; deswegen gibt es Baudratenquarze wie z.B. 3,6864 MHz. Näheres steht im Datenblatt.
  • Geschieht die Konfiguration des U(S)ART automatisch durch die Programmiersprache (z.B. in BASCOM, C), dann muss dort der Takt genau angegeben werden. Setzt man z.B. einen 3,6864 MHz-Quarz ein, darf man dort nicht einfach "4 MHz" angeben, weil dann die Abweichung mit ca. 8% viel zu hoch wäre. Damit funktioniert die Übertragung nicht mehr.
  • Wenn ein externer Oszillator oder Quarz angeschlossen ist: Sind die Fuses des Controllers so gesetzt, dass er auch verwendet wird?
  • Ist die Fuse CLKDIV nicht programmiert?
  • Um zu prüfen ob der externe Quarz auch wirklich verwendet wird, kann man mittels _delay_ms() einfach mal eine LED im Sekundentakt blinken lassen. Den Unterschied zwischen Quarz und internem RC-Oszillator kann man bei grösseren Frequenzunterschieden leicht sehen. Ebenso sieht man, ob versehentlich die CLKDIV Fuse gesetzt ist, die Blinkfreqeunz ist dann achtmal langsamer. Allerdings muss man auch hier aufpassen. Siehe AVR-Tutorial.
  • Erscheinen im Terminalprogramm kryptische Zeichen anstatt ordentlichen Buchstaben (z.B. ü statt A), liegt das zu 99,9% an einer falsch eingestellten/erzeugten Baudrate im Mikrocontroller.
  • In den Tutorials für Assembler und GCC wird die Nutzung recht gut erklärt und mit Beispielen hinterlegt.

[bearbeiten] Sonstige Fehlerquellen bei UART/USART

  • Funktioniert die Datenübertragung zum PC nur solange der Programmieradapter eingesteckt ist, deutet dies auf ein Problem mit der Masse hin (z.B. GND-Anschluss am RS232-Stecker nicht belegt oder dergleichen).
  • Der Pegelwandler/Inverter (z.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 (100 nF keramisch) zwischen VCC und GND des ICs. Das jeweilige Datenblatt gibt Auskunft über die Beschaltung bei "typischer Anwendung".
  • TX/RX vertauscht? Modem- oder Nullmodemkabel?
  • Die Hardware und Verkabelung kann man schnell prüfen, indem man das Pin R1OUT bzw. R2OUT mit T1IN bzw. T2IN verbindet (je nachdem welches verwendet wird). Dann sollte man auf dem PC ein Terminalprogramm starten (z.B. Hyperterminal) und Zeichen eigeben können und sofort angezeigt bekommen, egal mit welcher Baudrate. Lediglich die Flusssteuerung muss auf "Kein" eingestellt werden. Man muss aber beachten, dass T1IN bzw. T2IN für diesen Test nicht mit dem Mikrocontroller verbunden sein darf, weil sonst zwei Ausgänge miteinander verbunden sind, was nicht wirklich gut ist (siehe Ausgangsstufen Logik-ICs). Wenn der uC gesockelt ist kann man ihn dafür einfach aus dem Sockel nehmen und die RX/TX Pins mit einem Stück Draht verbinden.

[bearbeiten] Analog-Digital-Wandler

  • Sind die Pullup-Widerstände deaktiviert?

[bearbeiten] Weblinks

webmaster@mikrocontroller.netImpressumWerbung auf Mikrocontroller.net