<?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=172.26.37.113</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=172.26.37.113"/>
	<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/articles/Spezial:Beitr%C3%A4ge/172.26.37.113"/>
	<updated>2026-04-10T21:36:52Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.39.7</generator>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR-GCC-Tutorial/Assembler_und_Inline-Assembler&amp;diff=105133</id>
		<title>AVR-GCC-Tutorial/Assembler und Inline-Assembler</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR-GCC-Tutorial/Assembler_und_Inline-Assembler&amp;diff=105133"/>
		<updated>2022-04-09T14:33:06Z</updated>

		<summary type="html">&lt;p&gt;172.26.37.113: neue url: Atmel: AVR 8-Bit Instruction Set (pdf)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Gelegentlich erweist es sich als nützlich, C- und Assembler-Code in einer Anwendung zu nutzen. Typischerweise wird das Hauptprogramm in C verfasst und wenige, zeitkritische oder hardwarenahe Operationen in Assembler.&lt;br /&gt;
&lt;br /&gt;
Die GNU-Toolchain bietet dazu zwei Möglichkeiten:&lt;br /&gt;
;Inline-Assembler: Die Assembleranweisungen werden direkt in den C-Code integriert. Eine Quellcode-Datei enthält somit C- und Assembleranweisungen&lt;br /&gt;
;Assembler-Dateien: Der Assemblercode befindet sich in eigenen Quellcodedateien. Diese werden vom GNU-Assembler (avr-as) zu Object-Dateien assembliert und mit den aus dem C-Code erstellten Object-Dateien zusammengelinkt.&lt;br /&gt;
&lt;br /&gt;
== Inline-Assembler ==&lt;br /&gt;
&lt;br /&gt;
Inline-Assembler bietet sich an, wenn nur wenig Assembleranweisungen benötigt werden. Typische Anwendung sind kurze Codesequenzen für zeitkritische Operationen, Takt-genaue Warteschleifen oder das Einfügen spezieller Instruktionen, die nicht durch reinen C-Code eingefügt werden können.&lt;br /&gt;
&lt;br /&gt;
Inline-Assembler wird mit &#039;&#039;&#039;asm&#039;&#039;&#039; oder &#039;&#039;&#039;asm volatile&#039;&#039;&#039; eingeleitet, zusätzlich gibt es das Ansi-konforme &#039;&#039;&#039;__asm__&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Die Assembler-Anweisungen werden als statisch konstanten String angegeben, der ähnlich wie bei einem &amp;lt;tt&amp;gt;printf&amp;lt;/tt&amp;gt; verwendet wird: %-Platzhalter werden durch die Werte der nachfolgenden C-Ausdrücke ersetzt und die resultierende Zeichenkette in die Assembler-Ausgabe des Compiler eingefügt. Ähnlich wie bei &amp;lt;tt&amp;gt;printf&amp;lt;/tt&amp;gt; gibt es auch bei Inline-Assembler Modifier, die es erlauben, Operanden in unterschiedlicher Weise darzustellen.&lt;br /&gt;
&lt;br /&gt;
Die Output-Operanden folgen auf das Assembler-Template und werden von diesem durch einen Doppelpunkt getrennt. Danach folgen – wieder durch einen&amp;amp;nbsp;:&amp;amp;nbsp;getrennt – die Input-Operanden. Danach eine Clobber-Liste sowie eine Liste mit Labels.&lt;br /&gt;
&lt;br /&gt;
Ein einfaches Beispiel für Inline-Assembler ist das Einfügen einer NOP-Anweisung (NOP steht für &#039;&#039;No OPeration&#039;&#039;). Dieser Assembler-Befehl benötigt auf einem AVR genau einen Taktzyklus, ansonsten hat er keinen Effekt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
    /* Verzögern der weiteren Programmausführung um 2 Taktzyklen */&lt;br /&gt;
    asm volatile (&amp;quot;nop&amp;quot;);&lt;br /&gt;
    asm volatile (&amp;quot;nop&amp;quot;);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Als Beispiel für mehrzeiligen Inline-Assembler dient eine präzise Delay-Funktion. Die Funktion erhält einen 16-Bit Wert als Parameter, und der Inline-Assembler dekrementiert diesen Wert so lange, bis er zu –1 unterläuft, was die Schleife beendet.&lt;br /&gt;
&lt;br /&gt;
Inline-Assembler hat hier den Vorteil, dass die Laufzeit – abgesehen von Interrupts, die gegebenenfalls während der Scheifenausführung auftreten – unabhängig von der Optimierungsstufe des Compilers und der Compiler-Version ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
static inline void __attribute__((always_inline))&lt;br /&gt;
delayloop16 (unsigned int count)&lt;br /&gt;
{&lt;br /&gt;
    /* Die Schleife dauert  4 * count + 3  Ticks */&lt;br /&gt;
&lt;br /&gt;
    asm volatile (&amp;quot;1:&amp;quot;           &amp;quot;\n\t&amp;quot;&lt;br /&gt;
                  &amp;quot;sbiw %0,1&amp;quot;    &amp;quot;\n\t&amp;quot;&lt;br /&gt;
                  &amp;quot;brcc 1b&amp;quot;&lt;br /&gt;
                  : &amp;quot;+w&amp;quot; (count));&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* Jede Anweisung wird mit &amp;lt;tt&amp;gt;&amp;quot;\n\t&amp;quot;&amp;lt;/tt&amp;gt; abgeschlossen. Der Zeilenumbruch teilt dem Assembler mit, dass ein neuer Befehl beginnt.&lt;br /&gt;
* Als Sprung-Label wurde eine Ziffer verwendet. Diese speziellen Labels sind mehrfach im Code verwendbar. Dies ist notwendig, wenn &amp;lt;tt&amp;gt;delayloop16&amp;lt;/tt&amp;gt; mehrfach verwendet wird und durch Inlining mehrfach in der Assembler-Ausgabe erscheint. Gesprungen wird jeweils zurück (&amp;lt;tt&amp;gt;b&amp;lt;/tt&amp;gt;) oder vorwärts (&amp;lt;tt&amp;gt;f&amp;lt;/tt&amp;gt;) zum nächsten auffindbaren Label.&lt;br /&gt;
* Das &amp;lt;tt&amp;gt;&amp;quot;+w&amp;quot;&amp;lt;/tt&amp;gt; wird als &#039;&#039;Inline-Assembler Constraint&#039;&#039; (Nebenbedingung) bezeichnet und legt fest, wie der Compiler mit dem Ausdruck &amp;lt;tt&amp;gt;count&amp;lt;/tt&amp;gt; umzugehen hat. &amp;lt;tt&amp;gt;w&amp;lt;/tt&amp;gt;&amp;amp;nbsp;steht für eine bestimmte Registerklasse, nämlich die Register R24...R31: SBIW brauch eines dieser Register mit gerader Registernummer. Dass die Registernummer gerade ist, ergibt sich daraus, dass das [http://gcc.gnu.org/wiki/avr-gcc#ABI avr-gcc ABI] dies für 16-Bit Werte so vorschreibt.&lt;br /&gt;
: Das &amp;lt;tt&amp;gt;+&amp;lt;/tt&amp;gt; vor der Registerklasse besagt, dass &amp;lt;tt&amp;gt;count&amp;lt;/tt&amp;gt; sowohl Eingabe als auch Ausgabe des Inline-Assembler ist und mithin vom Inline-Assembler verändert wird.  Es ist wichtig, dies dem Compiler mitzuteilen, damit er &amp;lt;tt&amp;gt;count&amp;lt;/tt&amp;gt; nicht an anderer Stelle wiederverwendet und damit falschen Code erzeugt.&lt;br /&gt;
&lt;br /&gt;
Das Resultat zeigt ein Blick in die Assembler-Datei, die der Compiler mit der Option &amp;lt;tt&amp;gt;-save-temps&amp;lt;/tt&amp;gt; nicht löscht:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
	1:&lt;br /&gt;
	sbiw r24,1&lt;br /&gt;
	brcc 1b&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Siehe auch: &lt;br /&gt;
* [http://ww1.microchip.com/downloads/en/devicedoc/atmel-0856-avr-instruction-set-manual.pdf Nicrochip: &#039;&#039;AVR 8-Bit Instruction Set&#039;&#039; (pdf)]&lt;br /&gt;
* [http://www.nongnu.org/avr-libc/user-manual/inline_asm.html AVR-Libc: &#039;&#039;Inline Assembler Cookbook&#039;&#039;:] Detaillierte Ausführungen zum Thema Inline-Assembler.&lt;br /&gt;
* [http://gcc.gnu.org/wiki/avr-gcc#Register_Layout GCC-Wiki: &#039;&#039;avr-gcc: Register Layout&#039;&#039;]: Das avr-gcc (Application Binary Interface (ABI).&lt;br /&gt;
* [http://www.roboternetz.de/wissen/index.php/Inline-Assembler_in_avr-gcc RN-Wissen: &#039;&#039;Deutsche Einführung in Inline-Assembler&#039;&#039;]&lt;br /&gt;
&lt;br /&gt;
== Assembler-Dateien ==&lt;br /&gt;
&lt;br /&gt;
:→ [http://www.nongnu.org/avr-libc/user-manual/assembler.html AVR-Libc Doku: avr-libc and assembler programs]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Gcc-flow.svg|thumb|right|250px|Codeerzeugung mit den GNU-Tools]]&lt;br /&gt;
Assembler-Module werden analog zu C-Modulen übersetzte:  Während ein C-Modul &amp;lt;tt&amp;gt;modul.c&amp;lt;/tt&amp;gt; mittels&lt;br /&gt;
    avr-gcc -c modul.c  {{pale|(weitere Optionen)}}&lt;br /&gt;
zum Object übersetzt wird, ist der Compileraufruf für eine Assembler-Quelle &amp;lt;tt&amp;gt;modul.sx&amp;lt;/tt&amp;gt;&lt;br /&gt;
    avr-gcc -c modul.sx  {{pale|(weitere Optionen)}}&lt;br /&gt;
&lt;br /&gt;
Durch die Endung &amp;lt;tt&amp;gt;.sx&amp;lt;/tt&amp;gt; erkennt gcc, dass es sich bei der Datei um eine Assembler-Quelle handelt.&lt;br /&gt;
&lt;br /&gt;
Die Quelle wird zunächst präprozessiert, d.h. man kann Direktiven wie &amp;lt;tt&amp;gt;#include&amp;lt;/tt&amp;gt; und &amp;lt;tt&amp;gt;#define&amp;lt;/tt&amp;gt; verwenden.  Danach wird die präprozessierte Datei an den Assembler übergeben.  Alternativ kann die Endung &amp;lt;tt&amp;gt;.S&amp;lt;/tt&amp;gt; verwendet werden.  Bei einer anderen Dateiendung kann das Quellformat mit &amp;lt;tt&amp;gt;-x&amp;lt;/tt&amp;gt; auf &#039;&#039;Assembler mit C-Präprozessor&#039;&#039; eingestellt werden:&lt;br /&gt;
    avr-gcc -x assembler-with-cpp -c modul.asm  {{pale|(weitere Optionen)}}&lt;br /&gt;
&lt;br /&gt;
Der Unterschied zwischen &amp;lt;tt&amp;gt;.sx&amp;lt;/tt&amp;gt; und &amp;lt;tt&amp;gt;.S&amp;lt;/tt&amp;gt; einerseits und &amp;lt;tt&amp;gt;.s&amp;lt;/tt&amp;gt; andererseits ist dass für &amp;lt;tt&amp;gt;s&amp;lt;/tt&amp;gt;-Dateien kein Präprozessor aufgerufen wird. s-Dateien werden zum Beispiel temporär von gcc erzeugt wenn eine C- oder C++-Quelle übersetzt wird. Der Compiler erzeugt keine Präprozessor-Direktiven und daher kann der Aufruf den Präprozessors nach dem Compilieren gespart werden was den Übersetzungsvorgang beschleunigt.&lt;br /&gt;
&lt;br /&gt;
In allen Fällen wird ein Modul &amp;lt;tt&amp;gt;modul.o&amp;lt;/tt&amp;gt; erzeugt, das genauso verwendet werden kann wie ein Modul, das aus C-Code oder C++-Code erzeugt wurde.  Soll die Object-Datei einen anderen Namen bekommen, dann dies mit &amp;lt;tt&amp;gt;-o dateiname&amp;lt;/tt&amp;gt; erreicht werden.&lt;br /&gt;
&lt;br /&gt;
Anhängig vom der verwendeten Build-Umgebung (eigenes Makefile, Mfile, Apache Ant, AVR Studio, Eclipe, Code::Blocks, Programmers Notepad, Shell-Skript, ...) wird die Assembler-Quelle zum Projekt hinzugefügt. Hierfür sei auf die Dokumentation der jeweiligen Entwicklungsumgebung verwiesen.&lt;br /&gt;
&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
=== Verwenden der C-Runtime Umgebung ===&lt;br /&gt;
&lt;br /&gt;
=== Stand-Alone Assembler ===&lt;br /&gt;
&lt;br /&gt;
== Globale Variablen für Datenaustausch ==&lt;br /&gt;
&lt;br /&gt;
Oftmals kommt man um globale Variablen nicht herum, z.&amp;amp;nbsp;B. um den Datenaustausch zwischen Hauptprogramm und Interrupt-Routinen zu realisieren. &lt;br /&gt;
Hierzu muss man im Assembler wissen, wo genau die Variable vom C-Compiler abgespeichert wird.&lt;br /&gt;
&lt;br /&gt;
Hierzu muss die Variable, hier &amp;quot;zaehler&amp;quot; genannt, zuerst im C-Code als Global definiert werden, z.&amp;amp;nbsp;B. so:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t zaehler;&lt;br /&gt;
&lt;br /&gt;
int16_t main (void)&lt;br /&gt;
{&lt;br /&gt;
    // irgendein Code, in dem zaehler benutzt werden kann&lt;br /&gt;
    &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im folgenden Assembler-Beispiel wird der Externe Interrupt0  verwendet, um den Zähler hochzuzählen. Es fehlen die Initialisierungen des Interrupts und die Interrupt-Freigabe, so richtig sinnvoll ist der Code auch nicht, aber er zeigt (hoffentlich) wie es geht.&lt;br /&gt;
&lt;br /&gt;
Im Umgang mit Interrupt-Vektoren gilt beim GCC-Assembler das Gleiche, wie bei C: Man muss die exakte Schreibweise beachten, ansonsten wird nicht der Interrupt-Vektor angelegt, sondern eine neue Funktion - und man wundert sich, dass nichts funktionert (vgl. das AVR-GCC-Handbuch).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
temp = 16&lt;br /&gt;
&lt;br /&gt;
.extern zaehler&lt;br /&gt;
&lt;br /&gt;
.global INT0_vect&lt;br /&gt;
INT0_vect:&lt;br /&gt;
&lt;br /&gt;
     push temp                      //; wichtig: Benutzte Register und das&lt;br /&gt;
     in temp,_SFR_IO_ADDR(SREG)     //; Status-Register (SREG) sichern!&lt;br /&gt;
     push temp&lt;br /&gt;
&lt;br /&gt;
     lds temp,zaehler               //; Wert aus dem Speicher lesen&lt;br /&gt;
     inc temp                       //; bearbeiten&lt;br /&gt;
     sts zaehler,temp               //; und wieder zurückschreiben&lt;br /&gt;
&lt;br /&gt;
     pop temp                       //; die benutzten Register wiederherstellen&lt;br /&gt;
     out _SFR_IO_ADDR(SREG),temp&lt;br /&gt;
     pop temp&lt;br /&gt;
     reti&lt;br /&gt;
&lt;br /&gt;
.end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Globale Variablen im Assemblerfile anlegen ===&lt;br /&gt;
&lt;br /&gt;
Alternativ können Variablen aber auch im Assemblerfile angelegt werden. Dadurch kann auf eine .c-Datei verzichtet werden. Für das obige Beispiel könnte der Quelltext dann die Dateien zaehl_asm.S und zaehl_asm.h abgelegt werden, so dass nur noch zaehl_asm.S mit kompiliert werden müsste.&lt;br /&gt;
&lt;br /&gt;
Anstatt im Assemblerfile über das Schlüsselwort &#039;&#039;.extern &#039;&#039; auf eine vorhandene Variable zu verweisen, wird dazu mit dem Schlüsselwort &#039;&#039;.comm&#039;&#039; die benötigte Anzahl von Bytes für eine Variable reserviert.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;zaehl_asm.S&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
temp = 16&lt;br /&gt;
&lt;br /&gt;
//; 1 Byte im RAM für den Zähler reservieren&lt;br /&gt;
.comm zaehler, 1&lt;br /&gt;
&lt;br /&gt;
.global INT0_vect&lt;br /&gt;
INT0_vect:&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In der Headerdatei wird dann auf die Variable nur noch verwiesen (Schlüsselwort &#039;&#039;extern&#039;&#039;):&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;zaehl_asm.h&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#ifndef ZAEHL_ASM_H&lt;br /&gt;
#define ZAEHL_ASM_H&lt;br /&gt;
// Funktionsdeklaration in C++, z.B. für Arduino&lt;br /&gt;
#ifdef __cplusplus&lt;br /&gt;
    extern &amp;quot;C&amp;quot; {&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
extern volatile uint8_t zaehler;&lt;br /&gt;
uint8_t test(uint16_t parameter1, char *ptr);    &lt;br /&gt;
&lt;br /&gt;
// Abschluss der Funktionsdeklaration in C++, z.B. für Arduino&lt;br /&gt;
#ifdef __cplusplus&lt;br /&gt;
    }&lt;br /&gt;
#endif&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im Gegensatz zu globalen Variablen in C werden so angelegte Variablen nicht automatisch mit dem Wert 0 initialisiert. Deshalb ist es meist besser, die globalen Variablen im C-Code zu definieren, dort kann man sie einfacher verwalten. Sie werden dann auch korrekt initialisiert, sei es mit 0 oder einem spezifischen Wert. Assemblerfunktionen brauchen natürlich auch eine Deklaration im Header, damit der Compiler weiß, wie der Aufruf aussieht. Für Interruptroutinen braucht man sie nicht, dort wird nur die Adresse in die ISR-Vektortabelle eingetragen. Dafür muss nur das Label per .global Direktive im Quelltext der .S Datei dem Linker mitgeteilt werden. Mit den beiden #ifdef __cplusplus Blöcken am Anfang und Ende ist die Headerdatei automatisch auch für einen C++ Compiler verdaulich, wie er z.B. beim Arduino genutzt wird. Wenn man nur mit einem C-Compiler arbeitet, kann man sie weglassen.&lt;br /&gt;
&lt;br /&gt;
=== Variablen größer als 1 Byte ===&lt;br /&gt;
&lt;br /&gt;
Variablen, die größer als &#039;&#039;&#039;ein&#039;&#039;&#039; Byte sind, können in Assembler auf ähnliche Art angesprochen werden. Hierzu müssen nur genug Bytes angefordert werden, um die Variable aufzunehmen. Soll z.&amp;amp;nbsp;B. für den Zähler eine Variable vom Typ &#039;&#039;unsigned long&#039;&#039;, also &#039;&#039;uint32_t&#039;&#039; verwendet werden, so müssen 4 Bytes reserviert werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
...&lt;br /&gt;
// 4 Byte im RAM für den Zähler reservieren&lt;br /&gt;
.comm zaehler, 4&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die dazugehörige Deklaration im Headerfile wäre dann:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
...&lt;br /&gt;
extern volatile uint32_t zaehler;&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei Variablen, die größer als ein Byte sind, werden die Werte beginnend mit dem niederwertigsten Byte im RAM abgelegt. Das folgende Codeschnippsel zeigt, wie unter Assembler auf die einzelnen Bytes zugegriffen werden kann. Dazu wird im Interrupt nun ein 32-Bit Zähler erhöht:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
temp = 16&lt;br /&gt;
&lt;br /&gt;
// 4 Byte im RAM für den Zähler reservieren&lt;br /&gt;
.comm zaehler, 4&lt;br /&gt;
&lt;br /&gt;
.global INT0_vect&lt;br /&gt;
INT0_vect:&lt;br /&gt;
&lt;br /&gt;
     push temp                      // wichtig: Benutzte Register und das&lt;br /&gt;
     in temp,_SFR_IO_ADDR(SREG)     // Status-Register (SREG) sichern !&lt;br /&gt;
     push temp&lt;br /&gt;
&lt;br /&gt;
     // 32-Bit-Zähler incrementieren&lt;br /&gt;
     lds temp, (zaehler + 0)        // 0. Byte (niederwertigstes Byte)&lt;br /&gt;
     inc temp&lt;br /&gt;
     sts (zaehler + 0), temp&lt;br /&gt;
     brne RAUS&lt;br /&gt;
	&lt;br /&gt;
     lds temp, (zaehler + 1)        // 1. Byte&lt;br /&gt;
     inc temp&lt;br /&gt;
     sts (zaehler + 1), temp&lt;br /&gt;
     brne RAUS&lt;br /&gt;
&lt;br /&gt;
     lds temp, (zaehler + 2)        // 2. Byte&lt;br /&gt;
     inc temp&lt;br /&gt;
     sts (zaehler + 2), temp&lt;br /&gt;
     brne RAUS&lt;br /&gt;
&lt;br /&gt;
     lds temp, (zaehler + 3)        // 3. Byte (höchstwertigstes Byte)&lt;br /&gt;
     inc temp&lt;br /&gt;
     sts (zaehler + 3), temp&lt;br /&gt;
     brne RAUS&lt;br /&gt;
	&lt;br /&gt;
RAUS:&lt;br /&gt;
     pop temp                       // die benutzten Register wiederherstellen&lt;br /&gt;
     out _SFR_IO_ADDR(SREG),temp&lt;br /&gt;
     pop temp&lt;br /&gt;
     reti&lt;br /&gt;
&lt;br /&gt;
.end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Todo ==&lt;br /&gt;
* 16-Bit / 32-Bit Variablen, Zugriff auf Arrays (Strings)&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.rn-wissen.de/index.php/Inline-Assembler_in_avr-gcc Roboternetz: Inline-Assembler in avr-gcc]&lt;br /&gt;
&lt;br /&gt;
=== Englisch ===&lt;br /&gt;
&lt;br /&gt;
; [http://nongnu.org/avr-libc/user-manual/ avr-libc-Manual]:&lt;br /&gt;
* [http://nongnu.org/avr-libc/user-manual/group__asmdemo.html Demo-Projekt: &#039;&#039;&amp;quot;Combining C and assembly source files&amp;quot;&#039;&#039;]&lt;br /&gt;
* [http://www.nongnu.org/avr-libc/user-manual/inline_asm.html Inline-Assembler Cookbook]&lt;br /&gt;
* [https://sourceware.org/binutils/docs/as/ gnu assembler manual]&lt;br /&gt;
; [http://gcc.gnu.org/onlinedocs/gcc/ GCC-Manual]:&lt;br /&gt;
* [http://gcc.gnu.org/onlinedocs/gcc/Explicit-Reg-Vars.html#Explicit-Reg-Vars Variables in Specified Registers]&lt;br /&gt;
* [http://gcc.gnu.org/onlinedocs/gcc/Asm-Labels.html#Asm-Labels Controlling Names Used in Assembler Code]&lt;br /&gt;
; Sonstiges&lt;br /&gt;
*[https://www.microchip.com/wwwAppNotes/AppNotes.aspx?appnote=en591235 Atmel AT1886: Mixing Assembly and C with AVRGCC]&lt;br /&gt;
[[Kategorie:avr-gcc Tutorial]]&lt;/div&gt;</summary>
		<author><name>172.26.37.113</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Statemachine&amp;diff=105132</id>
		<title>Statemachine</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Statemachine&amp;diff=105132"/>
		<updated>2022-04-08T12:17:37Z</updated>

		<summary type="html">&lt;p&gt;172.26.37.113: /* Geschwindigkeitsvergleich */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;==Einleitung==&lt;br /&gt;
&lt;br /&gt;
Bei einem sogenannten [http://de.wikipedia.org/wiki/Finite_State_Machine Endlichen Zustandsautomaten] (engl. &#039;&#039;&#039;f&#039;&#039;&#039;inite &#039;&#039;&#039;s&#039;&#039;&#039;tate &#039;&#039;&#039;m&#039;&#039;&#039;achine, kurz FSM) handelt es sich um die Realisation eines Steuerungskonzeptes, welches eine abstrahierte Maschine zum Vorbild hat, die eine Reihe von Zuständen besitzt, durch die sich ihre Funktion definiert. Diese Maschine arbeitet, indem sie von einem Zustand in einen anderen übergeht und bei den Zustandsübergängen oder dem Verharren in Zuständen bestimmte Aktionen ausführt. Dabei ergibt sich der Folgezustand aus der Kombination des momentanen Zustands und einem externen Ereignis, z. B. einem Tastendruck oder einem Signal aus anderen Bereichen der Software. Dabei wird die Maschine oftmals in verschiedenen Zuständen nur für ganz bestimmte Ereignisse sensibel gemacht.&lt;br /&gt;
&lt;br /&gt;
Die FSM selbst wird immer in irgendeiner Weise über einen Takt angetrieben, kann also nicht in beliebig kurzen Zeitspannen auf Ereignisse reagieren und Zustände wechseln. Der aktive Takt definiert dabei, ob gerade ein Zustandswechsel stattfindet, oder ob in Zuständen verharrt wird. Mit jedem Takt wird anhand des vorliegenden Zustands und dem Status der Eingabekanäle entschieden, welcher Zustand als nächstes vorliegen soll und welche Aktionen dabei auszuführen sind.&lt;br /&gt;
&lt;br /&gt;
Abstrahierte Formen dieser Maschine werden in vielen elektronischen Geräten eingesetzt, um Bedieneraktivitäten und andere Ereignisse im System zu verarbeiten sowie autark ablaufende Prozesse geeignet zu beeinflussen. Entsprechend formulierte FSMs können sowohl in Software auf Prozessoren als auch als eletronische Hardware aufgebaut werden. &lt;br /&gt;
&lt;br /&gt;
Die Beschreibung einer FSM ist auf mehrere Arten möglich. Zum einen kann sie in Form einer Tabelle beschrieben werden, aber auch eine graphische Darstellung der Zustände und deren Abhängigkeiten in Form eines Zustandsdiagramms ist möglich.&lt;br /&gt;
&lt;br /&gt;
==Darstellung von Zustandsautomaten==&lt;br /&gt;
&lt;br /&gt;
Zustandsautomaten haben den großen Charme, dass es meistens leicht möglich ist, ihre Funktion durch eine Grafik zu veranschaulichen.&lt;br /&gt;
&lt;br /&gt;
Beispiel: Es ist eine FSM zu entwerfen, die eine Rollosteuerung übernimmt. Es gibt einen Motor, der sich in 3 Zuständen befinden kann: stop, rauf drehend, runter drehend. Außerdem gibt es Endschalter, welche betätigt werden, wenn das Rollo die jeweilige Endposition erreicht hat. Und es gibt 2 Taster &amp;quot;Up&amp;quot; und &amp;quot;Down&amp;quot; durch welche der Benutzer den Bewegungswunsch an die FSM weitergibt. Irgendwie weiß jeder, wie so eine Rollosteuerung funktioniert, und so recht und schlecht kann das auch jeder in der einen oder anderen Form beschreiben. Aber kann man das ganze auch so &#039;beschreiben&#039;, dass man im Vorfeld, vor der Programmierung tatsächlich alle Eventualitäten erfasst und so darstellt, dass auch ein Nicht-Informatiker die Funktionsweise versteht? Genau an dieser Stelle kommt die graphische Darstellung ins Spiel. &lt;br /&gt;
&lt;br /&gt;
Wie sieht nun eine derartige FSM aus? Jede Wolke im Bild sei ein Zustand, dem man einen Namen gibt. Die Pfeile zwischen den Wolken zeigen die Zustandsübergänge an, wobei am Pfeil vermerkt ist, unter welcher Bedingung dieser Übergang genommen werden kann (in Rot) und welche Aktionen dabei auszuführen sind (in Blau).&lt;br /&gt;
&lt;br /&gt;
[[Datei:StateRollo.jpg|center|framed|Zustandsautomat für eine Rollosteuerung]]&lt;br /&gt;
&lt;br /&gt;
Aus der Zeichnung ist ablesbar:&lt;br /&gt;
Befindet sich die Maschine im Zustand &amp;quot;unten&amp;quot; und wird die Taste &amp;quot;Up&amp;quot; gedrückt, dann folgt als Aktion, daß der Motor auf &amp;quot;rauf drehend&amp;quot; gestellt wird und gleichzeitig wechselt die Maschine in den Zustand &amp;quot;nach oben&amp;quot;. In diesem Zustand verbleibt die Maschine, während der Motor immer weiter dreht, bis der Endschalter meldet, dass das Rollo oben angekommen ist. Dies ist eine Möglichkeit wie die Maschine den Zustand &amp;quot;nach oben&amp;quot; verlassen kann. In diesem Fall wird dann der Motor abgeschaltet und die Maschine wechselt in den Zustand &amp;quot;oben&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Man sieht hier schon, dass es mit so einer Grafik relativ einfach ist, sich von der korrekten Logik zu überzeugen. In einfachsten Fall legt man zur Simulation einfach einen Gegenstand in die betreffende Wolke, die den gerade aktiven Zustand symbolisiert. Danach geht man alle Möglichkeiten durch, wie diese Maschine von aussen (Taster, Schalter, etc) beeinflusst werden kann und sieht sich an, ob es dafür in der Grafik einen Pfeil gibt, der von der aktiven Wolke wegführt. Gibt es keinen, dann passiert auch nichts. Gibt es einen, dann verschiebt man den Gegenstand in die betreffende Wolke und führt (in Gedanken) die Aktion aus. Auf die Art kann man ganz leicht einige typische Benutzerszenarien durchspielen aber auch ausprobieren, ob man alle Eventualitäten berücksichtigt hat. Denn gerade diese Evantualitäten, an die man am Anfang gar nicht denkt, die sind es, die einem in weiterer Folge oft Probleme bereiten.&lt;br /&gt;
&lt;br /&gt;
Um bei der Rollosteuerung zu bleiben: Was soll denn passieren, wenn das Rollo gerade hochfährt und der Benutzer ein weiteres mal auf &amp;quot;Up&amp;quot; drückt? Oder wenn er auf &amp;quot;Down&amp;quot; drückt? In der Grafik ist ersichtlich, wie in diesem Fall zu verfahren ist. (Und Hand aufs Herz: Hätten Sie daran gedacht, dass diese Fälle zu berücksichtigen sind, als sie &#039;Rollosteuerung&#039; gelesen haben?)&lt;br /&gt;
&lt;br /&gt;
==Implementierungsvariationen==&lt;br /&gt;
&lt;br /&gt;
Der konkrete softwaremässige Aufbau einer FSM kann in weiten Grenzen variieren. Das grundlegende Konzept, Aktionen an Zustände zu knüpfen und logische Abläufe an die Abfolge von Zuständen zu binden, bleibt dabei in allen Fällen erhalten. Aber je nach Lust und Laune und dem Können des Programmierers gibt es viele unterschiedliche Möglichkeiten eine FSM zu implementieren. Ziel ist es dabei immer, die eigentliche Maschine, also das was in der Zustandstabelle ausgedrückt wird, so einfach und überschaubar wie möglich zu präsentieren. Sie implementiert die Logik und definiert was die Maschine eigentlich macht und warum sie es macht. Ein einfacher Ansatz ist die Verwendung des C-Konstukts switch, in der in jedem case-zweig die einzelnen Zustände kodiert werden. Es ist aber auch durchaus möglich eine universelle FSM zu bauen, bei denen eine generische Funktion die Tabelle in Arrayform bekommt und zusammen mit einigen globalen Variablen die Maschine implementiert. Oft wird auch eine Statemaschine dadurch gebaut, indem das zentrale switch-case Konstukt der Sprache [C] durch einen einzelnen [[Funktionszeiger in C | Funktionszeiger]] ersetzt wird und jeder Zustand nichts anderes als eine Funktion ist. Der Übergang von einem Zustand in einen anderen Zustand ist dann nichts anderes als das Zuweisen einer Funktion an diesen Funktionszeiger. Oder aber man kombiniert Tabelle und Funktionszeiger in ein gemeinsames Konzept.&lt;br /&gt;
&lt;br /&gt;
==Grundlegender Aufbau==&lt;br /&gt;
&lt;br /&gt;
Im Folgenden wird eine FSM in Software verwirklicht, welche die Ampelsteuerung einer Kreuzung übernimmt.&lt;br /&gt;
[[Bild:Statemachine_Kreuzung.png|center|framed|Ampeln an einer Kreuzung]]&lt;br /&gt;
&lt;br /&gt;
Die Abfolge der Lichtzeichen einer einzelnen Ampel ist dabei&lt;br /&gt;
&amp;lt;br&amp;gt;[[Bild:Statemachine_Ampel.png|center|framed|Zustände einer einzelnen Ampel]]&lt;br /&gt;
&lt;br /&gt;
Die komplette Lichtfolge aller Ampeln in der Kreuzung stellt sich dann wie folgt dar: Es ist dabei ausreichend, nur Ampel 1 und Ampel 2 zu betrachten, da Ampel 3 bzw. Ampel 4 die jeweils gleichen Lichtsignale anzeigen. Dies muss nicht immer so sein! Auf einer Kreuzung kann es durchaus für eine Fahrtrichtung Zusatzampeln geben, die die Lichtfolge der Hauptampel modifizieren.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
{| {{Tabelle|min-width:15em;text-align:center;}}&lt;br /&gt;
|+ &#039;&#039;&#039;Zustandstabelle der Ampelanlage&#039;&#039;&#039;&lt;br /&gt;
|-  style=&amp;quot;background-color:#ffddcc&amp;quot;&lt;br /&gt;
!width=&amp;quot;20%&amp;quot;| Zustand ||width=&amp;quot;20%&amp;quot;| Ampel 1 ||width=&amp;quot;20%&amp;quot;| Ampel 2 ||width=&amp;quot;20%&amp;quot;| nächster&amp;lt;br&amp;gt;Zustand&lt;br /&gt;
|-&lt;br /&gt;
|  1 || rot ||  grün || 2&lt;br /&gt;
|-&lt;br /&gt;
|  2 || rot ||  gelb || 3&lt;br /&gt;
|-&lt;br /&gt;
|  3 || rot ||  rot  || 4&lt;br /&gt;
|-&lt;br /&gt;
|  4 || rot/gelb ||  rot  || 5&lt;br /&gt;
|-&lt;br /&gt;
|  5 || grün ||  rot  || 6&lt;br /&gt;
|-&lt;br /&gt;
|  6 || gelb ||  rot  || 7&lt;br /&gt;
|-&lt;br /&gt;
|  7 || rot ||  rot  || 8&lt;br /&gt;
|-&lt;br /&gt;
|  8 || rot ||  rot/gelb  || 1&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Zustandsnummer ist in diesem Fall einfach die Taktung der FSM. Verfolgt man die Zustände von einem Zustand zum nächsten, dann kann man sich sehr leicht davon überzeugen, daß die Lichtfolge der beiden Ampeln tatsächlich der gewünschten Abfolge entspricht.&lt;br /&gt;
&lt;br /&gt;
Hat man die Funktionalität einer FSM erst mal soweit in Tabellenform festgelegt, dann ist es sehr einfach daraus ein Programm in einer Programmiersprache wie z.B. C abzuleiten, welches diese Statemachine implementiert.&lt;br /&gt;
&lt;br /&gt;
Kochrezeptartig kann man dabei folgenden Aufbau vornehmen:&lt;br /&gt;
* Es gibt eine globale Variable, die den aktuellen Zustand der Maschine repräsentiert. Die Zustände wurden in obiger Tabelle bereits durchnummeriert, so dass es sich anbietet, Zustände innerhalb der Maschine durch ebendiese Zahlen darzustellen.&lt;br /&gt;
* Die FSM wird als Funktion implementiert, die für jeden einzelnen Takt aufgerufen wird.&lt;br /&gt;
* Jeder Zustand wird innerhalb der Funktion durch einen case innerhalb einer  switch Anweisung dargestellt.&lt;br /&gt;
* Jeder Zustand kann vor verlassen der Funktion den aktuellen Zustand der FSM beim nächsten Aufruf der Funktion festlegen, indem er an die globale Variable die Nummer des nächsten Zustands zuweist.&lt;br /&gt;
* Jegliche Form von Warteschleifen innerhalb der FSM sind verboten. Wenn die FSM auf ein Ereignis warten müsste, dann ist dafür ein eigener Zustand vorzusehen, der auf das Eintreten des Ereignisses prüft und nur dann den nächsten Zustand auswählt, wenn das Ereignis tatsächlich eingetreten ist. Damit erreicht man [[Multitasking]].&lt;br /&gt;
* Es ist sinnvoll, den Ampelfarben Namen in Form eines #define oder enums zu geben, damit wird das Konstrukt deutlich leichter lesbar.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define ROT       1&lt;br /&gt;
#define ROT_GELB  2&lt;br /&gt;
#define GRUEN     3&lt;br /&gt;
#define GELB      4&lt;br /&gt;
&lt;br /&gt;
void Ampel1( unsigned char Farbe );  // schaltet Ampel1 auf eine Farbe&lt;br /&gt;
void Ampel2( unsigned char Farbe );  // schaltet Ampel2 auf eine Farbe&lt;br /&gt;
&lt;br /&gt;
unsigned char state = 1;   // globale Variable, die den Status repräsentiert&lt;br /&gt;
&lt;br /&gt;
void stateMachine()&lt;br /&gt;
{&lt;br /&gt;
  switch( state ) {&lt;br /&gt;
    case 1:&lt;br /&gt;
      Ampel1( ROT );&lt;br /&gt;
      Ampel2( GRUEN );&lt;br /&gt;
      state = 2;&lt;br /&gt;
      break;&lt;br /&gt;
&lt;br /&gt;
    case 2:&lt;br /&gt;
      Ampel1( ROT );&lt;br /&gt;
      Ampel2( GELB );&lt;br /&gt;
      state = 3;&lt;br /&gt;
      break;&lt;br /&gt;
&lt;br /&gt;
    case 3:&lt;br /&gt;
      Ampel1( ROT );&lt;br /&gt;
      Ampel2( ROT );&lt;br /&gt;
      state = 4;&lt;br /&gt;
      break;&lt;br /&gt;
&lt;br /&gt;
    case 4:&lt;br /&gt;
      Ampel1( ROT_GELB );&lt;br /&gt;
      Ampel2( ROT );&lt;br /&gt;
      state = 5;&lt;br /&gt;
      break;&lt;br /&gt;
&lt;br /&gt;
    case 5:&lt;br /&gt;
      Ampel1( GRUEN );&lt;br /&gt;
      Ampel2( ROT );&lt;br /&gt;
      state = 6;&lt;br /&gt;
      break;&lt;br /&gt;
&lt;br /&gt;
    case 6:&lt;br /&gt;
      Ampel1( GELB );&lt;br /&gt;
      Ampel2( ROT );&lt;br /&gt;
      state = 7;&lt;br /&gt;
      break;&lt;br /&gt;
&lt;br /&gt;
    case 7:&lt;br /&gt;
      Ampel1( ROT );&lt;br /&gt;
      Ampel2( ROT );&lt;br /&gt;
      state = 8;&lt;br /&gt;
      break;&lt;br /&gt;
&lt;br /&gt;
    case 8:&lt;br /&gt;
      Ampel1( ROT );&lt;br /&gt;
      Ampel2( ROT_GELB );&lt;br /&gt;
      state = 1;&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
  ....&lt;br /&gt;
&lt;br /&gt;
  while( 1 ) {&lt;br /&gt;
    stateMachine();&lt;br /&gt;
    delay_ms( 1000 );&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wird diese Funktion im Sekundentakt aufgerufen, so werden die Funktionen Ampel1() bzw. Ampel2() mit der jeweils richtigen Lichtstellung in der richtigen Reihenfolge aufgerufen um die Lichtwechsel der Ampeln einer Kreuzung zu realisieren. Der Einfachheit halber wird in diesem Beispiel die Funktion delay_ms() verwendet. Praktisch wird man in den meisten Fällen besser einen [[Timer]] benutzen, um die Statemachine periodisch aufzurufen. Wie das geht und was das für Vorteile hat ist im Artikel [[Multitasking#Verbesserter Ansatz mit Timer | Multitasking]] beschrieben.&lt;br /&gt;
&lt;br /&gt;
==Reaktionen auf äußere Ereignisse==&lt;br /&gt;
&lt;br /&gt;
Obige Statemaschine ist noch sehr primitiv. Angenommen an dieser Ampelkreuzung gibt es eine Induktionsschleife. Diese sei derartig geschaltet, dass die Hauptrichtung über Ampel2/Ampel4 ständig Grün zeigt und nur bei Annäherung eines Fahrzeugs auf der Strecke Ampel1/Ampel3 wird ein Lichtwechselzyklus durchgeführt, um diesem Fahrzeug die geordnete Durchfahrt zu ermöglichen. Die Statemaschine muss daher auf ein äußeres Ereignis reagieren können. Der Übergang von Zustand 1 in Zustand 2 ist von diesem Ereignis abhängig. Nur wenn es auftritt wird dieser Übergang durchgeführt, ansonsten verbleibt die Maschine im Zustand 1. Die Beschreibung der FSM wird also um einen weiteren Tabelleneintrag ergänzt, in dem festgehalten wird, wie mit dem zusätzlichen Eingang verfahren werden soll. In dieserm erweiterten Beispiel sollen die Zustände mit einem aussagekräftigen Namen versehen werden, denn Menschen sind sehr schlecht im Umgang mit abstrakten Zahlen, sie sind viel besser mit Wörtern vertraut. Die x in der Tabellenspalte &amp;quot;Induktionsschleife&amp;quot; besagen, daß dieses Eingangsignal für die Entscheidungen der Statemaschine keine Rolle spielt (engl. don&#039;t care).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
{| {{Tabelle|min-width:50em;text-align:center;}}&lt;br /&gt;
|+ &#039;&#039;&#039;Zustandstabelle der Ampelanlage mit zusätzlichem Eingang&#039;&#039;&#039;&lt;br /&gt;
|-  style=&amp;quot;background-color:#ffddcc&amp;quot;&lt;br /&gt;
!| Zustand ||| Name ||| Ampel 1 || | Ampel 2 ||  Induktionsschleife || | nächster&amp;lt;br&amp;gt;Zustand&lt;br /&gt;
|-&lt;br /&gt;
|  1 || OSTWEST_GRUEN      || rot     ||  grün      || ==1 ? || 2&lt;br /&gt;
|-&lt;br /&gt;
|  2 || OSTWEST_GELB       || rot     ||  gelb      || x ||3&lt;br /&gt;
|-&lt;br /&gt;
|  3 || ALLE_ROT_1         || rot     ||  rot       || x || 4&lt;br /&gt;
|-&lt;br /&gt;
|  4 || NORDSUED_ROTGELB   ||rot/gelb ||  rot       || x || 5&lt;br /&gt;
|-&lt;br /&gt;
|  5 || NORDSUED_GRUEN     || grün    ||  rot       || x || 6&lt;br /&gt;
|-&lt;br /&gt;
|  6 || NORDSUED_GELB      || gelb    ||  rot       || x || 7&lt;br /&gt;
|-&lt;br /&gt;
|  7 || ALLE_ROT_2         || rot     ||  rot       || x || 8&lt;br /&gt;
|-&lt;br /&gt;
|  8 || OSTWEST_ROTGELB    || rot     ||  rot/gelb  || x || 1&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define ROT       1&lt;br /&gt;
#define ROT_GELB  2&lt;br /&gt;
#define GRUEN     3&lt;br /&gt;
#define GELB      4&lt;br /&gt;
 &lt;br /&gt;
void Ampel1( unsigned char Farbe );   // schaltet Ampel1 auf eine Farbe&lt;br /&gt;
void Ampel2( unsigned char Farbe );   // schaltet Ampel2 auf eine Farbe&lt;br /&gt;
unsigned char Induktionsschleife();   // fragt die Induktionsschleife ab&lt;br /&gt;
typedef enum { NORDSUED_ROTGELB, NORDSUED_GRUEN, NORDSUED_GELB, ALLE_ROT_1,&lt;br /&gt;
               OSTWEST_ROTGELB, OSTWEST_GRUEN, OSTWEST_GELB, ALLE_ROT_2} state_t ;&lt;br /&gt;
&lt;br /&gt;
state_t state = ALLE_ROT_1;&lt;br /&gt;
 &lt;br /&gt;
void stateMachine()&lt;br /&gt;
{&lt;br /&gt;
  switch( state ) {&lt;br /&gt;
    case OSTWEST_GRUEN:&lt;br /&gt;
      Ampel1( ROT );&lt;br /&gt;
      Ampel2( GRUEN );&lt;br /&gt;
      if( Induktionsschleife() ) {&lt;br /&gt;
        state = OSTWEST_GELB;&lt;br /&gt;
      }&lt;br /&gt;
      break;&lt;br /&gt;
 &lt;br /&gt;
    case OSTWEST_GELB:&lt;br /&gt;
      Ampel1( ROT );&lt;br /&gt;
      Ampel2( GELB );&lt;br /&gt;
      state = ALLE_ROT_1;&lt;br /&gt;
      break;&lt;br /&gt;
 &lt;br /&gt;
    case ALLE_ROT_1:&lt;br /&gt;
      Ampel1( ROT );&lt;br /&gt;
      Ampel2( ROT );&lt;br /&gt;
      state = NORDSUED_ROTGELB;&lt;br /&gt;
      break;&lt;br /&gt;
 &lt;br /&gt;
    case NORDSUED_ROTGELB:&lt;br /&gt;
      Ampel1( ROT_GELB );&lt;br /&gt;
      Ampel2( ROT );&lt;br /&gt;
      state = NORDSUED_GRUEN;&lt;br /&gt;
      break;&lt;br /&gt;
 &lt;br /&gt;
    case NORDSUED_GRUEN:&lt;br /&gt;
      Ampel1( GRUEN );&lt;br /&gt;
      Ampel2( ROT );&lt;br /&gt;
      state = NORDSUED_GELB;&lt;br /&gt;
      break;&lt;br /&gt;
 &lt;br /&gt;
    case NORDSUED_GELB:&lt;br /&gt;
      Ampel1( GELB );&lt;br /&gt;
      Ampel2( ROT );&lt;br /&gt;
      state = ALLES_ROT_2;&lt;br /&gt;
      break;&lt;br /&gt;
 &lt;br /&gt;
    case ALLES_ROT_2:&lt;br /&gt;
      Ampel1( ROT );&lt;br /&gt;
      Ampel2( ROT );&lt;br /&gt;
      state = OSTWEST_ROTGELB;&lt;br /&gt;
      break;&lt;br /&gt;
 &lt;br /&gt;
    case OSTWEST_ROTGELB:&lt;br /&gt;
      Ampel1( ROT );&lt;br /&gt;
      Ampel2( ROT_GELB );&lt;br /&gt;
      state = OSTWEST_GRUEN;&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Warteschleifen==&lt;br /&gt;
&lt;br /&gt;
Das Warten auf ein äußeres Ereignis kann mit dem Verzweigen oder auch nicht Verzweigen in einen anderen Zustand realisiert werden. In obiger Statemaschine soll z.B. die Grünphase der Ampel1 von einem Takt auf 5 Takte angehoben werden. Grundfalsch wäre es, dies jetzt mit einer while-Schleife im Zustand 5 zu realisieren. Warten wird immer über zusätzliche Zustände realisiert. Eine Statemaschine darf innerhalb eines Zustands niemals auf etwas warten, sondern muss so schnell als möglich die Kontrolle wieder abgeben. Geht man naiv an die Sache ran, dann könnte man die 5 Takte über die Einführung von zusätzlichen Zuständen leicht erreichen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
{| {{Tabelle|min-width:35em;text-align:center;}}&lt;br /&gt;
|+ &#039;&#039;&#039;Zustandstabelle der Ampelanlage mit zusätzlichem Eingang&#039;&#039;&#039;&lt;br /&gt;
|-  style=&amp;quot;background-color:#ffddcc&amp;quot;&lt;br /&gt;
!width=&amp;quot;20%&amp;quot;| Zustand ||width=&amp;quot;20%&amp;quot;| Ampel 1 ||width=&amp;quot;20%&amp;quot;| Ampel 2 ||width=&amp;quot;20%&amp;quot;| Induktions-&amp;lt;br&amp;gt;schleife ||width=&amp;quot;20%&amp;quot;| nächster&amp;lt;br&amp;gt;Zustand&lt;br /&gt;
|-&lt;br /&gt;
|  1 || rot ||  grün || ==1? || 2&lt;br /&gt;
|-&lt;br /&gt;
|  2 || rot ||  gelb || x ||3&lt;br /&gt;
|-&lt;br /&gt;
|  3 || rot ||  rot  || x || 4&lt;br /&gt;
|-&lt;br /&gt;
|  4 || rot/gelb ||  rot  || x || 5&lt;br /&gt;
|-&lt;br /&gt;
|  5 || grün ||  rot  || x || 9&lt;br /&gt;
|-&lt;br /&gt;
|  6 || gelb ||  rot  || x || 7&lt;br /&gt;
|-&lt;br /&gt;
|  7 || rot ||  rot  || x || 8&lt;br /&gt;
|-&lt;br /&gt;
|  8 || rot ||  rot/gelb  || x || 1&lt;br /&gt;
|-&lt;br /&gt;
|  9 || grün ||  rot  || x || 10&lt;br /&gt;
|-&lt;br /&gt;
| 10 || grün ||  rot  || x || 11&lt;br /&gt;
|-&lt;br /&gt;
| 11 || grün ||  rot  || x || 12&lt;br /&gt;
|-&lt;br /&gt;
| 12 || grün ||  rot  || x || 6&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Daß ein derartiges Vorgehen bei längeren Wartezeiten oder gar bei berechneter Wartezeitdauer nicht praktikabel ist, dürfte auf der Hand liegen. Besser ist daher die Einführung eines internen Zählers sowie nur eines einzigen, neuen Wartezustands. Beginnt die Wartezeit wird der Zähler auf einen Wert entsprechend der Wartezeit gestellt. Im neuen Zustand wird der Zähler um 1 verringert und nur dann, wenn der Zähler 0 erreicht hat, wird in den ursprünglichen Folgezustand gewechselt. Der Zähler kann also in ähnlicher Form wie die Induktionsschleife als Ereignislieferant aufgefasst werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
{| {{Tabelle|width:40em; text-align:center;}}&lt;br /&gt;
|+ &#039;&#039;&#039;Zustandstabelle der Ampelanlage mit zusätzlichem Eingang&#039;&#039;&#039;&lt;br /&gt;
|-  style=&amp;quot;background-color:#ffddcc&amp;quot;&lt;br /&gt;
! width=&amp;quot;17%&amp;quot; | Zustand&lt;br /&gt;
! width=&amp;quot;17%&amp;quot; | Ampel 1&lt;br /&gt;
! width=&amp;quot;17%&amp;quot; | Ampel 2&lt;br /&gt;
! width=&amp;quot;20%&amp;quot; | Induktions-&amp;lt;br&amp;gt;schleife&lt;br /&gt;
! width=&amp;quot;15%&amp;quot; | Wartezeit&lt;br /&gt;
! nächster&amp;lt;br&amp;gt;Zustand&lt;br /&gt;
|-&lt;br /&gt;
|  1 || rot ||  grün || ==1 ? || x || 2&lt;br /&gt;
|-&lt;br /&gt;
|  2 || rot ||  gelb || x || x || 3&lt;br /&gt;
|-&lt;br /&gt;
|  3 || rot ||  rot  || x || x || 4&lt;br /&gt;
|-&lt;br /&gt;
|  4 || rot/gelb ||  rot  || x || x || 5&lt;br /&gt;
|-&lt;br /&gt;
|  5 || grün ||  rot  || x || =4 || 9&lt;br /&gt;
|-&lt;br /&gt;
|  6 || gelb ||  rot  || x || x || 7&lt;br /&gt;
|-&lt;br /&gt;
|  7 || rot ||  rot  || x || x || 8&lt;br /&gt;
|-&lt;br /&gt;
|  8 || rot ||  rot/gelb  || x || x || 1&lt;br /&gt;
|-&lt;br /&gt;
|  9 || x ||  x  || x || dec / ==0 ? || 6&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define ROT       1&lt;br /&gt;
#define ROT_GELB  2&lt;br /&gt;
#define GRUEN     3&lt;br /&gt;
#define GELB      4&lt;br /&gt;
&lt;br /&gt;
void Ampel1( unsigned char Farbe );   // schaltet Ampel1 auf eine Farbe&lt;br /&gt;
void Ampel2( unsigned char Farbe );   // schaltet Ampel2 auf eine Farbe&lt;br /&gt;
unsigned char Induktionsschleife();   // fragt die Induktionsschleife ab&lt;br /&gt;
typedef enum { NORDSUED_ROTGELB, NORDSUED_GRUEN, NORDSUED_GELB,&lt;br /&gt;
               ALLE_ROT_1,&lt;br /&gt;
               OSTWEST_ROTGELB, OSTWEST_GRUEN, OSTWEST_GELB,&lt;br /&gt;
               ALLE_ROT_2, WARTE_NORDSUED}  state_t;&lt;br /&gt;
 &lt;br /&gt;
state_t state = ALLE_ROT_1;&lt;br /&gt;
unsigned char zaehler;&lt;br /&gt;
 &lt;br /&gt;
void stateMachine()&lt;br /&gt;
{&lt;br /&gt;
  switch( state ) {&lt;br /&gt;
    case OSTWEST_GRUEN:&lt;br /&gt;
      Ampel1( ROT );&lt;br /&gt;
      Ampel2( GRUEN );&lt;br /&gt;
      if( Induktionsschleife() ) {&lt;br /&gt;
        state = OSTWEST_GELB;&lt;br /&gt;
      }&lt;br /&gt;
      break;&lt;br /&gt;
 &lt;br /&gt;
    case OSTWEST_GELB:&lt;br /&gt;
      Ampel1( ROT );&lt;br /&gt;
      Ampel2( GELB );&lt;br /&gt;
      state = ALLES_ROT_1;&lt;br /&gt;
      break;&lt;br /&gt;
 &lt;br /&gt;
    case ALLES_ROT_1:&lt;br /&gt;
      Ampel1( ROT );&lt;br /&gt;
      Ampel2( ROT );&lt;br /&gt;
      state = NORDSUED_ROTGELB;&lt;br /&gt;
      break;&lt;br /&gt;
 &lt;br /&gt;
    case NORDSUED_ROTGELB:&lt;br /&gt;
      Ampel1( ROT_GELB );&lt;br /&gt;
      Ampel2( ROT );&lt;br /&gt;
      state = NORDSUED_GRUEN;&lt;br /&gt;
      break;&lt;br /&gt;
 &lt;br /&gt;
    case NORDSUED_GRUEN:&lt;br /&gt;
      Ampel1( GRUEN );&lt;br /&gt;
      Ampel2( ROT );&lt;br /&gt;
      zaehler = 4;&lt;br /&gt;
      state = WARTE_NORDSUED;&lt;br /&gt;
      break;&lt;br /&gt;
 &lt;br /&gt;
    case NORDSUED_GELB:&lt;br /&gt;
      Ampel1( GELB );&lt;br /&gt;
      Ampel2( ROT );&lt;br /&gt;
      state = ALLES_ROT_2;&lt;br /&gt;
      break;&lt;br /&gt;
 &lt;br /&gt;
    case ALLES_ROT_2:&lt;br /&gt;
      Ampel1( ROT );&lt;br /&gt;
      Ampel2( ROT );&lt;br /&gt;
      state = OSTWEST_ROTGELB;&lt;br /&gt;
      break;&lt;br /&gt;
 &lt;br /&gt;
    case OSTWEST_ROTGELB:&lt;br /&gt;
      Ampel1( ROT );&lt;br /&gt;
      Ampel2( ROT_GELB );&lt;br /&gt;
      state = OSTWEST_GRUEN;&lt;br /&gt;
      break;&lt;br /&gt;
&lt;br /&gt;
    case WARTE_NORDSUED:&lt;br /&gt;
      zaehler = zaehler - 1;&lt;br /&gt;
      if( zaehler == 0 )&lt;br /&gt;
        state = NORDSUED_GELB;&lt;br /&gt;
      break;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Umsetzung in Tabellenform ==&lt;br /&gt;
&lt;br /&gt;
Im letzten Beispiel wollen wir die Ampelsteuerung noch etwas realistischer gestalten. Denn die einzelnen Phasen sind unterschiedlich lang, der Zustand Gelb ist deutlich kürzer als der Zustand Grün. Wenn wir also in fast jedem Zustand eine bestimmte Anzahl Takte warten wollen, erscheint es nicht sinnvoll, dafür jedesmal einen neuen Zustand anzuspringen. Sinnvoller ist die Integration des Wartens direkt in den Zustand, so wie im vorherigen Beispiel der Zustand &amp;quot;WARTE_NORDSUED&amp;quot;. Dabei fallen jedoch zwei Sachen auf.&lt;br /&gt;
&lt;br /&gt;
* In jedem Zustand muss die Wartezeit des &#039;&#039;nächsten&#039;&#039; Zustands zugewiesen werden. Das ist etwas verwirrend.&lt;br /&gt;
* Fast alle Anweisungen sind gleich in den Zuständen, nur die Zahlen und der Wert für den nächsten Zustand ändern sich.&lt;br /&gt;
&lt;br /&gt;
Darum soll hier die FSM von einer großen switch Anweisung auf eine Tabelle geändert werden. Das hat den Vorteil, dass die Zustandstabelle nahezu 1:1 in den Quelltext geschrieben werden kann und sie so sehr kompakt und übersichtlich ist. Die eigentliche FSM wird sehr klein und arbeitet sich durch die Tabelle durch. Zur weiteren Verbesserung der Lesbarkeit (siehe [[Strukturierte Programmierung auf Mikrocontrollern]]) nutzen wir einen Struct, welche den Zustand der State machine mit sinnvollen Variablennamen beschreibt. Bei dieser Methode muss man beachten, dass die Reihenfolge der Zustände in der enum Definition gleich sein muss mit der Reihenfolge der Zustände in der Tabelle, sonst funktioniert es nicht. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define ROT       1&lt;br /&gt;
#define GRUEN     2&lt;br /&gt;
#define GELB      4&lt;br /&gt;
#define ROTGELB   5&lt;br /&gt;
 &lt;br /&gt;
void Ampel1( unsigned char Farbe );   // schaltet Ampel1 auf eine Farbe&lt;br /&gt;
void Ampel2( unsigned char Farbe );   // schaltet Ampel2 auf eine Farbe&lt;br /&gt;
int Induktionsschleife();   // fragt die Induktionsschleife ab&lt;br /&gt;
 &lt;br /&gt;
typedef enum { OSTWEST_GRUEN=0, OSTWEST_GELB, ALLE_ROT_1,&lt;br /&gt;
               NORDSUED_ROTGELB, NORDSUED_GRUEN, NORDSUED_GELB, ALLE_ROT_2,&lt;br /&gt;
               OSTWEST_ROTGELB }  state_t;&lt;br /&gt;
&lt;br /&gt;
typedef struct {&lt;br /&gt;
    int Ampel1;&lt;br /&gt;
    int Ampel2;&lt;br /&gt;
    int I_Schleife;&lt;br /&gt;
    int Wartezeit;&lt;br /&gt;
    int Naechster;&lt;br /&gt;
} ampel_state_t;&lt;br /&gt;
&lt;br /&gt;
state_t state = ALLE_ROT_1;&lt;br /&gt;
int zaehler=1;&lt;br /&gt;
 &lt;br /&gt;
// Tabelle fuer state machine&lt;br /&gt;
 &lt;br /&gt;
ampel_state_t state_table[8] = {&lt;br /&gt;
 &lt;br /&gt;
// AMPEL1 AMPEL2   Induktionsschleife ? &lt;br /&gt;
// |         |       |   Wartezeit in s&lt;br /&gt;
// |         |       |   |&lt;br /&gt;
// |         |       |   |   naechster Zustand     Name&lt;br /&gt;
//----------------------------------------------------------------------&lt;br /&gt;
{ROT     , GRUEN   , 1, 10,  OSTWEST_GELB},        // OSTWEST_GRUEN&lt;br /&gt;
{ROT     , GELB    , 0,  1,  ALLE_ROT_1},          // OSTWEST_GELB&lt;br /&gt;
{ROT     , ROT     , 0,  3,  NORDSUED_ROTGELB},    // ALLE_ROT_1&lt;br /&gt;
{ROTGELB , ROT     , 0,  1,  NORDSUED_GRUEN},      // NORDSUED_ROTGELB&lt;br /&gt;
{GRUEN   , ROT     , 0, 10,  NORDSUED_GELB},       // NORDSUED_GRUEN&lt;br /&gt;
{GELB    , ROT     , 0,  1,  ALLE_ROT_2},          // NORDSUED_GELB&lt;br /&gt;
{ROT     , ROT     , 0,  3,  OSTWEST_ROTGELB},     // ALLE_ROT_2&lt;br /&gt;
{ROT     , ROTGELB , 0,  1,  OSTWEST_GRUEN}};      // OSTWEST_ROTGELB&lt;br /&gt;
 &lt;br /&gt;
void stateMachine()&lt;br /&gt;
{&lt;br /&gt;
    Ampel1(state_table[state].Ampel1);&lt;br /&gt;
    Ampel2(state_table[state].Ampel2);&lt;br /&gt;
 &lt;br /&gt;
    if (zaehler&amp;gt;0) {&lt;br /&gt;
        zaehler--;    &lt;br /&gt;
    } else {&lt;br /&gt;
        if ( ((state_table[state].I_Schleife == 1) &amp;amp;&amp;amp; Induktionsschleife() ) ||&lt;br /&gt;
             (state_table[state].I_Schleife == 0) )&lt;br /&gt;
        {&lt;br /&gt;
            state =   state_table[state].Naechster;&lt;br /&gt;
            zaehler = state_table[state].Wartezeit;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Implementierung einer objektorientierten Finite State Machine in C++==&lt;br /&gt;
&lt;br /&gt;
* Notation von Endlichen Automaten in UML&lt;br /&gt;
* Praktisches Beispiel, anhand dessen die Funktionsweise eines Toasters erklärt wird. Dazu wird die Notation in UML verwendet. &lt;br /&gt;
* Implementation des Beispiels in C++ auf einem AVR-Controller&lt;br /&gt;
&lt;br /&gt;
Die gezeigte Möglichkeit bzw. das Beispiel sollte als Denkanstoss verstanden werden und nicht als Referenzimplementation. Es wurden bewusst bestimmte Feinheiten von endlichen Automaten verzichtet, um das Beispiel auf gut verständlichem Niveau zu halten. &lt;br /&gt;
&lt;br /&gt;
* Dokumentation im PDF Format [http://www.mikrocontroller.net/attachment/137066/ImplementierungEinerFiniteStateMachine_V1.1.pdf ImplementierungEinerFiniteStateMachine_V1.1.pdf]&lt;br /&gt;
* LaTeX Source der Dokumentation [http://www.mikrocontroller.net/attachment/137067/Dokumentation_Source_V1.1.zip Dokumentation_Source_V1.1.zip]&lt;br /&gt;
* Beispielcode für AVR-Studio 4 [http://www.mikrocontroller.net/attachment/135434/AVR_Beispiel_Source.zip AVR_Beispiel_Source.zip]&lt;br /&gt;
&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/248837#2556592 Forumsbeitrag]: Eine objektorientierte State Machine in C++&lt;br /&gt;
&lt;br /&gt;
== Grafische Modellierung einer Finite State Machine ==&lt;br /&gt;
Das Open Source Werkzeug Yakindu Statechart Tools (http://www.statecharts.org) ermöglicht es Zustandsautomaten grafisch zu modellieren, deren Verhalten zu simulieren und Code für verschiedene Sprachen (C/C++, Java) zu generieren.&lt;br /&gt;
Die grafischen Modellelemente entsprechen denen der UML2 und werden durch eine einfache und zweckmäßige Expression-Language ergänzt.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Einfaches Ampel Modell&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Das Modell einer einfachen Ampel wie oben beschrieben sieht in Yakindu SCT wie folgt aus: &lt;br /&gt;
&lt;br /&gt;
[[Datei:Sct_beispiel1.jpg|center|framed|Einfaches Ampel Modell]]&lt;br /&gt;
&lt;br /&gt;
Wie erwartet hat die Ampel vier Zustände, die wiederum mit Übergangs-Pfeilen (Transitionen) verbunden sind. Jede Transition verfügt über einen Auslöser, in diesem Fall mit dem Namen &#039;&#039;tick&#039;&#039;    &lt;br /&gt;
Mit Hilfe der Yakindu DSL wird im linken Teil des Editors ein internes Event mit dem Name &amp;quot;tick&amp;quot; definiert, das entsprechend der Taktung des Zustandsautomaten &amp;quot;gefeuert&amp;quot; werden soll. Der Ausdruck &#039;&#039;every 1s / raise tick&#039;&#039; sorgt dafür, dass das Event &#039;&#039;tick&#039;&#039; jede Sekunde einmal gefeuert wird.&lt;br /&gt;
Da Yakindu SCT es erlaubt Zustandsautomaten zu simulieren, ist es jederzeit überprüfbar ob das modellierte Verhalten den Erwartungen entspricht. Über &#039;&#039;Run as... --&amp;gt; YAKINDU Statechart&#039;&#039; lässt sich in die &#039;&#039;Simulation View&#039;&#039; wechseln. Der jeweils aktive Zustand wird nun rot hinterlegt.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Sct_beispiel1b.jpg|center|framed|Simulation View]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Einfache Kreuzung mit Zwei Ampel-Gruppen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Im zweiten Beispiel soll eine einfache Ampelkreuzung modelliert werden. Es wird davon ausgegangen, dass die Ampeln in zwei Gruppen geschaltet werden. Ampel 1 und 3 bilden die nord_süd – Gruppe, während die übrigen Ampeln die ost-west – Gruppe bilden. Der Einfachheit halber werden Ampeln einer Gruppe immer gleich geschaltet. Wie oben darf eine Ampel-Gruppe nur dann den Zustand &#039;&#039;rot&#039;&#039; verlassen, wenn die jeweils andere Gruppe sich im Zustand &#039;&#039;rot&#039;&#039; befindet. &lt;br /&gt;
&lt;br /&gt;
[[Datei:Sct_beispiel2.jpg|800px|center|Ampelkreuzung]]&lt;br /&gt;
&lt;br /&gt;
Im Yakindu SCT Modell gibt es nun für jede Ampel-Gruppe eine eigene Region. Wird der Zustandsautomat betreten so wird nun parallel der Zustand &#039;&#039;rot&#039;&#039; in der &#039;&#039;nord_sued&#039;&#039; Region und der Zustand &#039;&#039;gruen&#039;&#039; in der &#039;&#039;ost_west&#039;&#039; Region aktiv. Wie bereits im ersten Beispiel wird der Zustandsautomat über das &#039;&#039;tick&#039;&#039; Ereignis angetrieben, das jede Sekunde einmal auftritt. &lt;br /&gt;
Um das gewünschte Ampel-Verhalten zu modellieren wird nun die Transition von &#039;&#039;rot&#039;&#039; zu &#039;&#039;rot-gelb&#039;&#039; mit einem &#039;&#039;Guard&#039;&#039;, also einer Bedingung geschützt. Zwar wird der Übergang weiterhin mit dem Ereignis &#039;&#039;tick&#039;&#039; angestoßen, allerdings wird der Übergang nur ausgeführt wenn die in eckigen Klammern formulierte Boolesche-Bedingung erfüllt ist. Die Funktion &#039;&#039;active()&#039;&#039; gehört zu den Bordmitteln von Yakindu SCT und prüft ob ein bestimmter Zustand aktiv ist. In diesem Beispiel kann in der Region &#039;&#039;nord_sued&#039;&#039; der Zustand &#039;&#039;rot&#039;&#039; nur verlassen werden, wenn in der Region &#039;&#039;ost-west&#039;&#039; der Zustand &#039;&#039;rot&#039;&#039; aktiv ist. Wie auch im vorhergegangenen Beispiel lässt sich das Verhalten simulieren, so das überprüft werden kann ob das Verhalten den Erwartungen entspricht.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ampel mit Induktionsschleife&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Das Verhalten der Ampelanlage aus Beispiel 2 soll um eine Induktionsschleife erweitert werden. Der Verkehr an der Ampelanlage fließt normalerweise in &#039;&#039;ost_west&#039;&#039; – Richtung, daher die Ampel in dieser Richtung immer den Zustand &#039;&#039;grün&#039;&#039; haben, es sei denn die Induktionsschleife in &#039;&#039;nord-süd&#039;&#039; - Richtung wird ausgelöst.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Sct_beispiel3.jpg|800px|center|Ampelkreuzung mit Induktionsschleife]]&lt;br /&gt;
&lt;br /&gt;
Um dieses Verhalten in das SCT-Modell zu integrieren muss zunächst ein neues Ereignis definiert werden. Dieses Ereignis wird als Teil des &#039;&#039;Interface-Scopes&#039;&#039; definiert, da es außerhalb des Zustandsautomaten erzeugt werden soll. Ereignisse die Teil einer externen Schnittstelle sind werden mit einer Richtung (in / out) deklariert, die angibt ob das Ereignis den Zustandsautomat betritt, oder verlässt. &lt;br /&gt;
&lt;br /&gt;
Nach dem das neue Ereignis definiert ist,  muss nur noch der Auslöser für den Übergang von &#039;&#039;gruen&#039;&#039; zu &#039;&#039;gelb&#039;&#039; geändert werden. Statt wie bisher durch das &#039;&#039;tick&#039;&#039; Event, wird nun das &#039;&#039;induktionsSignal&#039;&#039; als Auslöser verwendet. In der Simulations-Ansicht kann das neue Ereignis manuell mit einem Klick ausgelöst werden, so dass das korrekte Verhalten wieder getestet werden kann.   &lt;br /&gt;
&lt;br /&gt;
[[Datei:Sct_simView.jpg|center|framed|Induktionsschleife auslösen]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Warteschleife&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Es soll die Grün-Phase verlängert werden, so dass erst nach dem 5. &#039;&#039;tick&#039;&#039; der Übergang in den &#039;&#039;gelb&#039;&#039; Zustand erfolgt.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Sct beispiel4.jpg|800px|center|Ampelkreuzung mit Warteschleife]]&lt;br /&gt;
&lt;br /&gt;
Um eine Warteschleife zu realisieren wird dem &#039;&#039;Internal-Scope&#039;&#039; zuerst eine neue Variable hinzugefügt. Da während des Wartens der &#039;&#039;grün&#039;&#039; Zustand nicht verlassen wird, lässt sich das Herunterzählen der Wartezeit mittels eines zusammengesetzten Zustands darstellen. Wird der Zustand &#039;&#039;grün&#039;&#039; betreten, wird zunächst einen Eintritts-Aktion ausgeführt, die den Wert von &#039;&#039;wartezeit&#039;&#039; auf 5 setzt. Außerdem wird ebenfalls der Zustand &#039;&#039;Warten&#039;&#039; aktiv. Erfolgt nun ein &#039;&#039;tick&#039;&#039; wird ohne &#039;&#039;grün&#039;&#039; zu verlassen in &#039;&#039;WartezeitVerringern&#039;&#039; gewechselt und der Wert von &#039;&#039;wartezeit&#039;&#039; um 1 verringert. &lt;br /&gt;
Der Übergang zu &#039;&#039;gelb&#039;&#039; ist wieder durch einen Guard geschützt und kann nur erfolgen wenn die  Bedingung &#039;&#039;wartezeit == 0&#039;&#039; erfüllt ist.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;C-Code aus dem Modell generieren&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Um nun Code aus dem Modell zu generieren muss zuerst eine GeneratorModel-Datei erzeugt werden, in der unter anderem die Ziel-Sprache angegeben wird.&lt;br /&gt;
Um den Zustandsautomaten abzubilden verwendet die konkrete Implementierung ein &#039;&#039;switch case&#039;&#039; Konstrukt, das dem oben Gezeigten ähnelt. Außerdem wurde ein &#039;&#039;code-only&#039;&#039; Ansatz verfolgt, so dass keine externen Bibliotheken oder Frameworks benötigt werden. Das komplette Eclipse Projekt kann [http://statecharts.org/Examples/ampel.zip hier] runtergeladen werden.&lt;br /&gt;
&lt;br /&gt;
== Realisation von FSMs in Hardware ==&lt;br /&gt;
=== Aufbau einer FSM in digitalen Chips ===&lt;br /&gt;
&lt;br /&gt;
Sollen sehr schnelle Steuerungen und Entscheider aufgebaut werden, wurden und werden digitale Bausteine mit Logikgattern verdrahtet, die steuerbare Zähler enthalten. Damit lassen sich effektive Taktgeschwindigkeiten im Bereich von mehreren MHz erreichen, die in Sicherheitsbereichen eingesetzt werden. Oft werden solche Schaltungen auch zur Überwachung von anderen Schaltungsteilen eingesetzt.&lt;br /&gt;
&lt;br /&gt;
Früher wurden fast alle logischen Schaltungen auf diese Weise entworfen, z.B. auch die ersten Computer von IBM.&lt;br /&gt;
&lt;br /&gt;
=== Umsetzung von FSMs in programmierbarer Hardware ===&lt;br /&gt;
&lt;br /&gt;
Da heute digitale Hardware vielfach in Form von programmierter PLD- und [[FPGA]]-Bausteine realisiert ist, gleicht der Entwurfsprozess der FSMs dem in der klassischen Softwareentwicklung. Dabei besteht je nach Vorliegen der funktionellen Beschreibung und anderer Randbedingungen die Möglichkeit, ein Abbild der digitalen Schaltung in VHDL zu formulieren und zu importieren, bzw. ein klassisches state diagram neu zu entwerfen oder die Zustandswechsel in Tabellenform zu importieren und das Erzeugerwerkzeug die FSM generieren zu lassen, was besonders bei umfangreichen FMSs praktiziert wird.&lt;br /&gt;
&lt;br /&gt;
Letztendlich kann in Hardware jede sequentielle Logikschaltung, welche [[FlipFlop]]s und Dekoder enthält als FSM betrachtet werden, egal ob es ein einfaches Schieberegister oder eine komplexe ALU einer CPU ist. Die einfachste, denkbare FSM ist ein Toggle-FlipFlop, welches mit jedem Takt seinen Ausgangszustand wechselt.&lt;br /&gt;
&lt;br /&gt;
== Geschwindigkeitsvergleich ==&lt;br /&gt;
* In Software realisierte state machines erreichen unter C++ auf Windows-PCs trotz hoher Prozessorleistung selten niedrigere Reaktionszeiten als im Millisekundenbereich. Die damit in Echtzeit erfassbaren und prozessierbaren externen Ereignisse bewegen sich üblicherweise im Bereich von einigen 100Hz. Ein Extrembeispiel ist der USB-3.0-Bus im Zusammenspiel mit HW-IO-Karten: Die Bandbreite lässt ein Laden von Daten mit über 3Gbit im streaming-Modus zu, während im Regelungsbetrieb in der Schleife typische Latenzen von bis zu 10ms auftreten, bis die Reaktion der PC-Software auf eine äußeree Signaländerung auch ausgegeben wurde&lt;br /&gt;
* Mit einem Echtzeitbetriebssystem auf einem PC, z. B. Linux mit Preempt-RT Patch, werden ungefähr 35 µs Zykluszeit erreicht, also circa 30 kHz. Trotz des stark verbesserten Treiberssystems unter Linux sind auf PCs auch hier mehrere Millisekunden Latenz zu beobachten.&lt;br /&gt;
* Mit Microcontrollern und DSPs erreicht man mit Nicht-Multi-tasking-FSMs Abtastraten bis einige 100kHz. Mit Assembler programmierte Signalprozessoren erreichen Abtastraten bis hin zu 20% ihrer Taktfrequenz, wenn sie direkt auf externe Port-Pins zugreifen.&lt;br /&gt;
* In VHDL realisierte state machines besitzen je nach FPGA-Familie, Art der Codierung typische Taktfrequenzen von bis zu 400MHz. Je nach Zyklustiefe laufen damit realisierte FSMs auf bis zu 100MHz und anders als bei DSPs und PCs senkt die Hinzunahme weiterer FMSs nicht deren Schleifen-Frequenz.&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.aqdi.com/state.htm Using State Machines In Your Designs] (C) 2003 Hank Wallace&lt;br /&gt;
* [http://qfsm.sourceforge.net/ Qfsm] - A graphical tool for designing finite state machines (GPL)&lt;br /&gt;
* [https://www.itemis.com/en/yakindu/statechart-tools/ YAKINDU Statechart Tools] Ein Werkzeug zum Modellieren und Simulieren von Statecharts sowie Code-Generatoren für Java, C und C++. &lt;br /&gt;
* [http://www.sinelabore.com www.sinelabore.com] Ein Werkzeug das aus UML State Machines C-Code speziell für eingebettete Systeme erzeugt.&lt;br /&gt;
* [http://smc.sourceforge.net SMC The State Machine Compiler]&lt;br /&gt;
* [http://block-net.de/Programmierung/cpp/fsm/fsm.html C/C++ event driven FSM] Open source Werkzeug zur Generierung von C++ FSM Code und UML Diagramm mittels Transitionstabelle. &lt;br /&gt;
* http://astade.tigris.org/ -&amp;gt; http://wiki.astade.de/dokuwiki/doku.php (https://www.mikrocontroller.net/search?query=astade)&lt;br /&gt;
* [http://stefanfrings.de/multithreading_arduino/index.html Multithreading in C und Arduino] von Stefan Frings&lt;br /&gt;
[[Kategorie:Algorithmen und Arithmetik]]&lt;/div&gt;</summary>
		<author><name>172.26.37.113</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Leiterbahnbreite&amp;diff=105128</id>
		<title>Leiterbahnbreite</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Leiterbahnbreite&amp;diff=105128"/>
		<updated>2022-04-07T13:36:18Z</updated>

		<summary type="html">&lt;p&gt;172.26.37.113: pdf&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Hier wird die Strombelastbarkeit einer Leiterbahn in Abhängigkeit von der Breite und der zulässigen Erwärmung dargestellt. Die Angaben gelten für eine Leiterbahndicke von 35µm (engl. 1 ounce per square feet, eine Unze pro Quadratfuß). Für übliches FR4 mit anderen Kupferdicken können die Werte nicht einfach linear umgerechnet werden, man nutzt besser die Tabellen in den verlinkten Dokumenten.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; rowspan=&amp;quot;3&amp;quot;| Leiterbreite&lt;br /&gt;
!colspan=&amp;quot;4&amp;quot; | Kupferdicke [µm]&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; | Kupferdicke [µm] &lt;br /&gt;
|-&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; | 35&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; | 70&lt;br /&gt;
! 35&lt;br /&gt;
! 70&lt;br /&gt;
|-&lt;br /&gt;
!colspan=&amp;quot;4&amp;quot; | zulässige Stromstärke [A] &amp;lt;br/&amp;gt; bei Erwärmung um&lt;br /&gt;
!colspan=&amp;quot;2&amp;quot; | mΩ/cm&lt;br /&gt;
|-&lt;br /&gt;
! [mm] || [mil] || 10 K || 30 K || 10 K || 30 K&lt;br /&gt;
!&lt;br /&gt;
!&lt;br /&gt;
|-&lt;br /&gt;
| 0,10 || 4 || 0,2 || 0,4 || 0,4 || 0,8 || 50,9 || 25,4&lt;br /&gt;
|-&lt;br /&gt;
| 0,15 || 6 || 0,3 || 0,6 || 0,6 || 1,2 || 33,9 || 17,0&lt;br /&gt;
|-&lt;br /&gt;
| 0,20 || 8 || 0,4 || 0,8 || 0,8 || 1,6 || 25,4 || 12,7&lt;br /&gt;
|-&lt;br /&gt;
| 0,25 || 10 || 0,5 || 1,0 || 1,0 || 2,0 || 20,3 || 10,2&lt;br /&gt;
|-&lt;br /&gt;
| 0,30 || 12 || 0,6 || 1,2 || 1,2 || 2,3 || 17,0 || 8,48&lt;br /&gt;
|-&lt;br /&gt;
| 0,5  || 20 || 1,0 || 2,0 || 2,0 || 3,5 || 10,2 || 5,09&lt;br /&gt;
|-&lt;br /&gt;
| 1,0  || 39 || 2,2 || 3,6 || 3,5 || 5,8 || 5,09 || 2,54&lt;br /&gt;
|-&lt;br /&gt;
| 1,5  || 59 || 3,0 || 4,6 || 4,5 || 7,5 || 3,39 || 1,70&lt;br /&gt;
|-&lt;br /&gt;
| 2,0  || 79 || 3,8 || 6,5 || 6,0 || 10,0 || 2,54 || 1,27&lt;br /&gt;
|-&lt;br /&gt;
| 3,0  || 118 || 4,5 || 8,0 || 7,5 || 14,0 || 1,70 || 0,848&lt;br /&gt;
|-&lt;br /&gt;
| 4,0  || 157 || 6,0 || 10 || 9,0 || 17,0 || 1,27 || 0,636&lt;br /&gt;
|-&lt;br /&gt;
| 5,0  || 197 || 7,0 || 12 || 10,0 || 19,0 || 1,02 || 0,509&lt;br /&gt;
|-&lt;br /&gt;
| 6,0  || 236 || 7,5 || 14 || 11,0 || 22,0 || 0,848 || 0,424&lt;br /&gt;
|-&lt;br /&gt;
| 8,0  || 315 || 9,0 || 17 || – || – || 0,636 || 0,318&lt;br /&gt;
|-&lt;br /&gt;
| 10   || 394 || 10  || 20 || – || – || 0,509 || 0,254&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Der Zusammenhang zwischen dem Abstand der Leitungen und der Spannung ist mit 5V/mil ~200V/mm angegeben. Dabei ist zu beachten, dass für Netzspannung größere Sicherheitsabstände einzuhalten sind (Quelle: Art Of Electronics, 2. Ausgabe, Seite 841). Siehe auch [[Leiterbahnabstände]].&lt;br /&gt;
&lt;br /&gt;
Es ist eine bisweilen weit verbreitete Unsitte, die Strombelastbarkeit von Leiterbahnen durch dickes Verzinnen erhöhen zu wollen. Fakt ist&lt;br /&gt;
* Der spezifische Widerstand von Kupfer beträgt 17,8mΩ·mm&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;/m&lt;br /&gt;
* Der spezifische Widerstand von Lötzinn Sn60Pb beträgt ca. 150mΩ·mm&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;/m&lt;br /&gt;
&lt;br /&gt;
Daraus folgt, dass eine Schicht aus Lötzinn ca. 8,4 mal so dick sein muss wie eine Kupferschicht, um den gleichen Widerstand zu erreichen. Im Falle des oft verwendeten FR4 mit 35µm Kupfer wären das 0,3mm. Bei 70µm Kupfer wären schon 0,6mm nötig. Und dadurch wird der Gesamtwiderstand gerade mal halbiert und die Strombelastbarkeit bei gleicher Erwärmung steigt wegen&lt;br /&gt;
: P = I&amp;lt;sup&amp;gt;2&amp;lt;/sup&amp;gt;·R&lt;br /&gt;
nur um den Faktor 1,41. Wesentlich sinnvoller und professioneller ist das Auflöten von massivem Kupferdraht oder Aufschrauben von Kupferschienen.&lt;br /&gt;
&lt;br /&gt;
Die Breite der Leiterbahnen ist im wesentlichen nur für die Stromversorgung sowie Masseleitungen von Bedeutung. Bei reinen Meß- und Steuersignalen – wie sie z.&amp;amp;nbsp;B. in analogen Messschaltungen mit Operationsverstärkern oder Digitalschaltkreisen auftreten – empfiehlt es sich übrigens die Leiterbahnen möglichst &#039;&#039;schmal&#039;&#039; zu halten. Das minimiert die Kapazitäten und somit die Schwingungsneigung der Schaltung.&lt;br /&gt;
&lt;br /&gt;
siehe auch: [[Eagle_im_Hobbybereich#Empfehlungen_für_Leiterbahnen_im_Hobbybereich | Empfehlung für Leiterbahnbreiten im Hobbybereich]]&lt;br /&gt;
&lt;br /&gt;
== Pulsbelastung von Leiterbahnen ==&lt;br /&gt;
&lt;br /&gt;
Siehe http://oliverbetz.de/pages/PIM/ImpulsBelastbarkeit.&lt;br /&gt;
&lt;br /&gt;
Bezogen auf Kupfer mit &amp;lt;math&amp;gt;\rho_E=17,8 \cdot 10^{-9} \Omega m, \rho=8900 kg/m^3, C=385 J/(kg \cdot K)&amp;lt;/math&amp;gt; und der&lt;br /&gt;
Fläche A in mm2 heißt das vereinfacht&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\Delta T = 5,2 \cdot 10^{-3} \cdot \frac{ I^2 \cdot t}{A^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dies gilt für einen rechteckförmigen Stromimpuls, für andere Pulsformen muss mittels Messung oder Simulation der entsprechende &amp;lt;math&amp;gt;I^2t&amp;lt;/math&amp;gt; Wert ermittelt werden.&lt;br /&gt;
&lt;br /&gt;
Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;\Delta T = 5,2 \cdot 10^{-3} \cdot \frac{ (1000A)^2 \cdot 1ms}{(1mm^2)^2}=5,2K&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
*[http://www.mikrocontroller.net/topic/283734#3004573 Forumsbeitrag]: Unglaublich hohe Stromdichte?&lt;br /&gt;
*[https://www.mikrocontroller.net/topic/374665?goto=4245383#4245383 Forumsbeitrag]: Strombelastbarkeit von VIAs&lt;br /&gt;
* [https://www.mikrocontroller.net/topic/484495#6037429 Forumsbeitrag]: IC oben, Kühlkörper unten?&lt;br /&gt;
* [https://www.mikrocontroller.net/topic/444367?goto=5300320#5300320 Forumsbeitrag]: Aluminiumkabel- Querschnitt - Kupfer&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&lt;br /&gt;
*[http://www.pcb-pool.com/download/spezifikation/deu_cmso001_strombelastbarkeit.pdf Leiterbahnspezifikationen] von [http://www.pcb-pool.de PCB-Pool]&lt;br /&gt;
*[http://wiki.oliverbetz.de/owiki.php/FormelSammlung Formelsammlung von allem Möglichem]&lt;br /&gt;
* [http://circuitcalculator.com/wordpress/2006/01/31/pcb-trace-width-calculator/ Online Calculator]--&amp;gt; Achtung: Metrische Ergebnisse falsch!&lt;br /&gt;
* [https://forum.dmxcontrol-projects.org/core/index.php?attachment/6839-ampacity-pdf/ Belastbarkeit von Basismaterial, Leiterbahnen und Durchkontaktierungen]&lt;br /&gt;
*[https://www.multi-circuit-boards.eu/leiterplatten-design-hilfe/oberflaeche/leiterbahn-strombelastbarkeit.html Leiterbahn / Strombelastbarkeit] von [https://www.multi-circuit-boards.eu Multi-CB]&lt;br /&gt;
* [http://circuitcalculator.com/wordpress/2006/03/12/pcb-via-calculator/ PCB Via Calculator ], elektrische und thermische Eigenschaften von VIAs berechnen&lt;br /&gt;
* [http://www.electronics-cooling.com/2004/08/thermal-vias-a-packaging-engineers-best-friend/ Thermal Vias – A Packaging Engineer’s Best Friend]&lt;br /&gt;
* [https://www.amazon.com/PCB-Trace-Via-Currents-%20Temperatures/dp/1530389437/ref=la_B001IR1JBS_1_4?s=books&amp;amp;ie=UTF8&amp;amp;qid=1476216597&amp;amp;sr=1-4 Douglas G. Brooks PhD: PCB Trace and Via Currents and Temperatures:: The Complete Analysis (2nd ed.)] ISBN 1541213521 (oder 978-1541213524)&lt;br /&gt;
*[https://www.eevblog.com/2012/07/21/eevblog-317-pcb-tinning-myth-busting/ eevblog-317-pcb-tinning-myth-busting], engl. Video&lt;br /&gt;
* [https://www.ultracad.com/articles/viacurrents.pdf Current Carrying Capacity of Vias], engl. (Bohrung&amp;gt;=Leiterbahnbreite/3)&lt;br /&gt;
[[Category:Platinen]]&lt;br /&gt;
[[Kategorie:Spannungsversorgung und Energiequellen]]&lt;/div&gt;</summary>
		<author><name>172.26.37.113</name></author>
	</entry>
</feed>