<?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=62.157.123.104</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=62.157.123.104"/>
	<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/articles/Spezial:Beitr%C3%A4ge/62.157.123.104"/>
	<updated>2026-04-10T23:46:13Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.39.7</generator>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Pegelwandler&amp;diff=86674</id>
		<title>Pegelwandler</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Pegelwandler&amp;diff=86674"/>
		<updated>2015-01-15T09:52:16Z</updated>

		<summary type="html">&lt;p&gt;62.157.123.104: /* 3,3 V ⇒ 5 V */ Typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Vorwort ==&lt;br /&gt;
&lt;br /&gt;
Dies ist die erste aufgeräumte Version. Sicher nicht die letzte.&lt;br /&gt;
&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-1-375051.html &amp;quot;Stein des Anstosses&amp;quot;]&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/list-1-1.html?filter=pegelwand*+levelsh*&amp;amp;x=0&amp;amp;y=0 Suche in den Forenartikel]&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Pegelwandeln (engl. level shifting) wird oft notwendig, wenn Systeme mit unterschiedlicher Ausgangs- und Eingangsspannungen (z.&amp;amp;nbsp;B. Versorgungs- oder Logikspannungen) miteinander verbunden werden sollen. Das vielleicht bekannteste Beispiel ist die Umsetzung von 0V/5V [[TTL]] Logikpegeln auf die -12V/12V Pegel einer seriellen [[RS232]] Schnittstelle. Die Probleme beim Pegelwandeln können sein:&lt;br /&gt;
&lt;br /&gt;
# Überlastung einer oder beider Seiten, bis hin zur Zerstörung&lt;br /&gt;
# Inkompatible Logikpegel und daraus resultierendes Nichtfunktionieren der Schaltung, oder noch schlimmer, sporadische Fehlfunktionen&lt;br /&gt;
# Verzögerungen der Signale durch die Pegelwandlung und daraus resultierende maximale Signalfrequenzen&lt;br /&gt;
&lt;br /&gt;
=== Überlastung ===&lt;br /&gt;
&lt;br /&gt;
Das Erzeugen von verschiedenen Versorgungsspannungen ist ziemlich einfach, aber man muss sicher gehen, daß man die Signalpegel der Bauteile auf Toleranz überprüft. Wenn z.B. ein 5V Bauteil ein Signal an ein 3V Bauteil schickt, können beide Bauteile beschädigt werden. Vor allem für neue ICs ist es ein Problem mit &amp;quot;hohen&amp;quot; Spannungen wie 5V zu arbeiten. Auf Grund der immer kleineren Schaltkreisstrukturen (der aktuelle Pentium wird mit 22nm Technologie hergestellt!) werden auch die Abstände und Schichtdicken immer geringer. Das reduziert natürlich auch die Spannungs- und Stromfestigkeit der Transistoren auf dem IC. Neue ICs vertragen deshalb meist nur noch 3.3V, teilweise sogar weniger! Die Überlastung erfolgt durch zu hohe Spannung und dadurch mehr oder weniger langsame Zerstörung des ICs.&lt;br /&gt;
&lt;br /&gt;
=== Schutzdioden ===&lt;br /&gt;
&lt;br /&gt;
Hauptursache Nummer zwei für Überlastung von ICs mit verschiedenen Betriebsspannungen sind die in nahezu allen ICs integrierten Schutzdioden. Deren Aufgabe ist es in Normalfall, elektrostatische Entladungen auf eine sichere, niedrige Spannung zu begrenzen. Die Entladungen geschehen durch unsachgemässe Handhabung und Transport von ICs, z.&amp;amp;nbsp;B. wenn jemand über einen Kunstfaserteppich läuft, sich dabei elektrostatisch auflädt und einen IC anfasst, oder wenn Bauteile in einem Gerät eingebaut sind und der Anwender berührt offen liegende Kontakte (RS232 Eingang, USB-Stick, PCI-Steckkarten beim Einbau etc.). Auch elektrostatische Entladungen / EMV können Ursache zu hoher Pegel auf den Leitungen sein.&lt;br /&gt;
&lt;br /&gt;
Die Schutzdioden beginnen, Strom zu leiten, wenn die Eingangsspannung ca. 300 mV - 600 mV über U&amp;lt;sub&amp;gt;CC&amp;lt;/sub&amp;gt; ansteigt oder entsprechend unter GND absinkt. Im Normalbetrieb sollten die Schutzdioden keinen Strom leiten. Manchmal kann man sie aber zur Spannungsbegrenzung missbrauchen, siehe [[#STEP-DOWN:_5V_-.3E_3.3V | Spannungsherabsetzung mit Vorwiderstand]].&lt;br /&gt;
&lt;br /&gt;
Besonderes Augenmerk ist hierbei auf die optimale Dimensionierung des R zu legen, um sicherzustellen, dass kein zu hoher Strom über die Schutzdioden abgeführt werden muss. Je nach Chip-Type und Ausgang halten diese zwsichen 100 µA und 10 mA aus.&lt;br /&gt;
&lt;br /&gt;
[[bild:pw_schutzdioden.png]]&lt;br /&gt;
&lt;br /&gt;
=== 5-V-tolerante Eingänge ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;i&amp;gt;5-Volt-tolerant&amp;lt;/i&amp;gt; bedeutet, dass 3-Volt-Bausteine ohne Probleme von einem 5-Volt-Baustein angesteuert werden dürfen.&lt;br /&gt;
&lt;br /&gt;
Viele Bauteile mit einer Betriebsspannung von 3 V verfügen über 5-V-tolerante Eingänge. Man sollte aber grundsätzlich im Datenblatt dies nachschauen, bevor die Schaltung aufgebaut wird. Sind sie es nicht, so ist ein &amp;lt;b&amp;gt;Pegelwandler&amp;lt;/b&amp;gt; auf den Verbindungsleitungen zwischen den Bauteilen notwendig. Ein Pegelwandler kann eine einfache Zener-Diode mit einem Widerstand sein, es kann aber auch ein eigens dafür vorgesehener IC sein. Sind die Signalwege bidirektional, so wird man meist die Lösung mit einem eigenen IC bevorzugen.&lt;br /&gt;
&lt;br /&gt;
Bei geringen Geschwindigkeitsanforderungen und erlaubten flachflankigen Signalen (bei Zähl- und Takteingängen ist dazu Schmitt-Trigger-Verhalten erforderlich) genügt ein Serienwiderstand (Richtwert 10 kΩ) in Verbindung mit der Eingangsschutzbeschaltung. Bei allen derartigen „passiven Pegelkonvertern“ muss die Logikschaltschwelle durchfahren werden. Bei heutzutage üblichen treibenden CMOS-Ausgangsstufen ist das kein Problem.&lt;br /&gt;
&lt;br /&gt;
Ob ein Bauteil 5-V-tolerant ist und unter welchen Betriebsbedingungen das gilt, steht im Datenblatt des betreffenden Bauteils vom betreffenden Hersteller. Wenn es auf diese Eigenschaft ankommt, lieber genau bei Lieferanten nachsehen, von welchem Hersteller die Bauteile kommen.&lt;br /&gt;
&lt;br /&gt;
==== Beispiele ====&lt;br /&gt;
&lt;br /&gt;
[[AVR]]s sind generell &#039;&#039;&#039;nicht&#039;&#039;&#039; 5-V-tolerant, wenn sie mit 3,3 V betrieben werden! Die absolute obere Grenze für Eingangsspannungen liegt bei U&amp;lt;sub&amp;gt;CC&amp;lt;/sub&amp;gt; + 0,5 V. Zu finden in den elektrischen Spezifikationen im Datenblatt.&lt;br /&gt;
&lt;br /&gt;
Die GPIO-Pins des Raspberry Pi sind ebenfalls &#039;&#039;&#039;nicht&#039;&#039;&#039; 5-V-tolerant!&lt;br /&gt;
&lt;br /&gt;
Vorsicht bei:&lt;br /&gt;
&lt;br /&gt;
* 74&#039;&#039;&#039;LVX&#039;&#039;&#039;xxxx und 74&#039;&#039;&#039;LCX&#039;&#039;&#039;xxxx (245, 244, 240 ...) an Vcc = 3,3 V.&amp;lt;br&amp;gt;&amp;lt;font color=FF0000&amp;gt;Achtung&amp;lt;/font&amp;gt;: Nicht alle 74LVX sind für 5 V -&amp;gt; 3,3 V geeignet, da jeder Hersteller die ICs anders baut!&lt;br /&gt;
* SN74LVC07AD&lt;br /&gt;
* SN74LV1T04 (auch geeignet zur umgekehrten Konvertierung (3,3V-&amp;gt;5V))&lt;br /&gt;
&lt;br /&gt;
=== Kompatibilität von Logikpegeln ===&lt;br /&gt;
&lt;br /&gt;
Siehe auch http://www.interfacebus.com/Design_Translation.html&lt;br /&gt;
&lt;br /&gt;
Verschiedene Mikroprozessoren haben eigene elektrische Kenndaten für HIGH- und LOW-Pegel, die abhängig von der Versorgungsspannung sind, z.&amp;amp;nbsp;B. der [[R8C]]:&lt;br /&gt;
&lt;br /&gt;
* HIGH größer 0,8 * U&amp;lt;sub&amp;gt;CC&amp;lt;/sub&amp;gt;&lt;br /&gt;
* LOW kleiner 0,2 * U&amp;lt;sub&amp;gt;CC&amp;lt;/sub&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man muss die Spannungen der Aus- und Eingänge vergleichen. Wenn es um ein Hobbyprojekt geht, kann man einfach messen. Wenn es um eine kommerzielle Anwendung geht, die man verkaufen will, sollte man besser die Spezifikationen der ICs studieren.&lt;br /&gt;
&lt;br /&gt;
== UNIDIREKTIONAL ==&lt;br /&gt;
&lt;br /&gt;
=== 1,8 V ⇒ 5 V ===&lt;br /&gt;
&lt;br /&gt;
* Die besondere Eigenschaft der alten TTL-Schaltkreise, nämlich dass Strom bei LOW &#039;&#039;&#039;aus&#039;&#039;&#039; dem Eingang in den treibenden Ausgang fließt kann man sich zunutze machen, wie die nachfolgende Schaltung zeigt. In dieser wird der HIGH-Pegel des 1,8-V-Signals durch eine Schottkydiode um ca. 0,3 V auf 2,1 V erhöht. Damit ist man fast offiziell im HIGH-Bereich für TTL (Schaltschwelle 1,4 V, HIGH &amp;gt; 2,0 V). Der LOW-Pegel wird auf ca. 0,3 V erhöht, was voll den TTL-Richtlinien entspricht. Als Schaltkreisfamilie &#039;&#039;&#039;muss&#039;&#039;&#039; ein [[74xx|TTL-Typ]] eingesetzt werdem, also LS, F, AS oder ähnlich. CMOS-Typen wie HC, LVC etc. funktionieren &#039;&#039;&#039;nicht&#039;&#039;&#039;!&lt;br /&gt;
&lt;br /&gt;
[[bild:pw_LS.png]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=FF0000&amp;gt;Achtung&amp;lt;/font&amp;gt;: Diese Schaltung entspricht bei HIGH ungefähr einem offenen TTL-Eingang, was zwar meistens funktioniert, aber etwas störempfindlich sein kann. Davon wurde in der TTL-Ära stets abgeraten. Zudem ist der Pegelwechsel LOW nach HIGH durch den niedrigen Strom eher langsam. Man kann das jedoch mit einem Pullup-Widerstand absichern. Dann sind auch Gatter der 74HCT-Reihe einsetzbar.&lt;br /&gt;
&lt;br /&gt;
=== 3,3 V ⇒ 5 V ===&lt;br /&gt;
&lt;br /&gt;
Diese Konversion ist mit Abstand die häufigste. Dabei kann man getrost 3,3 V (früher) und 3 V (moderner) gleich setzen.&lt;br /&gt;
&lt;br /&gt;
* 3,3-V-Pegel werden bei TTL-kompatiblen Eingängen richtig erkannt (Schaltschwelle 1,4 V). Es ist kein Pegelwandler erforderlich. Direkte Verbindung. Einer der großen Vorteile klassischer TTL-Technik!&lt;br /&gt;
&lt;br /&gt;
* 5-V-CMOS Eingänge haben typisch eine minimale Eingangsspannug für HIGH (&amp;lt;math&amp;gt;V_{IH}&amp;lt;/math&amp;gt;) von 0.6 * U&amp;lt;sub&amp;gt;CC&amp;lt;/sub&amp;gt; = 0.6 * 5 V = 3 V. Das kann ein 3,3-V-CMOS-Ausgang direkt treiben, allerdings kann sich das Zeitverhalten dadurch etwas ändern, weil der HIGH Pegel später erkannt wird. Vorsicht! Viele 5-V-CMOS-ICs wollen für HIGH offiziell mindestens 0,7 * U&amp;lt;sub&amp;gt;CC&amp;lt;/sub&amp;gt; = 3,5 V oder manche auch 0,8 * U&amp;lt;sub&amp;gt;CC&amp;lt;/sub&amp;gt; = 4,0V! Das geht dann offiziell nicht mehr mit einem 3,3-V-Ausgang! Für Hobbyzwecke kann man das aber ggf. probieren.&lt;br /&gt;
Zu beachten ist, dass der nicht ganz nach High durchgesteuerte Eingang Querstrom von der Speisespannung ziehen kann. Das kann für batteriebetriebene Geräte oder USB-konformes Standby durchaus ausschlaggebend sein.&lt;br /&gt;
&lt;br /&gt;
* 3,3-V-[[Ausgangsstufen_Logik-ICs | Open Collector]] nach 5 V (TTL oder CMOS): Einfach einen Pull-Up Widerstand hinzufügen und gut. Allerdings verbraucht der Pull-Up-Widerstand bei LOW auf jeden Fall Strom und begrenzt bei HIGH den maximalen Gate-Umladestrom. Die Schaltgeschwindigkeit von LOW nach HIGH wird durch die Größe des Pull-Ups bestimmt. Je nach Geschwindigkeitsanforderungen kann der in Mikrocontrollern meistens zuschaltbare innere Widerstand dazu benutzt werden. Zudem kann dieser, bei bekannt LOW bleibendem Eingangspegel, zur Reduktion der Stromaufnahme abgeschaltet werden. Bipolare TTL-Schaltkreise benötigen in der Bastelschaltung keinen Pull-Up (liefern Strom); bei Schaltungen mit erhöhter Zuverlässigkeit ist dennoch ein externer Pull-Up angeraten (Richtwert 4,7 kΩ).&lt;br /&gt;
&lt;br /&gt;
[[bild:pw_oc_3-5.png]]&lt;br /&gt;
&lt;br /&gt;
* 3,3 V auf echte 5 V (CMOS) geht am einfachsten mit einem Baustein der HCT-Familie (NICHT HC!). Diese haben TTL-kompatible Eingänge und echte CMOS-Ausgänge&lt;br /&gt;
&lt;br /&gt;
* Man kann einen Komparator &amp;lt;small&amp;gt;in nichtinvertierender Schaltung&amp;lt;/small&amp;gt; benutzen (LM339/393). Allerdings ist diese Lösung relativ langsam, abhängig vom verwendeten Komparator. Komparatoren bieten eine freie Wahl des Eingangsspannungsbereichs und sind deshalb eine gute Wahl bei &#039;&#039;variabler&#039;&#039; Speisespannung der Treiberseite.&lt;br /&gt;
&lt;br /&gt;
[[bild:pw_comp_3-5.png]]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Bauteile&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* 74HCTxxx (245, 244, 240 ...) (HCs können funktionieren, ist aber eigtl. ungeeignet, da bei 5V Versorgung und höheren Temperaturen V(input,high)=3,2V)&lt;br /&gt;
* 74HCT125: OE Pins auf Masse und dann das Signal einfach anschließen. &lt;br /&gt;
* SN74LVC07AD &lt;br /&gt;
* SN74LV1T04 (auch geeignet zur umgekehrten Konvertierung (5V-&amp;gt;3,3V))&lt;br /&gt;
* 74V1T126 (single Gatter, V(input,high)=2V)&lt;br /&gt;
&lt;br /&gt;
=== 5 V ⇒ 9..15(..30) V ===&lt;br /&gt;
&lt;br /&gt;
* Am einfachsten geht das mit einem (geeigneten!) Open-Collector-Ausgang, einfach einen Pull-Up hinzufügen (an die hohe Spannung) und fertig. Ein 74&#039;&#039;xx&#039;&#039;03 geht hier nicht! Auch kann man nicht einen Push-Pull-Ausgang eines Mikrocontrollers dafür verwenden, indem man den Ausgang bei HIGH zum Eingang macht.&lt;br /&gt;
Hintergrund sind parasitäre Dioden zwischen Ausgang und Speisespannung.&lt;br /&gt;
Alle (geeigneten) Treiberausgänge haben eine maximal erlaubte Kollektorspannung, die zu beachten ist. Mehr Freiheit hat man bei der Verwendung von Einzeltransistoren, wobei eine gewisse Lücke von 30 V bis 200 V von Bipolartransistoren dominiert wird; für kleinere oder größere Spannungen gibt es preiswerte MOSFETs. (Die Lücke entsteht durch den geringen Bedarf des Weltmarktes an diesen Kollektorspannungen.)&lt;br /&gt;
&lt;br /&gt;
[[bild:pw_oc_5-12.png]]&lt;br /&gt;
&lt;br /&gt;
* Man kann einen Komparator benutzen. Allerdings ist diese Lösung relativ langsam, abhängig vom verwendeten Komparator. Wenn nur zwei Signale gewandelt werden müssen bietet sich der LM393 an, ein Doppelkomparator mit Open-Collector-Ausgang, mit dem man auf einen beliebigen Pegel ausgeben kann. Der LM339 (man beachte den unauffälligen Zahlendreher) ist ein Vierfachkomparator mit den gleichen Eigenschaften. Wenn wenig Platz vorhanden ist, dann ist der TL311 im winzigen SOT-23 Gehäuse sehr empfehlenswert. Bei jedem Komparator kann auch einfach eine Invertierung gemacht werden, einfach die Eingänge + und - vertauschen. Diese Komparatoren eignen sich bis ca. 1 MHz.&lt;br /&gt;
&lt;br /&gt;
* [http://www.elektronik-kompendium.de/sites/praxis/bausatz_pegelwandler-mit-transistoren.htm Pegelwandler mit Transistor, invertierend]&lt;br /&gt;
&lt;br /&gt;
[[bild:pw_trans_inv.png]]&lt;br /&gt;
&lt;br /&gt;
* Pegelwandler mit Transistor, nicht invertierend&lt;br /&gt;
&lt;br /&gt;
[[bild:pw_trans_ni.png]]&lt;br /&gt;
&lt;br /&gt;
Die Idee ist einfach. Wenn der Ausgang des 5-V-Gatters auf HIGH ist dann ist der Transistor ausgeschaltet, der Pull-Up-Widerstand R7 zieht den Ausgang auf + 12 V. Ist der Ausgang des 5-V-Gatters auf LOW ist, dann ist er vollkommen durchgesteuert und der Ausgang nahe 0 V (je nach Typ ca. 300 mV). Der Vorteil ist hier erhöhte Störsicherheit im Gegensatz zur einfachen Ansteuerung der Basis über einen Vorwiderstand. Außerdem wird dadurch nicht die Logik invertiert. Nachteilig ist der geringe Strom, der bei HIGH zur Verfügung steht (typisch 100 µA). Diese Schaltung ist die seltene Anwendung einer Basisschaltung für digitale Signale. Der Vorteil der Basisschaltung ist die höhere Grenzfrequenz durch die herabgesetzte Wirksamkeit der (störenden) Miller-Kapazität.&lt;br /&gt;
&lt;br /&gt;
* Wenn mehr Geschwindigkeit, Ausgangsstrom und weniger Stromverbrauch nötig ist, dann muss ein spezieller Baustein her, wie z.&amp;amp;nbsp;B.&amp;lt;BR&amp;gt;&amp;lt;BR&amp;gt;&lt;br /&gt;
** [[Mosfet-Übersicht#Mosfet-Treiber|MOSFET-Treiber]] z.B. ICL7667&lt;br /&gt;
** [[H-Brücken Übersicht | Motortreiber]] ICs: (z.&amp;amp;nbsp;B. L293, L298, UCC27325 und deren Verwandte), wenns nicht zu schnell ist (einige Dutzend kHz)&lt;br /&gt;
** CD40109, bei Reichelt verfügbar&lt;br /&gt;
** HEF4104, 4fach LOW-HIGH-Pegelwandler mit normalen und invertierten Augängen sowie Tristate. Um ggf. sicherzustellen, dass wie im Datenblatt beschrieben immer U&amp;lt;sub&amp;gt;DDI&amp;lt;/sub&amp;gt; &amp;lt;= U&amp;lt;sub&amp;gt;DDO&amp;lt;/sub&amp;gt; ist, kann man einfach eine Diode von U&amp;lt;sub&amp;gt;DDO&amp;lt;/sub&amp;gt; nach U&amp;lt;sub&amp;gt;DDI&amp;lt;/sub&amp;gt; schalten (z.&amp;amp;nbsp;B. Schottky SB120, aber auch 1N4148 &amp;amp; Co. sollte problemlos funktionieren)&lt;br /&gt;
** CMOS 4504, 6fach LOW-HIGH/HIGH-LOW 3-20V Pegelwandler, TTL/CMOS (umschaltbar) =&amp;gt; CMOS, kein Reihenfolge von U&amp;lt;sub&amp;gt;CC&amp;lt;/sub&amp;gt;/U&amp;lt;sub&amp;gt;EE&amp;lt;/sub&amp;gt; erforderlich (Bezugsquelle: CSD)&lt;br /&gt;
** MAX232, der braucht nur 5 V Versorgungsspannung. Allerdings ist der Ausgangswiderstand relativ hoch (ca. 300 Ω) und man kann nur ca. 5 mA Ausgangstrom liefern. Die Ausgangsspannung beträgt maximal 10 V.&lt;br /&gt;
&lt;br /&gt;
=== 5 V ⇒ 3,3 V ===&lt;br /&gt;
&lt;br /&gt;
Ob 3,3 V (klassisch) oder 3 V (modern) ist bei dieser Betrachtung nahezu egal.&lt;br /&gt;
&lt;br /&gt;
* Zuerst sollte man prüfen, ob die Eingänge 5-V-tolerant sind. Dann kann man die ICs direkt verbinden. Sehr schnell und billig!&lt;br /&gt;
&lt;br /&gt;
* Wenn die Eingänge nicht 5-V-tolerant sind und es trotzdem schnell sein soll, muss ein Gatter aus der LVC- oder AHC-Familie dazwischen geschaltet werden, also eines mit 5-V-Toleranz. Bei 3 V Betriebsspannung kann man problemlos 5 V an den Eingang anlegen. Der Baustein 74HC4050 erlaubt per Definition eine Pegelwandlung bis etwa 15 V (siehe Datenblatt). Beide Anordungen verbrauchen auch sehr wenig Ruhestrom.&lt;br /&gt;
&lt;br /&gt;
: &#039;&#039;&#039;Bauteile&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
:* 74LVC245A (&#039;A&#039; ist wichtig, I/Os 5V-tolerant)&lt;br /&gt;
:* 74LVC245DW &lt;br /&gt;
:* 74LVT245 &lt;br /&gt;
:* 74LVXxxx (245, 244, 240 ...) an Vcc=3,3V. Achtung: Nicht alle 74LVX sind für 5V -&amp;gt; 3,3V geeignet, da jeder Hersteller die ICs anders baut!&lt;br /&gt;
:** 74LVX04 &lt;br /&gt;
:** 74LVX244 (Fairchild)&lt;br /&gt;
:** 74LVX245 (nicht von Reichelt, nicht 5V tolerant)&lt;br /&gt;
:** bei TI heissen die 74LVX... nur 74LV...&lt;br /&gt;
&lt;br /&gt;
:* 74HC4050 (bis 15 V Step-Down-Pegelwandlung laut Datenblatt, bei Reichelt in DIP und SO erhältlich)&lt;br /&gt;
:* MAX3373/MAX3375&lt;br /&gt;
:* NC7SZ08 oder andere aus derselben Serie. CMOS-Logik mit 5-V-toleranten Eingängen, recht flott und braucht dank SOT-23 auch wenig Platz auf der Platine&lt;br /&gt;
&lt;br /&gt;
* 5 V Open Collector auf 3,3-V-Eingang. Einfach einen Pull-Up hinzufügen (Pull-Up liegt auf 3,3 V). Nachteilig ist der relativ hohe Stromverbrauch bei LOW, die begrenzte Geschwindigkeit bei hochohmigen Pull-Ups und der relativ geringe Ausgangsstrom bei HIGH (abhängig vom Pull-Up).&lt;br /&gt;
&lt;br /&gt;
[[bild:pw_oc_5-3.png]]&lt;br /&gt;
&lt;br /&gt;
* Spannungsteiler mit 680 Ω und 1 kΩ. Der Nachteil dieser Lösung ist der relativ hohe Stromverbrauch (~3mA), der relativ geringe Ausgangsstrom (mehr als 200..300 µA sollte man da nicht rausziehen) und die relativ geringe Geschwindigkeit (ca. 10 MHz).&lt;br /&gt;
&lt;br /&gt;
[[bild:pw_st_5-3.png]]&lt;br /&gt;
&lt;br /&gt;
* 1 kΩ Vorwiderstand. Dadurch wird der Strom vom 5-V-Ausgang in die 3,3-V-Versorgung durch die internen Schutzdioden auf ca. 1 mA begrenzt. Diese Lösung ist auch relativ langsam (ca. 5MHz). Ggf. kann man den Vorwiderstand auf 100 Ω reduzieren, das erhöht dann wieder die Geschwindigkeit. Aufpassen, einige ICs vertragen nur 1 mA oder weniger durch die Schutzdioden! Ausserdem muss man aufpassen, das jetzt von der 5-V-Seite Strom in die 3,3-V-Versorgung eingespeist wird. Besonders in Schaltungen mit sehr niedrigem Stromverbrauch kann das zum Problem werden, wenn weniger Strom verbraucht wird als über die Vorwiderstände eingespeist wird. Dann nimmt es meist der Spannungsregler für 3,3 V übel wenn jemand „schiebt“, sprich, Strom einspeist. Denn die allermeisten Spannungsregler können nur Strom liefern (source), aber keinen Strom aufnehmen (sink). Es gibt 4-fach-Diodennetzwerke, die die internen Schutzdioden entlasten können (Schottkydioden mit kleinerer Flusspannung von ≈ 0,3 V als die internen Silizizumdioden mit ≈ 0,7 V), außerdem ist teilweise noch eine [[Diode#Z-Diode|Zenerdiode]] enthalten, die ggf. den überschüssig eingespeisten Strom aufnehmen kann.&lt;br /&gt;
&lt;br /&gt;
Alle Lösungen mit Vorwiderständen reduzieren die Flankensteilheit der Signale. Dies kann bei Takt- und Zähleingängen zu unerwünschten Schwingungen und damit Fehlzählungen führen. Derartig benutzte Eingänge sollten Schmitt-Trigger-Verhalten aufweisen.&lt;br /&gt;
&lt;br /&gt;
[[bild:pw_vw_5-3.png]]&lt;br /&gt;
&lt;br /&gt;
Achtung: Mindestens für 74HC(T) Gatter ist dokumentiert (Philips 74HC/T High-Speed CMOS User Guide), dass auch schon geringer Strom durch die internen Schutzdioden zu einer unerwünschten Kopplung von Eingängen führen kann, d.h. der Strom fliesst zu einem anderen Eingang wieder hinaus. Sind also andere Eingänge ebenso hochohmig angeschlossen, kann dieser Querstrom zu Fehlfunktion führen.&lt;br /&gt;
&lt;br /&gt;
== BIDIREKTIONAL ==&lt;br /&gt;
&lt;br /&gt;
Für bidirektionale Busse gibt es spezielle Pegelwandler mit 2 Versorgungsspannungen. Allerdings brauchen die meist ein Signal zur Richtungsumschaltung. Auch muss man die Reihenfolge der Versorgungsspannungen beim Einschalten beachten. Aktive bidirektionale Pegelwandler OHNE Steuereingang zur Richtungsumschaltung sind mit Vorsicht zu genießen, denn die brauchen teilweise kurzzeitig einen relativ hohen Strom, um die Eingänge zu treiben.&lt;br /&gt;
&lt;br /&gt;
=== 5 V ⇔ 3,3 V ===&lt;br /&gt;
&lt;br /&gt;
* Wenn die 5-V-Seite TTL-kompatible Eingänge hat kann wieder der Spannungsteiler oder Vorwiderstand wie bei der unidirektionalen Anpassung verwendet werden (mit all seinen Vor- und Nachteilen).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Bauteile&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* SN74CB3T3306&lt;br /&gt;
* SN74CBTD3861 (10 Bit,flow through, Betrieb mit 5 Volt)&lt;br /&gt;
* MAX1741 &lt;br /&gt;
* MAX3378E &lt;br /&gt;
* 74AHC126 s.u.&lt;br /&gt;
* ST2378 (bei CSD erhältlich, 3.5 eur, leider TSSOP)&lt;br /&gt;
* TXS0104E (TI: 4-BIT BIDIRECTIONAL VOLTAGE-LEVEL TRANSLATOR FOR OPEN-DRAIN AND PUSH-PULL APPLICATIONS)&lt;br /&gt;
* SN74LVC07A&lt;br /&gt;
* von Analog Devices die ADUM Serie&lt;br /&gt;
&lt;br /&gt;
=== 1,65 V ... 5,5 V ⇔ 1,65 V ... 5,5 V ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Bauteile&#039;&#039;&#039;&lt;br /&gt;
* SN74LVC1T45&lt;br /&gt;
* SN74LVC2T45&lt;br /&gt;
* SN74LVC(H)8T245&lt;br /&gt;
* SN74LVC(H)16T245&lt;br /&gt;
&lt;br /&gt;
=== 1,2 V ... 3,6 V ⇔ 1,65V ... 5,5V ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Bauteile&#039;&#039;&#039;&lt;br /&gt;
* TXB0101&lt;br /&gt;
* TXB0102&lt;br /&gt;
* TXB0104&lt;br /&gt;
* TXB0106&lt;br /&gt;
* TXB0108&lt;br /&gt;
&lt;br /&gt;
=== 1,2 V ... 3,6V ⇔ 1,2 V ... 3,6 V ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Bauteile&#039;&#039;&#039;&lt;br /&gt;
* SN74AVC(H)1T45&lt;br /&gt;
* SN74AVC(H)2T45&lt;br /&gt;
* SN74AVC(H)4T245&lt;br /&gt;
* SN74AVC(H)8T245&lt;br /&gt;
* SN74AVC(H)16T245&lt;br /&gt;
* SN74AVC(H)20T245&lt;br /&gt;
* SN74AVC(H)24T245&lt;br /&gt;
* SN74AVC(H)32T245&lt;br /&gt;
&lt;br /&gt;
=== 1,5 V ... 3,6 V ⇔ 1,5 V ... 5,5 V ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Bauteile&#039;&#039;&#039;&lt;br /&gt;
* 74LVC4245A&lt;br /&gt;
&lt;br /&gt;
== Mit galvanischer Trennung ==&lt;br /&gt;
&lt;br /&gt;
* [[Optokoppler]] (Langsam! Es gibt verschieden schnelle Koppler, aber über 1 MHz kommen sie kaum hinaus. Grundregel: Solche mit Fototransistoren sind am langsamsten, Richtwert 10 kHz, Fotodioden sind schneller, schnelle Optokoppler haben eine gesondert zu speisende Empfängerschaltung.)&lt;br /&gt;
&lt;br /&gt;
[[bild:pw_opto.png]]&lt;br /&gt;
&lt;br /&gt;
* GMR-Koppler von der Firma NVE &lt;br /&gt;
* iCoupler Technologie von der Firma Analog Devices&lt;br /&gt;
* [[Kapazitiver Koppler]] (schnell, begrenzter Potenzialversatz)&lt;br /&gt;
* Transformatorkopplung (nur für gleichspannungsfreie Wechselsignale geeignet; sehr schnell; Beispiel: Netzkarten)&lt;br /&gt;
&lt;br /&gt;
Lit.: &#039;&#039;Galvanische Trennung: Optokoppler, GMR-Koppler oder iCoupler?&#039;&#039;, Siegfried W. Best, Redaktion elektronik industrie, [http://www.elektronik-industrie.de/ei/11,2003/article/2f0082f824c.html elektronik industrie 11-2003, S. 22ff.]&lt;br /&gt;
&lt;br /&gt;
== Praktische Beispiele ==&lt;br /&gt;
&lt;br /&gt;
=== Einfaches RS232-Interface ===&lt;br /&gt;
&lt;br /&gt;
[http://web.archive.org/web/20050122013618/http://www.henrik-reimers.de/control/rs232interface.gif Erfolgreicher Einsatz bis 19200 Baud und bis zu 10 m Leitungslänge]&lt;br /&gt;
Beschränkungen:&lt;br /&gt;
&lt;br /&gt;
* ggf. Platzbedarf&lt;br /&gt;
* Geschwindigkeit s.o.&lt;br /&gt;
&lt;br /&gt;
Beispiel: http://www.hagtech.com/pdf/translator.pdf&lt;br /&gt;
&lt;br /&gt;
=== [[I2C]]-Bus: gemeinsam 3.3V und 5V ===&lt;br /&gt;
&lt;br /&gt;
* [[MSP430]] an 3,3V/5V: http://www-s.ti.com/sc/psheets/slaa148/slaa148.pdf&lt;br /&gt;
&lt;br /&gt;
* Philips [http://www.nxp.com/documents/data_sheet/PCA9515.pdf PCA9515]: I2C Puffer mit Pegelwandlung. Der PCA9515 ist ein I2C-Bus Repeater, welcher I2C Busse mit verschiedenen Spannungen isoliert. Verfügbar bei Reichelt und DigiKey.&lt;br /&gt;
&lt;br /&gt;
* [http://ics.nxp.com/support/documents/interface/pdf/an97055.pdf Philips AN97055 Bi-directional level shifter for I²C-bus and other systems]&lt;br /&gt;
&lt;br /&gt;
* Bevor man ein Philips I2C Chip auswählt sollte man prüfen ob er verfügbar ist und auch das verfügbare Gehäuse wählen. Man sollte auch überlegen ob ein Puffer wirklich gebraucht wird. Wenn man echte I2C ICs mit 5V betreibt, dann sind die Eingänge vom Typ Schmitt Trigger CMOS (z.&amp;amp;nbsp;B. PCF8574). Dann müssen 3.3V Pegel auf 5V umgesetzt werden. Wenn man jedoch SMBUS Ics verwendet (z.&amp;amp;nbsp;B. ADT7461, Silabs 8051) dann sind die Schwellspannungen TTL kompatibel und es ist keine Anpassung notwendig. Für neue Pegelwandler sollte man hier nachschauen. http://www.bus-buffer.com&lt;br /&gt;
&lt;br /&gt;
* [http://www.edn.com/article/CA193193.html &amp;quot;Two-transistor circuit replaces IC&amp;quot;]. Für diese Anwendung kann ENABLE direkt mit 3.3V verbunden werden. Es ist eigentlich nur dazu da, den ICs &amp;quot;hot-swappable&amp;quot; zu machen (kann unter Spannung gesteckt und getrennt werden). Es geht sogar mit nur einem [[Transistor]] [http://www.mikrocontroller.net/topic/92447 siehe Forum]. Man sollte beachten, daß die Schaltung sowohl für SCL als auch SDA benötigt wird. &lt;br /&gt;
* Noch einfachere Lösungen mit nur einem MOSFET und zwei Pull-Up Widerständen pro Leitung sind in den folgenden Links zu finden. &lt;br /&gt;
** http://www.nxp.com/documents/application_note/AN10441.pdf&lt;br /&gt;
** http://www.semiconductors.philips.com/acrobat_download/literature/9398/39340011.pdf (Kapitel 18), bei der Berechnung der erreichbaren Geschwindigkeit dürfen die parasitären Kapazitäten der FETs nicht ignoriert werden&lt;br /&gt;
&lt;br /&gt;
=== Auswählbare Pegel ===&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Frage:&#039;&#039;&#039;&lt;br /&gt;
Ein CMOS Logikpegel zwischen 1,8V, 2,5V und 3,3V (abhängig von der Anwendung) muss auf 5V CMOS Logikpegel gewandelt werden. Es geht nur um diese Richtung mit maximal 8MHz. Es gibt die Stromversorgung für alle Pegel. Ein normaler Komparator wie LM311 ist nicht möglich, da er beim Betrieb mit 5V Versorgunsspannung erst ab 1V zu schalten anfängt. Meine Idee ist die Verwendung eines High Speed OPVs mit R2R Eingang, z.&amp;amp;nbsp;B. LMH6645.&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;&#039;Antworten:&#039;&#039;&#039;&lt;br /&gt;
* Man könnte einen ultra-low threshold N-Kanal MOSFET nehmen und als Open Drain mit einem Pull-Up nach 5V betreiben, BSH103 könnte passen (Schwellspannung ~0,4V).&lt;br /&gt;
* High-Speed Single Supply Komparator wie z.&amp;amp;nbsp;B. [http://www-s.ti.com/sc/ds/tl712.pdf TL712] .&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Frage:&#039;&#039;&#039;&lt;br /&gt;
Ich suchen einen IC, welcher eine Pegelwandlung von 3,3V nach 1,8V, 2,0V oder 5V ermöglicht und während des Betriebs umgeschaltet werden kann.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Antworten:&#039;&#039;&#039;&lt;br /&gt;
* So ein IC ist der Linear [http://www.linear.com/pc/productDetail.jsp?navId=H0,C1,C1007,C1071,P1601 LTC1555L-1.8] . &lt;br /&gt;
&lt;br /&gt;
=== AVR SPI (SDC/MMC)===&lt;br /&gt;
&lt;br /&gt;
Für &#039;&#039;&#039;bidirektionalen Betrieb&#039;&#039;&#039; zwischen 5V-AVR und 3,3V-Geräten und anders herum gibt es den Level-Translator &#039;&#039;&#039;MAX3378E&#039;&#039;&#039; von Maxim.&lt;br /&gt;
&lt;br /&gt;
Wenn die Datenrichtung am SPI im Zielsystem festgelegt ist, reichen &#039;&#039;&#039;unidirektionale Bausteine&#039;&#039;&#039;:&lt;br /&gt;
* 3x von 5V nach 3,3V und 1x von 3,3V nach 5V: &#039;&#039;&#039;MAX3392E&#039;&#039;&#039;&lt;br /&gt;
* 1x von 5V nach 3,3V und 3x von 3,3V nach 5V: &#039;&#039;&#039;MAX3390E&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Zum Anschließen einer SDC/MMC an einen 5V-AVR eignen sich somit der MAX3978E und der MAX3392E. Beide sind u.A. im winzigen TSSOP-14-Gehäuse verfügbar, nehmen sehr wenig Energie auf und eignen sich auch für andere Spannungen. Mit 3,3 und 5V beträgt die garantierte Übertragungsrate 8Mbps.&lt;br /&gt;
&lt;br /&gt;
* [http://datasheets.maxim-ic.com/en/ds/MAX3372E-MAX3393E.pdf Datenblatt]&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit zum Übersetzen zwischen 3,3 und 5V liegt in der Verwendung des &#039;&#039;&#039;74LVC245&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
5V-AVR an eine MMC (ohne Level-Shifter-Baustein):&lt;br /&gt;
* [http://www.microsyl.com/index.php/2010/03/24/led-sign-with-mmc-memory-card/ Projektseite] &lt;br /&gt;
* [http://www.microsyl.com/projects/ledsign/ledsign1.pdf Schaltplan]&lt;br /&gt;
&lt;br /&gt;
=== Mikrocontroller ⇔ Parallelport ([[ISP]]-Dongle, [[JTAG]] Wiggler, ...) ===&lt;br /&gt;
&lt;br /&gt;
Dieser Schaltplan funktioniert auch bei 3,3 V wenn man einen 74&amp;lt;B&amp;gt;HC&amp;lt;/B&amp;gt;244 anstatt eines 74&amp;lt;B&amp;gt;LS&amp;lt;/B&amp;gt;244 verwendet: [http://www.epanorama.net/circuits/parallel_output.html Parallel port interfacing made easy: Simple circuits and programs to show how to use PC parallel port output capabilities].&lt;br /&gt;
&lt;br /&gt;
=== Doppeltes Leitungspaar RX/TX 5V/3,3V ===&lt;br /&gt;
&lt;br /&gt;
Der [http://www.hackaday.com/2008/06/19/sparkfuns-logic-level-converter/ SparkFun&#039;s Logic Level Converter] ist eine Baugruppe mit MOSFETs [http://www.fairchildsemi.com/pf/BS/BSS138.html BSS138] für die Pegelwandlung von 5V auf 3,3V. 5V/2,8V und 5V/1,8V sind ebenfalls machbar.&lt;br /&gt;
&lt;br /&gt;
=== Steuerleitung zwischen Mikrocontroller und FPGA ===&lt;br /&gt;
&lt;br /&gt;
Oftmals werden PLDs oder FPGAs per Microcontroller-Platine angesteuert. Ältere Typen laufen meist als 5V oder sitzen in 5V-kompatiblen Platinen. Sollen moderne FPGAs angesteuert werden, trifft man fast immer auf 3,3-V-Typen, bzw. muss sogar 2,5-V- / 1,8-V-Bänke beschalten, wenn nur noch dort Pins frei sind.&lt;br /&gt;
&lt;br /&gt;
==== Mikrocontroller ⇒ FPGA ====&lt;br /&gt;
&lt;br /&gt;
Die 5 V sind also im Extremfall auf 1,8 V herabzusetzen, was bei einem maximal zulässigen Diodenstrom von 3 mA (Beispiel Xilinx) einen Mindestwiderstand von ca. 1 kΩ erfordert. Die resultierende maximale Schaltfrequenz liegt dann bei einem typischen FPGA-Eingang bei etwa &amp;lt; 500 kHz. Soll der Eingang aus Belastungsgründen nicht mit mehr als 0,3 mA belastet werden, müsste der Widerstand auf 10 kΩ steigen, wodurch die Frequenz auf 1/10 sinkt. Zudem ist der Eingang dann störempfindlicher. Daher ist es besser, man schaltet dem Eingang eine zusätzliche Z-Diode bei und dimensioniert den Vorwiderstand so, dass die Strombelastbarkeit des Mikrocontrollers ausgelastet wird.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Möglichkeit ist es, die Spannung mit einer Diode in Vorwärtsrichtung herabzusetzen. Dann muss jedoch der Vorwiderstand noch exakter toleriert werden und auch Abweichungen der Spannung (Welligkeit) berücksichtigt werden.&lt;br /&gt;
&lt;br /&gt;
==== FPGA ⇒ Mikrocontroller ====&lt;br /&gt;
&lt;br /&gt;
Umgekehrt ist es oft nötig, dass Bausteine einen fremden Chip treiben müssen, dessen Eingang bereits mit einem Pull-Up versehen ist. Über diesen wird dann stets ein Strom in die Schutzdiode eingeprägt, auch wenn der Ausgang auf HIGH geht. Soll z. B. von einem PLD oder einem FPGA aus eine Mikrocontrollerplatine bedient werden, die über einen Pull-Up von 1 kΩ verfügt, würden immer ca. 1 mA in die Schutzdiode eingeprägt. Hier kann eine Seriendiode helfen, die Spannung genügend herabzusetzen, um den Ausgang zu schützen und dennoch die Funktion zu erhalten. Dann steuert ein LOW-Ausgang den Eingang auf geschätzte 1V, was aber meistens für das Erkennen von LOW noch sicher reicht.&lt;br /&gt;
&lt;br /&gt;
== Bauteile ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;74ALVC164245&#039;&#039;&#039; - &#039;&#039;16bit dual supply translating transceiver&#039;&#039;. Eine Seite von 1.5V bis 3.6V, die andere von 1.5 bis 5.5V.&lt;br /&gt;
* &#039;&#039;&#039;74LVX573&#039;&#039;&#039; (unidirektional, Latch, nicht alle Hersteller bauen diesen 5V tolerant!)&lt;br /&gt;
* &#039;&#039;&#039;74LVX245&#039;&#039;&#039; (bidirektional, nicht alle Hersteller bauen diesen 5V tolerant!)&lt;br /&gt;
* &#039;&#039;&#039;74LVX125&#039;&#039;&#039; - &#039;&#039;Low Voltage Quad Buffer with 3-STATE Outputs&#039;&#039;. http://www.fairchildsemi.com/pf/74/74LVX125.html&lt;br /&gt;
* &#039;&#039;&#039;SN74LVC2T45&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;SN74LVC8T245&#039;&#039;&#039; - &#039;&#039;8-Bit Dual-Supply Bus Transceiver with Configurable Voltage Translation and Three-State Outputs&#039;&#039;. http://focus.ti.com/docs/prod/folders/print/sn74lvc8t245.html&lt;br /&gt;
* &#039;&#039;&#039;74LCX244MSA&#039;&#039;&#039; von Fairchild.&lt;br /&gt;
* &#039;&#039;&#039;MAX3377&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;MAX3000&#039;&#039;&#039; 8-Kanal bidirektioneler Pegelwandler ohne Richtungsumschaltung&lt;br /&gt;
* &#039;&#039;&#039;ADG3308&#039;&#039;&#039; 8-Kanal bi-dir. Pegelwandler ohne Richtungsumschaltung, 1,15V..5,5V, 50MBps (hohe Umschaltströme beachten)&lt;br /&gt;
&lt;br /&gt;
Vierfachdioden im kleinen 6-poligen SMD-Gehäuse:&lt;br /&gt;
* http://www.st.com/stonline/products/literature/ds/12635/dsilc6-4xx.pdf&lt;br /&gt;
* http://www.st.com/stonline/products/literature/ds/11599.pdf&lt;br /&gt;
* http://www.st.com/stonline/products/literature/ds/6477/dalc208.pdf&lt;br /&gt;
* [http://www.diodes.com/datasheets/ds30195.pdf QSBT40, vierfach Schottky Terminator für Datenleitungen]&lt;br /&gt;
* [http://www.littlefuse.com/data/en/Data_Sheets/SP724Lead_Free.pdf SP724, Siliziumschutzarray]&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/307702#3316500 Forumsbeitrag]: Entkopplung von FT232 und AVR&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&lt;br /&gt;
* Holmes D., [http://delphys.net/d.holmes/hardware/levelshift.html Bi-directional level-shift with MOSFETs]&lt;br /&gt;
* Gaurang Kavaiya, [http://www.edn.com/design/analog/4318916/Don-t-pay-for-level-translators-in-systems-using-multiple-power-supply-voltages Don’t pay for level translators in systems using multiple power-supply voltages], EDN, MAY 25, 2006, 81-86&lt;br /&gt;
* [http://www.elektronik-kompendium.de/public/schaerer/scf3_lc.htm Einfacher Pegelwandler im ELKO]&lt;br /&gt;
* [http://www.prog-link.com/dcf77/dcf77-17.html Pegelwandler für DFC77 Module]&lt;br /&gt;
* [http://elektronik.kai-uwe-schmidt.de/index.php?page=mp3_blueschaltung Pegelwandler für [[I2C]] Bus in einem MP3 Player]&lt;br /&gt;
* [http://www.mikrocontroller.net/attachment.php/256452/levelshifter.pdf Application Note von Philips, I2C Pegelwandler]&lt;br /&gt;
* [http://www.semiconductors.philips.com/acrobat_download/literature/9398/39340011.pdf I2C Spezifikation]  &lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-1-234277.html#new Forumsbeitrag zum Thema 1,8V-5V Pegelwandler] &lt;br /&gt;
* [http://www.st.com/stonline/products/literature/ds/5186/74lcx16245.pdf 74LCX16245, 16 Bit Pegelwandler]&lt;br /&gt;
* [http://www.standardics.nxp.com/products/lvc/buffers/ LVC Logikfamilie]&lt;br /&gt;
* [http://www.standardics.nxp.com/products/lvc/transceivers/ LVC Tranceiver]&lt;br /&gt;
* [http://www.microchip.com/stellent/groups/techpub_sg/documents/devicedoc/en026368.pdf 3V Tips ‘n Tricks] (PDF) von Microchip&lt;br /&gt;
* [http://www.ti.com/lit/an/slaa148/slaa148.pdf Interfacing the 3-V MSP430 to 5-V Circuits] (PDF) von Texas Instruments&lt;br /&gt;
&lt;br /&gt;
[[Category:Bauteile]]&lt;br /&gt;
[[Kategorie:Datenübertragung]]&lt;/div&gt;</summary>
		<author><name>62.157.123.104</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Entprellung&amp;diff=84375</id>
		<title>Entprellung</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Entprellung&amp;diff=84375"/>
		<updated>2014-08-06T08:47:01Z</updated>

		<summary type="html">&lt;p&gt;62.157.123.104: Typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Problembeschreibung ==&lt;br /&gt;
Mechanische [[Schalter]] wie [[Drehgeber]] neigen beim Ein- und Ausschalten zum sogenannten &#039;&#039;&#039;Prellen&#039;&#039;&#039;, d.h sie schalten schnell mehrfach aus und ein, verursacht durch mechanische Vibrationen des Schaltkontaktes, sofern sie nicht dagegen geschützt sind. Vereinfacht dargestellt, sieht eine von einem Schalter oder Taster geschaltete Spannung beim Schalten wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Entprellen.png]]&lt;br /&gt;
&lt;br /&gt;
Für die Vermeidung bzw. Auswertung dieses unsauberen Signals gibt es verschiedene Ansätze:&lt;br /&gt;
&lt;br /&gt;
== Hardwareentprellung ==&lt;br /&gt;
&lt;br /&gt;
===Prellfreie Schalter===&lt;br /&gt;
&lt;br /&gt;
Für Spezialanwendungen hält die elektromechanische Industrie verschiedene Sonderkonstruktionen bereit, die saubere Schaltzustände nach Aussen generieren, indem sie entweder eine mechanische Dämpfung in Form eines selbsthemmenden Federmechanismus oder eine integrierte elektronische Signalverzögerung benutzen.&lt;br /&gt;
&lt;br /&gt;
Solche Systeme sind jedoch teuer und werden meist nur im Leistungsbereich eingesetzt.&lt;br /&gt;
&lt;br /&gt;
===Wechselschalter===&lt;br /&gt;
&lt;br /&gt;
Für die Entprellung von Wechselschaltern (engl. Double Throw Switch) kann ein klassisches RS-[[Flipflop]] genutzt werden. Bei dieser Variante werden neben zwei NAND-Gattern nur noch zwei Pull-Up Widerstände benötigt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:NAND_debouncer.png|thumb|left|350px|&#039;&#039;&#039;Taster entprellen mit NAND-RS-Flipflop&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In der gezeigten Schalterstellung liegt an der Position /S der Pegel 0 an. Damit ist das Flipflop gesetzt und der Ausgang auf dem Pegel 1. Schließt der Schalter zwischen den Kontakten 2 und 3, liegt an der Postion /R der Pegel 0 an. Dies bedeutet, dass der Ausgang des Flipflops auf den Pegel 0 geht. Sobald der Schalter von einem zum anderen Kontakt wechselt, beginnt er in der Regel zu prellen. Während des Prellens wechselt der Schalter zwischen den beiden Zuständen &amp;quot;Schalter berührt Kontakt&amp;quot; und &amp;quot;Schalter ist frei in der Luft&amp;quot;. Der Ausgang des Flipflops bleibt in dieser Prellzeit aber stabil, da der Schalter während des Prellens nie den gegenüberliegenden Kontakt berührt und das RS-Flipflop seinen Zustand allein halten kann. Die Prellzeit ist stark vom Schaltertyp abhängig und liegt zwischen 0,1 und 10ms. Die Dimensionierung der Widerstände ist relativ unkritisch. Als Richtwert können hier 100kOhm verwendet werden.&lt;br /&gt;
&lt;br /&gt;
====Wechselschalter ohne Flip-Flop====&lt;br /&gt;
&lt;br /&gt;
Wenn man mal gerade kein Flip-Flop zur Hand hat, kann man sich auch mit dieser Schaltung behelfen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:WechselEntprellC.PNG|thumb|left|350px|&#039;&#039;&#039;Wechsler entprellen mit Kondensator&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zur Funktionsweise:&lt;br /&gt;
Beim Umschalten wird der Kondensator immer sofort umgeladen.&lt;br /&gt;
Während der Kontakt prellt, befindet er sich in der Luft und hat keinerlei Verbindung. Während dieser Zeit übernimmt der Kondensator das halten des Pegels.&lt;br /&gt;
&lt;br /&gt;
Dimensionierung:&lt;br /&gt;
Ist der entprellte Taster an ein IC Angeschlossen, ist der &#039;&#039;Input Leakage Current&#039;&#039; der ausschlaggebende Strom. Falls weitere Ströme fließen sind diese mit zu berücksichtigen. Bei einem Mikrocontroller von Atmel sind 1µA typisch.&lt;br /&gt;
Es gilt:&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{dU}{dt} = \frac{I}{C}&amp;lt;/math&amp;gt;&lt;br /&gt;
Da eine Prellung ca. 10ms dauert und die Spannung in dieser Zeit beispielsweise um maximal 0,5V fallen soll kommt man auf folgende Kapazität:&lt;br /&gt;
:&amp;lt;math&amp;gt; C = \frac{I \cdot dt}{dU} = \frac{1\mu A \cdot 10ms}{0,5V} = 20nF &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um Stromspitzen zu verringern kann ein Widerstand mit eingefügt werden. Eine Zeitkonstante von 1µs bis 1ms scheint sinnvoll. Also 500 Ohm bis 500kOhm sind nutzbar, wobei bei niedrigem Widerstand die Stromspitzen höher sind, und bei 500kOhm der Pinstrom störend wird.&lt;br /&gt;
&lt;br /&gt;
===Einfacher Taster===&lt;br /&gt;
&lt;br /&gt;
Auch wenn das RS-Flipflop sehr effektiv ist, wird diese Variante der Entprellung nur selten angewendet. Grund dafür ist, dass in Schaltungen häufiger einfache Taster eingesetzt werden. Diese sind oft kleiner und preisgünstiger. Um einfache Taster (engl. Single Throw Switch) zu entprellen, kann ein einfacher RC-Tiefpass eingesetzt werden. Hierbei wird ein Kondensator über einen Widerstand je nach Schalterstellung auf- oder entladen. Das RC-Glied bildet einen Tiefpass, sodass die Spannung über den Kondensator nicht von einen Pegel auf den anderen springen kann.&lt;br /&gt;
&lt;br /&gt;
[[Bild:RC_debouncer.png|thumb|left|300px|Taster entprellen mit RC-Entpreller]]&lt;br /&gt;
&lt;br /&gt;
[[Datei:Entprellen1a.png|thumb|350px| Entstehender Spannungsverlauf]]&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
Wenn der Schalter geöffnet ist, lädt sich der Kondensator langsam über die beiden Widerstände R&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; und R&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; auf V&amp;lt;sub&amp;gt;cc&amp;lt;/sub&amp;gt; auf. Beim Erreichen der Umschaltschwelle springt der Ausgang auf den Pegel 0. Wird der Schalter geschlossen, entlädt sich der Kondensator langsam über den Widerstand R&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;. Demnach ändert sich der Ausgang des Inverters auf den Pegel 1. Während der Taster prellt, kann sich die Spannung über dem Kondensator nicht sprunghaft ändern, da das Auf- und Entladen eher langsam über die Widerstände erfolgt. Außerdem sind die Schaltschwellen für den Übergang LOW-&amp;gt;HIGH und HIGH-&amp;gt;LOW stark verschieden (Hysterese, siehe Artikel [[Schmitt-Trigger]]). Bei richtiger Dimensionierung der Bauelemente wird somit der Ausgang des Inverters prellfrei.&lt;br /&gt;
&lt;br /&gt;
Zu beachten ist, dass der Inverter &#039;&#039;&#039;unbedingt&#039;&#039;&#039; einer mit [[Schmitt-Trigger]]-Eingängen sein muss, weil bei Standard-Logikeingängen im Bereich von üblicherweise 0,8V - 2,0V der Ausgang nicht definiert ist. Als Inverter kann zum Beispiel der 74HC14 oder der CD40106 (pinkompatibel) eingesetzt werden. Alternativ kann auch ein CD4093 eingesetzt werden. Bei dem CD4093 handelt es sich um NAND-Gatter mit Schmitt-Trigger-Eingängen. Um aus einem NAND-Gatter einen Inverter zu machen, müssen einfach nur die beiden Eingänge verbunden werden oder ein Eingang fest auf HIGH gelegt werden.&lt;br /&gt;
&lt;br /&gt;
Für eine geeignete Dimensionierung muss man etwas mit den Standardformeln für einen Kondensator jonglieren. Die Spannung über den Kondensator beim Entladen berechnet sich nach:&lt;br /&gt;
:&amp;lt;math&amp;gt;U_C(t) = U_0 \cdot e^{\frac{-t}{R_2 C_1}}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit der Ausgang des Inverters stabil ist, muss die Spannung über den Kondensator und damit die Spannung am Eingang des Inverters über der Spannung bleiben, bei welcher der Inverter umschaltet. Diese Schwellwertspannung ist genau die zeitabhängige Spannung über den Kondensator.&lt;br /&gt;
:&amp;lt;math&amp;gt;U_C(t)\!\ = U_{th}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Durch Umstellen der Formel ergibt sich nun:&lt;br /&gt;
:&amp;lt;math&amp;gt;R_2=\frac{-t}{C_1 \cdot ln\left(\frac{U_{th}}{U_0} \right)}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ein Taster prellt üblicherweise etwa 10ms. Zur Sicherheit kann bei der Berechnung des Widerstandes eine Prellzeit von 20ms angenommen werden. U_0 ist die Betriebsspannung also Vcc. Die Schwellwertspannung muss aus dem Datenblatt des eingesetzten Schmitt-Triggers abgelesen werden. Beim 74HC14 beträgt der gesuchte Wert 2,0V. Nimmt man für den Kondensator 1µF und beträgt die  Betriebsspannung 5V, ergibt sich für den Widerstand ein Wert von etwa 22kOhm.&lt;br /&gt;
&lt;br /&gt;
Wird der Schalter geöffnet, lädt sich der Kondensator nach folgender Formel auf:&lt;br /&gt;
:&amp;lt;math&amp;gt;U_C(t) = U_0 \cdot \left( 1-e^{\frac{-t}{(R_1+R_2)\cdot C_1}} \right)&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit U_th=U_C ergibt das Umstellen nach (R_1+R_2):&lt;br /&gt;
:&amp;lt;math&amp;gt;R_1+R_2 = \frac{-t}{C_1 \cdot ln\left(1-\frac{U_{th}}{U_0} \right)} &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für die Schwellspannung lässt sich aus dem Datenblatt ein Wert von 2,3V ablesen. Mit diesem Wert und den Annahmen von oben ergibt sich für R_1+R_2 ein Wert von 32kOhm. Somit ergibt sich für R_1 ein Wert von etwa 10kOhm.&lt;br /&gt;
&lt;br /&gt;
Anmerkung: Beim 74LS14 von Hitachi z.&amp;amp;nbsp;B. sind die oberen und unteren Schaltschwellwerte unterschiedlich. Es muss darauf geachtet werden, dass U_{th} beim Entladen die untere Schwelle und U_{th} beim Laden die obere Schwelle einnimmt.&lt;br /&gt;
&lt;br /&gt;
== Softwareentprellung ==&lt;br /&gt;
&lt;br /&gt;
In den Zeiten der elektronischen Auswertung von Tastern und Schaltern ist das softwaretechnische Entprellen oft billiger, als die Benutzung eines teuren Schalters. Daher werden heute z.B. auch Computertastaturen nicht mehr mit prellarmen Tasten oder Entprellkondensatoren ausgestattet.&lt;br /&gt;
&lt;br /&gt;
Bei Verwendung des in den meisten Geräten ohnehin vorhandenen Mikrocontrollers z.B., kann man sich die zusätzliche Hardware sparen, da die Entprellung in Software praktisch genauso gut funktioniert. Dabei ist nur zu beachten, dass zusätzliche Rechenleistung und je nach Umsetzung auch einige Hardwareressourcen (z.B. Timer) benötigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Flankenerkennung ===&lt;br /&gt;
Bei einem Taster gibt es insgesamt 4 theoretische Zustände:&lt;br /&gt;
&lt;br /&gt;
* 1. war nicht gedrückt und ist nicht gedrückt&lt;br /&gt;
* 2. war nicht gedrückt und ist gedrückt (steigende Flanke)&lt;br /&gt;
* 3. war gedrückt und ist immer noch gedrückt&lt;br /&gt;
* 4. war gedrückt und ist nicht mehr gedrückt (fallende Flanke)&lt;br /&gt;
&lt;br /&gt;
Diese einzelnen Zustände lassen sich jetzt bequem abfragen/durchlaufen. Die Entprellung geschieht dabei durch die ganze Laufzeit des Programms. Die Taster werden hierbei als Active-Low angeschlossen, um die internen Pull-Ups zu nutzen.&lt;br /&gt;
&lt;br /&gt;
Diese Routine gibt für den Zustand &amp;quot;steigende Flanke&amp;quot; den Wert &amp;quot;1&amp;quot; zurück, sonst &amp;quot;0&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
#define TASTERPORT PINC&lt;br /&gt;
#define TASTERBIT PINC1&lt;br /&gt;
&lt;br /&gt;
char taster(void)&lt;br /&gt;
{&lt;br /&gt;
    static unsigned char zustand;&lt;br /&gt;
    char rw = 0;&lt;br /&gt;
&lt;br /&gt;
    if(zustand == 0 &amp;amp;&amp;amp; !(TASTERPORT &amp;amp; (1&amp;lt;&amp;lt;TASTERBIT)))   //Taster wird gedrueckt (steigende Flanke)&lt;br /&gt;
    {&lt;br /&gt;
        zustand = 1;&lt;br /&gt;
        rw = 1;&lt;br /&gt;
    }&lt;br /&gt;
    else if (zustand == 1 &amp;amp;&amp;amp; !(TASTERPORT &amp;amp; (1&amp;lt;&amp;lt;TASTERBIT)))   //Taster wird gehalten&lt;br /&gt;
    {&lt;br /&gt;
         zustand = 2;&lt;br /&gt;
         rw = 0;&lt;br /&gt;
    }&lt;br /&gt;
    else if (zustand == 2 &amp;amp;&amp;amp; (TASTERPORT &amp;amp; (1&amp;lt;&amp;lt;TASTERBIT)))   //Taster wird losgelassen (fallende Flanke)&lt;br /&gt;
    {&lt;br /&gt;
        zustand = 3;&lt;br /&gt;
        rw = 0;&lt;br /&gt;
    }&lt;br /&gt;
    else if (zustand == 3 &amp;amp;&amp;amp; (TASTERPORT &amp;amp; (1&amp;lt;&amp;lt;TASTERBIT)))   //Taster losgelassen&lt;br /&gt;
    {&lt;br /&gt;
        zustand = 0;&lt;br /&gt;
        rw = 0;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return rw;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eine Erweiterung, damit beliebig lange das Halten einer Taste erkannt wird kann man ganz einfach so implementieren:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
    // zustand kann entweder zum ersten mal als gehalten detektiert werden oder aber jedes weitere mal&lt;br /&gt;
    else if (((zustand == 1) || (zustand == 2)) &amp;amp;&amp;amp; !(TASTERPORT &amp;amp; (1&amp;lt;&amp;lt;TASTERBIT)))   //Taster wird gehalten&lt;br /&gt;
    {&lt;br /&gt;
         zustand = 2;&lt;br /&gt;
         rw = 0;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Warteschleifen-Verfahren ===&lt;br /&gt;
&lt;br /&gt;
Soll nun mit einem Mikrocontroller gezählt werden, wie oft ein Kontakt oder ein Relais geschaltet wird, muss das Prellen des Kontaktes exakt berücksichtigt - und von einem gewollten Mehrfachschalten abgegrenzt werden, da sonst  möglicherweise Fehlimpulse gezählt- oder andererseits echte Schaltvorgänge übersprungen werden. Dies muss beim Schreiben des Programms hinsichtlich des Abtastens des Kontaktes unbedingt Rechnung getragen werden.&lt;br /&gt;
&lt;br /&gt;
Beim folgenden einfachen Beispiel für eine Entprellung ist zu beachten, dass der AVR im Falle eines Tastendrucks 200ms wartet, also brach liegt. Bei zeitkritischen Anwendungen sollte man ein anderes Verfahren nutzen (z.&amp;amp;nbsp;B. Abfrage der Tastenzustände in einer Timer-Interrupt-Service-Routine).&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;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
#ifndef F_CPU&lt;br /&gt;
#warning &amp;quot;F_CPU war noch nicht definiert, wird nun mit 3686400 definiert&amp;quot;&lt;br /&gt;
#define F_CPU 3686400UL     /* Quarz mit 3.6864 Mhz  */&lt;br /&gt;
#endif&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;     /* bei alter avr-libc: #include &amp;lt;avr/delay.h&amp;gt; */      &lt;br /&gt;
&lt;br /&gt;
/* Einfache Funktion zum Entprellen eines Tasters */&lt;br /&gt;
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)&lt;br /&gt;
{&lt;br /&gt;
    if ( !(*port &amp;amp; (1 &amp;lt;&amp;lt; pin)) )&lt;br /&gt;
    {&lt;br /&gt;
        /* Pin wurde auf Masse gezogen, 100ms warten   */&lt;br /&gt;
        _delay_ms(50);   // Maximalwert des Parameters an _delay_ms &lt;br /&gt;
        _delay_ms(50);   // beachten, vgl. Dokumentation der avr-libc&lt;br /&gt;
        if ( *port &amp;amp; (1 &amp;lt;&amp;lt; pin) )&lt;br /&gt;
        {&lt;br /&gt;
            /* Anwender Zeit zum Loslassen des Tasters geben */&lt;br /&gt;
            _delay_ms(50);&lt;br /&gt;
            _delay_ms(50); &lt;br /&gt;
            return 1;&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
    DDRB &amp;amp;= ~( 1 &amp;lt;&amp;lt; PB0 );        /* PIN PB0 auf Eingang Taster)  */&lt;br /&gt;
    PORTB |= ( 1 &amp;lt;&amp;lt; PB0 );        /* Pullup-Widerstand aktivieren */&lt;br /&gt;
    ...&lt;br /&gt;
    if (debounce(&amp;amp;PINB, PB0))&lt;br /&gt;
    {&lt;br /&gt;
        /* Falls Taster an PIN PB0 gedrueckt     */&lt;br /&gt;
        /* LED an Port PD7 an- bzw. ausschalten: */&lt;br /&gt;
        PORTD = PORTD ^ ( 1 &amp;lt;&amp;lt; PD7 );&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die obige Routine hat leider mehrere Nachteile:&lt;br /&gt;
* sie detektiert nur das Loslassen (unergonomisch)&lt;br /&gt;
* sie verzögert die Mainloop immer um 100ms bei gedrückter Taste&lt;br /&gt;
* sie verliert Tastendrücke, je mehr die Mainloop zu tun hat.&lt;br /&gt;
&lt;br /&gt;
Eine ähnlich einfach zu benutzende Routine, aber ohne all diese Nachteile findet sich im Forenthread&lt;br /&gt;
[http://www.mikrocontroller.net/topic/164194#new Entprellung für Anfänger]&lt;br /&gt;
&lt;br /&gt;
Der &#039;&#039;DEBOUNCE&#039;&#039; Befehl in dem BASIC-Dialekt BASCOM für AVR ist ebenfalls nach dem Warteschleifen-Verfahren programmiert. Die Wartezeit beträgt standardmäßig 25 ms, kann aber vom Anwender überschrieben werden. Vgl.  [http://avrhelp.mcselec.com/bascom-avr.html?DEBOUNCE BASCOM Online-Manual zu DEBOUNCE].&lt;br /&gt;
&lt;br /&gt;
Eine C-Implementierung für eine Tastenabfrage mit Warteschleife ist im Artikel [[AVR-GCC-Tutorial#IO-Register_als_Parameter_und_Variablen|AVR-GCC-Tutorial: IO-Register als Parameter und Variablen]] angeben.&lt;br /&gt;
&lt;br /&gt;
Der Nachteil dieses Verfahrens ist, dass der Controller durch die Warteschleife blockiert wird. Günstiger ist die Implementierung mit einem Timer-Interrupt.&lt;br /&gt;
&lt;br /&gt;
==== Warteschleifenvariante mit Maske und Pointer (nach Christian Riggenbach) ====&lt;br /&gt;
&lt;br /&gt;
Hier eine weitere Funktion, um Taster zu entprellen: Durch den zusätzlichen Code kann eine Entprellzeit von durchschnittlich 1-3ms (mindestens 8*150µs = 1ms) erreicht werden. Grundsätzlich prüft die Funktion den Pegel der Pins auf einem bestimmten Port. Wenn die/der Pegel 8 Mal konstant war, wird die Schleife verlassen. Diese Funktion kann sehr gut eingesetzt werden, um in einer Endlosschleife Taster anzufragen, da sie, wie erwähnt, eine kurze Wartezeit hat.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
void entprellung( volatile uint8_t *port, uint8_t maske ) {&lt;br /&gt;
  uint8_t   port_puffer;&lt;br /&gt;
  uint8_t   entprellungs_puffer;&lt;br /&gt;
&lt;br /&gt;
  for( entprellungs_puffer=0 ; entprellungs_puffer!=0xff ; ) {&lt;br /&gt;
    entprellungs_puffer&amp;lt;&amp;lt;=1;&lt;br /&gt;
    port_puffer = *port;&lt;br /&gt;
    _delay_us(150);&lt;br /&gt;
    if( (*port &amp;amp; maske) == (port_puffer &amp;amp; maske) )&lt;br /&gt;
      entprellungs_puffer |= 0x01;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Die Funktion wird wie folgt aufgerufen:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
  // Bugfix 20100414&lt;br /&gt;
  // http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_port_pass&lt;br /&gt;
  entprellung( &amp;amp;PINB, (1&amp;lt;&amp;lt;PINB2) ); // ggf. Prellen abwarten &lt;br /&gt;
  if( PINB &amp;amp; (1&amp;lt;&amp;lt;PINB2) )           // dann stabilen Wert einlesen&lt;br /&gt;
  {&lt;br /&gt;
    // mach was&lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
  {&lt;br /&gt;
    // mach was anderes&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Als Maske kann ein beliebiger Wert übergeben werden. Sie verhindert, dass nichtverwendete Taster die Entprellzeit negativ beeinflussen.&lt;br /&gt;
&lt;br /&gt;
==== Debounce-Makro von Peter Dannegger ====&lt;br /&gt;
&lt;br /&gt;
Peter Dannegger hat in [http://www.mikrocontroller.net/topic/164194#1566921 &amp;quot;Entprellen für Anfänger&amp;quot;] folgende vereinfachtes Entprellverfahren beschrieben. Das Makro arbeitet in der Originalversion mit &#039;&#039;active low&#039;&#039; geschalteten Tastern, kann aber einfach für  &#039;&#039;active high&#039;&#039; geschaltete Taster angepasst werden ([[Pollin Funk-AVR-Evaluationsboard#Tasty Reloaded|Tasty Reloaded]]). &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/************************************************************************/&lt;br /&gt;
/*                                                                      */&lt;br /&gt;
/*                      Not so powerful Debouncing Example              */&lt;br /&gt;
/*                      No Interrupt needed                             */&lt;br /&gt;
/*                                                                      */&lt;br /&gt;
/*              Author: Peter Dannegger                                 */&lt;br /&gt;
/*                                                                      */&lt;br /&gt;
/************************************************************************/&lt;br /&gt;
// Target: ATtiny13&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#define F_CPU 9.6e6&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define debounce( port, pin )                                         \&lt;br /&gt;
({                                                                    \&lt;br /&gt;
  static uint8_t flag = 0;     /* new variable on every macro usage */  \&lt;br /&gt;
  uint8_t i = 0;                                                      \&lt;br /&gt;
                                                                      \&lt;br /&gt;
  if( flag ){                  /* check for key release: */           \&lt;br /&gt;
    for(;;){                   /* loop ... */                         \&lt;br /&gt;
      if( !(port &amp;amp; 1&amp;lt;&amp;lt;pin) ){  /* ... until key pressed or ... */     \&lt;br /&gt;
        i = 0;                 /* 0 = bounce */                       \&lt;br /&gt;
        break;                                                        \&lt;br /&gt;
      }                                                               \&lt;br /&gt;
      _delay_us( 98 );         /* * 256 = 25ms */                     \&lt;br /&gt;
      if( --i == 0 ){          /* ... until key &amp;gt;25ms released */     \&lt;br /&gt;
        flag = 0;              /* clear press flag */                 \&lt;br /&gt;
        i = 0;                 /* 0 = key release debounced */        \&lt;br /&gt;
        break;                                                        \&lt;br /&gt;
      }                                                               \&lt;br /&gt;
    }                                                                 \&lt;br /&gt;
  }else{                       /* else check for key press: */        \&lt;br /&gt;
    for(;;){                   /* loop ... */                         \&lt;br /&gt;
      if( (port &amp;amp; 1&amp;lt;&amp;lt;pin) ){   /* ... until key released or ... */    \&lt;br /&gt;
        i = 0;                 /* 0 = bounce */                       \&lt;br /&gt;
        break;                                                        \&lt;br /&gt;
      }                                                               \&lt;br /&gt;
      _delay_us( 98 );         /* * 256 = 25ms */                     \&lt;br /&gt;
      if( --i == 0 ){          /* ... until key &amp;gt;25ms pressed */      \&lt;br /&gt;
        flag = 1;              /* set press flag */                   \&lt;br /&gt;
        i = 1;                 /* 1 = key press debounced */          \&lt;br /&gt;
        break;                                                        \&lt;br /&gt;
      }                                                               \&lt;br /&gt;
    }                                                                 \&lt;br /&gt;
  }                                                                   \&lt;br /&gt;
  i;                           /* return value of Macro */            \&lt;br /&gt;
})&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
   Testapplication&lt;br /&gt;
 */&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
  DDRB  &amp;amp;= ~(1&amp;lt;&amp;lt;PB0);&lt;br /&gt;
  PORTB |=   1&amp;lt;&amp;lt;PB0;&lt;br /&gt;
  DDRB  |=   1&amp;lt;&amp;lt;PB2;&lt;br /&gt;
  DDRB  &amp;amp;= ~(1&amp;lt;&amp;lt;PB1);&lt;br /&gt;
  PORTB |=   1&amp;lt;&amp;lt;PB1;&lt;br /&gt;
  DDRB  |=   1&amp;lt;&amp;lt;PB3;&lt;br /&gt;
  for(;;){&lt;br /&gt;
    if( debounce( PINB, PB1 ) )&lt;br /&gt;
      PORTB ^= 1&amp;lt;&amp;lt;PB2;&lt;br /&gt;
    if( debounce( PINB, PB0 ) )&lt;br /&gt;
      PORTB ^= 1&amp;lt;&amp;lt;PB3;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn das Makro für die gleiche Taste (Pin) an mehreren Stellen aufgerufen werden soll, muss eine Funktion angelegt werden, damit beide Aufrufe an die gleiche Zustandsvariable &#039;&#039;flag&#039;&#039; auswerten [http://www.mikrocontroller.net/topic/195914#1918727]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// Hilfsfunktion&lt;br /&gt;
uint8_t debounce_C1( void )&lt;br /&gt;
{&lt;br /&gt;
  return debounce(PINC, PC1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Beispielanwendung&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
  DDRB  |=   1&amp;lt;&amp;lt;PB2;&lt;br /&gt;
  DDRB  |=   1&amp;lt;&amp;lt;PB3;&lt;br /&gt;
  DDRC  &amp;amp;= ~(1&amp;lt;&amp;lt;PC1);&lt;br /&gt;
  PORTC |=   1&amp;lt;&amp;lt;PC1; // Pullup für Taster&lt;br /&gt;
&lt;br /&gt;
  for(;;){&lt;br /&gt;
    if( debounce_C1() )  // nicht: debounce(PINC, PC1)&lt;br /&gt;
      PORTB ^= 1&amp;lt;&amp;lt;PB2;&lt;br /&gt;
    if( debounce_C1() )  // nicht: debounce(PINC, PC1)&lt;br /&gt;
      PORTB ^= 1&amp;lt;&amp;lt;PB3;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Timer-Verfahren (nach Peter Dannegger) ===&lt;br /&gt;
&lt;br /&gt;
==== Grundroutine (AVR Assembler) ====&lt;br /&gt;
&lt;br /&gt;
Siehe dazu: [http://www.mikrocontroller.net/forum/read-4-20435.html#new Forum] &lt;br /&gt;
&lt;br /&gt;
Vorteile&lt;br /&gt;
* besonders kurzer Code&lt;br /&gt;
* schnell&lt;br /&gt;
&lt;br /&gt;
Außerdem können 8 Tasten (aktiv low) gleichzeitig bearbeitet werden, es dürfen also&lt;br /&gt;
alle exakt zur selben Zeit gedrückt werden. Andere Routinen können z.&amp;amp;nbsp;B. nur eine Taste verarbeiten, d.h. die zuerst oder zuletzt gedrückte gewinnt, oder es kommt Unsinn heraus.&lt;br /&gt;
&lt;br /&gt;
Die eigentliche Einlese- und Entprellroutine ist nur 8 Instruktionen&lt;br /&gt;
kurz. Der entprellte Tastenzustand ist im Register &#039;&#039;key_state&#039;&#039;. Mit nur 2 weiteren Instruktionen wird dann der Wechsel von &#039;&#039;Taste offen&#039;&#039; zu&lt;br /&gt;
&#039;&#039;Taste gedrückt&#039;&#039; erkannt und im Register &#039;&#039;key_press&#039;&#039; abgelegt. Im Beispielcode werden dann damit 8 LEDs ein- und ausgeschaltet. Jede Taste entspricht einem Bit in den Registern, d.h. die Verarbeitung erfolgt bitweise mit logischen Operationen. Zum Verständnis empfiehlt es sich daher, die Logikgleichungen mit Gattern für ein Bit = eine Taste aufzumalen. Die Register kann man sich als Flipflops denken, die mit der Entprellzeit als Takt arbeiten. D.h. man kann das auch so z.&amp;amp;nbsp;B. in einem GAL22V10 realisieren.&lt;br /&gt;
&lt;br /&gt;
Als Kommentar sind neben den einzelnen Instruktionen alle 8 möglichen&lt;br /&gt;
Kombinationen der 3 Signale dargestellt.&lt;br /&gt;
&lt;br /&gt;
Beispielcode für AVR (Assembler):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
.nolist&lt;br /&gt;
.include &amp;quot;c:\avr\inc\1200def.inc&amp;quot;&lt;br /&gt;
.list&lt;br /&gt;
.def  save_sreg         = r0&lt;br /&gt;
.def  iwr0              = r1&lt;br /&gt;
.def  iwr1              = r2&lt;br /&gt;
&lt;br /&gt;
.def  key_old           = r3&lt;br /&gt;
.def  key_state         = r4&lt;br /&gt;
.def  key_press         = r5&lt;br /&gt;
&lt;br /&gt;
.def  leds              = r16&lt;br /&gt;
.def  wr0               = r17&lt;br /&gt;
&lt;br /&gt;
.equ  key_port          = pind&lt;br /&gt;
.equ  led_port          = portb&lt;br /&gt;
&lt;br /&gt;
      rjmp   init&lt;br /&gt;
.org OVF0addr		;timer interrupt 24ms&lt;br /&gt;
      in     save_sreg, SREG&lt;br /&gt;
get8key:                               ;/old      state     iwr1      iwr0&lt;br /&gt;
      mov    iwr0, key_old             ;00110011  10101010            00110011&lt;br /&gt;
      in     key_old, key_port         ;11110000&lt;br /&gt;
      eor    iwr0, key_old             ;                              11000011&lt;br /&gt;
      com    key_old                   ;00001111&lt;br /&gt;
      mov    iwr1, key_state           ;                    10101010&lt;br /&gt;
      or     key_state, iwr0           ;          11101011&lt;br /&gt;
      and    iwr0, key_old             ;                              00000011&lt;br /&gt;
      eor    key_state, iwr0           ;          11101000&lt;br /&gt;
      and    iwr1, iwr0                ;                    00000010&lt;br /&gt;
      or     key_press, iwr1           ;store key press detect&lt;br /&gt;
;&lt;br /&gt;
;			insert other timer functions here&lt;br /&gt;
;&lt;br /&gt;
      out    SREG, save_sreg&lt;br /&gt;
      reti&lt;br /&gt;
;-------------------------------------------------------------------------&lt;br /&gt;
init:&lt;br /&gt;
      ldi    wr0, 0xFF&lt;br /&gt;
      out    ddrb, wr0&lt;br /&gt;
      ldi    wr0, 1&amp;lt;&amp;lt;CS02 | 1&amp;lt;&amp;lt;CS00    ;divide by 1024 * 256&lt;br /&gt;
      out    TCCR0, wr0&lt;br /&gt;
      ldi    wr0, 1&amp;lt;&amp;lt;TOIE0             ;enable timer interrupt&lt;br /&gt;
      out    TIMSK, wr0&lt;br /&gt;
&lt;br /&gt;
      clr    key_old&lt;br /&gt;
      clr    key_state&lt;br /&gt;
      clr    key_press&lt;br /&gt;
      ldi    leds, 0xFF&lt;br /&gt;
main: cli&lt;br /&gt;
      eor    leds, key_press           ;toggle LEDs&lt;br /&gt;
      clr    key_press                 ;clear, if key press action done&lt;br /&gt;
      sei&lt;br /&gt;
      out    led_port, leds&lt;br /&gt;
      rjmp   main&lt;br /&gt;
;-------------------------------------------------------------&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Komfortroutine (C für AVR) ====&lt;br /&gt;
&lt;br /&gt;
Siehe dazu: [http://www.mikrocontroller.net/forum/read-4-310276.html Forum]&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Anmerkung&#039;&#039;&#039; Wenn statt active-low (Ruhezustand High) active-high (Ruhezustand Low) verwendet wird muss eine Zeile geändert werden siehe:&lt;br /&gt;
[http://www.mikrocontroller.net/forum/read-4-310276.html gesamter Beitrag im Forum], &lt;br /&gt;
[http://www.mikrocontroller.net/topic/48465#606555 Stelle 1 im Beitrag], ([http://www.mikrocontroller.net/topic/48465#2306398 Stelle 2 im Beitrag] muss *nicht* geändert werden, da hier die Polarität gar keinen Einfluß hat).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Anmerkung 2&#039;&#039;&#039; Zur Initialisierung siehe [http://www.mikrocontroller.net/topic/48465#3572793 Forum]&lt;br /&gt;
&lt;br /&gt;
Funktionsprinzip wie oben plus zusätzliche Features:  &lt;br /&gt;
* Kann Tasten sparen durch unterschiedliche Aktionen bei kurzem oder langem Drücken&lt;br /&gt;
* Wiederholfunktion, z.&amp;amp;nbsp;B. für die Eingabe von Werten&lt;br /&gt;
&lt;br /&gt;
Das Programm ist für avr-gcc/avr-libc geschrieben, kann aber mit ein paar Anpassungen auch mit anderen Compilern und Mikrocontrollern verwendet werden. Eine Portierung für den AT91SAM7 findet man [http://www.google.com/codesearch?q=show:ac2viP-2E2Y:pzkOO5QRsoc:RPICuprYy-A&amp;amp;sa=N&amp;amp;cd=1&amp;amp;ct=rc&amp;amp;cs_p=svn://mikrocontroller.net/mp3dec/trunk&amp;amp;cs_f=keys.c#a0 hier] (aus dem Projekt [[ARM MP3/AAC Player]]).&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/************************************************************************/&lt;br /&gt;
/*                                                                      */&lt;br /&gt;
/*                      Debouncing 8 Keys                               */&lt;br /&gt;
/*                      Sampling 4 Times                                */&lt;br /&gt;
/*                      With Repeat Function                            */&lt;br /&gt;
/*                                                                      */&lt;br /&gt;
/*              Author: Peter Dannegger                                 */&lt;br /&gt;
/*                      danni@specs.de                                  */&lt;br /&gt;
/*                                                                      */&lt;br /&gt;
/************************************************************************/&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#ifndef F_CPU&lt;br /&gt;
#define F_CPU           1000000                   // processor clock frequency&lt;br /&gt;
#warning kein F_CPU definiert&lt;br /&gt;
#endif&lt;br /&gt;
 &lt;br /&gt;
#define KEY_DDR         DDRB&lt;br /&gt;
#define KEY_PORT        PORTB&lt;br /&gt;
#define KEY_PIN         PINB&lt;br /&gt;
#define KEY0            0&lt;br /&gt;
#define KEY1            1&lt;br /&gt;
#define KEY2            2&lt;br /&gt;
#define ALL_KEYS        (1&amp;lt;&amp;lt;KEY0 | 1&amp;lt;&amp;lt;KEY1 | 1&amp;lt;&amp;lt;KEY2)&lt;br /&gt;
 &lt;br /&gt;
#define REPEAT_MASK     (1&amp;lt;&amp;lt;KEY1 | 1&amp;lt;&amp;lt;KEY2)       // repeat: key1, key2&lt;br /&gt;
#define REPEAT_START    50                        // after 500ms&lt;br /&gt;
#define REPEAT_NEXT     20                        // every 200ms&lt;br /&gt;
&lt;br /&gt;
#define LED_DDR         DDRA&lt;br /&gt;
#define LED_PORT        PORTA&lt;br /&gt;
#define LED0            0&lt;br /&gt;
#define LED1            1&lt;br /&gt;
#define LED2            2&lt;br /&gt;
 &lt;br /&gt;
volatile uint8_t key_state;                                // debounced and inverted key state:&lt;br /&gt;
                                                  // bit = 1: key pressed&lt;br /&gt;
volatile uint8_t key_press;                                // key press detect&lt;br /&gt;
 &lt;br /&gt;
volatile uint8_t key_rpt;                                  // key long press and repeat&lt;br /&gt;
 &lt;br /&gt;
 &lt;br /&gt;
ISR( TIMER0_OVF_vect )                            // every 10ms&lt;br /&gt;
{&lt;br /&gt;
  static uint8_t ct0, ct1, rpt;&lt;br /&gt;
  uint8_t i;&lt;br /&gt;
 &lt;br /&gt;
  TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);  // preload for 10ms&lt;br /&gt;
 &lt;br /&gt;
  i = key_state ^ ~KEY_PIN;                       // key changed ?&lt;br /&gt;
  ct0 = ~( ct0 &amp;amp; i );                             // reset or count ct0&lt;br /&gt;
  ct1 = ct0 ^ (ct1 &amp;amp; i);                          // reset or count ct1&lt;br /&gt;
  i &amp;amp;= ct0 &amp;amp; ct1;                                 // count until roll over ?&lt;br /&gt;
  key_state ^= i;                                 // then toggle debounced state&lt;br /&gt;
  key_press |= key_state &amp;amp; i;                     // 0-&amp;gt;1: key press detect&lt;br /&gt;
 &lt;br /&gt;
  if( (key_state &amp;amp; REPEAT_MASK) == 0 )            // check repeat function&lt;br /&gt;
     rpt = REPEAT_START;                          // start delay&lt;br /&gt;
  if( --rpt == 0 ){&lt;br /&gt;
    rpt = REPEAT_NEXT;                            // repeat delay&lt;br /&gt;
    key_rpt |= key_state &amp;amp; REPEAT_MASK;&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
///////////////////////////////////////////////////////////////////&lt;br /&gt;
//&lt;br /&gt;
// check if a key has been pressed. Each pressed key is reported&lt;br /&gt;
// only once&lt;br /&gt;
//&lt;br /&gt;
uint8_t get_key_press( uint8_t key_mask )&lt;br /&gt;
{&lt;br /&gt;
  cli();                                          // read and clear atomic !&lt;br /&gt;
  key_mask &amp;amp;= key_press;                          // read key(s)&lt;br /&gt;
  key_press ^= key_mask;                          // clear key(s)&lt;br /&gt;
  sei();&lt;br /&gt;
  return key_mask;&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
///////////////////////////////////////////////////////////////////&lt;br /&gt;
//&lt;br /&gt;
// check if a key has been pressed long enough such that the&lt;br /&gt;
// key repeat functionality kicks in. After a small setup delay&lt;br /&gt;
// the key is reported being pressed in subsequent calls&lt;br /&gt;
// to this function. This simulates the user repeatedly&lt;br /&gt;
// pressing and releasing the key.&lt;br /&gt;
//&lt;br /&gt;
uint8_t get_key_rpt( uint8_t key_mask )&lt;br /&gt;
{&lt;br /&gt;
  cli();                                          // read and clear atomic !&lt;br /&gt;
  key_mask &amp;amp;= key_rpt;                            // read key(s)&lt;br /&gt;
  key_rpt ^= key_mask;                            // clear key(s)&lt;br /&gt;
  sei();&lt;br /&gt;
  return key_mask;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
///////////////////////////////////////////////////////////////////&lt;br /&gt;
//&lt;br /&gt;
// check if a key is pressed right now&lt;br /&gt;
//&lt;br /&gt;
uint8_t get_key_state( uint8_t key_mask )&lt;br /&gt;
&lt;br /&gt;
{&lt;br /&gt;
  key_mask &amp;amp;= key_state;&lt;br /&gt;
  return key_mask;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
///////////////////////////////////////////////////////////////////&lt;br /&gt;
//&lt;br /&gt;
uint8_t get_key_short( uint8_t key_mask )&lt;br /&gt;
{&lt;br /&gt;
  cli();                                          // read key state and key press atomic !&lt;br /&gt;
  return get_key_press( ~key_state &amp;amp; key_mask );&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
///////////////////////////////////////////////////////////////////&lt;br /&gt;
//&lt;br /&gt;
uint8_t get_key_long( uint8_t key_mask )&lt;br /&gt;
{&lt;br /&gt;
  return get_key_press( get_key_rpt( key_mask ));&lt;br /&gt;
}&lt;br /&gt;
 &lt;br /&gt;
int main( void )&lt;br /&gt;
{&lt;br /&gt;
  LED_PORT = 0xFF;&lt;br /&gt;
  LED_DDR = 0xFF;                     &lt;br /&gt;
&lt;br /&gt;
  // Configure debouncing routines&lt;br /&gt;
  KEY_DDR &amp;amp;= ~ALL_KEYS;                // configure key port for input&lt;br /&gt;
  KEY_PORT |= ALL_KEYS;                // and turn on pull up resistors&lt;br /&gt;
&lt;br /&gt;
  TCCR0 = (1&amp;lt;&amp;lt;CS02)|(1&amp;lt;&amp;lt;CS00);         // divide by 1024&lt;br /&gt;
  TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);  // preload for 10ms&lt;br /&gt;
  TIMSK |= 1&amp;lt;&amp;lt;TOIE0;                   // enable timer interrupt&lt;br /&gt;
&lt;br /&gt;
  sei();&lt;br /&gt;
&lt;br /&gt;
  while(1){&lt;br /&gt;
    if( get_key_short( 1&amp;lt;&amp;lt;KEY1 ))&lt;br /&gt;
      LED_PORT ^= 1&amp;lt;&amp;lt;LED1;&lt;br /&gt;
 &lt;br /&gt;
    if( get_key_long( 1&amp;lt;&amp;lt;KEY1 ))&lt;br /&gt;
      LED_PORT ^= 1&amp;lt;&amp;lt;LED2;&lt;br /&gt;
 &lt;br /&gt;
    // single press and repeat&lt;br /&gt;
 &lt;br /&gt;
    if( get_key_press( 1&amp;lt;&amp;lt;KEY2 ) || get_key_rpt( 1&amp;lt;&amp;lt;KEY2 )){&lt;br /&gt;
      uint8_t i = LED_PORT;&lt;br /&gt;
 &lt;br /&gt;
      i = (i &amp;amp; 0x07) | ((i &amp;lt;&amp;lt; 1) &amp;amp; 0xF0);&lt;br /&gt;
      if( i &amp;lt; 0xF0 )&lt;br /&gt;
        i |= 0x08;&lt;br /&gt;
      LED_PORT = i;      &lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das single-press-und-repeat-Beispiel geht nicht in jeder Beschaltung; folgendes Beispiel sollte universeller sein (einzelne LED an/aus):&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
// single press and repeat&lt;br /&gt;
if( get_key_press( 1&amp;lt;&amp;lt;KEY2 ) || get_key_rpt( 1&amp;lt;&amp;lt;KEY2 ))&lt;br /&gt;
    LED_PORT ^=0x08;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===== Funktionsweise =====&lt;br /&gt;
Der Code basiert auf 8 parallelen vertikalen Zählern, die über die Variablen ct0 und ct1 aufgebaut werden&lt;br /&gt;
&lt;br /&gt;
[[Bild:VertCount.png|framed|center|&#039;&#039;&#039;8 vertikale Zähler in 2 8-Bit Variablen&#039;&#039;&#039;]]&lt;br /&gt;
&lt;br /&gt;
wobei jeweils ein Bit in ct0 mit dem gleichwertigen Bit in ct1 zusammengenommen einen 2-Bit-Zähler bildet.&lt;br /&gt;
Der Code der sich um die 8 Zähler kümmert, ist so geschrieben, daß er alle 8 Zähler gemeinsam parallel behandelt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
  i = key_state ^ ~KEY_PIN;                       // key changed ?&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
i enthält an dieser Stelle für jede Taste, die sich im Vergleich mit dem vorhergehenden entprellten Zustand (keystate) verändert hat, ein 1 Bit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
  ct0 = ~( ct0 &amp;amp; i );                             // reset or count ct0&lt;br /&gt;
  ct1 = ct0 ^ (ct1 &amp;amp; i);                          // reset or count ct1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese beiden Anweisungen erniedrigen den 2-Bit Zähler ct0/ct1 für jedes Bit um 1, welches in i gesetzt ist. Liegt an der entsprechenden Stelle in i ein 0 Bit vor (keine Änderung des Zustands), so wird der Zähler ct0/ct1 für dieses Bit auf 1 gesetzt.&lt;br /&gt;
Der Grundzustand des Zählers ist als ct0 == 1 und ct1 == 1 (Wert 3). Der Zähler zählt daher mit jedem ISR Aufruf, bei dem die Taste im Vergleich zu keystate als verändert erkannt wurde&lt;br /&gt;
&lt;br /&gt;
   ct1   ct0&lt;br /&gt;
     1    1   // 3&lt;br /&gt;
     1    0   // 2&lt;br /&gt;
     0    1   // 1&lt;br /&gt;
     0    0   // 0&lt;br /&gt;
     1    1   // 3&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
  i &amp;amp;= ct0 &amp;amp; ct1;                                 // count until roll over ?&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
in i bleibt nur dort ein 1-Bit erhalten, wo sowohl in ct1 als auch in ct0 ein 1 Bit vorgefunden wird, der betreffenede Zähler also bis 3 zählen konnte. Durch die zusätzliche Verundung mit i wird der Fall abgefangen, dass ein konstanter Zählerwert von 3 in i ein 1 Bit hinterlässt. Im Endergebnis bedeutet dass, dass nur ein Zählerwechsel von 0 auf 3 zu einem 1 Bit an der betreffenden Stelle in i führt, aber auch nur dann, wenn in i an dieser Bitposition ebenfalls ein 1 Bit war (welches wiederrum deswegen auf 1 war, weil an diesem Eingabeport eine Veränderung zum letzten bekannten entprellten Zustand festgestellt wurde). alles zusammengenommen heißt das, dass ein Tastendruck dann erkannt wird, wenn die Taste 4 mal hintereinander in einem anderen Zustand vorgefunden wurde als dem zuletzt bekannten entprellten Tastenzustand.&lt;br /&gt;
&lt;br /&gt;
An dieser Stelle ist i daher ein Vektor von 8 Bits, von denen jedes einzelne der Bits darüber Auskunft gibt, ob die entsprechende Taste mehrmals hintereinander im selben Zustand angetroffen wurde, der nicht mit dem zuletzt bekannten Tastenzustand übereinstimmt. Ist das der Fall, dann wird eine entsprechende Veränderung des Tastenzustands in key_state registriert&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
  key_state ^= i;                                 // then toggle debounced state&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
und wenn sich in key_state das entsprechende Bit von 0 auf 1 verändert hat, wird dieses Ereignis als &#039;Taste wurde niedergedrückt&#039; gewertet.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
  key_press |= key_state &amp;amp; i;                     // 0-&amp;gt;1: key press detect&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Damit ist der Tasteneingang entprellt. Und zwar sowohl beim Drücken einer Taste als auch beim Loslassen (damit Tastenpreller beim Loslassen nicht mit dem Niederdrücken einer Taste verwechselt werden). Der weitere Code beschäftigt sich dann nur noch damit, diesen entprellten Tastenzustand weiter zu verarbeiten.&lt;br /&gt;
&lt;br /&gt;
Der Codeteil sieht durch die Verwendung der vielen bitweisen Operationen relativ komplex aus. Behält man aber im Hinterkopf, dass einige der bitweisen wie ein &#039;paralles If&#039; gleichzeitig auf allen 8 Bits eingesetzt werden, dann vereinfacht sich vieles. Ein&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
    key_press |= key_state &amp;amp; i;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
ist nichts anderes als ein&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
    // teste ob Bit 0 sowohl in key_state als auch in i gesetzt ist&lt;br /&gt;
    // und setze Bit 0 in key_press, wenn das der Fall ist&lt;br /&gt;
    if( ( key_state &amp;amp; ( 1 &amp;lt;&amp;lt; 0 ) ) &amp;amp;&amp;amp;&lt;br /&gt;
        ( i &amp;amp; ( 1 &amp;lt;&amp;lt; 0 ) )&lt;br /&gt;
       key_press |= ( 1 &amp;lt;&amp;lt; 0 );&lt;br /&gt;
&lt;br /&gt;
    // Bit 1&lt;br /&gt;
    if( ( key_state &amp;amp; ( 1 &amp;lt;&amp;lt; 1 ) ) &amp;amp;&amp;amp;&lt;br /&gt;
        ( i &amp;amp; ( 1 &amp;lt;&amp;lt; 1 ) )&lt;br /&gt;
       key_press |= ( 1 &amp;lt;&amp;lt; 1 );&lt;br /&gt;
&lt;br /&gt;
    // Bit 2&lt;br /&gt;
    if( ( key_state &amp;amp; ( 1 &amp;lt;&amp;lt; 2 ) ) &amp;amp;&amp;amp;&lt;br /&gt;
        ( i &amp;amp; ( 1 &amp;lt;&amp;lt; 2 ) )&lt;br /&gt;
       key_press |= ( 1 &amp;lt;&amp;lt; 2 );&lt;br /&gt;
&lt;br /&gt;
    ...&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
nur als wesentlich kompaktere Operation ausgeführt und für alle 8 Bits gleichzeitig.&lt;br /&gt;
Die Kürze und Effizienz dieser paar Codezeilen ergibt sich aus dem Umstand, dass jedes Bit in den Variablen für eine Taste steht und alle 8 (maximal möglichen) Tasten gleichzeitig die Operationen durchlaufen.&lt;br /&gt;
&lt;br /&gt;
===== Reduziert auf lediglich 1 Taste =====&lt;br /&gt;
Diskussionen im Forum zeigen immer wieder, dass viele eine Abneigung gegen diesen Code haben, weil er ihnen sehr kompliziert vorkommt.&lt;br /&gt;
&lt;br /&gt;
Der Code ist nicht leicht zu analysieren und er zieht alle Register dessen, was möglich ist, um sowohl Laufzeit als auch Speicherverbrauch einzusparen. Oft hört man auch das Argument: Ich benötige ja nur eine Entprellung für 1 Taste, gibt es da nichts Einfacheres?&lt;br /&gt;
&lt;br /&gt;
Hier ist die &#039;Langform&#039; des Codes, so wie man das für lediglich 1 Taste schreiben würde, wenn man exakt dasselbe Entprellverfahren einsetzen würde. Man sieht: Da ist keine Hexerei dabei: In key_state wird der letzte bekannte entprellte Zustand der Taste gehalten. Der Pin-Eingang wird mit diesem Zustand verglichen und wenn sich die beiden unterscheiden, dann wird ein Zähler heruntergezählt. Produziert dieses herunterzählen einen Unterlauf des Zählers, dann gilt die Taste als entprellt und wenn dann auch noch die Taste gerade gedrückt ist, dann wird dieses in key_press entsprechend vermerkt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
uint8_t key_state;&lt;br /&gt;
uint8_t key_counter;&lt;br /&gt;
volatile uint8_t key_press;&lt;br /&gt;
&lt;br /&gt;
ISR( ... Overflow ... )&lt;br /&gt;
{&lt;br /&gt;
  uint8_t input = KEY_PIN &amp;amp; ( 1 &amp;lt;&amp;lt; KEY0 );&lt;br /&gt;
&lt;br /&gt;
  if( input != key_state ) {&lt;br /&gt;
    key_counter--;&lt;br /&gt;
    if( key_counter == 0xFF ) {&lt;br /&gt;
      key_counter = 3;&lt;br /&gt;
      key_state = input;&lt;br /&gt;
      if( input )&lt;br /&gt;
        key_press = TRUE;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  else&lt;br /&gt;
    key_counter = 3;&lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
uint8_t get_key_press()&lt;br /&gt;
{&lt;br /&gt;
  uint8_t result;&lt;br /&gt;
&lt;br /&gt;
  cli();&lt;br /&gt;
  result = key_press;&lt;br /&gt;
  key_press = FALSE;&lt;br /&gt;
  sei();&lt;br /&gt;
&lt;br /&gt;
  return result;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der vollständige Entprellcode, wie weiter oben gelistet, besticht jetzt aber darin, dass er compiliert kleiner ist als diese anschaulichere Variante für lediglich 1 Taste. Und das bei gleichzeitig erhöhter Funktionalität. Denn zb. ein Autorepeat ist in diesem Code noch gar nicht eingebaut. Und spätestens wenn man dann eine 2.te Taste entprellen möchte, dann ist auch der SRAM-Speicherverbrauch dieser Langform höher als der des Originals für 8 Tasten. Daraus folgt: Selbst für lediglich 1 Taste ist die Originalroutine die bessere Wahl.&lt;br /&gt;
&lt;br /&gt;
Und wegen der Komplexität mal eine Frage: Sind Sie selbst in der Lage eine entsprechend effiziente sqrt() Funktion zu schreiben, wie die, die sie in der Standard-C-Bibliothek vorfinden? Nein? Dann dürften Sie eigentlich Ihrer Argumentation nach die Bibliotheksfunktion sqrt() nicht verwenden, sondern müssten sich statt dessen selbst eine Wurzel-Funktion schreiben.&lt;br /&gt;
&lt;br /&gt;
=== Selbstsättigender Filter (nach Jürgen Schuhmacher) ===&lt;br /&gt;
Durch die Nutzung der diskreten Signalanalyse in Software kann die Funktionalität einer einfachen Entprellung mit einem Widerstand, einem Kondensator und einem Schmitttrigger wie in Hardware nachgebildet werden, indem ein abstrakter IIR-Filter benutzt wird, der eine Kondensatorladekurve emuliert. Mit der Vorschrift Y(t) = k Y(t-1) + Input wird ein einfaches Filter erzeugt, dass dem Eingangswert träge folgt. Bei Überschreiten eines bestimmten Wertes erfolgt mit einer einfachen Abfrage das Schalten des Ausgangssignals.&lt;br /&gt;
&lt;br /&gt;
Für Assembler und VHDL bei FPGAs eignet sich aufgrund der leicht zu implementierenden binären Operationen folgende Darstellung mit einer Auflösung des Filterwertspeichers von nur 8 bit: Wert_Neu = Wert_Alt - Wert_Alt/16 + 16*(Taste = True). Der Filterwert bildet dann den gedämpften Verlauf des Eingangs (flankenverschliffen) ab und kann Prellen bis nahe an den Grenzbereich zum schnellen Tasten unterdrücken. Der Ausgangswert ist dann einfach das höchstwertige Bit des Filterwertes.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Entprellung mit IIR-Filter.gif]]&lt;br /&gt;
&lt;br /&gt;
Dazu muss das Signal des Tasters idealerweise um den Faktor 10-20 schneller abgetastet werden, als die höchste gewünschte Tippgeschwindigkeit vorgibt. Noch schneller abzutasten ist möglich, führt aber zu mehr Bedarf an Bits beim Filter. Die Schmittriggerfunktion kann dadurch gebildet werden, dass eine 1 am Ausgang bei z.B. Überschreiten einer 55% Grenze und eine 0 bei Unterschreitung der 45%-Grenze ausgeben wird. Im Zwischenbereich wird der alte Wert gehalten.&lt;br /&gt;
&lt;br /&gt;
=== Einfacher Mittelwertfilter (nach Lothar Miller) ===&lt;br /&gt;
Für digitale Schaltungen oder PLDs empfiehlt sich ein FIR-Filter mit aneinandergereihten FlipFlops. Man schiebt das Eingangssignal in eine FlipFlop-Kette und schaltet oberhalb der Mitte um:&lt;br /&gt;
&lt;br /&gt;
SignalInput -&amp;gt; FF1 -&amp;gt; FF2 -&amp;gt; FF3 -&amp;gt; FF4 -&amp;gt; FF5 -&amp;gt; FF6 -&amp;gt; FF7 -&amp;gt; FF8&lt;br /&gt;
&lt;br /&gt;
Wenn alle FFs = 1 (Summe der FFs=8) dann SignalOutput = 1&amp;lt;br /&amp;gt;&lt;br /&gt;
Wenn alle FFs = 0 (Summe der FFs=0) dann SignalOutput = 0&lt;br /&gt;
&lt;br /&gt;
Dieses Verfahren kann sehr einfach in Logik abgebildet werden, weil für die Berechnung des Ausgangs nur ein NOR bz. ein AND Gatter nötig ist.&lt;br /&gt;
&lt;br /&gt;
== Gegenüberstellung der Verfahren ==&lt;br /&gt;
* HW - &amp;quot;entprellte Schalter&amp;quot;: Sehr teuer, grosse Bauform, verschleissbelastet, geringe Haltbarkeit&lt;br /&gt;
* HW - &amp;quot;Umschalter&amp;quot; : benötigt aufwändigeren Schalter, benötigt Elektronik&lt;br /&gt;
* HW - &amp;quot;Umschalter ohne FF&amp;quot; : benötigt aufwändigeren Schalter und kleiner Kondensator&lt;br /&gt;
* HW - &amp;quot;Kondensatorentprellung&amp;quot; : benötigt etwas mehr Platz, kommt mit schlechten Schaltern zurecht&lt;br /&gt;
&lt;br /&gt;
* SW - Flankenverfahren:&lt;br /&gt;
* SW - Warteschleife: Durch die Warteschleifen eine nicht zu vernachlässigende Verzögerung im Code. Speziell wenn mehrere Tasten zu überwachen sind, nicht unproblematisch&lt;br /&gt;
* SW - Timer: Universalfunktionalität, die durch geringen Speicherverbrauch, geringen Rechenzeitverbrauch und gute Funktion besticht. Der &#039;Verbrauch&#039; eines Timers sieht auf den ersten Blick schlimmer aus, als er ist, denn in den meisten Programmen hat man sowieso einen Basistimer für die Zeitsteuerung des Programms im Einsatz, der für die Tastenentprellung mitbenutzt werden kann.&lt;br /&gt;
* SW - Filter: sehr geringer Platzbedarf in FPGAs, relativ gute Wirkung&lt;br /&gt;
* SW - Filter 2: sehr geringer Platzbedarf, gute Wirkung&lt;br /&gt;
&lt;br /&gt;
== Links zum Thema ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.edn.com/design/analog/4324067/Contact-debouncing-algorithm-emulates-Schmitt-trigger Contact-debouncing algorithm (Artikel)],  [http://www.edn.com/file/13370-70705di.pdf als PDF]&lt;br /&gt;
* [[AVR-Tutorial: Tasten]]&lt;br /&gt;
* [[AVR-GCC-Tutorial#.28Tasten-.29Entprellung|AVR-GCC-Tutorial Tastenentprellung]]&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/read-4-20435.html Beitrag im Forum, AVR Assembler]&lt;br /&gt;
* [http://www.ganssle.com/debouncing.pdf A guide to debouncing (engl.), praktische Erläuterungen zum Entprellen in Soft- und Hardware]&lt;br /&gt;
* [http://www.pololu.com/docs/0J16/all Understanding Destructive LC Voltage Spikes]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR]]&lt;br /&gt;
[[Kategorie:Signalverarbeitung]]&lt;/div&gt;</summary>
		<author><name>62.157.123.104</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Stromversorgung_f%C3%BCr_FPGAs&amp;diff=81255</id>
		<title>Stromversorgung für FPGAs</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Stromversorgung_f%C3%BCr_FPGAs&amp;diff=81255"/>
		<updated>2014-01-31T08:35:12Z</updated>

		<summary type="html">&lt;p&gt;62.157.123.104: /* Messungen */ typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In diesem Artikel soll eine kurze Erklärung zum Entwurfsproblem von Stromversorgungen für Hochleistungs-[[FPGA]]s gegeben werden. Ein neuer Ansatz zur Messung des Frequenzgangs wird dargestellt. Praktische Messungen werden gezeigt.&lt;br /&gt;
&lt;br /&gt;
FPGAs werden immer mehr Bestandteil moderner Elektronik. Die Bausteine werden größer, schneller und leistungsstärker mit jedem Tag. Und so steigt auch die Leistungsaufnahme. Obwohl die Leistung pro Gatter sich durch bessere Technologie und kleinere Geometrien verringert, steigt die Taktfrequenz und die Anzahl der Gatter pro Bauteil. Mit steigender Schaltgeschwindigkeit wird die Stromversorgung zu einem kritischen Teil im Systementwurf. Das Stromversorgungsnetz muss eine Quelle mit niedriger Impedanz über einen sehr weiten Frequenzbereich sein. Anderenfalls könnnen Überschwinger, Spannungsabfall oder Störpulse auf VCC/GND die Funktion des FPGAs stören, welche durch den schnell wechselnden Leistungsbedarf des FPGAs verursacht wird.&lt;br /&gt;
&lt;br /&gt;
== Breitbandentkopplung ist Teamwork ==&lt;br /&gt;
&lt;br /&gt;
Der Spannungsregler muss die Gleichstromkomponente für das Stromversorgungsnetzwerk liefern. Bei maximaler Leistung und Umgebungstemperatur muss er immer noch sauber funktionieren ohne zu überhitzen, Spannungseinbrüche etc. Seine Aufgabe ist es, auf niederfrequente Lastsprünge zu reagieren (ca. 0..30kHz).&lt;br /&gt;
&lt;br /&gt;
Im mittleren Frequenzbereich kann der Spannungsregler nicht mehr reagieren, er ist zu langsam. Der Strom muss dann von großen Elektrolytkondensatoren geliefert werden. Diese Kondensatoren können bis einige MHz Strom liefern, danach begrenzen der parasitäre Widerstand (ESR, engl. effective series resistance) bzw. die parasitäre Induktivität (ESL, engl. effective series inductance) die Stromlieferfähigkeit des Kondensators und machen ihn irgendwann bei höheren Frequenzen nutzlos.&lt;br /&gt;
&lt;br /&gt;
Jetzt kommt die Zeit der kleinen Keramikkondensatoren, typisch 10 oder 100nF. Sie gibt es in kleinen [[SMD]]-Gehäusen wie 0603 und kleiner mit sehr wenig parasitärer Induktivität. Sie können Strom bis einige hundert MHz liefern und sind damit eine niederohmige Quelle für Hochfrequenzströme.&lt;br /&gt;
&lt;br /&gt;
Aber für die &#039;&#039;&#039;wirklich&#039;&#039;&#039; schnell schaltenden ICs sind auch diese Keramikkondensatoren nicht ausreichend, um das Stromversorgungsnetzwerk ausreichend zu entkoppeln. Hier braucht man die Kapazität der Stromversorgungsflächen, welche duch VCC- und Masseflächen in mehrlagigen Platinen gebildet wird. Um ein Maximum an Kapazität zu erreichen sollte ein dünnes Dielektrikum mit einer hohen Dielektrizitätskonstante und niedrigen Verlusten benutzen. Außerdem sollte man ein VIA für jedes VCC/GND Pin benutzen, um die parasitären Induktivitäten zu minimieren, nicht ein VIA für mehrere Pins! [[IC-Gehäuseformen#BGA | BGA-Gehäuse]] bieten zusätzlich kürzere Verbindungen vom eigentlichen IC zur Platine, sie sind aber schwieriger zu handhaben (Layout und [[SMD Löten | Löten]]).&lt;br /&gt;
&lt;br /&gt;
== Der klassische Ansatz ==&lt;br /&gt;
&lt;br /&gt;
Es gibt viele Theorien und Application Notes zum Thema Entkopplung von Stromversorgungen. Einige nehmen einfach die Brechstange und bauen einen Friedhof für unzählige Kondensatoren, andere sind schlauer. Es gibt auch sehr viele Simulationen zu dem Thema. Aber am Ende sind die Eigenschaften des Stromversorgungsnetzes definiert duch das Zusammenspiel von&lt;br /&gt;
&lt;br /&gt;
* dem FPGA und dessen Leistungsaufnahme, welche von der Schaltfrequenz abhängt&lt;br /&gt;
* dem Layout der Platine mit der Platzierung der verschiedenen Kondensatoren&lt;br /&gt;
&lt;br /&gt;
Eine Möglichkeit zur Messung der Qualität des Stromversorgungsnetzwerkes ist die Nutzung eines Netzwerkanalysators. Dafür benötigt man eine Platine, welche nur mit den passiven Komponenten bestückt ist. Dabei wird ein Testsignal in das Netzwerk eingespeist (meist an Stelle des Spannungsreglers) und an einer anderen Stelle gemessen (meist an Stelle der ICs). Der Netzwerkanalysator variiert dann die Frequenz und zeichnet eine Kurve des Widerstand über die Frequenz auf. Diese Methode hat einige Nachteile.&lt;br /&gt;
&lt;br /&gt;
*Man braucht einen teuren Netzwerkanalysator&lt;br /&gt;
*Man benötigt eine zusätzliches Board, welches nur mit den Kondensatoren bestückt ist, welches nicht immer verfügbar ist&lt;br /&gt;
*Die Messung spiegelt nicht die wahren Bedingungen wieder, weil alle ICs und aktiven Teile fehlen. Ausserdem sind nur Punkt zu Punkt Messungen möglich, welche das reale Verhalten nicht korrekt wiedergeben.&lt;br /&gt;
&lt;br /&gt;
Die Methode in diesem Artikel versucht, die meisten Nachteile zu vermeiden.&lt;br /&gt;
&lt;br /&gt;
== Ein direkter Ansatz ==&lt;br /&gt;
&lt;br /&gt;
Da wir hier über FPGAs reden, haben wir die Möglichkeit, &#039;&#039;&#039;jede&#039;&#039;&#039; beliebige digitale Funktion hineinzuprogrammieren. Also sollten wir eine digitale Funktion entwerfen, welche dem schlimmstmöglichen Fall der Belastung der Stromversorgung entspricht. Aus der Theorie der linearen Netzwerke wissen wir, dass der Frequenzgang eines linearen Systems aus der Sprungantwort am Eingang und der Reaktion am Ausgang gemessen werden kann. Für das Stromversorgungsnetzwerk funktioniert das sogar wenn es nicht vollständig linear ist, da wir ja die reale Reaktion auf konstante Last und Lastsprünge messen wollen. Was ist nun der schlimmste Belastungsfall für die Stromversorgung? Da fast alle ICs auf CMOS-Technologie beruhen, wird die meiste Leistung umgesetzt, wenn Signalnetze ihren Pegel wechseln. Bei einem FPGA heißt das, dass alle [[FlipFlop]]s ihren Pegel gleichzeitig wechseln und dabei große Signalnetze treiben (parasitäre Kapazität). Also entwerfen wir die folgende Schaltung. &lt;br /&gt;
&lt;br /&gt;
[[bild:Schematic.gif|thumb|left|600px|Logik für Lasttest]]&lt;br /&gt;
{{clear}}&lt;br /&gt;
&lt;br /&gt;
Der Kern besteht aus einer Matrix aus 30x50 FlipFlops, wobei jeweils 50 FlipFlops aus einem Puffer-FlipFlop gespeist werden, um die Ausgangslast relativ niedrig zu halten und damit eine hohe Taktfrequenz zu erreichen. Um etwas kombinatorische Logik zu erzeugen und um die HDL Compiler davon abzuhalten, die FlipFlops wegzuoptimieren, verbinden wir alle FlipFlops über ein gigantisches ODER-Gatter und leiten den Ausgang auf ein IO-Pad. Dieser Ausgang wird aber nicht weiter genutzt. Dann haben wir noch einen 16-Bit  Zähler und etwas Steuerlogik, welche das Toggle-FlipFlop gemäß folgender Tabelle steuert.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Steuerung der Testlogik&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
! sel&amp;lt;1&amp;gt; || sel&amp;lt;0&amp;gt; || Modus&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 0 || inaktiv&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 1 || konstante Umschaltung&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 0 || Burstbetrieb&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== VHDL Code ==&lt;br /&gt;
&lt;br /&gt;
Wenn der Code synthetisiert wird, muss die Option &amp;quot;remove duplicate registers&amp;quot; in der Synthesesoftware ausgeschaltet werden. Es sollten zwei Dateien angelegt werden, top.vhd und row.vhd.&lt;br /&gt;
&lt;br /&gt;
Datei top.vhd&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;vhdl&amp;quot;&amp;gt;&lt;br /&gt;
library IEEE;&lt;br /&gt;
use IEEE.STD_LOGIC_1164.ALL;&lt;br /&gt;
use IEEE.STD_LOGIC_ARITH.ALL;&lt;br /&gt;
use IEEE.STD_LOGIC_UNSIGNED.ALL;&lt;br /&gt;
&lt;br /&gt;
entity power is&lt;br /&gt;
    Port ( clk_in  : in std_logic;                      -- clock input&lt;br /&gt;
           sel     : in std_logic_vector(1 downto 0);   -- select modulation ON/OFF&lt;br /&gt;
           gnd     : out std_logic_vector(5 downto 0);  -- artificial gnd&lt;br /&gt;
           mod_out : out std_logic;                     -- modulation signal&lt;br /&gt;
           reset   : in std_logic;                      -- reset for DLL&lt;br /&gt;
           dummy   : out std_logic);                    -- dummy out, to fool the synthesizer&lt;br /&gt;
           &lt;br /&gt;
end power;&lt;br /&gt;
&lt;br /&gt;
architecture Behavioral of power is&lt;br /&gt;
&lt;br /&gt;
COMPONENT row&lt;br /&gt;
    PORT(&lt;br /&gt;
        clk  : IN std_logic;&lt;br /&gt;
        data : IN std_logic;    &lt;br /&gt;
        dout : OUT std_logic&lt;br /&gt;
        );&lt;br /&gt;
END COMPONENT;&lt;br /&gt;
&lt;br /&gt;
-- DLL (Delay Locked Loop), a Virtex primitive&lt;br /&gt;
&lt;br /&gt;
component CLKDLL&lt;br /&gt;
    port (  &lt;br /&gt;
        CLKIN   : in    std_logic;&lt;br /&gt;
        CLKFB   : in    std_logic;&lt;br /&gt;
        RST     : in    std_logic;&lt;br /&gt;
        CLK0    : out   std_logic;&lt;br /&gt;
        CLK90   : out   std_logic;&lt;br /&gt;
        CLK180  : out   std_logic;&lt;br /&gt;
        CLK270  : out   std_logic;&lt;br /&gt;
        CLK2X   : out   std_logic;&lt;br /&gt;
        CLKDV   : out   std_logic;&lt;br /&gt;
        LOCKED  : out   std_logic);&lt;br /&gt;
end component;&lt;br /&gt;
&lt;br /&gt;
-- BUFG (Global Clock buffer), a Virtex  primitive&lt;br /&gt;
&lt;br /&gt;
component BUFG&lt;br /&gt;
    port (  I   : in    std_logic;&lt;br /&gt;
            O   : out   std_logic);&lt;br /&gt;
end component;&lt;br /&gt;
&lt;br /&gt;
-- IBUFG (Global Clock input buffer ), aa Virtex primitive&lt;br /&gt;
&lt;br /&gt;
component IBUFG&lt;br /&gt;
    port (  I   : in    std_logic;&lt;br /&gt;
            O   : out   std_logic);&lt;br /&gt;
end component;&lt;br /&gt;
&lt;br /&gt;
component SRL16     -- virtex primitive&lt;br /&gt;
  port (&lt;br /&gt;
        D    : in std_logic;        &lt;br /&gt;
        CLK  : in std_logic;&lt;br /&gt;
        A0   : in std_logic;&lt;br /&gt;
        A1   : in std_logic;&lt;br /&gt;
        A2   : in std_logic;&lt;br /&gt;
        A3   : in std_logic;        &lt;br /&gt;
        Q    : out std_logic&lt;br /&gt;
       ); &lt;br /&gt;
end component;&lt;br /&gt;
&lt;br /&gt;
constant rows: integer:=30;&lt;br /&gt;
&lt;br /&gt;
type flop_array is array (rows-1 downto 0) of std_logic_vector(49 downto 0);&lt;br /&gt;
&lt;br /&gt;
signal toggle   : std_logic;                            -- a toggle flipflop&lt;br /&gt;
signal ff_ar    : flop_array;&lt;br /&gt;
signal drive_ar : std_logic_vector (rows-1 downto 0);   -- driver array for toggeling rows&lt;br /&gt;
signal dout_ar  : std_logic_vector (rows-1 downto 0);   -- driver array for toggeling rows&lt;br /&gt;
signal or_ar    : std_logic_vector (rows-1 downto 0);   -- driver array for toggeling rows&lt;br /&gt;
signal cnt      : std_logic_vector (15 downto 0);       -- modulation divider&lt;br /&gt;
&lt;br /&gt;
signal CLKIN_w, RESET_w, CLK2X_dll, CLK2X_g, CLK4X_dll, CLK4X_g, CLK8X_dll, CLK8X_g: std_logic;&lt;br /&gt;
signal LOCKED2X, LOCKED2X_delay, RESET4X, RESET8X, LOCKED4X, LOCKED4X_delay, LOCKED8X : std_logic;&lt;br /&gt;
&lt;br /&gt;
signal logic1,clk : std_logic;&lt;br /&gt;
&lt;br /&gt;
signal clk2x,clk4x,clk8x, clkmux: std_logic;&lt;br /&gt;
&lt;br /&gt;
begin&lt;br /&gt;
&lt;br /&gt;
-- use two DLL to get 147 MHz&lt;br /&gt;
&lt;br /&gt;
logic1&amp;lt;=&#039;1&#039;;&lt;br /&gt;
&lt;br /&gt;
clkpad : IBUFG  port map (I=&amp;gt;CLK_IN, O=&amp;gt;CLKIN_w);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
dll2x  : CLKDLL port map (CLKIN=&amp;gt;CLKIN_w,   CLKFB=&amp;gt;CLK2X_g, RST=&amp;gt;RESET,&lt;br /&gt;
                          CLK0=&amp;gt;open,   CLK90=&amp;gt;open, CLK180=&amp;gt;open, CLK270=&amp;gt;open,&lt;br /&gt;
                          CLK2X=&amp;gt;CLK2X_dll, CLKDV=&amp;gt;open, LOCKED=&amp;gt;LOCKED2X);&lt;br /&gt;
&lt;br /&gt;
clk2xg : BUFG   port map (I=&amp;gt;CLK2X_dll,   O=&amp;gt;CLK2X_g);&lt;br /&gt;
&lt;br /&gt;
rstsrl : SRL16  port map (D=&amp;gt;LOCKED2X, CLK=&amp;gt;CLK2X_g, Q=&amp;gt;LOCKED2X_delay,&lt;br /&gt;
                          A3=&amp;gt;logic1, A2=&amp;gt;logic1, A1=&amp;gt;logic1, A0=&amp;gt;logic1);&lt;br /&gt;
&lt;br /&gt;
RESET4X &amp;lt;= not LOCKED2X_delay;&lt;br /&gt;
&lt;br /&gt;
dll4x  : CLKDLL port map (CLKIN=&amp;gt;CLK2X_g,  CLKFB=&amp;gt;CLK4X_g, RST=&amp;gt;RESET4X,&lt;br /&gt;
                          CLK0=&amp;gt;open,   CLK90=&amp;gt;open, CLK180=&amp;gt;open, CLK270=&amp;gt;open,&lt;br /&gt;
                          CLK2X=&amp;gt;CLK4X_dll, CLKDV=&amp;gt;open, LOCKED=&amp;gt;LOCKED4X);&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
clk4xg : BUFG   port map (I=&amp;gt;CLK4X_dll,  O=&amp;gt;CLK4X_g);&lt;br /&gt;
&lt;br /&gt;
clk&amp;lt;=clk4x_g;&lt;br /&gt;
&lt;br /&gt;
-- the toggeling array&lt;br /&gt;
&lt;br /&gt;
l_rows: for i in 0 to rows-1 generate&lt;br /&gt;
    Inst_row: row PORT MAP(&lt;br /&gt;
        clk  =&amp;gt; clk,&lt;br /&gt;
        data =&amp;gt; drive_ar(i),&lt;br /&gt;
        dout =&amp;gt; dout_ar(i)&lt;br /&gt;
    );&lt;br /&gt;
  end generate;&lt;br /&gt;
&lt;br /&gt;
-- combine all douts via a BIG or-gate&lt;br /&gt;
&lt;br /&gt;
  process(dout_ar)&lt;br /&gt;
  variable tmp: std_logic;&lt;br /&gt;
  begin&lt;br /&gt;
    tmp:=&#039;0&#039;;&lt;br /&gt;
    l_or: for i in 0 to rows-1 loop&lt;br /&gt;
      tmp:=tmp or dout_ar(i);&lt;br /&gt;
    end loop;&lt;br /&gt;
    dummy&amp;lt;=tmp;&lt;br /&gt;
  end process;&lt;br /&gt;
&lt;br /&gt;
-- prescaler&lt;br /&gt;
&lt;br /&gt;
  process(clk)&lt;br /&gt;
  begin&lt;br /&gt;
    if clk=&#039;1&#039; and clk&#039;event then&lt;br /&gt;
      cnt&amp;lt;=cnt+1;&lt;br /&gt;
    end if;&lt;br /&gt;
  end process;&lt;br /&gt;
&lt;br /&gt;
-- toggle fliplop and distribution&lt;br /&gt;
&lt;br /&gt;
  process(clk)&lt;br /&gt;
  begin&lt;br /&gt;
    if clk=&#039;1&#039; and clk&#039;event then&lt;br /&gt;
      case sel is&lt;br /&gt;
        when &amp;quot;00&amp;quot;       =&amp;gt; toggle &amp;lt;= &#039;0&#039;;&lt;br /&gt;
        when &amp;quot;01&amp;quot;       =&amp;gt; toggle &amp;lt;= not toggle;&lt;br /&gt;
        when &amp;quot;10&amp;quot;       =&amp;gt; if cnt(15)=&#039;1&#039; then toggle &amp;lt;= not toggle; else toggle&amp;lt;=&#039;0&#039;; end if;&lt;br /&gt;
        when others     =&amp;gt; null;&lt;br /&gt;
      end case;&lt;br /&gt;
      drive_ar&amp;lt;=(others=&amp;gt;toggle);&lt;br /&gt;
    end if;&lt;br /&gt;
  end process;&lt;br /&gt;
&lt;br /&gt;
gnd&amp;lt;=(others=&amp;gt;&#039;0&#039;);&lt;br /&gt;
mod_out&amp;lt;=cnt(15);&lt;br /&gt;
&lt;br /&gt;
end Behavioral;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Datei row.vhd&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;vhdl&amp;quot;&amp;gt;&lt;br /&gt;
library IEEE;&lt;br /&gt;
use IEEE.STD_LOGIC_1164.ALL;&lt;br /&gt;
use IEEE.STD_LOGIC_ARITH.ALL;&lt;br /&gt;
use IEEE.STD_LOGIC_UNSIGNED.ALL;&lt;br /&gt;
&lt;br /&gt;
entity row is&lt;br /&gt;
    Port ( clk  : in std_logic;&lt;br /&gt;
           data : in std_logic;&lt;br /&gt;
           dout : out std_logic);&lt;br /&gt;
end row;&lt;br /&gt;
&lt;br /&gt;
architecture Behavioral of row is&lt;br /&gt;
&lt;br /&gt;
signal my_array: std_logic_vector (49 downto 0);&lt;br /&gt;
&lt;br /&gt;
begin&lt;br /&gt;
&lt;br /&gt;
-- generate 50 FFs with clock enable&lt;br /&gt;
&lt;br /&gt;
  process (clk)&lt;br /&gt;
  begin&lt;br /&gt;
    if clk=&#039;1&#039; and clK&#039;event then&lt;br /&gt;
      my_array&amp;lt;=(others=&amp;gt;data);     &lt;br /&gt;
    end if;&lt;br /&gt;
  end process;&lt;br /&gt;
&lt;br /&gt;
-- combine all into a BIG OR&lt;br /&gt;
&lt;br /&gt;
  process(my_array)&lt;br /&gt;
  variable tmp: std_logic;&lt;br /&gt;
  begin&lt;br /&gt;
    tmp:=&#039;0&#039;;&lt;br /&gt;
    l: for i in 0 to 49 loop&lt;br /&gt;
      tmp:=tmp or my_array(i);&lt;br /&gt;
    end loop;&lt;br /&gt;
    dout&amp;lt;=tmp;&lt;br /&gt;
  end process;&lt;br /&gt;
&lt;br /&gt;
end Behavioral;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Messungen ==&lt;br /&gt;
&lt;br /&gt;
[[bild:Term1.gif|thumb|right|220px|Terminierung 1: 50Ω vor dem Koppelkondensator, f&amp;lt;sub&amp;gt;g&amp;lt;/sub&amp;gt;&amp;amp;nbsp;=&amp;amp;nbsp;10&amp;amp;nbsp;Hz]]&lt;br /&gt;
[[bild:Term2.gif|thumb|right|220px|Terminierung 2: 50Ω nach dem Koppelkondensator, f&amp;lt;sub&amp;gt;g&amp;lt;/sub&amp;gt;&amp;amp;nbsp;=&amp;amp;nbsp;200&amp;amp;nbsp;kHz]]&lt;br /&gt;
&lt;br /&gt;
Die nachfolgenden Messungen wurden mit einem Spartan-II Demoboard von Insight Electronics durchgeführt. Es ist mit einem XC2S100-5 im PQ208 Gehäuse bestückt. Es nutzt eine Kernspannung von 2,5V und eine IO-Spannung von 3,3V. Beide Spannungen werden durch Linearregler geliefert. Ein 36.864 MHz Oszillator wurde hinzugefügt. Für die Messung wurde der Takt mittels DLL vervierfacht auf 147 MHz. Diese hohe Frequenz wurde gewählt, um die Effekte gut demonstrieren zu können. In einer praktischen Anwendung wird man diesen Test nur mit der normalen Frequenz betreiben, welche auch in der realen Anwendung genutzt wird. Das Board wird durch ein starkes Netzteil versorgt.&lt;br /&gt;
&lt;br /&gt;
Die Kernspannung wird mit einem Stück Koaxialkabel vom Typ RG 174 gemessen, welches direkt an ein VCC/GND-Pin des FPGAs angelötet ist. Das [[Oszilloskop]] ist auf 50Ω Eingangsimpedanz mit AC-Kopplung geschaltet. Wir sind nicht an der absoluten Größe der Versorgungsspannung interessiert sind, nur an Wechselanteilen, welche hoffentlich deutlich kleiner sind. Mit AC-Kopplung kann man einen deutlich kleineren Messbereich für die vertikale Auflösung verwenden. Dieser Aufbau hat eine gute Abschirmung gegen Störungen und eine sehr hohe Bandbreite zur Messung der hochfrequenten Störungen.&lt;br /&gt;
&lt;br /&gt;
Während der Messung wurde festgestellt, dass es zwei verschiedene [[Wellenwiderstand | Terminierungsmethoden]] in Oszilloskopen gibt. Das alte Tektronix CSA 404 mit einem 11A34 Verstärker nutzt Terminierung 1 am 50Ω Eingang. Daraus ergibt sich eine untere Grenzfrequenz des Hochpasses von ~10 Hz. Das zweite Oszilloskop, ein Tektronix TDS 3034, mit welchem die Screenshots gemacht wurden, nutz Terminierung 2, welche in einer unteren Grenzfrequenz von ~200 kHz resultiert. Das ist nicht akzeptabel für die Messung der Sprungantwort, weswegen die 1 M&amp;amp;Omega; Eingangsterminierung benutzt wurde. Das ist OK für die Messung niedriger Frequenzen (&amp;lt;10 MHz). Zur Messung der Hochfrequenzstörungen (Messung 4) ist die Grenzfrequenz von 200 kHz kein Problem.&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
== Messung 1 - FPGA unkonfiguriert ==&lt;br /&gt;
&lt;br /&gt;
Bei diesem Schritt können wir die Leistungsaufnahme in Ruhezustand messen, welche größtenteils durch Leckströme verursacht wird. Zu beachten ist auch, dass unser Oszilloskop mit Eingangsschaltung 1 viel Strom zieht (50Ω @ 2,5V = 50mA). Wir können mittles Multimeter messen, ob unsere Spannungsregler die korrekte Spannung liefern. Wir schreiben den aktuellen Stromverbrauch und Kernspannung auf. Dabei ist der Stromverbrauch der Eingangstermninierung nicht enthalten, weil für alle Messungen das zweite Oszilloskop mit Schaltung 2 verwendet wurde.&lt;br /&gt;
&lt;br /&gt;
== Messung 2 - FPGA mit leerer Logik == &lt;br /&gt;
&lt;br /&gt;
Ein Design mit einer einfachen Schleife von einem Eingang auf einen Ausgang ist jetzt in das FPGA geladen. Nach der Konfiguration &#039;&#039;&#039;sinkt&#039;&#039;&#039; der Stromverbrauch, weil die Konfigurationslogik im FPGA abgeschaltet wurde, welche permanant den Konfigurationsspeicher löscht. Die Leistungsaufnahme dieser Minimalschaltung wird als Kalibrierungspunkt für alle nachfolgenden Messungen verwendet.&lt;br /&gt;
&lt;br /&gt;
== Messung 3 - FPGA konfiguriert ohne schaltende Logik ==&lt;br /&gt;
&lt;br /&gt;
Jetzt steigt die Leistungsaufnahme deutlich. Auf den ersten Blick ist das unerwartet, denn im FPGA werden keinerlei Signale geschaltet , die FlipFlips laden immer den gleichen Wert. Aber das ist nicht ganz korrekt. Das Taktnetzwerk läuft auf voller Leistung. Daran erkennt man, dass die Taktverteilung signifikant Leistung benötigt. Darum nutzen [[Ultra low power | stromsparende ICs]] eine saubere Methode zur [[Taktung FPGA/CPLD | Taktabschaltung (clock gating)]], um die Leitungsaufnahme zu verringern. Aber das muss auf sichere Weise erfolgen.&lt;br /&gt;
&lt;br /&gt;
== Messung 4 - FPGA mit dauerhaft schaltenden Signalen ==&lt;br /&gt;
&lt;br /&gt;
Jetzt starten wir ein Feurwerk! Die Stromversorgung erfährt jetzt ihren schlimmsten Albtraum. 1500 FlipFlops die gleichzeitig mit 147 MHz umschalten (togglen)&lt;br /&gt;
ist kein Kindergeburtstag! Schau auf den Strommesser! Das FPGA wird schnell sehr heiß. Aber was sehen wir auf dem Oszilloskop? Da die Stromaufnahme konstant ist, können wir nur Hochfrequenzstörungen durch die schaltende Logik sehen, welche durch unzureichende Entkopplung der Keramikkondensatoren verursacht werden könnte. Mit einem schnellen Oszilloskop (1GHz++) und schlechten Versorgungslagen und Keramikkondensatoren, könnte man die &#039;&#039;&#039;wirklich&#039;&#039;&#039; hochfrequenten Störungen sehen. Mit dem 1 GHz Oszilloskop sieht man in diesem Fall aber nichts, eben weil die Kondensatoren und Stromversorgungslagen gut funktionieren. Mit langsameren Oszilloskopen (300MHz oder weniger) sieht man nur den Effekt der Kondensatoren. Hier können wir auch die Kernspannung unter Volllast messen. Aber man muss sicherstellen, die Spannung zu messen, welche wirklich am FPGA ankommt, d.h. man muss &#039;&#039;&#039;direkt&#039;&#039;&#039; an den Pins des FPGA messen, nicht irgendwo auf dem Board! Denn das Stromversorgungsnetz hat einen endlichen Widerstand, welcher einen Spannungsabfall vom Spannungsregler bis zum FPGA verursacht. In einem guten Entwurf sollte der Spannungsabfall kleiner als 1% der Nennspannung sein.&lt;br /&gt;
&lt;br /&gt;
== Messung 5 - Burstbetrieb ==&lt;br /&gt;
&lt;br /&gt;
Zum Schluß erreichen wir den interessantesten Punkt. Mit dem 16-Bit Zähler wird das Umschalten des FlipFlop-Arrays mit einer niedrigen Frequenz moduliert, die Modulationsfrequenz ist 1/65356 der Taktfrequenz, hier ~2,2 kHz. Das ist die Sprungfunktion, welche in den Abschnitten weiter oben genannt wurde. Und wir sehen die Reaktion des Stromversorgungsnetzes. Wenn es ideal wäre, würden wir nur eine gerade Linie auf dem Oszilloskop sehen. Aber da es numal keine Idealfälle gibt, sehen wir Überschwinger und einen verbleibenden Offset. Das nachfolgende Bild zeigt das deutlich. Der blaue Kanal ist das Modulationssignal des 16-Bit Zählers (MSB), der gelbe Kanal die Kernspannung.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;gallery widths=&amp;quot;140&amp;quot;&amp;gt;&lt;br /&gt;
bild:01.gif| Sprungantwort mit 10µF&lt;br /&gt;
bild:02.gif| Sprungantwort mit 110µF&lt;br /&gt;
bild:03.gif| Abschaltflanke 10µF&lt;br /&gt;
bild:04.gif| Abschaltflanke 110µF&lt;br /&gt;
bild:05.gif| Zoom, Abschaltflanke 110µF&lt;br /&gt;
bild:06.gif| Anschaltflanke 10µF&lt;br /&gt;
bild:07.gif| Anschaltflanke 110µF&lt;br /&gt;
bild:08.gif| Zoom, Anschaltflanke 110µF&lt;br /&gt;
&amp;lt;/gallery&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Erklärung ==&lt;br /&gt;
&lt;br /&gt;
Der Unterschwinger beim Einschalten wird verursacht durch unzureichende Entkopplung im mittleren Frequenzbereich. Der sprunghaft steigende Stromverbrauch kann nicht von den Mittelfrequenzkondensatoren geliefert werden (zu wenig Kapazität), auch nicht vom Spannungsregler (er ist zu langsam dafür). Das originale Demoboard ist nur mit einem 10µF Tantalkondensator hinter dem Spannungsregler bestückt, welche für so eine große Last viel zu klein ist. Durch Ergänzung eines 100µF Kondensatores kann der Unterschwinger deutlich verkleinert werden.&lt;br /&gt;
&lt;br /&gt;
Der Überschwinger beim Abschalten ist ähnlich, aber hier ist der Spannungsregler ist zu langsam, den Ausgangsstrom herunterzuregeln. Der überschüssige Strom (Ladung) wird in den Mittelfrequenzkondensatoren gespeichert, aber da dieser nur 10µF hat, steigt die Spannung schnell an. Ein einfacher Vergleich. Es ist genauso wie wenn man mit einem kleinen Fass das Regenwasser von einem großen Dach auffangen will, das Faß füllt sich schnell.&lt;br /&gt;
&lt;br /&gt;
Was verursacht den verbliebenden Offset? Nun, das ist der Gleichstromwiderstand des Stromversorgungsnetzwerks vom Spannungsregler (wo dieser die Ausgangsspanung misst und regelt) bis zum VCC-Pin des FPGAs. Die Stromaufnahme des FPGAs schwankt zwischen Messung 3 (kein Umschalten) und Messung 4 (konstantes Umschalten). Auf dem Oszilloskop sehen wir eine Spannungsdifferenz von ~70mV bei einer Stromdifferenz von 912 mA, woraus ca. 76m&amp;amp;Omega; Widerstand resultieren. Die Schlußfolgerung daraus ist, dass die Verbindung zwischen dem Punkt der Spannungsmessung durch den Spannungsregler und den VCC-Pins einen möglichst niedrigen Widerstand haben muss. Das beste sind komplette Lagen für die Stromversorgung (Power Planes), aber kurze, dicke Leitungen sind meist auch OK. Es gibt auch Spannungsregler mit extra Messeingängen, welche den Spannungsabfall über der Zuleitung kompensieren können, weil sie direkt am Verbraucher die Spannung messen. Als weitere Möglichkeit werden heutzutage meist sog. Point of Load Module eingesetzt. Das sind Spannungsregler (Schaltregler), welche direkt am zu versorgenden FPGA sitzen und mit einer hohen Spannung von 5..48V über das Board versorgt werden.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Messergebnisse&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
! Messung || FPGA-Inhalt                || Icc [mA] || Vcc [V] || P [mW]&lt;br /&gt;
|-&lt;br /&gt;
| 1 || keine Konfiguration              || 80 || 2.501 || 200&lt;br /&gt;
|-&lt;br /&gt;
| 2 || Minimallogik                     || 40 || 2.502 || 100&lt;br /&gt;
|-&lt;br /&gt;
| 3 || Testlogik, inaktiv               || 235 || 2.487 || 584&lt;br /&gt;
|-&lt;br /&gt;
| 4 || Testlogik, konstantes Umschalten || 1147 || 2.433 || 2790&lt;br /&gt;
|-&lt;br /&gt;
| 5 || Testlogik, Burstbetrieb           || 690 || 2.464 || 1700&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Zusammenfassung ==&lt;br /&gt;
&lt;br /&gt;
In diesem Artikel wurde eine einfache aber leistungsfähige Methode zur Messung des Frequenzgangs des Stromversorgungsnetzwerks für FPGAs gezeigt. Die Messung kann deutlich einfacher und mit leicht verfügbaren Messgeräten unter realistischeren Bedingungen durchgeführt werden als eine klassische Messung mit einem Netzwerkanalysator. Es läßt viel Raum für Experimente mit der Entkopplung der Stromversorgung in Bezug auf die Platzierung und Werte der Kondensatoren.&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&lt;br /&gt;
*[http://processors.wiki.ti.com/index.php/General_hardware_design/BGA_PCB_design/BGA_decoupling General hardware design/BGA PCB design/BGA decoupling, Texas Instruments (engl.)]&lt;br /&gt;
*[http://www.signalintegrity.com/Pubs/pubsKeyword.htm#power%20system Signal integrity of power systems] by Howard Johnson (engl.)&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Spannungsversorgung und Energiequellen]]&lt;br /&gt;
[[Kategorie:FPGA und Co]]&lt;br /&gt;
[[Kategorie:VHDL]]&lt;/div&gt;</summary>
		<author><name>62.157.123.104</name></author>
	</entry>
</feed>