<?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=Jackfritt</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=Jackfritt"/>
	<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/articles/Spezial:Beitr%C3%A4ge/Jackfritt"/>
	<updated>2026-04-10T23:21:17Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.39.7</generator>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Versorgung_aus_einer_Zelle&amp;diff=87377</id>
		<title>Versorgung aus einer Zelle</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Versorgung_aus_einer_Zelle&amp;diff=87377"/>
		<updated>2015-02-13T14:17:50Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: /* ICs */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Bei batteriebetriebenen Anwendungen stellt sich oft das Problem der Spannungsversorgung. Darauf soll hier näher eingegangen werden.&lt;br /&gt;
&lt;br /&gt;
== Erste Ideen ==&lt;br /&gt;
&lt;br /&gt;
=== 9V-Block mit Linearregler ===&lt;br /&gt;
&lt;br /&gt;
Die erste Idee ist, einen 9V-Block mit dahintergehängtem Linearregler à la 7805 zu verwenden. Dieser Ansatz ist einfach, er hat aber einen sehr schlechten Wirkungsgrad. Bei Abwärtsregelung auf 5V verbrät der Regler immerhin 45% =&amp;gt; 55% Wirkungsgrad, bei 3,3V verbrät er 64% =&amp;gt; nur noch 36% Wirkungsgrad), und auch der Platzbedarf auf der Leiterplatte ist erheblich. Angesichts dessen kann man schon fast vernachlässigen, dass der klassische 7805 ca. 5mA für sich selber braucht. Das ist meist mehr als ein Mikrocontroller! Diesbezüglich besser sind Low Power Linearregler wie z.&amp;amp;nbsp;B. der [http://www.national.com/mpf/LP/LP2950.html LP2950] (ca. 75&amp;amp;mu;A Eigenverbrauch) oder gar ein [http://focus.ti.com/docs/prod/folders/print/tps71501.html TPS715xx] von [http://www.ti.com Texas Instuments], der mit unglaublich geringen 3,2 &amp;amp;mu;A auskommt.&lt;br /&gt;
Statt des Linearreglers könnte man natürlich auch einen Step-Down-Schaltregler benutzen, dann hätte man zumindest einen besseren Wirkungsgrad von 80-90%. Last but not least ist die Energiedichte von 9V-Blocks im Verhältnis zu Mignonzellen eher gering.&lt;br /&gt;
&lt;br /&gt;
http://data.energizer.com/ (Auf Technical Info oben rechts klicken, dann die Batteriefamilie links auswählen, z.&amp;amp;nbsp;B. Alkaline)&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! width=&amp;quot;18%&amp;quot; | Batterietyp &lt;br /&gt;
! Volumen&amp;lt;BR&amp;gt;[cm³] &lt;br /&gt;
! Kapazität&amp;lt;BR&amp;gt;[mAh] &lt;br /&gt;
! mittlere&amp;lt;BR&amp;gt;Ausgangs-&amp;lt;BR&amp;gt;spannung [V] &lt;br /&gt;
! Energiegehalt&amp;lt;BR&amp;gt;[mWh] &lt;br /&gt;
! Energiedichte&amp;lt;BR&amp;gt;[mWh/cm³] &lt;br /&gt;
! Masse&amp;lt;BR&amp;gt;[g]&lt;br /&gt;
|-&lt;br /&gt;
|9V Alkaline&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 21,1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 625&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 7&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 4375&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 207&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 45,6&lt;br /&gt;
|-&lt;br /&gt;
|Mono Alkaline [D]&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 56&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 20500&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1,3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 26650&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 475&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 148&lt;br /&gt;
|-&lt;br /&gt;
|Baby Alkaline [C]&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 26,9&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 8350&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1,3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 10855&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 404&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 26,2&lt;br /&gt;
|-&lt;br /&gt;
|Mignon Alkaline [AA]&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 8,1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2850&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1,3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3705&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 457&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 23&lt;br /&gt;
|-&lt;br /&gt;
|Micro Alkaline [AAA]&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3,8&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1250&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1,3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1625&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 428&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 11,5&lt;br /&gt;
|-&lt;br /&gt;
|Lithiumzelle, 2032&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 240&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 2,9&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 496&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 653&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3&lt;br /&gt;
|-&lt;br /&gt;
|Lithium-Thionylchlorid [C]&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 26.9&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 8500&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 3.6&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 28000&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 1040&lt;br /&gt;
| align=&amp;quot;center&amp;quot; | 50&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Vier Mignonzellen mit LowDrop-Linearregler ===&lt;br /&gt;
&lt;br /&gt;
Als weitere Möglichkeit wären vier Mignonzellen (leer 3,6V, voll 6V) mit nachgeschaltetem LowDrop-Linearregler zu verwenden. Wenn die Schaltung mit 3,3V auskommt, dann ist man mit dieser Möglichkeit bestens bedient. Die Batterien können bis zum Ende ausgenutzt werden und der Wirkungsgrad liegt bei ca. 75%.&lt;br /&gt;
Allerdings bleibt ein Nachteil, wenn man 5V braucht: Die Batterien werden nicht einmal annähernd geleert, weil sie bereits bei 1,25V pro Zelle zusammen gerade noch 5V ergeben, der Regler aber auch gern noch seinen Teil abhaben will (Dropout Voltage). Zu bedenken sind hierbei die Entladekennlinien von Batterien oder noch schlimmer, die von Akkus.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Sparsame Spannungsregler&#039;&#039;&#039;&lt;br /&gt;
!Bezeichnung || Ausgangsspannung [V] || Stromverbrauch [µA] || DropOut @ 50/150/250mA [mV] || Lieferant&lt;br /&gt;
|-&lt;br /&gt;
|LP2950&lt;br /&gt;
| align=&amp;quot;center&amp;quot; |3 / 3,3 / 5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; |75&lt;br /&gt;
| align=&amp;quot;center&amp;quot; |300 / - / -&lt;br /&gt;
| [[Elektronikversender#Reichelt | Rei]]&lt;br /&gt;
|-&lt;br /&gt;
|LF33&lt;br /&gt;
| align=&amp;quot;center&amp;quot; |3,3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; |500&lt;br /&gt;
| align=&amp;quot;center&amp;quot; |100 / 175 / 250&lt;br /&gt;
| [[Elektronikversender#Reichelt | Rei]], [[Elektronikversender#IT-WNS | I]]&lt;br /&gt;
|-&lt;br /&gt;
|LF50&lt;br /&gt;
| align=&amp;quot;center&amp;quot; |5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; |500&lt;br /&gt;
| align=&amp;quot;center&amp;quot; |100 / 175 / 250&lt;br /&gt;
| [[Elektronikversender#Reichelt | Rei]]&lt;br /&gt;
|-&lt;br /&gt;
|TPS715xx&lt;br /&gt;
| align=&amp;quot;center&amp;quot; |1,2..5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; |3.2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; |415 / - / -&lt;br /&gt;
| [[Elektronikversender#RS Components | RS]]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| [http://www.robotikhardware.de/download/tps78233.pdf TPS78233]&lt;br /&gt;
| align=&amp;quot;center&amp;quot; |3.3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; |0.42&lt;br /&gt;
| align=&amp;quot;center&amp;quot; |130&lt;br /&gt;
| [[Elektronikversender#Robotikhardware | RH]]&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
|MCP1702&lt;br /&gt;
| align=&amp;quot;center&amp;quot; |1,2..5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; |2&lt;br /&gt;
| align=&amp;quot;center&amp;quot; |15 / 40 / 650&lt;br /&gt;
| [[Elektronikversender#Reichelt | Rei]],[[Elektronikversender#IT-WNS | I]]&lt;br /&gt;
|-&lt;br /&gt;
|MCP1824&lt;br /&gt;
| align=&amp;quot;center&amp;quot; |0,8..5&lt;br /&gt;
| align=&amp;quot;center&amp;quot; |120&lt;br /&gt;
| align=&amp;quot;center&amp;quot; |30 / 90 / 150&lt;br /&gt;
| [[Elektronikversender#RS Components | RS]]&lt;br /&gt;
|- &lt;br /&gt;
|ZLDO330&lt;br /&gt;
| align=&amp;quot;center&amp;quot; |3,3&lt;br /&gt;
| align=&amp;quot;center&amp;quot; |1000&lt;br /&gt;
| align=&amp;quot;center&amp;quot; |20 / 50 / 85&lt;br /&gt;
| [[Elektronikversender#Reichelt | Rei]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Drei Mignonzellen ohne Spannungsregler ===&lt;br /&gt;
&lt;br /&gt;
Die meisten modernen [[Mikrocontroller]] haben einen sehr breiten Versorgungsspannungsbereich, teilweise von 1,8V bis 5,5V. Daher können sie direkt mit drei in Reihe geschalteten Zellen betrieben werden. Während der Entladung sinkt die Betriebsspannung (3&amp;amp;times;0,8V = 2,4V), was der Mikrocontroller aber verkraftet, sofern er nicht mit maximalem Takt läuft. Wenn man keine weiteren ICs in der Schaltung benötigt oder diese ebenso tolerant bezüglich einer veränderlichen Versorgungsspannung sind, ist diese Methode die einfachste und günstigste (100% Wirkungsgrad). Vor allem wird bei [[Ultra low power | Low Power]] Anwendungen mit [[Sleep Mode]] kein Mikroampere für einen Spannungsregler verschwendet.&lt;br /&gt;
&lt;br /&gt;
=== Lithiumzelle ===&lt;br /&gt;
&lt;br /&gt;
Lithiumzellen haben eine sehr geringe Selbstentladung und eine hohe Spannung von typisch 3V. Damit kann man einen sparsamen Mikrocontroller betreiben. Meist werden diese Zellen für Echtzeituhren und zum Datenerhalt von RAMs genutzt, da hier nur sehr geringe Ströme im Mikroamperebereich benötigt werden. Darauf sind diese Zellen ausgelegt. Aus den meisten kann man nur einige mA entnehmen, bei 10mA und mehr sinkt die verfügbare Kapazität rapide.&lt;br /&gt;
&lt;br /&gt;
Um ein Gerät nur im Notfall mit einer Lithiumzelle zu betreiben (Pufferbetrieb, Netzausfallsicherung), braucht man eine unterbrechungsfreie Umschaltung zwischen Netzteilbetrieb und Batteriebetrieb. Kritisch ist das vor allem für die Lithiumzelle (damit ist kein Lithiumakku gemeint!), da diese nicht aufgeladen werden darf. Sie wird dabei mit heftiger Reaktion zerstört! Eine einfache Schaltung ist die Nutzung von zwei Schottkydioden zur Entkopplung von Batterie und Netzteil, wie es im Artikel &#039;&#039;Speicher&#039;&#039; über  [[Speicher#EEPROM_Schreibzugriffe_minimieren | EEPROM]] gezeigt wird.&lt;br /&gt;
&lt;br /&gt;
Der Nachteil dieser Lösung ist der relativ hohe Spannungsabfall von 300..400mV über den Dioden. Besser ist der Einsatz eines P-Kanal MOSFETs zum Schalten der Batteriespannung. Dadurch kann der Spannungsabfall auf wenige Millivolt gesenkt werden. Die Schaltung dazu ist im diesem [http://www.mikrocontroller.net/topic/72275#591483 Beitrag] zu finden.&lt;br /&gt;
&lt;br /&gt;
== Bessere Lösungsansätze ==&lt;br /&gt;
&lt;br /&gt;
Wie man sehen kann, sind oben dargestellte Methoden nur bedingt zufriedenstellend. Vor allem der Platzbedarf dürfte ein k.-o.-Kriterium sein. Besser wäre es, nur eine oder zwei Zellen zu verwenden.&lt;br /&gt;
&lt;br /&gt;
=== Step-Down-Schaltregler (Abwärtsregler, Tiefsetzsteller) ===&lt;br /&gt;
&lt;br /&gt;
Falls die Batteriespannung auch am Ende der Entladung höher als die Versorgungsspannung ist, bieten sich Step-down Regler an.&lt;br /&gt;
* TPS62056 : U&amp;lt;sub&amp;gt;in&amp;lt;/sub&amp;gt; 2,7 .. 10 V, U&amp;lt;sub&amp;gt;out&amp;lt;/sub&amp;gt;=0,7 .. 6 V, 12 µA Eigenverbrauch, SMD-Gehäuse MSOP10&lt;br /&gt;
* TPS62202 : U&amp;lt;sub&amp;gt;in&amp;lt;/sub&amp;gt; 2,5 .. 6 V, U&amp;lt;sub&amp;gt;out&amp;lt;/sub&amp;gt; 1,8V, 12 µA Eigenverbrauch, SMD-Gehäuse SOT23-5&lt;br /&gt;
* OKI-78SR-xx : U&amp;lt;sub&amp;gt;in&amp;lt;/sub&amp;gt; 7 .. 36 V, U&amp;lt;sub&amp;gt;out&amp;lt;/sub&amp;gt; 3.3V/5V, Module mit Standard 78xx Anschluss.&lt;br /&gt;
&lt;br /&gt;
=== Step-Up-Schaltregler (Aufwärtsregler, Hochsetzsteller) ===&lt;br /&gt;
&lt;br /&gt;
Step-Up-Schaltregler bringen die Spannung, wie der Name schon sagt, &#039;einen Schritt nach oben&#039;. Ideal also, um aus 1,5V oder 3V z.&amp;amp;nbsp;B. 5V zu erzeugen. Desweiteren sind sie auch geeignet, um höhere Ströme (bis 0,5 A, je nach Aufbau und Spule) zu entnehmen. Das Arbeitsprinzip bei Step-Up-Schaltreglern ist immer gleich: Eine Spule wird ständig an- und abgeschaltet und durch Eigeninduktion eine höhere Spannung erzeugt. Um einen Step-Up-Schaltregler aufzubauen, gibt es verschiedene Möglichkeiten:&lt;br /&gt;
&lt;br /&gt;
==== ICs ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vorteile&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* zuverlässig&lt;br /&gt;
* meist wenig Außenbeschaltung nötig&lt;br /&gt;
* geringe Größe, auch der Spule, da hohe Schaltfrequenzen verwendet werden&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Nachteile&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* teuer, vor allem die, welche ab 1V arbeiten&lt;br /&gt;
* teilweise schwer zu bekommen&lt;br /&gt;
* benötigen mehr Aufwand für Filterung und Schirmung als Linearregler.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Bauteile]]&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ &#039;&#039;&#039;Schaltregler-ICs&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;width: 10%&amp;quot;| IC !! style=&amp;quot;width:*&amp;quot;| Bemerkung !! style=&amp;quot;width:7em&amp;quot;| Lieferant&lt;br /&gt;
|-&lt;br /&gt;
| [http://www.tranzistoare.ro/datasheets/2300/57048_DS.pdf LT1073-5] &lt;br /&gt;
| 1V (1 Zelle) auf 5V, 40mA&lt;br /&gt;
|-&lt;br /&gt;
| [http://cds.linear.com/docs/en/datasheet/1111fd.pdf LT1111]&lt;br /&gt;
| 2V-12V Step-Up, bis 30V Step-Down, 72kHz Schaltfrequenz, Bezeichnung  -5 und -12 mit fester Ausgangsspannung 5V bzw. 12V&lt;br /&gt;
| R&lt;br /&gt;
|-&lt;br /&gt;
| [http://www.ortodoxism.ro/datasheets/lineartechnology/lt1301.pdf LT1301] &lt;br /&gt;
| 2V (2 Zellen) auf 5V oder 12V, 250mA &lt;br /&gt;
| C&lt;br /&gt;
|-&lt;br /&gt;
| [http://www.ortodoxism.ro/datasheets/lineartechnology/lt1302.pdf LT1302] ||2V (2 Zellen) auf 5V oder 12V, 250mA &lt;br /&gt;
| C, R, RobHard&amp;lt;ref name=&amp;quot;plat_mod&amp;quot;&amp;gt;Platinen/ Module&amp;lt;/ref&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| [http://cds.linear.com/docs/en/datasheet/3401fb.pdf LTC3401]  ||ziemlich geniales Teil, weil es mit hoher Schaltfrequenz arbeitet, dadurch kann eine kleine Spule verwendet und ein sehr hoher Wirkungsgrad erzielt werden. 0.5...5.5V Vin, 1,0V Startup-Voltage, 2,6...5,5V Vout, bis 1A&lt;br /&gt;
|-&lt;br /&gt;
| [http://cds.linear.com/docs/Datasheet/3429fa.pdf LTC3429]||0,5...4,4V Vin, 1,0V Startup-Voltage, 2,5...4,3V Vout, 100mA aus einer Zelle, 250mA aus zwei Zellen bei 3,3V Vout&lt;br /&gt;
|-&lt;br /&gt;
| [http://www.linear.com/pc/downloadDocument.do?navId=H0,C1,C1003,C1042,C1031,C1060,P13393,D9338 LTC3525-5] ||&lt;br /&gt;
|-&lt;br /&gt;
| [http://datasheets.maxim-ic.com/en/ds/MAX866-MAX867.pdf MAX866/MAX867] ||ziemlich geniales Teil, weil es mit hoher Schaltfrequenz arbeitet, ab 0.8V, bei 0.9V Start-Up-Voltage&lt;br /&gt;
|-&lt;br /&gt;
|-&lt;br /&gt;
| [http://www.maximintegrated.com/datasheet/index.mvp/id/1207] || wie MAX866/867 jedoch 85% Wirkungsgrad bei 100mA und 500kHz Schaltgeschwindigkeit&lt;br /&gt;
|-&lt;br /&gt;
| [http://datasheets.maxim-ic.com/en/ds/MAX1595.pdf MAX1595] || dito, benötigt lediglich 3 Kondensatoren als Außenbeschaltung&lt;br /&gt;
|-&lt;br /&gt;
| [http://datasheets.maxim-ic.com/en/ds/MAX1674-MAX1676.pdf MAX1674-1676] ||bis zu ein Ampere, bei einer Zelle ist aber bei 100mA Schluss, und das auch nur, wenn die Spannung beim &amp;quot;Hochfahren&amp;quot; höher war und die richtige Spule verwendet wird&lt;br /&gt;
|I (MAX1674)&lt;br /&gt;
|-&lt;br /&gt;
| [http://datasheets.maxim-ic.com/en/ds/MAX1759.pdf MAX1759] || noch ein Hochfrequenz-Teil&lt;br /&gt;
|-&lt;br /&gt;
| [http://datasheets.maxim-ic.com/en/ds/MAX1722-MAX1724.pdf MAX1722-1724] || bis 150 mA&lt;br /&gt;
|-&lt;br /&gt;
| [http://ww1.microchip.com/downloads/en/DeviceDoc/22234B.pdf MCP1640] ||ab 0.35V bei 0.65V startup, einfache Beschaltung, regelbare Ausgangsspannung, bis 350 mA, 19µA quiescent current, nur kleine Induktivität (4,7µH) nötig&lt;br /&gt;
| C, R&lt;br /&gt;
|-&lt;br /&gt;
| [http://www.prema.com/Application/whiteleddriver.html PR4401/PR4402]||22 und 44 mA, benötigen lediglich 1 externes Bauteil, die Spule. Einfach zu handhaben&lt;br /&gt;
| R, I&lt;br /&gt;
|-&lt;br /&gt;
| [http://www.prema.com/Application/pr4404_e.html PR4404]||150 mA von einer, und 300 mA von zwei Zellen. Preiswert&lt;br /&gt;
| R, I&lt;br /&gt;
|-&lt;br /&gt;
| [http://www.sipex.com/Files/DataSheets/sp6648.pdf SP6648]&lt;br /&gt;
||&lt;br /&gt;
|-&lt;br /&gt;
| [http://focus.ti.com/lit/ds/symlink/tps61200.pdf TPS61200/201/202] ||1,8..5,5V out, Quellspannung bis herunter auf 0,3V, ?&amp;gt;90%, 0,5mm Pinabstand, 3,15*3,15mm, 10-Pin QFN&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
| [http://focus.ti.com/lit/ds/symlink/tps61220.pdf TPS61220] ||1,8..5,5V out, Quellspannung bis herunter auf 0,7V, &amp;gt;90%, 6-pin SC-70(DCK),2mm*2mm&lt;br /&gt;
|R&lt;br /&gt;
|-&lt;br /&gt;
| [http://focus.ti.com/docs/prod/folders/print/tps61006.html TPS6100x]||Single- and Dual-Cell Boost Converster, min 0,8V Vin, 1,5V...3,3V Vout, min. 100mA aus einer Zelle, min.250mA auf zwei Zellen, Gehäuse 10MSOP&lt;br /&gt;
|-&lt;br /&gt;
| [http://focus.ti.com/docs/prod/folders/print/tps61016.html TPS6101x]||1-Cell and 2-Cell Boost Converters, TPS61006 and TPS61016 are functionally equivalent. TPS61006 is non-synchronous. TPS61016 is synchronous and does not require an external Schottky diode.&lt;br /&gt;
|-&lt;br /&gt;
| TPS6030x, TPS6031x, [http://www.ortodoxism.ro/datasheets/lineartechnology/15023f.pdf LTC1502-3.3]  ||(typ. 3,x V bei 15-20 mA)&lt;br /&gt;
|-&lt;br /&gt;
| [http://www.ortodoxism.ro/datasheets2/7/0y1y62f9lzj79rs7uuf28jq4xtwy.pdf LM2621] &lt;br /&gt;
||&lt;br /&gt;
|-&lt;br /&gt;
| [[MC34063]]||(ungeeignet, läuft erst ab 3V)&lt;br /&gt;
| R, I&lt;br /&gt;
|-&lt;br /&gt;
| [http://atmel.com/dyn/products/product_card.asp?part_id=4523 ATtiny43U]||AVR-Microcontroller, der einen Boost-Converter eingebaut hat und damit eine Batterie bis auf 0.7V aussaugen kann.&lt;br /&gt;
|-&lt;br /&gt;
| [http://www.onsemi.com/pub_link/Collateral/NCP1400A-D.PDF NCP1400A]||Startup 0.8V / |&lt;br /&gt;
| W&amp;lt;ref name=&amp;quot;plat_mod&amp;quot; /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| [http://www.onsemi.com/pub_link/Collateral/NCP1402-D.PDF NCP1402]||Startup 0.8V, 200mA, Preis &amp;lt; 1 Euro &lt;br /&gt;
| W&amp;lt;ref name=&amp;quot;plat_mod&amp;quot; /&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| [http://cds.linear.com/docs/en/datasheet/338813f.pdf LTC3388] ||Nanopower Step Down Regulator, weniger als 1µA Leerlaufstrom, 50mA Ausgangsstrom&lt;br /&gt;
|}&lt;br /&gt;
Lieferanten &#039;&#039;&#039;C&#039;&#039;&#039;onrad, &#039;&#039;&#039;R&#039;&#039;&#039;eichelt, &#039;&#039;&#039;W&#039;&#039;&#039;atterott, &#039;&#039;&#039;Rob&#039;&#039;&#039;otik&#039;&#039;&#039;Hard&#039;&#039;&#039;ware.de, &#039;&#039;&#039;I&#039;&#039;&#039;T-WNS &amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Dioden&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
*Prakisch kann nahezu jede Schottkydiode mit ausreichend Strombelastbarkeit genutzt werden, siehe [[Dioden-Übersicht]].&lt;br /&gt;
&lt;br /&gt;
==== Diskrete Schaltungen ====&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vorteile:&#039;&#039;&#039;&lt;br /&gt;
* größtmögliche Anpassung an Verwendungszweck&lt;br /&gt;
* teilweise schon mit Standardhühnerfutter aufzubauen&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Nachteile:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* kompliziert&lt;br /&gt;
* nicht garantierte Funktion (z.&amp;amp;nbsp;B. wegen gepulster Gleichspannung)&lt;br /&gt;
* schlechte EMV-Eigenschaften&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Auflistung diskreter Step-Up-Schaltregler:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* http://www.elektronik-kompendium.de/forum/forum_entry.php?id=17395&lt;br /&gt;
* http://www.joretronik.de/Web_NT_Buch/Kap6_2/Kapitel6_2.html#6.2&lt;br /&gt;
* http://www.mikrocontroller.net/topic/73532#604774&lt;br /&gt;
* [http://www.nxp.com/acrobat_download/applicationnotes/AN10218_1.pdf NXP AN10218] (PDF) (Philips LPC900 microcontroller) single cell power supply&lt;br /&gt;
* [http://www.b-kainka.de/bastel36.htm Der LED-Spannungswandler] von B. Kainka&lt;br /&gt;
* [http://www.bigclive.com/joule.htm Make a Joule Thief] - Versorgung einer LED aus einer 1,5V Zelle&lt;br /&gt;
* Diskussionen von &#039;&#039;&#039;Joule-Thief&#039;&#039;&#039; Schaltungen im Forum&lt;br /&gt;
** [http://www.mikrocontroller.net/topic/47224 Sensor autark betreiben mit einem Thermogenerator]&lt;br /&gt;
** [http://www.mikrocontroller.net/topic/55041 LEDs mit Akku(s) effizient betreiben]&lt;br /&gt;
** [http://www.mikrocontroller.net/topic/38163 Wie kann man eine Knopfzellenspannung um ca. 1 Volt erhöhen]&lt;br /&gt;
** [http://www.mikrocontroller.net/topic/62158 Spannungsanhebung 1,2V -&amp;gt; 2V]&lt;br /&gt;
** [http://www.mikrocontroller.net/topic/77154 Step-Up Transistorschaltung für LED Lampe]&lt;br /&gt;
** [http://www.mikrocontroller.net/topic/56523 3x 2,9V LEDs mit 2xAAA versorgen]&lt;br /&gt;
** [http://www.mikrocontroller.net/topic/55962 Gibt es eine Möglichkeit LEDs bei 1V zu betreiben]&lt;br /&gt;
** [http://cappels.org/dproj/ledpage/leddrv.htm#Rusty_Nail_Night_Light Rusty Nail Night Light]&lt;br /&gt;
&lt;br /&gt;
=== Ladungspumpen ===&lt;br /&gt;
&lt;br /&gt;
Ladungspumpen erhöhen die Spannung, indem sie Kondensatoren zyklisch parallel laden, umpolen und in Reihe entladen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vorteile:&#039;&#039;&#039;&lt;br /&gt;
* geringer Stromverbrauch, deshalb für Low-Power-Anwendungen gut geeignet&lt;br /&gt;
* keine Spulen, deshalb kein magnetisches Störfeld&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Nachteile:&#039;&#039;&#039;&lt;br /&gt;
* nur geringe Ausgangsströme möglich (100mA)&lt;br /&gt;
* ICs nur für höhere Eingangspannungen erhältlich, ab 3V&lt;br /&gt;
* Teilweise starke Strompulse beim Umladen der Kondensatoren, womit empfindliche Analogschaltungen gestört werden können (Funkempfänger etc.)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Auflistung von Ladungspumpen:&#039;&#039;&#039;&lt;br /&gt;
* TPS60300 - Vin 0,9-1,8V&lt;br /&gt;
* TPS60100 - Vin 1,8-3,6V (200mA)&lt;br /&gt;
* MAX1759 - Vin 1,6-5,5V (2-3 Zellen)&lt;br /&gt;
* ICL7660 - Vin 1,5-10V (10mA) [Pollin]&lt;br /&gt;
&lt;br /&gt;
== Forumsbeiträge zum Thema ==&lt;br /&gt;
&lt;br /&gt;
*[http://www.mikrocontroller.net/topic/45101 3v3 Volt aus einer 1v2 Volt Zelle]&lt;br /&gt;
*[http://www.mikrocontroller.net/topic/18789 Stromversorgung aus einer Zelle]&lt;br /&gt;
*[http://www.mikrocontroller.net/topic/73532 Step-Up Mignon zu 5V]&lt;br /&gt;
*[http://www.mikrocontroller.net/topic/141635 Stepup/-down: Konstante 5V aus 4xMonozelle]&lt;br /&gt;
*[http://www.mikrocontroller.net/topic/189526 Ersatz 9V-Block durch Mikrozelle]&lt;br /&gt;
&lt;br /&gt;
== Externe Links ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.powerdesignersusa.com/InfoWeb/index.shtml Powerdesigners InfoWeb] - Free tools, resources and education for power electronics designers and students (engl.)&lt;br /&gt;
* http://www.linear.com/products/Step-Up_(Boost)_Regulators&lt;br /&gt;
* http://www.ti.com/power&lt;br /&gt;
* http://www.maxim-ic.com/products/power/&lt;br /&gt;
* [http://focus.ti.com/lit/an/slaa105/slaa105.pdf TI Application Report SLAA 105] Simple 1.5-V Boost Converter for MSP430&lt;br /&gt;
* 2-6V DC nach 5V DC Konverter auf der Basis des &#039;&#039;&#039;LT1302&#039;&#039;&#039; als  [http://www.shop.robotikhardware.de/shop/catalog/product_info.php?cPath=83&amp;amp;products_id=195 Fertigmodul] bzw. [http://www.shop.robotikhardware.de/shop/catalog/product_info.php?products_id=194 Platine] (Shop robotikhardware.de)&lt;br /&gt;
* [http://www.heise.de/mobil/Langzeittest-von-NiMH-Akkus-mit-reduzierter-Selbstentladung--/artikel/143297 Langzeittest von NiMH-Akkus mit reduzierter Selbstentladung] auf heise.de&lt;br /&gt;
* [http://spritesmods.com/?art=ucboost Run an uC from an AA-battery] auf spritesmods.com&lt;br /&gt;
* [http://www.powerstream.com/BatteryFAQ.html PowerStream Battery Chemistry FAQ]&lt;br /&gt;
* [http://ww1.microchip.com/downloads/en/AppNotes/01416a.pdf AN1416: Low-Power Design Guide] von Microchip (PDF)&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Bauteile]]&lt;br /&gt;
[[Kategorie:Spannungsversorgung und Energiequellen]]&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=C&amp;diff=86172</id>
		<title>C</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=C&amp;diff=86172"/>
		<updated>2014-12-10T09:09:17Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: Diverse tote links entfernt. Link auf Verzeichnisse mit nichtssagenden PDF Dateien entfernt.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Hardwarenahe Programmiersprache, ursprünglich als eine Art maschinenunabhängiger Makroassembler gedacht. C ist neben Assembler die bei Mikrocontrollern am häufigsten verwendete Programmiersprache.&lt;br /&gt;
&lt;br /&gt;
== C-Tutorials/Einführungen ==&lt;br /&gt;
&lt;br /&gt;
* [http://roboternetz.de/download/c_tutorial.zip Download umfangreiches C-Tutorial mit Beispielen für RN-Control und andere AVR-Boards im ZIP-Archiv] von A.Seeger&lt;br /&gt;
* [http://www.c-howto.de Einführung in C] von E. Fischer&lt;br /&gt;
* [http://www.schellong.de/c.htm C-Tutorial] von H. Schellong&lt;br /&gt;
* [http://www.c-plusplus.de/c.htm verschiedene Tutorials] zum Download&lt;br /&gt;
* [http://www.tutorials.at/ tutorials.at] auch für Pascal, Basic&lt;br /&gt;
* [http://suparum.rz.uni-mannheim.de/manuals/c/cde.htm C-Tutorial von C. Wirth] &lt;br /&gt;
* [http://www.strath.ac.uk/IT/Docs/Ccourse/ C programming] by S. Holmes&lt;br /&gt;
* [http://www.haw-hamburg.de/rzbt/dankert/c_tutor.html/ C und C++ für UNIX, DOS und MS-Windows] von J. Dankert, zum download&lt;br /&gt;
* [http://openbook.galileocomputing.de/c_von_a_bis_z/ online Version des Buchs &amp;quot;C von A bis Z&amp;quot;] von J. Wolf&lt;br /&gt;
* [http://home.fhtw-berlin.de/~junghans/cref/ C-Referenz] von M. Leslie/G.Junghanns&lt;br /&gt;
* [http://info.baeumle.com/ansic.html &amp;quot;Einiges zu Ansi-C&amp;quot;] von B. Baeumle-Courth&lt;br /&gt;
* [http://www2.informatik.uni-wuerzburg.de/dclc-faq/ FAQ der Newsgroup de.comp.lang.c]&lt;br /&gt;
* [http://www.coding-guidelines.com/cbook/cbook1_0a.pdf Derek M. Jones:  The New C Standard] e-Buch, engl., &amp;gt;1600 Seiten, mehr als &amp;quot;nur&amp;quot; Einführung/Tutorial&lt;br /&gt;
&lt;br /&gt;
== Weitere Links ==&lt;br /&gt;
* [http://www.crasseux.com/books/ctutorial/Precedence-of-operators.html#Precedence%20of%20operators Liste aller Operatoren und ihrer Prioritäten]&lt;br /&gt;
&lt;br /&gt;
[[Category:Programmiersprachen]]&lt;br /&gt;
[[Category:C| ]]&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_-_Die_genaue_Sekunde_/_RTC&amp;diff=81554</id>
		<title>AVR - Die genaue Sekunde / RTC</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_-_Die_genaue_Sekunde_/_RTC&amp;diff=81554"/>
		<updated>2014-02-12T19:19:46Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: /* Durchlaufender Hardwarezähler und fortlaufende Addition */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
Oftmals sieht man Projekte, bei denen ein externer RTC-Baustein (engl. &#039;&#039;&#039;R&#039;&#039;&#039;eal &#039;&#039;&#039;T&#039;&#039;&#039;ime &#039;&#039;&#039;C&#039;&#039;&#039;lock, Echtzeituhr; z.&amp;amp;nbsp;B. PCF8583 mit [[I2C]]-Anschluss [http://www-us.semiconductors.philips.com/acrobat/datasheets/PCF8583_5.pdf Datenblatt (PDF)]) angeschlossen ist, ohne dessen Vorteil wirklich zu nutzen.&lt;br /&gt;
&lt;br /&gt;
Die wichtigsten Vorteile einer externen RTC sind &lt;br /&gt;
# Die Zeitzählung läuft während eines Ausfalls der Hauptstromversorgung über eine kleine Stützbatterie bei geringem Strombedarf weiter.&lt;br /&gt;
# Es gibt hochgenaue RTCs, die man im Gegensatz zu Selbstbaulösungen nicht abgleichen muss.&lt;br /&gt;
# Der Strombedarf eines externen RTC ist in der Regel etwas niedriger als die RTC Funktion eines Prozessors. Als Vergleich diene ein DS1302(300nA@2V) zu einem Mega32(5uA@2.7V) als nicht ganz neuer Vertreter, bzw. ein Mega324P(500nA@1.8V) als moderner Vertreter. Dieser Vorteil kommt bei Datenschreibern (engl. data logger) zum Tragen, welche die meiste Zeit inaktiv im [[Sleep Mode]] sind.&lt;br /&gt;
&lt;br /&gt;
In allen anderen Fällen ist die zusätzliche Hardware nicht unbedingt nötig und man kann eine präzise Zeitbasis bequem mit dem Hauptquarz des Mikrokontrollers programmieren. Daraus ergeben sich sogar noch zusätzliche Vorteile, wie eine geringere Temperaturabhängigkeit und höhere Güte, die Quarze im MHz-Bereich gegenüber Quarzen im kHz-Bereich besitzen. Ich möchte hiermit die Angst vor dem bisschen Mathematik nehmen, welche zur Berechnung der Teilerfaktoren benötigt wird.&lt;br /&gt;
&lt;br /&gt;
==Lösung==&lt;br /&gt;
&lt;br /&gt;
Speziell für den AVR kommen Quarze im Bereich 1MHz bis 16MHz zum Einsatz, d.h. in einer Sekunde werden 1.000.000 bis 16.000.000 Zyklen durchlaufen (Zyklen pro Sekunde = Frequenz). Möchte man eine Sekunde messen, kann man somit die entsprechende Anzahl Zyklen von Null an hochzählen oder von dem entsprechenden Wert bis auf 0 runterzählen. Für das Zählen bietet sich im µC der Compare-Modus eines Timers an.&lt;br /&gt;
&lt;br /&gt;
Die obigen Zahlen lassen sich jedoch nicht in einer 16 Bit Variablen ausdrücken da sie zu gross sind und somit ist ein direktes Setzen des Compare-Wertes des Timers T1 im AVR nicht möglich. Deshalb unterteilt man die Quarzfrequenz in zwei Faktoren; der erste (Softwareteiler) bestimmt die Periode des Timers T1 und der zweite den Reloadwert eines Registers, welches im Timerinterrupt runtergezählt wird.&lt;br /&gt;
&lt;br /&gt;
==Beispiel== &lt;br /&gt;
&lt;br /&gt;
Im Beispiel AVR wird ein 11,0592-MHz-Quarz verwendet, was einem üblichen [[Baudratenquarz]] entspricht, d.h. damit können die UART-Standardbaudraten erzeugt werden.&lt;br /&gt;
&lt;br /&gt;
Der Softwareteiler wird mit 256 gewählt, d.h. 256 Timerinterrupts pro Sekunde, und kann somit mit nur einem einzigen Byte realisiert werden. Für größere Werte muß der Softwareteiler als int (2 Byte) deklariert werden. Bei kleineren Werten als 256 muss man beachten, dass der zweite Faktor immer noch in 2 Byte passt, um als Comparewert für den 16-Bit-Timer 1 verwendet werden zu können. &lt;br /&gt;
&lt;br /&gt;
Die Timerroutine wird in einer Sekunde Softwareteiler-Mal aufgerufen. Mit diesen 256 Hz ergibt sich eine Timerinterruptzeit von ca. 4ms, die auch sehr gut zum Entprellen von Tasten benutzt werden kann. Eine Entprellroutine kann also bequem in den Timerinterrupt mit eingefügt werden. Beachten muss man nur noch, dass das Nullsetzen des Timers erst einen Zyklus nach dem Comparematch erfolgt.&lt;br /&gt;
&lt;br /&gt;
==Berechnung==&lt;br /&gt;
&lt;br /&gt;
Die Berechnung des Comparewertes ist sehr einfach: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
Comparewert OCR1A = 11059200 / 256 - 1 = 43199, Rest 0. &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da haben wir ja noch mal Glück gehabt, es gibt keinen Rest bei der Division und die Sekunde ist exakt&lt;br /&gt;
256 * 43200 = 11059200 Zyklen lang.&amp;lt;br&amp;gt;&lt;br /&gt;
Theoretisch.&amp;lt;br&amp;gt;&lt;br /&gt;
Denn selbst wenn auf dem Quarz eine Frequenz von 11,0592 Mhz aufgedruckt ist, so schwingt er doch auf&lt;br /&gt;
einer etwas anderen Frequenz. Der Grund dafür sind Fertigungstoleranzen und natürlich die Tatsache, &lt;br /&gt;
dass die Frequenz eines Quarzes auch von der Temperatur abhängig ist. Es gilt also zunächst einmal&lt;br /&gt;
herauszufinden, auf welcher Frequenz der Quarz wirklich schwingt.&lt;br /&gt;
&lt;br /&gt;
Dazu wird eine Uhr programmiert und mit dem theoretischen Wert laufen gelassen. Nun habe ich die Uhr&lt;br /&gt;
einen Tag laufen lassen und festgestellt, dass sie 1,5 s nach geht (Dazu kann man beispielsweise die Tagesschau nutzen, welche jeden Tag um 20:00 (+einer konstanten Zeitverschiebung durch das Übertragungsmedium SAT,DVB-T, ...) beginnt und sogar eine Uhr dabei einblendet). D.h. die Quarzfrequenz beträgt in&lt;br /&gt;
Wirklichkeit: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
11059200 * (1 - 1,5 / 24 / 60 / 60) = 11059008 Hz. &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Ausführliche Rechnung:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
(Zyklen in 24h - Zyklen Verspätung) / Sekunden pro 24h = korrekte Frequenz&lt;br /&gt;
((24 * 60 * 60 * 256 * 43200) - (1,5 * 256 * 43200)) / (24 * 60 * 60) = 11059008 Hz.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also die ganze Rechnung nochmal: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
OCR1A = 11059008 / 256 - 1 = 43198, Rest 64. &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Nun haben wir einen Rest und es würden uns jede Sekunde 64 Zyklen fehlen. Das geht natürlich nicht. &lt;br /&gt;
&lt;br /&gt;
Deshalb wird jedesmal, wenn der Softwareteiler Null ist und die Sekunde weitergezählt wird, ein&lt;br /&gt;
anderer Comparewert geladen. Dieser ist dann um den Rest größer. Und beim nächsten Timerinterrupt&lt;br /&gt;
wird dann wieder der Comparewert geladen, der das Ergebnis der Division war. &lt;br /&gt;
&lt;br /&gt;
Es ergeben sich somit: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
255 * (43198 + 1) + 1 * (43198 + 64  + 1) = 11059008 Zyklen&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Exakt so, wie wir es wollten.&lt;br /&gt;
&lt;br /&gt;
==Das Programm== &lt;br /&gt;
&lt;br /&gt;
Nachfolgend nun das C-Programm. Da wir ja alle nicht gerne rechnen, lassen wir das einfach den C-Compiler erledigen. D.h. wir brauchen nur noch per Definition für XTAL den entsprechenden Wert eintragen und der Compiler rechnet alle nötigen Konstanten ganz alleine aus. &lt;br /&gt;
&lt;br /&gt;
So ein Compiler ist auch ziemlich faul, der merkt sofort, wenn die Operanden für eine Berechnung alles Konstanten sind. Und ehe er sich damit abquält, extra Code für diese Berechnungen zu erzeugen, rechnet er es lieber selber aus und fügt das Ergebnis direkt in den Code ein. &lt;br /&gt;
&lt;br /&gt;
Der Assembler kann auch 32-Bit Konstanten-Berechnungen ausführen. Allerdings muß man dann die entsprechenden Präprozessoroperationen benutzen. Man könnte auch eine Divisionsroutine aufrufen, aber dann würde ja echter Code erzeugt. &lt;br /&gt;
&lt;br /&gt;
===Beispiel in C===&lt;br /&gt;
&lt;br /&gt;
Wichtig: Ab Ver.1.4.0 haben sich Namen/Funktionen geändert: &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;There are currently two different styles present for naming the vectors. One form uses names starting with SIG_, followed by a relatively verbose but arbitrarily chosen name describing the interrupt vector. This has been the only available style in avr-libc up to version 1.2.x.&lt;br /&gt;
&lt;br /&gt;
Starting with avr-libc version 1.4.0, a second style of interrupt vector names has been added, where a short phrase for the vector description is followed by _vect. The short phrase matches the vector name as described in the datasheet of the respective device (and in Atmel&#039;s XML files), with spaces replaced by an underscore and other non-alphanumeric characters dropped. Using the suffix _vect is intented to improve portability to other C compilers available for the AVR that use a similar naming convention....&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quelle: http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/************************************************************************/&lt;br /&gt;
/*                                                                      */&lt;br /&gt;
/*          Precise 1 Second Timebase           */&lt;br /&gt;
/*                                                                      */&lt;br /&gt;
/*              Author: Peter Dannegger                                 */&lt;br /&gt;
/*                      danni@specs.de                                  */&lt;br /&gt;
/*                                                                      */&lt;br /&gt;
/************************************************************************/&lt;br /&gt;
// Target: Mega8, 2313&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/signal.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#ifndef OCR1A&lt;br /&gt;
#define OCR1A OCR1  // 2313 support&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#ifndef WGM12&lt;br /&gt;
#define WGM12 CTC1  // 2313 support&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#ifndef PINC&lt;br /&gt;
#define KEY_INPUT   PIND    // 2313&lt;br /&gt;
#else&lt;br /&gt;
#define KEY_INPUT   PINC    // Mega8&lt;br /&gt;
#endif&lt;br /&gt;
#define LED_DIR     DDRB&lt;br /&gt;
&lt;br /&gt;
//#define XTAL      11059201L   // nominal value&lt;br /&gt;
#define XTAL        11059008L   // after measuring deviation: 1.5s/d&lt;br /&gt;
&lt;br /&gt;
#define DEBOUNCE    256L        // debounce clock (256Hz = 4msec)&lt;br /&gt;
&lt;br /&gt;
#define uchar unsigned char&lt;br /&gt;
#define uint unsigned int&lt;br /&gt;
&lt;br /&gt;
uchar prescaler;&lt;br /&gt;
uchar volatile second;          // count seconds&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
SIGNAL (SIG_OUTPUT_COMPARE1A)&lt;br /&gt;
{&lt;br /&gt;
/************************************************************************/&lt;br /&gt;
/*          Insert Key Debouncing Here          */&lt;br /&gt;
/************************************************************************/&lt;br /&gt;
&lt;br /&gt;
#if XTAL % DEBOUNCE                     // bei rest&lt;br /&gt;
  OCR1A = XTAL / DEBOUNCE - 1;      // compare DEBOUNCE - 1 times&lt;br /&gt;
#endif&lt;br /&gt;
  if( --prescaler == 0 ){&lt;br /&gt;
    prescaler = (uchar)DEBOUNCE;&lt;br /&gt;
    second++;               // exact one second over&lt;br /&gt;
#if XTAL % DEBOUNCE         // handle remainder&lt;br /&gt;
    OCR1A = XTAL / DEBOUNCE + XTAL % DEBOUNCE - 1; // compare once per second&lt;br /&gt;
#endif&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main( void )&lt;br /&gt;
{&lt;br /&gt;
  LED_DIR = 0xFF;&lt;br /&gt;
  while( KEY_INPUT &amp;amp; 1 );               // start with key 0 pressed&lt;br /&gt;
&lt;br /&gt;
  TCCR1B = (1&amp;lt;&amp;lt;WGM12) | (1&amp;lt;&amp;lt;CS10);      // divide by 1&lt;br /&gt;
                    // clear on compare&lt;br /&gt;
  OCR1A = XTAL / DEBOUNCE - 1;          // Output Compare Register&lt;br /&gt;
  TCNT1 = 0;                            // Timmer startet mit 0&lt;br /&gt;
  second = 0;&lt;br /&gt;
  prescaler = (uchar)DEBOUNCE;          //software teiler&lt;br /&gt;
&lt;br /&gt;
  TIMSK = 1&amp;lt;&amp;lt;OCIE1A;                    // beim Vergleichswertes Compare Match                    &lt;br /&gt;
                                        // Interrupt (SIG_OUTPUT_COMPARE1A)&lt;br /&gt;
  sei();&lt;br /&gt;
&lt;br /&gt;
  for(;;){&lt;br /&gt;
    if( second == 60 )&lt;br /&gt;
      second = 0;&lt;br /&gt;
    PORTB = second;         // display second (binary)&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Beispiel in Assembler===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
;************************************************************************/&lt;br /&gt;
;*                                                                      */&lt;br /&gt;
;*          Precise 1 Second Timebase           */&lt;br /&gt;
;*                                                                      */&lt;br /&gt;
;*              Author: Peter Dannegger                                 */&lt;br /&gt;
;*                      danni@specs.de                                  */&lt;br /&gt;
;*                                                                      */&lt;br /&gt;
;************************************************************************/&lt;br /&gt;
.nolist&lt;br /&gt;
.include &amp;quot;m8def.inc&amp;quot;&lt;br /&gt;
&lt;br /&gt;
.equ    xtal      = 11059008&lt;br /&gt;
.equ    debounce  = 256&lt;br /&gt;
.equ    remainder = xtal - xtal / debounce * debounce&lt;br /&gt;
&lt;br /&gt;
.def    isreg     = r15&lt;br /&gt;
.def    wr0       = r16&lt;br /&gt;
.def    iwr0      = r17&lt;br /&gt;
.def    prescaler = r18&lt;br /&gt;
.def    second    = r19&lt;br /&gt;
&lt;br /&gt;
.list&lt;br /&gt;
    rjmp    init&lt;br /&gt;
.org    OC1Aaddr&lt;br /&gt;
    rjmp    OC1Aint&lt;br /&gt;
;-------------------------------------------------------------------------&lt;br /&gt;
OC1Aint:&lt;br /&gt;
    in  isreg, sreg&lt;br /&gt;
;************************************************************************/&lt;br /&gt;
;*          Insert Key Debouncing Here          */&lt;br /&gt;
;************************************************************************/&lt;br /&gt;
&lt;br /&gt;
    ldi iwr0, high( xtal / debounce - 1 )&lt;br /&gt;
    out ocr1ah, iwr0&lt;br /&gt;
    ldi iwr0, low( xtal / debounce - 1 )&lt;br /&gt;
    out ocr1al, iwr0&lt;br /&gt;
&lt;br /&gt;
    dec prescaler&lt;br /&gt;
    brne    _oci1&lt;br /&gt;
&lt;br /&gt;
    ldi prescaler, debounce&lt;br /&gt;
    inc second&lt;br /&gt;
&lt;br /&gt;
    ldi iwr0, high( xtal / debounce + remainder - 1 )&lt;br /&gt;
    out ocr1ah, iwr0&lt;br /&gt;
    ldi iwr0, low( xtal / debounce + remainder - 1 )&lt;br /&gt;
    out ocr1al, iwr0&lt;br /&gt;
_oci1:&lt;br /&gt;
    out sreg, isreg&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;
    sbic    pinc, 0&lt;br /&gt;
    rjmp    init&lt;br /&gt;
&lt;br /&gt;
    ldi wr0, high( ramend )&lt;br /&gt;
    out sph, wr0&lt;br /&gt;
    ldi wr0, low( ramend )&lt;br /&gt;
    out spl, wr0&lt;br /&gt;
&lt;br /&gt;
    ldi wr0, 1&amp;lt;&amp;lt;WGM12^1&amp;lt;&amp;lt;CS10&lt;br /&gt;
    out TCCR1B, wr0&lt;br /&gt;
&lt;br /&gt;
    ldi wr0, high( xtal / debounce - 1 )&lt;br /&gt;
    out ocr1ah, wr0&lt;br /&gt;
    ldi wr0, low( xtal / debounce - 1 )&lt;br /&gt;
    out ocr1al, wr0&lt;br /&gt;
    out tcnt1l, wr0&lt;br /&gt;
    ldi prescaler, debounce&lt;br /&gt;
&lt;br /&gt;
    ldi wr0, 1&amp;lt;&amp;lt;OCIE1A&lt;br /&gt;
    out TIMSK, wr0&lt;br /&gt;
    sei&lt;br /&gt;
main:&lt;br /&gt;
    ldi second, 0&lt;br /&gt;
_mai1:&lt;br /&gt;
    cpi second, 60&lt;br /&gt;
    breq    main&lt;br /&gt;
    out PORTB, second&lt;br /&gt;
    rjmp    _mai1&lt;br /&gt;
;------------------------------------&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Verbesserte Version mit durchlaufendem Hardwarezähler===&lt;br /&gt;
&lt;br /&gt;
Hier sind trotzdem kleine Verbesserungsvorschläge.&lt;br /&gt;
&lt;br /&gt;
Wird im Timer die Option &amp;quot;Clear On Compare Match&amp;quot; verwendet, so verliert man den Overflow Interrupt. Oder möchte man nebenher noch eine Zeit mit dem Capture Interrupt messen, so benötigt man einen durchlaufenden Timer. Um dies zu erreichen, wird OCR1A nicht fest eingestellt, sondern bei jedem Aufruf um den gleichen Wert erhöht.&lt;br /&gt;
&lt;br /&gt;
In Peters Code wurde der Rest auf einmal abgearbeitet. Damit erspart man sich bei jedem Interrupt einen Vergleich und die Verarbeitungszeit verkürzt sich in seinem Code. Der Unterschied zwischen kurzem und langem Interrupt ist hier der Rest. Bei den geänderten Codeschnipseln wird der Rest gleichmäßiger abgearbeitet. Der Unterschied zwischen kurzem und langem Interrupt beträgt 1 Takt.&lt;br /&gt;
&lt;br /&gt;
ungetesteter Code für den durchlaufenden Timer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
SIGNAL (SIG_OUTPUT_COMPARE1A) {&lt;br /&gt;
/************************************************************************/&lt;br /&gt;
/*      Insert Key Debouncing Here      */&lt;br /&gt;
/************************************************************************/&lt;br /&gt;
&lt;br /&gt;
  if( --prescaler == 0 ){ &lt;br /&gt;
    prescaler = (uchar) DEBOUNCE;&lt;br /&gt;
    second++;      // exact one second over  &lt;br /&gt;
  }  &lt;br /&gt;
#if XTAL % DEBOUNCE&lt;br /&gt;
  if (prescaler &amp;lt;= XTAL % DEBOUNCE)&lt;br /&gt;
    OCR1A += XTAL / DEBOUNCE +1;   /* um 1 Takt längere Periode um den Rest abzutragen */&lt;br /&gt;
  else&lt;br /&gt;
#endif&lt;br /&gt;
    OCR1A += XTAL / DEBOUNCE;   /* kurze Periode */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Durchlaufender Hardwarezähler und fortlaufende Addition===&lt;br /&gt;
&lt;br /&gt;
Gänzlich ohne Hin- und Hertogglen eines Bits kommt man aus, wenn irgendein Timer mit einer Überlauf-Interruptfrequenz &amp;gt; 1Hz arbeitet. Dann kann die ISR eine 32-bit-Konstante auf einen 32-bit-Akkumulator addieren; bei Überlauf ist eine Sekunde vergangen. Zugegeben, es gibt &amp;quot;lange&amp;quot; und &amp;quot;kurze&amp;quot; Sekunden, aber der Fehler summiert sich nicht, und der Code ist sehr einfach.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel:&lt;br /&gt;
&lt;br /&gt;
Es gibt ein Programm gettick(), das einen Wert holt. Dieser Wert wird von Zeit zu Zeit von der Hardware (Beispiel AVR: der Timer) oder dem Betriebssystem ermittelt. (Beispiel Linux: gettick ruft getmsec, getmsec ruft gettimeofday)&lt;br /&gt;
&lt;br /&gt;
Dieser aufgerufene Wert sollte pro Sekunde um TICKPERSEC erhöht werden, was aber mit einer gewissen Ungenauigkeit geschieht.&lt;br /&gt;
&lt;br /&gt;
Die Laufzeitkorrektur wird dadurch ausgeführt, dass der von gettick() zurückgegebene Wert mit einem Faktor TFAK multipliziert wird. Der Faktor sollte so gewählt werden, dass:&lt;br /&gt;
&lt;br /&gt;
* Das Ergebnis actual_value immer in 32 Bit hineinpasst.&lt;br /&gt;
* Die Multiplikation durch Schiebeopertionen ersetzt werden kann, weil der Faktor eine 2-er-Potenz ist. (Das erledigt avr-gcc)&lt;br /&gt;
&lt;br /&gt;
Immer wenn tsdaytim_calibrated() erkennt, dass eine Sekunde vergangen, wird last_value um die Zahl onesecond erhöht.&lt;br /&gt;
&lt;br /&gt;
Der Zahlenwert onsecond wird mit TICKPERSEC*TFAK initalisiert und kann angezeigt oder neu eingegeben werden (Die Bedienung der seriellen Schnittstelle hierfür ist in diesem Beispiel nicht enthalten).&lt;br /&gt;
&lt;br /&gt;
Wenn festgestellt wird, dass die Uhr pro Zeit (P) um (E) zu schnell geht, dann kann der Wert onsecond korrigiert werden.&lt;br /&gt;
&lt;br /&gt;
c = d *  (P+E)/P&lt;br /&gt;
Beispiel Pro 7 Tage 120 Sekunden zu viel:&lt;br /&gt;
&lt;br /&gt;
7 Tage = 7*86400= 604800 sekunden&lt;br /&gt;
c = 992000000 * (604800+120)/604800=991803175&lt;br /&gt;
Dann wird die Uhr genauer gehen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/****************************************************************/&lt;br /&gt;
/* File home/cc/qq/danclock.cpp                                 */&lt;br /&gt;
/*          Precise 1 Second Timebase                           */&lt;br /&gt;
/*                                                              */&lt;br /&gt;
/*      Author: Peter Dannegger / Hjherbert                     */&lt;br /&gt;
/*          danni@specs.de                                      */&lt;br /&gt;
/*                                                              */&lt;br /&gt;
/****************************************************************/&lt;br /&gt;
// Target: atmega8, (2313?)&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
// #include &amp;lt;avr/signal.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#ifndef OCR1A&lt;br /&gt;
#define OCR1A OCR1  // 2313 support&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#ifndef WGM12&lt;br /&gt;
#define WGM12 CTC1  // 2313 support&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#ifndef PINC&lt;br /&gt;
#define KEY_INPUT   PIND    // 2313&lt;br /&gt;
#else&lt;br /&gt;
#define KEY_INPUT   PINC    // Mega8&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//#define F_CPU     11059201L   // nominal value&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define DIVISOR 256&lt;br /&gt;
&lt;br /&gt;
#define TICKPERSEC  (F_CPU/DIVISOR)&lt;br /&gt;
&lt;br /&gt;
uint8_t volatile second;            // count seconds&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// TFAK ? TICKPERSEC must not exceed 2^32&lt;br /&gt;
#define TM (0x7FFFFFFFUL/2/TICKPERSEC)  // max of TFAK&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define TFAK ( (  (TM&amp;gt;&amp;gt;1) | (TM&amp;gt;&amp;gt;2) | (TM&amp;gt;&amp;gt;3)  | (TM&amp;gt;&amp;gt;4)  | (TM&amp;gt;&amp;gt;5)  | (TM&amp;gt;&amp;gt;6)  | (TM&amp;gt;&amp;gt;7) \&lt;br /&gt;
                | (TM&amp;gt;&amp;gt;8) | (TM&amp;gt;&amp;gt;9) | (TM&amp;gt;&amp;gt;10) | (TM&amp;gt;&amp;gt;11)  | (TM&amp;gt;&amp;gt;12)  | (TM&amp;gt;&amp;gt;13)  | (TM&amp;gt;&amp;gt;14)  | (TM&amp;gt;&amp;gt;15) \&lt;br /&gt;
                | (TM&amp;gt;&amp;gt;16) | (TM&amp;gt;&amp;gt;17) | (TM&amp;gt;&amp;gt;18) | (TM&amp;gt;&amp;gt;19)  | (TM&amp;gt;&amp;gt;20)  | (TM&amp;gt;&amp;gt;21)  | (TM&amp;gt;&amp;gt;22)  | (TM&amp;gt;&amp;gt;23) \&lt;br /&gt;
                | (TM&amp;gt;&amp;gt;24) | (TM&amp;gt;&amp;gt;25) | (TM&amp;gt;&amp;gt;26) | (TM&amp;gt;&amp;gt;27)  | (TM&amp;gt;&amp;gt;28)  | (TM&amp;gt;&amp;gt;29)  | (TM&amp;gt;&amp;gt;30)  | (TM&amp;gt;&amp;gt;31) \&lt;br /&gt;
               ) + 1 )&lt;br /&gt;
// TFAK is a power the biggest power of two which is less than TM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
uint32_t onesecond = 1*TICKPERSEC*TFAK ;    // correct this value if see the clock is late / too fast&lt;br /&gt;
uint32_t last_value ;&lt;br /&gt;
uint32_t ticks ;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
SIGNAL (SIG_OUTPUT_COMPARE1A)&lt;br /&gt;
{&lt;br /&gt;
    ++ticks ;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
uint32_t gettick( void )&lt;br /&gt;
{&lt;br /&gt;
    uint32_t l ;&lt;br /&gt;
    cli();&lt;br /&gt;
    l = ticks ;&lt;br /&gt;
    sei();&lt;br /&gt;
    return l ;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void tsdaytim_calibrated(void)&lt;br /&gt;
// Keep the time-of-the-day actual&lt;br /&gt;
// Add a second, if a second if gone&lt;br /&gt;
{&lt;br /&gt;
    uint32_t actual_value ;         // gettick() multiplied by factor 2^n&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    actual_value = gettick() * TFAK ;   // because TFAK is a power of two&lt;br /&gt;
                                        // The compiler will create some shift commands&lt;br /&gt;
&lt;br /&gt;
    if ( actual_value - last_value &amp;gt; onesecond )&lt;br /&gt;
    {                           // once per second&lt;br /&gt;
        if ( ++second &amp;gt;= 60 )&lt;br /&gt;
        {&lt;br /&gt;
            second = 0 ;&lt;br /&gt;
        }&lt;br /&gt;
        last_value += onesecond ;   // One second more&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main( void )&lt;br /&gt;
{&lt;br /&gt;
    DDRB = 0xFF;&lt;br /&gt;
    while( KEY_INPUT &amp;amp; 1 );         // start with key 0 pressed&lt;br /&gt;
&lt;br /&gt;
    TCCR1B = 1&amp;lt;&amp;lt;WGM12^1&amp;lt;&amp;lt;CS10;      // divide by 1&lt;br /&gt;
                                    // clear on compare&lt;br /&gt;
    OCR1A = DIVISOR ;               // Output Compare Register&lt;br /&gt;
    TCNT1 = 0;                      // Timer start value&lt;br /&gt;
    second = 0;&lt;br /&gt;
&lt;br /&gt;
    TIMSK = 1&amp;lt;&amp;lt;OCIE1A;              // beim Vergleichswertes Compare Match&lt;br /&gt;
                                    // Interrupt (SIG_OUTPUT_COMPARE1A)&lt;br /&gt;
    sei();&lt;br /&gt;
    last_value = gettick() * TFAK ;&lt;br /&gt;
    for(;;)&lt;br /&gt;
    {&lt;br /&gt;
        tsdaytim_calibrated();&lt;br /&gt;
        PORTB = second;             // display second (binary)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Echtzeituhr mit Uhrenquarz ==&lt;br /&gt;
&lt;br /&gt;
=== RTC mit wenig Stromverbrauch ===&lt;br /&gt;
&lt;br /&gt;
Das vorgestellte Verfahren ist leider nicht direkt anwendbar, wenn man eine RTC mit einem 32,768 KHz Uhrenquarz realisieren möchte. Dieser Weg ist dann notwendig, wenn der Controller [[Ultra low power | batteriebetrieben]] sehr lange laufen soll und durch Verwendung des [[Sleep Mode]] Strom gespart wird.&lt;br /&gt;
&lt;br /&gt;
=== Begrenzung der Auflösung ===&lt;br /&gt;
&lt;br /&gt;
Wo liegt das Problem? Das obige Verfahren nutzt recht hochfrequente Quarze mit 1 MHz und mehr. Wenn man die Frequenz eines Quarzes von 1 MHz = 1.000.000 Hz mit einer [[Auflösung und Genauigkeit| Auflösung]] von 1 Hz angibt, entspricht das einem maximalen Fehler von 1/1.000.000 oder 1ppm (engl. parts per million, millionstel Teil). Das ist sehr wenig. Eine RTC mit einem Fehler von 1ppm hat eine Gangabweichung von 86,4ms pro Tag, oder 2,5s pro Monat. Das ist ein sehr guter Wert. Wenn ich nun aber die Frequenz 32768 Hz mit 1 Hz Auflösung angebe, ist das schlimmstenfalls ein Fehler von 1/32768 = 30,5ppm, was einer Abweichung von 2,5s pro Tag und 75s pro Monat entspricht!&lt;br /&gt;
&lt;br /&gt;
=== Uhrentakt genau messen und digital korrigieren ===&lt;br /&gt;
&lt;br /&gt;
Wie kann man das Problem lösen? Die AVRs können im [[Sleep Mode]] den Uhrenquarz nur am Timer 2 betreiben, welcher ein 8 Bit Timer ist. D.H. ein Überlauf passiert alle 256 Takte, sprich 7,8125ms (=128 Hz). Man kann auch einen Prescaler verwenden, welcher das Problem aber nicht löst.&lt;br /&gt;
&lt;br /&gt;
Wie bereits festgestellt, müssen wir die Frequenz des 32768Hz Uhrenquarzes genauer messen und darstellen. Wir wollen hier annehmen, dass wir die Frequenz auf 0,001Hz = 1mHz (Millihertz) auflösen, ein guter Frequenzzähler kann das problemlos und ist auch so [[Auflösung und Genauigkeit|&#039;&#039;&#039;genau&#039;&#039;&#039;]]. Wir können beispielsweise feststellen, dass ein Quarz mit 32768,423Hz schwingt, das entspricht einem Fehler von &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;F_r=(\frac{f_{ist}}{f_{soll}} -1 )\cdot 10^6=(\frac{32768,423}{32768} -1 )\cdot 10^6=12,9ppm&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dabei ist zu beachten, daß diese Messung &#039;&#039;&#039;nicht&#039;&#039;&#039; direkt am Quarz erfolgen darf, auch nicht mit kapazitätsarmen 10:1 Tastköpfen! Denn so ein Quarz wird von kleinsten Kapazitäten im Bereich von weniger als ein pF messbar verstimmt. Darum muss man in so einem Fall den Uhrentakt auf ein anderes IO-Pin ausgeben und dort messen. Beim [[MSP430]] ist das einfach, man kann ACLK auf ein Pin direkt ausgeben. Der [[AVR]] kann das leider nicht. Hier muss man zu einem Trick greifen. Man benutzt die Output Compare Funktion, um mit Timer 2 einen 128 Hz Takt zu erzeugen. Dieser ist fest mit dem Uhrentakt verbunden und kann anstellte dessen gemessen werden, ohne den Quarz zu verstimmen. Die Messung ergibt in diesem Fall eine Frequenz von 128,00165 Hz.&lt;br /&gt;
&lt;br /&gt;
OK, jetzt haben wir den Takt gemessen, wir wissen, daß pro Sekunde 128 Timerüberläufe passieren (Prescaler =1). Wir wissen, dass unser Quarz pro Sekunde um 0,423 Takte zu schnell ist. Wir können aber keine halben Takte mehr oder weniger zählen? Doch! Mit [[Festkommaarithmetik]]! Denn nach 1000s ist unser Quarz um 423 Takte zu weit gelaufen und muss um diese Anzahl zurückgestellt werden. Also könnte man im ersten Ansatz nach 1000 Sekunden den Timer 2 um diesen Betrag korrigieren. Das Problem dabei ist nur, dass der Zähler nur 8 Bit breit ist. Ein Addieren oder Subtrahieren von 423 würde mehrfache Überläufe verursachen, welche programmtechnisch nur schwer zu handhaben wären. Also muss eine etwas bessere Methode her.&lt;br /&gt;
&lt;br /&gt;
=== Bresenham für RTCs ===&lt;br /&gt;
&lt;br /&gt;
Wenn man sich die Idee der [[Festkommaarithmetik]] mal eine Weile durch den Kopf gehen lässt, kommt man vielleicht auf folgende Idee. Der Frequenzfehler beträgt in unserem Beispiel 0,423 Hz, also Takte pro Sekunde. Oder aber 423 Tausendstel Takte pro Sekunde. Nach drei Sekunden sind es schon 1,269 Takte oder 1269 Tausendstel Takte. Moment! &#039;&#039;&#039;Einen&#039;&#039;&#039; Takt können wir korrigieren, indem wir den Zähler um 1 Takt zurück setzen. Den Restfehler von 269 Tausendstel merken wir uns und akkumulieren weiter. Wenn dann wieder die 1000er Marke überschritten wird machen wir das Gleiche. Analog dazu natürlich auch bei negativem Vorzeichen, sprich wenn der Quarz zu langsam schwingt wird er um einen Takt vorgestellt. É Voilà! Dieses Verfahren ist sehr ähnlich zum [http://de.wikipedia.org/wiki/Bresenham-Algorithmus Bresenham-Algorithmus] zum Zeichnen von Linien auf Computermonitoren.&lt;br /&gt;
&lt;br /&gt;
=== Beispielprogramm ===&lt;br /&gt;
&lt;br /&gt;
Das folgende Beispiel stellt eine RTC mit sehr niedrigem Stromverbrauch zur Verfügung. Laut Datenblatt beträgt die Stromaufnahme nur ca. 6µA bei 3V Versorgungsspannung, besser als einige kommerzielle RTCs! Möglich macht das die Nutzung des Power Save [[Sleep Mode]]s. Die Frequenz kann auf &amp;lt;math&amp;gt;10^{-5}&amp;lt;/math&amp;gt; Hz genau abgeglichen werden, was in diesem Fall bei einer Messfrequenz von 128Hz einer Auflösung von 0,078ppm entspricht. Das bedeutet eine Abweichung von 6,7ms pro Tag, 0,2s pro Monat oder 2,46s pro Jahr!&lt;br /&gt;
&lt;br /&gt;
Die Abweichung des Quarzes wird in einer vorzeichenbehafteten 16 Bit Variable in der Einheit &amp;lt;math&amp;gt;10^{-3}&amp;lt;/math&amp;gt; Hz gespeichert. D.h. es kann ein Frequenzfehler von +/- 32,768 Hz korrigiert werden, das sind 1000ppm! Normale Quarze haben Abweichungen von max. 100ppm, meist viel weniger. Jede Sekunde wird der Frequenzfehler neu berechnet und in den darauffolgenden 128 Interrupts ggf. mehrfach korrigiert. Wichtig ist dabei, dass die Korrektur wirklich ganz am Anfang der ISR steht, weil hier das Timing wirklich kritisch ist. Denn innerhalb eines Uhrenquarztaktes von ~30µs muss der Timer 2 neu beschrieben werden. Bei 1 MHz RC-Oszillatortakt sind das nur 30 Takte, wovon 6 zum Aufwachen und 4 zum Anspringen der ISR benötigt werden. Dazu kommen noch das Sichern einiger Register am Anfang der ISR, was man im C nicht direkt sieht. Sicherheitshalber sollte man auch einen höheren Takt einstellen, z.&amp;amp;nbsp;B. 2 MHz, dann ist das Timing wesentlich entspannter.&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;
*&lt;br /&gt;
* Stromsparende Echtzeituhr mit 32768Hz Uhrenquarz&lt;br /&gt;
*&lt;br /&gt;
* ATmega88 mit internem 2 MHz Oszillator + 32,768 kHz Quarz&lt;br /&gt;
*&lt;br /&gt;
* Fuses bleiben auf Standardeistellungen&lt;br /&gt;
* LOW Fuse Byte = 0x62&lt;br /&gt;
* HIGH Fuse Byte = 0xDF&lt;br /&gt;
* EXT Fuse Byte = 0xF9&lt;br /&gt;
*&lt;br /&gt;
* LED mit 1K Vorwiderstand an PB5&lt;br /&gt;
* Kalibriertaktausgang an PB3&lt;br /&gt;
************************************************************************&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define F_CPU 2000000L          // Systemtakt in Hz&lt;br /&gt;
#define F_CAL 12800000L         // gemessener Kalibriertakt in 10^-5 Hz&lt;br /&gt;
                                // Endung L ist wichtig!&lt;br /&gt;
&lt;br /&gt;
#define LED_TOGGLE PORTB ^= (1&amp;lt;&amp;lt;PB5);&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/eeprom.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// EEPROM Daten&lt;br /&gt;
&lt;br /&gt;
int16_t ee_rtc_cal EEMEM = (F_CAL-12800000)*256/100;        // Kalibrierung für RTC, Frequenzfehler in 1/1000 Hz&lt;br /&gt;
&lt;br /&gt;
// globale Variablen&lt;br /&gt;
&lt;br /&gt;
// beidseitiger Zugriff durch ISR und Hauptprogramm&lt;br /&gt;
&lt;br /&gt;
volatile uint32_t time;             // 24h Zeitstempel, 1s Auflösung&lt;br /&gt;
volatile int16_t rtc_cal;           // Kalibrierung des 32K Quarzes&lt;br /&gt;
volatile uint8_t flag_1s;           // Flag für 1s Intervall&lt;br /&gt;
&lt;br /&gt;
void long_delay(uint16_t ms) {&lt;br /&gt;
    for (; ms&amp;gt;0; ms--) _delay_ms(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main (void) {&lt;br /&gt;
&lt;br /&gt;
// Clock divider auf /4&lt;br /&gt;
&lt;br /&gt;
    CLKPR = 0x80;       // update  enable&lt;br /&gt;
    CLKPR = 2;          // Prescaler /4&lt;br /&gt;
&lt;br /&gt;
// IO konfigurieren&lt;br /&gt;
&lt;br /&gt;
    DDRB  = (1&amp;lt;&amp;lt;PB3) | (1&amp;lt;&amp;lt;PB5);&lt;br /&gt;
    PORTB = ~((1&amp;lt;&amp;lt;PB3) | (1&amp;lt;&amp;lt;PB5)); // Pull ups &lt;br /&gt;
    PORTC = 0xFF;       &lt;br /&gt;
    PORTD = 0xFF;&lt;br /&gt;
&lt;br /&gt;
// Analogcomparator ausschalten&lt;br /&gt;
&lt;br /&gt;
    ACSR = 0x80;&lt;br /&gt;
&lt;br /&gt;
// Timer2 konfigurieren&lt;br /&gt;
&lt;br /&gt;
    ASSR   = (1&amp;lt;&amp;lt; AS2);             // Timer2 asynchron takten&lt;br /&gt;
    long_delay(1000);               // Einschwingzeit des 32kHz Quarzes&lt;br /&gt;
    TCCR2A = (1&amp;lt;&amp;lt;COM2A1) | (1&amp;lt;&amp;lt;WGM21) | (1&amp;lt;&amp;lt;WGM20); // Fast PWM, non inverted&lt;br /&gt;
    TCCR2B = 1;                     // Vorteiler 1 -&amp;gt; 7,8ms Überlaufperiode&lt;br /&gt;
    OCR2A  = 128;                   // PWM, Tastverhältnis 50%&lt;br /&gt;
    while((ASSR &amp;amp; (1&amp;lt;&amp;lt; TCR2BUB)));  // Warte auf das Ende des Zugriffs&lt;br /&gt;
    TIFR2  &amp;amp;= ~(1&amp;lt;&amp;lt;TOV2);           // Interrupts löschen&lt;br /&gt;
    TIMSK2 |= (1&amp;lt;&amp;lt;TOIE2);           // Timer overflow Interrupt freischalten&lt;br /&gt;
&lt;br /&gt;
// EEPROM Werte auslesen&lt;br /&gt;
&lt;br /&gt;
    rtc_cal= eeprom_read_word(&amp;amp;ee_rtc_cal);&lt;br /&gt;
&lt;br /&gt;
// Interrupts freigeben&lt;br /&gt;
&lt;br /&gt;
    sei();&lt;br /&gt;
&lt;br /&gt;
// Endlose Hauptschleife&lt;br /&gt;
&lt;br /&gt;
    while(1) {&lt;br /&gt;
&lt;br /&gt;
        while((ASSR &amp;amp; (1&amp;lt;&amp;lt; OCR2AUB)));  // Warte auf das Ende des Zugriffs&lt;br /&gt;
        set_sleep_mode(SLEEP_MODE_PWR_SAVE);&lt;br /&gt;
        sleep_mode();                   // in den Schlafmodus wechseln&lt;br /&gt;
&lt;br /&gt;
        // hier wachen wir wieder auf, nach Ausführung des 7,8ms Timerinterupt&lt;br /&gt;
&lt;br /&gt;
        if (flag_1s) {  &lt;br /&gt;
            flag_1s =0;&lt;br /&gt;
            LED_TOGGLE                      // Test&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Timer2 overflow Interrupt&lt;br /&gt;
&lt;br /&gt;
ISR(TIMER2_OVF_vect) {&lt;br /&gt;
    static uint8_t ticks;               // Hilfsvariable für Messintervall&lt;br /&gt;
    static int16_t time_error;          // RTC Fehlerkompensation&lt;br /&gt;
&lt;br /&gt;
    // Zeitkritische Dinge, welche am Anfang der ISR stehen müssen!&lt;br /&gt;
&lt;br /&gt;
    OCR2A=128;                          // Dummy-Write zur Sicherung des Timings&lt;br /&gt;
                                        // von Timer 2 im asynchronen Modus &lt;br /&gt;
&lt;br /&gt;
    // RTC Fehler korrigieren&lt;br /&gt;
&lt;br /&gt;
    if (time_error&amp;gt;999) {               // RTC zu schnell&lt;br /&gt;
        TCNT2 = 2;                      // Zähler einen Schritt zurück setzen (2 Takte Verzögerung!)&lt;br /&gt;
        time_error -= 1000;&lt;br /&gt;
    } else if (time_error&amp;lt;-999) {       // RTC zu langsam&lt;br /&gt;
        TCNT2 = 4;                      // Zähler einen Schritt vor setzen (2 Takte Verzögerung!)&lt;br /&gt;
        time_error += 1000;     &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ab hier ist es nicht mehr zeitkritisch&lt;br /&gt;
&lt;br /&gt;
    // Echtzeituhr&lt;br /&gt;
    ticks++;                            // 1/128tel Sekunde&lt;br /&gt;
    if (ticks==128) {                   // Sekundenintervall&lt;br /&gt;
        time_error += rtc_cal;          // RTC Fehler akkumulieren&lt;br /&gt;
&lt;br /&gt;
        // 24h Timer&lt;br /&gt;
        time++;&lt;br /&gt;
        if (time==86400) time=0;        // 24h Überlauf&lt;br /&gt;
&lt;br /&gt;
        ticks=0;&lt;br /&gt;
        flag_1s =1;                     // setzte Flag für 1s Verarbeitung in main Endlosschleife&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Weitere Verbesserungen ===&lt;br /&gt;
&lt;br /&gt;
Der Algorithmus ermöglicht eine sehr hochauflösende Kalibrierung der RTC. Allerdings heisst das leider noch lange nicht, daß die RTC dann auch wirklich so genau ist. Denn diese Kalibrierung gilt nur für eine exakte Temperatur! Auch ein Quarz hat eine Temperaturabhängigkeit der Schwingfrequenz. Wenn man nun eine sehr genaue RTC bauen möchte, welche über einen grossen Temperaturbereich genau läuft, muss man periodisch die Temperatur messen und in die Kalibrierung einbeziehen. Einen typischen Temperaturverlauf des Frequenzfehlers zeigt das folgende Bild.&lt;br /&gt;
&lt;br /&gt;
[[bild:rtc_tk.gif|thumb|260px|left|Temperaturgang eines Uhrenquarzes]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Weiterhin kann man natürlich die Kalibrierung ohne erneutes Kompilieren des Quelltextets vornehmen, indem man den Kalibrierwert per [[UART]] oder [[I2C]] an den AVR sendet und im [[Speicher#EEPROM | EEPROM]] speichert.&lt;br /&gt;
&lt;br /&gt;
Kernpunkt der Kalibrierung ist natürlich die Messung der realen Quarzfrequenz. Die oben beschriebene Methode per Tagesschau und 1 Tag warten ist sehr zeitaufwändig und hat eine begrenzte Genauigkeit von ca. 1/2 Sekunde, das entspricht 5,8ppm. Hier muss zwangsläufig ein guter Frequenzzähler her. Da dieser nicht jedem Hobbybastler zur Verfügung steht, muss man sich in Lehrwerkstätten, Universitäten oder Firmen im Elektronikbereich umsehen und nachfragen, ob man einen Frequenzzähler vor Ort kurze Zeit nutzen kann.&lt;br /&gt;
&lt;br /&gt;
Einige GPS-Module bieten auch einen hochgenauen 1PPS (Pulse Per Second) Ausgang an, der sich für den Abgleich gut heranziehen lässt. Auch das Sekunden-Zeichen eines DCF77-Funkuhr-Moduls ist sehr genau und kann als Referenz dienen.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
*[http://www.mikrocontroller.net/articles/Uhr Implementierung einer Uhr mit Siebensegmentausgabe auf einem AVR ATTiny2313]&lt;br /&gt;
*[http://www.mikrocontroller.net/topic/165249 Uhr mit genauer Sekunde BASCOM]&lt;br /&gt;
*[https://www.mikrocontroller.net/topic/298306 Stromsparende und günstige Zeitmessung: ATtiny mit Uhrenquarz getaktet]&lt;br /&gt;
&lt;br /&gt;
[[Category:AVR-Projekte]]&lt;br /&gt;
[[Category:Timer und Uhren]]&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_Bootloader_FastBoot_von_Peter_Dannegger&amp;diff=81100</id>
		<title>AVR Bootloader FastBoot von Peter Dannegger</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_Bootloader_FastBoot_von_Peter_Dannegger&amp;diff=81100"/>
		<updated>2014-01-23T08:55:35Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: /* Added links for avrdude support */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von Karsten Donat&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Was ist ein Bootloader? ==&lt;br /&gt;
&lt;br /&gt;
Der Bootloader ist selbst ein kleines Programm. Es wird beim Start des Controllers zuerst ausgeführt. Damit sich das PC-Programm für das Firmware-Update melden kann, wartet der Bootloader  eine gewisse Zeit (hier 0,33 Sekunden) auf ein Zeichen über die serielle Schnittstelle (UART RS232, USB). Kommt dies Zeichen, wird die neue Firmware gebrannt. Andernfalls wird das eigentliche Programm des Controllers ausgeführt.&lt;br /&gt;
&lt;br /&gt;
Dem eigentlichen Anwendungsprogramm geht natürlich der Platz verloren, den der Bootloader benötigt. Da Peters Bootloader jedoch in ein 512Bytes (256 Worte!) großes Segment passt, stört das nicht weiter.&lt;br /&gt;
&lt;br /&gt;
Normalerweise wird der Programmcode des Mikrocontrollers mit einem ISP-Dongle in den Flash gebrannt. Aus verschiedenen Gründen kann dies jedoch nicht möglich/ gewünscht sein:&lt;br /&gt;
* Geschwindigkeit: Der ISP-Dongle kann langsam sein (z.&amp;amp;nbsp;B. myAVR mit aktuellem AVRDude)&lt;br /&gt;
* PINs: Man braucht die PINs und will ISP abschalten (Fuses, aber Vorsicht!, danach kann man nur mit dem Bootloader oder einem [[AVR HV-Programmer]] noch an den Flash-Speicher)&lt;br /&gt;
* Komfort: Man möchte dem Kunden/Nutzer die Möglichkeit geben, eine neue Firmware selbst einzuspielen. In der Regel hat dieser jedoch keinen ISP-Dongle zur Hand. Eine RS232- oder USB-Schnittstelle ist aber oftmals vorhanden.&lt;br /&gt;
* Sicherheit: Man möchte dem Kunden nicht die Firmware in deassemblierbarer Form geben (über geänderten Bootloader kann die Datei verschlüsselt sein).&lt;br /&gt;
&lt;br /&gt;
== Features ==&lt;br /&gt;
* Automatische Erkennung der vom PC verwendeten Baudrate&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/73196#610574 Ein] oder zwei Wire Betrieb&lt;br /&gt;
* Support für viele verschiedene AVRs wie: tiny13, tiny2313, tiny25, tiny261, tiny44, tiny45, tiny461, tiny84, tiny85, tiny861, mega48, mega8, mega8515, mega8525, mega88, mega16, mega162, mega168, mega32, mega64, mega644, mega128, mega1281, mega2561.&lt;br /&gt;
* Passwortschutz gegen unberechtigtes Umprogrammieren (aber keine Verschlüsselung des Programms).&lt;br /&gt;
* Freie Software - unter GPL lizenziert ([http://www.mikrocontroller.net/topic/73196?goto=848377#848377 Link]). Das eigentliche Anwendungsprogramm, das über den Bootloader geladen wird muß deswegen *nicht* unter der GPL stehen und dessen Quelltext auch *nicht* veröffentlicht werden ([http://www.mikrocontroller.net/topic/73196?goto=950943#950943 Link]).&lt;br /&gt;
&lt;br /&gt;
== Anforderungen an das zu ladende Programm ==&lt;br /&gt;
Bei AVRs ohne &amp;quot;boot reset vector fuse&amp;quot; (BOOTRST) wie beispielsweise ATtinys und kleinen ATmegas (ATmega48) muß der erste Befehl ein RJMP sein. Für C-Programme ist das automatisch sichergestellt (und für Assembler-Programme leicht selbst sicherzustellen).&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Thread zum Bootloader: [http://www.mikrocontroller.net/topic/73196 UART Bootloader ATtiny13 - ATmega644]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Version 2.1&#039;&#039;&#039; (Forumsbeiträge):&lt;br /&gt;
** [http://www.mikrocontroller.net/topic/goto_post/850843 Ursprüngliche Version von Peter Dannegger], inkl. DOS Host-Software&lt;br /&gt;
** [http://www.mikrocontroller.net/topic/goto_post/1824790 Angepasste Version für AVR-GCC-Toolchain]&lt;br /&gt;
** [http://www.mikrocontroller.net/topic/goto_post/685654 Protokollbeschreibung] Host &amp;lt;-&amp;gt; Target Kommunikation&lt;br /&gt;
** [http://www.mikrocontroller.net/topic/goto_post/610574 Schaltbild für One-Wire-Betrieb]&lt;br /&gt;
* &#039;&#039;&#039;Host-Software für Version 2.1&#039;&#039;&#039;&lt;br /&gt;
** [http://www.mikrocontroller.net/topic/goto_post/2320796 Linux-Host] (mit One-Wire-Unterstützung), Sourcecode im [https://github.com/Boregard/FBoot-Linux GitHub]&lt;br /&gt;
** [http://www.avrfreaks.net/index.php?module=Freaks%20Academy&amp;amp;func=viewItem&amp;amp;item_type=project&amp;amp;item_id=1927 Linux- und Mac-Host] (ohne One-Wire-Unterstützung), nur mit Anmeldung&lt;br /&gt;
** [http://www.mikrocontroller.net/topic/goto_post/1855508 Dev-C++ Portierung] (Win64)&lt;br /&gt;
** [http://www.mikrocontroller.net/topic/314358 Windows-Host mit GUI] von [http://www.leo-andres.de/2012/09/updateloader-benutzeroberflache-fur-avr-bootloader/ leo-andres.de], [http://www.mikrocontroller.net/topic/goto_post/2827323 alte Version]&lt;br /&gt;
* &#039;&#039;&#039;Host-Software für Version 1.7&#039;&#039;&#039;&lt;br /&gt;
** [http://www.kreatives-chaos.com/artikel/fastboot17-frontend-python Python-Script] von kreatives-chaos.com&lt;br /&gt;
** [http://www.mikrocontroller.net/topic/goto_post/698193 Dev-C++ Portierung] (Win32)&lt;br /&gt;
* &#039;&#039;&#039;Sonstiges&#039;&#039;&#039;&lt;br /&gt;
** Atmel AVR-Studio (um Bootloader zu assemblieren): [http://www.atmel.com/dyn/products/tools_card.asp?tool_id=2725 http://www.atmel.com/dyn/products/tools_card.asp?tool_id=2725]&lt;br /&gt;
** Ältere Version dieser Anleitung als PDF: [http://www.KarstenDonat.de/AVR/Bootloader.pdf http://www.KarstenDonat.de/AVR/Bootloader.pdf]&lt;br /&gt;
&lt;br /&gt;
== Bootloader anpassen ==&lt;br /&gt;
&lt;br /&gt;
=== CPU auswählen – BOOTLOAD.ASM ===&lt;br /&gt;
&lt;br /&gt;
Die CPU (der Atmel auf dem der Bootloader laufen soll) wird durch Einkommentieren der zugehörigen Include-Files ausgewählt. Im Beispiel für einen ATtiny45.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
;           select the appropriate include file:&lt;br /&gt;
;.include &amp;quot;tn13def.inc&amp;quot;&lt;br /&gt;
;.include &amp;quot;tn2313def.inc&amp;quot;&lt;br /&gt;
;.include &amp;quot;tn25def.inc&amp;quot;&lt;br /&gt;
;.include &amp;quot;tn261def.inc&amp;quot;&lt;br /&gt;
;.include &amp;quot;tn44def.inc&amp;quot;&lt;br /&gt;
.include &amp;quot;tn45def.inc&amp;quot;&lt;br /&gt;
;.include &amp;quot;tn461def.inc&amp;quot;&lt;br /&gt;
;.include &amp;quot;m48def.inc&amp;quot;&lt;br /&gt;
;.include &amp;quot;tn84def.inc&amp;quot;&lt;br /&gt;
;.include &amp;quot;tn85def.inc&amp;quot;&lt;br /&gt;
;.include &amp;quot;tn861def.inc&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dabei nicht vergessen, die bisher (per Default) ausgewählte CPU ATmega168 auszukommentieren:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
;.include &amp;quot;m168def.inc&amp;quot;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== UART Port und Pins festlegen – BOOTLOAD.ASM ===&lt;br /&gt;
&lt;br /&gt;
Da die verwendeten Pins für die Schnittstelle frei wählbar sind, müssen diese noch eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
STX_PORT: Hier den Sendeport angeben. Für die Pins des Hardware-UARTs des M8 wäre das Port D. Es müssen zwar nicht dieselben Pins sein, wenn man sie aber ohnehin als Schnittstelle nutzt, ist es sinnvoll, sie auszuwählen.  Verwendet wird immer ein im Bootloader integrierter Software-UART, der auf beliebigen I/O-Pins lauschen kann.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
.equ    STX_PORT        = PORTD&lt;br /&gt;
.equ    STX             = PD1&lt;br /&gt;
&lt;br /&gt;
.equ    SRX_PORT        = PORTD&lt;br /&gt;
.equ    SRX             = PD0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&#039;&#039;Beispiel für gleiche Bepinnung wie Hardware-UART im ATMega 8, 48, 168&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Für One-Wire-Betrieb muß für TX und RX zweimal der gleiche Pin angeben werden. Beim Assemblieren wird das erkannt und One-Wire aktiviert - es ist keine weitere Änderung nötig.&lt;br /&gt;
&lt;br /&gt;
=== CPU-Frequenz und Wartezeit festlegen - FASTLOAD.H ===&lt;br /&gt;
&lt;br /&gt;
Bei XTAL die benutzte Frequenz des Controllers einstellen (jungfräuliche AVRs haben oft intern 1MHz aktiviert!).&lt;br /&gt;
Im Standard Makefile von WinAVR steht die Frequenz unter F_CPU&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
.equ	XTAL		= 8000000   ; 8MHz, not critical&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um die Wartezeit auf das Firmware-Update beim Booten anzupassen:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
.equ	BootDelay	= XTAL / 3  ; 2.66s&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Assemblieren des Bootloaders ==&lt;br /&gt;
&lt;br /&gt;
Da der Bootloader in Assembler geschrieben ist, kann WinAVR nicht so ohne weiteres damit umgehen.&lt;br /&gt;
Das einfachste ist, sich das AVRStudio von Atmel herunterzuladen [http://www.atmel.com/dyn/products/tools_card.asp?tool_id=2725 http://www.atmel.com/dyn/products/tools_card.asp?tool_id=2725]&lt;br /&gt;
&lt;br /&gt;
Im Unterverzeichnis AvrAssembler2 befindet sich der benötigte Assembler. Das Einfachste ist, sich die unter &amp;quot;Appnotes&amp;quot; benötigte Include Datei des jeweiligen Controllers (oder das komplette Verzeichnis) und die avrasm2.exe ins Verzeichnis des Bootloaders zu kopieren.&lt;br /&gt;
&lt;br /&gt;
Danach wird der Assembler aufgerufen (m8.asm für ATMega 8) und der Bootloader kompiliert:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrasm2 -fI BOOTLOAD.ASM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es ist wichtig, dass die Includes des avrasm2 und nicht die der alten Version verwendet werden, da es sonst beim Assemblieren zu dem Fehler &lt;br /&gt;
&amp;quot;&#039;&#039;fastload.h(112): error: Use of undefined or forward referenced symbol &#039;SRAM_START&#039; in .org&#039;&#039;&amp;quot;&lt;br /&gt;
kommt.&lt;br /&gt;
&lt;br /&gt;
Das AVRStudio lässt sich unter Linux auch mit WINE installieren (die IDE des AVR Studio 4 geht allerdings nur mit ein paar Tricks aus der AppDB - ist für das Assemblieren des Bootloaders aber nicht nötig). Wenn &amp;quot;avrasm2.exe&amp;quot; und die zum AVR passende Include-Datei (beispielsweise &amp;quot;tn45def.inc&amp;quot; für ATtiny45) im gleichen Verzeichnis wie die restlichen Dateien des Bootloaders liegen, kann der Bootloader mit folgendem Befehl assembliert werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
wine avrasm2.exe -fI BOOTLOAD.ASM&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Brennen des Bootloaders ==&lt;br /&gt;
&lt;br /&gt;
Der nun erzeugte Bootloader wird mit dem vorhanden ISP Dongle in den AVR gebrannt (Intel Hex Format):&lt;br /&gt;
&lt;br /&gt;
 &amp;quot;avrdude&amp;quot; -p m8 -c avr910 -P com1 -U flash:w:&amp;quot;C:\Test\m8 3686400.hex&amp;quot;:i -U flash:v:&amp;quot;C:\Test\m8 3686400.hex&amp;quot;:i -y&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Brennen mit AVRDude auf COM 1 und einem AVR910 kompatiblen Dongle (z.&amp;amp;nbsp;B. myAVR USB)&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Einstellen der Fuses ==&lt;br /&gt;
&lt;br /&gt;
Damit der Bootloader zu Beginn gestartet wird, müssen die entsprechenden Fuses gesetzt werden. Möglich ist dies u.a. mit der AVRDude GUI.&lt;br /&gt;
* BOOTRST muss auf 0 gestellt werden (aktiviert den Bootloader)&lt;br /&gt;
* BOOTSZ muss auf 256 Worte (= 512 Byte) (oder dem minimal möglichen Wert, wenn AVR nur größere Bootloader Regionen unterstützt) gestellt werden. Beispielsweise ist für den ATMega8 der Wert 10.&lt;br /&gt;
&lt;br /&gt;
Bei einigen Controllern wie z.&amp;amp;nbsp;B. dem ATMega 48 wird das Flag&lt;br /&gt;
* Selfprogramming enabled gesetzt.&lt;br /&gt;
&lt;br /&gt;
Auf dieser [http://www.engbedded.com/fusecalc/ Website (Fusecalc)] kann man sich die Fuses elegant zusammenstellen und erhält gleich die Parameter für avrdude. Eine schnelle und *sichere* Alternative zum fehlerträchtigen &amp;quot;Kaputtflashen&amp;quot; von Atmels.&lt;br /&gt;
&lt;br /&gt;
== Brennen des eigentlichen Programmes ==&lt;br /&gt;
&lt;br /&gt;
Damit das Programm mit Peters Tool in den Controller geladen werden kann, muss es im Intel HEX Format vorliegen. Im makefile Template von WinAVR (und auch der ATMegaIDE) ist dies standardmäßig eingestellt.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
# Output format. (can be srec, ihex, binary)&lt;br /&gt;
FORMAT = ihex&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach wird Peters Firmware-Update Tool aufgerufen (hier COM2)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
fboot /C2 /Pmain.hex&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&#039;&#039;hier wird die main.hex als Hauptprogramm gebrannt&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Wichtig hierbei ist, dass der Dateiname der alten DOS Konvention entspricht. Also keine langen Dateinamen.&lt;br /&gt;
&lt;br /&gt;
Peters Firmware-Update Tool lässt sich unter Linux leider nicht mit WINE starten, dafür aber mit DOSBOX. Der Aufruf ist dann der gleiche wie unter Windows.&lt;br /&gt;
&lt;br /&gt;
Wenn noch keine Firmware im Controller ist (direkt nach dem Installieren des Bootloaders), startet der Brennvorgang automatisch. Andernfalls wartet das Programm auf den Reset des Controllers. Peters Tool arbeitet nur mit COM1 bis COM4 zusammen. Also ggf. den USB Adapter im Gerätemanager umstellen.&lt;br /&gt;
&lt;br /&gt;
Die Ausgabe sieht dann wie folgt aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
C:\DOCUME~1\zzzzzz\Desktop\avr\_soft\fboot18&amp;gt;fboot18 /Ptest.hex /b9600 /c1&lt;br /&gt;
COM 1 at 9600 Baud: Connected (One wire)&lt;br /&gt;
Bootloader V1.8&lt;br /&gt;
Target: 1E9108&lt;br /&gt;
Buffer: 32 Byte&lt;br /&gt;
Size available: 1534 Byte&lt;br /&gt;
Program test.hex: 00000 - 00073 successful&lt;br /&gt;
CRC: o.k.&lt;br /&gt;
Elapsed time: 1.43 seconds&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für Linux steht ebenfalls ein [https://github.com/Boregard/FBoot-Linux Programmiertool] (aus diesem [http://www.mikrocontroller.net/topic/73196#1067153 Beitrag]) für die aktuelle Version 2.1 des Bootloaders für die Kommandozeile zur Verfügung, das auch den One-Wire-Betrieb unterstützt.&lt;br /&gt;
&lt;br /&gt;
Es lässt sich nach dem Entpacken durch ein simples &amp;quot;make&amp;quot; übersetzen. Die Verwendung ist analog zum DOS-Tool:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
./bootloader -d /dev/ttyS0 -b 115200 -p tiny45test.hex&lt;br /&gt;
&lt;br /&gt;
=================================================&lt;br /&gt;
|           BOOTLOADER, Target: V2.1            |&lt;br /&gt;
=================================================&lt;br /&gt;
Port    : /dev/ttyS0&lt;br /&gt;
Baudrate: 115200&lt;br /&gt;
File    : tiny45test.hex&lt;br /&gt;
Reading : tiny45test.hex... File read.&lt;br /&gt;
Size    : 2717 Bytes&lt;br /&gt;
Program device.&lt;br /&gt;
-------------------------------------------------&lt;br /&gt;
Waiting for device... connected (one wire)!&lt;br /&gt;
Bootloader    : V2.1&lt;br /&gt;
Target        : 1E9206 ATtiny45&lt;br /&gt;
Buffer        : 64 Byte&lt;br /&gt;
Size available: 3582 Byte&lt;br /&gt;
CRC enabled and OK.&lt;br /&gt;
Programming   : 00000 - 00A9D&lt;br /&gt;
Writing | ##################################### | 100%&lt;br /&gt;
Elapsed time: 0.79 seconds, 3439 Bytes/sec.&lt;br /&gt;
&lt;br /&gt;
 ++++++++++ Device successfully programmed! ++++++++++&lt;br /&gt;
&lt;br /&gt;
...starting application&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Bootloader-Support in ATMegaIDE 2007 ==&lt;br /&gt;
&lt;br /&gt;
Die IDE kann wahlweise mit AVRDude und einem entsprechenden ISP-Dongle oder mit dem Bootloader das Programm in den Flash brennen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Anpassen des Programms ===&lt;br /&gt;
Um das Firmware Update komfortabler zu gestalten, kann ein Software-Reset eingebaut werden, der per RS232- bzw. USB-Schnittstelle oder Tastendruck ausgelöst wird.&lt;br /&gt;
&lt;br /&gt;
==== Tastendruck ====&lt;br /&gt;
In der mitgelieferten Standard.h gibt es den Befehl void Reset();. Er löst mit Hilfe des Watchdog-Timers einen Hardwarereset aus. Man kann jetzt z.&amp;amp;nbsp;B. auf einen bestimmten Tastendruck (-kombination) hin diesen Reset ausführen.&lt;br /&gt;
&lt;br /&gt;
==== RS232/USB ====&lt;br /&gt;
Alternativ kann ein entsprechender Befehl über die RS232 gesendet werden. Standardmäßig ist dies 0xFF ‚R‘.&lt;br /&gt;
&lt;br /&gt;
=== Einstellungen in der IDE ===&lt;br /&gt;
&lt;br /&gt;
Der Bootloader Support kann bei den Projekt-Eigenschaften eingestellt werden. Beim Brennen wird er dann automatisch benutzt.&lt;br /&gt;
&lt;br /&gt;
== ToDo ==&lt;br /&gt;
&lt;br /&gt;
=== Komfortables Stand-Alone Firmware-Update ===&lt;br /&gt;
&lt;br /&gt;
Basierend auf dem Code der IDE wird es im September noch ein Standalone-Programm für das Firmware-Update geben. Es wird auch ein entsprechendes Protokoll zur Versionskontrolle haben (die bisherige Soft- und viel wichtiger Hardwareversion wird überprüft). Eine Verschlüsselung der Firmware-Datei ist in Planung.&lt;br /&gt;
&lt;br /&gt;
=== Automatisches Erzeugen des Bootloaders ===&lt;br /&gt;
Sobald ich Zeit habe kommt in die IDE auch die Möglichkeit, die Anpassungen des Bootloaders von der IDE durchführen zu lassen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Integration von fastboot in avrdude  ===&lt;br /&gt;
Scheint zu laufen, wurde aber wegen diversen Änderungen in avrdude noch nicht integriert.&lt;br /&gt;
Eventuell erbarmt sich ja mal jemand :)&lt;br /&gt;
* [http://savannah.nongnu.org/patch/?7594 patch #7594 Support for Atmel serial UART-Bootloader &amp;quot;FastBoot&amp;quot;]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/73196#1789173 Patch von  Stefan G. (sgm)] &lt;br /&gt;
[[Kategorie:AVR-Programmer und -Bootloader|B]]&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_-_Die_genaue_Sekunde_/_RTC&amp;diff=78441</id>
		<title>AVR - Die genaue Sekunde / RTC</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_-_Die_genaue_Sekunde_/_RTC&amp;diff=78441"/>
		<updated>2013-09-07T11:37:09Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: /* Uhrentakt genau messen und digital korrigieren */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
Oftmals sieht man Projekte, bei denen ein externer RTC-Baustein (engl. &#039;&#039;&#039;R&#039;&#039;&#039;eal &#039;&#039;&#039;T&#039;&#039;&#039;ime &#039;&#039;&#039;C&#039;&#039;&#039;lock, Echtzeituhr; z.&amp;amp;nbsp;B. PCF8583 mit [[I2C]]-Anschluss [http://www-us.semiconductors.philips.com/acrobat/datasheets/PCF8583_5.pdf Datenblatt (PDF)]) angeschlossen ist, ohne dessen Vorteil wirklich zu nutzen.&lt;br /&gt;
&lt;br /&gt;
Die wichtigsten Vorteile einer externen RTC sind &lt;br /&gt;
# Die Zeitzählung läuft während eines Ausfalls der Hauptstromversorgung über eine kleine Stützbatterie bei geringem Strombedarf weiter.&lt;br /&gt;
# Es gibt hochgenaue RTCs, die man im Gegensatz zu Selbstbaulösungen nicht abgleichen muss.&lt;br /&gt;
# Der Strombedarf eines externen RTC ist in der Regel etwas niedriger als die RTC Funktion eines Prozessors. Als Vergleich diene ein DS1302(300nA@2V) zu einem Mega32(5uA@2.7V) als nicht ganz neuer Vertreter, bzw. ein Mega324P(500nA@1.8V) als moderner Vertreter. Dieser Vorteil kommt bei Datenschreibern (engl. data logger) zum Tragen, welche die meiste Zeit inaktiv im [[Sleep Mode]] sind.&lt;br /&gt;
&lt;br /&gt;
In allen anderen Fällen ist die zusätzliche Hardware nicht unbedingt nötig und man kann eine präzise Zeitbasis bequem mit dem Hauptquarz des Mikrokontrollers programmieren. Daraus ergeben sich sogar noch zusätzliche Vorteile, wie eine geringere Temperaturabhängigkeit und höhere Güte, die Quarze im MHz-Bereich gegenüber Quarzen im kHz-Bereich besitzen. Ich möchte hiermit die Angst vor dem bisschen Mathematik nehmen, welche zur Berechnung der Teilerfaktoren benötigt wird.&lt;br /&gt;
&lt;br /&gt;
==Lösung==&lt;br /&gt;
&lt;br /&gt;
Speziell für den AVR kommen Quarze im Bereich 1MHz bis 16MHz zum Einsatz, d.h. in einer Sekunde werden 1.000.000 bis 16.000.000 Zyklen durchlaufen (Zyklen pro Sekunde = Frequenz). Möchte man eine Sekunde messen, kann man somit die entsprechende Anzahl Zyklen von Null an hochzählen oder von dem entsprechenden Wert bis auf 0 runterzählen. Für das Zählen bietet sich im µC der Compare-Modus eines Timers an.&lt;br /&gt;
&lt;br /&gt;
Die obigen Zahlen lassen sich jedoch nicht in einer 16 Bit Variablen ausdrücken da sie zu gross sind und somit ist ein direktes Setzen des Compare-Wertes des Timers T1 im AVR nicht möglich. Deshalb unterteilt man die Quarzfrequenz in zwei Faktoren; der erste (Softwareteiler) bestimmt die Periode des Timers T1 und der zweite den Reloadwert eines Registers, welches im Timerinterrupt runtergezählt wird.&lt;br /&gt;
&lt;br /&gt;
==Beispiel== &lt;br /&gt;
&lt;br /&gt;
Im Beispiel AVR wird ein 11,0592-MHz-Quarz verwendet, was einem üblichen [[Baudratenquarz]] entspricht, d.h. damit können die UART-Standardbaudraten erzeugt werden.&lt;br /&gt;
&lt;br /&gt;
Der Softwareteiler wird mit 256 gewählt, d.h. 256 Timerinterrupts pro Sekunde, und kann somit mit nur einem einzigen Byte realisiert werden. Für größere Werte muß der Softwareteiler als int (2 Byte) deklariert werden. Bei kleineren Werten als 256 muss man beachten, dass der zweite Faktor immer noch in 2 Byte passt, um als Comparewert für den 16-Bit-Timer 1 verwendet werden zu können. &lt;br /&gt;
&lt;br /&gt;
Die Timerroutine wird in einer Sekunde Softwareteiler-Mal aufgerufen. Mit diesen 256 Hz ergibt sich eine Timerinterruptzeit von ca. 4ms, die auch sehr gut zum Entprellen von Tasten benutzt werden kann. Eine Entprellroutine kann also bequem in den Timerinterrupt mit eingefügt werden. Beachten muss man nur noch, dass das Nullsetzen des Timers erst einen Zyklus nach dem Comparematch erfolgt.&lt;br /&gt;
&lt;br /&gt;
==Berechnung==&lt;br /&gt;
&lt;br /&gt;
Die Berechnung des Comparewertes ist sehr einfach: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
Comparewert OCR1A = 11059200 / 256 - 1 = 43199, Rest 0. &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da haben wir ja noch mal Glück gehabt, es gibt keinen Rest bei der Division und die Sekunde ist exakt&lt;br /&gt;
256 * 43200 = 11059200 Zyklen lang.&amp;lt;br&amp;gt;&lt;br /&gt;
Theoretisch.&amp;lt;br&amp;gt;&lt;br /&gt;
Denn selbst wenn auf dem Quarz eine Frequenz von 11,0592 Mhz aufgedruckt ist, so schwingt er doch auf&lt;br /&gt;
einer etwas anderen Frequenz. Der Grund dafür sind Fertigungstoleranzen und natürlich die Tatsache, &lt;br /&gt;
dass die Frequenz eines Quarzes auch von der Temperatur abhängig ist. Es gilt also zunächst einmal&lt;br /&gt;
herauszufinden, auf welcher Frequenz der Quarz wirklich schwingt.&lt;br /&gt;
&lt;br /&gt;
Dazu wird eine Uhr programmiert und mit dem theoretischen Wert laufen gelassen. Nun habe ich die Uhr&lt;br /&gt;
einen Tag laufen lassen und festgestellt, dass sie 1,5 s nach geht (Dazu kann man beispielsweise die Tagesschau nutzen, welche jeden Tag um 20:00 (+einer konstanten Zeitverschiebung durch das Übertragungsmedium SAT,DVB-T, ...) beginnt und sogar eine Uhr dabei einblendet). D.h. die Quarzfrequenz beträgt in&lt;br /&gt;
Wirklichkeit: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
11059200 * (1 - 1,5 / 24 / 60 / 60) = 11059008 Hz. &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Ausführliche Rechnung:&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
(Zyklen in 24h - Zyklen Verspätung) / Sekunden pro 24h = korrekte Frequenz&lt;br /&gt;
((24 * 60 * 60 * 256 * 43200) - (1,5 * 256 * 43200)) / (24 * 60 * 60) = 11059008 Hz.&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also die ganze Rechnung nochmal: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
OCR1A = 11059008 / 256 - 1 = 43198, Rest 64. &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Nun haben wir einen Rest und es würden uns jede Sekunde 64 Zyklen fehlen. Das geht natürlich nicht. &lt;br /&gt;
&lt;br /&gt;
Deshalb wird jedesmal, wenn der Softwareteiler Null ist und die Sekunde weitergezählt wird, ein&lt;br /&gt;
anderer Comparewert geladen. Dieser ist dann um den Rest größer. Und beim nächsten Timerinterrupt&lt;br /&gt;
wird dann wieder der Comparewert geladen, der das Ergebnis der Division war. &lt;br /&gt;
&lt;br /&gt;
Es ergeben sich somit: &lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
255 * (43198 + 1) + 1 * (43198 + 64  + 1) = 11059008 Zyklen&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Exakt so, wie wir es wollten.&lt;br /&gt;
&lt;br /&gt;
==Das Programm== &lt;br /&gt;
&lt;br /&gt;
Nachfolgend nun das C-Programm. Da wir ja alle nicht gerne rechnen, lassen wir das einfach den C-Compiler erledigen. D.h. wir brauchen nur noch per Definition für XTAL den entsprechenden Wert eintragen und der Compiler rechnet alle nötigen Konstanten ganz alleine aus. &lt;br /&gt;
&lt;br /&gt;
So ein Compiler ist auch ziemlich faul, der merkt sofort, wenn die Operanden für eine Berechnung alles Konstanten sind. Und ehe er sich damit abquält, extra Code für diese Berechnungen zu erzeugen, rechnet er es lieber selber aus und fügt das Ergebnis direkt in den Code ein. &lt;br /&gt;
&lt;br /&gt;
Der Assembler kann auch 32-Bit Konstanten-Berechnungen ausführen. Allerdings muß man dann die entsprechenden Präprozessoroperationen benutzen. Man könnte auch eine Divisionsroutine aufrufen, aber dann würde ja echter Code erzeugt. &lt;br /&gt;
&lt;br /&gt;
===Beispiel in C===&lt;br /&gt;
&lt;br /&gt;
Wichtig: Ab Ver.1.4.0 haben sich Namen/Funktionen geändert: &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;There are currently two different styles present for naming the vectors. One form uses names starting with SIG_, followed by a relatively verbose but arbitrarily chosen name describing the interrupt vector. This has been the only available style in avr-libc up to version 1.2.x.&lt;br /&gt;
&lt;br /&gt;
Starting with avr-libc version 1.4.0, a second style of interrupt vector names has been added, where a short phrase for the vector description is followed by _vect. The short phrase matches the vector name as described in the datasheet of the respective device (and in Atmel&#039;s XML files), with spaces replaced by an underscore and other non-alphanumeric characters dropped. Using the suffix _vect is intented to improve portability to other C compilers available for the AVR that use a similar naming convention....&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quelle: http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/************************************************************************/&lt;br /&gt;
/*                                                                      */&lt;br /&gt;
/*          Precise 1 Second Timebase           */&lt;br /&gt;
/*                                                                      */&lt;br /&gt;
/*              Author: Peter Dannegger                                 */&lt;br /&gt;
/*                      danni@specs.de                                  */&lt;br /&gt;
/*                                                                      */&lt;br /&gt;
/************************************************************************/&lt;br /&gt;
// Target: Mega8, 2313&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/signal.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#ifndef OCR1A&lt;br /&gt;
#define OCR1A OCR1  // 2313 support&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#ifndef WGM12&lt;br /&gt;
#define WGM12 CTC1  // 2313 support&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#ifndef PINC&lt;br /&gt;
#define KEY_INPUT   PIND    // 2313&lt;br /&gt;
#else&lt;br /&gt;
#define KEY_INPUT   PINC    // Mega8&lt;br /&gt;
#endif&lt;br /&gt;
#define LED_DIR     DDRB&lt;br /&gt;
&lt;br /&gt;
//#define XTAL      11059201L   // nominal value&lt;br /&gt;
#define XTAL        11059008L   // after measuring deviation: 1.5s/d&lt;br /&gt;
&lt;br /&gt;
#define DEBOUNCE    256L        // debounce clock (256Hz = 4msec)&lt;br /&gt;
&lt;br /&gt;
#define uchar unsigned char&lt;br /&gt;
#define uint unsigned int&lt;br /&gt;
&lt;br /&gt;
uchar prescaler;&lt;br /&gt;
uchar volatile second;          // count seconds&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
SIGNAL (SIG_OUTPUT_COMPARE1A)&lt;br /&gt;
{&lt;br /&gt;
/************************************************************************/&lt;br /&gt;
/*          Insert Key Debouncing Here          */&lt;br /&gt;
/************************************************************************/&lt;br /&gt;
&lt;br /&gt;
#if XTAL % DEBOUNCE                     // bei rest&lt;br /&gt;
  OCR1A = XTAL / DEBOUNCE - 1;      // compare DEBOUNCE - 1 times&lt;br /&gt;
#endif&lt;br /&gt;
  if( --prescaler == 0 ){&lt;br /&gt;
    prescaler = (uchar)DEBOUNCE;&lt;br /&gt;
    second++;               // exact one second over&lt;br /&gt;
#if XTAL % DEBOUNCE         // handle remainder&lt;br /&gt;
    OCR1A = XTAL / DEBOUNCE + XTAL % DEBOUNCE - 1; // compare once per second&lt;br /&gt;
#endif&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main( void )&lt;br /&gt;
{&lt;br /&gt;
  LED_DIR = 0xFF;&lt;br /&gt;
  while( KEY_INPUT &amp;amp; 1 );               // start with key 0 pressed&lt;br /&gt;
&lt;br /&gt;
  TCCR1B = (1&amp;lt;&amp;lt;WGM12) | (1&amp;lt;&amp;lt;CS10);      // divide by 1&lt;br /&gt;
                    // clear on compare&lt;br /&gt;
  OCR1A = XTAL / DEBOUNCE - 1;          // Output Compare Register&lt;br /&gt;
  TCNT1 = 0;                            // Timmer startet mit 0&lt;br /&gt;
  second = 0;&lt;br /&gt;
  prescaler = (uchar)DEBOUNCE;          //software teiler&lt;br /&gt;
&lt;br /&gt;
  TIMSK = 1&amp;lt;&amp;lt;OCIE1A;                    // beim Vergleichswertes Compare Match                    &lt;br /&gt;
                                        // Interrupt (SIG_OUTPUT_COMPARE1A)&lt;br /&gt;
  sei();&lt;br /&gt;
&lt;br /&gt;
  for(;;){&lt;br /&gt;
    if( second == 60 )&lt;br /&gt;
      second = 0;&lt;br /&gt;
    PORTB = second;         // display second (binary)&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Beispiel in Assembler===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;avrasm&amp;quot;&amp;gt; &lt;br /&gt;
;************************************************************************/&lt;br /&gt;
;*                                                                      */&lt;br /&gt;
;*          Precise 1 Second Timebase           */&lt;br /&gt;
;*                                                                      */&lt;br /&gt;
;*              Author: Peter Dannegger                                 */&lt;br /&gt;
;*                      danni@specs.de                                  */&lt;br /&gt;
;*                                                                      */&lt;br /&gt;
;************************************************************************/&lt;br /&gt;
.nolist&lt;br /&gt;
.include &amp;quot;m8def.inc&amp;quot;&lt;br /&gt;
&lt;br /&gt;
.equ    xtal      = 11059008&lt;br /&gt;
.equ    debounce  = 256&lt;br /&gt;
.equ    remainder = xtal - xtal / debounce * debounce&lt;br /&gt;
&lt;br /&gt;
.def    isreg     = r15&lt;br /&gt;
.def    wr0       = r16&lt;br /&gt;
.def    iwr0      = r17&lt;br /&gt;
.def    prescaler = r18&lt;br /&gt;
.def    second    = r19&lt;br /&gt;
&lt;br /&gt;
.list&lt;br /&gt;
    rjmp    init&lt;br /&gt;
.org    OC1Aaddr&lt;br /&gt;
    rjmp    OC1Aint&lt;br /&gt;
;-------------------------------------------------------------------------&lt;br /&gt;
OC1Aint:&lt;br /&gt;
    in  isreg, sreg&lt;br /&gt;
;************************************************************************/&lt;br /&gt;
;*          Insert Key Debouncing Here          */&lt;br /&gt;
;************************************************************************/&lt;br /&gt;
&lt;br /&gt;
    ldi iwr0, high( xtal / debounce - 1 )&lt;br /&gt;
    out ocr1ah, iwr0&lt;br /&gt;
    ldi iwr0, low( xtal / debounce - 1 )&lt;br /&gt;
    out ocr1al, iwr0&lt;br /&gt;
&lt;br /&gt;
    dec prescaler&lt;br /&gt;
    brne    _oci1&lt;br /&gt;
&lt;br /&gt;
    ldi prescaler, debounce&lt;br /&gt;
    inc second&lt;br /&gt;
&lt;br /&gt;
    ldi iwr0, high( xtal / debounce + remainder - 1 )&lt;br /&gt;
    out ocr1ah, iwr0&lt;br /&gt;
    ldi iwr0, low( xtal / debounce + remainder - 1 )&lt;br /&gt;
    out ocr1al, iwr0&lt;br /&gt;
_oci1:&lt;br /&gt;
    out sreg, isreg&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;
    sbic    pinc, 0&lt;br /&gt;
    rjmp    init&lt;br /&gt;
&lt;br /&gt;
    ldi wr0, high( ramend )&lt;br /&gt;
    out sph, wr0&lt;br /&gt;
    ldi wr0, low( ramend )&lt;br /&gt;
    out spl, wr0&lt;br /&gt;
&lt;br /&gt;
    ldi wr0, 1&amp;lt;&amp;lt;WGM12^1&amp;lt;&amp;lt;CS10&lt;br /&gt;
    out TCCR1B, wr0&lt;br /&gt;
&lt;br /&gt;
    ldi wr0, high( xtal / debounce - 1 )&lt;br /&gt;
    out ocr1ah, wr0&lt;br /&gt;
    ldi wr0, low( xtal / debounce - 1 )&lt;br /&gt;
    out ocr1al, wr0&lt;br /&gt;
    out tcnt1l, wr0&lt;br /&gt;
    ldi prescaler, debounce&lt;br /&gt;
&lt;br /&gt;
    ldi wr0, 1&amp;lt;&amp;lt;OCIE1A&lt;br /&gt;
    out TIMSK, wr0&lt;br /&gt;
    sei&lt;br /&gt;
main:&lt;br /&gt;
    ldi second, 0&lt;br /&gt;
_mai1:&lt;br /&gt;
    cpi second, 60&lt;br /&gt;
    breq    main&lt;br /&gt;
    out PORTB, second&lt;br /&gt;
    rjmp    _mai1&lt;br /&gt;
;------------------------------------&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Verbesserte Version mit durchlaufendem Hardwarezähler===&lt;br /&gt;
&lt;br /&gt;
Hier sind trotzdem kleine Verbesserungsvorschläge.&lt;br /&gt;
&lt;br /&gt;
Wird im Timer die Option &amp;quot;Clear On Compare Match&amp;quot; verwendet, so verliert man den Overflow Interrupt. Oder möchte man nebenher noch eine Zeit mit dem Capture Interrupt messen, so benötigt man einen durchlaufenden Timer. Um dies zu erreichen, wird OCR1A nicht fest eingestellt, sondern bei jedem Aufruf um den gleichen Wert erhöht.&lt;br /&gt;
&lt;br /&gt;
In Peters Code wurde der Rest auf einmal abgearbeitet. Damit erspart man sich bei jedem Interrupt einen Vergleich und die Verarbeitungszeit verkürzt sich in seinem Code. Der Unterschied zwischen kurzem und langem Interrupt ist hier der Rest. Bei den geänderten Codeschnipseln wird der Rest gleichmäßiger abgearbeitet. Der Unterschied zwischen kurzem und langem Interrupt beträgt 1 Takt.&lt;br /&gt;
&lt;br /&gt;
ungetesteter Code für den durchlaufenden Timer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
SIGNAL (SIG_OUTPUT_COMPARE1A) {&lt;br /&gt;
/************************************************************************/&lt;br /&gt;
/*      Insert Key Debouncing Here      */&lt;br /&gt;
/************************************************************************/&lt;br /&gt;
&lt;br /&gt;
  if( --prescaler == 0 ){ &lt;br /&gt;
    prescaler = (uchar) DEBOUNCE;&lt;br /&gt;
    second++;      // exact one second over  &lt;br /&gt;
  }  &lt;br /&gt;
#if XTAL % DEBOUNCE&lt;br /&gt;
  if (prescaler &amp;lt;= XTAL % DEBOUNCE)&lt;br /&gt;
    OCR1A += XTAL / DEBOUNCE +1;   /* um 1 Takt längere Periode um den Rest abzutragen */&lt;br /&gt;
  else&lt;br /&gt;
#endif&lt;br /&gt;
    OCR1A += XTAL / DEBOUNCE;   /* kurze Periode */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Durchlaufender Hardwarezähler und fortlaufende Addition===&lt;br /&gt;
&lt;br /&gt;
Gänzlich ohne Hin- und Hertogglen eines Bits kommt man aus, wenn irgendein Timer mit einer Überlauf-Interruptfrequenz &amp;gt; 1Hz arbeitet. Dann kann die ISR eine 32-bit-Konstante auf einen 32-bit-Akkumulator addieren; bei Überlauf ist eine Sekunde vergangen. Zugegeben, es gibt &amp;quot;lange&amp;quot; und &amp;quot;kurze&amp;quot; Sekunden, aber der Fehler summiert sich nicht, und der Code ist sehr einfach.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel:&lt;br /&gt;
&lt;br /&gt;
Es gibt ein Programm gettick(), das einen Wert holt. Dieser Wert wird von Zeit zu Zeit von der Hardware (Beispiel AVR: der Timer) oder dem Betriebssystem (Beispiel Linux: gettick ruft getmsec, getmsec ruft gettimeofday)&lt;br /&gt;
&lt;br /&gt;
Dieser aufgerufene Wert sollte pro Sekunde um TICKPERSEC erhöht werden, was aber mit einer gewissen Ungenauigkeit geschieht.&lt;br /&gt;
&lt;br /&gt;
Die Laufzeitkorrektur wird dadurch ausgeführt, dass der von gettick() zurückgegebene Wert mit einem Faktor TFAK multipliziert wird. Der Faktor sollte so gewählt werden, dass:&lt;br /&gt;
&lt;br /&gt;
* Das Ergebnis actual_value immer in 32 Bit hineinpasst.&lt;br /&gt;
* Die Multiplikation durch Schiebeopertionen ersetzt werden kann, weil der Faktor eine 2-er-Potenz ist. (Das erledigt avr-gcc)&lt;br /&gt;
&lt;br /&gt;
Immer wenn tsdaytim_calibrated() erkennt, dass eine Sekunde vergangen, wird last_value um die Zahl onesecond erhöht.&lt;br /&gt;
&lt;br /&gt;
Der Zahlenwert onsecond wird mit TICKPERSEC*TFAK initalisiert und kann angezeigt oder neu eingegeben werden (Die Bedienung der seriellen Schnittstelle hierfür ist in diesem Beispiel nicht enthalten).&lt;br /&gt;
&lt;br /&gt;
Wenn festgestellt wird, dass die Uhr pro Zeit (P) um (E) zu schnell geht, dann kann der Wert onsecond korrigiert werden.&lt;br /&gt;
&lt;br /&gt;
c = d *  (P+E)/P&lt;br /&gt;
Beispiel Pro 7 Tage 120 Sekunden zu viel:&lt;br /&gt;
&lt;br /&gt;
7 Tage = 7*86400= 604800 sekunden&lt;br /&gt;
c = 992000000 * (604800+120)/604800=991803175&lt;br /&gt;
Dann wird die Uhr genauer gehen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;c&amp;quot;&amp;gt;&lt;br /&gt;
/****************************************************************/&lt;br /&gt;
/* File home/cc/qq/danclock.cpp                                 */&lt;br /&gt;
/*          Precise 1 Second Timebase                           */&lt;br /&gt;
/*                                                              */&lt;br /&gt;
/*      Author: Peter Dannegger / Hjherbert                     */&lt;br /&gt;
/*          danni@specs.de                                      */&lt;br /&gt;
/*                                                              */&lt;br /&gt;
/****************************************************************/&lt;br /&gt;
// Target: atmega8, (2313?)&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
// #include &amp;lt;avr/signal.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#ifndef OCR1A&lt;br /&gt;
#define OCR1A OCR1  // 2313 support&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#ifndef WGM12&lt;br /&gt;
#define WGM12 CTC1  // 2313 support&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#ifndef PINC&lt;br /&gt;
#define KEY_INPUT   PIND    // 2313&lt;br /&gt;
#else&lt;br /&gt;
#define KEY_INPUT   PINC    // Mega8&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//#define F_CPU     11059201L   // nominal value&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define DIVISOR 256&lt;br /&gt;
&lt;br /&gt;
#define TICKPERSEC  (F_CPU/DIVISOR)&lt;br /&gt;
&lt;br /&gt;
uint8_t volatile second;            // count seconds&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// TFAK ? TICKPERSEC must not exceed 2^32&lt;br /&gt;
#define TM (0x7FFFFFFFUL/2/TICKPERSEC)  // max of TFAK&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define TFAK ( (  (TM&amp;gt;&amp;gt;1) | (TM&amp;gt;&amp;gt;2) | (TM&amp;gt;&amp;gt;3)  | (TM&amp;gt;&amp;gt;4)  | (TM&amp;gt;&amp;gt;5)  | (TM&amp;gt;&amp;gt;6)  | (TM&amp;gt;&amp;gt;7) \&lt;br /&gt;
                | (TM&amp;gt;&amp;gt;8) | (TM&amp;gt;&amp;gt;9) | (TM&amp;gt;&amp;gt;10) | (TM&amp;gt;&amp;gt;11)  | (TM&amp;gt;&amp;gt;12)  | (TM&amp;gt;&amp;gt;13)  | (TM&amp;gt;&amp;gt;14)  | (TM&amp;gt;&amp;gt;15) \&lt;br /&gt;
                | (TM&amp;gt;&amp;gt;16) | (TM&amp;gt;&amp;gt;17) | (TM&amp;gt;&amp;gt;18) | (TM&amp;gt;&amp;gt;19)  | (TM&amp;gt;&amp;gt;20)  | (TM&amp;gt;&amp;gt;21)  | (TM&amp;gt;&amp;gt;22)  | (TM&amp;gt;&amp;gt;23) \&lt;br /&gt;
                | (TM&amp;gt;&amp;gt;24) | (TM&amp;gt;&amp;gt;25) | (TM&amp;gt;&amp;gt;26) | (TM&amp;gt;&amp;gt;27)  | (TM&amp;gt;&amp;gt;28)  | (TM&amp;gt;&amp;gt;29)  | (TM&amp;gt;&amp;gt;30)  | (TM&amp;gt;&amp;gt;31) \&lt;br /&gt;
               ) + 1 )&lt;br /&gt;
// TFAK is a power the biggest power of two which is less than TM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
uint32_t onesecond = 1*TICKPERSEC*TFAK ;    // correct this value if see the clock is late / too fast&lt;br /&gt;
uint32_t last_value ;&lt;br /&gt;
uint32_t ticks ;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
SIGNAL (SIG_OUTPUT_COMPARE1A)&lt;br /&gt;
{&lt;br /&gt;
    ++ticks ;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
uint32_t gettick( void )&lt;br /&gt;
{&lt;br /&gt;
    uint32_t l ;&lt;br /&gt;
    cli();&lt;br /&gt;
    l = ticks ;&lt;br /&gt;
    sei();&lt;br /&gt;
    return l ;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void tsdaytim_calibrated(void)&lt;br /&gt;
// Keep the time-of-the-day actual&lt;br /&gt;
// Add a second, if a second if gone&lt;br /&gt;
{&lt;br /&gt;
    uint32_t actual_value ;         // gettick() multiplied by factor 2^n&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    actual_value = gettick() * TFAK ;   // because TFAK is a power of two&lt;br /&gt;
                                        // The compiler will create some shift commands&lt;br /&gt;
&lt;br /&gt;
    if ( actual_value - last_value &amp;gt; onesecond )&lt;br /&gt;
    {                           // once per second&lt;br /&gt;
        if ( ++second &amp;gt;= 60 )&lt;br /&gt;
        {&lt;br /&gt;
            second = 0 ;&lt;br /&gt;
        }&lt;br /&gt;
        last_value += onesecond ;   // One second more&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main( void )&lt;br /&gt;
{&lt;br /&gt;
    DDRB = 0xFF;&lt;br /&gt;
    while( KEY_INPUT &amp;amp; 1 );         // start with key 0 pressed&lt;br /&gt;
&lt;br /&gt;
    TCCR1B = 1&amp;lt;&amp;lt;WGM12^1&amp;lt;&amp;lt;CS10;      // divide by 1&lt;br /&gt;
                                    // clear on compare&lt;br /&gt;
    OCR1A = DIVISOR ;               // Output Compare Register&lt;br /&gt;
    TCNT1 = 0;                      // Timer start value&lt;br /&gt;
    second = 0;&lt;br /&gt;
&lt;br /&gt;
    TIMSK = 1&amp;lt;&amp;lt;OCIE1A;              // beim Vergleichswertes Compare Match&lt;br /&gt;
                                    // Interrupt (SIG_OUTPUT_COMPARE1A)&lt;br /&gt;
    sei();&lt;br /&gt;
    last_value = gettick() * TFAK ;&lt;br /&gt;
    for(;;)&lt;br /&gt;
    {&lt;br /&gt;
        tsdaytim_calibrated();&lt;br /&gt;
        PORTB = second;             // display second (binary)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Echtzeituhr mit Uhrenquarz ==&lt;br /&gt;
&lt;br /&gt;
=== RTC mit wenig Stromverbrauch ===&lt;br /&gt;
&lt;br /&gt;
Das vorgestellte Verfahren ist leider nicht direkt anwendbar, wenn man eine RTC mit einem 32,768 KHz Uhrenquarz realisieren möchte. Dieser Weg ist dann notwendig, wenn der Controller [[Ultra low power | batteriebetrieben]] sehr lange laufen soll und durch Verwendung des [[Sleep Mode]] Strom gespart wird.&lt;br /&gt;
&lt;br /&gt;
=== Begrenzung der Auflösung ===&lt;br /&gt;
&lt;br /&gt;
Wo liegt das Problem? Das obige Verfahren nutzt recht hochfrequente Quarze mit 1 MHz und mehr. Wenn man die Frequenz eines Quarzes von 1 MHz = 1.000.000 Hz mit einer [[Auflösung und Genauigkeit| Auflösung]] von 1 Hz angibt, entspricht das einem maximalen Fehler von 1/1.000.000 oder 1ppm (engl. parts per million, millionstel Teil). Das ist sehr wenig. Eine RTC mit einem Fehler von 1ppm hat eine Gangabweichung von 86,4ms pro Tag, oder 2,5s pro Monat. Das ist ein sehr guter Wert. Wenn ich nun aber die Frequenz 32768 Hz mit 1 Hz Auflösung angebe, ist das schlimmstenfalls ein Fehler von 1/32768 = 30,5ppm, was einer Abweichung von 2,5s pro Tag und 75s pro Monat entspricht!&lt;br /&gt;
&lt;br /&gt;
=== Uhrentakt genau messen und digital korrigieren ===&lt;br /&gt;
&lt;br /&gt;
Wie kann man das Problem lösen? Die AVRs können im [[Sleep Mode]] den Uhrenquarz nur am Timer 2 betreiben, welcher ein 8 Bit Timer ist. D.H. ein Überlauf passiert alle 256 Takte, sprich 7,8125ms (=128 Hz). Man kann auch einen Prescaler verwenden, welcher das Problem aber nicht löst.&lt;br /&gt;
&lt;br /&gt;
Wie bereits festgestellt, müssen wir die Frequenz des 32768Hz Uhrenquarzes genauer messen und darstellen. Wir wollen hier annehmen, dass wir die Frequenz auf 0,001Hz = 1mHz (Millihertz) auflösen, ein guter Frequenzzähler kann das problemlos und ist auch so [[Auflösung und Genauigkeit|&#039;&#039;&#039;genau&#039;&#039;&#039;]]. Wir können beispielsweise feststellen, dass ein Quarz mit 32768,423Hz schwingt, das entspricht einem Fehler von &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;F_r=(\frac{f_{ist}}{f_{soll}} -1 )\cdot 10^6=(\frac{32768,423}{32768} -1 )\cdot 10^6=12,9ppm&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dabei ist zu beachten, daß diese Messung &#039;&#039;&#039;nicht&#039;&#039;&#039; direkt am Quarz erfolgen darf, auch nicht mit kapazitätsarmen 10:1 Tastköpfen! Denn so ein Quarz wird von kleinsten Kapazitäten im Bereich von weniger als ein pF messbar verstimmt. Darum muss man in so einem Fall den Uhrentakt auf ein anderes IO-Pin ausgeben und dort messen. Beim [[MSP430]] ist das einfach, man kann ACLK auf ein Pin direkt ausgeben. Der [[AVR]] kann das leider nicht. Hier muss man zu einem Trick greifen. Man benutzt die Output Compare Funktion, um mit Timer 2 einen 128 Hz Takt zu erzeugen. Dieser ist fest mit dem Uhrentakt verbunden und kann anstellte dessen gemessen werden, ohne den Quarz zu verstimmen. Die Messung ergibt in diesem Fall eine Frequenz von 128,00165 Hz.&lt;br /&gt;
&lt;br /&gt;
OK, jetzt haben wir den Takt gemessen, wir wissen, daß pro Sekunde 128 Timerüberläufe passieren (Prescaler =1). Wir wissen, dass unser Quarz pro Sekunde um 0,423 Takte zu schnell ist. Wir können aber keine halben Takte mehr oder weniger zählen? Doch! Mit [[Festkommaarithmetik]]! Denn nach 1000s ist unser Quarz um 423 Takte zu weit gelaufen und muss um diese Anzahl zurückgestellt werden. Also könnte man im ersten Ansatz nach 1000 Sekunden den Timer 2 um diesen Betrag korrigieren. Das Problem dabei ist nur, dass der Zähler nur 8 Bit breit ist. Ein Addieren oder Subtrahieren von 423 würde mehrfache Überläufe verursachen, welche programmtechnisch nur schwer zu handhaben wären. Also muss eine etwas bessere Methode her.&lt;br /&gt;
&lt;br /&gt;
=== Bresenham für RTCs ===&lt;br /&gt;
&lt;br /&gt;
Wenn man sich die Idee der [[Festkommaarithmetik]] mal eine Weile durch den Kopf gehen lässt, kommt man vielleicht auf folgende Idee. Der Frequenzfehler beträgt in unserem Beispiel 0,423 Hz, also Takte pro Sekunde. Oder aber 423 Tausendstel Takte pro Sekunde. Nach drei Sekunden sind es schon 1,269 Takte oder 1269 Tausendstel Takte. Moment! &#039;&#039;&#039;Einen&#039;&#039;&#039; Takt können wir korrigieren, indem wir den Zähler um 1 Takt zurück setzen. Den Restfehler von 269 Tausendstel merken wir uns und akkumulieren weiter. Wenn dann wieder die 1000er Marke überschritten wird machen wir das Gleiche. Analog dazu natürlich auch bei negativem Vorzeichen, sprich wenn der Quarz zu langsam schwingt wird er um einen Takt vorgestellt. É Voilà! Dieses Verfahren ist sehr ähnlich zum [http://de.wikipedia.org/wiki/Bresenham-Algorithmus Bresenham-Algorithmus] zum Zeichnen von Linien auf Computermonitoren.&lt;br /&gt;
&lt;br /&gt;
=== Beispielprogramm ===&lt;br /&gt;
&lt;br /&gt;
Das folgende Beispiel stellt eine RTC mit sehr niedrigem Stromverbrauch zur Verfügung. Laut Datenblatt beträgt die Stromaufnahme nur ca. 6µA bei 3V Versorgungsspannung, besser als einige kommerzielle RTCs! Möglich macht das die Nutzung des Power Save [[Sleep Mode]]s. Die Frequenz kann auf &amp;lt;math&amp;gt;10^{-5}&amp;lt;/math&amp;gt; Hz genau abgeglichen werden, was in diesem Fall bei einer Messfrequenz von 128Hz einer Auflösung von 0,078ppm entspricht. Das bedeutet eine Abweichung von 6,7ms pro Tag, 0,2s pro Monat oder 2,46s pro Jahr!&lt;br /&gt;
&lt;br /&gt;
Die Abweichung des Quarzes wird in einer vorzeichenbehafteten 16 Bit Variable in der Einheit &amp;lt;math&amp;gt;10^{-3}&amp;lt;/math&amp;gt; Hz gespeichert. D.h. es kann ein Frequenzfehler von +/- 32,768 Hz korrigiert werden, das sind 1000ppm! Normale Quarze haben Abweichungen von max. 100ppm, meist viel weniger. Jede Sekunde wird der Frequenzfehler neu berechnet und in den darauffolgenden 128 Interrupts ggf. mehrfach korrigiert. Wichtig ist dabei, dass die Korrektur wirklich ganz am Anfang der ISR steht, weil hier das Timing wirklich kritisch ist. Denn innerhalb eines Uhrenquarztaktes von ~30µs muss der Timer 2 neu beschrieben werden. Bei 1 MHz RC-Oszillatortakt sind das nur 30 Takte, wovon 6 zum Aufwachen und 4 zum Anspringen der ISR benötigt werden. Dazu kommen noch das Sichern einiger Register am Anfang der ISR, was man im C nicht direkt sieht. Sicherheitshalber sollte man auch einen höheren Takt einstellen, z.&amp;amp;nbsp;B. 2 MHz, dann ist das Timing wesentlich entspannter.&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;
*&lt;br /&gt;
* Stromsparende Echtzeituhr mit 32768Hz Uhrenquarz&lt;br /&gt;
*&lt;br /&gt;
* ATmega88 mit internem 2 MHz Oszillator + 32,768 kHz Quarz&lt;br /&gt;
*&lt;br /&gt;
* Fuses bleiben auf Standardeistellungen&lt;br /&gt;
* LOW Fuse Byte = 0x62&lt;br /&gt;
* HIGH Fuse Byte = 0xDF&lt;br /&gt;
* EXT Fuse Byte = 0xF9&lt;br /&gt;
*&lt;br /&gt;
* LED mit 1K Vorwiderstand an PB5&lt;br /&gt;
* Kalibriertaktausgang an PB3&lt;br /&gt;
************************************************************************&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define F_CPU 2000000L          // Systemtakt in Hz&lt;br /&gt;
#define F_CAL 12800000L         // gemessener Kalibriertakt in 10^-5 Hz&lt;br /&gt;
                                // Endung L ist wichtig!&lt;br /&gt;
&lt;br /&gt;
#define LED_TOGGLE PORTB ^= (1&amp;lt;&amp;lt;PB5);&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/eeprom.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// EEPROM Daten&lt;br /&gt;
&lt;br /&gt;
int16_t ee_rtc_cal EEMEM = (F_CAL-12800000)*256/100;        // Kalibrierung für RTC, Frequenzfehler in 1/1000 Hz&lt;br /&gt;
&lt;br /&gt;
// globale Variablen&lt;br /&gt;
&lt;br /&gt;
// beidseitiger Zugriff durch ISR und Hauptprogramm&lt;br /&gt;
&lt;br /&gt;
volatile uint32_t time;             // 24h Zeitstempel, 1s Auflösung&lt;br /&gt;
volatile int16_t rtc_cal;           // Kalibrierung des 32K Quarzes&lt;br /&gt;
volatile uint8_t flag_1s;           // Flag für 1s Intervall&lt;br /&gt;
&lt;br /&gt;
void long_delay(uint16_t ms) {&lt;br /&gt;
    for (; ms&amp;gt;0; ms--) _delay_ms(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main (void) {&lt;br /&gt;
&lt;br /&gt;
// Clock divider auf /4&lt;br /&gt;
&lt;br /&gt;
    CLKPR = 0x80;       // update  enable&lt;br /&gt;
    CLKPR = 2;          // Prescaler /4&lt;br /&gt;
&lt;br /&gt;
// IO konfigurieren&lt;br /&gt;
&lt;br /&gt;
    DDRB  = (1&amp;lt;&amp;lt;PB3) | (1&amp;lt;&amp;lt;PB5);&lt;br /&gt;
    PORTB = ~((1&amp;lt;&amp;lt;PB3) | (1&amp;lt;&amp;lt;PB5)); // Pull ups &lt;br /&gt;
    PORTC = 0xFF;       &lt;br /&gt;
    PORTD = 0xFF;&lt;br /&gt;
&lt;br /&gt;
// Analogcomparator ausschalten&lt;br /&gt;
&lt;br /&gt;
    ACSR = 0x80;&lt;br /&gt;
&lt;br /&gt;
// Timer2 konfigurieren&lt;br /&gt;
&lt;br /&gt;
    ASSR   = (1&amp;lt;&amp;lt; AS2);             // Timer2 asynchron takten&lt;br /&gt;
    long_delay(1000);               // Einschwingzeit des 32kHz Quarzes&lt;br /&gt;
    TCCR2A = (1&amp;lt;&amp;lt;COM2A1) | (1&amp;lt;&amp;lt;WGM21) | (1&amp;lt;&amp;lt;WGM20); // Fast PWM, non inverted&lt;br /&gt;
    TCCR2B = 1;                     // Vorteiler 1 -&amp;gt; 7,8ms Überlaufperiode&lt;br /&gt;
    OCR2A  = 128;                   // PWM, Tastverhältnis 50%&lt;br /&gt;
    while((ASSR &amp;amp; (1&amp;lt;&amp;lt; TCR2BUB)));  // Warte auf das Ende des Zugriffs&lt;br /&gt;
    TIFR2  &amp;amp;= ~(1&amp;lt;&amp;lt;TOV2);           // Interrupts löschen&lt;br /&gt;
    TIMSK2 |= (1&amp;lt;&amp;lt;TOIE2);           // Timer overflow Interrupt freischalten&lt;br /&gt;
&lt;br /&gt;
// EEPROM Werte auslesen&lt;br /&gt;
&lt;br /&gt;
    rtc_cal= eeprom_read_word(&amp;amp;ee_rtc_cal);&lt;br /&gt;
&lt;br /&gt;
// Interrupts freigeben&lt;br /&gt;
&lt;br /&gt;
    sei();&lt;br /&gt;
&lt;br /&gt;
// Endlose Hauptschleife&lt;br /&gt;
&lt;br /&gt;
    while(1) {&lt;br /&gt;
&lt;br /&gt;
        while((ASSR &amp;amp; (1&amp;lt;&amp;lt; OCR2AUB)));  // Warte auf das Ende des Zugriffs&lt;br /&gt;
        set_sleep_mode(SLEEP_MODE_PWR_SAVE);&lt;br /&gt;
        sleep_mode();                   // in den Schlafmodus wechseln&lt;br /&gt;
&lt;br /&gt;
        // hier wachen wir wieder auf, nach Ausführung des 7,8ms Timerinterupt&lt;br /&gt;
&lt;br /&gt;
        if (flag_1s) {  &lt;br /&gt;
            flag_1s =0;&lt;br /&gt;
            LED_TOGGLE                      // Test&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Timer2 overflow Interrupt&lt;br /&gt;
&lt;br /&gt;
ISR(TIMER2_OVF_vect) {&lt;br /&gt;
    static uint8_t ticks;               // Hilfsvariable für Messintervall&lt;br /&gt;
    static int16_t time_error;          // RTC Fehlerkompensation&lt;br /&gt;
&lt;br /&gt;
    // Zeitkritische Dinge, welche am Anfang der ISR stehen müssen!&lt;br /&gt;
&lt;br /&gt;
    OCR2A=128;                          // Dummy-Write zur Sicherung des Timings&lt;br /&gt;
                                        // von Timer 2 im asynchronen Modus &lt;br /&gt;
&lt;br /&gt;
    // RTC Fehler korrigieren&lt;br /&gt;
&lt;br /&gt;
    if (time_error&amp;gt;999) {               // RTC zu schnell&lt;br /&gt;
        TCNT2 = 2;                      // Zähler einen Schritt zurück setzen (2 Takte Verzögerung!)&lt;br /&gt;
        time_error -= 1000;&lt;br /&gt;
    } else if (time_error&amp;lt;-999) {       // RTC zu langsam&lt;br /&gt;
        TCNT2 = 4;                      // Zähler einen Schritt vor setzen (2 Takte Verzögerung!)&lt;br /&gt;
        time_error += 1000;     &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ab hier ist es nicht mehr zeitkritisch&lt;br /&gt;
&lt;br /&gt;
    // Echtzeituhr&lt;br /&gt;
    ticks++;                            // 1/128tel Sekunde&lt;br /&gt;
    if (ticks==128) {                   // Sekundenintervall&lt;br /&gt;
        time_error += rtc_cal;          // RTC Fehler akkumulieren&lt;br /&gt;
&lt;br /&gt;
        // 24h Timer&lt;br /&gt;
        time++;&lt;br /&gt;
        if (time==86400) time=0;        // 24h Überlauf&lt;br /&gt;
&lt;br /&gt;
        ticks=0;&lt;br /&gt;
        flag_1s =1;                     // setzte Flag für 1s Verarbeitung in main Endlosschleife&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Weitere Verbesserungen ===&lt;br /&gt;
&lt;br /&gt;
Der Algorithmus ermöglicht eine sehr hochauflösende Kalibrierung der RTC. Allerdings heisst das leider noch lange nicht, daß die RTC dann auch wirklich so genau ist. Denn diese Kalibrierung gilt nur für eine exakte Temperatur! Auch ein Quarz hat eine Temperaturabhängigkeit der Schwingfrequenz. Wenn man nun eine sehr genaue RTC bauen möchte, welche über einen grossen Temperaturbereich genau läuft, muss man periodisch die Temperatur messen und in die Kalibrierung einbeziehen. Einen typischen Temperaturverlauf des Frequenzfehlers zeigt das folgende Bild.&lt;br /&gt;
&lt;br /&gt;
[[bild:rtc_tk.gif|thumb|260px|left|Temperaturgang eines Uhrenquarzes]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Weiterhin kann man natürlich die Kalibrierung ohne erneutes Kompilieren des Quelltextets vornehmen, indem man den Kalibrierwert per [[UART]] oder [[I2C]] an den AVR sendet und im [[Speicher#EEPROM | EEPROM]] speichert.&lt;br /&gt;
&lt;br /&gt;
Kernpunkt der Kalibrierung ist natürlich die Messung der realen Quarzfrequenz. Die oben beschriebene Methode per Tagesschau und 1 Tag warten ist sehr zeitaufwändig und hat eine begrenzte Genauigkeit von ca. 1/2 Sekunde, das entspricht 5,8ppm. Hier muss zwangsläufig ein guter Frequenzzähler her. Da dieser nicht jedem Hobbybastler zur Verfügung steht, muss man sich in Lehrwerkstätten, Universitäten oder Firmen im Elektronikbereich umsehen und nachfragen, ob man einen Frequenzzähler vor Ort kurze Zeit nutzen kann.&lt;br /&gt;
&lt;br /&gt;
Einige GPS-Module bieten auch einen hochgenauen 1PPS (Pulse Per Second) Ausgang an, der sich für den Abgleich gut heranziehen lässt. Auch das Sekunden-Zeichen eines DCF77-Funkuhr-Moduls ist sehr genau und kann als Referenz dienen.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
*[http://www.mikrocontroller.net/articles/Uhr Implementierung einer Uhr mit Siebensegmentausgabe auf einem AVR ATTiny2313]&lt;br /&gt;
*[http://www.mikrocontroller.net/topic/165249 Uhr mit genauer Sekunde BASCOM]&lt;br /&gt;
*[https://www.mikrocontroller.net/topic/298306 Stromsparende und günstige Zeitmessung: ATtiny mit Uhrenquarz getaktet]&lt;br /&gt;
&lt;br /&gt;
[[Category:AVR-Projekte]]&lt;br /&gt;
[[Category:Timer und Uhren]]&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=PLL&amp;diff=68833</id>
		<title>PLL</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=PLL&amp;diff=68833"/>
		<updated>2012-10-24T15:27:06Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: /* Software */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Eine &#039;&#039;&#039;PLL&#039;&#039;&#039; (engl.: phase locked loop) ist ein Regelkreis in Hardware oder Software, der sich auf einen Eingangstakt synchronisieren kann.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
PLLs sind als analoge Schaltkreise aufgebaut, die einen Eingangstakt hoch multiplizieren und wieder herunter dividieren und somit als nichtganzzahliger [[Taktteiler]] fungieren. Ferner wird in der Regel die Phase verschoben, dass ein gewünschtes Verhältnis eingestellt wird. Durch einen sog. feedback loop wird erreicht, dass sich die Phase auf dem hohen Frquenzniveau stabil verhält und dem [[Jitter]] des Eingangstaktes nur langsam folgt. Zur Stabilisierung des hochfrequenten Zwischentaktes werden rückgekoppelte Filter benutzt, die genau in dem Frequenzbereich stabil sind. Bei FPGAs sind diese Filter oft parametier- und umschaltbar.&lt;br /&gt;
&lt;br /&gt;
Die Einstellung erfolg voll analog, also nicht zeitdiskret. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
Solche Regelkreise lassen sich in SW nachbilden, wenn sich ein [[Microcontroller]] auf einen eingehenden seriellen Takt einstellt bzw ein [[FPGA]] einen Eingangstakt ausmisst und sich in die Mitte stellt, um parallele Daten zu verarbeiten. (siehe [[SERDES]], [[GTP]]).&lt;br /&gt;
&lt;br /&gt;
Die Verarbeitung erfolgt dann voll digital, also diskret mit dem Systemtakt des FPGAs / des Controllers.&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
In dieser Tabelle werden die durch ganzzahlige Teiler und Multiplizierer erreichbaren Frequenzverhältnisse aufgelistet:&lt;br /&gt;
[[Settings for Multiplier and Divider]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Timer und Uhren]]&lt;br /&gt;
[[Category:Grundlagen]]&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=PLL&amp;diff=68832</id>
		<title>PLL</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=PLL&amp;diff=68832"/>
		<updated>2012-10-24T15:26:34Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: /* Software */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Eine &#039;&#039;&#039;PLL&#039;&#039;&#039; (engl.: phase locked loop) ist ein Regelkreis in Hardware oder Software, der sich auf einen Eingangstakt synchronisieren kann.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
PLLs sind als analoge Schaltkreise aufgebaut, die einen Eingangstakt hoch multiplizieren und wieder herunter dividieren und somit als nichtganzzahliger [[Taktteiler]] fungieren. Ferner wird in der Regel die Phase verschoben, dass ein gewünschtes Verhältnis eingestellt wird. Durch einen sog. feedback loop wird erreicht, dass sich die Phase auf dem hohen Frquenzniveau stabil verhält und dem [[Jitter]] des Eingangstaktes nur langsam folgt. Zur Stabilisierung des hochfrequenten Zwischentaktes werden rückgekoppelte Filter benutzt, die genau in dem Frequenzbereich stabil sind. Bei FPGAs sind diese Filter oft parametier- und umschaltbar.&lt;br /&gt;
&lt;br /&gt;
Die Einstellung erfolg voll analog, also nicht zeitdiskret. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
Solche Regelkreise lassen sich in SW nachbilden, wenn sich ein [[Microcontroller]] auf einen eingehenden seriellen Takt einstellt bzw ein [[FPGA]] einen Eingangstakt ausmisst und sich in die Mitte stellt, um parallele Daten zu verarbeiten. (siehe [[SERDES]], [[GTP]]).&lt;br /&gt;
&lt;br /&gt;
Die Verarbeitung erfolg dann voll digital, also diskret mit dem Systemtakt des FPGAs / des Controllers.&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
In dieser Tabelle werden die durch ganzzahlige Teiler und Multiplizierer erreichbaren Frequenzverhältnisse aufgelistet:&lt;br /&gt;
[[Settings for Multiplier and Divider]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Timer und Uhren]]&lt;br /&gt;
[[Category:Grundlagen]]&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR-GCC-Tutorial/Der_Watchdog&amp;diff=68451</id>
		<title>AVR-GCC-Tutorial/Der Watchdog</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR-GCC-Tutorial/Der_Watchdog&amp;diff=68451"/>
		<updated>2012-09-24T08:21:31Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: /* Watchdog-Anwendungshinweise */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Und hier kommt das ultimative Mittel gegen die Unvollkommenheit von uns&lt;br /&gt;
Programmierern, der [[Watchdog]].&lt;br /&gt;
&lt;br /&gt;
So sehr wir uns auch anstrengen, es wird uns kaum je gelingen, das absolut&lt;br /&gt;
perfekte und fehlerfreie Programm zu entwickeln.&lt;br /&gt;
&lt;br /&gt;
Der Watchdog kann uns zwar auch nicht zu besseren Programmen verhelfen aber er&lt;br /&gt;
kann dafür sorgen, dass unser Programm, wenn es sich wieder mal in&#039;s Nirwana&lt;br /&gt;
verabschiedet hat, neu gestartet wird, indem ein Reset des Controllers&lt;br /&gt;
ausgelöst wird.&lt;br /&gt;
&lt;br /&gt;
== Ein Fallbeispiel ==&lt;br /&gt;
&lt;br /&gt;
Betrachten wir doch einmal folgende Codesequenz:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
    uint8_t x;&lt;br /&gt;
&lt;br /&gt;
    x = 10;&lt;br /&gt;
&lt;br /&gt;
    while (x &amp;gt;= 0)&lt;br /&gt;
    {&lt;br /&gt;
      // tu was&lt;br /&gt;
&lt;br /&gt;
      x--;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn wir die Schleife mal genau anschauen sollte uns auffallen, dass dieselbe niemals beendet wird. Warum nicht? Ganz einfach, weil eine als &#039;&#039;&#039;&#039;&#039;unsigned&#039;&#039;&#039;&#039;&#039; deklarierte Variable niemals kleiner als Null werden kann (der Compiler sollte jedoch eine ensprechende Warnung ausgeben).&lt;br /&gt;
Das Programm wird also ewig diese Schleife durchlaufen.&lt;br /&gt;
Und hier genau kommt der Watchdog zum Zug.&lt;br /&gt;
&lt;br /&gt;
== Wie funktioniert nun der Watchdog? ==&lt;br /&gt;
&lt;br /&gt;
Der Watchdog enthält einen separaten Timer/Counter, welcher mit einem intern erzeugten Takt von 1 MHz bei 5V Vcc getaktet wird. Einige Controller haben einen eigenen Watchdog Oszillator, z.&amp;amp;nbsp;B. der Tiny2313 mit 128kHz. Nachdem der Watchdog aktiviert und der gewünschte Vorteiler eingestellt wurde, beginnt der Counter von 0 an hochzuzählen. &lt;br /&gt;
Wenn nun die je nach Vorteiler eingestellte Anzahl Zyklen erreicht wurde, löst der Watchdog einen Reset aus. Um nun also im Normalbetrieb den Reset zu verhindern, müssen wir den Watchdog regelmäßig wieder neu starten bzw. rücksetzen (Watchdog Reset). &lt;br /&gt;
Dies sollte innerhalb unserer Hauptschleife passieren.&lt;br /&gt;
&lt;br /&gt;
Um ein unbeabsichtigtes Ausschalten des Watchdogs zu verhindern, muss ein spezielles Prozedere verwendet werden, um den WD auszuschalten. Es müssen zuerst die beiden Bits WDTOE und WDE in einer einzelnen Operation (also nicht mit sbi) auf 1 gesetzt werden. &lt;br /&gt;
Dann muss innerhalb der nächsten 4 Taktzyklen das Bit WDE auf 0 gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
Das Watchdog Control Register:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;WDTCR&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;W&#039;&#039;&#039;atch&#039;&#039;&#039;D&#039;&#039;&#039;og &#039;&#039;&#039;T&#039;&#039;&#039;imer&amp;amp;nbsp; &#039;&#039;&#039;C&#039;&#039;&#039;ontrol &#039;&#039;&#039;R&#039;&#039;&#039;egister&lt;br /&gt;
&lt;br /&gt;
In diesem Register stellen wir ein, wie wir den Watchdog verwenden möchten.&lt;br /&gt;
&lt;br /&gt;
Das Register ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
{|  class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
! Bit&lt;br /&gt;
| 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|- &lt;br /&gt;
! Name&lt;br /&gt;
| &#039;&#039;&#039;-&#039;&#039;&#039;|| &#039;&#039;&#039;-&#039;&#039;&#039;|| &#039;&#039;&#039;-&#039;&#039;&#039;|| &#039;&#039;&#039;WDTOE&#039;&#039;&#039;|| &#039;&#039;&#039;WDE&#039;&#039;&#039;|| &#039;&#039;&#039;WDP2&#039;&#039;&#039;|| &#039;&#039;&#039;WDP1&#039;&#039;&#039;|| &#039;&#039;&#039;WDP0&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
! R/W&lt;br /&gt;
| R|| R|| R|| R/W|| R/W|| R/W|| R/W|| R/W&lt;br /&gt;
|- &lt;br /&gt;
! Initialwert&lt;br /&gt;
| 0 || 0 || 0 || 0 || 0 || 0 || 0 || 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WDTOE&#039;&#039;&#039; (&#039;&#039;&#039;W&#039;&#039;&#039;atch&#039;&#039;&#039;d&#039;&#039;&#039;og &#039;&#039;&#039;T&#039;&#039;&#039;urn &#039;&#039;&#039;O&#039;&#039;&#039;ff &#039;&#039;&#039;E&#039;&#039;&#039;nable)&lt;br /&gt;
:Dieses Bit muss gesetzt sein, wenn das Bit &#039;&#039;&#039;WDE&#039;&#039;&#039; gelöscht wird, andernfalls wird der Watchdog nicht ausgeschaltet.&lt;br /&gt;
:Wenn das Bit einmal gesetzt ist, wird es von der Hardware nach 4 Taktzyklen automatisch wieder gelöscht.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WDE&#039;&#039;&#039; (&#039;&#039;&#039;W&#039;&#039;&#039;atch&#039;&#039;&#039;d&#039;&#039;&#039;og &#039;&#039;&#039;E&#039;&#039;&#039;nable)&lt;br /&gt;
:Wenn dieses Bit gesetzt wird, so wird der Watchdog aktiviert.&lt;br /&gt;
:Das Bit kann nur gelöscht werden, solange das Bit &#039;&#039;&#039;WDTOE&#039;&#039;&#039; auf 1 steht.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;WDP2&#039;&#039;&#039;, &#039;&#039;&#039;WDP1&#039;&#039;&#039;, &#039;&#039;&#039;WDP0&#039;&#039;&#039; (&#039;&#039;&#039;W&#039;&#039;&#039;atch&#039;&#039;&#039;d&#039;&#039;&#039;og Timer &#039;&#039;&#039;P&#039;&#039;&#039;rescaler Bits)&lt;br /&gt;
:Diese 3 Bits bestimmen die Anzahl Oszillatorzyklen für den Watchdog, also, wie lange es dauert, bis ein Reset ausgelöst wird:&lt;br /&gt;
&lt;br /&gt;
:{|  class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
! WDP2|| WDP1|| WDP0|| Anzahl Zyklen|| Typ. Timeoutzeit bei Vcc = 3V|| Typ. Timeoutzeit bei Vcc = 5V&lt;br /&gt;
|- &lt;br /&gt;
| 0 || 0 || 0 || 16K|| 47ms|| 15ms&lt;br /&gt;
|- &lt;br /&gt;
| 0 || 0 || 1 || 32K|| 94ms|| 30ms&lt;br /&gt;
|- &lt;br /&gt;
| 0 || 1 || 0 || 64K|| 0.19s|| 60ms&lt;br /&gt;
|- &lt;br /&gt;
| 0 || 1 || 1 || 128K|| 0.38s|| 0.12s&lt;br /&gt;
|- &lt;br /&gt;
| 1 || 0 || 0 || 256K|| 0.75s|| 0.24s&lt;br /&gt;
|- &lt;br /&gt;
| 1 || 0 || 1 || 512K|| 1.5s|| 0.49s&lt;br /&gt;
|- &lt;br /&gt;
| 1 || 1 || 0 || 1024K|| 3s|| 0.97s&lt;br /&gt;
|- &lt;br /&gt;
| 1 || 1 || 1 || 2048K|| 6s|| 1.9s&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Um den Watchdog mit dem avr-gcc Compiler zu verwenden, muss die Headerdatei &#039;&#039;wdt.h&#039;&#039; (&#039;&#039;#include &amp;lt;avr/wdt.h&amp;gt;&#039;&#039;) in die Quelldatei eingebunden werden. &lt;br /&gt;
&amp;lt;!-- mt: das stimmt wohl nicht mehr?!:&lt;br /&gt;
Dadurch wird auch der Startup-Code entsprechend angepasst, so dass der Watchdog nach einem Reset automatisch gestartet wird. &lt;br /&gt;
Das WDTCR-Register wird dabei mit dem Wert 0 beschrieben. &lt;br /&gt;
Falls ein anderer Wert gewünscht ist, so kann dies im Makfile in den Linker-Optionen eingetragen werden. &lt;br /&gt;
Dazu muss in der Zeile LDFLAGS folgende Option angefügt werden:&amp;lt;br /&amp;gt;&lt;br /&gt;
&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp; --defsym __init_wdtcr__=0x1f&amp;lt;br /&amp;gt;&lt;br /&gt;
wenn beispielsweise der Wert des Registers auf 0x1f gestellt werden soll.&amp;lt;br /&amp;gt; --&amp;gt;&lt;br /&gt;
Danach können die folgenden Funktionen verwendet werden:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;wdt_enable(uint8_t timeout)&#039;&#039;&#039;&lt;br /&gt;
:Aktiviert den Watchdog und stellt den Vorteiler auf den gewünschten Wert ein bzw. der in timeout übergebene Wert wird in das WDTCR-Register eingetragen. Einige Timeout-Werte sind als Konstanten vordefiniert&lt;br /&gt;
:Mögliche Timeoutwerte:&lt;br /&gt;
&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;&lt;br /&gt;
{|  class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Konstante || Wert || TimeOut&lt;br /&gt;
|- &lt;br /&gt;
| WDTO_15MS   || 0 || 15 ms&lt;br /&gt;
|-&lt;br /&gt;
| WDTO_30MS   || 1 || 30 ms&lt;br /&gt;
|-&lt;br /&gt;
| WDTO_60MS   || 2 || 60 ms&lt;br /&gt;
|-&lt;br /&gt;
| WDTO_120MS  || 3 || 120 ms&lt;br /&gt;
|-&lt;br /&gt;
| WDTO_250MS  || 4 || 250 ms&lt;br /&gt;
|-&lt;br /&gt;
| WDTO_500MS  || 5 || 500 ms&lt;br /&gt;
|-&lt;br /&gt;
| WDTO_1S     || 6 || 1 s&lt;br /&gt;
|-&lt;br /&gt;
| WDTO_2S     || 7 || 2 s&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
;wdt_disable():Mit dieser Funktion kann der Watchdog ausgeschaltet werden. Dabei wird das notwendige Prozedere, wie oben beschrieben, automatisch ausgeführt.&lt;br /&gt;
;wdt_reset():Dies ist wohl die wichtigste der Watchdog-Funktionen. Sie erzeugt einen Watchdog-Reset, welcher periodisch, und zwar vor Ablauf der Timeoutzeit, ausgeführt werden muss, damit der Watchdog nicht den AVR zurücksetzt.&lt;br /&gt;
&lt;br /&gt;
Selbstverständlich kann das &#039;&#039;&#039;WDTCR&#039;&#039;&#039;-Register auch mit den uns bereits bekannten Funktionen für den Zugriff auf Register programmiert werden.&lt;br /&gt;
&lt;br /&gt;
== Watchdog-Anwendungshinweise ==&lt;br /&gt;
&lt;br /&gt;
Ob nun der Watchdog als Schutzfunktion überhaupt verwendet werden soll, hängt stark von der Anwendung, der genutzten Peripherie und dem Umfang und der Qualitätssicherung des Codes ab. Will man sicher gehen, dass ein Programm sich nicht in einer Endlosschleife verfängt, ist der Watchdog das geeignete Mittel dies zu verhindern. Weiterhin kann bei geschickter Programmierung der Watchdog dazu genutzt werden, bestimmte Stromsparfunktionen zu implementieren. Bei einigen neueren AVRs (z.&amp;amp;nbsp;B. dem ATTiny13) kann der Watchdog auch direkt als Timer genutzt werden, der den Controller aus einem Schlafmodus aufweckt. Auch dies kann im &#039;&#039;&#039;WDTCR&#039;&#039;&#039;-Register eingestellt werden. Außerdem bietet der WD die einzige Möglichkeit einen beabsichtigten System-Reset (ein &amp;quot;richtiger Reset&amp;quot;, kein &amp;quot;jmp 0x0000&amp;quot;) ohne externe Beschaltung auszulösen, was z.&amp;amp;nbsp;B. bei der Implementierung eines Bootloaders nützlich ist. Bei bestimmten Anwendungen kann die Nutzung des WD als &amp;quot;ultimative Deadlock-Sicherung für nicht bedachte Zustände&amp;quot; natürlich immer als zusätzliche Sicherung dienen. &lt;br /&gt;
&lt;br /&gt;
Es besteht die Möglichkeit herauszufinden, ob ein Reset durch den Watchdog ausgelöst wurde (beim ATmega16 z.&amp;amp;nbsp;B. Bit WDRF in MCUCSR). Diese Information sollte auch genutzt werden, falls ein WD-Reset in der Anwendung nicht planmäßig implementiert wurde. Zum Beispiel kann man eine LED an einen freien Pin hängen, die nur bei einem Reset durch den WD aufleuchtet oder aber das &amp;quot;Ereignis WD-Reset&amp;quot; im internen EEPROM des AVR absichern, um die Information später z.&amp;amp;nbsp;B. über UART oder ein Display auszugeben (oder einfach den EEPROM-Inhalt über die ISP/JTAG-Schnittstelle auslesen).&lt;br /&gt;
&lt;br /&gt;
Bei neueren AVR-Typen bleibt der Watchdog auch nach einem Reset durch den Watchdog aktiviert. Wenn ein Programm nach dem Neustart bis zur erstmaligen Rückstellung des Watchdogs länger braucht, als die im Watchdog eingestellte Zeit, sollte man den Watchdog explizit möglichst früh deaktivieren. Ansonsten resetet der Watchdog den Controller immerfort von Neuem. Die frühe Deaktivierung sollte durch eine Funktion erfolgen, die noch vor allen anderen Operationen (insbesondere vor dem mglw. länger andauernden internen Initialisierungen vor dem Sprung zu main()) ausgeführt wird. Näheres zur Implementierung mit avr-gcc/avr-libc findet sich in der Dokumentation der avr-libc (Suchbegriffe: attribut, section, init).&lt;br /&gt;
&lt;br /&gt;
Siehe auch: &lt;br /&gt;
* [http://www.nongnu.org/avr-libc/user-manual/index.html Dokumentation der avr-libc] Abschnitt [http://www.nongnu.org/avr-libc/user-manual/group__avr__watchdog.html Modules/Watchdog timer handling]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/77273#642501 Bug in ATtiny2313?]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:avr-gcc Tutorial]]&lt;br /&gt;
[[Kategorie:Timer und Uhren]]&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Transformatoren_und_Spulen&amp;diff=68428</id>
		<title>Transformatoren und Spulen</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Transformatoren_und_Spulen&amp;diff=68428"/>
		<updated>2012-09-20T13:09:22Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: /* Drosseln */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Vorwort ==&lt;br /&gt;
&lt;br /&gt;
Dieser Text ist eine Übersetzung des englischen [http://ludens.cl/Electron/Magnet.html Originals]. Es wurde nur dahin erweitert bzw. verändert, dass für alle Formelzeichen die in Deutschland gängigen Buchstaben verwendet wurden. Weiterhin sind alle Formeln bei der ersten Erklärung doppelt geschrieben. Einmal mit Formelzeichen und einmal mit den dazugehörigen Einheiten, welche dann in eckigen Klammern [ ] dargestellt werden.&lt;br /&gt;
Dieser Artikel existiert auch als leicht überarbeitetes PDF zum Herunterladen und Drucken: [[Datei:Transformatoren_und_Spulen.pdf]].&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Es gibt viele Elektroniker, sowohl Hobbybastler als auch Profis, welche mit dem Elektromagnetismus auf Kriegsfuß stehen. Immer, wenn sie eine [http://de.wikipedia.org/wiki/Spule_%28Elektrotechnik%29 Spule] oder einen [http://de.wikipedia.org/wiki/Transformator Transformator] entwerfen müssen, tut sich ein Abgrund der Verzweiflung vor diesen Leuten auf. Das Schlimmste ist, dass diese armen Opfer meist nicht schuld sind, da die Autoren von Sachbüchern scheinbar eine Verschwörung geschmiedet haben, um diese Dinge möglichst kompliziert zu erklären, so dass sie niemand wirklich verstehen kann. Oder die Autoren haben es selber nicht richtig verstanden?&lt;br /&gt;
&lt;br /&gt;
Gut – das Internet rettet uns. Ich werde die Grundlagen in einfachen, verständlichen Worten erklären. Hier findest du die meisten Informationen, welche benötigt werden, um elektromagnetische Teile zu entwickeln.&lt;br /&gt;
&lt;br /&gt;
==Die Einheiten==&lt;br /&gt;
&lt;br /&gt;
Ich habe eine Bitte. Wer auf dieser Seite landet, soll bitte alle alten und absurden Einheiten, mit denen die Sachbücher vollgestopft sind, vergessen. Am meisten zu nennen Zoll (Inch), Gauß und Oersted. Entferne diese Worte vollständig aus deinem Vokabular. Die haben dort keinen Platz. Sie sind grundlegende Schuldige bei der Verwirrung der Menschen, welche magnetische Entwicklungen machen wollen, sie machen sie irre. Nachdem wir sie nun losgeworden sind, können wir anfangen.&lt;br /&gt;
&lt;br /&gt;
Die erste Einheit, die wir nutzen werden, ist das Weber, geschrieben als Wb. Das ist die offizielle Einheit des &amp;lt;u&amp;gt;magnetischen Flusses &amp;lt;math&amp;gt;\Phi&amp;lt;/math&amp;gt;&amp;lt;/u&amp;gt;. Wenn man eine Leiterschleife nimmt und 1 V für 1 s anlegt, wird der Fluß in der Schleife sich um 1 Wb geändert haben. Man beachte, dass das immer so ist, egal wie groß oder geformt die Schleife ist und egal, was sich in ihr befindet. Offiziell ist die Definition des Weber so&lt;br /&gt;
::&amp;lt;math&amp;gt;\Phi = U \cdot t&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;math&amp;gt;[\Phi] = \text{Wb} = \text{V} \cdot \text{s}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aber ich bevorzuge die Gleichung in etwas praktischerer Form, bei der die Windungszahl N einer Spule berücksichtigt wird. Das ist eine unserer grundlegenden Wahrheiten.&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;(1)\quad \Phi = \frac{U \cdot t}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
d.h. die Änderung des magnetischen Flusses (in Weber) ist die Spannung (in Volt) multipliziert mit der Zeit (in Sekunden) geteilt durch die Windungszahl. Das ist eine der mächtigsten und nützlichsten Formeln die wir haben.&lt;br /&gt;
&lt;br /&gt;
Wenn wir ein gewisses Maß an magnetischem Fluß durch eine bestimme Fläche pressen, dann können wir von &amp;lt;u&amp;gt;Flußdichte&amp;lt;/u&amp;gt; sprechen. Die Einheit ist Tesla, geschrieben als T, das Formelzeichen ist B. Die Definition ist einfach und offensichtlich.&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;(2)\quad B = \frac{\Phi}{A}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;math&amp;gt;\left[\text{B}\right] = \frac{\text{Wb}}{\text{m}^2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man beachte, daß die Sprache von Quadratmetern im Bereich der Elektronik etwas praxisfern klingt, da die meisten Bauteile eher Querschnitte im Bereich von Quadratzentimetern haben. Aber bitte glaub mir daß es praktischer ist, diese &amp;quot;unpraktischen&amp;quot; Dinge zu akzeptieren als ein Dutzend verschiedene Umrechnungsfaktoren zu benutzen! Die Grundeinheiten haben den großen Vorteil, daß absolut keine Umrechnung nötig ist.&lt;br /&gt;
&lt;br /&gt;
Die Grundeigenschaft einer jeden Spule ist &amp;lt;u&amp;gt;[http://de.wikipedia.org/wiki/Induktivit%C3%A4t Induktivität]&amp;lt;/u&amp;gt;, Formelzeichen L. Sie ist gemessen in Henry, geschrieben als H, definiert durch:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;(3)\quad L = \frac{\Phi}{I}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;math&amp;gt;[\text{L}] = \frac{\text{Wb}}{\text{A}}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
oder in Worten: Ein Henry ist die Induktivität, welche den Strom um 1 Ampere steigen läßt, wenn man für eine Sekunde ein Volt anlegt. Diese Gleichung ist für unser Zwecke auch sehr nützlich. Jetzt können wir anfangen zu spielen. Wir können Gleichung (1) und (3) verbinden und erhalten das Folgende&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;math&amp;gt;L = \frac{\Phi \cdot N}{I}&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;[\text{L}] = \frac{\text{Wb}}{\text{A}}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Solche mathematischen Umwandlungen stimmen immer und geben uns die Möglichkeit, unbekannte Größen zu bestimmen.&lt;br /&gt;
&lt;br /&gt;
=== Tabelle aller verwendeten Formelzeichen ===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
!Parameter || Formelzeichen || Einheit || Einheit&amp;lt;br&amp;gt;Kurzform&lt;br /&gt;
|-&lt;br /&gt;
| magnetischer Fluß || &amp;lt;math&amp;gt;\!\,\Phi&amp;lt;/math&amp;gt; || Weber || Wb&lt;br /&gt;
|-&lt;br /&gt;
| magnetische Flußdichte  || B || Tesla || T	&lt;br /&gt;
|-&lt;br /&gt;
| Induktivität  || L || Henry || H 	&lt;br /&gt;
|-&lt;br /&gt;
| Spannung  || U || Volt || V 	&lt;br /&gt;
|-&lt;br /&gt;
| Strom  || I || Ampere || A 	&lt;br /&gt;
|-&lt;br /&gt;
| Fläche  || A || Quadratmeter || &amp;lt;math&amp;gt;\!\,\text{m}^2&amp;lt;/math&amp;gt;	&lt;br /&gt;
|-&lt;br /&gt;
| Zeit || t || Sekunde || s&lt;br /&gt;
|-&lt;br /&gt;
| Energie || E || Joule || J&lt;br /&gt;
|-&lt;br /&gt;
| Windungszahl || N || keine || 1&lt;br /&gt;
|-&lt;br /&gt;
| Frequenz || f || Hertz || Hz&lt;br /&gt;
|-&lt;br /&gt;
| Länge || l || Meter || m&lt;br /&gt;
|-&lt;br /&gt;
| Widerstand || R || Ohm ||  &amp;lt;math&amp;gt;\!\,\Omega&amp;lt;/math&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| spezifischer&amp;lt;br&amp;gt;Widerstand ||  &amp;lt;math&amp;gt;\!\,\rho&amp;lt;/math&amp;gt; || Ohm mal Quadratmillimeter&amp;lt;br&amp;gt;pro Meter||&amp;lt;math&amp;gt;\frac{\Omega \cdot \text{mm}^2}{\text{m}}&amp;lt;/math&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| Relative&amp;lt;br&amp;gt;Permeabilität || &amp;lt;math&amp;gt;\mu_r&amp;lt;/math&amp;gt; || keine || 1&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Achtung! Nicht das Formelzeichen der Fläche mit der Einheit des Stroms verwechseln!&lt;br /&gt;
&lt;br /&gt;
Aber jetzt geht&#039;s an praktische Dinge.&lt;br /&gt;
&lt;br /&gt;
== Entwicklung von Netztrafos ==&lt;br /&gt;
&lt;br /&gt;
Während fast jeder Elektroniker weiß, daß das Spannungsverhältnis eines Transformators von dem Windungsverhältnis abhängt, taucht die Frage bei vielen Anfängern auf&lt;br /&gt;
&lt;br /&gt;
&amp;quot;Wieviele Windungen pro Volt brauche ich?&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Es ist sehr einfach. Man hat einen Eisenkern, den will man bewickeln. Als erstes mißt man den Querschnitt des Eisens, durch den der magnetische Fluß geht. Sagen wir, der Mittelschenkel eines Transformators ist 2cm breit und der ganze Stapel der laminierten Bleche ist gut zusammengepreßt auf 3cm. Das bringt uns &amp;lt;math&amp;gt;6cm^2&amp;lt;/math&amp;gt; bzw. &amp;lt;math&amp;gt;6 * 10^{-4} m^2&amp;lt;/math&amp;gt; Querschnitt. Nun müssen wir entscheiden, wieviel Flußdichte wir in unserem Eisen haben wollen. Bei niedrigen Frequenzen wie bei 50Hz Netztrafos ist der begrenzende Faktor die Sättigung des Kerns. Sehr bescheidene Transformatoren sättigen bei 1T, aber typische Werte liegen bei 1,2 oder 1,3T, und ein gutes kornorientiertes Material geht vielleicht bis 1,6 oder sogar 1,7T. Wenn man wirklich nicht weiß welches Material man hat sollte man besser bei 1T auf der sicheren Seite bleiben. Für diese Beispiel nehmen wir an, daß das Eisen für 1,2T gut genug ist.&lt;br /&gt;
&lt;br /&gt;
Durch Anwendung von Formel (2) erhält man den maximal zulässigen Fluß von 0,72mWb. Doch bevor es weitergeht, warte für einen Moment und denk nach!!! Eisen kann in beide Richtungen magnetisiert werden. Die Gesamtänderung des magnetischen Flusses, vom maximal negativem zum maximal positiven kann 1,4mWb betragen! Weiter mit Formel (1) und der Berechnung der Windungen. Nehmen wir an wir reden von Chile oder einem anderen Land mit 220V und 50 Hz.&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;math&amp;gt;1,44~\text{mWb}=\frac{220~\text{V} \cdot 10~\text{ms}}{N}&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;N=\frac{220~\text{V} \cdot 10~\text{ms}}{1,44~\text{mWb}}=1528&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das ist die Windungszahl der 220V Primärwicklung.&lt;br /&gt;
Einfach, oder? In Wirklichkeit ist das oben Gesagte zu einfach um wahr zu sein. Es gibt einen anderen Faktor, den ich übersprungen habe. Das Obige wäre wahr, wenn die Netzspannung 220V Rechteck wäre. In Wahrheit ist es aber ein Sinus mit 220V Effektivwert, während der Mittelwert etwas anders ist. Und der magnetische Flußaufbau hängt vom Mittelwert ab, &#039;&#039;&#039;nicht&#039;&#039;&#039; vom Effektivwert! Also müssen wir einen kleinen Korrekturfaktor einführen, welcher durch Mathematik aus der Sinusfunktion abgeleitet werden kann. Anstatt mit der exakten Mathematik hier zu nerven empfehle ich mein Kochbuchrezept. 11% zu unserem Vorteil. Also reichen hier 1376 Windungen. Wo kommen die 10ms her, mag man fragen? Denk noch mal. Die Änderung vom maximal negativen zum maximal positiven Fluß passiert in einer Halbwelle. Und bei 50 Hz sind das 10ms. Wir können das alles in eine einfache, universelle Formel packen, gültig für die Berechnung der Windungen für alle Transformatoren und Spulen mit Sinusspannung.&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;(4)\quad N = \frac{U_{RMS}}{4,44 \cdot A \cdot f \cdot B}&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt;[Windungen] = \frac{[V]}{4,44 \cdot [m^2] \cdot [Hz] \cdot [T]}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die 4,44 ist kein Umrechnungsfaktor, sondern ergibt sich aus 2 * 2 * 1,11. Eine &amp;quot;2&amp;quot; ist für die Tatsache, daß der magnetische Umschwung doppelt so groß wie der einseitige ist (damit kann man die einfache Sättigungsgrenze einsetzen), die andere &amp;quot;2&amp;quot; entsteht durch die zwei Halbwellen der Sinusschwingung und die 1.11 ist der Umrechnungsfaktor von Effektivwert auf Mittelwert der Sinusspannung.&lt;br /&gt;
&lt;br /&gt;
=== Leistung ===&lt;br /&gt;
&lt;br /&gt;
Eine andere Frage ist meistens, wieviel Leistung ein Trafo bestimmter Größe übertragen kann. Laßt uns das analysieren.&lt;br /&gt;
&lt;br /&gt;
Der magnetische Fluß im Kern hängt ab von der Spannung, welche an die Windungen angelegt wird, der Frequenz, aber &#039;&#039;&#039;nicht&#039;&#039;&#039; dem Strom, welcher der Transformator liefert! Oh, na gut, ein wenig Abhängigkeit gibt es da schon durch Effekte der realen Welt. Wenn man mehr Strom zieht, fällt durch den Widerstand der Wicklung etwas Spannung ab, wodurch die effektiv an der Wicklung wirksame Spannung reduziert wird und dadurch der magnetische Fluß proportional reduziert wird. Aber der entscheidende Punkt ist, daß der Kern des Trafos &#039;&#039;&#039;nicht&#039;&#039;&#039; die Ausgangsleistung beeinflußt. Diese Grenze kommt von den Wicklungen und hat zwei Seiten. Eine ist der Spannungsabfall, welche proportional zum Ausgangsstrom ist und an einem Punkt so groß sein wird, daß die Spannung für die Last nicht mehr ausreicht. Die andere ist Erwärmung. Mit steigender Last steigt die Verlustleistung in den Wicklungen quadratisch, und wenn man genügend Leistung lange genug entnimmt werden sie abbrennen.&lt;br /&gt;
&lt;br /&gt;
All das Gesagte macht klar, daß die Leistung eines Transformators abhängt von dem magnetischen Kernquerschnitt (weil mehr Querschnitt weniger Windungen benötigt, damit dickerer Draht verwendet werden kann) und von der Größe des Wickelfensters, das ist der Querschnitt wo sich die Wicklungen befinden. Aber es gibt keine lineare Formel für den Zusammenhang dieser beiden Dinge zur Leistung! Wenn ein Transformator größer wird, wird der Pfad zur Wärmeableitung länger und somit wird das Anwachsen der Leistung geringer als das Produkt der beiden Querschnittsflächen.&lt;br /&gt;
&lt;br /&gt;
Bei all dem Durcheinander werde ich keine Abschätzungen abgeben, dafür aber die reale Berechnung empfehlen. Für einen gegebenen Eisenkern, berechne die benötigten Windungen, beachte den verfügbaren Platz dafür, berechne die Drahtstärke und über den spezifischen Widerstand von Kupfer von &amp;lt;math&amp;gt;0,0178 \Omega \cdot mm^2/m&amp;lt;/math&amp;gt; den Gesamtwiderstand der Wicklung. Jetzt kann es helfen zu wissen, daß für kleine Transformatoren ein maximaler Verlust von 10% (5% pro Wicklung) normalerweise akzeptiert wird. Das sollte es ermöglichen, die Leistung zu berechnen, welche sicher aus dem Trafo entnommen werden kann, wenn man genug Wissen für diese Rechnung hat! Man braucht nicht mehr Mathematik als man in der Schule gelernt hat, etwa in der 5. Klasse.&lt;br /&gt;
&lt;br /&gt;
Hey, ich höre euch schreien!!! OK, OK, um die Sache klarer zu machen werde ich ein Beispiel vorrechnen. Nehmen wir den Kern von oben an, mit &amp;lt;math&amp;gt;6cm^2&amp;lt;/math&amp;gt; Querschnitt und &amp;lt;math&amp;gt;10cm^2&amp;lt;/math&amp;gt; verfügbar für die Wicklungen und daß eine Windung im Mittel 20cm lang ist. Wir verteilen den Wickelraum gleichmäßig auf Primär- und Sekundärseite. Und wir nehmen an, daß nur 40% des Wickelfensters wirklich für Kupfer genutzt werden, der Rest ist Isolation, Luft und verlorener Zwischenraum. Das ist in etwa eine realistische Annahme und beschert uns &amp;lt;math&amp;gt;2cm^2&amp;lt;/math&amp;gt; für das Kupfer pro Wicklung. Mit 1376 Windungen hat die Primärwicklung einen Drahtquerschnitt von &amp;lt;math&amp;gt;0,14mm^2&amp;lt;/math&amp;gt;, die Gesamtlänge ist 275m. Der Widerstand berechnet sich aus&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;math&amp;gt;R = \frac{\rho \cdot l}{A} = \frac{0,0178 \frac{\Omega \cdot mm^2}{m} \cdot 275m}{0,14mm^2}=35 \Omega&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir erlauben 5% Verlust in jeder Wicklung. Bei 220V sind das 11V. Nun einfach das ohmsche Gesetz anwenden und der maximal Primärstrom ist 0,32A, multipliziert mit 220V ergibt das ein maximale Eingangsleistung von 70VA für diesen Trafo.&lt;br /&gt;
&lt;br /&gt;
Cool, he? ;-)&lt;br /&gt;
&lt;br /&gt;
Man beachte, daß der Magnetisierungsstrom hier nicht berücksichtigt wird. Du sagst vielleicht, daß selbst wenn es nur 10 oder 20% des Maximalstroms sind, er doch berücksichtigt werden muß! Wenn du das sagst, liegst du falsch. Der Magnetisierungsstrom ist 90 Grad phasenverschoben zum transformierten Laststrom und dadurch, selbst wenn es 20% des Laststrom sind, die Spitze der vektoriellen Summe der beiden sehr nahe beim Laststrom allein liegt. Es lohnt sich nicht den kleinen Unterschied zu beachten.&lt;br /&gt;
&lt;br /&gt;
== Transformatoren für Schaltnetzteile ==&lt;br /&gt;
&lt;br /&gt;
Das vorherige Kapitel kann nahezu vollständig auf Transformatoren höherer Frequenz in Schaltnetzteilen angewendet werden. Es gibt nur ein paar praktische Unterschiede, welche ich jetzt nennen werde.&lt;br /&gt;
&lt;br /&gt;
Bei Frequenzen über ein paar hundert Hertz ist die Sättigung nicht mehr der begrenzende Faktor bei Auswahl der maximalen Flußdichte. Der Grund liegt darin, daß die Verluste des magnetischen Materials so hoch werden, daß die Flußdichte verringert werden muß, um ein akzeptables Maß an Verlusten zu erreichen! Man braucht wirklich das Datenblatt des Herstellers um festzustellen, welche Flußdichte akzeptabel ist. Um eine grobe Vorstellung zu erhalten sollte man bedenken, daß fast immer Ferritmaterial benutzt wird. Ferrit sättigt bei 0,3 bis 0,4T, das ist die absolute Grenze. Für ein typisches Leistungsferrit muß man die Flußdichte bei 25kHz unterhalb 150mT halten, und über 100kHz unter 50mT. Aber viel hängt auch von der Kerngröße ab. Ein größerer Kern muß dabei mit geringerer Flußdichte arbeiten, um eine Überhitzung zu vermeiden.&lt;br /&gt;
&lt;br /&gt;
Normalerweise arbeiten Schaltnetzteile mit Rechtecksignalen, d.h. man muß die 11% zur &amp;quot;Sinuskorrektur&amp;quot; aus der Formel (4) entfernen. Und dann nutzen viele Schaltnetzteile den magnetischen Kern nur einseitig, sprich er wird nur in eine Richtung magnetisiert, was wiederum einen Faktor zwei aus der Formel entfernt. Für den Rest ist die Rechnung die gleiche wie für Netztafos.&lt;br /&gt;
&lt;br /&gt;
Sei nicht überrascht wenn man mit sehr wenigen Windungen endet. Faktisch ist es ziemlich normal, nur 10 oder 20 Windungen an einer 300V Primärwicklung eines großen Schaltnetzteils zu haben.  &lt;br /&gt;
&lt;br /&gt;
== HF-Breitbandübertrager==&lt;br /&gt;
&lt;br /&gt;
Vielleicht hast du diese Ferrittrafos schon am Ausgang von Transistor HF-Verstärkern gesehen. Sie sehen aus wie zwei Ferritröhren nebeneinander, mit zwei Kupferröhren hineingesteckt, welche die Primärwicklung mit einer Windung ergeben. Durch diese Kupferröhren sind einige Windungen isolierter Draht gezogen, welche die Sekundärwicklung bilden. Laßt uns so einen Trafo als Beispiel nutzen.&lt;br /&gt;
&lt;br /&gt;
Unser hypothetischer Fall ist ein 100W Push-Pull Verstärker für 1,8-30MHz, gespeist von 13.8V, wie sie zu Millionen täglich von Funkamateuren und allen möglichen kommerziellen Diensten genutzt werden. Jeder Transistor kann seine Seite der Primärwicklung ziemlich nah an Masse ziehen, aber nicht ganz, wegen der Sättigungsspannung. HF-Transistoren sättigen typisch bei 1V, so daß es vernünftig ist anzunehmen, daß der Transistor um 12,8V schalten kann, was 25,6V Spitzenspannung für die Primärwicklung bedeutet, oder ca. 18V RMS. Auf der anderen Seite soll die Sekundärwicklung die HF-Leistung an 50Ω liefern, und 100W an 50Ω sind 70,7V. Deshalb brauchen wir ein Spannungs(Windungs)verhältnis von ca. 3,9. Mit einer Primärwicklung mit nur einer Windung können wir nur ganzzahlige Verhältnisse realisieren, deshalb entscheiden wir uns für vier Sekundärwindungen. Der Effekt ist, daß bei 100W die Transistoren bei 17,7V RMS laufen, oder 25V Spitze. D.h. sie schwingen über 12,5Vder Stromversorgung und lassen dabei 1,3V übrig für sie Sättigung. So weit so gut.&lt;br /&gt;
&lt;br /&gt;
Bei 1,8MHz, unsere niedrigste Frequenz, kann ein typischer Ferrit sicher bis 12mT belastet werden. Wir haben einen schönen, reinen Sinus, also nutzen wir Gleichung (4).&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;math&amp;gt;1 Windung = \frac{17,7V}{4,44 \cdot A \cdot 1,8MHz \cdot 12mT}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
umgestellt nach der Fläche&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;math&amp;gt;A = \frac{17,7V}{4,44 \cdot 1 Windung \cdot 1,8MHz \cdot 12mT} = 1,8 \cdot 10^{-4}m^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir brauchen ein Kernquerschnitt von 1,8cm^2. Ein kleinerer Kern würde bei voller Leistung nach einiger Zeit überhitzen, während ein größerer etwas teuerer wäre, aber den Vorteil der spektralen Reinheit mit sich bringt, denn geringere Flußdichte heißt weniger Verzerrung. Aber für die Übung bleiben wir bei 1,8cm^2 &lt;br /&gt;
&lt;br /&gt;
Wir müssen noch etwas arbeiten. Wir könnten einen langen, dünnen Ferrit nutzen, oder einen kurzen dicken. Und wir können unter verschiedenen Ferrittypen wählen! Um die Auswahl einzuschränken, schauen wir uns die Induktivitätsforderung an. Der Ansatz ist, daß der Transformator eine Induktivität haben sollte, die hoch genug ist, um wenig Einfluß zu haben, wenn man ihn parallel zur Last schaltet. Pi mal Daumen sollte der induktive Widerstand 10mal höher sein als die Last. Man kann sich aussuchen, ob man das für die Sekundärspule mit 4 Windungen und 50Ω oder die Primärspule mit 1 Windung und 3,1Ω berechnen will, das Ergebnis ist gleich. Ich wähle die Primärseite. Der induktive Widerstand berechnet sich aus.&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;math&amp;gt;X_L=2 \pi \cdot f \cdot L&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das heißt für uns&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;math&amp;gt; L=\frac{X_L}{2 \pi \cdot f}=\frac{31 \Omega}{2 \pi \cdot 1,8 MHz}=2,7 \mu H&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir brauchen also 2,7µH, um Pi mal Daumen die Anforderung des zehnfachen induktiven Widerstands zu erfüllen. Jetzt muß man sich die Datenblätter der Kerne anschauen und den passenden raussuchen. Für diese Beispiel werde ich den Katalog von Amidon nutzen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Versuchen wir den ziemlich verbreiteten Typ FT-50-43. Dieser Ringkern hat 0,133cm^2 Querschnitt. Zwei Stapel zu je sieben Stück würden unsere Anforderung bezüglich Flußdichte erfüllen. Der [http://de.wikipedia.org/wiki/AL-Wert#Bestimmung_der_Induktivit.C3.A4t_mittels_AL-Wert AL-Wert] ist 0,52µH/N^2, d.h. 14 Kerne mit einer Wicklung ergeben 7,3µH, ein Mehrfaches unseres benötigten Wertes. Weil aber Breitbandverstärker zu Schwingungen bei niedrigen Frequenzen tendieren, weil dort die Transistoren die größte Verstärkung haben, ist es keine gute Idee mehr Leistung bei niedrigen Frequenzen anzubieten als notwendig! Versuchen wir einen anderen Typ.&lt;br /&gt;
&lt;br /&gt;
Das Material 43 hat eine [http://de.wikipedia.org/wiki/Permeabilit%C3%A4t_%28Magnetismus%29 Permeabilität] von 850. Ein Kern mit den gleichen Abmessungen aber mit einer Permeabilität von nur 330 wäre nett. Aber Amidon macht keine Kerne dieser Größe in einer Permeabilität auch nur annähernd zu dem. Hey, man kann nicht immer umsonst Achterbahn fahren. Die nächstniedrigere Permeabilität, welche von Amidon verfügbar und für unser Projekt brauchbar ist, ist 125, das ist zu wenig. Also bleiben wir beim 43er Material uns sehen was wir machen können.&lt;br /&gt;
Es gibt den FT-82-43 aus dem gleichen Material. Er ist viel dicker, hat 0,25cm^2 Querschnitt und einen AL-Wert ziemlich ähnlich zu unserem anderen Kern, 0,55µH/N^2. Zwei Stapel mit je 4 Stück ergeben mehr als genug Querschnitt mit 4,4µH. Das ist eine brauchbare Lösung und bringt uns mehr Platz für die Wicklungen.&lt;br /&gt;
&lt;br /&gt;
Bei höheren Frequenzen ist die Flußdichte geringer und bleibt damit unterhalb der Grenze des Materials. Das Verhältnis zwischen induktivem Widerstand und Lastwiderstand verbessert sich mit steigender Frequenz, aber bei den höchsten Frequenzen könnten parasitäre Kapazitäten starken Einfluß gewinnen, so daß man sie bei der Entwicklung berücksichtigen sollte.&lt;br /&gt;
 &lt;br /&gt;
== Energiespeicherung in Magnetkernen ==&lt;br /&gt;
&lt;br /&gt;
Weiß du wieviel Energie eine Spule speichert? Das ist definiert durch die gleiche, alte Formel, die oft in der klassischen Physik auftaucht.&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;(5)\quad E = \frac{1}{2} \cdot L \cdot I^2&amp;lt;/math&amp;gt;&lt;br /&gt;
::&amp;lt;math&amp;gt; [J] = \frac{1}{2} \cdot [H] \cdot [A]^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Einheit der Energie ist Joule (J). Die Induktivität L in Henry (H) sowie der Strom I durch die Spule in Ampere (A). Im Falle eines Transformators muß dieser Strom netto berechnet werden, nachdem man die (transformierten) Primär- und Sekundärströme abgezogen hat unter Berücksichtigung des Windungsverhältnisses. Kurz, das ist der Magnetisierungsstrom.&lt;br /&gt;
&lt;br /&gt;
In den meisten Anwendungen als Transformator ist dieser Strom nicht wirklich gewünscht, aber ein unvermeidbarer Nebeneffekt. Aber es gibt Anwendungen, welche diese Energiespeicherung gut nutzen! Ein sehr wichtiges Beispiel ist der Sperrwandler. Im Prinzip speichert dieser Wandler die Energie von der Primärseite und entlädt sie in die Sekundärseite, oft mit einer Spannung, welche &#039;&#039;&#039;nicht&#039;&#039;&#039; dem Windungsverhältnis entspricht! Weil Primär- und Sekundärstrom nicht zur gleichen Zeit fließen ist es nicht mehr gültig, daß die Spannungen im gleichen Verhältnis wie die Windungszahlen stehen!&lt;br /&gt;
&lt;br /&gt;
Nehmen wir an, wir entwickeln ein Schaltnetzteil auf dieser Basis. Wir wollen 13,8V Ausgangsspannung, während die Eingangsspannung 110 oder 220V ist. Der logische Ansatz in diesem Fall ist die Nutzung eines Gleichrichters, welcher als Brücke für 220V oder als Verdoppler für 110V geschaltet werden kann. Am Ende haben wir 300VDC in beiden Fällen, der Rest des Schaltnetzteils ist identisch, unabhängig von der Netzspannung. Nehmen wir weiter an, wir haben einen Ferritkern mit 2cm^2 Querschnitt, 12cm magnetische Pfadlänge mit einer Anfangspermeabilität von 2000 und 350mT Sättingsflußdichte. Der Wandler soll bei 100 kHz laufen. Für die Entwicklung brauchen wir noch ein paar Informationen. Den AL-Wert, welcher das Verhältnis zwischen Anzahl der Windungen und Induktivität beschreibt. Wenn er nicht im Datenblatt angegeben ist, kann man ihn aus den physikalischen Abmessungen und Ferriteigenschaften berechnen. Oder man wickelt eine Meßspule und mißt den Wert nach, aber es ist ganz sicher einfacher ihn aus dem Katalog zu bekommen! Nehmen wir an unser Kern hat 6µH/N^2, d.h. 1 Windung ergibt 6µH, 10 Windungen ergeben 600µH und so weiter. Diese angenommenen Werte sind typisch für praktische Fälle.&lt;br /&gt;
&lt;br /&gt;
Um die Spannungsbelastung des Transistors der Primärseite zu verringern, wählen wir 30% der Zykluszeit für die Aufladung des Transformators und 60% für die Entladung. Das erlaubt die Entladung mit der halben Eingangsspannung, d.h. der Schalttransistor sieht nur 450V statt 600V. Das reduziert auch die Stromspitze des sekundären Gleichrichters, während dadurch aber die Stromstärke der Primärseite sowie Spannungsfestigkeit der Sekundärseite erhöht werden, was hier aber kein Problem ist. Die verbleibenden 10% der Schaltzeit sind reserviert für Schaltzeit des Transistors, Totzeitsteuerung des Steuer-ICs etc. Bei 100kHz ist die Ladezeit 3µs, die Entladezeit 6µs. Ein Blick ins Datenblatt sagt uns, daß bei 100kHz und einseitiger Magnetisierung die Flußdichte auf 100mT begrenzt werden sollte. Durch Anwendung von Formel (1) und (2) können wir schnell ausrechnen.&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;math&amp;gt; B = \frac{U \cdot t}{N \cdot A}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;math&amp;gt; N = \frac{U \cdot t}{B \cdot A} = \frac{300V \cdot 3\mu s}{0,1T \cdot 2 \cdot 10^{-4}m^2}=45&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
45 Windungen laden diesen Kern auf 0,1T in 3µs, wenn man 300V anlegt. Schön und einfach. Auf der Sekundärseite brauchen wir 13,8V, plus ca. 1V für die Gleichrichterdiode, macht in Summe ca. 15V. Wir können die gleiche Formel einsetzen, nur mit anderen Werten für Spannung und Zeit.&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;math&amp;gt; N = \frac{U \cdot t}{B \cdot A} = \frac{15V \cdot 6\mu s}{0,1T \cdot 2 \cdot 10^{-4}m^2}=4,5&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Gefällt dir das? Das Windungsverhältnis ist 10:1, während das Spannungsverhältnis 20:1 ist, weil das Zeitverhältnis 1:2 ist!&lt;br /&gt;
&lt;br /&gt;
Entscheide frei ob du lieber 4 oder 5 Windungen haben willst, das bewirkt nur eine geringfügige Änderung der Lade- und Entladezeiten.&lt;br /&gt;
&lt;br /&gt;
Nun, wieviel Leistung kann dieses Netzteil liefern? Nein, rechne jetzt nicht wie bei einem Netztrafo! Wir haben hier zwei Grenzen. Eine ist die begrenzte Wärmeerzeugung im Transformator, aber es gibt auch eine funktionale Grenze, welche viel wichtiger ist. Unser Schaltnetzteil arbeitet mit Energiespeicherung und bei jedem Zyklus wird nur eine kleine Menge an Energie gespeichert, wodurch die am Ausgang verfügbare Leistung streng begrenzt ist!&lt;br /&gt;
&lt;br /&gt;
Durch unseren oben angenommenen AL-Wert hat unsere Primärwicklung mit 45 Windungen eine Induktivität von 12mH. Über die Definition der Induktivität können wir den Spitzenstrom am Ende des Ladezyklus ausrechnen.&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;math&amp;gt; I = \frac{U \cdot t}{L} = \frac{300V \cdot 3 \mu s}{12mH}= 75mA&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nur 75mA! Sieht nicht viel aus. Berechnen wir die gespeicherte Energie.&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;math&amp;gt;E = \frac{1}{2} \cdot L \cdot I^2= \frac{1}{2} \cdot 12mH \cdot (75mA)^2=34\mu J&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Man kann das auch über einen anderen Ansatz berechnen. Da der Strom linear von Null bis 75mA ansteigt, ergibt das im Mittel 37,5mA. Bei 300V und 3µs sind das&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;math&amp;gt;E = U \cdot I \cdot t = 300V \cdot 37,5mA \cdot 3\mu s =34\mu J&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Schön wenn die Dinge übereinstimmen...? ;-)&lt;br /&gt;
&lt;br /&gt;
Wenn man bedenkt, daß man bei 100kHz 100.000 dieser kleinen Brocken von Energie pro Sekunde hat, und Leistung schlicht Energie pro Zeit ist, dann kommen wir auf traurige 3,4W für unser glorreiches Netzteil! Sieht nach einer ziemlich schlechten Nutzung für einen Kern dieser Größe aus, nicht wahr? Dieser Kern ist mit &amp;quot;250W typisch&amp;quot; durch den Hersteller gekennzeichnet!!!&lt;br /&gt;
&lt;br /&gt;
Wir müssen herausfinden, wie wir mehr Energie in dem Kern speichern können. Wenn wir die Induktivität erhöhen, wird der Strom kleiner, aber der Strom geht quadratisch in die Energie ein! Keine gute Idee. Es ist besser die Induktivität zu verringern, dadurch steigt der Strom. Da die gespeicherte Energie linear von der Induktivität, aber quadratisch vom Strom abhängt, ist es offensichtlich daß die gespeicherte Energie proportional steigt.&lt;br /&gt;
&lt;br /&gt;
Wie machen wir das? Wir können nicht einfach die Windungszahl verringern! Das bringt uns in Widerspruch mit Gleichung (1), erhöht die Flußdichte mehr als der Ferrit verträgt. Erkennst du das Problem? Wir müssen die Induktivität verringern, ohne die Windungszahl zu verringern, um die Flußdichte zu erhalten.&lt;br /&gt;
&lt;br /&gt;
Es gibt ein einfaches Werkzeug um das zu erreichen. Luft! Man muß nur den Magnetfluß über einen Luftspalt laufen lassen, indem man die beiden Kernhälften geringfügig auseinander zieht. Der Effekt dieses Luftspalts ist die Verringerung der effektiven Permeabilität des Kerns und damit die Reduzierung des AL-Werts, ohne Einfluß auf andere Parameter. Schauen wir was passiert wenn wir einen Luftspalt von insgesamt 1mm einfügen, was durch das Entfernen der Kernhälften um 0,5mm erreicht wird.&lt;br /&gt;
&lt;br /&gt;
Der magnetische Fluß läuft nun 120mm durch Ferrit mit einer Permeabilität von 2000 und 1mm durch Luft mit einer Permeabilität von Eins. 2000mm Ferrit haben den gleichen magnetischen Widerstand wie 1mm Luft! D.h. unser Kern hat nun nur noch eine effektive Permeabilität von 120 anstatt der 2000! Das heißt auch, unser AL-Wert ist nun 0,36µH/N^2 und unsere Primärwicklung mit 45 Windungen hat nun nur noch 720µH. Das wiederum heißt, daß sie in 3µs auf 1,25A aufgeladen wird und 0,56mJ pro Zyklus speichert, woraus 56W Ausgangsleistung entstehen. Das sieht deutlich besser aus als unsere mageren 3,4W ohne Luftspalt! Und all das bei der gleichen Flußdichte im Kern!&lt;br /&gt;
&lt;br /&gt;
Hast du jemals gedacht, daß eine 1mm dicke Luftschicht so schrecklich wichtig sein kann?&lt;br /&gt;
&lt;br /&gt;
Die nächste Frage wäre, ob es eine Grenze für den Luftspalt gibt. Sicher, es gibt zwei Grenzen. Eine ist einfach, wenn man die gespeicherte und übertragene Energie erhöht, erhöht sich auch der Verlust in der Wicklung. An einem Punkt erreicht man die Grenze der thermischen Verluste im Kupfer, genauso wie im Netztransformator. Die Größe des Luftspalts ist meist ein Kompromiß des Entwicklers. Aber es gibt ein anderes Problem. Mit fallender effektiver Permeabilität fällt auch die Kopplung zwischen den Wicklungen. Der Transformator entwickelt ein starkes Streufeld und zeigt starke ungekoppelte Induktivität, welche zur Zerstörung des Leistungstransistors und der Diode führen kann und in den meisten Fällen einen [[Snubber]] notwendig macht. Der Entwickler muß manchmal mit weniger Luftspalt auskommen als was die Wicklungen thermisch verkraften könnten. In jedem Fall kann das Koppelproblem durch richtige Konstruktion des Transformators minimiert werden. Die Primär- und Sekundärwicklung kann gemischt sein, eine bifilare Wicklung ist manchmal möglich. Und es ist oft eine gute Idee, eine dicke Kupferfolie um den kompletten Transformator zu wickeln, welche eine Kurzschlußwindung darstellt. Diese bewirkt, daß der Fluß außerhalb zu Null wird, was bedeutet, daß der Fluß durch den Spulenaufbau gleich dem um die Spule (Seitenschenkel des Kerns) ist und damit die Kopplung verbessert.&lt;br /&gt;
&lt;br /&gt;
In vielen Fällen ist es besser ein Material mit weniger Permeabilität zu verwenden, wie z.&amp;amp;nbsp;B. Eisenpulver. Der Transformator wäre nahezu identisch, wenn wir ihn mit einem Material mit einer Permeabilität von 120 ohne Luftspalt bauen würden. Er hätte eine bessere Kopplung und weniger Streufeld. Andererseits ist der große Vorteil des Luftspalts, daß der Entwickler genau festlegen kann, wieviel effektive Permeabilität er will, ohne einen neuen Kern bestellen zu müssen!&lt;br /&gt;
&lt;br /&gt;
== Drosseln ==&lt;br /&gt;
&lt;br /&gt;
Eines der schlimmsten Dinge, die ich je in einem elektrischen Sachbuch sah, daß man verschiedene Formeln für das Gleichstrom- und Wechselstromverhalten von Spulen angegeben hat. Das ist kompletter Unsinn!!! Es gibt keinen grundlegenden Unterschied zwischen Gleich- und Wechselstrom. Zu jedem Zeitpunkt des Wechselstroms fließt ein &amp;quot;Gleichstrom&amp;quot;, und in Gleichstromanwendungen fließt auch ein Wechselstrom, wenigsten beim Ein- und Ausschalten. Deshalb können und sollten wir die gleichen Entwicklungsansätze für Drosseln nutzen.&lt;br /&gt;
&lt;br /&gt;
Schauen wir uns das in der Praxis an. Eine verbreitete Aufgabe ist die Entwicklung einer Drossel mit einer bestimmten Induktivität, welche einen bestimmten Strom aushält ohne in die Sättigung zu gehen. Beachte, daß für Gleichstromanwendungen die Grenze immer durch die Flußdichte gesetzt wird. Erinnerst du dich daran, was ich weiter oben geschrieben habe? Bei hohen Frequenzen ist die Grenze durch die Kernverluste bestimmt, und bei niedrigen durch die Sättigung. Und Gleichstrom ist einfach eine sehr, sehr niedrige Frequenz. ;-)&lt;br /&gt;
&lt;br /&gt;
Nehmen wir an, wir brauchen eine Drossel mit 100µH, die wenigstens 10A aushält, bevor sie in die Sättigung geht. Nehmen wir an, wir nutzen einen Ringkern aus Eisenpulver dafür mit einem Querschnitt von 1cm^2 und einer Pfadlänge von 10cm. Die Permeabilität ist 75 und die Sättigung beginnt bei 0,5T, Der AL-Wert ist 80nH/N^2. Allein aus dem AL-Wert können wir leicht ausrechnen, daß wir 35 Windungen brauchen. Nun, wie können wir den Fluß ausrechnen? Letztendlich wird keine Spannung an die Wicklung angelegt! Denk noch mal nach! Es &#039;&#039;&#039;muß&#039;&#039;&#039; eine Spannung angelegt worden sein, um den Strom fließen lassen zu können. Wenn wir 1V anlegen, würde es bei 100µH 1ms dauern, ehe 10A erreicht werden, wie man aus Gleichung (3) leicht errechnen kann. Zusammen mit Hilfe von Gleichung (2) können wir die Flußdichte direkt berechnen&lt;br /&gt;
&lt;br /&gt;
::&amp;lt;math&amp;gt;B = \frac{L \cdot I}{A \cdot N}= \frac{100 \mu H \cdot 10A}{1 \cdot 10^{-4}m^2 \cdot 35}=0,28T&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
welche in einer Flußdichte von 0,28T endet in unserem Kern mit 1cm^2 Querschnitt. Bingo! Diese Drossel könnte fast das Doppelte an Strom leiten, bevor sie in die Sättigung geht. Ein kostenbewußter Entwickler würde die selbe Übung mit dem nächstkleineren Kern durchführen, welcher gerade groß genug ist, um die Drossel mit 100µH bei 10A zu erreichen.&lt;br /&gt;
&lt;br /&gt;
== Kernauswahl ==&lt;br /&gt;
&lt;br /&gt;
Es gibt unzählige Formen und Größen von magnetischen Kernen, und alle sind mit verschiedenen Materialien verfügbar. Es ist eine gute Idee, wenn man wenigsten prinzipiell weiß, was es gibt.&lt;br /&gt;
&lt;br /&gt;
===Materialien===&lt;br /&gt;
&lt;br /&gt;
Das älteste Material für Transformatoren ist &#039;&#039;&#039;Eisen&#039;&#039;&#039;, bekannt als [http://de.wikipedia.org/wiki/Dynamoblech Dynamoblech]. Es ist in dünnen Blechen verfügbar, welche voneinander isoliert werden müssen, um die Wirbelströme gering zu halten. Nur in reinen Gleichstromanwendungen kann man massives Eisen oder unisolierte Bleche nehmen. Transformatoreisen verträgt mindestens 1T bevor es in die Sättigung geht, während 1,2T für die meisten Typen OK ist, 1,5T für einige und 1,7T sind mit den Besten möglich. Die Permeabilität dieses Materials ist ca. 2000 bis 5000. Die Eisenlegierungen mit höherer Sättigungsgrenze haben die geringeren Werte. Die Verluste sind so hoch, daß sie für Frequenzen kurz über 100Hz der begrenzende Faktor sind, anstatt die Sättigung.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Eisenstaub&#039;&#039;&#039; wird auch genutzt, gemischt mit Epoxidharz und in Magnetkerne geformt. Die Permeabilität hängt vom Eisengehalt der Mischung ab. Da selbst eine kleine Menge Harz deutlich weniger Permeabilität als das Eisen hat, ist die effektive Permeabilität ziemlich niedrig, zwischen 2..100 sind typisch. Für höhere Permeabilitäten wird die Korngröße und Form des Eisen sehr wichtig, da man sehr enge Kornpackungen erzielen kann.&lt;br /&gt;
Sättigung setzt eher als bei massivem Eisen ein, weil der Fluß tendenziell aus den Eisenpartikeln gedrängt wird, 0,5T ist ein typischer Wert. Auf jeden Fall ist die Sättigung sehr &amp;quot;weich&amp;quot;, es gibt keinen gut definierten Punkt an dem die Sättigung einsetzt. Die Verluste sind niedrig, so daß die Typen mit geringer Permeabilität bis in den HF-Bereich verwendet werden können. Diese Pulverkerne gibt es auch mit anderen Legierungen, wie z.&amp;amp;nbsp;B. Permalloy, in einigen Fällen mit attraktiven Eigenschaften.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Ferrite&#039;&#039;&#039; sind die vielseitigsten aller verfügbaren Materialien. Während sie bei niedrigeren Werten sättigen, typisch 0,3T, gibt es sie in einer riesigen Breite von Permeabilitäten. Es ist nicht schwer Ferrite mit einer Permeabilität von 20 oder 25.000 zu finden! Der unerfahren Anwender kann den Unterschied  von Außen nicht erkennen. Selbst wenn zwei Ferritkerne identisch aussehen, kann der eine 1000fach verschieden zum anderen sein! Also sollte man sicherstellen, daß man &#039;&#039;&#039;weiß&#039;&#039;&#039;, welches Material man hat, bevor man mit der Rechnung anfängt.&lt;br /&gt;
&lt;br /&gt;
In jedem Fall gibt es zwei große Kategorien von Ferriten. Leistungsferrite, genutzt in Schaltnetzteilen etc., sie haben eine Permeabilität von etwa 2000 und geringe Verluste zwischen 20..100kHz. HF-Ferrite mit Permeabilitäten zwischen 100...1000 und geringen Verlusten machen sie brauchbar bis 30MHz. Aber es gibt viele Ferrittypen, die bei weit höheren Frequenzen noch arbeiten und weniger Permeabilität haben. Die Permeabilitäten über 2000 sind reserviert für spezielle Kerne wie Breitbandübertrager, Transductoren und Rauschfilter.&lt;br /&gt;
&lt;br /&gt;
=== Formen ===&lt;br /&gt;
&lt;br /&gt;
Bei den Formen will ich nur einige nennen.&lt;br /&gt;
&lt;br /&gt;
*Ringkerne: Sie sind einfach, billig und leicht zu nutzen, haben geringe Dispersion (wenig Streufeld), gute Selbstabschirmung, können aber keinen Luftspalt enthalten, und 10.000 Windungen auf einen Ringkern wickeln ist nichts was ich gern tun würde.&lt;br /&gt;
*Für Speicherdrosseln gibt es Ringkerne mit &amp;quot;verteiltem&amp;quot; Luftspalt. Sie bestehen aus Eisenpulver mit Bindemittel, der Luftspalt verteilt sich über den gesamten Ring&lt;br /&gt;
*E-Kerne: Sehr zweckmäßig für die meisten Anwendungen, aber die scharfen Ecken sorgen für mehr Streuverluste&lt;br /&gt;
* U-Kerne: Etwas billiger und leicht ineffizienter als E-Kerne (wegen der größeren Pfadlänge)&lt;br /&gt;
*Schalenkerne: Vereint die Zweckmäßigkeit des E-Kerns mit der guten Schirmung des Ringkerns (er ist sogar besser!), aber sie kosten mehr. Manche haben einen einstellbaren Luftspalt.&lt;br /&gt;
*Stäbe: Nutzbar für Drosseln. Sie haben wirklich große Luftspalte! ;-) Aus genau diesem Grund sind sie unbrauchbar für Transformatoren, die Kopplung wäre zu schlecht.&lt;br /&gt;
*E-I Laminate: Das ist so ziemlich die einzige Form, in der man Transformatoreisen kaufen kann.&lt;br /&gt;
&lt;br /&gt;
Ich empfehle man bestellt sich einige Kataloge der Hersteller von magnetischen Materialien und kann so mehr über die anderen 994 Formen lernen . . . Ich empfehle Amidon, Ferroxcube , Ferrinox (Thomson Composants), SiFerrit (Siemens), TDK, Philips, um einige zu nennen. Ich habe meist mit Amidon, Ferrinox und Mülleimerkernen gearbeitet. Die besten Leistungsdaten scheinen von einigen japanischen Ferriten zu kommen.&lt;br /&gt;
&lt;br /&gt;
Diese kleine Abhandlung des Elektromagnetismus kann natürlich nicht als vollständig betrachtet werden, aber ich bevorzuge es, mich auf die wichtigsten Dinge für den Entwickler bzw. Hobbybastler zu konzentrieren. Ich habe alle Dinge übersprungen, welche in meinen Augen weniger wichtig sind für die praktische Anwendung. Ich habe auch viele praktische Hinweise übersprungen, welche zwar nützlich wären, aber diesen Artikel zu sehr in ein Kochbuch verwandelt hätten. Wer Fragen hat soll nicht zögern. Meine Adresse ist auf der ersten [http://ludens.cl/index.html Seite]. Wenn genug Fragen auftauchen, werde ich ein F.A.Q. anfügen.&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
*[[Spule]]&lt;br /&gt;
*[[Platinen-Induktivität]]&lt;br /&gt;
*[[MC34063]]&lt;br /&gt;
*[[Spartransformator]]&lt;br /&gt;
*[http://www.mikrocontroller.net/topic/181036 Forumsbeitrag]: Kurzschlußwindung bei Ringkernmontage vermeiden&lt;br /&gt;
*[http://www.mikrocontroller.net/topic/172992?goto=2586118#2586118 Forumsbeitrag]: galvanisch getrennter DC/DC 5V/17mA mit Ethernettrafo&lt;br /&gt;
*[http://www.mikrocontroller.net/topic/172992?goto=2586118#2600216 Forumsbeitrag]: galvanisch getrennter DC/DC 8V/170mA mit Ethernettrafo&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.amidon.de/ Amidon], Hersteller von Kernen aller Art&lt;br /&gt;
* [http://www.ferroxcube.com/ Ferroxcube], Hersteller von Kernen aller Art&lt;br /&gt;
* [http://www.micrometals.com/ Micrometals], Hersteller von Kernen aller Art&lt;br /&gt;
* [http://www.epcos.de Epcos], ehemals Siemens, Hersteller von Kernen aller Art&lt;br /&gt;
* [http://www.ferrite.de ferrite.de], Händler für Kerne aller Art&lt;br /&gt;
* [http://www.tridelta-weichferrite.de/ TRIDELTA Weichferrite]&lt;br /&gt;
* [http://www.spulen.com/ MM Spulen für Elektronik] - Der Shop rund um die Spule - Drähte, Litzen, Ferrite, Spulen aller Art&lt;br /&gt;
* Sehr gute Erklärung der [[media:verlustarme_trafos.pdf | Wirkungsweise eines Trafos (PDF)]], [http://www.emeko.de/ Homepage] des Autors&lt;br /&gt;
* [http://www.wolfgang-wippermann.de/koppelfa.htm Koppelfaktor messen], mit Beispielen von realen Spulenanordnungen auf dem Amateurfunkbereich&lt;br /&gt;
* [http://www.dos4ever.com/flyback/flyback.html Flyback Converter for dummies], engl. Gute Seite über Sperrwandler und Drosselspulen für Nixieröhren mit einfacher Messung des Sättigungsstroms&lt;br /&gt;
* [http://www.joretronik.de/Web_NT_Buch/Kap1/Kapitel1.html Weitere Informationen zu 50-Hz-Trafos und Drosseln]&lt;br /&gt;
[[Category:Grundlagen]]&lt;br /&gt;
[[Category:Spannungsversorgung und Energiequellen]]&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Konstantstromquelle&amp;diff=67922</id>
		<title>Konstantstromquelle</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Konstantstromquelle&amp;diff=67922"/>
		<updated>2012-08-15T14:42:55Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: /* Beschreibung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Eine &#039;&#039;&#039;Konstantstromquelle&#039;&#039;&#039; ist eine Schaltung, deren Zweck es ist, den Strom durch eine Last (z.&amp;amp;nbsp;B. eine [[LED]]) möglichst konstant zu halten, das heißt Änderungen des Stroms durch Variationen der Betriebsspannung und/oder des Lastwiderstands entgegen zu wirken.&lt;br /&gt;
&lt;br /&gt;
Es gibt viele verschiedene Schaltungen, die zu diesem Zweck eingesetzt werden. Sie unterscheiden sich in ihrer Präzision, der minimalen und maximalen Betriebsspannung, und dem Bauteilaufwand. Es sollen hier nur einige besonders einfache Schaltungen vorgestellt werden.&lt;br /&gt;
&amp;lt;div class=&amp;quot;toclimit-2&amp;quot;&amp;gt;&lt;br /&gt;
__TOC__&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Konstantstromquelle mit J-FET ==&lt;br /&gt;
&lt;br /&gt;
=== Beschreibung ===&lt;br /&gt;
&lt;br /&gt;
Eine sehr einfache Konstantstromquelle lässt sich mit einem [[FET|JFET]] realisieren. Der resultierende Strom ist durch den verwendeten FET bestimmt, dabei wird die Eigenschaft genutzt, dass der JFET selbstleitend ist, also bei einer Gate-Source-Spannung von 0V seinen maximal möglichen Strom leitet und bei ansteigender negativer Gate-Source-Spannung U_GS den Drain-Source-Kanal zunehmend abschnürt. Es werden Bauteile angeboten, bei denen die Verbindung zwischen Gate und Source des FET schon intern vorgenommen wurde (Konstantstromdiode, engl. current regulator diode). Diese werden mit engeren Toleranzen gefertigt und erlauben daher eine genauere Definition des Stroms. Außerdem benötigen diese keinen Widerstand in der Sourceleitung und brauchen damit weniger Spannungsabfall zum Betrieb.&lt;br /&gt;
&lt;br /&gt;
=== Vorteile ===&lt;br /&gt;
&lt;br /&gt;
* Großer Betriebsspannungsbereich, nach oben nur durch die maximale Drain-Source-Spannung (V_DS) des FETs und seine maximale Verlustleistung begrenzt.&lt;br /&gt;
* Einfachster Aufbau&lt;br /&gt;
&lt;br /&gt;
=== Nachteile ===&lt;br /&gt;
&lt;br /&gt;
* Beeinflussung durch Toleranzen der Fertigungsparameter des FET, typ. +/- 10%&lt;br /&gt;
* hohe Sättigungsspannung über dem FET, typ. 1-3V&lt;br /&gt;
* nur mäßig temperaturstabil&lt;br /&gt;
* selbstleitende FETs für Ströme größer als 30mA sind selten und entsprechend teuer&amp;lt;ref&amp;gt;Es gibt aber einige Depletion-Mode Mosfets mit sehr hohen Sperrspannungen und z.T. auch grösseren Strömen.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Schaltung ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Konstantstrom.gif]]&lt;br /&gt;
&lt;br /&gt;
=== Weblinks ===&lt;br /&gt;
* [http://www.vishay.com/docs/70596/70596.pdf Vishay AN103 - The FET Constant-Current Source/Limiter]&lt;br /&gt;
* [http://www.elektronik-kompendium.de/sites/slt/0207011.htm ELKO: FET als Konstantstromquelle]&lt;br /&gt;
* [http://www.elektronik-kompendium.de/public/schaerer/curr2pol.htm ELKO: Der Transistor-LED-und der FET-Konstantstromzweipol]&lt;br /&gt;
* [http://home.arcor.de/slotracingtechnik/homepage/bd256b.htm Konstantstromquelle für Leuchtdioden mit dem BF256B]&lt;br /&gt;
* [[Mosfet-Übersicht#N-Kanal J-FET | Liste von J-FETs]]&lt;br /&gt;
* [http://search.datasheetcatalog.net/key/LM334 LM334] betagter, aber guter IC, programmierbare Konstantstromquelle mit 1µA-10mA, 0,8-1V Spannungsabfall&lt;br /&gt;
&lt;br /&gt;
== Konstantstromquelle mit bipolaren Transistoren ==&lt;br /&gt;
&lt;br /&gt;
[[Datei:Ksq.png|thumb|right|231px|U&amp;lt;sub&amp;gt;BE&amp;lt;/sub&amp;gt;-Konstantstromquelle]]&lt;br /&gt;
Die auch als U&amp;lt;sub&amp;gt;BE&amp;lt;/sub&amp;gt;-Konstantstromquelle bekannte Stromquelle funktioniert folgendermassen:&lt;br /&gt;
&lt;br /&gt;
Wenn die Spannung über R1 die Basis-Emitter-Flussspannung (verwendeter BC546: 0,6V) von T2 überschreitet, schaltet T2 durch. Dadurch wird die Basis von T1 geräumt und damit gesperrt. Der Strom durch T1 und damit die Spannung über R1 sinkt, wodurch T2 wieder zu sperren beginnt, was T1 wieder leiten lässt. So pendelt diese Schaltung auf die konstante BE-Spannung von ca. 0,6..0,7V – je nach verwendetem Transistor – über R1 ein. Weil R1 konstant ist hat dies einen  konstanten Strom durch T2 zur Folge.&lt;br /&gt;
R1 berechnet sich daher wie folgt:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\begin{align}&lt;br /&gt;
R &amp;amp; = \frac{U}{I}\\&lt;br /&gt;
R1 &amp;amp; = \frac{U_{BE,T2}}{I_{\text{soll}}} = \frac{0.6\text{V}}{I_{\text{soll}}}&lt;br /&gt;
\end{align}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
R2 wird so ausgelegt, dass T1 grundsätzlich sättigen kann. Siehe dazu [[Basiswiderstand]]. Ein guter Richtwert bei 5V Vcc ist 4,7kΩ.&lt;br /&gt;
&lt;br /&gt;
Anstatt &#039;&#039;&#039;T2&#039;&#039;&#039; kann auch eine Leuchtdiode verwendet werden, dazu den Basisanschluss weglassen. Die LED leuchtet auf, wenn die Stromquelle regelt, und verlischt bei Leerlauf. So lassen sich einfache Konstantstrom-Ladegeräte mit Kontrollanzeige aufbauen.&lt;br /&gt;
&lt;br /&gt;
Eine temperaturstabile Präzisions-Stromquelle entsteht durch Ersetzen von &#039;&#039;&#039;T2&#039;&#039;&#039; durch einen TL431[http://www.mikrocontroller.net/part/TL431].&lt;br /&gt;
&lt;br /&gt;
=== Vorteile ===&lt;br /&gt;
* gut bei niedriger Betriebsspannung, da Schaltung bereits mit kleiner Restspannung von&lt;br /&gt;
:: &amp;lt;math&amp;gt;U_{BE,T2}+U_{CE,T1} \approx 0{,}65\,\text{V}+0{,}15\,\text{V}&amp;lt;/math&amp;gt;&lt;br /&gt;
: am Transistor läuft und die Regelung auch dann erfolgt, wenn nur noch wenige hundert mV zwischen Kollektor und Emitter des Transistors T1 anliegen.&lt;br /&gt;
* Ausschließlich &amp;quot;Allerweltsteile&amp;quot;, d.h. kann aus Resten aus der Bastelkiste aufgebaut werden&lt;br /&gt;
&lt;br /&gt;
=== Nachteile ===&lt;br /&gt;
* nicht temperaturkompensiert. Strom schwankt um &lt;br /&gt;
:: &amp;lt;math&amp;gt;\frac{\Delta U_{BE}}{R1} \quad\text{ mit }\quad \Delta U_{BE} \left(\Delta\vartheta\right) \approx -1{,}7 \,\frac{\text{mV}}{\text{K}} \cdot \Delta\vartheta&amp;lt;/math&amp;gt;&lt;br /&gt;
: Das sind etwa 2,6% pro 10°C&lt;br /&gt;
&lt;br /&gt;
[[Datei:Ksq_2T_sim.svg|thumb|right|300px|Analyse bei steigender Versorgungsspannung]]&lt;br /&gt;
&lt;br /&gt;
=== Weblinks ===&lt;br /&gt;
* [http://www.elektronik-kompendium.de/sites/slt/0210253.htm ELKO: Transistor als Konstantstromquelle]&lt;br /&gt;
* [http://www.elektronik-kompendium.de/public/schaerer/currled.htm ELKO: Die Transistor-LED-Konstantstromquelle mit ein oder zwei Transistoren und Konstantstromquelle mit Bandgap und Opamp]&lt;br /&gt;
* [http://www.elektronik-kompendium.de/public/schaerer/curr2pol.htm ELKO: Der Transistor-LED-und der FET-Konstantstromzweipol]&lt;br /&gt;
* [http://www.ferromel.de/tronic_6.htm Verschiedene Konstantstromquellen mit Beschreibung]&lt;br /&gt;
* [http://www.elexs.de/kap5_9.htm Konstantstromquelle bei ELEXS]&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
== Konstantstromquelle mit Operationsverstärker und Transistor ==&lt;br /&gt;
&lt;br /&gt;
[[Datei:Ksq_opv.png|thumb|right|231px|Konstantstromquelle mit OPV und Bipolartransistor]]&lt;br /&gt;
&lt;br /&gt;
Der Strom, welcher konstant gehalten werden soll, wird durch R2 gemessen (Shunt). Der OPV arbeitet als Spannungsfolger und versucht, die Spannung am - Eingang so groß wie am + Eingang zu halten. Ist z.B. die Spanunng am - Eingang etwas kleiner als am + Eingang (Bruchteile von mV!), dann steigt die Ausgangsspannung des OPV um einige mV und erhöht damit die Basis-Emitter-Spannung von T1 und damit den Basisstrom. Dadurch fließt ein höherer Kollerktorstom, welcher wiederum einen höheren Spannungsabfall über R2 verursacht, bis die Spannungen am - und + Eingang des OPV wieder absolut gleich sind (die Offsetspannung wird hier zunächst vernachlässigt). Die Beispielschaltung hier ist bei ausreichender [[Kühlkörper|Kühlung]] für T1 für ca. 1A brauchbar. Der Strom wird mit 0-100mV eingestellt.&lt;br /&gt;
&lt;br /&gt;
Nachteilig ist, dass der Basisstrom von T1 nicht durch die Last fließt, aber durch R2 und somit die Konstantstromregelung verfälscht. Als Gegenmaßnahme nutzt man einen Darlingtontransistor mit sehr hoher Stromverstärkung von 1000 und mehr, was bedeutet, dass der verfälschende Basisstrom nur noch 1 Promille Fehler verursacht. Oder noch besser einen MOSFET, dieser hat Gateströme (Leckströme) im Bereich von unter einem Mikroampere. Dieser Fehler fällt bei 99,9% der Anwendungen nicht ins Gewicht. Prüfen sollte man dabei, dass der MOSFET für [[FET#Linearbetrieb_von_MOSFETs | Linearbetrieb]] geeignet ist, denn das sind viele Hochleistungs-MOSFETs nicht! Hier wird noch ein zusätzlicher Widerstand vor dem Gate des MOSFETs geschaltet, um die hohe Kapazität des Gates vom OPV-Ausgang zu entkoppeln, welche viele OPVs wieder instabil machen würde.&lt;br /&gt;
&lt;br /&gt;
[[Datei:Ksq_opv_mosfet.png|thumb|right|231px|Konstantstromquelle mit OPV und MOSFET]]&lt;br /&gt;
&lt;br /&gt;
Wichtig sind R1 und C1. In vielen Schaltungen im Internet fehlen sie, die Spannung über R2 geht direkt an den - Eingang des OPV. Das ist aber falsch und funktioniert oft nur durch Zufall. Denn R1 und C1 sind wichtig zu Frequenzgangkompensation des OPV. Die Schaltung ist ein Regelkreis und diese sind für notorische Instabilitäten bekannt, d.h. sie schwingen. Durch Rechnung oder Probieren muss der richtige Wert für R1 und C1 gefunden werden, bei der die Stromquelle ausreichend schnell regiert ohne zu schwingen. Testen kann man das u.a. dadurch, dass man einen Sprung auf den Eingang gibt, z.B. mit einem Funktionsgenerator oder einfach einem NE555 als Taktgeber. Dabei beobachtet man die Spannung über R2 mit dem Oszilloskop, ggf. auch am Ausgang des OPV. Hier sieht man wie schnell die Stromquelle reagiert und ob sie schwingt.&lt;br /&gt;
&lt;br /&gt;
=== Vorteile ===&lt;br /&gt;
* Größe Ströme können sehr genau und schnell geregelt werden, nur durch T1 und dessen Kühlung begrenzt&lt;br /&gt;
* einfacher Aufbau mit Standardkomponenten&lt;br /&gt;
* wird oft als Stromregler in elektronischen Lasten benutzt&lt;br /&gt;
&lt;br /&gt;
=== Nachteile ===&lt;br /&gt;
* bei sehr hohen Stömen muss man eine Vierdrahtmessung an R2 vornehmen&lt;br /&gt;
* hohe Verlustleistung bei kleinen Lastwiderständen und hoher Betriebsspannung (lineare Stromquelle)&lt;br /&gt;
* nur Einquadrantenbetrieb möglich&lt;br /&gt;
&lt;br /&gt;
=== Weblinks ===&lt;br /&gt;
*Analog by Design Show - Hosted by Bob Pease&lt;br /&gt;
** [http://www.youtube.com/watch?v=411f0DvXu18 Konstantstromquellen]&lt;br /&gt;
** [http://www.youtube.com/watch?v=2N6cjGS7lUE Präzise 1A Konstantstromquelle ]&lt;br /&gt;
&lt;br /&gt;
== Stromspiegel als Konstantstromquelle ==&lt;br /&gt;
&lt;br /&gt;
[[Datei:Stromspiegel als Konstantstromquelle.svg|miniatur|Stromspiegel mit Widerstand]]&lt;br /&gt;
Bei stabiler Versorgungsspannung eignet sich ein Stromspiegel mit Widerstand als Spannungs-Stromwandler und findet sich beispielsweise in älteren Operationsverstärkern wie dem LM741. Das Konzept des Stromspiegels wird an dieser Stelle nicht weiter erläutert.&lt;br /&gt;
&lt;br /&gt;
Die Widerstände R2 und R3 reduzieren die Auswirkungen von Bauteiltoleranzen und der Temperaturdrift. Als grober Richtwert sollte deren Spannungsabfall 0,2 V oder mehr betragen. T1 und T2 sind identische Transistortypen (z.B. BC557B), die idealerweise von einer Bauteilrolle stammen.&lt;br /&gt;
&lt;br /&gt;
Bei geeigneter Wahl von R2 und R3 oder Parallelschaltung von Transistoren wird aus dem Stromspiegel ein Stromvervielfacher. Bei gleichen Transistoren und gleichen Widerständen entsteht ein 1:1 Stromspiegel.&lt;br /&gt;
&lt;br /&gt;
Berechnung:&lt;br /&gt;
&lt;br /&gt;
U&amp;lt;sub&amp;gt;B&amp;lt;/sub&amp;gt; und der gewünschte Strom I sind bekannt&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;I_{ref} = \frac{U_B - 0{,}65 V}{R1+R2}&amp;lt;/math&amp;gt; (Ausgangsformel)&lt;br /&gt;
:&amp;lt;math&amp;gt;R3 = R2&amp;lt;/math&amp;gt; (1:1 Stromspiegel)&lt;br /&gt;
:&amp;lt;math&amp;gt;I = I_{ref}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;R1 + R2 = R_g = \frac{U_B - 0{,}65 V}{I}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;U_{R2} \approx 0{,}2 V&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;R2 = \frac{U_{R2}}{I}=\frac{0{,}2 V}{I}&amp;lt;/math&amp;gt;&lt;br /&gt;
:&amp;lt;math&amp;gt;R1 = R_g - R2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Vorteile ===&lt;br /&gt;
&lt;br /&gt;
* wenige, günstige Bauteile&lt;br /&gt;
* sehr einfache Konstruktion&lt;br /&gt;
* mäßiger Spannungsabfall (ca. 1V)&lt;br /&gt;
* schnell da keine ausgeprägte Rückkopplung vorhanden&lt;br /&gt;
* zur Stromsenke umformbar (Überkopf stellen und npn-Typen verwenden)&lt;br /&gt;
&lt;br /&gt;
=== Nachteile ===&lt;br /&gt;
&lt;br /&gt;
* geringer Wirkungsgrad, doppelt wegen Referenzstrom&lt;br /&gt;
* mäßig hoher Quellenwiderstand (einfacher Stromspiegel)&lt;br /&gt;
&lt;br /&gt;
== PTAT-Konstantstromquelle ==&lt;br /&gt;
&lt;br /&gt;
:→ siehe  [[PTAT-Stromquelle]]&lt;br /&gt;
&lt;br /&gt;
== Konstantstromquelle mit Linearreglern ==&lt;br /&gt;
&lt;br /&gt;
=== Grundschaltung mit LM317 ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:LM317_constant_current.png|thumb|right|280px|Konstantstromquelle mit LM317]]&lt;br /&gt;
&lt;br /&gt;
Eine sehr einfache, günstige und doch genaue Konstantstromquelle kann mittels LM317 aufgebaut werden. Für einen LED Strom von 20mA ist ein R1 von 62,5 Ω erforderlich, praktisch wird man 68Ω wählen. Dabei ist zu beachten, daß die Eingangsspannung &#039;&#039;V&#039;&#039;&amp;lt;sub&amp;gt;in&amp;lt;/sub&amp;gt; mindestens 3,5V + &#039;&#039;U&#039;&#039;&amp;lt;sub&amp;gt;f,LED&amp;lt;/sub&amp;gt; (Flußspannung der LED) betragen muss.&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
==== Vorteile ====&lt;br /&gt;
&lt;br /&gt;
* temperaturstabil&lt;br /&gt;
* sehr wenige, billige Bauteile&lt;br /&gt;
&lt;br /&gt;
==== Nachteile ====&lt;br /&gt;
&lt;br /&gt;
* Überschwinger beim Einschalten können vorkommen, so dass sensible Lasten zerstört werden können.&lt;br /&gt;
* Hohe Spannungsabfall über der Schaltung von mind. 3,5V&lt;br /&gt;
* Verlustleistung&lt;br /&gt;
:: &amp;lt;math&amp;gt;PV_\text{LM317} = I_\text{out}\cdot (V_\text{in}- U_\text{f,LED} -1,25\,\mathrm V)&amp;lt;/math&amp;gt;&lt;br /&gt;
* Abhängig vom Gehäuse ist bei höheren Eingangsspannungen ein Kühlkörper am LM317 nötig:&lt;br /&gt;
** TO220: 1W&lt;br /&gt;
** TO92: 500mW&lt;br /&gt;
** SO-8: 600mW&lt;br /&gt;
* Bei niedrigen Strömen unter 3.5 mA ungenau (min. Load Current 3.5 mA laut Datenblatt)&lt;br /&gt;
&lt;br /&gt;
==== Schrittweise einstellbare Variante ====&lt;br /&gt;
&lt;br /&gt;
Eine schrittweise voreinstellbare Variante der Grundschaltung wurde 2008 von einem Mitarbeiter von National Semiconductor (Hersteller des LM317) im EDN-Magazin vorgestellt: [http://www.edn.com/contents/images/6566536.pdf Programmable current source requires no power supply]. Dabei ist hier mit &#039;&#039;programmable&#039;&#039; manuell voreinstellbar gemeint, nicht Mikrocontroller-gesteuert. Auch der Teil des Titles &#039;&#039;requires no power supply&#039;&#039; ist irreführend. Die Konstantstromquelle benötigt sehr wohl eine externe Stromversorgung. Die Schaltung benötigt lediglich keine zusätzlichen Hilfsspannungen, entspricht sie doch der oben genannten Grundschaltung.&lt;br /&gt;
&lt;br /&gt;
Mittels dreier 0−9 BCD-Schalter werden geschickt gewählte Widerstände zwischen ADJ und OUT parallel geschaltet. Die Widerstände sind so gewählt, dass der erste Schalter mit seinen zehn Stellungen und Widerständen zwischen 0 mA und 9 mA in 1 mA Schritten zum Gesamtstrom beiträgt, der zweite 0 mA bis 90 mA in 10 mA Schritten und der dritte 0 mA bis 900 mA in 100 mA Schritten. &lt;br /&gt;
&lt;br /&gt;
In dieser Kombination ergibt das eine einstellbare Konstantstromquelle bis 999 mA in 1mA-Schritten bei rund 2% Genauigkeit.&lt;br /&gt;
&lt;br /&gt;
Insgesamt werden &lt;br /&gt;
&lt;br /&gt;
* 45 Widerstände, alle 1%, 1/4 W&lt;br /&gt;
** 15 × 1,24 kΩ&lt;br /&gt;
** 15 × 124 Ω&lt;br /&gt;
** 15 × 12,4 Ω&lt;br /&gt;
* ein LM317&lt;br /&gt;
* drei 0−9 BCD-Schaltern und&lt;br /&gt;
* Gehäusematerial (Gehäuse, Kühlkörper für den LM317, Polklemmen, ...)&lt;br /&gt;
benötigt.&lt;br /&gt;
&lt;br /&gt;
Der LM317 wird bei dieser einstellbaren Stromquelle gerade noch innerhalb seiner Spezifikation betrieben - wenn man den Spannungsabfall über ihn gering hält. Im Stromquellen-Beispiel im Datenblatt wird ein maximaler Widerstand von 120 Ω genannt, wohingegen die einstellbare Stromquelle bis zu 1,24 kΩ (nominell 1 mA Ausgangsstrom) und ∞ Ω (offen, nominell 0 mA Ausgangsstrom) verwendet. Mit etwas Geduld kann man aus dem Datenblatt herauslesen, dass 1,24 kΩ gerade noch ausreichen, damit die Regelung des LM317 nicht aussetzt. Dies findet man im Datenblatt in der Graphik &#039;&#039;Minimum Operating Current&#039;&#039; und im Beispiel &#039;&#039;1.2V-20V Regulator with Minimum Program Current&#039;&#039;. Mit ∞ Ω ist man definitiv außerhalb des Arbeitsbereiches.&lt;br /&gt;
&lt;br /&gt;
Der Strom bei der Einstellung 000 mA (Widerstand → ∞ Ω, d.h. offen) entspricht nicht 0,0 mA, sondern dem Strom aus dem ADJ-Anschluss für den nicht spezifizierten Fall, dass der LM317 außerhalb seines Arbeitsbereiches betrieben wird. Die im Datenblatt angegebenen 50 µA (typ.), 100 µA (max.) für den Arbeitsbereich können dabei je nach Exemplar überschnitten werden und sind nicht konstant. &lt;br /&gt;
&lt;br /&gt;
Die Messung an neueren Chargen (gefertigt nach 2006) des LM317 diverser Hersteller zeigt, dass auch 1mA nicht sicher erreichbar sind. Es ist vielmehr so, das diese KSQ erst korrekt ab 003 mA bis hoch zu den 999 mA funktioniert. Das heißt konkret, die Einstellungen 000 mA, 001 mA und 002 mA sind nicht mehr stromstabilsiert. Das sollte man beachten, sofern man unbedingt den LM317 bei sehr kleinen Strömen einsetzen möchte.&lt;br /&gt;
&lt;br /&gt;
In der Praxis lohnt es sich besonders bei kleinen Strömen ein Strommessgerät in Reihe zu schalten. Dabei ist Vorsicht bei billigen Multimetern geboten&amp;lt;ref&amp;gt;Bei billigen Multimetern ist auch aus anderen Gründen immer Vorsicht geboten. Siehe [http://gps.sozialnetz.de/global/show_document.asp?id=aaaaaaaaaaaajxn Schwerpunktaktion „Handmultimeter“ der hessischen Marktüberwachung ...]&amp;lt;/ref&amp;gt;. Deren niedrige Strommessbereichen sind häufig mit einer 200 mA oder 250 mA Schmelzsicherung abgesichert. Schaltet man die Stromquelle versehentlich über 200 mA, beziehungsweise 250 mA, ist ein Sicherungswechsel fällig.&lt;br /&gt;
&lt;br /&gt;
==== Weblinks ====&lt;br /&gt;
&lt;br /&gt;
* National Semiconductor Datenblatt [http://www.national.com/ds/LM/LM117.pdf LM117/LM317A/LM317 3-Terminal Adjustable Regulator]&lt;br /&gt;
* [http://www.roboternetz.de/phpBB2/konstantstrom.php Passenden Widerstand für Konstantstromschaltung mit LM317 berechnen]&lt;br /&gt;
* [http://www.lumitronixforum.de/viewtopic.php?t=2611&amp;amp;highlight=lm317 Einfachste Konstantstromquelle mit dem LM317]&lt;br /&gt;
* [http://www.umnicom.de/Elektronik/Schaltungssammlung/Strom/Quelle/Stromquelle.html Konstantstromquelle bis 3A mit LM2576]&lt;br /&gt;
*[http://www.edn.com/contents/images/6566536.pdf Programmable current source requires no power supply]&lt;br /&gt;
&lt;br /&gt;
==== Preise ====&lt;br /&gt;
&lt;br /&gt;
; LM317:&lt;br /&gt;
* TO3: 1,90 €&lt;br /&gt;
* TO-220: &amp;lt; 0,25 €&lt;br /&gt;
* TO-92: &amp;lt; 0,15 €&lt;br /&gt;
* SO-8: &amp;lt; 0,20 €&lt;br /&gt;
&lt;br /&gt;
=== Andere Linearregler ===&lt;br /&gt;
&lt;br /&gt;
Der zuvor beschriebene LM317 eignet sich besonders gut als Stromquelle, da er seine Regelspannung auf der &#039;high-side&#039; erwartet (1,25 V zwischen Vout und ADJ) und man den Regelpfad als Konstantstrompfad missbrauchen kann (ADJ als Ausgang nach GND, wobei der Strom über den Widerstand und nicht von ADJ geliefert wird)).&lt;br /&gt;
&lt;br /&gt;
==== Mittels Shunt und Messverstärker ====&lt;br /&gt;
&lt;br /&gt;
Die meisten anderen Linearregler messen ihre Regelspannung im Bezug auf GND. Um einen solchen Regler als Konstantstromquelle zu benutzen, kann man einen Stromsensor und einen Messverstärker verwenden. Letzterer steuert dann die Regelung des Linearreglers. Maxim hat in [http://www.maxim-ic.com/app-notes/index.mvp/id/921] ein Beispiel veröffentlicht, das so oder so ähnlich auch mit anderen Linearreglern funktioniert. Maxim misst den Strom auf der Eingangsseite. Vorteil: der Innenwiderstand des Ausgangs des Linearreglers wird durch den Messwiderstand nicht erhöht. Nachteil: Der Eigenverbrauch des Linearreglers wird mitgemessen.&lt;br /&gt;
&lt;br /&gt;
Man kann den Strom auch auf der Ausgangsseite messen.&lt;br /&gt;
&lt;br /&gt;
Das gleiche Prinzip funktioniert für Schaltregler, siehe zum Beispiel [[#LM2576_Step_Down| LM2576 Step Down]] auf dieser Seite.&lt;br /&gt;
&lt;br /&gt;
==== Im Regelpfad - High-Side ====&lt;br /&gt;
&lt;br /&gt;
              .-----------.&lt;br /&gt;
 VCC       IN |           | OUT&lt;br /&gt;
  ------------o           o------&amp;gt;----.&lt;br /&gt;
              |           |      I    |                 |&lt;br /&gt;
              |           |           |                 |&lt;br /&gt;
              |           |          .-.                |&lt;br /&gt;
              |           |          | |                |&lt;br /&gt;
              |           |          | |  Rload, R1     |&lt;br /&gt;
              |           |          &#039;-&#039;                |&lt;br /&gt;
              |           |           |                 |&lt;br /&gt;
              |           | FB        |                 |&lt;br /&gt;
              |           o------&amp;lt;----o                 |Vout&lt;br /&gt;
              |           |    Iref   |        |        |&lt;br /&gt;
              |           |           |        |        |&lt;br /&gt;
              |           |          .-.       |        |&lt;br /&gt;
              |           |          | |       | Vref   |&lt;br /&gt;
              |           |          | |  R2   |        |&lt;br /&gt;
              &#039;-----o-----&#039;          &#039;-&#039;       |        |&lt;br /&gt;
                    | GND             |        |        |&lt;br /&gt;
                    |                 |        |        |&lt;br /&gt;
                   ===               ===       v        v&lt;br /&gt;
                   GND               GND&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
                             Iref &amp;lt;&amp;lt; I&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die meisten einstellbaren Linearregeler werden durch einen Spannungsteiler (R&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt;, R&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;) zwischen Ausgangsspannung (V&amp;lt;sub&amp;gt;out&amp;lt;/sub&amp;gt;) und Masse (GND) eingestellt. Der Spannungsteiler wird dabei so dimensioniert, dass eine vorgegebene Spannung V&amp;lt;sub&amp;gt;ref&amp;lt;/sub&amp;gt; (meist 1,25 V) gegen GND an der Anzapfung des Spannungsteilers abfällt, die dann zum Regeleingang des Linearreglers geführt wird. Dabei wird üblicherweise angenommen, dass der Strom I&amp;lt;sub&amp;gt;ref&amp;lt;/sub&amp;gt; in den Regler hinein vernachlässigbar ist.&lt;br /&gt;
&lt;br /&gt;
Dann gilt für den Strom I im Spannungsteiler:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;I = I_{R_1} = I_{R_2} = \frac{V_\text{out}}{R_1 + R_2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;I_{R_2} = \frac{V_\text{ref}}{R_2}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Strom I im Spannungsteiler ist somit alleine durch Wahl von R&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; bestimmt und unabhängig von R&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; bei vorgegebenem R&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Ersetzt man daher R&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; durch die Last, so erzeugt der Linearregler durch Steuerung von V&amp;lt;sub&amp;gt;out&amp;lt;/sub&amp;gt; einen konstanten Strom&lt;br /&gt;
&lt;br /&gt;
:{|cellpadding=&amp;quot;2&amp;quot; style=&amp;quot;border:2px solid #ccccff&amp;quot;&lt;br /&gt;
|&amp;lt;math&amp;gt;I = \frac{V_\text{ref}}{R_2}&amp;lt;/math&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
durch die Last.&lt;br /&gt;
&lt;br /&gt;
Dabei muss man die Grenzen des Linearreglers beachten:&lt;br /&gt;
&lt;br /&gt;
Der maximale Strom &#039;&#039;I&#039;&#039;&amp;lt;sub&amp;gt;max&amp;lt;/sub&amp;gt; des Reglers darf nicht überschritten werden. Damit die Annahme gilt, dass der Reglerstrom &#039;&#039;I&#039;&#039;&amp;lt;sub&amp;gt;ref&amp;lt;/sub&amp;gt; gegenüber dem Strom &#039;&#039;I&#039;&#039; im Spannungsteiler vernachlässigbar ist muss R&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; klein gegenüber dem Innenwiderstand des Regeleingangs sein. Dass bedeutet, dass R&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt; so zu wählen ist, dass immer gilt:&lt;br /&gt;
&lt;br /&gt;
:{|cellpadding=&amp;quot;2&amp;quot; style=&amp;quot;border:2px solid #ccccff&amp;quot;&lt;br /&gt;
|&amp;lt;math&amp;gt;\frac{V_\text{ref}}{I_\text{max}} \leqq R_2 \ll R_\text{in,ref} = \frac{V_\text{ref}}{I_\text{ref}}&amp;lt;/math&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Es muss ein Minimalstrom &#039;&#039;I&#039;&#039;&amp;lt;sub&amp;gt;min&amp;lt;/sub&amp;gt; durch den Spannungsteiler fließen, damit die Regelung nicht aussetzt. Für diesen Strom gilt gegenüber dem Regelstrom &#039;&#039;I&#039;&#039;&amp;lt;sub&amp;gt;ref&amp;lt;/sub&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;I_\text{min} = \frac{V_\text{out,min}}{R_1 + R_2} \gg I_\text{ref}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;V_\text{out,min} = V_\text{ref}\,&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
folgt&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;R_1 \ll \frac{V_\text{ref}}{I_\text{ref}} - R_2 = R_\text{in,ref} - R_2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Angenähert:&lt;br /&gt;
&lt;br /&gt;
:{|cellpadding=&amp;quot;2&amp;quot; style=&amp;quot;border:2px solid #ccccff&amp;quot;&lt;br /&gt;
|&amp;lt;math&amp;gt;R_\text{load} \approx R_1 \ll \frac{V_\text{ref}}{I_\text{ref}}&amp;lt;/math&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Neben diesen Einschränkungen ist auch zu beachten, dass Die Last R&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; auf der High-Side hängt und nicht gegen GND.&lt;br /&gt;
&lt;br /&gt;
== Konstantstromquelle mit Schaltregler ==&lt;br /&gt;
Am günstigsten erscheinen Tiefsetzsteller (StepDown-Schaltregler), die mit einer großen Drossel im nichtlückenden Bereich arbeiten. Dann ist der Strom-Ripple (Wechselspannungsanteil) durch die Induktivität und Schaltfrequenz vorgegeben. Ein weiters Glätten des Stromes ist dann gar nicht mehr erforderlich. Es sind nahezu beliebig große Gleichströme bereitstellbar.&lt;br /&gt;
=== MC34063, Step Up ===&lt;br /&gt;
==== Beschreibung ====&lt;br /&gt;
Der Ausgangsstrom beträgt 1,25V/Rx. Die Stromquelle ist &#039;&#039;&#039;nicht&#039;&#039;&#039; kurzschlussfest. Der Widerstand Rsc dient der Strombegrenzung der einzelnen Strompulse (Schaltregler), was u.a. einen gewissen Überlastschutz für den MC34063 darstellt. Rsc = 0.3/I_max, wobei I_max der maximale Pulsstrom ist und dieser kleiner 1.5A sein muss, weil der IC nicht mehr hergibt. In den meisten Anwendung nimmt man hier 0,22Ω oder mehr. &lt;br /&gt;
Das Ganze kann man z.&amp;amp;nbsp;B. für mehrere LEDs in Reihe verwenden um diese mit&lt;br /&gt;
5V oder mit 4x 1,5V Batterien zu betreiben. Weiterhin ist zu beachten,&lt;br /&gt;
dass die Schaltung nicht leerlauffest ist: Im Leerlauf läuft die&lt;br /&gt;
Spannung auf &amp;gt;40V, und dann geht der MC34063 kaputt. Daher sollte man&lt;br /&gt;
zur Sicherheit eine Z-Diode parallel zum Ausgang legen, deren Z-Spannung 2..3V über der maximal zu erwartenden Ausgangsspannung liegt, wenn es&lt;br /&gt;
passieren kann, dass die Last abgeklemmt wird.&lt;br /&gt;
Aufgrund des Elkos am Ausgang ist die Stromquelle recht träge. R1 dient dazu den MC34063 vor dem Stromstoß zu schützen, wenn sich der Elko in eine zu kleine Last entlädt und der Strom kurzzeitig höher als der eingestellte Wert wird.&lt;br /&gt;
Die Bauteilwerte sind alle relativ unkritisch. Je nach Betriebsspannung sind die Bauteilwerte etwas anzupassen um den optimalen Wirkungsgrad und die beste Performance zu erzielen. Die eingezeichneten Bauteilwerte sind für geringe Ströme (&amp;lt;100mA) und Eingangsspannungen zwischen 5 und 15V ausgelegt. R2 sollte bei hohen Spannungen vergrößert werden. Wie man die Werte genau berechnet, steht in der Application Note AN920/D.&lt;br /&gt;
http://www.onsemi.com/pub/Collateral/AN920-D.PDF&lt;br /&gt;
&lt;br /&gt;
Stromquellen sollten grundsätzlich &#039;&#039;keinen&#039;&#039; Ausgangselko aufweisen! Wie die Schaltregler-Schaltung dann stabil arbeitet muss gesondert herausgefunden werden.&lt;br /&gt;
&lt;br /&gt;
==== Schaltung ====&lt;br /&gt;
&lt;br /&gt;
[[Bild:mc34063_constant_current.gif]]&lt;br /&gt;
&lt;br /&gt;
==== Vorteile ====&lt;br /&gt;
* überschüssige Spannung wird nicht verheizt&lt;br /&gt;
&lt;br /&gt;
==== Nachteile ====&lt;br /&gt;
* nicht kurzschlussfest&lt;br /&gt;
* ohne Z-Diode D2 nicht leerlauffest&lt;br /&gt;
* träge beim Einschalten&lt;br /&gt;
&lt;br /&gt;
=== MC34063, Step Down ===&lt;br /&gt;
==== Beschreibung ====&lt;br /&gt;
&lt;br /&gt;
Die Step-Down Version funktioniert im Prinzip genauso wie die normale, lineare Konstantstromquelle, nur dass die ungenutzte Spannung nicht sinnlos verheizt wird. Die Eingangsspannung muss mindestens 2V größer sein als die Ausgangsspannung.&lt;br /&gt;
&lt;br /&gt;
Diese Version ist auch ohne die Z-Diode leerlauffest. Kurzschlussfest wird sie durch Rsc. Allerdings entlädt sich der Elko erstmal in die Last, wenn man diese im Betrieb anklemmt. Dadurch kann die Last und der MC34063 beschädigt werden, der Widerstand R1 verhindert aber letzteres.&lt;br /&gt;
&lt;br /&gt;
Bei der Step-Down Version kann man die Elkos etwas kleiner machen, als bei der Step-Up Version, da der Stromfluss durch die Spule in die Last nahezu konstant ist. Wenn man die Spule vergrößert, wird der Strom gleichmäßiger und man kann die Elkos verkleinern. Allerdings wird der Wirkungsgrad aufgrund des höheren Gleichstromwiderstands der Spule schlechter und die Schaltung reagiert langsamer auf Laständerungen. Wie immer ist es also ein Kompromiss zwischen Wirkungsgrad, Kosten und Bauteilgröße.&lt;br /&gt;
&lt;br /&gt;
Konstantstromregler sollten grundsätzlich &#039;&#039;keinen&#039;&#039; Ausgangskondensator haben, weil dieser den gewünschten Regeleffekt zunichte macht. Wie die Rückführung zum Regelverstärker im Schaltregler regelschwingungsfrei gemacht wird muss dann gesondert herausgefunden werden.&lt;br /&gt;
&lt;br /&gt;
==== Schaltung ====&lt;br /&gt;
&lt;br /&gt;
[[Bild:mc34063_constant_current_2.gif]]&lt;br /&gt;
&lt;br /&gt;
==== Vorteile ====&lt;br /&gt;
* überschüssige Spannung wird nicht verheizt&lt;br /&gt;
* leerlauf &lt;br /&gt;
* kurzschlussfest&lt;br /&gt;
&lt;br /&gt;
==== Nachteile ====&lt;br /&gt;
* träge beim Ausschalten&lt;br /&gt;
&lt;br /&gt;
Besser ist hier eine [[Konstantstromquelle fuer Power LED]].&lt;br /&gt;
&lt;br /&gt;
=== LM2576 Step Down ===&lt;br /&gt;
In einem Thread im Forum (http://www.mikrocontroller.net/topic/97838#new) wird folgende Schaltung genannt: http://www.mikrocontroller.net/attachment/34179/current_source.pdf &lt;br /&gt;
Vollständiger Artikel: http://www.ednasia.com/article-621-switchingregularformsconstantcurrentsource-Asia.html&lt;br /&gt;
&lt;br /&gt;
== Konstantstromquelle mit Komparatoren ==&lt;br /&gt;
=== Einfache Abwärtswandlung (Vout &amp;lt; Vin)===&lt;br /&gt;
&lt;br /&gt;
==== Beschreibung ====&lt;br /&gt;
&lt;br /&gt;
Diese Schaltung wurde eigentlich für 1W LEDs entworfen, kann aber sicherlich auch anderweitig verwendet werden. Sie ähnelt sehr der eines vollintegrierten Schaltreglers wie MC34063 oder LM2576, ohne jedoch einen solchen zu verwenden.&lt;br /&gt;
Der Komparator vergleicht den Spannungsabfall über einem Shunt mit dem einer Referenzspannungsquelle. Ist die Spannung über dem Shunt zu groß, so schaltet er ab und der P-Kanal MOSFET sperrt. Umgekehrt, ist die Spannung über dem Shunt kleiner als die Referenzspannung, leitet der P-FET. Q4 arbeitet als [[Konstantstromquelle]] und sorgt dafür, dass die Gateansteuerung auch bei unterschiedlichen Versorgungsspannungen immer gleich bleibt. Die Referenzspannung von 100mV wird hier einfach durch eine Z-Diode und einen Spannungsteiler eingestellt. Für D4 muss eine schnelle Diode eingesetzt werden, entweder eine Schottkydiode oder schnelle Siliziumdiode! Q2 und Q3 dienen als sehr einfacher [[FET|MOSFET]]-[[Treiber]]. D3 ist nur aus Sicherheitsgründen vorhanden, um die Gate-Source Spannung des MOSFETs zu begrenzen, sie kann ggf. auch weggelassen werden. Über den Anschluß PWM kann ein invertiertes [[PWM]]-Signal zur Dimmung eingespeist werden. Hierbei muss das PWM-Signal im HIGH-Zustand größer als ca. 1V sein, ein einfaches 3,3V oder 5V Logiksignal ist also voll OK.&lt;br /&gt;
&lt;br /&gt;
Der Ausgangsstrom kann durch Veränderung von R1 eingestellt werden. Der Wert kann einfach über die Formel&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;I_{aus}=\frac{V_{Ref}}{R1} = \frac{100mV}{R1}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
bestimmt werden.&lt;br /&gt;
&lt;br /&gt;
==== Schaltung ====&lt;br /&gt;
&lt;br /&gt;
Platinendatei im Eagle-Format gibt es [http://www.mikrocontroller.net/wikifiles/3/38/LED_Stromregler.sch hier].&lt;br /&gt;
&lt;br /&gt;
[[Bild:LED_Stromregler.png|thumb|left|600px| Einfacher Stromregler aus Standardbauteilen]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:LED_Stromregler_brd.png|thumb|left|600px| Beispiel eines Platinenlayouts]]&lt;br /&gt;
&lt;br /&gt;
{{clear}}&lt;br /&gt;
&lt;br /&gt;
==== Vorteile ====&lt;br /&gt;
&lt;br /&gt;
* Kurzschlussfest&lt;br /&gt;
* guter Wirkungsgrad bei hohen Eingangsspannungen, Energie wird nicht wie bei einem Linearregler in Wärme umgesetzt&lt;br /&gt;
* einfachste Komponenten&lt;br /&gt;
* sehr preiswert, max. 2 EUR &lt;br /&gt;
* Dimmung per [[PWM]] möglich&lt;br /&gt;
* Eingangsspannungsbereich sehr groß, ca. 6-30V&lt;br /&gt;
* sehr einfach auch auf anderen Strom einstellbar&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
== Platzhalter == &lt;br /&gt;
=== Beschreibung ===&lt;br /&gt;
=== Vorteile ===&lt;br /&gt;
=== Nachteile ===&lt;br /&gt;
=== Schaltung ===&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Threads im Forum  ==&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/75355#new Philosophiestunde Konstantstromquelle]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/71573#new Suche regelbare Konstantstromquelle für ACULED]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/67593#new Konstantstrom für Windmessung]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/66825#new Konstantstromdiode]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/66033#new Konstantstromquelle als IC und einstellbar]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/59467#new Konstantstromquelle für einen Haufen LEDs]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/58036#new Konstantstromquelle]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/61778#new temperaturunabhängige Konstantstromquelle]&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/45039#new Konstanter Strom für LED bei 2,5V bis 5,5V]&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* [http://de.wikipedia.org/wiki/Konstantstromquelle Konstantstromquelle bei Wikipedia]&lt;br /&gt;
* [http://www.dse-faq.elektronik-kompendium.de/dse-faq.htm DSE FAQ]&lt;br /&gt;
* [http://www.led-treiber.de Seite zu LED Treibern]&lt;br /&gt;
* [http://www.christiankoch.de/archiv/led-ksq/ Diskrete LED-Konstantstromquelle auf Schaltregler-Basis]&lt;br /&gt;
* [http://www.national.com/an/AN/AN-1392.pdf NATIONAL Application Note 1392: LM3485 LED Demo Board]&lt;br /&gt;
* [http://www.circuit-fantasia.com/circuit_stories/understanding_circuits/current_source/howland_current_source/howland_current_source.htm Howland Current Source]&lt;br /&gt;
* [http://www.national.com/an/AN/AN-1515.pdf &amp;quot;A Comprehensive Study of the Howland Current Pump&amp;quot;, Application Note von National Semiconductior, engl.]&lt;br /&gt;
* [http://www.nomad.ee/micros/mc34063a/index.shtml MC34063A Design Tool (engl.)]&lt;br /&gt;
* [http://www.onsemi.com/pub_link/Collateral/MC34063A-D.PDF Datenblatt des MC34063 bei ON Semi]&lt;br /&gt;
* [http://www.stromflo.de/dokuwiki/doku.php?id=led_tutorial LED_Tutorial]&lt;br /&gt;
* [[Konstantstromquelle fuer Power LED]]&lt;br /&gt;
* [http://www.joretronik.de/Web_NT_Buch/Kap3/Kapitel3_2.html weitere Beispiele von Konstantstromquellen]&lt;br /&gt;
&lt;br /&gt;
== Fußnoten ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;references /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Spannungsversorgung und Energiequellen]]&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR-Tutorial:_ADC&amp;diff=67034</id>
		<title>AVR-Tutorial: ADC</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR-Tutorial:_ADC&amp;diff=67034"/>
		<updated>2012-06-26T09:32:42Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: Rechnung falsch da auf 1024 gerechnet wurde.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Was macht der ADC? ==&lt;br /&gt;
&lt;br /&gt;
Wenn es darum geht, Spannungen zu messen, wird der Analog-/Digital-Wandler (kurz: A/D-Wandler) oder englisch [[ADC | &#039;&#039;&#039;A&#039;&#039;&#039;nalog &#039;&#039;&#039;D&#039;&#039;&#039;igital &#039;&#039;&#039;C&#039;&#039;&#039;onverter]] (ADC) benutzt. Er konvertiert eine elektrische Spannung in eine Digitalzahl. Prinzipiell wird dabei die Messspannung mit einer Referenzspannung verglichen. Die Zahl drückt daher das Verhältnis der Messspannung zu dieser Referenzspannung aus. Sie kann in gewohnter Weise von einem [[Mikrocontroller]] weiterverarbeitet werden.&lt;br /&gt;
&lt;br /&gt;
== Elektronische Grundlagen ==&lt;br /&gt;
&lt;br /&gt;
Die ADC-Versorgungsspannung (AVCC) darf maximal um +/-0,3V von der Versorgung des Digitalteils (VCC) abweichen, jedoch nicht 5,5V überschreiten. Die externe Referenzspannung VREF darf nicht kleiner als die im Datenblatt unter ADC Characteristics als VREFmin angegebene Spannung (z.&amp;amp;nbsp;B. ATmega8: 2V, ATmega644P: 1V) und nicht größer als AVCC sein. Die Spannungen an den Wandlereingängen müssen im Intervall GND &amp;amp;le; VIN &amp;amp;le; VREF liegen.&lt;br /&gt;
&lt;br /&gt;
Im Extremfall bedeutet dies: Sei VCC = 5,5V, folgt AVCC_max = VREF_max = VIN_max = 5,5V.&lt;br /&gt;
&lt;br /&gt;
Der Eingangswiderstand des ADC liegt in der Größenordnung von einigen Megaohm, so dass der ADC die Signalquelle praktisch nicht belastet. Desweiteren enthält der Mikrocontroller eine sog. &#039;&#039;&#039;Sample&amp;amp;Hold&#039;&#039;&#039; Schaltung. Dies ist wichtig, wenn sich während des Wandlungsvorgangs die Eingangsspannung verändert, da die AD-Wandlung eine bestimmte Zeit dauert. Die Sample&amp;amp;Hold-Stufe speichert zum Beginn der Wandlung die anliegende Spannung und hält sie während des Wandlungsvorgangs konstant.&lt;br /&gt;
&lt;br /&gt;
=== Beschaltung des ADC-Eingangs ===&lt;br /&gt;
&lt;br /&gt;
Um den ADC im Folgenden zu testen wird eine einfache Schaltung an den PC0-Pin des ATmega8 angeschlossen. Dies ist der ADC-Kanal 0. Bei anderen AVR-Typen liegt der entsprechende Eingang auf einem andern Pin, hier ist ein Blick ins Datenblatt angesagt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tut_ADC_01.gif|framed|center|Testschaltung]]&lt;br /&gt;
&lt;br /&gt;
Der Wert des [[Potentiometer]]s ist Dank des hohen Eingangswiderstandes des ADC ziemlich unkritisch. Es kann jedes Potentiometer von 1k&amp;amp;Omega; bis 1M&amp;amp;Omega; benutzt werden.&lt;br /&gt;
&lt;br /&gt;
Wenn andere Messgrößen gemessen werden sollen, so bedient man sich oft und gern des Prinzips des [[Spannungsteiler]]s. Der [http://www.mikrocontroller.net/articles/Kategorie:Sensorik Sensor] ist ein veränderlicher Widerstand. Zusammen mit einem zweiten, konstanten Widerstand bekannter Größe wird ein Spannungsteiler aufgebaut. Aus der Variation der durch den variablen Spannungsteiler entstehenden Spannung kann auf den Messwert zurückgerechnet werden.&lt;br /&gt;
&lt;br /&gt;
      Vcc ----------+                Vcc ---------+&lt;br /&gt;
                    |                             |&lt;br /&gt;
                   ---                         Sensor,&lt;br /&gt;
                   | |                     der seinen Widerstand&lt;br /&gt;
                   | |                     in Abhängigkeit der&lt;br /&gt;
                   ---                     Messgröße ändert&lt;br /&gt;
                    |                             |&lt;br /&gt;
                    +------- PC0                  +-------- PC0&lt;br /&gt;
                    |                             |&lt;br /&gt;
                Sensor,                          ---&lt;br /&gt;
           der seinen Widerstand                 | |&lt;br /&gt;
           in Abhängigkeit der                   | |&lt;br /&gt;
           Messgröße ändert                      ---&lt;br /&gt;
                    |                             |&lt;br /&gt;
       GND ---------+                 GND --------+&lt;br /&gt;
&lt;br /&gt;
Die Größe des zweiten Widerstandes im Spannungsteiler richtet sich nach dem Wertebereich, in welchem der Sensor seinen Wert ändert. Als Daumenregel kann man sagen, dass der Widerstand so gross sein sollte wie der Widerstand des Sensors in der Mitte des Messbereichs.&lt;br /&gt;
&lt;br /&gt;
Beispiel: Wenn ein [[Temperatursensor]] seinen Widerstand von 0..100 Grad von 2k&amp;amp;Omega; auf 5k&amp;amp;Omega; ändert, sollte der zweite Widerstand eine Grösse von etwa (2+5)/2 = 3,5k&amp;amp;Omega; haben.&lt;br /&gt;
&lt;br /&gt;
===Referenzspannung AREF===&lt;br /&gt;
[[bild:adc_connection.png|thumb|right|300px|Beschaltung von A&amp;lt;sub&amp;gt;REF&amp;lt;/sub&amp;gt;]]&lt;br /&gt;
Der ADC benötigt für seine Arbeit eine Referenzspannung. Dabei gibt es 2 Möglichkeiten:&lt;br /&gt;
* interne Referenzspannung&lt;br /&gt;
* externe Referenzspannung&lt;br /&gt;
&lt;br /&gt;
Bei der Umstellung der Referenzspannung sind Wartezeiten zu beachten, bis die ADC-Hardware einsatzfähig ist (Datenblatt und  [http://www.mikrocontroller.net/topic/165513]).&lt;br /&gt;
&lt;br /&gt;
==== Interne Referenzspannung ====&lt;br /&gt;
&lt;br /&gt;
Mittels Konfigurationsregister können beim ATmega8 verschiedene Referenzspannungen eingestellt werden. Dies umfasst die Versorgungsspannung AVcc sowie eine vom AVR bereitgestellte Spannung von 2,56V (bzw. bei den neueren AVRs 1,1V, wie z.&amp;amp;nbsp;B. beim ATtiny13, ATmega48, 88, 168, ...). In beiden Fällen wird an den AREF-Pin des Prozessors ein Kondensator von 100nF als Minimalbeschaltung nach Masse angeschlossen, um die Spannung zu puffern/glätten. Es ist jedoch zu beachten, dass die interne Referenzspannung ca. +/-10% vom Nominalwert abweichen kann, vgl. dazu das Datenblatt Abschnitt ADC Characteristics VINT (z.&amp;amp;nbsp;B. ATmega8: 2,3-2,9V, ATmega324P: 2,33-2,79V bzw. 1,0-1,2V &amp;quot;Values are guidelines only.&amp;quot;). Die typische Abweichung der internen Referenzspannung vom Sollwert bei einigen AVR-Controllern wird in [http://www.schramm-software.de/tipps/adc-referenzspannung/ dieser Testschaltung] exemplarisch untersucht.&lt;br /&gt;
&lt;br /&gt;
==== Externe Referenzspannung ====&lt;br /&gt;
&lt;br /&gt;
Wird eine externe Referenz verwendet, so wird diese an AREF angeschlossen. Aber aufgepasst! Wenn eine Referenz in Höhe der Versorgungsspannung benutzt werden soll, so ist es besser, dies über die interne Referenz zu tun. Außer bei anderen Spannungen als 5V bzw. 2,56V gibt es eigentlich keinen Grund, an AREF eine Spannungsquelle anzuschließen. In Standardanwendungen fährt man immer besser, wenn die interne Referenzspannung mit einem Kondensator an AREF benutzt wird. Die 10µH-Spule L1 kann man meist auch durch einen 47Ω-Widerstand ersetzen.&lt;br /&gt;
&lt;br /&gt;
== Ein paar ADC-Grundlagen ==&lt;br /&gt;
&lt;br /&gt;
Der ADC ist ein 10-Bit ADC, d.h. er liefert Messwerte im Bereich 0 bis 1023. Liegt am Eingangskanal 0V an, so liefert der ADC einen Wert von 0. Hat die Spannung am Eingangskanal die Referenzspannung erreicht (stimmt nicht ganz), so liefert der ADC einen Wert von 1023. Unterschreitet oder überschreitet die zu messende Spannung diese Grenzen, so liefert der ADC 0 bzw. 1023. Wird die Auflösung von 10 Bit nicht benötigt, so ist es möglich die Ausgabe durch ein Konfigurationsregister so einzuschränken, dass ein leichter Zugriff auf die 8 höchstwertigen Bits möglich ist.&lt;br /&gt;
&lt;br /&gt;
Wie bei vielen analogen Schaltungen, unterliegt auch der ADC einem Rauschen. Das bedeutet, dass man nicht davon ausgehen sollte, dass der ADC bei konstanter Eingangsspannung auch immer denselben konstanten Wert ausgibt. Ein &amp;quot;Zittern&amp;quot; der niederwertigsten 2 Bits ist durchaus nicht ungewöhnlich. Besonders hervorgehoben werden soll an dieser Stelle nochmals die Qualität der Referenzspannung. Diese Qualität geht in erheblichem Maße in die Qualität der Wandelergebnisse ein. Die Beschaltung von AREF mit einem Kondensator ist die absolut notwendige Mindestbeschaltung, um eine einigermaßen akzeptable Referenzspannung zu erhalten. Reicht dies nicht aus, so kann die Qualität einer Messung durch &amp;lt;i&amp;gt;Oversampling&amp;lt;/i&amp;gt; erhöht werden. Dazu werden mehrere Messungen gemacht und deren Mittelwert gebildet.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tut_ADC_03.gif|right|framed]]&lt;br /&gt;
Oft interessiert auch der absolute Spannungspegel nicht. Im Beschaltungsbeispiel oben ist man normalerweise nicht direkt an der am Poti entstehenden Spannung interessiert. Viel mehr ist diese Spannung nur ein notwendiges Übel, um die Stellung des Potis zu bestimmen. In solchen Fällen kann die Poti-Beschaltung wie folgt abgewandelt werden:&lt;br /&gt;
&lt;br /&gt;
Hier wird AREF (bei interner Referenz) als vom µC gelieferte Spannung benutzt und vom Spannungsteiler bearbeitet wieder an den µC zur Messung zurückgegeben. Dies hat den Vorteil, dass der Spannungsteiler automatisch Spannungen bis zur Höhe der Referenzspannung ausgibt, ohne dass eine externe Spannung mit AREF abgeglichen werden müsste. Selbst Schwankungen in AREF wirken sich hier nicht mehr aus, da ja das Verhältnis der Spannungsteilerspannung zu AREF immer konstant bleibt (ratiometrische Messung). Und im Grunde bestimmt der ADC ja nur dieses Verhältnis. Wird diese Variante gewählt, so muss berücksichtigt werden, dass die Ausgangsspannung an AREF nicht allzusehr belastet wird. Der Spannungsteiler muss einen Gesamtwiderstand von deutlich über 10k&amp;amp;Omega; besitzen. Werte von 100k&amp;amp;Omega; oder höher sind anzustreben. Verwendet man anstatt AREF AVCC und schaltet auch die Referenzspannung auf AVCC um, ist die Belastung durch den Poti unkritisch, weil hier die Stromversorgung direkt zur Speisung verwendet wird.&lt;br /&gt;
&lt;br /&gt;
Ist hingegen die absolute Spannung von Interesse, so muss man darauf achten, dass ein ADC in [[Digital | digitalen]] Bereichen arbeitet ([[Quantisierung]]). An einem einfacheren Beispiel soll demonstriert werden was damit gemeint ist.&lt;br /&gt;
&lt;br /&gt;
Angenommen der ADC würde nur 5 Stufen auflösen können und AREF sei 5V:&lt;br /&gt;
&lt;br /&gt;
      Volt    Wert vom ADC&lt;br /&gt;
&lt;br /&gt;
       0 -+&lt;br /&gt;
          |         0&lt;br /&gt;
       1 -+&lt;br /&gt;
          |         1&lt;br /&gt;
       2 -+&lt;br /&gt;
          |         2&lt;br /&gt;
       3 -+&lt;br /&gt;
          |         3&lt;br /&gt;
       4 -+&lt;br /&gt;
          |         4&lt;br /&gt;
       5 -+&lt;br /&gt;
&lt;br /&gt;
Ein ADC Wert von 0 bedeutet also keineswegs, dass die zu messende Spannung exakt den Wert 0 hat. Es bedeutet lediglich, dass die Messspannung irgendwo im Bereich von 0V bis 1V liegt. Sinngemäß bedeutet daher auch das Auftreten des Maximalwertes nicht, dass die Spannung exakt AREF beträgt, sondern lediglich, dass die Messspannung sich irgendwo im Bereich der letzten Stufe (also von 4V bis 5V) bewegt.&lt;br /&gt;
&lt;br /&gt;
== Umrechnung des ADC Wertes in eine Spannung ==&lt;br /&gt;
&lt;br /&gt;
Die Größe eines &amp;quot;Bereiches&amp;quot; bestimmt sich also zu&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
   Bereichsbreite = \frac {Referenzspannung}{Maximalwert}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Messwert vom ADC rechnet sich dann wie folgt in eine Spannung um:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
  Spannung = ADCwert \cdot \frac {Referenzspannung} {Maximalwert}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wird der ADC also mit 10 Bit an 5 V betrieben, so lauten die Umrechnungen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
   Bereichsbreite = \frac{5~\text{V}}{1023} = 0,004888~\text{V} = 4,888~\text{mV}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
   Spannung = ADCwert \cdot 4,888~\text{mV}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn man genau hinsieht stellt man fest, dass sowohl die Referenzspannung als auch der Maximalwert Konstanten sind. D.h. der Quotient aus Referenzspannung und Maximalwert ist konstant. Somit muss nicht immer eine Addition und Division ausgeführt werden, sondern nur eine Multiplikation! Das spart viel Aufwand und Rechenzeit! Dabei kann sinnvollerweise [[Festkommaarithmetik]] zum Einsatz kommen.&lt;br /&gt;
&lt;br /&gt;
== Kalibrierung ==&lt;br /&gt;
Hat man eine externe, genaue Referenzspannung zu Hand, dann kann ein Korrekturfaktor berechnet werden, mit dem die Werte des ADCs im Nachinein korrigiert werden können. Dies geschieht normalerweise über eine sogenannte gain offset Korrektur an einer Geraden oder einer Parabel. In erster Näherung kann man auch die interne Referenzspannung um das Inverse des ermittelten Korrekturwertes verstellen, um einen genaueren bereits digitalisierten Wert zu bekommen.&lt;br /&gt;
&lt;br /&gt;
== Die Steuerregister des ADC ==&lt;br /&gt;
&lt;br /&gt;
=== ADMUX ===&lt;br /&gt;
&lt;br /&gt;
{{Byte|ADMUX| REFS1 | REFS0 | ADLAR |       |  MUX3 |  MUX2 |  MUX1 |  MUX0}}&lt;br /&gt;
&lt;br /&gt;
* Referenzspannung &amp;lt;i&amp;gt;REFS1, REFS0&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| {{Tabelle}}&lt;br /&gt;
|-  style=&amp;quot;background-color:#ffddcc&amp;quot;&lt;br /&gt;
!REFS1||REFS0||Referenz&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
||externe Referenz&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|interne Referenz: Avcc&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
||wird beim Mega8 nicht benutzt&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
||interne Referenz: 2.56 Volt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* Ausrichtung &amp;lt;i&amp;gt;ADLAR&amp;lt;/i&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;0&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;ADLAR&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;&amp;lt;/th&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;0&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Das Ergebnis wird in den Registern ADCH/ADCL rechtsbündig ausgerichtet. Die 8 niederwertigsten Bits des Ergebnisses werden in ADCL abgelegt. Die verbleibenden 2 Bits des Ergebnisses werden im Register ADCH in den Bits 0 und 1 abgelegt.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Das Ergebnis wird in den Registern ADCH/ADCL linksbündig ausgerichtet. Die 8 höchstwertigen Bits des Ergebnisses werden in ADCH abgelegt. Die verbleibenden 2 niederwertigen Bits werden im Register ADCL in den Bits 6 und 7 abgelegt.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Kanalwahl &amp;lt;i&amp;gt;MUX3, MUX2, MUX1, MUX0&amp;lt;/i&amp;gt;&lt;br /&gt;
{| {{Tabelle}}&lt;br /&gt;
|-  style=&amp;quot;background-color:#ffddcc&amp;quot;&lt;br /&gt;
!MUX3||MUX2||MUX1||MUX0||Kanal&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
||Kanal 0, Pin PC0&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
||Kanal 1, Pin PC1&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
||Kanal 2, Pin PC2&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
||Kanal 3, Pin PC3&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
||Kanal 4, Pin PC4&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
||Kanal 5, Pin PC5&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
||Kanal 6 (*)&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
||Kanal 7 (*)&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
||1.23V, Vbg&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
||0V, GND&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
(*) Bei Atmega8 nur in der Gehäusebauform TQFP und MLF verfügbar, nicht in PDIP&lt;br /&gt;
&lt;br /&gt;
===ADCSRA===&lt;br /&gt;
{{Byte|ADCSRA|  ADEN |  ADSC |  ADFR |  ADIF |  ADIE | ADPS2 | ADPS1 | ADPS0}}&lt;br /&gt;
&lt;br /&gt;
;ADEN: &amp;quot;ADC Enable&amp;quot;: Mittels ADEN wird der ADC ein und ausgeschaltet. Eine 1 an dieser Bitposition schaltet den ADC ein.&lt;br /&gt;
; ADSC: &amp;quot;ADC Start Conversion&amp;quot;: Wird eine 1 an diese Bitposition geschrieben, so beginnt der ADC mit der Wandlung. Das Bit bleibt auf 1, solange die Wandlung im Gange ist. Wenn die Wandlung beendet ist, wird dieses Bit von der ADC Hardware wieder auf 0 gesetzt.&lt;br /&gt;
; ADFR: &amp;quot;ADC Free Running&amp;quot;: Wird eine 1 an ADFR geschrieben, so wird der ADC im Free Running Modus betrieben. Dabei startet der ADC nach dem Abschluss einer Messung automatisch die nächste Messung. Die erste Messung wird ganz normal über das Setzen des ADSC-Bits gestartet.&lt;br /&gt;
; ADIF: &amp;quot;ADC Interrupt Flag&amp;quot;: Wenn eine Messung abgeschlossen ist, wird das ADIF Bit gesetzt. Ist zusätzlich noch das &amp;lt;i&amp;gt;ADIE&amp;lt;/i&amp;gt; Bit gesetzt, so wird ein Interrupt ausgelöst und der entsprechende Interrupt Handler angesprungen.&lt;br /&gt;
; ADIE: &amp;quot;ADC Interrupt Enable&amp;quot;: Wird eine 1 an ADIE geschrieben, so löst der ADC nach Beendigung einer Messung einen Interrupt aus.&lt;br /&gt;
; ADPS2, ADPS1, ADPS0: &amp;quot;ADC Prescaler&amp;quot;: Mit dem Prescaler kann die ADC-Frequenz gewählt werden. Laut Datenblatt sollte diese für die optimale Auflösung zwischen 50kHz und 200kHz liegen. Ist die Wandlerfrequenz langsamer eingestellt, kann es passieren dass die eingebaute Sample &amp;amp; Hold Schaltung die Eingangsspannung nicht lange genug konstant halten kann. Ist die Frequenz aber zu schnell eingestellt, dann kann es passieren dass sich die Sample &amp;amp; Hold Schaltung nicht schnell genug an die Eingangsspannung anpassen kann.&lt;br /&gt;
&lt;br /&gt;
{| {{Tabelle}}&lt;br /&gt;
|-  style=&amp;quot;background-color:#ffddcc&amp;quot;&lt;br /&gt;
!ADPS2||ADPS1||ADPS0||Vorteiler&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|2&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|2&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|4&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|8&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|16&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|32&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|64&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|128&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Die Ergebnisregister ADCL und ADCH ==&lt;br /&gt;
&lt;br /&gt;
Da das Ergebnis des ADC ein 10 Bit Wert ist, passt dieser Wert naturgemäß nicht in ein einzelnes Register, das ja bekanntlich nur 8 Bit breit ist. Daher wird das Ergebnis in 2 Register &#039;&#039;&#039;ADCL&#039;&#039;&#039; und &#039;&#039;&#039;ADCH&#039;&#039;&#039; abgelegt. Von den 10 Ergebnisbits sind die niederwertigsten 8 im Register &#039;&#039;&#039;ADCL&#039;&#039;&#039; abgelegt und die noch fehlenden 2 Bits werden im Register &#039;&#039;&#039;ADCH&#039;&#039;&#039; an den niederwertigsten Bitpositionen gespeichert.&lt;br /&gt;
&lt;br /&gt;
              ADCH                                   ADCL&lt;br /&gt;
   +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+&lt;br /&gt;
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |&lt;br /&gt;
   +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+&lt;br /&gt;
                             9   8       7   6   5   4   3   2   1   0&lt;br /&gt;
&lt;br /&gt;
Diese Zuordnung kann aber auch geändert werden: Durch setzen des &#039;&#039;&#039;ADLAR&#039;&#039;&#039; Bits im &#039;&#039;&#039;ADMUX&#039;&#039;&#039; Register wird die Ausgabe geändert zu:&lt;br /&gt;
&lt;br /&gt;
              ADCH                                   ADCL&lt;br /&gt;
   +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+&lt;br /&gt;
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |&lt;br /&gt;
   +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+&lt;br /&gt;
     9   8   7   6   5   4   3   2       1   0&lt;br /&gt;
&lt;br /&gt;
Dies ist besonders dann interessant, wenn das ADC Ergebnis als 8 Bit Zahl weiterverarbeitet werden soll. In diesem Fall stehen die 8 höchstwertigen Bits bereits verarbeitungsfertig im Register &#039;&#039;&#039;ADCH&#039;&#039;&#039; zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
Beim Auslesen der ADC-Register ist zu beachten:&lt;br /&gt;
Immer zuerst &#039;&#039;&#039;ADCL&#039;&#039;&#039; und erst dann &#039;&#039;&#039;ADCH&#039;&#039;&#039; auslesen. Beim Zugriff auf &#039;&#039;&#039;ADCL&#039;&#039;&#039; wird das &#039;&#039;&#039;ADCH&#039;&#039;&#039; Register gegenüber Veränderungen vom &#039;&#039;&#039;ADC&#039;&#039;&#039; gesperrt. Erst beim nächsten Auslesen des &#039;&#039;&#039;ADCH&#039;&#039;&#039;-Registers wird diese Sperre wieder aufgehoben. Dadurch ist sichergestellt, daß die Inhalte von &#039;&#039;&#039;ADCL&#039;&#039;&#039; und &#039;&#039;&#039;ADCH&#039;&#039;&#039; immer aus demselben Wandlungsergebnis stammen, selbst wenn der &#039;&#039;&#039;ADC&#039;&#039;&#039; im Hintergrund selbsttätig weiterwandelt. Das &#039;&#039;&#039;ADCH&#039;&#039;&#039; Register &#039;&#039;&#039;muss&#039;&#039;&#039; ausgelesen werden!&lt;br /&gt;
&lt;br /&gt;
== Beispiele ==&lt;br /&gt;
&lt;br /&gt;
=== Ausgabe als ADC-Wert ===&lt;br /&gt;
&lt;br /&gt;
Das folgende Programm liest in einer Schleife ständig den ADC aus und verschickt das Ergebnis im Klartext (ASCII) über die [[AVR-Tutorial: UART|UART]]. Zur Verringerung des unvermeidlichen Rauschens werden 256 Messwerte herangezogen und deren Mittelwert als endgültiges Messergebnis gewertet. Dazu werden die einzelnen Messungen in den Registern temp2, temp3, temp4 als 24 Bit Zahl aufaddiert. Die Division durch 256 erfolgt dann ganz einfach dadurch, dass das Register temp2 verworfen wird und die Register temp3 und temp4 als 16 Bit Zahl aufgefasst werden. Eine Besonderheit ist noch, dass je nach dem Wert in temp2 die 16 Bit Zahl in temp3 und temp4 noch aufgerundet wird: Enthält temp2 einen Wert größer als 128, dann wird zur 16 Bit Zahl in temp3/temp4 noch 1 dazu addiert.&lt;br /&gt;
&lt;br /&gt;
In diesem Programm findet man oft die Konstruktion&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
    subi    temp3, low(-1)      ; addieren von 1&lt;br /&gt;
    sbci    temp4, high(-1)     ; addieren des Carry&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dabei handelt es sich um einen kleinen Trick. Um eine Konstante zu einem Register direkt addieren zu können bräuchte man einen Befehl ala addi (Add Immediate, Addiere Konstante), den der AVR aber nicht hat. Ebenso gibt es kein adci (Add with carry Immediate, Addiere Konstante mit Carry Flag). Man müsste also erst eine Konstante in ein Register laden und addieren. Das kostet aber Programmspeicher, Rechenzeit und man muss ein Register zusätzlich frei haben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
; 16 Bit Addition mit Konstante, ohne Cleverness&lt;br /&gt;
    ldi     temp5, low(1)&lt;br /&gt;
    add     temp3, temp5        ; addieren von 1&lt;br /&gt;
    ldi     temp5, high(1)&lt;br /&gt;
    adc     temp3, temp5        ; addieren des Carry&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier greift man einfach zu dem Trick, dass eine Addition gleich der Subtraktion der negativen Werts ist. Also &amp;quot;addiere +1&amp;quot; ist gleich &amp;quot;subtrahiere -1&amp;quot;. Dafür hat der AVR zwei Befehle, subi (Substract Immediate, Subtrahiere Konstante) und sbci (Substract Immediate with carry, Subtrahiere Konstante mit Carry Flag).&lt;br /&gt;
&lt;br /&gt;
Das folgende Programm ist für den &#039;&#039;&#039;ATmega8&#039;&#039;&#039; geschrieben. Für moderne Nachfolgetypen wie den ATmega88 muss der Code angepasst werden ([http://www.mikrocontroller.net/topic/204069#2011175], [http://www.atmel.com/dyn/resources/prod_documents/doc2553.pdf AVR094: Replacing ATmega8 by ATmega88 (PDF)]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
.include &amp;quot;m8def.inc&amp;quot;&lt;br /&gt;
&lt;br /&gt;
.def temp1     = r16         ; allgemeines temp Register, zur kurzfristigen Verwendung&lt;br /&gt;
.def temp2     = r17         ; Register für 24 Bit Addition, Lowest Byte&lt;br /&gt;
.def temp3     = r18         ; Register für 24 Bit Addition, Middle Byte&lt;br /&gt;
.def temp4     = r19         ; Register für 24 Bit Addition, Highest Byte&lt;br /&gt;
.def adlow     = r20         ; Ergebnis vom ADC / Mittelwert der 256 Messungen&lt;br /&gt;
.def adhigh    = r21         ; Ergebnis vom ADC / Mittelwert der 256 Messungen&lt;br /&gt;
.def messungen = r22         ; Schleifenzähler für die Messungen&lt;br /&gt;
.def ztausend  = r23         ; Zehntausenderstelle des ADC Wertes&lt;br /&gt;
.def tausend   = r24         ; Tausenderstelle des ADC Wertes&lt;br /&gt;
.def hundert   = r25         ; Hunderterstelle des ADC Wertes&lt;br /&gt;
.def zehner    = r26         ; Zehnerstelle des ADC Wertes&lt;br /&gt;
.def zeichen   = r27         ; Zeichen zur Ausgabe auf den UART&lt;br /&gt;
&lt;br /&gt;
.equ F_CPU = 4000000                            ; Systemtakt in Hz&lt;br /&gt;
.equ BAUD  = 9600                               ; Baudrate&lt;br /&gt;
&lt;br /&gt;
; Berechnungen&lt;br /&gt;
.equ UBRR_VAL   = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; clever runden&lt;br /&gt;
.equ BAUD_REAL  = (F_CPU/(16*(UBRR_VAL+1)))     ; Reale Baudrate&lt;br /&gt;
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ; Fehler in Promille&lt;br /&gt;
&lt;br /&gt;
.if ((BAUD_ERROR&amp;gt;10) || (BAUD_ERROR&amp;lt;-10))       ; max. +/-10 Promille Fehler&lt;br /&gt;
  .error &amp;quot;Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!&amp;quot;&lt;br /&gt;
.endif&lt;br /&gt;
 &lt;br /&gt;
; hier geht das Programm los&lt;br /&gt;
 &lt;br /&gt;
    ldi     temp1, LOW(RAMEND)                  ; Stackpointer initialisieren&lt;br /&gt;
    out     SPL, temp1&lt;br /&gt;
    ldi     temp1, HIGH(RAMEND)&lt;br /&gt;
    out     SPH, temp1&lt;br /&gt;
 &lt;br /&gt;
;UART Initalisierung&lt;br /&gt;
 &lt;br /&gt;
    ldi     temp1, LOW(UBRR_VAL)                    ; Baudrate einstellen&lt;br /&gt;
    out     UBRRL, temp1&lt;br /&gt;
    ldi     temp1, HIGH(UBRR_VAL)&lt;br /&gt;
    out     UBRRH, temp1&lt;br /&gt;
&lt;br /&gt;
    sbi     UCSRB, TXEN                         ; TX einschalten&lt;br /&gt;
 &lt;br /&gt;
; ADC initialisieren: ADC0, Vcc als Referenz, Single Conversion, Vorteiler 128&lt;br /&gt;
&lt;br /&gt;
    ldi     temp1, (1&amp;lt;&amp;lt;REFS0)                   ; Kanal 0, interne Referenzspannung 5V&lt;br /&gt;
    out     ADMUX, temp1&lt;br /&gt;
    ldi     temp1, (1&amp;lt;&amp;lt;ADEN) | (1&amp;lt;&amp;lt;ADPS2) | (1&amp;lt;&amp;lt;ADPS1) | (1&amp;lt;&amp;lt;ADPS0)&lt;br /&gt;
    out     ADCSRA, temp1&lt;br /&gt;
 &lt;br /&gt;
Main:&lt;br /&gt;
    clr     temp1&lt;br /&gt;
    clr     temp2&lt;br /&gt;
    clr     temp3&lt;br /&gt;
    clr     temp4&lt;br /&gt;
&lt;br /&gt;
    ldi     messungen, 0        ; 256 Schleifendurchläufe&lt;br /&gt;
 &lt;br /&gt;
; neuen ADC-Wert lesen  (Schleife - 256 mal)&lt;br /&gt;
&lt;br /&gt;
sample_adc:&lt;br /&gt;
    sbi     ADCSRA, ADSC        ; den ADC starten&lt;br /&gt;
 &lt;br /&gt;
wait_adc:&lt;br /&gt;
    sbic    ADCSRA, ADSC        ; wenn der ADC fertig ist, wird dieses Bit gelöscht&lt;br /&gt;
    rjmp    wait_adc&lt;br /&gt;
 &lt;br /&gt;
; ADC einlesen:&lt;br /&gt;
&lt;br /&gt;
    in      adlow, ADCL         ; immer zuerst LOW Byte lesen&lt;br /&gt;
    in      adhigh, ADCH        ; danach das mittlerweile gesperrte High Byte&lt;br /&gt;
 &lt;br /&gt;
; alle 256 ADC-Werte addieren&lt;br /&gt;
; dazu wird mit den Registern temp4, temp3 und temp2 ein&lt;br /&gt;
; 24-Bit breites Akkumulationsregister gebildet, in dem&lt;br /&gt;
; die 10 Bit Werte aus adhigh, adlow aufsummiert werden&lt;br /&gt;
&lt;br /&gt;
    add     temp2, adlow        ; addieren&lt;br /&gt;
    adc     temp3, adhigh       ; addieren über Carry&lt;br /&gt;
    adc     temp4, temp1        ; addieren über Carry, temp1 enthält 0&lt;br /&gt;
    dec     messungen           ; Schleifenzähler MINUS 1&lt;br /&gt;
    brne    sample_adc          ; wenn noch keine 256 ADC Werte -&amp;gt; nächsten Wert einlesen&lt;br /&gt;
 &lt;br /&gt;
; Aus den 256 Werten den Mittelwert berechnen&lt;br /&gt;
; Mathematisch eine Division durch 256&lt;br /&gt;
; Da aber 2^8 = 256 ist ist da einfach durch das weglassen des niederwertigsten Bytes&lt;br /&gt;
; erreicht werden&lt;br /&gt;
;&lt;br /&gt;
; allerdings wird der Wert noch gerundet&lt;br /&gt;
&lt;br /&gt;
    cpi     temp2,128           ; &amp;quot;Kommastelle&amp;quot; kleiner als 128 ?&lt;br /&gt;
    brlo    no_round            ; ist kleiner ==&amp;gt; Sprung&lt;br /&gt;
 &lt;br /&gt;
; Aufrunden&lt;br /&gt;
    subi    temp3, low(-1)      ; addieren von 1&lt;br /&gt;
    sbci    temp4, high(-1)     ; addieren des Carry&lt;br /&gt;
 &lt;br /&gt;
no_round:&lt;br /&gt;
&lt;br /&gt;
;   Ergebnis nach adlow und adhigh kopieren&lt;br /&gt;
;   damit die temp Register frei werden&lt;br /&gt;
&lt;br /&gt;
    mov     adlow, temp3&lt;br /&gt;
    mov     adhigh, temp4&lt;br /&gt;
 &lt;br /&gt;
;in ASCII umwandeln&lt;br /&gt;
; Division durch mehrfache Subtraktion&lt;br /&gt;
&lt;br /&gt;
    ldi     ztausend, &#039;0&#039;-1     ; Ziffernzähler direkt als ASCII Code&lt;br /&gt;
    ; bzgl. &#039;0&#039;-1 siehe http://www.mikrocontroller.net/topic/198681&lt;br /&gt;
Z_ztausend:&lt;br /&gt;
    inc     ztausend&lt;br /&gt;
    subi    adlow, low(10000)   ; -10,000&lt;br /&gt;
    sbci    adhigh, high(10000) ; 16 Bit&lt;br /&gt;
    brcc    Z_ztausend&lt;br /&gt;
                                    &lt;br /&gt;
    subi    adlow, low(-10000)  ; nach Unterlauf wieder einmal addieren&lt;br /&gt;
    sbci    adhigh, high(-10000); +10,000&lt;br /&gt;
 &lt;br /&gt;
    ldi     tausend, &#039;0&#039;-1      ; Ziffernzähler direkt als ASCII Code&lt;br /&gt;
Z_tausend:&lt;br /&gt;
    inc     tausend&lt;br /&gt;
    subi    adlow, low(1000)    ; -1,000&lt;br /&gt;
    sbci    adhigh, high(1000)  ; 16 Bit&lt;br /&gt;
    brcc    Z_tausend&lt;br /&gt;
                                    &lt;br /&gt;
    subi    adlow, low(-1000)   ; nach Unterlauf wieder einmal addieren&lt;br /&gt;
    sbci    adhigh, high(-1000) ; +1,000&lt;br /&gt;
 &lt;br /&gt;
    ldi     hundert, &#039;0&#039;-1      ; Ziffernzähler direkt als ASCII Code&lt;br /&gt;
Z_hundert:&lt;br /&gt;
    inc     hundert&lt;br /&gt;
    subi    adlow, low(100)     ; -100&lt;br /&gt;
    sbci    adhigh, high(100)   ; 16 Bit&lt;br /&gt;
    brcc    Z_hundert&lt;br /&gt;
                                    &lt;br /&gt;
    subi    adlow, low(-100)    ; nach Unterlauf wieder einmal addieren&lt;br /&gt;
    sbci    adhigh, high(-100)  ; +100&lt;br /&gt;
 &lt;br /&gt;
    ldi     zehner, &#039;0&#039;-1       ; Ziffernzähler direkt als ASCII Code&lt;br /&gt;
Z_zehner:&lt;br /&gt;
    inc     zehner&lt;br /&gt;
    subi    adlow, low(10)      ; -10&lt;br /&gt;
    sbci    adhigh, high(10)    ; 16 Bit&lt;br /&gt;
    brcc    Z_zehner&lt;br /&gt;
                                    &lt;br /&gt;
    subi    adlow, low(-10)     ; nach Unterlauf wieder einmal addieren&lt;br /&gt;
    sbci    adhigh, high(-10)   ; +10&lt;br /&gt;
&lt;br /&gt;
    subi    adlow, -&#039;0&#039;         ; adlow enthält die Einer, Umwandlung in ASCII&lt;br /&gt;
 &lt;br /&gt;
;an UART Senden&lt;br /&gt;
&lt;br /&gt;
    mov     zeichen, ztausend   ; Zehntausender Stelle&lt;br /&gt;
    rcall   transmit&lt;br /&gt;
    mov     zeichen, tausend    ; Tausender Stelle ausgeben&lt;br /&gt;
    rcall   transmit    &lt;br /&gt;
    mov     zeichen, hundert    ; Hunderter Stelle ausgeben&lt;br /&gt;
    rcall   transmit&lt;br /&gt;
    mov     zeichen, zehner     ; Zehner Stelle ausgeben&lt;br /&gt;
    rcall   transmit&lt;br /&gt;
    mov     zeichen, adlow      ; Einer Stelle ausgeben&lt;br /&gt;
    rcall   transmit&lt;br /&gt;
    ldi     zeichen, 13         ; CR, Carrige Return (Wagenrücklauf)&lt;br /&gt;
    rcall   transmit&lt;br /&gt;
    ldi     zeichen, 10         ; LF, Line Feed (Neue Zeile)&lt;br /&gt;
    rcall   transmit&lt;br /&gt;
 &lt;br /&gt;
    rjmp    Main&lt;br /&gt;
 &lt;br /&gt;
transmit:&lt;br /&gt;
    sbis    UCSRA,UDRE          ; Warten, bis UDR bereit ist ...&lt;br /&gt;
    rjmp    transmit&lt;br /&gt;
    out     UDR, zeichen        ; und Zeichen ausgeben&lt;br /&gt;
    ret&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ausgabe als Spannungswert ===&lt;br /&gt;
&lt;br /&gt;
Das zweite Beispiel ist schon um einiges größer. Hier wird der gemittelte ADC-Wert in eine Spannung umgerechnet. Dazu wird [[Festkommaarithmetik]] verwendet. Die Daten sind in diesem Fall&lt;br /&gt;
&lt;br /&gt;
* Referenzspannung : 5V&lt;br /&gt;
* alte Auflösung   : 5V / 1024 = 4,8828125mV&lt;br /&gt;
* neue Auflösung   : 1mV&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Faktor = 4,8828125mV / 1mV = 4,8828125&lt;br /&gt;
&lt;br /&gt;
Der Faktor wird dreimal mit 10 multipliziert und das Ergebnis auf 4883 gerundet. Die neue Auflösung wird dreimal durch 10 dividiert und beträgt 1&amp;amp;mu;V. Der relative Fehler beträgt&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; F_r = \frac {4883}{4882,8125}-1 = 0,00384% = \frac {1}{26042}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Fehler ist absolut vernachlässigbar. Nach der Multiplikation des ADC-Wertes mit 4883 liegt die gemessene Spannung in der Einheit &amp;amp;mu;V vor. Vorsicht! Das ist &#039;&#039;&#039;nicht&#039;&#039;&#039; die reale [[Auflösung und Genauigkeit]], nur rein mathematisch bedingt. Für maximale Genauigkeit sollte man die Versorgungsspannung AVCC, welche hier gleichzeitig als Referenzspannung dient, exakt messen, die Rechnung nachvollziehen und den Wert im Quelltext eintragen. Damit führt man eine einfach Einpunktkalibrierung durch.&lt;br /&gt;
&lt;br /&gt;
Da das Programm schon um einiges größer und komplexer ist, wurde es im Vergleich zur Vorgängerversion geändert. Die Multiplikation sowie die Umwandung der Zahl in einen ASCII-String sind als Unterprogramme geschrieben, dadurch erhält man wesentlich mehr Überblick im Hauptprogramm und die Wiederverwendung in anderen Programmen vereinfacht sich. Ausserdem wird der String im RAM gespeichert und nicht mehr in CPU-Registern. Die Berechung der einzelnen Ziffern erfolgt über ein Schleife, das ist kompakter und übersichtlicher.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
.include &amp;quot;m8def.inc&amp;quot;&lt;br /&gt;
&lt;br /&gt;
.def z0        = r1          ; Zahl für Integer -&amp;gt; ASCII Umwandlung&lt;br /&gt;
.def z1        = r2&lt;br /&gt;
.def z2        = r3&lt;br /&gt;
.def z3        = r4&lt;br /&gt;
.def temp1     = r16         ; allgemeines Register, zur kurzfristigen Verwendung&lt;br /&gt;
.def temp2     = r17         ; Register für 24 Bit Addition, niederwertigstes Byte (LSB)&lt;br /&gt;
.def temp3     = r18         ; Register für 24 Bit Addition, mittlerers Byte&lt;br /&gt;
.def temp4     = r19         ; Register für 24 Bit Addition, höchstwertigstes Byte (MSB)&lt;br /&gt;
.def adlow     = r20         ; Ergebnis vom ADC-Mittelwert der 256 Messungen&lt;br /&gt;
.def adhigh    = r21         ; Ergebnis vom ADC-Mittelwert der 256 Messungen&lt;br /&gt;
.def messungen = r22         ; Schleifenzähler für die Messungen&lt;br /&gt;
.def zeichen   = r23         ; Zeichen zur Ausgabe auf den UART&lt;br /&gt;
.def temp5     = r24&lt;br /&gt;
.def temp6     = r25&lt;br /&gt;
&lt;br /&gt;
; Faktor für Umrechung des ADC-Wertes in Spannung&lt;br /&gt;
; = (Referenzspannung / 1024 ) * 100000&lt;br /&gt;
; = 5V / 1024 * 1.000.000&lt;br /&gt;
.equ Faktor = 4883&lt;br /&gt;
&lt;br /&gt;
.equ F_CPU = 4000000                            ; Systemtakt in Hz&lt;br /&gt;
.equ BAUD  = 9600                               ; Baudrate&lt;br /&gt;
&lt;br /&gt;
; Berechnungen&lt;br /&gt;
.equ UBRR_VAL   = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; clever runden&lt;br /&gt;
.equ BAUD_REAL  = (F_CPU/(16*(UBRR_VAL+1)))     ; Reale Baudrate&lt;br /&gt;
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ; Fehler in Promille&lt;br /&gt;
&lt;br /&gt;
.if ((BAUD_ERROR&amp;gt;10) || (BAUD_ERROR&amp;lt;-10))       ; max. +/-10 Promille Fehler&lt;br /&gt;
  .error &amp;quot;Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!&amp;quot;&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
; RAM&lt;br /&gt;
.dseg&lt;br /&gt;
.org 0x60&lt;br /&gt;
Puffer: .byte 10&lt;br /&gt;
&lt;br /&gt;
; hier geht das Programm los&lt;br /&gt;
.cseg&lt;br /&gt;
.org 0&lt;br /&gt;
 &lt;br /&gt;
    ldi     temp1, LOW(RAMEND)                  ; Stackpointer initialisieren&lt;br /&gt;
    out     SPL, temp1&lt;br /&gt;
    ldi     temp1, HIGH(RAMEND)&lt;br /&gt;
    out     SPH, temp1&lt;br /&gt;
 &lt;br /&gt;
;UART Initalisierung&lt;br /&gt;
 &lt;br /&gt;
    ldi     temp1, LOW(UBRR_VAL)                ; Baudrate einstellen&lt;br /&gt;
    out     UBRRL, temp1&lt;br /&gt;
    ldi     temp1, HIGH(UBRR_VAL)&lt;br /&gt;
    out     UBRRH, temp1&lt;br /&gt;
&lt;br /&gt;
    sbi     UCSRB, TXEN                         ; TX einschalten&lt;br /&gt;
 &lt;br /&gt;
; ADC initialisieren: Single Conversion, Vorteiler 128&lt;br /&gt;
; Kanal 0, interne Referenzspannung AVCC&lt;br /&gt;
&lt;br /&gt;
    ldi     temp1, (1&amp;lt;&amp;lt;REFS0)                   &lt;br /&gt;
    out     ADMUX, temp1&lt;br /&gt;
    ldi     temp1, (1&amp;lt;&amp;lt;ADEN) | (1&amp;lt;&amp;lt;ADPS2) | (1&amp;lt;&amp;lt;ADPS1) | (1&amp;lt;&amp;lt;ADPS0)&lt;br /&gt;
    out     ADCSRA, temp1&lt;br /&gt;
 &lt;br /&gt;
Hauptschleife:&lt;br /&gt;
    clr     temp1&lt;br /&gt;
    clr     temp2&lt;br /&gt;
    clr     temp3&lt;br /&gt;
    clr     temp4&lt;br /&gt;
&lt;br /&gt;
    ldi     messungen, 0        ; 256 Schleifendurchläufe&lt;br /&gt;
 &lt;br /&gt;
; neuen ADC-Wert lesen  (Schleife - 256 mal)&lt;br /&gt;
&lt;br /&gt;
adc_messung:&lt;br /&gt;
    sbi     ADCSRA, ADSC        ; den ADC starten&lt;br /&gt;
 &lt;br /&gt;
adc_warten:&lt;br /&gt;
    sbic    ADCSRA, ADSC        ; wenn der ADC fertig ist, wird dieses Bit gelöscht&lt;br /&gt;
    rjmp    adc_warten&lt;br /&gt;
 &lt;br /&gt;
; ADC einlesen:&lt;br /&gt;
&lt;br /&gt;
    in      adlow, ADCL         ; immer zuerst LOW Byte lesen&lt;br /&gt;
    in      adhigh, ADCH        ; danach das mittlerweile gesperrte High Byte&lt;br /&gt;
 &lt;br /&gt;
; alle 256 ADC-Werte addieren&lt;br /&gt;
; dazu wird mit den Registern temp4, temp3 und temp2 ein&lt;br /&gt;
; 24-Bit breites Akkumulationsregister gebildet, in dem&lt;br /&gt;
; die 10 Bit Werte aus adhigh, adlow aufsummiert werden&lt;br /&gt;
&lt;br /&gt;
    add     temp2, adlow        ; addieren&lt;br /&gt;
    adc     temp3, adhigh       ; addieren über Carry&lt;br /&gt;
    adc     temp4, temp1        ; addieren über Carry, temp1 enthält 0&lt;br /&gt;
    dec     messungen           ; Schleifenzähler MINUS 1&lt;br /&gt;
    brne    adc_messung         ; wenn noch keine 256 ADC Werte -&amp;gt; nächsten Wert einlesen&lt;br /&gt;
 &lt;br /&gt;
; Aus den 256 Werten den Mittelwert berechnen&lt;br /&gt;
; Bei 256 Werten ist das ganz einfach: Das niederwertigste Byte&lt;br /&gt;
; (im Register temp2) fällt einfach weg&lt;br /&gt;
;&lt;br /&gt;
; allerdings wird der Wert noch gerundet&lt;br /&gt;
&lt;br /&gt;
    cpi     temp2,128           ; &amp;quot;Kommastelle&amp;quot; kleiner als 128 ?&lt;br /&gt;
    brlo    nicht_runden        ; ist kleiner ==&amp;gt; Sprung&lt;br /&gt;
 &lt;br /&gt;
; Aufrunden&lt;br /&gt;
    subi    temp3, low(-1)      ; addieren von 1&lt;br /&gt;
    sbci    temp4, high(-1)     ; addieren des Carry&lt;br /&gt;
 &lt;br /&gt;
nicht_runden:&lt;br /&gt;
&lt;br /&gt;
;   Ergebnis nach adlow und adhigh kopieren&lt;br /&gt;
;   damit die temp Register frei werden&lt;br /&gt;
&lt;br /&gt;
    mov     adlow, temp3&lt;br /&gt;
    mov     adhigh, temp4&lt;br /&gt;
&lt;br /&gt;
; in Spannung umrechnen&lt;br /&gt;
&lt;br /&gt;
    ldi     temp5,low(Faktor)&lt;br /&gt;
    ldi     temp6,high(Faktor)&lt;br /&gt;
    rcall   mul_16x16&lt;br /&gt;
&lt;br /&gt;
; in ASCII umwandeln&lt;br /&gt;
&lt;br /&gt;
    ldi     XL, low(Puffer)&lt;br /&gt;
    ldi     XH, high(Puffer)&lt;br /&gt;
    rcall   Int_to_ASCII&lt;br /&gt;
 &lt;br /&gt;
;an UART Senden&lt;br /&gt;
&lt;br /&gt;
    ldi     ZL, low(Puffer+3)&lt;br /&gt;
    ldi     ZH, high(Puffer+3)&lt;br /&gt;
    ldi     temp1, 1&lt;br /&gt;
    rcall   sende_zeichen       ; eine Vorkommastelle ausgeben&lt;br /&gt;
&lt;br /&gt;
    ldi     zeichen, &#039;,&#039;        ; Komma ausgeben&lt;br /&gt;
    rcall   sende_einzelzeichen&lt;br /&gt;
&lt;br /&gt;
    ldi     temp1, 3            ; Drei Nachkommastellen ausgeben&lt;br /&gt;
    rcall   sende_zeichen&lt;br /&gt;
&lt;br /&gt;
    ldi     zeichen, &#039;V&#039;        ; Volt Zeichen ausgeben&lt;br /&gt;
    rcall   sende_einzelzeichen&lt;br /&gt;
&lt;br /&gt;
    ldi     zeichen, 10         ; New Line Steuerzeichen&lt;br /&gt;
    rcall   sende_einzelzeichen&lt;br /&gt;
&lt;br /&gt;
    ldi     zeichen, 13         ; Carrige Return Steuerzeichen&lt;br /&gt;
    rcall   sende_einzelzeichen&lt;br /&gt;
&lt;br /&gt;
    rjmp    Hauptschleife&lt;br /&gt;
&lt;br /&gt;
; Ende des Hauptprogramms&lt;br /&gt;
&lt;br /&gt;
; Unterprogramme&lt;br /&gt;
 &lt;br /&gt;
 ; ein Zeichen per UART senden&lt;br /&gt;
&lt;br /&gt;
sende_einzelzeichen:&lt;br /&gt;
    sbis    UCSRA,UDRE          ; Warten, bis UDR bereit ist ...&lt;br /&gt;
    rjmp    sende_einzelzeichen&lt;br /&gt;
    out     UDR, zeichen        ; und Zeichen ausgeben&lt;br /&gt;
    ret&lt;br /&gt;
&lt;br /&gt;
; mehrere Zeichen ausgeben, welche durch Z adressiert werden&lt;br /&gt;
; Anzahl in temp1&lt;br /&gt;
&lt;br /&gt;
sende_zeichen:&lt;br /&gt;
    sbis    UCSRA,UDRE          ; Warten, bis UDR bereit ist ...&lt;br /&gt;
    rjmp    sende_zeichen&lt;br /&gt;
    ld      zeichen, Z+         ; Zeichen laden&lt;br /&gt;
    out     UDR, zeichen        ; und Zeichen ausgeben&lt;br /&gt;
    dec     temp1&lt;br /&gt;
    brne    sende_zeichen&lt;br /&gt;
    ret&lt;br /&gt;
&lt;br /&gt;
; 32 Bit Zahl in ASCII umwandeln&lt;br /&gt;
; Zahl liegt in temp1..4&lt;br /&gt;
; Ergebnis ist ein 10stelliger ASCII String, welcher im SRAM abgelegt wird&lt;br /&gt;
; Adressierung über X Pointer&lt;br /&gt;
; mehrfache Subtraktion wird als Ersatz für eine Division durchgeführt.&lt;br /&gt;
&lt;br /&gt;
Int_to_ASCII:&lt;br /&gt;
    &lt;br /&gt;
    push    ZL                      ; Register sichern&lt;br /&gt;
    push    ZH&lt;br /&gt;
    push    temp5&lt;br /&gt;
    push    temp6&lt;br /&gt;
&lt;br /&gt;
    ldi     ZL,low(Tabelle*2)       ; Zeiger auf Tabelle&lt;br /&gt;
    ldi     ZH,high(Tabelle*2)&lt;br /&gt;
    ldi     temp5, 10               ; Schleifenzähler&lt;br /&gt;
&lt;br /&gt;
Int_to_ASCII_schleife:&lt;br /&gt;
    ldi     temp6, -1+&#039;0&#039;           ; Ziffernzähler zählt direkt im ASCII Code &lt;br /&gt;
    lpm     z0,Z+                   ; Nächste Zahl laden&lt;br /&gt;
    lpm     z1,Z+&lt;br /&gt;
    lpm     z2,Z+&lt;br /&gt;
    lpm     z3,Z+&lt;br /&gt;
&lt;br /&gt;
Int_to_ASCII_ziffer:&lt;br /&gt;
    inc     temp6                   ; Ziffer erhöhen&lt;br /&gt;
    sub     temp1, z0               ; Zahl subrahieren&lt;br /&gt;
    sbc     temp2, z1               ; 32 Bit&lt;br /&gt;
    sbc     temp3, z2&lt;br /&gt;
    sbc     temp4, z3&lt;br /&gt;
    brge    Int_to_ASCII_ziffer     ; noch kein Unterlauf, nochmal&lt;br /&gt;
&lt;br /&gt;
    add     temp1, z0               ; Unterlauf, eimal wieder addieren&lt;br /&gt;
    adc     temp2, z1               ; 32 Bit&lt;br /&gt;
    adc     temp3, z2&lt;br /&gt;
    adc     temp4, z3                                            &lt;br /&gt;
    st      X+,temp6                ; Ziffer speichern&lt;br /&gt;
    dec     temp5&lt;br /&gt;
    brne    Int_to_ASCII_schleife   ; noch eine Ziffer?&lt;br /&gt;
&lt;br /&gt;
    pop     temp6&lt;br /&gt;
    pop     temp5&lt;br /&gt;
    pop     ZH&lt;br /&gt;
    pop     ZL                      ; Register wieder herstellen&lt;br /&gt;
    ret&lt;br /&gt;
&lt;br /&gt;
; Tabelle mit Zahlen für die Berechung der Ziffern&lt;br /&gt;
; 1 Milliarde bis 1&lt;br /&gt;
Tabelle:&lt;br /&gt;
.dd 1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1&lt;br /&gt;
&lt;br /&gt;
; 16 Bit Wert in Spannung umrechnen&lt;br /&gt;
;&lt;br /&gt;
; = 16Bitx16Bit=32 Bit Multiplikation&lt;br /&gt;
; = vier 8x8 Bit Multiplikationen&lt;br /&gt;
;&lt;br /&gt;
; adlow/adhigh * temp5/temp6&lt;br /&gt;
&lt;br /&gt;
mul_16x16:&lt;br /&gt;
    push    zeichen&lt;br /&gt;
    clr     temp1                   ; 32 Bit Akku löschen&lt;br /&gt;
    clr     temp2&lt;br /&gt;
    clr     temp3&lt;br /&gt;
    clr     temp4&lt;br /&gt;
    clr     zeichen                 ; Null, für Carry-Addition&lt;br /&gt;
&lt;br /&gt;
    mul     adlow, temp5            ; erste Multiplikation&lt;br /&gt;
    add     temp1, r0               ; und akkumulieren&lt;br /&gt;
    adc     temp2, r1&lt;br /&gt;
&lt;br /&gt;
    mul     adhigh, temp5           ; zweite Multiplikation&lt;br /&gt;
    add     temp2, r0               ; und gewichtet akkumlieren&lt;br /&gt;
    adc     temp3, r1&lt;br /&gt;
&lt;br /&gt;
    mul     adlow, temp6            ; dritte Multiplikation&lt;br /&gt;
    add     temp2, r0               ; und gewichtet akkumlieren&lt;br /&gt;
    adc     temp3, r1&lt;br /&gt;
    adc     temp4, zeichen          ; carry addieren&lt;br /&gt;
&lt;br /&gt;
    mul     adhigh, temp6           ; vierte Multiplikation&lt;br /&gt;
    add     temp3, r0               ; und gewichtet akkumlieren&lt;br /&gt;
    adc     temp4, r1&lt;br /&gt;
&lt;br /&gt;
    pop     zeichen&lt;br /&gt;
    ret&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für alle, die es besonders eilig haben gibt es hier eine geschwindigkeitsoptimierte Version der Integer in ASCII Umwandlung. Zunächst wird keine Schleife verwendet sondern alle Stufen der Schleife direkt hingeschrieben. Das braucht zwar mehr Programmspeicher, ist aber schneller. Ausserdem wird abwechselnd subtrahiert und addiert, dadurch entfällt das immer wieder notwendige addieren nach dem Unterlauf. Zu guter Letzt werden die Berechnungen nur mit der minimal notwenigen Wortbreite durchgeführt. Am Anfang mit 32 Bit, dann nur noch mit 16 bzw. 8 Bit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
; 32 Bit Zahl in ASCII umwandeln&lt;br /&gt;
; geschwindigkeitsoptimierte Version&lt;br /&gt;
; Zahl liegt in temp1..4&lt;br /&gt;
; Ergebnis ist ein 10stelliger ASCII String, welcher im SRAM abgelegt wird&lt;br /&gt;
; Adressierung über X Pointer&lt;br /&gt;
&lt;br /&gt;
Int_to_ASCII:&lt;br /&gt;
    ldi     temp5, -1 + &#039;0&#039;&lt;br /&gt;
_a1ser:&lt;br /&gt;
    inc     temp5&lt;br /&gt;
    subi    temp1,BYTE1(1000000000) ; - 1.000.000.000&lt;br /&gt;
    sbci    temp2,BYTE2(1000000000)&lt;br /&gt;
    sbci    temp3,BYTE3(1000000000)&lt;br /&gt;
    sbci    temp4,BYTE4(1000000000)&lt;br /&gt;
    brcc    _a1ser&lt;br /&gt;
&lt;br /&gt;
    st      X+,temp5                ; im Puffer speichern&lt;br /&gt;
    ldi     temp5, 10 + &#039;0&#039;&lt;br /&gt;
_a2ser:&lt;br /&gt;
    dec     temp5&lt;br /&gt;
    subi    temp1,BYTE1(-100000000) ; + 100.000.000&lt;br /&gt;
    sbci    temp2,BYTE2(-100000000)&lt;br /&gt;
    sbci    temp3,BYTE3(-100000000)&lt;br /&gt;
    sbci    temp4,BYTE4(-100000000)&lt;br /&gt;
    brcs    _a2ser&lt;br /&gt;
&lt;br /&gt;
    st      X+,temp5                ; im Puffer speichern&lt;br /&gt;
    ldi     temp5, -1 + &#039;0&#039;&lt;br /&gt;
_a3ser:&lt;br /&gt;
    inc     temp5&lt;br /&gt;
    subi    temp1,low(10000000)     ; - 10.000.000&lt;br /&gt;
    sbci    temp2,high(10000000)&lt;br /&gt;
    sbci    temp3,BYTE3(10000000)&lt;br /&gt;
    sbci    temp4,BYTE4(10000000)&lt;br /&gt;
    brcc    _a3ser&lt;br /&gt;
&lt;br /&gt;
    st      X+,temp5                ; im Puffer speichern&lt;br /&gt;
    ldi     temp5, 10 + &#039;0&#039;&lt;br /&gt;
_a4ser:&lt;br /&gt;
    dec     temp5&lt;br /&gt;
    subi    temp1,low(-1000000)     ; + 1.000.000&lt;br /&gt;
    sbci    temp2,high(-1000000)&lt;br /&gt;
    sbci    temp3,BYTE3(-1000000)&lt;br /&gt;
    sbci    temp4,BYTE4(-1000000)&lt;br /&gt;
    brcs    _a4ser&lt;br /&gt;
&lt;br /&gt;
    st      X+,temp5                ; im Puffer speichern&lt;br /&gt;
    ldi     temp5, -1 + &#039;0&#039;&lt;br /&gt;
_a5ser:&lt;br /&gt;
    inc     temp5&lt;br /&gt;
    subi    temp1,low(100000)       ; -100.000&lt;br /&gt;
    sbci    temp2,high(100000)&lt;br /&gt;
    sbci    temp3,BYTE3(100000)&lt;br /&gt;
    brcc    _a5ser&lt;br /&gt;
&lt;br /&gt;
    st      X+,temp5                ; im Puffer speichern&lt;br /&gt;
    ldi     temp5, 10 + &#039;0&#039;&lt;br /&gt;
_a6ser:&lt;br /&gt;
    dec     temp5&lt;br /&gt;
    subi    temp1,low(-10000)       ; +10,000&lt;br /&gt;
    sbci    temp2,high(-10000)&lt;br /&gt;
    sbci    temp3,BYTE3(-10000)&lt;br /&gt;
    brcs    _a6ser&lt;br /&gt;
&lt;br /&gt;
    st      X+,temp5                ; im Puffer speichern &lt;br /&gt;
    ldi     temp5, -1 + &#039;0&#039;&lt;br /&gt;
_a7ser:&lt;br /&gt;
    inc     temp5&lt;br /&gt;
    subi    temp1,low(1000)         ; -1000&lt;br /&gt;
    sbci    temp2,high(1000)&lt;br /&gt;
    brcc    _a7ser&lt;br /&gt;
 &lt;br /&gt;
    st      X+,temp5                ; im Puffer speichern&lt;br /&gt;
    ldi     temp5, 10 + &#039;0&#039;&lt;br /&gt;
_a8ser:&lt;br /&gt;
    dec     temp5&lt;br /&gt;
    subi    temp1,low(-100)         ; +100&lt;br /&gt;
    sbci    temp2,high(-100)&lt;br /&gt;
    brcs    _a8ser&lt;br /&gt;
 &lt;br /&gt;
    st      X+,temp5                ; im Puffer speichern&lt;br /&gt;
    ldi     temp5, -1 + &#039;0&#039;&lt;br /&gt;
_a9ser:&lt;br /&gt;
    inc     temp5&lt;br /&gt;
    subi    temp1, 10               ; -10&lt;br /&gt;
    brcc    _a9ser&lt;br /&gt;
    &lt;br /&gt;
    st      X+,temp5                ; im Puffer speichern&lt;br /&gt;
    ldi     temp5, 10 + &#039;0&#039;&lt;br /&gt;
_a10ser:&lt;br /&gt;
    dec     temp5&lt;br /&gt;
    subi    temp1, -1               ; +1&lt;br /&gt;
    brcs    _a10ser&lt;br /&gt;
&lt;br /&gt;
    st      X+,temp5                ; im Puffer speichern&lt;br /&gt;
    ret&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
{{Navigation_zurückhochvor|&lt;br /&gt;
zurücktext=Uhr|&lt;br /&gt;
zurücklink=AVR-Tutorial: Uhr|&lt;br /&gt;
hochtext=Inhaltsverzeichnis|&lt;br /&gt;
hochlink=AVR-Tutorial|&lt;br /&gt;
vortext=Tasten|&lt;br /&gt;
vorlink=AVR-Tutorial: Tasten}}&lt;br /&gt;
&lt;br /&gt;
[[Category:AVR-Tutorial|ADC]]&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR-Tutorial:_ADC&amp;diff=67020</id>
		<title>AVR-Tutorial: ADC</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR-Tutorial:_ADC&amp;diff=67020"/>
		<updated>2012-06-25T15:06:01Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: Satzstellung zum Verständnis korrigiert.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Was macht der ADC? ==&lt;br /&gt;
&lt;br /&gt;
Wenn es darum geht, Spannungen zu messen, wird der Analog-/Digital-Wandler (kurz: A/D-Wandler) oder englisch [[ADC | &#039;&#039;&#039;A&#039;&#039;&#039;nalog &#039;&#039;&#039;D&#039;&#039;&#039;igital &#039;&#039;&#039;C&#039;&#039;&#039;onverter]] (ADC) benutzt. Er konvertiert eine elektrische Spannung in eine Digitalzahl. Prinzipiell wird dabei die Messspannung mit einer Referenzspannung verglichen. Die Zahl drückt daher das Verhältnis der Messspannung zu dieser Referenzspannung aus. Sie kann in gewohnter Weise von einem [[Mikrocontroller]] weiterverarbeitet werden.&lt;br /&gt;
&lt;br /&gt;
== Elektronische Grundlagen ==&lt;br /&gt;
&lt;br /&gt;
Die ADC-Versorgungsspannung (AVCC) darf maximal um +/-0,3V von der Versorgung des Digitalteils (VCC) abweichen, jedoch nicht 5,5V überschreiten. Die externe Referenzspannung VREF darf nicht kleiner als die im Datenblatt unter ADC Characteristics als VREFmin angegebene Spannung (z.&amp;amp;nbsp;B. ATmega8: 2V, ATmega644P: 1V) und nicht größer als AVCC sein. Die Spannungen an den Wandlereingängen müssen im Intervall GND &amp;amp;le; VIN &amp;amp;le; VREF liegen.&lt;br /&gt;
&lt;br /&gt;
Im Extremfall bedeutet dies: Sei VCC = 5,5V, folgt AVCC_max = VREF_max = VIN_max = 5,5V.&lt;br /&gt;
&lt;br /&gt;
Der Eingangswiderstand des ADC liegt in der Größenordnung von einigen Megaohm, so dass der ADC die Signalquelle praktisch nicht belastet. Desweiteren enthält der Mikrocontroller eine sog. &#039;&#039;&#039;Sample&amp;amp;Hold&#039;&#039;&#039; Schaltung. Dies ist wichtig, wenn sich während des Wandlungsvorgangs die Eingangsspannung verändert, da die AD-Wandlung eine bestimmte Zeit dauert. Die Sample&amp;amp;Hold-Stufe speichert zum Beginn der Wandlung die anliegende Spannung und hält sie während des Wandlungsvorgangs konstant.&lt;br /&gt;
&lt;br /&gt;
=== Beschaltung des ADC-Eingangs ===&lt;br /&gt;
&lt;br /&gt;
Um den ADC im Folgenden zu testen wird eine einfache Schaltung an den PC0-Pin des ATmega8 angeschlossen. Dies ist der ADC-Kanal 0. Bei anderen AVR-Typen liegt der entsprechende Eingang auf einem andern Pin, hier ist ein Blick ins Datenblatt angesagt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tut_ADC_01.gif|framed|center|Testschaltung]]&lt;br /&gt;
&lt;br /&gt;
Der Wert des [[Potentiometer]]s ist Dank des hohen Eingangswiderstandes des ADC ziemlich unkritisch. Es kann jedes Potentiometer von 1k&amp;amp;Omega; bis 1M&amp;amp;Omega; benutzt werden.&lt;br /&gt;
&lt;br /&gt;
Wenn andere Messgrößen gemessen werden sollen, so bedient man sich oft und gern des Prinzips des [[Spannungsteiler]]s. Der [http://www.mikrocontroller.net/articles/Kategorie:Sensorik Sensor] ist ein veränderlicher Widerstand. Zusammen mit einem zweiten, konstanten Widerstand bekannter Größe wird ein Spannungsteiler aufgebaut. Aus der Variation der durch den variablen Spannungsteiler entstehenden Spannung kann auf den Messwert zurückgerechnet werden.&lt;br /&gt;
&lt;br /&gt;
      Vcc ----------+                Vcc ---------+&lt;br /&gt;
                    |                             |&lt;br /&gt;
                   ---                         Sensor,&lt;br /&gt;
                   | |                     der seinen Widerstand&lt;br /&gt;
                   | |                     in Abhängigkeit der&lt;br /&gt;
                   ---                     Messgröße ändert&lt;br /&gt;
                    |                             |&lt;br /&gt;
                    +------- PC0                  +-------- PC0&lt;br /&gt;
                    |                             |&lt;br /&gt;
                Sensor,                          ---&lt;br /&gt;
           der seinen Widerstand                 | |&lt;br /&gt;
           in Abhängigkeit der                   | |&lt;br /&gt;
           Messgröße ändert                      ---&lt;br /&gt;
                    |                             |&lt;br /&gt;
       GND ---------+                 GND --------+&lt;br /&gt;
&lt;br /&gt;
Die Größe des zweiten Widerstandes im Spannungsteiler richtet sich nach dem Wertebereich, in welchem der Sensor seinen Wert ändert. Als Daumenregel kann man sagen, dass der Widerstand so gross sein sollte wie der Widerstand des Sensors in der Mitte des Messbereichs.&lt;br /&gt;
&lt;br /&gt;
Beispiel: Wenn ein [[Temperatursensor]] seinen Widerstand von 0..100 Grad von 2k&amp;amp;Omega; auf 5k&amp;amp;Omega; ändert, sollte der zweite Widerstand eine Grösse von etwa (2+5)/2 = 3,5k&amp;amp;Omega; haben.&lt;br /&gt;
&lt;br /&gt;
===Referenzspannung AREF===&lt;br /&gt;
[[bild:adc_connection.png|thumb|right|300px|Beschaltung von A&amp;lt;sub&amp;gt;REF&amp;lt;/sub&amp;gt;]]&lt;br /&gt;
Der ADC benötigt für seine Arbeit eine Referenzspannung. Dabei gibt es 2 Möglichkeiten:&lt;br /&gt;
* interne Referenzspannung&lt;br /&gt;
* externe Referenzspannung&lt;br /&gt;
&lt;br /&gt;
Bei der Umstellung der Referenzspannung sind Wartezeiten zu beachten, bis die ADC-Hardware einsatzfähig ist (Datenblatt und  [http://www.mikrocontroller.net/topic/165513]).&lt;br /&gt;
&lt;br /&gt;
==== Interne Referenzspannung ====&lt;br /&gt;
&lt;br /&gt;
Mittels Konfigurationsregister können beim ATmega8 verschiedene Referenzspannungen eingestellt werden. Dies umfasst die Versorgungsspannung AVcc sowie eine vom AVR bereitgestellte Spannung von 2,56V (bzw. bei den neueren AVRs 1,1V, wie z.&amp;amp;nbsp;B. beim ATtiny13, ATmega48, 88, 168, ...). In beiden Fällen wird an den AREF-Pin des Prozessors ein Kondensator von 100nF als Minimalbeschaltung nach Masse angeschlossen, um die Spannung zu puffern/glätten. Es ist jedoch zu beachten, dass die interne Referenzspannung ca. +/-10% vom Nominalwert abweichen kann, vgl. dazu das Datenblatt Abschnitt ADC Characteristics VINT (z.&amp;amp;nbsp;B. ATmega8: 2,3-2,9V, ATmega324P: 2,33-2,79V bzw. 1,0-1,2V &amp;quot;Values are guidelines only.&amp;quot;). Die typische Abweichung der internen Referenzspannung vom Sollwert bei einigen AVR-Controllern wird in [http://www.schramm-software.de/tipps/adc-referenzspannung/ dieser Testschaltung] exemplarisch untersucht.&lt;br /&gt;
&lt;br /&gt;
==== Externe Referenzspannung ====&lt;br /&gt;
&lt;br /&gt;
Wird eine externe Referenz verwendet, so wird diese an AREF angeschlossen. Aber aufgepasst! Wenn eine Referenz in Höhe der Versorgungsspannung benutzt werden soll, so ist es besser, dies über die interne Referenz zu tun. Außer bei anderen Spannungen als 5V bzw. 2,56V gibt es eigentlich keinen Grund, an AREF eine Spannungsquelle anzuschließen. In Standardanwendungen fährt man immer besser, wenn die interne Referenzspannung mit einem Kondensator an AREF benutzt wird. Die 10µH-Spule L1 kann man meist auch durch einen 47Ω-Widerstand ersetzen.&lt;br /&gt;
&lt;br /&gt;
== Ein paar ADC-Grundlagen ==&lt;br /&gt;
&lt;br /&gt;
Der ADC ist ein 10-Bit ADC, d.h. er liefert Messwerte im Bereich 0 bis 1023. Liegt am Eingangskanal 0V an, so liefert der ADC einen Wert von 0. Hat die Spannung am Eingangskanal die Referenzspannung erreicht (stimmt nicht ganz), so liefert der ADC einen Wert von 1023. Unterschreitet oder überschreitet die zu messende Spannung diese Grenzen, so liefert der ADC 0 bzw. 1023. Wird die Auflösung von 10 Bit nicht benötigt, so ist es möglich die Ausgabe durch ein Konfigurationsregister so einzuschränken, dass ein leichter Zugriff auf die 8 höchstwertigen Bits möglich ist.&lt;br /&gt;
&lt;br /&gt;
Wie bei vielen analogen Schaltungen, unterliegt auch der ADC einem Rauschen. Das bedeutet, dass man nicht davon ausgehen sollte, dass der ADC bei konstanter Eingangsspannung auch immer denselben konstanten Wert ausgibt. Ein &amp;quot;Zittern&amp;quot; der niederwertigsten 2 Bits ist durchaus nicht ungewöhnlich. Besonders hervorgehoben werden soll an dieser Stelle nochmals die Qualität der Referenzspannung. Diese Qualität geht in erheblichem Maße in die Qualität der Wandelergebnisse ein. Die Beschaltung von AREF mit einem Kondensator ist die absolut notwendige Mindestbeschaltung, um eine einigermaßen akzeptable Referenzspannung zu erhalten. Reicht dies nicht aus, so kann die Qualität einer Messung durch &amp;lt;i&amp;gt;Oversampling&amp;lt;/i&amp;gt; erhöht werden. Dazu werden mehrere Messungen gemacht und deren Mittelwert gebildet.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tut_ADC_03.gif|right|framed]]&lt;br /&gt;
Oft interessiert auch der absolute Spannungspegel nicht. Im Beschaltungsbeispiel oben ist man normalerweise nicht direkt an der am Poti entstehenden Spannung interessiert. Viel mehr ist diese Spannung nur ein notwendiges Übel, um die Stellung des Potis zu bestimmen. In solchen Fällen kann die Poti-Beschaltung wie folgt abgewandelt werden:&lt;br /&gt;
&lt;br /&gt;
Hier wird AREF (bei interner Referenz) als vom µC gelieferte Spannung benutzt und vom Spannungsteiler bearbeitet wieder an den µC zur Messung zurückgegeben. Dies hat den Vorteil, dass der Spannungsteiler automatisch Spannungen bis zur Höhe der Referenzspannung ausgibt, ohne dass eine externe Spannung mit AREF abgeglichen werden müsste. Selbst Schwankungen in AREF wirken sich hier nicht mehr aus, da ja das Verhältnis der Spannungsteilerspannung zu AREF immer konstant bleibt (ratiometrische Messung). Und im Grunde bestimmt der ADC ja nur dieses Verhältnis. Wird diese Variante gewählt, so muss berücksichtigt werden, dass die Ausgangsspannung an AREF nicht allzusehr belastet wird. Der Spannungsteiler muss einen Gesamtwiderstand von deutlich über 10k&amp;amp;Omega; besitzen. Werte von 100k&amp;amp;Omega; oder höher sind anzustreben. Verwendet man anstatt AREF AVCC und schaltet auch die Referenzspannung auf AVCC um, ist die Belastung durch den Poti unkritisch, weil hier die Stromversorgung direkt zur Speisung verwendet wird.&lt;br /&gt;
&lt;br /&gt;
Ist hingegen die absolute Spannung von Interesse, so muss man darauf achten, dass ein ADC in [[Digital | digitalen]] Bereichen arbeitet ([[Quantisierung]]). An einem einfacheren Beispiel soll demonstriert werden was damit gemeint ist.&lt;br /&gt;
&lt;br /&gt;
Angenommen der ADC würde nur 5 Stufen auflösen können und AREF sei 5V:&lt;br /&gt;
&lt;br /&gt;
      Volt    Wert vom ADC&lt;br /&gt;
&lt;br /&gt;
       0 -+&lt;br /&gt;
          |         0&lt;br /&gt;
       1 -+&lt;br /&gt;
          |         1&lt;br /&gt;
       2 -+&lt;br /&gt;
          |         2&lt;br /&gt;
       3 -+&lt;br /&gt;
          |         3&lt;br /&gt;
       4 -+&lt;br /&gt;
          |         4&lt;br /&gt;
       5 -+&lt;br /&gt;
&lt;br /&gt;
Ein ADC Wert von 0 bedeutet also keineswegs, dass die zu messende Spannung exakt den Wert 0 hat. Es bedeutet lediglich, dass die Messspannung irgendwo im Bereich von 0V bis 1V liegt. Sinngemäß bedeutet daher auch das Auftreten des Maximalwertes nicht, dass die Spannung exakt AREF beträgt, sondern lediglich, dass die Messspannung sich irgendwo im Bereich der letzten Stufe (also von 4V bis 5V) bewegt.&lt;br /&gt;
&lt;br /&gt;
== Umrechnung des ADC Wertes in eine Spannung ==&lt;br /&gt;
&lt;br /&gt;
Die Größe eines &amp;quot;Bereiches&amp;quot; bestimmt sich also zu&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
   Bereichsbreite = \frac {Referenzspannung}{Maximalwert}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Messwert vom ADC rechnet sich dann wie folgt in eine Spannung um:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
  Spannung = ADCwert \cdot \frac {Referenzspannung} {Maximalwert}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wird der ADC also mit 10 Bit an 5 V betrieben, so lauten die Umrechnungen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
   Bereichsbreite = \frac{5~\text{V}}{1023} = 0,004883~\text{V} = 4,883~\text{mV}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;&lt;br /&gt;
   Spannung = ADCwert \cdot 4,883~\text{mV}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn man genau hinsieht stellt man fest, dass sowohl die Referenzspannung als auch der Maximalwert Konstanten sind. D.h. der Quotient aus Referenzspannung und Maximalwert ist konstant. Somit muss nicht immer eine Addition und Division ausgeführt werden, sondern nur eine Multiplikation! Das spart viel Aufwand und Rechenzeit! Dabei kann sinnvollerweise [[Festkommaarithmetik]] zum Einsatz kommen.&lt;br /&gt;
&lt;br /&gt;
== Kalibrierung ==&lt;br /&gt;
Hat man eine externe, genaue Referenzspannung zu Hand, dann kann ein Korrekturfaktor berechnet werden, mit dem die Werte des ADCs im Nachinein korrigiert werden können. Dies geschieht normalerweise über eine sogenannte gain offset Korrektur an einer Geraden oder einer Parabel. In erster Näherung kann man auch die interne Referenzspannung um das Inverse des ermittelten Korrekturwertes verstellen, um einen genaueren bereits digitalisierten Wert zu bekommen.&lt;br /&gt;
&lt;br /&gt;
== Die Steuerregister des ADC ==&lt;br /&gt;
&lt;br /&gt;
=== ADMUX ===&lt;br /&gt;
&lt;br /&gt;
{{Byte|ADMUX| REFS1 | REFS0 | ADLAR |       |  MUX3 |  MUX2 |  MUX1 |  MUX0}}&lt;br /&gt;
&lt;br /&gt;
* Referenzspannung &amp;lt;i&amp;gt;REFS1, REFS0&amp;lt;/i&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{| {{Tabelle}}&lt;br /&gt;
|-  style=&amp;quot;background-color:#ffddcc&amp;quot;&lt;br /&gt;
!REFS1||REFS0||Referenz&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
||externe Referenz&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|interne Referenz: Avcc&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
||wird beim Mega8 nicht benutzt&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
||interne Referenz: 2.56 Volt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
* Ausrichtung &amp;lt;i&amp;gt;ADLAR&amp;lt;/i&amp;gt;&lt;br /&gt;
&amp;lt;table border=&amp;quot;0&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;ADLAR&amp;lt;/th&amp;gt;&amp;lt;th align=&amp;quot;left&amp;quot;&amp;gt;&amp;lt;/th&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;0&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Das Ergebnis wird in den Registern ADCH/ADCL rechtsbündig ausgerichtet. Die 8 niederwertigsten Bits des Ergebnisses werden in ADCL abgelegt. Die verbleibenden 2 Bits des Ergebnisses werden im Register ADCH in den Bits 0 und 1 abgelegt.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;tr&amp;gt;&lt;br /&gt;
&amp;lt;td&amp;gt;1&amp;lt;/td&amp;gt;&amp;lt;td&amp;gt;Das Ergebnis wird in den Registern ADCH/ADCL linksbündig ausgerichtet. Die 8 höchstwertigen Bits des Ergebnisses werden in ADCH abgelegt. Die verbleibenden 2 niederwertigen Bits werden im Register ADCL in den Bits 6 und 7 abgelegt.&amp;lt;/td&amp;gt;&lt;br /&gt;
&amp;lt;/tr&amp;gt;&lt;br /&gt;
&amp;lt;/table&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* Kanalwahl &amp;lt;i&amp;gt;MUX3, MUX2, MUX1, MUX0&amp;lt;/i&amp;gt;&lt;br /&gt;
{| {{Tabelle}}&lt;br /&gt;
|-  style=&amp;quot;background-color:#ffddcc&amp;quot;&lt;br /&gt;
!MUX3||MUX2||MUX1||MUX0||Kanal&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
||Kanal 0, Pin PC0&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
||Kanal 1, Pin PC1&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
||Kanal 2, Pin PC2&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
||Kanal 3, Pin PC3&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
||Kanal 4, Pin PC4&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
||Kanal 5, Pin PC5&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
||Kanal 6 (*)&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
||Kanal 7 (*)&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
||1.23V, Vbg&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
||0V, GND&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
(*) Bei Atmega8 nur in der Gehäusebauform TQFP und MLF verfügbar, nicht in PDIP&lt;br /&gt;
&lt;br /&gt;
===ADCSRA===&lt;br /&gt;
{{Byte|ADCSRA|  ADEN |  ADSC |  ADFR |  ADIF |  ADIE | ADPS2 | ADPS1 | ADPS0}}&lt;br /&gt;
&lt;br /&gt;
;ADEN: &amp;quot;ADC Enable&amp;quot;: Mittels ADEN wird der ADC ein und ausgeschaltet. Eine 1 an dieser Bitposition schaltet den ADC ein.&lt;br /&gt;
; ADSC: &amp;quot;ADC Start Conversion&amp;quot;: Wird eine 1 an diese Bitposition geschrieben, so beginnt der ADC mit der Wandlung. Das Bit bleibt auf 1, solange die Wandlung im Gange ist. Wenn die Wandlung beendet ist, wird dieses Bit von der ADC Hardware wieder auf 0 gesetzt.&lt;br /&gt;
; ADFR: &amp;quot;ADC Free Running&amp;quot;: Wird eine 1 an ADFR geschrieben, so wird der ADC im Free Running Modus betrieben. Dabei startet der ADC nach dem Abschluss einer Messung automatisch die nächste Messung. Die erste Messung wird ganz normal über das Setzen des ADSC-Bits gestartet.&lt;br /&gt;
; ADIF: &amp;quot;ADC Interrupt Flag&amp;quot;: Wenn eine Messung abgeschlossen ist, wird das ADIF Bit gesetzt. Ist zusätzlich noch das &amp;lt;i&amp;gt;ADIE&amp;lt;/i&amp;gt; Bit gesetzt, so wird ein Interrupt ausgelöst und der entsprechende Interrupt Handler angesprungen.&lt;br /&gt;
; ADIE: &amp;quot;ADC Interrupt Enable&amp;quot;: Wird eine 1 an ADIE geschrieben, so löst der ADC nach Beendigung einer Messung einen Interrupt aus.&lt;br /&gt;
; ADPS2, ADPS1, ADPS0: &amp;quot;ADC Prescaler&amp;quot;: Mit dem Prescaler kann die ADC-Frequenz gewählt werden. Laut Datenblatt sollte diese für die optimale Auflösung zwischen 50kHz und 200kHz liegen. Ist die Wandlerfrequenz langsamer eingestellt, kann es passieren dass die eingebaute Sample &amp;amp; Hold Schaltung die Eingangsspannung nicht lange genug konstant halten kann. Ist die Frequenz aber zu schnell eingestellt, dann kann es passieren dass sich die Sample &amp;amp; Hold Schaltung nicht schnell genug an die Eingangsspannung anpassen kann.&lt;br /&gt;
&lt;br /&gt;
{| {{Tabelle}}&lt;br /&gt;
|-  style=&amp;quot;background-color:#ffddcc&amp;quot;&lt;br /&gt;
!ADPS2||ADPS1||ADPS0||Vorteiler&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|2&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|2&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|4&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|8&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|16&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|32&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|0&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|64&lt;br /&gt;
|-&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|1&lt;br /&gt;
|align=&amp;quot;center&amp;quot;|128&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Die Ergebnisregister ADCL und ADCH ==&lt;br /&gt;
&lt;br /&gt;
Da das Ergebnis des ADC ein 10 Bit Wert ist, passt dieser Wert naturgemäß nicht in ein einzelnes Register, das ja bekanntlich nur 8 Bit breit ist. Daher wird das Ergebnis in 2 Register &#039;&#039;&#039;ADCL&#039;&#039;&#039; und &#039;&#039;&#039;ADCH&#039;&#039;&#039; abgelegt. Von den 10 Ergebnisbits sind die niederwertigsten 8 im Register &#039;&#039;&#039;ADCL&#039;&#039;&#039; abgelegt und die noch fehlenden 2 Bits werden im Register &#039;&#039;&#039;ADCH&#039;&#039;&#039; an den niederwertigsten Bitpositionen gespeichert.&lt;br /&gt;
&lt;br /&gt;
              ADCH                                   ADCL&lt;br /&gt;
   +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+&lt;br /&gt;
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |&lt;br /&gt;
   +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+&lt;br /&gt;
                             9   8       7   6   5   4   3   2   1   0&lt;br /&gt;
&lt;br /&gt;
Diese Zuordnung kann aber auch geändert werden: Durch setzen des &#039;&#039;&#039;ADLAR&#039;&#039;&#039; Bits im &#039;&#039;&#039;ADMUX&#039;&#039;&#039; Register wird die Ausgabe geändert zu:&lt;br /&gt;
&lt;br /&gt;
              ADCH                                   ADCL&lt;br /&gt;
   +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+&lt;br /&gt;
   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |   |&lt;br /&gt;
   +---+---+---+---+---+---+---+---+   +---+---+---+---+---+---+---+---+&lt;br /&gt;
     9   8   7   6   5   4   3   2       1   0&lt;br /&gt;
&lt;br /&gt;
Dies ist besonders dann interessant, wenn das ADC Ergebnis als 8 Bit Zahl weiterverarbeitet werden soll. In diesem Fall stehen die 8 höchstwertigen Bits bereits verarbeitungsfertig im Register &#039;&#039;&#039;ADCH&#039;&#039;&#039; zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
Beim Auslesen der ADC-Register ist zu beachten:&lt;br /&gt;
Immer zuerst &#039;&#039;&#039;ADCL&#039;&#039;&#039; und erst dann &#039;&#039;&#039;ADCH&#039;&#039;&#039; auslesen. Beim Zugriff auf &#039;&#039;&#039;ADCL&#039;&#039;&#039; wird das &#039;&#039;&#039;ADCH&#039;&#039;&#039; Register gegenüber Veränderungen vom &#039;&#039;&#039;ADC&#039;&#039;&#039; gesperrt. Erst beim nächsten Auslesen des &#039;&#039;&#039;ADCH&#039;&#039;&#039;-Registers wird diese Sperre wieder aufgehoben. Dadurch ist sichergestellt, daß die Inhalte von &#039;&#039;&#039;ADCL&#039;&#039;&#039; und &#039;&#039;&#039;ADCH&#039;&#039;&#039; immer aus demselben Wandlungsergebnis stammen, selbst wenn der &#039;&#039;&#039;ADC&#039;&#039;&#039; im Hintergrund selbsttätig weiterwandelt. Das &#039;&#039;&#039;ADCH&#039;&#039;&#039; Register &#039;&#039;&#039;muss&#039;&#039;&#039; ausgelesen werden!&lt;br /&gt;
&lt;br /&gt;
== Beispiele ==&lt;br /&gt;
&lt;br /&gt;
=== Ausgabe als ADC-Wert ===&lt;br /&gt;
&lt;br /&gt;
Das folgende Programm liest in einer Schleife ständig den ADC aus und verschickt das Ergebnis im Klartext (ASCII) über die [[AVR-Tutorial: UART|UART]]. Zur Verringerung des unvermeidlichen Rauschens werden 256 Messwerte herangezogen und deren Mittelwert als endgültiges Messergebnis gewertet. Dazu werden die einzelnen Messungen in den Registern temp2, temp3, temp4 als 24 Bit Zahl aufaddiert. Die Division durch 256 erfolgt dann ganz einfach dadurch, dass das Register temp2 verworfen wird und die Register temp3 und temp4 als 16 Bit Zahl aufgefasst werden. Eine Besonderheit ist noch, dass je nach dem Wert in temp2 die 16 Bit Zahl in temp3 und temp4 noch aufgerundet wird: Enthält temp2 einen Wert größer als 128, dann wird zur 16 Bit Zahl in temp3/temp4 noch 1 dazu addiert.&lt;br /&gt;
&lt;br /&gt;
In diesem Programm findet man oft die Konstruktion&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
    subi    temp3, low(-1)      ; addieren von 1&lt;br /&gt;
    sbci    temp4, high(-1)     ; addieren des Carry&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dabei handelt es sich um einen kleinen Trick. Um eine Konstante zu einem Register direkt addieren zu können bräuchte man einen Befehl ala addi (Add Immediate, Addiere Konstante), den der AVR aber nicht hat. Ebenso gibt es kein adci (Add with carry Immediate, Addiere Konstante mit Carry Flag). Man müsste also erst eine Konstante in ein Register laden und addieren. Das kostet aber Programmspeicher, Rechenzeit und man muss ein Register zusätzlich frei haben.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
; 16 Bit Addition mit Konstante, ohne Cleverness&lt;br /&gt;
    ldi     temp5, low(1)&lt;br /&gt;
    add     temp3, temp5        ; addieren von 1&lt;br /&gt;
    ldi     temp5, high(1)&lt;br /&gt;
    adc     temp3, temp5        ; addieren des Carry&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier greift man einfach zu dem Trick, dass eine Addition gleich der Subtraktion der negativen Werts ist. Also &amp;quot;addiere +1&amp;quot; ist gleich &amp;quot;subtrahiere -1&amp;quot;. Dafür hat der AVR zwei Befehle, subi (Substract Immediate, Subtrahiere Konstante) und sbci (Substract Immediate with carry, Subtrahiere Konstante mit Carry Flag).&lt;br /&gt;
&lt;br /&gt;
Das folgende Programm ist für den &#039;&#039;&#039;ATmega8&#039;&#039;&#039; geschrieben. Für moderne Nachfolgetypen wie den ATmega88 muss der Code angepasst werden ([http://www.mikrocontroller.net/topic/204069#2011175], [http://www.atmel.com/dyn/resources/prod_documents/doc2553.pdf AVR094: Replacing ATmega8 by ATmega88 (PDF)]).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
.include &amp;quot;m8def.inc&amp;quot;&lt;br /&gt;
&lt;br /&gt;
.def temp1     = r16         ; allgemeines temp Register, zur kurzfristigen Verwendung&lt;br /&gt;
.def temp2     = r17         ; Register für 24 Bit Addition, Lowest Byte&lt;br /&gt;
.def temp3     = r18         ; Register für 24 Bit Addition, Middle Byte&lt;br /&gt;
.def temp4     = r19         ; Register für 24 Bit Addition, Highest Byte&lt;br /&gt;
.def adlow     = r20         ; Ergebnis vom ADC / Mittelwert der 256 Messungen&lt;br /&gt;
.def adhigh    = r21         ; Ergebnis vom ADC / Mittelwert der 256 Messungen&lt;br /&gt;
.def messungen = r22         ; Schleifenzähler für die Messungen&lt;br /&gt;
.def ztausend  = r23         ; Zehntausenderstelle des ADC Wertes&lt;br /&gt;
.def tausend   = r24         ; Tausenderstelle des ADC Wertes&lt;br /&gt;
.def hundert   = r25         ; Hunderterstelle des ADC Wertes&lt;br /&gt;
.def zehner    = r26         ; Zehnerstelle des ADC Wertes&lt;br /&gt;
.def zeichen   = r27         ; Zeichen zur Ausgabe auf den UART&lt;br /&gt;
&lt;br /&gt;
.equ F_CPU = 4000000                            ; Systemtakt in Hz&lt;br /&gt;
.equ BAUD  = 9600                               ; Baudrate&lt;br /&gt;
&lt;br /&gt;
; Berechnungen&lt;br /&gt;
.equ UBRR_VAL   = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; clever runden&lt;br /&gt;
.equ BAUD_REAL  = (F_CPU/(16*(UBRR_VAL+1)))     ; Reale Baudrate&lt;br /&gt;
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ; Fehler in Promille&lt;br /&gt;
&lt;br /&gt;
.if ((BAUD_ERROR&amp;gt;10) || (BAUD_ERROR&amp;lt;-10))       ; max. +/-10 Promille Fehler&lt;br /&gt;
  .error &amp;quot;Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!&amp;quot;&lt;br /&gt;
.endif&lt;br /&gt;
 &lt;br /&gt;
; hier geht das Programm los&lt;br /&gt;
 &lt;br /&gt;
    ldi     temp1, LOW(RAMEND)                  ; Stackpointer initialisieren&lt;br /&gt;
    out     SPL, temp1&lt;br /&gt;
    ldi     temp1, HIGH(RAMEND)&lt;br /&gt;
    out     SPH, temp1&lt;br /&gt;
 &lt;br /&gt;
;UART Initalisierung&lt;br /&gt;
 &lt;br /&gt;
    ldi     temp1, LOW(UBRR_VAL)                    ; Baudrate einstellen&lt;br /&gt;
    out     UBRRL, temp1&lt;br /&gt;
    ldi     temp1, HIGH(UBRR_VAL)&lt;br /&gt;
    out     UBRRH, temp1&lt;br /&gt;
&lt;br /&gt;
    sbi     UCSRB, TXEN                         ; TX einschalten&lt;br /&gt;
 &lt;br /&gt;
; ADC initialisieren: ADC0, Vcc als Referenz, Single Conversion, Vorteiler 128&lt;br /&gt;
&lt;br /&gt;
    ldi     temp1, (1&amp;lt;&amp;lt;REFS0)                   ; Kanal 0, interne Referenzspannung 5V&lt;br /&gt;
    out     ADMUX, temp1&lt;br /&gt;
    ldi     temp1, (1&amp;lt;&amp;lt;ADEN) | (1&amp;lt;&amp;lt;ADPS2) | (1&amp;lt;&amp;lt;ADPS1) | (1&amp;lt;&amp;lt;ADPS0)&lt;br /&gt;
    out     ADCSRA, temp1&lt;br /&gt;
 &lt;br /&gt;
Main:&lt;br /&gt;
    clr     temp1&lt;br /&gt;
    clr     temp2&lt;br /&gt;
    clr     temp3&lt;br /&gt;
    clr     temp4&lt;br /&gt;
&lt;br /&gt;
    ldi     messungen, 0        ; 256 Schleifendurchläufe&lt;br /&gt;
 &lt;br /&gt;
; neuen ADC-Wert lesen  (Schleife - 256 mal)&lt;br /&gt;
&lt;br /&gt;
sample_adc:&lt;br /&gt;
    sbi     ADCSRA, ADSC        ; den ADC starten&lt;br /&gt;
 &lt;br /&gt;
wait_adc:&lt;br /&gt;
    sbic    ADCSRA, ADSC        ; wenn der ADC fertig ist, wird dieses Bit gelöscht&lt;br /&gt;
    rjmp    wait_adc&lt;br /&gt;
 &lt;br /&gt;
; ADC einlesen:&lt;br /&gt;
&lt;br /&gt;
    in      adlow, ADCL         ; immer zuerst LOW Byte lesen&lt;br /&gt;
    in      adhigh, ADCH        ; danach das mittlerweile gesperrte High Byte&lt;br /&gt;
 &lt;br /&gt;
; alle 256 ADC-Werte addieren&lt;br /&gt;
; dazu wird mit den Registern temp4, temp3 und temp2 ein&lt;br /&gt;
; 24-Bit breites Akkumulationsregister gebildet, in dem&lt;br /&gt;
; die 10 Bit Werte aus adhigh, adlow aufsummiert werden&lt;br /&gt;
&lt;br /&gt;
    add     temp2, adlow        ; addieren&lt;br /&gt;
    adc     temp3, adhigh       ; addieren über Carry&lt;br /&gt;
    adc     temp4, temp1        ; addieren über Carry, temp1 enthält 0&lt;br /&gt;
    dec     messungen           ; Schleifenzähler MINUS 1&lt;br /&gt;
    brne    sample_adc          ; wenn noch keine 256 ADC Werte -&amp;gt; nächsten Wert einlesen&lt;br /&gt;
 &lt;br /&gt;
; Aus den 256 Werten den Mittelwert berechnen&lt;br /&gt;
; Mathematisch eine Division durch 256&lt;br /&gt;
; Da aber 2^8 = 256 ist ist da einfach durch das weglassen des niederwertigsten Bytes&lt;br /&gt;
; erreicht werden&lt;br /&gt;
;&lt;br /&gt;
; allerdings wird der Wert noch gerundet&lt;br /&gt;
&lt;br /&gt;
    cpi     temp2,128           ; &amp;quot;Kommastelle&amp;quot; kleiner als 128 ?&lt;br /&gt;
    brlo    no_round            ; ist kleiner ==&amp;gt; Sprung&lt;br /&gt;
 &lt;br /&gt;
; Aufrunden&lt;br /&gt;
    subi    temp3, low(-1)      ; addieren von 1&lt;br /&gt;
    sbci    temp4, high(-1)     ; addieren des Carry&lt;br /&gt;
 &lt;br /&gt;
no_round:&lt;br /&gt;
&lt;br /&gt;
;   Ergebnis nach adlow und adhigh kopieren&lt;br /&gt;
;   damit die temp Register frei werden&lt;br /&gt;
&lt;br /&gt;
    mov     adlow, temp3&lt;br /&gt;
    mov     adhigh, temp4&lt;br /&gt;
 &lt;br /&gt;
;in ASCII umwandeln&lt;br /&gt;
; Division durch mehrfache Subtraktion&lt;br /&gt;
&lt;br /&gt;
    ldi     ztausend, &#039;0&#039;-1     ; Ziffernzähler direkt als ASCII Code&lt;br /&gt;
    ; bzgl. &#039;0&#039;-1 siehe http://www.mikrocontroller.net/topic/198681&lt;br /&gt;
Z_ztausend:&lt;br /&gt;
    inc     ztausend&lt;br /&gt;
    subi    adlow, low(10000)   ; -10,000&lt;br /&gt;
    sbci    adhigh, high(10000) ; 16 Bit&lt;br /&gt;
    brcc    Z_ztausend&lt;br /&gt;
                                    &lt;br /&gt;
    subi    adlow, low(-10000)  ; nach Unterlauf wieder einmal addieren&lt;br /&gt;
    sbci    adhigh, high(-10000); +10,000&lt;br /&gt;
 &lt;br /&gt;
    ldi     tausend, &#039;0&#039;-1      ; Ziffernzähler direkt als ASCII Code&lt;br /&gt;
Z_tausend:&lt;br /&gt;
    inc     tausend&lt;br /&gt;
    subi    adlow, low(1000)    ; -1,000&lt;br /&gt;
    sbci    adhigh, high(1000)  ; 16 Bit&lt;br /&gt;
    brcc    Z_tausend&lt;br /&gt;
                                    &lt;br /&gt;
    subi    adlow, low(-1000)   ; nach Unterlauf wieder einmal addieren&lt;br /&gt;
    sbci    adhigh, high(-1000) ; +1,000&lt;br /&gt;
 &lt;br /&gt;
    ldi     hundert, &#039;0&#039;-1      ; Ziffernzähler direkt als ASCII Code&lt;br /&gt;
Z_hundert:&lt;br /&gt;
    inc     hundert&lt;br /&gt;
    subi    adlow, low(100)     ; -100&lt;br /&gt;
    sbci    adhigh, high(100)   ; 16 Bit&lt;br /&gt;
    brcc    Z_hundert&lt;br /&gt;
                                    &lt;br /&gt;
    subi    adlow, low(-100)    ; nach Unterlauf wieder einmal addieren&lt;br /&gt;
    sbci    adhigh, high(-100)  ; +100&lt;br /&gt;
 &lt;br /&gt;
    ldi     zehner, &#039;0&#039;-1       ; Ziffernzähler direkt als ASCII Code&lt;br /&gt;
Z_zehner:&lt;br /&gt;
    inc     zehner&lt;br /&gt;
    subi    adlow, low(10)      ; -10&lt;br /&gt;
    sbci    adhigh, high(10)    ; 16 Bit&lt;br /&gt;
    brcc    Z_zehner&lt;br /&gt;
                                    &lt;br /&gt;
    subi    adlow, low(-10)     ; nach Unterlauf wieder einmal addieren&lt;br /&gt;
    sbci    adhigh, high(-10)   ; +10&lt;br /&gt;
&lt;br /&gt;
    subi    adlow, -&#039;0&#039;         ; adlow enthält die Einer, Umwandlung in ASCII&lt;br /&gt;
 &lt;br /&gt;
;an UART Senden&lt;br /&gt;
&lt;br /&gt;
    mov     zeichen, ztausend   ; Zehntausender Stelle&lt;br /&gt;
    rcall   transmit&lt;br /&gt;
    mov     zeichen, tausend    ; Tausender Stelle ausgeben&lt;br /&gt;
    rcall   transmit    &lt;br /&gt;
    mov     zeichen, hundert    ; Hunderter Stelle ausgeben&lt;br /&gt;
    rcall   transmit&lt;br /&gt;
    mov     zeichen, zehner     ; Zehner Stelle ausgeben&lt;br /&gt;
    rcall   transmit&lt;br /&gt;
    mov     zeichen, adlow      ; Einer Stelle ausgeben&lt;br /&gt;
    rcall   transmit&lt;br /&gt;
    ldi     zeichen, 13         ; CR, Carrige Return (Wagenrücklauf)&lt;br /&gt;
    rcall   transmit&lt;br /&gt;
    ldi     zeichen, 10         ; LF, Line Feed (Neue Zeile)&lt;br /&gt;
    rcall   transmit&lt;br /&gt;
 &lt;br /&gt;
    rjmp    Main&lt;br /&gt;
 &lt;br /&gt;
transmit:&lt;br /&gt;
    sbis    UCSRA,UDRE          ; Warten, bis UDR bereit ist ...&lt;br /&gt;
    rjmp    transmit&lt;br /&gt;
    out     UDR, zeichen        ; und Zeichen ausgeben&lt;br /&gt;
    ret&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ausgabe als Spannungswert ===&lt;br /&gt;
&lt;br /&gt;
Das zweite Beispiel ist schon um einiges größer. Hier wird der gemittelte ADC-Wert in eine Spannung umgerechnet. Dazu wird [[Festkommaarithmetik]] verwendet. Die Daten sind in diesem Fall&lt;br /&gt;
&lt;br /&gt;
* Referenzspannung : 5V&lt;br /&gt;
* alte Auflösung   : 5V / 1024 = 4,8828125mV&lt;br /&gt;
* neue Auflösung   : 1mV&lt;br /&gt;
&lt;br /&gt;
-&amp;gt; Faktor = 4,8828125mV / 1mV = 4,8828125&lt;br /&gt;
&lt;br /&gt;
Der Faktor wird dreimal mit 10 multipliziert und das Ergebnis auf 4883 gerundet. Die neue Auflösung wird dreimal durch 10 dividiert und beträgt 1&amp;amp;mu;V. Der relative Fehler beträgt&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; F_r = \frac {4883}{4882,8125}-1 = 0,00384% = \frac {1}{26042}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Fehler ist absolut vernachlässigbar. Nach der Multiplikation des ADC-Wertes mit 4883 liegt die gemessene Spannung in der Einheit &amp;amp;mu;V vor. Vorsicht! Das ist &#039;&#039;&#039;nicht&#039;&#039;&#039; die reale [[Auflösung und Genauigkeit]], nur rein mathematisch bedingt. Für maximale Genauigkeit sollte man die Versorgungsspannung AVCC, welche hier gleichzeitig als Referenzspannung dient, exakt messen, die Rechnung nachvollziehen und den Wert im Quelltext eintragen. Damit führt man eine einfach Einpunktkalibrierung durch.&lt;br /&gt;
&lt;br /&gt;
Da das Programm schon um einiges größer und komplexer ist, wurde es im Vergleich zur Vorgängerversion geändert. Die Multiplikation sowie die Umwandung der Zahl in einen ASCII-String sind als Unterprogramme geschrieben, dadurch erhält man wesentlich mehr Überblick im Hauptprogramm und die Wiederverwendung in anderen Programmen vereinfacht sich. Ausserdem wird der String im RAM gespeichert und nicht mehr in CPU-Registern. Die Berechung der einzelnen Ziffern erfolgt über ein Schleife, das ist kompakter und übersichtlicher.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
.include &amp;quot;m8def.inc&amp;quot;&lt;br /&gt;
&lt;br /&gt;
.def z0        = r1          ; Zahl für Integer -&amp;gt; ASCII Umwandlung&lt;br /&gt;
.def z1        = r2&lt;br /&gt;
.def z2        = r3&lt;br /&gt;
.def z3        = r4&lt;br /&gt;
.def temp1     = r16         ; allgemeines Register, zur kurzfristigen Verwendung&lt;br /&gt;
.def temp2     = r17         ; Register für 24 Bit Addition, niederwertigstes Byte (LSB)&lt;br /&gt;
.def temp3     = r18         ; Register für 24 Bit Addition, mittlerers Byte&lt;br /&gt;
.def temp4     = r19         ; Register für 24 Bit Addition, höchstwertigstes Byte (MSB)&lt;br /&gt;
.def adlow     = r20         ; Ergebnis vom ADC-Mittelwert der 256 Messungen&lt;br /&gt;
.def adhigh    = r21         ; Ergebnis vom ADC-Mittelwert der 256 Messungen&lt;br /&gt;
.def messungen = r22         ; Schleifenzähler für die Messungen&lt;br /&gt;
.def zeichen   = r23         ; Zeichen zur Ausgabe auf den UART&lt;br /&gt;
.def temp5     = r24&lt;br /&gt;
.def temp6     = r25&lt;br /&gt;
&lt;br /&gt;
; Faktor für Umrechung des ADC-Wertes in Spannung&lt;br /&gt;
; = (Referenzspannung / 1024 ) * 100000&lt;br /&gt;
; = 5V / 1024 * 1.000.000&lt;br /&gt;
.equ Faktor = 4883&lt;br /&gt;
&lt;br /&gt;
.equ F_CPU = 4000000                            ; Systemtakt in Hz&lt;br /&gt;
.equ BAUD  = 9600                               ; Baudrate&lt;br /&gt;
&lt;br /&gt;
; Berechnungen&lt;br /&gt;
.equ UBRR_VAL   = ((F_CPU+BAUD*8)/(BAUD*16)-1)  ; clever runden&lt;br /&gt;
.equ BAUD_REAL  = (F_CPU/(16*(UBRR_VAL+1)))     ; Reale Baudrate&lt;br /&gt;
.equ BAUD_ERROR = ((BAUD_REAL*1000)/BAUD-1000)  ; Fehler in Promille&lt;br /&gt;
&lt;br /&gt;
.if ((BAUD_ERROR&amp;gt;10) || (BAUD_ERROR&amp;lt;-10))       ; max. +/-10 Promille Fehler&lt;br /&gt;
  .error &amp;quot;Systematischer Fehler der Baudrate grösser 1 Prozent und damit zu hoch!&amp;quot;&lt;br /&gt;
.endif&lt;br /&gt;
&lt;br /&gt;
; RAM&lt;br /&gt;
.dseg&lt;br /&gt;
.org 0x60&lt;br /&gt;
Puffer: .byte 10&lt;br /&gt;
&lt;br /&gt;
; hier geht das Programm los&lt;br /&gt;
.cseg&lt;br /&gt;
.org 0&lt;br /&gt;
 &lt;br /&gt;
    ldi     temp1, LOW(RAMEND)                  ; Stackpointer initialisieren&lt;br /&gt;
    out     SPL, temp1&lt;br /&gt;
    ldi     temp1, HIGH(RAMEND)&lt;br /&gt;
    out     SPH, temp1&lt;br /&gt;
 &lt;br /&gt;
;UART Initalisierung&lt;br /&gt;
 &lt;br /&gt;
    ldi     temp1, LOW(UBRR_VAL)                ; Baudrate einstellen&lt;br /&gt;
    out     UBRRL, temp1&lt;br /&gt;
    ldi     temp1, HIGH(UBRR_VAL)&lt;br /&gt;
    out     UBRRH, temp1&lt;br /&gt;
&lt;br /&gt;
    sbi     UCSRB, TXEN                         ; TX einschalten&lt;br /&gt;
 &lt;br /&gt;
; ADC initialisieren: Single Conversion, Vorteiler 128&lt;br /&gt;
; Kanal 0, interne Referenzspannung AVCC&lt;br /&gt;
&lt;br /&gt;
    ldi     temp1, (1&amp;lt;&amp;lt;REFS0)                   &lt;br /&gt;
    out     ADMUX, temp1&lt;br /&gt;
    ldi     temp1, (1&amp;lt;&amp;lt;ADEN) | (1&amp;lt;&amp;lt;ADPS2) | (1&amp;lt;&amp;lt;ADPS1) | (1&amp;lt;&amp;lt;ADPS0)&lt;br /&gt;
    out     ADCSRA, temp1&lt;br /&gt;
 &lt;br /&gt;
Hauptschleife:&lt;br /&gt;
    clr     temp1&lt;br /&gt;
    clr     temp2&lt;br /&gt;
    clr     temp3&lt;br /&gt;
    clr     temp4&lt;br /&gt;
&lt;br /&gt;
    ldi     messungen, 0        ; 256 Schleifendurchläufe&lt;br /&gt;
 &lt;br /&gt;
; neuen ADC-Wert lesen  (Schleife - 256 mal)&lt;br /&gt;
&lt;br /&gt;
adc_messung:&lt;br /&gt;
    sbi     ADCSRA, ADSC        ; den ADC starten&lt;br /&gt;
 &lt;br /&gt;
adc_warten:&lt;br /&gt;
    sbic    ADCSRA, ADSC        ; wenn der ADC fertig ist, wird dieses Bit gelöscht&lt;br /&gt;
    rjmp    adc_warten&lt;br /&gt;
 &lt;br /&gt;
; ADC einlesen:&lt;br /&gt;
&lt;br /&gt;
    in      adlow, ADCL         ; immer zuerst LOW Byte lesen&lt;br /&gt;
    in      adhigh, ADCH        ; danach das mittlerweile gesperrte High Byte&lt;br /&gt;
 &lt;br /&gt;
; alle 256 ADC-Werte addieren&lt;br /&gt;
; dazu wird mit den Registern temp4, temp3 und temp2 ein&lt;br /&gt;
; 24-Bit breites Akkumulationsregister gebildet, in dem&lt;br /&gt;
; die 10 Bit Werte aus adhigh, adlow aufsummiert werden&lt;br /&gt;
&lt;br /&gt;
    add     temp2, adlow        ; addieren&lt;br /&gt;
    adc     temp3, adhigh       ; addieren über Carry&lt;br /&gt;
    adc     temp4, temp1        ; addieren über Carry, temp1 enthält 0&lt;br /&gt;
    dec     messungen           ; Schleifenzähler MINUS 1&lt;br /&gt;
    brne    adc_messung         ; wenn noch keine 256 ADC Werte -&amp;gt; nächsten Wert einlesen&lt;br /&gt;
 &lt;br /&gt;
; Aus den 256 Werten den Mittelwert berechnen&lt;br /&gt;
; Bei 256 Werten ist das ganz einfach: Das niederwertigste Byte&lt;br /&gt;
; (im Register temp2) fällt einfach weg&lt;br /&gt;
;&lt;br /&gt;
; allerdings wird der Wert noch gerundet&lt;br /&gt;
&lt;br /&gt;
    cpi     temp2,128           ; &amp;quot;Kommastelle&amp;quot; kleiner als 128 ?&lt;br /&gt;
    brlo    nicht_runden        ; ist kleiner ==&amp;gt; Sprung&lt;br /&gt;
 &lt;br /&gt;
; Aufrunden&lt;br /&gt;
    subi    temp3, low(-1)      ; addieren von 1&lt;br /&gt;
    sbci    temp4, high(-1)     ; addieren des Carry&lt;br /&gt;
 &lt;br /&gt;
nicht_runden:&lt;br /&gt;
&lt;br /&gt;
;   Ergebnis nach adlow und adhigh kopieren&lt;br /&gt;
;   damit die temp Register frei werden&lt;br /&gt;
&lt;br /&gt;
    mov     adlow, temp3&lt;br /&gt;
    mov     adhigh, temp4&lt;br /&gt;
&lt;br /&gt;
; in Spannung umrechnen&lt;br /&gt;
&lt;br /&gt;
    ldi     temp5,low(Faktor)&lt;br /&gt;
    ldi     temp6,high(Faktor)&lt;br /&gt;
    rcall   mul_16x16&lt;br /&gt;
&lt;br /&gt;
; in ASCII umwandeln&lt;br /&gt;
&lt;br /&gt;
    ldi     XL, low(Puffer)&lt;br /&gt;
    ldi     XH, high(Puffer)&lt;br /&gt;
    rcall   Int_to_ASCII&lt;br /&gt;
 &lt;br /&gt;
;an UART Senden&lt;br /&gt;
&lt;br /&gt;
    ldi     ZL, low(Puffer+3)&lt;br /&gt;
    ldi     ZH, high(Puffer+3)&lt;br /&gt;
    ldi     temp1, 1&lt;br /&gt;
    rcall   sende_zeichen       ; eine Vorkommastelle ausgeben&lt;br /&gt;
&lt;br /&gt;
    ldi     zeichen, &#039;,&#039;        ; Komma ausgeben&lt;br /&gt;
    rcall   sende_einzelzeichen&lt;br /&gt;
&lt;br /&gt;
    ldi     temp1, 3            ; Drei Nachkommastellen ausgeben&lt;br /&gt;
    rcall   sende_zeichen&lt;br /&gt;
&lt;br /&gt;
    ldi     zeichen, &#039;V&#039;        ; Volt Zeichen ausgeben&lt;br /&gt;
    rcall   sende_einzelzeichen&lt;br /&gt;
&lt;br /&gt;
    ldi     zeichen, 10         ; New Line Steuerzeichen&lt;br /&gt;
    rcall   sende_einzelzeichen&lt;br /&gt;
&lt;br /&gt;
    ldi     zeichen, 13         ; Carrige Return Steuerzeichen&lt;br /&gt;
    rcall   sende_einzelzeichen&lt;br /&gt;
&lt;br /&gt;
    rjmp    Hauptschleife&lt;br /&gt;
&lt;br /&gt;
; Ende des Hauptprogramms&lt;br /&gt;
&lt;br /&gt;
; Unterprogramme&lt;br /&gt;
 &lt;br /&gt;
 ; ein Zeichen per UART senden&lt;br /&gt;
&lt;br /&gt;
sende_einzelzeichen:&lt;br /&gt;
    sbis    UCSRA,UDRE          ; Warten, bis UDR bereit ist ...&lt;br /&gt;
    rjmp    sende_einzelzeichen&lt;br /&gt;
    out     UDR, zeichen        ; und Zeichen ausgeben&lt;br /&gt;
    ret&lt;br /&gt;
&lt;br /&gt;
; mehrere Zeichen ausgeben, welche durch Z adressiert werden&lt;br /&gt;
; Anzahl in temp1&lt;br /&gt;
&lt;br /&gt;
sende_zeichen:&lt;br /&gt;
    sbis    UCSRA,UDRE          ; Warten, bis UDR bereit ist ...&lt;br /&gt;
    rjmp    sende_zeichen&lt;br /&gt;
    ld      zeichen, Z+         ; Zeichen laden&lt;br /&gt;
    out     UDR, zeichen        ; und Zeichen ausgeben&lt;br /&gt;
    dec     temp1&lt;br /&gt;
    brne    sende_zeichen&lt;br /&gt;
    ret&lt;br /&gt;
&lt;br /&gt;
; 32 Bit Zahl in ASCII umwandeln&lt;br /&gt;
; Zahl liegt in temp1..4&lt;br /&gt;
; Ergebnis ist ein 10stelliger ASCII String, welcher im SRAM abgelegt wird&lt;br /&gt;
; Adressierung über X Pointer&lt;br /&gt;
; mehrfache Subtraktion wird als Ersatz für eine Division durchgeführt.&lt;br /&gt;
&lt;br /&gt;
Int_to_ASCII:&lt;br /&gt;
    &lt;br /&gt;
    push    ZL                      ; Register sichern&lt;br /&gt;
    push    ZH&lt;br /&gt;
    push    temp5&lt;br /&gt;
    push    temp6&lt;br /&gt;
&lt;br /&gt;
    ldi     ZL,low(Tabelle*2)       ; Zeiger auf Tabelle&lt;br /&gt;
    ldi     ZH,high(Tabelle*2)&lt;br /&gt;
    ldi     temp5, 10               ; Schleifenzähler&lt;br /&gt;
&lt;br /&gt;
Int_to_ASCII_schleife:&lt;br /&gt;
    ldi     temp6, -1+&#039;0&#039;           ; Ziffernzähler zählt direkt im ASCII Code &lt;br /&gt;
    lpm     z0,Z+                   ; Nächste Zahl laden&lt;br /&gt;
    lpm     z1,Z+&lt;br /&gt;
    lpm     z2,Z+&lt;br /&gt;
    lpm     z3,Z+&lt;br /&gt;
&lt;br /&gt;
Int_to_ASCII_ziffer:&lt;br /&gt;
    inc     temp6                   ; Ziffer erhöhen&lt;br /&gt;
    sub     temp1, z0               ; Zahl subrahieren&lt;br /&gt;
    sbc     temp2, z1               ; 32 Bit&lt;br /&gt;
    sbc     temp3, z2&lt;br /&gt;
    sbc     temp4, z3&lt;br /&gt;
    brge    Int_to_ASCII_ziffer     ; noch kein Unterlauf, nochmal&lt;br /&gt;
&lt;br /&gt;
    add     temp1, z0               ; Unterlauf, eimal wieder addieren&lt;br /&gt;
    adc     temp2, z1               ; 32 Bit&lt;br /&gt;
    adc     temp3, z2&lt;br /&gt;
    adc     temp4, z3                                            &lt;br /&gt;
    st      X+,temp6                ; Ziffer speichern&lt;br /&gt;
    dec     temp5&lt;br /&gt;
    brne    Int_to_ASCII_schleife   ; noch eine Ziffer?&lt;br /&gt;
&lt;br /&gt;
    pop     temp6&lt;br /&gt;
    pop     temp5&lt;br /&gt;
    pop     ZH&lt;br /&gt;
    pop     ZL                      ; Register wieder herstellen&lt;br /&gt;
    ret&lt;br /&gt;
&lt;br /&gt;
; Tabelle mit Zahlen für die Berechung der Ziffern&lt;br /&gt;
; 1 Milliarde bis 1&lt;br /&gt;
Tabelle:&lt;br /&gt;
.dd 1000000000, 100000000, 10000000, 1000000, 100000, 10000, 1000, 100, 10, 1&lt;br /&gt;
&lt;br /&gt;
; 16 Bit Wert in Spannung umrechnen&lt;br /&gt;
;&lt;br /&gt;
; = 16Bitx16Bit=32 Bit Multiplikation&lt;br /&gt;
; = vier 8x8 Bit Multiplikationen&lt;br /&gt;
;&lt;br /&gt;
; adlow/adhigh * temp5/temp6&lt;br /&gt;
&lt;br /&gt;
mul_16x16:&lt;br /&gt;
    push    zeichen&lt;br /&gt;
    clr     temp1                   ; 32 Bit Akku löschen&lt;br /&gt;
    clr     temp2&lt;br /&gt;
    clr     temp3&lt;br /&gt;
    clr     temp4&lt;br /&gt;
    clr     zeichen                 ; Null, für Carry-Addition&lt;br /&gt;
&lt;br /&gt;
    mul     adlow, temp5            ; erste Multiplikation&lt;br /&gt;
    add     temp1, r0               ; und akkumulieren&lt;br /&gt;
    adc     temp2, r1&lt;br /&gt;
&lt;br /&gt;
    mul     adhigh, temp5           ; zweite Multiplikation&lt;br /&gt;
    add     temp2, r0               ; und gewichtet akkumlieren&lt;br /&gt;
    adc     temp3, r1&lt;br /&gt;
&lt;br /&gt;
    mul     adlow, temp6            ; dritte Multiplikation&lt;br /&gt;
    add     temp2, r0               ; und gewichtet akkumlieren&lt;br /&gt;
    adc     temp3, r1&lt;br /&gt;
    adc     temp4, zeichen          ; carry addieren&lt;br /&gt;
&lt;br /&gt;
    mul     adhigh, temp6           ; vierte Multiplikation&lt;br /&gt;
    add     temp3, r0               ; und gewichtet akkumlieren&lt;br /&gt;
    adc     temp4, r1&lt;br /&gt;
&lt;br /&gt;
    pop     zeichen&lt;br /&gt;
    ret&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für alle, die es besonders eilig haben gibt es hier eine geschwindigkeitsoptimierte Version der Integer in ASCII Umwandlung. Zunächst wird keine Schleife verwendet sondern alle Stufen der Schleife direkt hingeschrieben. Das braucht zwar mehr Programmspeicher, ist aber schneller. Ausserdem wird abwechselnd subtrahiert und addiert, dadurch entfällt das immer wieder notwendige addieren nach dem Unterlauf. Zu guter Letzt werden die Berechnungen nur mit der minimal notwenigen Wortbreite durchgeführt. Am Anfang mit 32 Bit, dann nur noch mit 16 bzw. 8 Bit.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
; 32 Bit Zahl in ASCII umwandeln&lt;br /&gt;
; geschwindigkeitsoptimierte Version&lt;br /&gt;
; Zahl liegt in temp1..4&lt;br /&gt;
; Ergebnis ist ein 10stelliger ASCII String, welcher im SRAM abgelegt wird&lt;br /&gt;
; Adressierung über X Pointer&lt;br /&gt;
&lt;br /&gt;
Int_to_ASCII:&lt;br /&gt;
    ldi     temp5, -1 + &#039;0&#039;&lt;br /&gt;
_a1ser:&lt;br /&gt;
    inc     temp5&lt;br /&gt;
    subi    temp1,BYTE1(1000000000) ; - 1.000.000.000&lt;br /&gt;
    sbci    temp2,BYTE2(1000000000)&lt;br /&gt;
    sbci    temp3,BYTE3(1000000000)&lt;br /&gt;
    sbci    temp4,BYTE4(1000000000)&lt;br /&gt;
    brcc    _a1ser&lt;br /&gt;
&lt;br /&gt;
    st      X+,temp5                ; im Puffer speichern&lt;br /&gt;
    ldi     temp5, 10 + &#039;0&#039;&lt;br /&gt;
_a2ser:&lt;br /&gt;
    dec     temp5&lt;br /&gt;
    subi    temp1,BYTE1(-100000000) ; + 100.000.000&lt;br /&gt;
    sbci    temp2,BYTE2(-100000000)&lt;br /&gt;
    sbci    temp3,BYTE3(-100000000)&lt;br /&gt;
    sbci    temp4,BYTE4(-100000000)&lt;br /&gt;
    brcs    _a2ser&lt;br /&gt;
&lt;br /&gt;
    st      X+,temp5                ; im Puffer speichern&lt;br /&gt;
    ldi     temp5, -1 + &#039;0&#039;&lt;br /&gt;
_a3ser:&lt;br /&gt;
    inc     temp5&lt;br /&gt;
    subi    temp1,low(10000000)     ; - 10.000.000&lt;br /&gt;
    sbci    temp2,high(10000000)&lt;br /&gt;
    sbci    temp3,BYTE3(10000000)&lt;br /&gt;
    sbci    temp4,BYTE4(10000000)&lt;br /&gt;
    brcc    _a3ser&lt;br /&gt;
&lt;br /&gt;
    st      X+,temp5                ; im Puffer speichern&lt;br /&gt;
    ldi     temp5, 10 + &#039;0&#039;&lt;br /&gt;
_a4ser:&lt;br /&gt;
    dec     temp5&lt;br /&gt;
    subi    temp1,low(-1000000)     ; + 1.000.000&lt;br /&gt;
    sbci    temp2,high(-1000000)&lt;br /&gt;
    sbci    temp3,BYTE3(-1000000)&lt;br /&gt;
    sbci    temp4,BYTE4(-1000000)&lt;br /&gt;
    brcs    _a4ser&lt;br /&gt;
&lt;br /&gt;
    st      X+,temp5                ; im Puffer speichern&lt;br /&gt;
    ldi     temp5, -1 + &#039;0&#039;&lt;br /&gt;
_a5ser:&lt;br /&gt;
    inc     temp5&lt;br /&gt;
    subi    temp1,low(100000)       ; -100.000&lt;br /&gt;
    sbci    temp2,high(100000)&lt;br /&gt;
    sbci    temp3,BYTE3(100000)&lt;br /&gt;
    brcc    _a5ser&lt;br /&gt;
&lt;br /&gt;
    st      X+,temp5                ; im Puffer speichern&lt;br /&gt;
    ldi     temp5, 10 + &#039;0&#039;&lt;br /&gt;
_a6ser:&lt;br /&gt;
    dec     temp5&lt;br /&gt;
    subi    temp1,low(-10000)       ; +10,000&lt;br /&gt;
    sbci    temp2,high(-10000)&lt;br /&gt;
    sbci    temp3,BYTE3(-10000)&lt;br /&gt;
    brcs    _a6ser&lt;br /&gt;
&lt;br /&gt;
    st      X+,temp5                ; im Puffer speichern &lt;br /&gt;
    ldi     temp5, -1 + &#039;0&#039;&lt;br /&gt;
_a7ser:&lt;br /&gt;
    inc     temp5&lt;br /&gt;
    subi    temp1,low(1000)         ; -1000&lt;br /&gt;
    sbci    temp2,high(1000)&lt;br /&gt;
    brcc    _a7ser&lt;br /&gt;
 &lt;br /&gt;
    st      X+,temp5                ; im Puffer speichern&lt;br /&gt;
    ldi     temp5, 10 + &#039;0&#039;&lt;br /&gt;
_a8ser:&lt;br /&gt;
    dec     temp5&lt;br /&gt;
    subi    temp1,low(-100)         ; +100&lt;br /&gt;
    sbci    temp2,high(-100)&lt;br /&gt;
    brcs    _a8ser&lt;br /&gt;
 &lt;br /&gt;
    st      X+,temp5                ; im Puffer speichern&lt;br /&gt;
    ldi     temp5, -1 + &#039;0&#039;&lt;br /&gt;
_a9ser:&lt;br /&gt;
    inc     temp5&lt;br /&gt;
    subi    temp1, 10               ; -10&lt;br /&gt;
    brcc    _a9ser&lt;br /&gt;
    &lt;br /&gt;
    st      X+,temp5                ; im Puffer speichern&lt;br /&gt;
    ldi     temp5, 10 + &#039;0&#039;&lt;br /&gt;
_a10ser:&lt;br /&gt;
    dec     temp5&lt;br /&gt;
    subi    temp1, -1               ; +1&lt;br /&gt;
    brcs    _a10ser&lt;br /&gt;
&lt;br /&gt;
    st      X+,temp5                ; im Puffer speichern&lt;br /&gt;
    ret&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
{{Navigation_zurückhochvor|&lt;br /&gt;
zurücktext=Uhr|&lt;br /&gt;
zurücklink=AVR-Tutorial: Uhr|&lt;br /&gt;
hochtext=Inhaltsverzeichnis|&lt;br /&gt;
hochlink=AVR-Tutorial|&lt;br /&gt;
vortext=Tasten|&lt;br /&gt;
vorlink=AVR-Tutorial: Tasten}}&lt;br /&gt;
&lt;br /&gt;
[[Category:AVR-Tutorial|ADC]]&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Eagle-Bibliotheken&amp;diff=62473</id>
		<title>Eagle-Bibliotheken</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Eagle-Bibliotheken&amp;diff=62473"/>
		<updated>2011-12-16T14:38:40Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: /* Halbleiterschalter */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Funktionsweise ==&lt;br /&gt;
&lt;br /&gt;
User laden im Forum eine Bibliothek mit einem oder mehreren zusammengehörigen Bauteilen hoch (beispielsweise ATXmegas) und tragen ein, welche Bauteile mit welchen Packages in der Bibliothek zu finden sind. Andere User können sie sich ansehen und auf Fehlerfreiheit prüfen. Dies wird in der Tabelle unten vermerkt.&lt;br /&gt;
&lt;br /&gt;
== Bibliotheken ==&lt;br /&gt;
&lt;br /&gt;
=== Bus-Isolatoren ===&lt;br /&gt;
&lt;br /&gt;
Von User: Kevin K.&lt;br /&gt;
Link: [[Datei:Bus-isolators.lbr]]&lt;br /&gt;
&lt;br /&gt;
{| {{Tabelle}} class=&amp;quot;sortable&amp;quot; id=&amp;quot;Errata&amp;quot;&lt;br /&gt;
|- bgcolor=&amp;quot;#eeeeee&amp;quot;&lt;br /&gt;
! Version&lt;br /&gt;
! Änderungen&lt;br /&gt;
! ausstehend&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| 2&lt;br /&gt;
| SO28/8-Package bei ISO124 hinzugefügt, Prefixe zugefügt, Name- und Value-Label korrigiert&lt;br /&gt;
| Pindirections eintragen&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
|3&lt;br /&gt;
| Pindirections eingefügt, ADUM1200, ADUM1201 und ADUM1400 zugefügt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| {{Tabelle}} class=&amp;quot;sortable&amp;quot; id=&amp;quot;Bus-isolators.lbr&amp;quot;&lt;br /&gt;
|- bgcolor=&amp;quot;#eeeeee&amp;quot;&lt;br /&gt;
! Hersteller&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Gehäuse&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anmerkungen&lt;br /&gt;
! Reviewed?&lt;br /&gt;
! Fehler&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| Analog Devices&lt;br /&gt;
| [http://www.mikrocontroller.net/part/ADM3251 ADM3251]&lt;br /&gt;
| SO-20L&lt;br /&gt;
| UART/RS232-Treiber, isoliert&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| Analog Devices&lt;br /&gt;
| [http://www.mikrocontroller.net/part/ADUM1200 ADUM1200]&lt;br /&gt;
| SO-8&lt;br /&gt;
| Digital-Isolator 2-&amp;gt;&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| Analog Devices&lt;br /&gt;
| [http://www.mikrocontroller.net/part/ADUM1201 ADUM1201]&lt;br /&gt;
| SO-8&lt;br /&gt;
| Digital-Isolator 1-&amp;gt; 1&amp;lt;-&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| Analog Devices&lt;br /&gt;
| [http://www.mikrocontroller.net/part/ADUM1250 ADUM1250]&lt;br /&gt;
| SO-8&lt;br /&gt;
| I²C-Isolator&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| Analog Devices&lt;br /&gt;
| [http://www.mikrocontroller.net/part/ADUM1400 ADUM1400]&lt;br /&gt;
| SO-16W&lt;br /&gt;
| Digital-Isolator 4-&amp;gt;&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
|&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
| Analog Devices&lt;br /&gt;
| [http://www.mikrocontroller.net/part/ADUM4160 ADUM4160]&lt;br /&gt;
| SO-16L&lt;br /&gt;
| USB1.1-Isolator&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| Texas Instruments&lt;br /&gt;
| [http://www.mikrocontroller.net/part/ISO124 ISO124]&lt;br /&gt;
| DIL-16/8&lt;br /&gt;
| Analog-Isolator&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| Silicon Laboratories&lt;br /&gt;
| [http://www.mikrocontroller.net/part/SI8405 SI8405]&lt;br /&gt;
| SO-16&lt;br /&gt;
| I²C + TTL-Isolator&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Kristalle und Oszillatoren ===&lt;br /&gt;
&lt;br /&gt;
Von User: Kevin K.&lt;br /&gt;
Link: [[Datei:crystals-new.lbr]]&lt;br /&gt;
&lt;br /&gt;
{| {{Tabelle}} class=&amp;quot;sortable&amp;quot; id=&amp;quot;crystals-new.lbr&amp;quot;&lt;br /&gt;
|- bgcolor=&amp;quot;#eeeeee&amp;quot;&lt;br /&gt;
! Hersteller&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Gehäuse&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anmerkungen&lt;br /&gt;
! Reviewed?&lt;br /&gt;
! Fehler&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| EuroQuartz&lt;br /&gt;
| [http://www.euroquartz.co.uk/Portals/0/mq.pdf]&lt;br /&gt;
| MQ&lt;br /&gt;
| Quartz&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| EuroQuartz&lt;br /&gt;
| [http://www.euroquartz.co.uk/Portals/0/mj.pdf]&lt;br /&gt;
| MJ&lt;br /&gt;
| Quartz&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| EuroQuartz&lt;br /&gt;
| [http://www.euroquartz.co.uk/Portals/0/mt.pdf]&lt;br /&gt;
| MT&lt;br /&gt;
| Quartz&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| EuroQuartz&lt;br /&gt;
| [http://www.euroquartz.co.uk/Portals/0/x22.pdf]&lt;br /&gt;
| X22&lt;br /&gt;
| Quartz&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| EuroQuartz&lt;br /&gt;
| [http://www.euroquartz.co.uk/Portals/0/xo91.pdf]&lt;br /&gt;
| XO91&lt;br /&gt;
| Oszillator&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| EuroQuartz&lt;br /&gt;
| [http://www.euroquartz.co.uk/Portals/0/xo53.pdf]&lt;br /&gt;
| XO53&lt;br /&gt;
| Oszillator&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| EuroQuartz&lt;br /&gt;
| [http://www.euroquartz.co.uk/Portals/0/xo32.pdf]&lt;br /&gt;
| XO32&lt;br /&gt;
| Oszillator&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Shuntwiderstände Vishay CSM-Serie ===&lt;br /&gt;
&lt;br /&gt;
Von User: Kevin K.&lt;br /&gt;
Link: [[Datei:R-Vishay.lbr]]&lt;br /&gt;
&lt;br /&gt;
{| {{Tabelle}} class=&amp;quot;sortable&amp;quot; id=&amp;quot;R-Vishay.lbr&amp;quot;&lt;br /&gt;
|- bgcolor=&amp;quot;#eeeeee&amp;quot;&lt;br /&gt;
! Hersteller&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Gehäuse&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anmerkungen&lt;br /&gt;
! Reviewed?&lt;br /&gt;
! Fehler&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| Vishay&lt;br /&gt;
| [http://www.vishaypg.com/docs/63089/csm.pdf]&lt;br /&gt;
| CSM2512&lt;br /&gt;
| Widerstand&lt;br /&gt;
| alle drei Varianten&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| Vishay&lt;br /&gt;
| [http://www.vishaypg.com/docs/63089/csm.pdf]&lt;br /&gt;
| CSM3637&lt;br /&gt;
| Widerstand&lt;br /&gt;
| alle zwei Varianten&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Spulen Fastron ===&lt;br /&gt;
&lt;br /&gt;
Von User: Kevin K.&lt;br /&gt;
Link: [[Datei:inductor-Fastron.lbr]]&lt;br /&gt;
&lt;br /&gt;
{| {{Tabelle}} class=&amp;quot;sortable&amp;quot; id=&amp;quot;inductor-Fastron.lbr&amp;quot;&lt;br /&gt;
|- bgcolor=&amp;quot;#eeeeee&amp;quot;&lt;br /&gt;
! Hersteller&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Gehäuse&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anmerkungen&lt;br /&gt;
! Reviewed?&lt;br /&gt;
! Fehler&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| Fastron&lt;br /&gt;
| [http://www.fastrongroup.com/image-show/54/PISG.pdf?type=Complete-DataSheet&amp;amp;productType=series]&lt;br /&gt;
| PISG&lt;br /&gt;
| Spule&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| Fastron&lt;br /&gt;
| [http://www.fastrongroup.com/image-show/58/PISR.pdf?type=Complete-DataSheet&amp;amp;productType=series]&lt;br /&gt;
| PISR&lt;br /&gt;
| Spule&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| Fastron&lt;br /&gt;
| [http://www.fastrongroup.com/image-show/56/PISM.pdf?type=Complete-DataSheet&amp;amp;productType=series]&lt;br /&gt;
| PISM&lt;br /&gt;
| Spule&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| Fastron&lt;br /&gt;
| [http://www.fastrongroup.com/image-show/47/PIS2408.pdf?type=Complete-DataSheet&amp;amp;productType=series]&lt;br /&gt;
| PIS 24XX&lt;br /&gt;
| Spule&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| Fastron&lt;br /&gt;
| [http://www.fastrongroup.com/image-show/49/PIS2812.pdf?type=Complete-DataSheet&amp;amp;productType=series]&lt;br /&gt;
| PIS 28XX&lt;br /&gt;
| Spule&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| Fastron&lt;br /&gt;
| [http://www.fastrongroup.com/image-show/52/PIS4720.pdf?type=Complete-DataSheet&amp;amp;productType=series]&lt;br /&gt;
| PIS 47XX&lt;br /&gt;
| Spule&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Micromatch THT und SMD ===&lt;br /&gt;
&lt;br /&gt;
Von User: Kevin K.&lt;br /&gt;
Link: [[Datei:con-amp-micromatch.lbr]]&lt;br /&gt;
&lt;br /&gt;
{| {{Tabelle}} class=&amp;quot;sortable&amp;quot; id=&amp;quot;con-amp-micromatch.lbr&amp;quot;&lt;br /&gt;
|- bgcolor=&amp;quot;#eeeeee&amp;quot;&lt;br /&gt;
! Hersteller&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Gehäuse&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anmerkungen&lt;br /&gt;
! Reviewed?&lt;br /&gt;
! Fehler&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| Tyco Electronics&lt;br /&gt;
| [http://www.tycoelectronics.com/commerce/DocumentDelivery/DDEController?Action=srchrtrv&amp;amp;DocNm=215464&amp;amp;DocType=CD&amp;amp;DocLang=EN]&lt;br /&gt;
| Micromatch&lt;br /&gt;
| SMD und THT&lt;br /&gt;
| 6-20 polig&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Halbleiterschalter ===&lt;br /&gt;
&lt;br /&gt;
Von User: Kevin K.&lt;br /&gt;
Link: [[Datei:linear-switch.lbr]]&lt;br /&gt;
&lt;br /&gt;
{| {{Tabelle}} class=&amp;quot;sortable&amp;quot; id=&amp;quot;linear-switch.lbr&amp;quot;&lt;br /&gt;
|- bgcolor=&amp;quot;#eeeeee&amp;quot;&lt;br /&gt;
! Hersteller&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Gehäuse&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anmerkungen&lt;br /&gt;
! Reviewed?&lt;br /&gt;
! Fehler&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| Linear Technology&lt;br /&gt;
| [http://www.linear.com/pc/downloadDocument.do?navId=H0,C1,C1010,C1203,P1248,D3572 LTC1043]&lt;br /&gt;
| DIL18 / SO18&lt;br /&gt;
| SMD und THT&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== TLC5951 ===&lt;br /&gt;
&lt;br /&gt;
Von User: Frank Link&lt;br /&gt;
Link: [[Datei:ti_tlc.lbr]]&lt;br /&gt;
&lt;br /&gt;
{| {{Tabelle}} class=&amp;quot;sortable&amp;quot; id=&amp;quot;ti_tlc.lbr&amp;quot;&lt;br /&gt;
|- bgcolor=&amp;quot;#eeeeee&amp;quot;&lt;br /&gt;
! Hersteller&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Gehäuse&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anmerkungen&lt;br /&gt;
! Reviewed?&lt;br /&gt;
! Fehler &amp;lt;!-- MIT Angabe von *Datum* bei wikified Dateien und *Attachment-Nummer* bei Dateianhängen --&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| Texas Instruments&lt;br /&gt;
| [http://www.mikrocontroller.net/part/TLC5951 TLC5951]&lt;br /&gt;
| HTSSOP-38&lt;br /&gt;
| 24 Channel, 12 Bit PWM LED-Driver&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| kein Pad-Überstand offen da noch nicht geklärt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== PCI-Express Mini-Karte ===&lt;br /&gt;
&lt;br /&gt;
von User: hownottobeseen&lt;br /&gt;
Link [[Datei:Con-heo.mini pci express.lbr]]&lt;br /&gt;
&lt;br /&gt;
Enthält Konnektor und Formfaktor für Full- und Halfsize-PCIe-Mini-Karten&lt;br /&gt;
&lt;br /&gt;
siehe auch [http://www.mikrocontroller.net/topic/214222 Diskussion im Forum]&lt;br /&gt;
&lt;br /&gt;
=== Maxim MAX1811 USB Li+ Lader ===&lt;br /&gt;
&lt;br /&gt;
von User: [http://www.mikrocontroller.net/user/show/muetze1 Muetze1] Link [[Datei:MAX1811.lbr]]&lt;br /&gt;
&lt;br /&gt;
Enthält den Maxim MAX1811 USB Li+ Lader im SO08 Gehäuse&lt;br /&gt;
&lt;br /&gt;
{| {{Tabelle}} class=&amp;quot;sortable&amp;quot; id=&amp;quot;MAX1811.lbr&amp;quot;&lt;br /&gt;
|- bgcolor=&amp;quot;#eeeeee&amp;quot;&lt;br /&gt;
! Hersteller&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Gehäuse&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anmerkungen&lt;br /&gt;
! Reviewed?&lt;br /&gt;
! Fehler &amp;lt;!-- MIT Angabe von *Datum* bei wikified Dateien und *Attachment-Nummer* bei Dateianhängen --&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| Maxim IC&lt;br /&gt;
| [http://www.mikrocontroller.net/part/MAX1811 MAX1811]&lt;br /&gt;
| SO08&lt;br /&gt;
| USB Li+ Loader (100mA/500mA)&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| -&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== International Rectifier IRLML6402 ===&lt;br /&gt;
&lt;br /&gt;
von User: [http://www.mikrocontroller.net/user/show/muetze1 Muetze1] Link [[Datei:IRLML6402.lbr]]&lt;br /&gt;
&lt;br /&gt;
Der IR IRLML6402 p-Channel MOSFET wird u.a. von FTDI in ihren Unterlagen zum FT232RL vorgeschlagen für die Schaltung der Versorgung nach dem Init des USB Gerätes.&lt;br /&gt;
&lt;br /&gt;
{| {{Tabelle}} class=&amp;quot;sortable&amp;quot; id=&amp;quot;IRLML6402.lbr&amp;quot;&lt;br /&gt;
|- bgcolor=&amp;quot;#eeeeee&amp;quot;&lt;br /&gt;
! Hersteller&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Gehäuse&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anmerkungen&lt;br /&gt;
! Reviewed?&lt;br /&gt;
! Fehler &amp;lt;!-- MIT Angabe von *Datum* bei wikified Dateien und *Attachment-Nummer* bei Dateianhängen --&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| [http://www.irf.com International Rectifier]&lt;br /&gt;
| [http://www.mikrocontroller.net/part/IRLML6402 IRLML6402]&lt;br /&gt;
| Micro 3/SOT23&lt;br /&gt;
| -20 V p-Channel MOSFET&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| -&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== USB 2 UART ===&lt;br /&gt;
&lt;br /&gt;
von User: [http://www.mikrocontroller.net/user/show/chrisw84 Chris W.] Link [[Datei:FT2232D.lbr]]&lt;br /&gt;
&lt;br /&gt;
Anwendungen: USB to Dual Port RS232 Converters, USB to Dual Port RS422 / RS485, USB JTAG Programming, USB to SPI Bus Interfaces&lt;br /&gt;
{| {{Tabelle}} class=&amp;quot;sortable&amp;quot; id=&amp;quot;FT2232D.lbr&amp;quot;&lt;br /&gt;
|- bgcolor=&amp;quot;#eeeeee&amp;quot;&lt;br /&gt;
! Hersteller&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Gehäuse&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anmerkungen&lt;br /&gt;
! Reviewed?&lt;br /&gt;
! Fehler &amp;lt;!-- MIT Angabe von *Datum* bei wikified Dateien und *Attachment-Nummer* bei Dateianhängen --&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| [http://www.ftdichip.com FTDI]&lt;br /&gt;
| [http://www.ftdichip.com/Support/Documents/DataSheets/ICs/DS_FT2232D.pdf FT2232D]&lt;br /&gt;
| LQFP 48&lt;br /&gt;
| - USB zu Dual UART&lt;br /&gt;
| Pin-Directions müssen nach Anwendungsfall&amp;lt;br&amp;gt; angepasst werden!&lt;br /&gt;
| nein&lt;br /&gt;
| -&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Ethernet-Controller von ASIX Electronics Corporation ===&lt;br /&gt;
&lt;br /&gt;
Von User: Steffen H.&lt;br /&gt;
Link: [[Datei:asix-v3.lbr]]&lt;br /&gt;
&lt;br /&gt;
Ethernet Controller, die man auch mit kleineren MCU&#039;s betreiben kann. Der neue AX88796C kann auch mit max. 40MHz SPI betrieben werden. Besonderes Feature: IPv4/IPv6 packet Checksum Offload Engine to reduce CPU loading, &lt;br /&gt;
including IPv4 IP/TCP/UDP/ICMP/IGMP &amp;amp; IPv6 TCP/UDP/ICM Pv6 checksum generation &amp;amp; check&lt;br /&gt;
&lt;br /&gt;
{| {{Tabelle}} class=&amp;quot;sortable&amp;quot; id=&amp;quot;asix-v3.lbr&amp;quot;&lt;br /&gt;
|- bgcolor=&amp;quot;#eeeeee&amp;quot;&lt;br /&gt;
! Hersteller&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Gehäuse&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anmerkungen&lt;br /&gt;
! Reviewed?&lt;br /&gt;
! Fehler&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| ASIX&lt;br /&gt;
| [http://www.asix.com.tw/products.php?op=ProductList&amp;amp;PLine=65&amp;amp;PSeries=86 AX88796B]&lt;br /&gt;
| LQFP-64&lt;br /&gt;
| 8/16-bit 10/100M Fast Ethernet Controller&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| ASIX&lt;br /&gt;
| [http://www.asix.com.tw/products.php?op=ProductList&amp;amp;PLine=65&amp;amp;PSeries=86  AX88796C]&lt;br /&gt;
| LQFP-64&lt;br /&gt;
| SPI(40MHz)/8/16-bit 10/100M Fast Ethernet Controller&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| ASIX&lt;br /&gt;
| [http://www.asix.com.tw/products.php?op=ProductList&amp;amp;PLine=65&amp;amp;PSeries=86 AX88796L]&lt;br /&gt;
| LQFP-128&lt;br /&gt;
| 8/16-bit 10/100M Fast Ethernet Controller, Print Port for printer server&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== ISSI High-speed CMOS STATIC RAM ===&lt;br /&gt;
&lt;br /&gt;
Von User: Steffen H.&lt;br /&gt;
Link: [[Datei:issi.lbr]]&lt;br /&gt;
&lt;br /&gt;
{| {{Tabelle}} class=&amp;quot;sortable&amp;quot; id=&amp;quot;asix-v3.lbr&amp;quot;&lt;br /&gt;
|- bgcolor=&amp;quot;#eeeeee&amp;quot;&lt;br /&gt;
! Hersteller&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Gehäuse&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anmerkungen&lt;br /&gt;
! Reviewed?&lt;br /&gt;
! Fehler&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| ISSI&lt;br /&gt;
| [http://www.icsi.com.tw IS62LV256L]&lt;br /&gt;
| 28-Pin TSOP-1&lt;br /&gt;
| High-speed 32K x 8 Low Power SRAM with 3.3V&lt;br /&gt;
| Footprint n. IPC7351A&lt;br /&gt;
| nein&lt;br /&gt;
| &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== RFT-Opto Bauelemente ===&lt;br /&gt;
&lt;br /&gt;
von User: [http://www.mikrocontroller.net/user/show/muetze1 Muetze1] Link [[Datei:rft-opto.lbr]]&lt;br /&gt;
&lt;br /&gt;
Enthält (bisher) die gängisten RFT LED Segment-Anzeigen&lt;br /&gt;
&lt;br /&gt;
{| {{Tabelle}} class=&amp;quot;sortable&amp;quot; id=&amp;quot;rft-opto.lbr&amp;quot;&lt;br /&gt;
|- bgcolor=&amp;quot;#eeeeee&amp;quot;&lt;br /&gt;
! Hersteller&lt;br /&gt;
! Bezeichnung&lt;br /&gt;
! Gehäuse&lt;br /&gt;
! Beschreibung&lt;br /&gt;
! Anmerkungen&lt;br /&gt;
! Reviewed?&lt;br /&gt;
! Fehler &amp;lt;!-- MIT Angabe von *Datum* bei wikified Dateien und *Attachment-Nummer* bei Dateianhängen --&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| RFT&lt;br /&gt;
| VQB 37&lt;br /&gt;
| TGL 32989&lt;br /&gt;
| 7-Segment-Miniatur-Anzeige mit gemeinsamer Katode und Linse, rotstrahlend&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| RFT&lt;br /&gt;
| VQB 71&lt;br /&gt;
| TGL 31245&lt;br /&gt;
| 7-Segment-Anzeige mit gemeinsamer Anode und Dezimalpunkt, rotstrahlend&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| RFT&lt;br /&gt;
| VQB 73&lt;br /&gt;
| TGL 31245&lt;br /&gt;
| 4-Segment Vorzeichen Anzeige mit gemeinsamer Anode, rotstrahlend&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| RFT&lt;br /&gt;
| VQB 76, VQB 76/1&lt;br /&gt;
| TGL ???&lt;br /&gt;
| 7-Segment-Anzeige in DIL Format mit Dezimalpunkt, rotstrahlend&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| RFT&lt;br /&gt;
| VQB 16&lt;br /&gt;
| TGL 55111&lt;br /&gt;
| Vorzeichen + 1, rotstrahlend&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| RFT&lt;br /&gt;
| VQB 17&lt;br /&gt;
| TGL 55111&lt;br /&gt;
| 7 Segmentanzeige mit DP, gemeinsame Katode, rotstrahlend&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| RFT&lt;br /&gt;
| VQB 18&lt;br /&gt;
| TGL 55111&lt;br /&gt;
| 7 Segmentanzeige mit DP, gemeinsame Anode, rotstrahlend&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| RFT&lt;br /&gt;
| VQB 26&lt;br /&gt;
| TGL 55111&lt;br /&gt;
| Vorzeichen + 1, grünstrahlend&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| RFT&lt;br /&gt;
| VQB 27&lt;br /&gt;
| TGL 55111&lt;br /&gt;
| 7 Segmentanzeige mit DP, gemeinsame Katode, grünstrahlend&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| RFT&lt;br /&gt;
| VQB 28&lt;br /&gt;
| TGL 55111&lt;br /&gt;
| 7 Segmentanzeige mit DP, gemeinsame Anode, grünstrahlend&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| RFT&lt;br /&gt;
| VQB 200&lt;br /&gt;
| TGL 42170&lt;br /&gt;
| 16-Segment-Anzeige mit Dezimalpunkt, grünstrahlend, gemeinsame Katode&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| RFT&lt;br /&gt;
| VQB 201&lt;br /&gt;
| TGL 42170&lt;br /&gt;
| 16-Segment-Anzeige mit Dezimalpunkt, grünstrahlend, gemeinsame Anode&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| RFT&lt;br /&gt;
| VQC 10&lt;br /&gt;
| TGL ???&lt;br /&gt;
| 4-stellige 5x7 Puntmatrix, rotstrahlend&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| RFT&lt;br /&gt;
| VQE 11&lt;br /&gt;
| TGL 55110&lt;br /&gt;
| 1 1/2 stellige 7-Segment-Anzeige mit Vorzeichen und gemeinsamer Katode, rotstrahlend&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| RFT&lt;br /&gt;
| VQE 12&lt;br /&gt;
| TGL 55110&lt;br /&gt;
| 1 1/2 stellige 7-Segment-Anzeige mit Vorzeichen und gemeinsamer Anode, rotstrahlend&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| RFT&lt;br /&gt;
| VQE 13&lt;br /&gt;
| TGL 55110&lt;br /&gt;
| 2 stellige 7-Segment-Anzeige mit gemeinsamer Katode, rotstrahlend&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| RFT&lt;br /&gt;
| VQE 14&lt;br /&gt;
| TGL 55110&lt;br /&gt;
| 2 stellige 7-Segment-Anzeige mit gemeinsamer Anode, rotstrahlend&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| RFT&lt;br /&gt;
| VQE 21&lt;br /&gt;
| TGL 39352&lt;br /&gt;
| 1 1/2 stellige 7-Segment-Anzeige mit Vorzeichen und gemeinsamer Katode, grünstrahlend&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| RFT&lt;br /&gt;
| VQE 22&lt;br /&gt;
| TGL 39352&lt;br /&gt;
| 1 1/2 stellige 7-Segment-Anzeige mit Vorzeichen und gemeinsamer Anode, grünstrahlend&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| RFT&lt;br /&gt;
| VQE 23&lt;br /&gt;
| TGL 39352&lt;br /&gt;
| 2 stellige 7-Segment-Anzeige mit gemeinsamer Katode, grünstrahlend&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| RFT&lt;br /&gt;
| VQE 24&lt;br /&gt;
| TGL 39352&lt;br /&gt;
| 2 stellige 7-Segment-Anzeige mit gemeinsamer Anode, grünstrahlend&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| -&lt;br /&gt;
|-&lt;br /&gt;
&lt;br /&gt;
| RFT&lt;br /&gt;
| MQE 10&lt;br /&gt;
| TGL ???&lt;br /&gt;
| 3-fach 7-Segment-Anzeige mit integrierten A/D Wandler (C 520)&lt;br /&gt;
| keine&lt;br /&gt;
| nein&lt;br /&gt;
| -&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Eagle]]&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Pegelwandler&amp;diff=62195</id>
		<title>Pegelwandler</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Pegelwandler&amp;diff=62195"/>
		<updated>2011-12-05T07:17:03Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: /* 5V -&amp;gt; 9..15V */&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&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 Signalleitungen zwischen den Bauteilen überprüft. Wenn 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 45nm Technologie hergestellt!) werden auch die Abstände und Schichtdicken immer geringer. Das reduziert natürlich auch die Spannungsfestigkeit 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.). Die Schutzdioden beginnen Strom zu leiten, wenn die Eingangsspannung ca. 500mV über VCC ansteigt oder mehr als 500mV 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 | Step Down mit Vorwiderstand]].&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, daß 3 Volt Bausteine ohne Probleme von einem 5 Volt Baustein angesteuert werden können.&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 darüber nachlesen, 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;
[[AVR]]s sind generell &#039;&#039;&#039;nicht&#039;&#039;&#039; 5V tolerant, wenn sie mit 3.3V betrieben werden! Die absolute obere Grenze für Eingangsspannungen liegt bei Vcc + 0.5V. Zu finden in den elektrischen Spezifikationen im Datenblatt.&lt;br /&gt;
&lt;br /&gt;
Ob ein Bauteil 5V-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;
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,3V.&amp;lt;br&amp;gt;&amp;lt;font color=FF0000&amp;gt;Achtung&amp;lt;/font&amp;gt;: Nicht alle 74LVX sind für 5V -&amp;gt; 3,3V geeignet, da jeder Hersteller die ICs anders baut!&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össer 0.8 * Vcc&lt;br /&gt;
* LOW kleiner 0.2 * Vcc&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.8V -&amp;gt; 5V ===&lt;br /&gt;
&lt;br /&gt;
* Die besondere Eigenschaft der alten TTL Schaltkreise, nämlich daß Strom bei LOW &#039;&#039;&#039;aus&#039;&#039;&#039; dem Eingang in den treibenden Ausgang fliesst kann man sich zu nutze machen wie die nachfolgende Schaltung zeigt. Dabei wird der HIGH-Pegel des 1,8V Signals durch eine Schottkydiode um ca. 0,3V auf 2,1V erhöht. Damit ist man fast offiziell im HIGH-Berich für TTL (Schaltschwelle 1,4V, HIGH&amp;gt;2.0V). Der LOW-Pegel wird auf ca. 0,3V 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;
&#039;&#039;&#039;Achtung:&#039;&#039;&#039; 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.3V -&amp;gt; 5V ===&lt;br /&gt;
&lt;br /&gt;
* 3.3V Pegel werden bei TTL kompatiblen Eingängen richtig erkannt (Schaltschwelle 1,4V). Es ist kein Pegelwandler erforderlich. Direkte Verbindung.&lt;br /&gt;
&lt;br /&gt;
* 5V 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 * VCC = 0.6 * 5V = 3V. Das kann ein 3.3V CMOS Ausgang direkt treiben, allerdings kann sich das Zeitverhalten dadurch etwas ändern weil der HIGH Pegel später erkannt wird. Vorsicht! Viele 5V CMOS ICs wollen für HIGH offiziell mindestens 0.7V * VCC = 3.5V oder manche auch 0.8 * VCC = 4.0V! Das geht dann offiziell nicht mehr mit einem 3.3V Ausgang! Für Hobbyzwecke kann man das aber ggf. probieren.&lt;br /&gt;
&lt;br /&gt;
* 3.3V [[Ausgangsstufen_Logik-ICs | Open Collector]] nach 5V (TTL oder CMOS): Einfach einen Pull-Up Widerstand hinzufügen und gut. Allerdings verbraucht der Pull-Up Widerstand bei LOW relativ viel Strom und kann bei HIGH nicht allzuviel Strom liefern. Die Schaltgeschwindigkeit von LOW nach HIGH wird durch die Grösse des Pull-Ups bestimmt.&lt;br /&gt;
&lt;br /&gt;
[[bild:pw_oc_3-5.png]]&lt;br /&gt;
&lt;br /&gt;
* 3,3V auf echte 5V (CMOS) geht am einfachsten mit einem Baustein der HCT Familie (NICHT HC !). Diese haben TTL-compatible Eingänge und echte CMOS Ausgänge&lt;br /&gt;
&lt;br /&gt;
* Man kann einen Komparator in nichtinvertierender Schaltung benutzen (LM339/393). Allerdings ist diese Lösung meist relativ langsam, abhängig vom verwendeten Komparator.&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 ...)&lt;br /&gt;
* 74HCT125: OE Pins auf Masse und dann das Signal einfach anschließen.&lt;br /&gt;
* SN74LVC07AD&lt;br /&gt;
&lt;br /&gt;
=== 5V -&amp;gt; 9..15V ===&lt;br /&gt;
&lt;br /&gt;
* Am einfachsten geht das mit einem Open Collector Ausgang, einfach einen Pull-Up hinzufügen (an die hohe Spannung) und fertig.&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 meist relativ langsam, abhängig vom verwendeten Komparator. Wenn nur zwei Signale pegelgewandlet 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 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 5V Gatters auf HIGH ist dann ist der Transistor ausgeschaltet, der Pull-Up Widerstand R7 zieht den Ausgang auf +12V. Ist der Ausgang des 5V Gatters auf LOW ist, dann ist er vollkommen durchgesteuert und der Ausgang nahe 0V (je nach Typ ca. 300mV). Der Vorteil ist hier erhöhte Störsicherheit im Gegensatz zur einfachen Ansteuerung der Basis über einen Vorwiderstand. Ausserdem wird dadurch nicht die Logik invertiert. Nachteilig ist der geringe Strom, der bei HIGH zur Verfügung steht (typisch 100&amp;amp;mu;A). Diese Schaltung ist die seltene Anwendung einer Basisschaltung für digitale Signale.&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 VDDI &amp;lt;= VDDO ist, kann man einfach eine Diode von VDDO nach VDDI 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 Vcc/Vee erforderlich (Bezugsquelle: CSD)&lt;br /&gt;
** MAX232, der braucht nur 5V Versorgungsspannung. Allerdings ist der Ausgangswiderstand relativ hoch (ca. 300Ω) und man kann nur ca. 5mA Ausgangstrom liefern. Die Ausgangsspannung beträgt maximal 10V.&lt;br /&gt;
&lt;br /&gt;
=== 5V -&amp;gt; 3.3V ===&lt;br /&gt;
&lt;br /&gt;
* Zuerst sollte man prüfen, ob die Eingänge 5V tolerant sind. Dann kann man die ICs direkt verbinden. Sehr schnell und billig!&lt;br /&gt;
&lt;br /&gt;
* Wenn die Eingänge nicht 5V tolerant sind und es trotzdem schnell sein soll, muss ein Gatter aus der LVC oder AHC Familie dazwischen geschaltet werden. Bei 3V Betriebsspannung kann man problemlos 5V an den Eingang anlegen. Der Baustein 74HC4050 erlaubt per Definition eine Pegelwandlung bis etwa 15V (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;
&lt;br /&gt;
:* 74HC4050 (bis 15V 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 5V-toleranten Eingängen, recht flott und braucht dank SOT-23 auch wenig Platz auf dem Print&lt;br /&gt;
&lt;br /&gt;
* 5V Open Collector auf 3.3V Eingang. Einfach einen Pull-Up hinzufügen (Pull-Up liegt auf 3.3V). 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 1kOhm. Der Nachteil dieser Lösung ist der relativ hohe Stromverbrauch (~3mA), der relativ geringe Ausgangsstrom (mehr als 200..300uA 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 kOhm Vorwiderstand. Dadurch wird der Strom vom 5V Ausgang in die 3.3V Versorgung durch die internen Schutzdioden auf ca. 1mA 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 1mA oder weniger durch die Schutzdioden! Ausserdem muss man aufpassen, das jetzt von der 5V Seite Strom in die 3.3V 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.3V übel wenn jemand &amp;quot;schiebt&amp;quot;, 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,3V als die internen Silizizumdioden mit ~0,7V), 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;
[[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 geniessen, denn die brauchen teilweise kurzzeitig einen relativ hohen Strom, um die Eingänge zu treiben.&lt;br /&gt;
&lt;br /&gt;
=== 5V &amp;lt;-&amp;gt; 3.3V ===&lt;br /&gt;
&lt;br /&gt;
* Wenn die 5V 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;
&lt;br /&gt;
=== 1,65V...5,5V &amp;lt;-&amp;gt; 1,65V...5,5V ===&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,2V...3,6V &amp;lt;-&amp;gt; 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,2V...3,6V &amp;lt;-&amp;gt; 1,2V...3,6V ===&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,5V...3,6V &amp;lt;-&amp;gt; 1,5V...5,5V ===&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]]&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]]&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;
&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 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://www.standardics.philips.com/support/documents/i2c/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. Vielleicht ist es sogar noch billiger Bipolartransistoren zu verwenden.&lt;br /&gt;
** http://www.semiconductors.philips.com/markets/mms/protocols/i2c/facts/#levelshifting&lt;br /&gt;
** http://www.semiconductors.philips.com/acrobat_download/literature/9398/39340011.pdf&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;
=== µC &amp;lt;-&amp;gt; Parallelport ([[ISP]]-Dongle, [[JTAG]] Wiggler, ...) ===&lt;br /&gt;
&lt;br /&gt;
Dieser Schaltplan funktioniert auch bei 3.3V 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;
=== 2 Leitungspaare 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;
= 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;
&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;
= Weblinks =&lt;br /&gt;
&lt;br /&gt;
* Gaurang Kavaiya, [http://www.edn.com/contents/images/6335309.pdf Don’t pay for level translators in systems using multiple power-supply voltages], EDN, MAY 25, 2006, 81-86 (PDF)&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 Palyer]&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 Themas 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;
&lt;br /&gt;
[[Category:Bauteile]]&lt;br /&gt;
[[Kategorie:Datenübertragung]]&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Snippets&amp;diff=62083</id>
		<title>Snippets</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Snippets&amp;diff=62083"/>
		<updated>2011-12-01T09:18:02Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: /* AVR: ADC */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Auf dieser Seite können kleine, oft verwendbare Quelltextchen und Designideen (Snippets) abgelegt und abgerufen werden.&lt;br /&gt;
&lt;br /&gt;
Bitte die Snippets universell verwendbar halten und für Dritte ausführlich und verständlich kommentieren.&lt;br /&gt;
&lt;br /&gt;
== Software-Snippets ==&lt;br /&gt;
&lt;br /&gt;
=== AVR: ADC ===&lt;br /&gt;
&lt;br /&gt;
Die folgenden Routinen sind einfachste C-Funktionen zum Auslesen des [[AD-Wandler]]s eines AVR. Die Registernamen bitte an den konkret verwendeten AVR anpassen (Datenblatt).&lt;br /&gt;
&lt;br /&gt;
Anm.: Umfangreichere Routinen mit Mittelwertbildung usw. finden sich im [[AVR-GCC-Tutorial#Analoge_Ein-_und_Ausgabe|AVR-GCC-Tutorial: Analoge Ein- und Ausgabe]]. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Auslesen eines Analogports&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
 // Führt eine AD Konversion durch und&lt;br /&gt;
 // liefert den Wert (0-1023) von PORT ADC(src) zurück&lt;br /&gt;
&lt;br /&gt;
 uint16_t ReadValue(uint8_t src)&lt;br /&gt;
 {&lt;br /&gt;
   ADMUX = src;&lt;br /&gt;
   ADCSR = _BV(ADEN)  | _BV(ADSC) | _BV(ADPS2);&lt;br /&gt;
   while (bit_is_set (ADCSR, ADSC));  &lt;br /&gt;
   return ADC;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Anmerkungen:&lt;br /&gt;
* ADMUX Parameter siehe Datenblatt (nicht gleich &amp;quot;Pinnummer&amp;quot;)&lt;br /&gt;
* ADSC/ADEN/ADPS2 Parameter siehe Datenblatt&lt;br /&gt;
* Einstellung der Referenzspannung beachten (Intern/Extern)&lt;br /&gt;
* Wandlerfrequenz an Genauigkeitsansprüche anpassen und nach Empfehlungen des Datenblatts in abh. vom &amp;quot;Haupttakt&amp;quot; einstellen&lt;br /&gt;
* ADEN nach erstmaligem Einschalten redundant&lt;br /&gt;
* evtl. Dummy Readout durchfuehren&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039; Umrechnung Wandlungsergebnis in gemessene Spannung&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
// Liefert die am ADC anliegende Spannung in mV zurück&lt;br /&gt;
#define ADC_CONV_CONST 5000/1024 // Spannung pro LSB (10 bit Wandler)&lt;br /&gt;
#define ADC_CORR_VAL (ADC*8)/9   // bei 5V Ref-Spannung erhält man mit dieser korrektur 5001mV bei einem ADC-Wert von 1023!&lt;br /&gt;
                                 // Für eine fehlerfreie Umwandlung ist eine Referenz von z.b 4.096V oder 2.56V notwendig...&lt;br /&gt;
uint16_t ReadValue(uint8_t src) {&lt;br /&gt;
  ADMUX = src;&lt;br /&gt;
  ADCSR = _BV(ADEN)  | _BV(ADSC) | _BV(ADPS2);&lt;br /&gt;
&lt;br /&gt;
  while (bit_is_set (ADCSR, ADSC))&lt;br /&gt;
    asm volatile (&amp;quot;nop&amp;quot;);&lt;br /&gt;
&lt;br /&gt;
  return ADC*ADC_CONV_CONST+ADC_CORR_VAL;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Anmerkungen:&lt;br /&gt;
* Das &#039;&#039;asm volatile&#039;&#039; Statement verhindert ein Wegoptimieren der Schleife.&lt;br /&gt;
&lt;br /&gt;
== Hardware-Snippets ==&lt;br /&gt;
&lt;br /&gt;
=== Wie schließe ich ein &amp;quot;LC-Display&amp;quot; an einen Mikrocontroller an? ===&lt;br /&gt;
&lt;br /&gt;
Siehe [[AVR-GCC-Tutorial#Ansteuerung_eines_LCD|AVR-GCC-Tutorial: Ansteuerung eines LCD]] und [[LCD]].&lt;br /&gt;
&lt;br /&gt;
===Wie schließe ich einen MOSFET an einen Mikrocontroller an?===&lt;br /&gt;
&lt;br /&gt;
In folgenden sind keine konkreten Typen für die MOS[[FET]]s genannt. Typen findet man in der [[Mosfet-Übersicht]] und in den parametrischen Suchmaschinen der Hersteller. Die genauen Daten und Belastungsgrenzen sind dann aus den Datenblättern zu entnehmen und für die geplante Schaltung zu prüfen. &lt;br /&gt;
&lt;br /&gt;
==&amp;gt; * [[FET]]&lt;br /&gt;
====Direkte Methode: N-Kanal MOSFET (NFET)====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                (VCC)&lt;br /&gt;
                  |&lt;br /&gt;
                (Last)&lt;br /&gt;
                  |&lt;br /&gt;
                  |&lt;br /&gt;
               (Drain )&lt;br /&gt;
(Port µC) -----(Gate  )&lt;br /&gt;
               (Source)&lt;br /&gt;
                  |&lt;br /&gt;
                  |&lt;br /&gt;
                (GND)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ausschlaggebend für die Steuerung ist die Gate-Source-Spannung. In dieser einfachen Schaltung ist das also die Spannung am Port des µC minus die Spannung an Source (= GND = 0V). Diese Spannung ist positiv!&lt;br /&gt;
Wenn diese einen Schwellwert überschreitet, dann sinkt der Drain-Source-Widerstand (RDSon)schlagartig auf ein Minimum. Übliche Werte liegen bei 0.1Ω, dieser Widerstand ist aber von dem Drain-Source-Strom und der Gate-Source-Spannung abhängig.&lt;br /&gt;
Der Umschaltpunkt (Spannung und Widerstand) kann im Datenblatt in den &amp;quot;RDSon vs. VGS&amp;quot; Diagramm abgelesen werden.&lt;br /&gt;
&lt;br /&gt;
====Direkte Methode: P-Kanal MOSFETs (PFET)====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
                (VCC)&lt;br /&gt;
                  |&lt;br /&gt;
                  |&lt;br /&gt;
               (Source)&lt;br /&gt;
(Port µC) -----(Gate  )&lt;br /&gt;
               (Drain )&lt;br /&gt;
                  |&lt;br /&gt;
                  |&lt;br /&gt;
                (Last)&lt;br /&gt;
                  |&lt;br /&gt;
                (GND)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ausschlaggebend für die Steuerung ist die Gate-Source-Spannung. In dieser einfachen Schaltung ist das also die Spannung am Port des µC minus die Spannung an Source (= VCC). Diese Spannung ist negativ!&lt;br /&gt;
Wenn diese einen Schwellwert unterschreitet, dann sinkt der Drain-Source-Widerstand (RDSon)schlagartig auf ein Minimum. Übliche Werte liegen bei 0.1Ω, dieser Widerstand ist aber von dem Drain-Source-Strom und der Gate-Source-Spannung abhängig.&lt;br /&gt;
Der Umschaltpunkt (Spannung und Widerstand) kann im Datenblatt in den &amp;quot;RDSon vs. VGS&amp;quot; Diagramm abgelesen werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Anmerkungen&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Zu beachten ist, dass zwischen Gate und Source und zwischen Gate und Drain eine Kapazität existiert, welche bei jedem Umschalt-Vorgang umgeladen werden muss. Besonders bei höheren Frequenzen (&amp;gt; 10kHz) ist zur Strombegrenzung zwischen Gate und Port-Pin ein Widerstand sinnvoll. Übliche Werte dafür sind 50 - 100Ω. Je höher der Widerstand ist, desto länger dauert das Umladen des Kondensators und desto langsamer schaltet der Transistor um. Daraus ergibt sich eine höhere Verlustleistung im Transistor, was unter Umständen zur Zerstörung des Transistors führen kann.&lt;br /&gt;
&lt;br /&gt;
TODO: Pinbelegung eines typischen MOSFETS&lt;br /&gt;
&lt;br /&gt;
====Indirekte Methode: Ansteuerungen mit Push-Pull-Transistoren====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 12V------------------------o------o---------------o-------------&lt;br /&gt;
                            |      |               |&lt;br /&gt;
                            |      |               |&lt;br /&gt;
                           .-.     |               |&lt;br /&gt;
                           | |2k2  |               |&lt;br /&gt;
                           | |R2   |               |&lt;br /&gt;
                           &#039;-&#039;     |T2             |&lt;br /&gt;
                            |      |BC338          |&lt;br /&gt;
                            |    |/                |&lt;br /&gt;
                            o----|                 |&lt;br /&gt;
                            |    |&amp;gt;         P-FET  |&lt;br /&gt;
                            |      |    ___ IRF4905|&lt;br /&gt;
                            o---|&amp;lt;-o---|___|----||-+&lt;br /&gt;
  .---------.               |  1N4148  R3 10R   ||-&amp;gt;&lt;br /&gt;
  |         |               |                   ||-+&lt;br /&gt;
  |         |    ___      |/                       |&lt;br /&gt;
  |         |---|___|-----|   T1                   o---------&lt;br /&gt;
  |         |   R1 2k2    |&amp;gt;  BC338                |         |&lt;br /&gt;
  |   µC    |               |                     .-.        |&lt;br /&gt;
  |         |               |                     | |        |&lt;br /&gt;
  |         |               |                     | | Last   - 1N5819&lt;br /&gt;
  |         |               |                     &#039;-&#039;        ^&lt;br /&gt;
  &#039;---------&#039;               |                      |         |&lt;br /&gt;
                            |                      |         |&lt;br /&gt;
 GND------------------------o----------------------o---------o---&lt;br /&gt;
(created by AACircuit v1.28.6 beta 04/19/05 www.tech-chat.de)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Durch die beiden NPN Treibertransistoren T1 &amp;amp; T2 (http://www.mikrocontroller.net/part/BC338) wird das Gate des P-FET auf HIGH oder LOW gezogen.&lt;br /&gt;
Wenn die Basis von T1 auf LOW ist dann wird das Gate von T2 auf HIGH gezogen.&lt;br /&gt;
der P-FET kann natürlich auch einfach gegen einen N-FET Ausgetauscht werden, wenn man die Last zwischen +12V und Drain Schaltet.&lt;br /&gt;
Mit dieser Schaltung kann man einen FET mit 20kHz und mehr (laut Simulation sind auch 50kHz kein Problem) Ansteuern.&lt;br /&gt;
Der Strom, welcher in das Gate rein bzw. raus fliesst, kann man mit R3 begrenzt werden.&lt;br /&gt;
Die geschaltete Betriebsspannung darf die zulässige Gate-Source Spannung (meist 20V) bei dieser Schaltung nicht überschreiten.&lt;br /&gt;
&lt;br /&gt;
Im µC Bereich können desweiteren folgende Hinweise  gegeben werden:&lt;br /&gt;
&lt;br /&gt;
* Es sollten sog. &amp;quot;Logik-Level&amp;quot; MOSFETS verwendet werden (Vth &amp;lt; 2V)&lt;br /&gt;
* Die Schaltleistung des FETs muss beachtet werden (Ids, VBrss)&lt;br /&gt;
* Beim Schalten von induktiven Lasten wie Relais, Motoren, oder auch Lasten über eine längere Zuleitung, sollten [[Relais_mit_Logik_ansteuern#Freilaufdiode|Freilaufdioden]] verwendet werden (im Schaltplan die Schottkydiode 1N5819 in Sperrrichtung über der Last.) Normale 1N400x Dioden sind zu langsam.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Algorithmen und Arithmetik]]&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Operationsverst%C3%A4rker-Grundschaltungen&amp;diff=61484</id>
		<title>Operationsverstärker-Grundschaltungen</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Operationsverst%C3%A4rker-Grundschaltungen&amp;diff=61484"/>
		<updated>2011-11-07T12:41:39Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: /* Spannungsfolger (Impedanzwandler) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Idealisiertes Modell eines OPV ==&lt;br /&gt;
&lt;br /&gt;
=== Anschlüsse ===&lt;br /&gt;
Ein Operationsverstärker hat zwei Eingänge (+) und (-) und einen Ausgang&lt;br /&gt;
(UA). Außerdem verfügt er über eine positive und eine negative&lt;br /&gt;
Spannungsversorgung (V+) und (V-).&lt;br /&gt;
&lt;br /&gt;
=== Spannungsversorgungen ===&lt;br /&gt;
Die Spannungsversorgungen sollen zunächst nicht interessieren. Sie&lt;br /&gt;
werden in Schaltungen oft nicht eingezeichnet. &lt;br /&gt;
In der Praxis ist es jedoch wichtig zu wissen, dass die Ausgangsspannung immer zwischen (V+) und (V-) liegt. Die Ausgangsspannung des OPV kommt schließlich  dadurch zustande, dass der Ausgang über einen Transistor mehr oder weniger hochohmig mit den beiden Versorgungsspannungen verbunden wird.&lt;br /&gt;
&lt;br /&gt;
Wenn man einen OPV also mit +5V versorgt, so kann der OPV im besten Fall am Ausgang +5V erzeugen. Man würde in diesem Fall von einem &amp;quot;Rail-to-Rail&amp;quot; Operationsverstärker sprechen.&lt;br /&gt;
Bei vielen Operationsverstärkern ist die maximal mögliche Ausgangsspannung geringer als die Versorgungsspannung. Ein mit +5V Spannungsversorgung beschalteter OPV kann dann beispielsweise nur +4V Ausgangsspannung erzeugen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
    | \&lt;br /&gt;
    |  \&lt;br /&gt;
 -- | - \&lt;br /&gt;
    |    \_______&lt;br /&gt;
    |    /&lt;br /&gt;
 -- | + /&lt;br /&gt;
    |  /&lt;br /&gt;
    | /&lt;br /&gt;
&lt;br /&gt;
=== Ausgang ===&lt;br /&gt;
Der Ausgang des OPV ist eine ideale Spannungsquelle. Das bedeutet, dass die&lt;br /&gt;
Ausgangsspannung unabhängig davon ist, was ausgangsseitig an den OPV&lt;br /&gt;
angeschlossen wird.&lt;br /&gt;
In der Praxis gilt dieses Modell häufig nur bei &amp;quot;sinnvollen Anwendungen&amp;quot;. So ist beispielsweise der Ausgangsstrom des OPV nach oben begrenzt (typischerweise im mA-Bereich), und manche OPV schwingen sehr leicht, wenn man sie kapazitiv belastet.&lt;br /&gt;
&lt;br /&gt;
=== Eingänge ===&lt;br /&gt;
Die Eingänge eines OPV sind hochohmig, d. h., es handelt sich nur um &amp;quot;Messfühler&amp;quot;, die keinen Strom führen.&lt;br /&gt;
&lt;br /&gt;
=== Funktionsweise ===&lt;br /&gt;
Der OPV mißt zu jeder Zeit die Differenz &amp;lt;math&amp;gt;U_D = U(+) - U(-)&amp;lt;/math&amp;gt; der&lt;br /&gt;
Eingangsspannungen.&lt;br /&gt;
&lt;br /&gt;
Ist die Spannung an (+) größer als an (-), so erhöht der OPV die&lt;br /&gt;
Ausgangsspannung.&lt;br /&gt;
Ist die Spannung an (+) niedriger als an (-), so vermindert der OPV die&lt;br /&gt;
Ausgangsspannung.&lt;br /&gt;
&lt;br /&gt;
Das Ergebnis dieses Vorgangs wird häufig über die Gleichung:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;U_a = v \cdot U_D&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
beschrieben, wobei &amp;lt;math&amp;gt;v&amp;lt;/math&amp;gt; eine sehr große Zahl (10^4...10^6) ist. &lt;br /&gt;
&lt;br /&gt;
Mit Hilfe der beschriebenen Funktionsweise lassen sich alle grundlegenden Schaltungen herleiten.&lt;br /&gt;
&lt;br /&gt;
=== Beispiel ===&lt;br /&gt;
&lt;br /&gt;
Betrachtet wird die invertierende Grundschaltung nach Abbildung a) im Abschnitt &amp;quot;Verstärkergrundschaltungen&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Für die Pfeilrichtungen der Spannungen und Ströme gilt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;U_e&amp;lt;/math&amp;gt;: von oben nach unten&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;I_{R3}&amp;lt;/math&amp;gt;: von links nach rechts&lt;br /&gt;
&lt;br /&gt;
Die Spannung am (+)Eingang ist gleich Null. Die Spannung am (-)Eingang wird durch die Spannungsquelle &amp;lt;math&amp;gt;U_e&amp;lt;/math&amp;gt; und durch die im OPV befindliche und mit dem Ausgang verbundene Spannungsquelle des OPV manipuliert.&lt;br /&gt;
&lt;br /&gt;
* Ist die Spannung am (-)Eingang negativ, so erhöht der Operationsverstärker die Ausgangsspannung. Dadurch wird auch die Spannung am (-)Eingang positiver. Und zwar so lange, bis die Spannung am (-)Eingang gleich groß ist, wie die Spannung am (+)Eingang, also U(-)=0V.&lt;br /&gt;
* Ist die Spannung am (-)Eingang positiv, so vermindert der Operationsverstärker die Ausgangsspannung. Dadurch wird auch die Spannung am (-)Eingang negativer. Und zwar so lange, bis die Spannung am (-)Eingang gleich groß ist, wie die Spannung am (+)Eingang, also U(-)=0V.&lt;br /&gt;
&lt;br /&gt;
Der Operationsverstärker wird also die Spannungen an (+) und (-)&lt;br /&gt;
angleichen. Das passiert immer dann, wenn der Ausgang mit dem (-)Eingang&lt;br /&gt;
verbunden ist. Man nennt das Prinzip &amp;quot;Gegenkopplung&amp;quot;. Auf diese Art und&lt;br /&gt;
Weise funktionieren alle analogen OPV-Schaltungen.&lt;br /&gt;
&lt;br /&gt;
Da an (+) Massepotential anliegt, liegt an &amp;lt;math&amp;gt;R_3&amp;lt;/math&amp;gt; die Spannung &amp;lt;math&amp;gt;U_e&amp;lt;/math&amp;gt; an, und es gilt: &lt;br /&gt;
&amp;lt;math&amp;gt;I_{R3}=\frac{U_e}{R_3}.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da der (-)Eingang hochohmig ist, fließt &amp;lt;math&amp;gt;I_{R3}&amp;lt;/math&amp;gt; über &amp;lt;math&amp;gt;R_4&amp;lt;/math&amp;gt; weiter zum OPV-Ausgang.&lt;br /&gt;
&lt;br /&gt;
Ua ist die Spannung vom Ausgang zur (virtuellen) Masse am (-)Eingang.&lt;br /&gt;
(--&amp;gt; Pfeil einzeichnen und klarmachen, daß es egal ist, ob der Pfeil vom&lt;br /&gt;
Ausgang zur Masse geht oder vom Ausgang &amp;quot;entgegen der Stromrichtung&amp;quot; zur&lt;br /&gt;
virtuellen Masse an (-)!)&lt;br /&gt;
&lt;br /&gt;
Mit Hilfe von &amp;lt;math&amp;gt;I_{R3}=\frac{U_e}{R_3}&amp;lt;/math&amp;gt; ergibt sich:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;U_a = -R_4 \cdot I_{R3} = -{{R_4} \over {R_3}} \cdot U_e.&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Energie für den Stromtransport über &amp;lt;math&amp;gt;R_4&amp;lt;/math&amp;gt; stammt vom OPV! Sobald die Ladungen ausgehend von der Spannungsquelle &amp;lt;math&amp;gt;U_e&amp;lt;/math&amp;gt; die virtuelle Masse an (-) erreicht haben, hat &amp;lt;math&amp;gt;U_e&amp;lt;/math&amp;gt; seine gesamte Energie abgegeben.&lt;br /&gt;
&lt;br /&gt;
== Reale OPs / Kennwerte ==&lt;br /&gt;
Abweichend vom idealen OP besitzen reale OPs diverse Einschränkungen und Kennwerte, die sie für verschiedene Einsätze mehr oder weniger prädestinieren.&lt;br /&gt;
&lt;br /&gt;
=== Leerlaufverstärkung ===&lt;br /&gt;
Die Leerlaufverstärkung gibt an, wie stark sich das Ausgangssignal i.A. der Änderung eines Eingangsignals statisch ändert, bzw nach dem Einschwingen erreichen könnte, wenn es nicht durch die Betriebsgrenzen limitiert wäre.&lt;br /&gt;
&lt;br /&gt;
=== Anstiegszeit ===&lt;br /&gt;
Bestimmend für die dynamische Änderung des Signal ist wiederum die slew rate, die wesentlich das AC-Verhalten bestimmt.&lt;br /&gt;
&lt;br /&gt;
=== Frequenz-Bandbreiteprodukt ===&lt;br /&gt;
&lt;br /&gt;
=== Gleichtaktverstärkung ===&lt;br /&gt;
Infolge des inhomogenen Aufbaus der internen Verstärkerstufen wird den die beiden Eingangssignale nicht exakt gleich verstärkt, was in einen Gleichanteil und einen Differenzaneil aufgeteilt werden kann. Der nicht erwünschte common mode ist dabei ein Mass für die Qualität des OP.&lt;br /&gt;
&lt;br /&gt;
== Verstärkergrundschaltungen ==&lt;br /&gt;
=== Grundbeschaltung mit Berechung ===&lt;br /&gt;
[[Bild:Op-verstaerker-a.png]] [[Bild:Op-verstaerker-b.png]]&lt;br /&gt;
&lt;br /&gt;
In a) und b) verwenden wir den OP als Verstärker und nutzen hier die Möglichkeit der Gegenkopplung, um definierte Verstärkungen zu erhalten. Wir gehen wieder davon aus, dass der OP ein ideales Bauteil ist und daher seine Leerlaufverstärkung unendlich ist. Ebenso betrachten wir den Eingangswiderstand als unendlich.&lt;br /&gt;
&lt;br /&gt;
In a) ist ein invertierender Verstärker mit einem OP dargestellt. Durch die Widerstände R3 und R4 wird die Verstärkung bestimmt:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;V = \frac{U_a}{U_e} = -\frac{R_4}{R_3}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Verhältnis der beiden Widerstände bestimmt also die Verstärkung und somit die Ausgangsspannung:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;U_a = -\frac{R_4}{R_3} \cdot U_e &amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
oder auch&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;U_a = V \cdot U_e&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das negative Vorzeichen drückt aus, dass es sich um einen invertierenden Verstärker handelt.&lt;br /&gt;
&lt;br /&gt;
Beim nichtinvertierenden Verstärker b) finden wir auch eine Rückkopplung über R6 zum invertierenden Eingang des OP. Die Verstärkung wird durch das Gegenkopplungsnetzwerk R6 und R7 exakt definiert. Hier ist:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;V = 1 + \frac{R6}{R7}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eine Verstärkung von 1 ist sinnvoll, wenn eingangsseitig eine Spannungsquelle mit hohem Innenwiderstand verwendet wird. Für &amp;lt;math&amp;gt;\frac{R6}{R7} \to 0&amp;lt;/math&amp;gt; heißt die Schaltung &amp;quot;Spannungsfolger&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Kleinere Werte als 1 lassen sich nicht realisieren. Die Ausgangsspannung errechnet sich also so:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;U_a = U_e \cdot \left (1 + \frac{R_6}{R_7}\right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiel: Eine Eingangsspannung von 0,5 V soll auf den Wert 5 V verstärkt werden, es ist also eine Verstärkung V von 10 benötigt. R7 ist mit 10 k&amp;amp;Omega; vorgegeben. Also ist das Verhältnis&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{R_6}{R_7} = V - 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei einem Wert von 10 k&amp;amp;Omega; für R7 errechnet sich R6 zu&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
R6 = (V - 1) \cdot R7&lt;br /&gt;
   = (10 - 1) \cdot 10\,\mathrm{k\Omega}&lt;br /&gt;
   = 90\,\mathrm{k\Omega}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Ausgangsspannung Ua wird also:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
U_a =   U_e \cdot \left (1 + \frac{R_6}{R_7}\right )&lt;br /&gt;
   = 0,5\,\mathrm{V} \cdot \left (1 + \frac{90\,\mathrm{k\Omega}}{10\,\mathrm{k\Omega}}\right)&lt;br /&gt;
   = 5\,\mathrm{V}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Spannungsfolger (Impedanzwandler) ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Op-spannungsfolger1.png]]&lt;br /&gt;
&lt;br /&gt;
Eine Abart des nichtinvertierenden Verstärkers stellt der Spannungsfolger dar. Beim nichtinvertierenden Verstärker errechnet sich die Ausgangsspannung aus:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;U_a = U_e \cdot \left (1 + \frac{R_2}{R_1}\right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wenn wir R2 auf 0 Ohm (mit R1 &amp;gt; 0) oder R1 auf unendlich (mit R2 &amp;lt; ∞) ändern, erhalten wir daher:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;V = 1 + \frac{R_2}{R_1} = 1&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ein Spannungsfolger hat also eine Verstärkung V von 1.&lt;br /&gt;
&lt;br /&gt;
Umgezeichnet sieht die Schaltung so aus: &lt;br /&gt;
&lt;br /&gt;
[[Bild:Op-spannungsfolger2.png]]&lt;br /&gt;
&lt;br /&gt;
Was soll das nun? Wir nutzen die Eigenschaft, dass ein idealer OP einen unendlichen Eingangswiderstand und einen Ausgangswiderstand von 0 Ohm hat. Real sieht das natürlich anders aus: so liegt der Eingangswiderstand Re bei normalen OPs in der Größenordnung von 1MOhm bis &amp;lt;math&amp;gt;10^{15} \Omega&amp;lt;/math&amp;gt;, der Ausgangswiderstand Ra im Bereich 20 Ohm bis 1kOhm. Deshalb spricht man bei dieser Schaltung von einem Impedanzwandler. Eine solche Schaltung kann also aus einer relativ hochohmigen Spannungsquelle eine niederohmige, durch Folgeschaltungen belastbare Spannungsquelle machen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Op-spannungsfolger3.png|left]]&lt;br /&gt;
&lt;br /&gt;
In dem nebenstehenden Beispiel ist eine einfache Möglichkeit zur Erzeugung einer Referenzspannung gezeigt. Es kommt eine normale Stabilisierungsschaltung mit einer Zenerdiode zur Anwendung, die aber nicht mehr die schlechten Eigenschaften der Standardbeschaltung mit lediglich Widerstand und Zenerdiode  hat. Bei einer Zenerdiode hängt die genaue Spannung davon ab, welcher Strom durch sie durchfliesst. Dieser Strom (und damit auch die Höhe der Zenerspannung) würde sich aber ändern, wenn ein Verbraucher die Zenerdiode direkt mit seinem Stromfluss belasten würde. Als Folge davon würde die Spannungslage der Zenerdiode je nach Verbraucher leicht schwanken. Durch den Spannungsfolger wird das verhindert, weil der jetzt den vom Verbraucher gezogenen Strom bereitstellt.&lt;br /&gt;
&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
[[Bild:Op-spannungsfolger4.png|left]]&lt;br /&gt;
&lt;br /&gt;
Eine weitere Anwendungsmöglichkeit wäre das hochohmige Auskoppeln einer Brückenspannung. Die Brückenschaltung selbst wird durch Folgeschaltungen nicht mehr belastet, alle anderen Eigenschaften bleiben erhalten.&lt;br /&gt;
&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
=== Der Komparator ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Op-komp-a.png]] [[Bild:Op-komp-b.png]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In der einfachsten Beschaltung des Operationsverstärkers erhält man einen Komparator. Es fällt auf, dass kein Gegenkopplungsnetzwerk vorhanden ist. Der OP arbeitet daher mit seiner vollen Leerlaufverstärkung Vo. Dies bedeutet, dass bereits eine kleine Eingangsspannung genügt, um den OP in die Begrenzung zu treiben. Das heißt, die Ausgangsspannung Ua wird annähernd die Betriebsspannung erreichen.&lt;br /&gt;
&lt;br /&gt;
Beim Komparator gibt es zwei Möglichkeiten der Beschaltung: die invertierende nach a) und die nichtinvertierende Beschaltung nach b). &lt;br /&gt;
&lt;br /&gt;
==== Berechnungsbeispiel für Schaltung b) ====&lt;br /&gt;
&lt;br /&gt;
Angenommen die Leerlaufverstärkung Vo von 40000 und eine Eingangsspannung von 0,1 Volt. Die Betriebsspannungen Vcc und Vee legen wir auf +/- 24 V fest. Damit ergibt sich theoretisch für Ua:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;U_a =  V_0 \cdot U_e = 40000 \cdot 0,1\,\mathrm{V} = 4000\,\mathrm{V}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das ist natürlich ein unrealistischer Wert, da Ua nicht höher sein kann als die Betriebsspannung. Also anders ausgedrückt: Bei welcher Spannung Ue erreicht der OP seine Aussteuerungsgrenze?&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;U_e = V_{cc} / V_0 = 24\,\mathrm{V} / 40000 = 0,6\,\mathrm{mV}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das bedeutet, dass eine Spannung von 0,6 mV ausreicht um den Komparator in die Begrenzung zu treiben.&lt;br /&gt;
&lt;br /&gt;
Das gleiche gilt auch für den invertierenden Komparator, allerdings wird hier der OP in die negative Begrenzung gebracht.&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;-U_a = V_0 \cdot U_e&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Der Addierer (Summierverstärker) ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Op-addierer.png]]&lt;br /&gt;
&lt;br /&gt;
Ein als invertierender Verstärker beschalteter OP lässt sich so beschalten, dass ein Summensignal aus den Eingangsspannungen gebildet wird. Um die Funktion deutlich zu machen, ist eine Betrachtung der einzelnen Ströme nötig.&lt;br /&gt;
&lt;br /&gt;
In einem invertierenden Verstärker wird sich die Ausgangsspannung immer so einstellen, dass der invertierende Eingang Massepotential hat. Die virtuelle Masse (VM) unterscheidet sich von einer &amp;quot;normalen&amp;quot; Masse dadurch, dass das Potential durch einen Regelungsvorgang zustande kommt. &lt;br /&gt;
An der virtuellen Masse (VM) gilt die Knotenpunktregel, wonach die Summe der zufließenden Ströme gleich der Summe der abfließenden Ströme ist.&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;I_1 + I_2 = -I_3&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Sofern &amp;lt;math&amp;gt;U_{e1}&amp;lt;/math&amp;gt; und &amp;lt;math&amp;gt;U_{e2}&amp;lt;/math&amp;gt; bekannt sind, lässt sich die Gleichung umformen in:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{U_{e1}}{R_1} + \frac{U_{e2}}{R_2} = -\frac{U_a}{R_3}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nach Ua aufgelöst ergibt sich:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;-U_a = \left (U_{e1} \cdot \frac{R_3}{R_1}\right ) + \left (U_{e2} \cdot \frac{R_3}{R_2}\right ) + ... + \left (U_{en} \cdot \frac{R_3}{R_n}\right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das war&#039;s eigentlich schon. Einen Sonderfall gibt es, wenn die Widerstände R1 und R2 gleich sind. Dann gilt&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;R_1 = R_2 = R_x&amp;lt;/math&amp;gt; &lt;br /&gt;
&lt;br /&gt;
und damit&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;-U_a = \frac{R_3}{R_x} \cdot (U_{e1} + U_{e2})&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Der Subtrahierer (Differenzverstärker) ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Op-subtrahierer.png]]&lt;br /&gt;
&lt;br /&gt;
Ein Subtrahierer ist die Zusammenschaltung eines invertierenden und eines nichtinvertierenden Verstärkers. Schliessen wir Punkt Ue1 nach Masse kurz und steuern Ue2 an, arbeitet die Schaltung als nichtinvertierender Verstärker. Wird Ue2 nach Masse verbunden und Ue1 angesteuert, verhält sich die Schaltung als invertierender Verstärker (R7 vorerst nicht beachten).&lt;br /&gt;
&lt;br /&gt;
Für den 1. Fall gilt:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;U_a = U_{e2} \cdot \left (1 + \frac{R_6}{R_4}\right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für den 2. Fall:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;U_a = -U_{e1} \cdot \frac{R_6}{R_4}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der dritte Fall ist die Ansteuerung beider Eingänge:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;U_a = -U_{e1} \cdot \frac{R_6}{R_4} + U_{e_2} \cdot \left (1 + \frac{R_6}{R_4}\right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Schaltung ist gut für eine Erklärung, praktisch aber taugt sie nichts. Denn liegen an den Eingängen gleiche Spannungen an, ist die Ausgangsspannung nicht 0, wie eigentlich zu vermuten wäre. Deshalb ändern wir die Schaltung und fügen R7 ein. Jetzt stellt sich am Punkt + des OPs die Spannung&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;U_{e2+} = U_{e2} \cdot \frac{R_7}{R_5 + R_7}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ein. Wenn wir das berücksichtigen, erhalten wir endlich einen richtigen Subtrahierer:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;U_a = U_{e2} \cdot \left (1 + \frac{R_6}{R_4}\right ) \cdot \frac{R_7}{R_5 + R_7} - \frac{R_6}{R_4} \cdot U_{e1}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dies gilt für alle Subtrahierer, obwohl es natürlich auch hier wieder zwei Sonderfälle gibt; nämlich a) wenn alle Gegenkopplungswiderstände gleich sind:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;R_6 = R_7 = R_4 = R_5&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
dann ist &lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;U_a = U_{e2} - U_{e1}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
oder b) wenn die Widerstandsverhältnisse gleich sind  :&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{R_6}{R_4} = \frac{R_7}{R_5}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dann ergibt sich für Ua:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;U_a = \left (U_{e2} \cdot \frac{R_6}{R_4}\right ) - \left (U_{e1} \cdot \frac{R_6}{R_4}\right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
oder noch einfacher:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;U_a = (U_{e2} - U_{e1}) \cdot \frac{R_6}{R_4}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Addierer/Subtrahierer mit unterschiedlichen Faktoren ===&lt;br /&gt;
Legt man nicht den + sondern den - Eingang des Operationsverstärkers als Bezugspunkt zur Masse mit einem Widerstand fest, übernimmt der Vorwiderstand vom - Eingang, R4 die Aufgabe von R5.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Op-addsub.png]]&lt;br /&gt;
&lt;br /&gt;
Hier die Schaltung die addieren und subtrahieren kann, mit unterschiedlichen Faktoren.&lt;br /&gt;
Sie kann verwendet werden für Aufgaben wie: Gesucht ist eine Schaltung, die aus 0...2.56 V eine Spannung von -10V...10V macht. Für dieses Beispiel wird hier die Dimensionierung durchgeführt:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align: left&amp;quot; &lt;br /&gt;
|&#039;&#039;&#039;Ue1 = 5V&#039;&#039;&#039;&lt;br /&gt;
|Einfach festgelegt, muss nur ein positiver Wert sein&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;R6 = 200k&#039;&#039;&#039;&lt;br /&gt;
|Einfach festgelegt, könnte auch 100k oder 500k sein&lt;br /&gt;
|-&lt;br /&gt;
|Ue2i = 0V, &#039;&#039;&#039;Uai = -10V&#039;&#039;&#039;&lt;br /&gt;
|gewählter momentaner &#039;&#039;Zustand 1&#039;&#039;, Ue2 = 0V ist günstig für Berechnung, Ua ist die dazupassende Ausgangsspannung&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Ue2ii = 2.56V&#039;&#039;&#039;, &#039;&#039;&#039;Uaii = 10V&#039;&#039;&#039;&lt;br /&gt;
|gewählter beliebiger &#039;&#039;Zustand 2&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
|Um = Ue2&lt;br /&gt;
|Gleichgewicht am Eingang&lt;br /&gt;
|-&lt;br /&gt;
|Ia + Ib = Ic&lt;br /&gt;
|In den Eingang fließt &amp;quot;kein&amp;quot; Strom&lt;br /&gt;
|-&lt;br /&gt;
|(Ua-Ue2)/R6 + (Ue1-Ue2)/R4 = Ue2/Rc&lt;br /&gt;
|Gleichung mit den Unbekannten R4 und Rc&lt;br /&gt;
|-&lt;br /&gt;
|(Uai-Ue2i)/R6 + (Ue1-Ue2i)/R4 = Ue2i/Rc&lt;br /&gt;
|Variablen für &#039;&#039;Zustand 1&#039;&#039; eingesetzt, bildet 1. Gleichung&lt;br /&gt;
|-&lt;br /&gt;
|(Uaii-Ue2ii)/R6 + (Ue1-Ue2ii)/R4 = Ue2ii/Rc&lt;br /&gt;
|Variablen für &#039;&#039;Zustand 2&#039;&#039; eingesetzt, bildet 2. Gleichung&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;math&amp;gt;R4=-\frac{R6*U_{e1}}{U_{ai}}&amp;lt;/math&amp;gt;&lt;br /&gt;
|2 Gleichungen mit 2 Unbekannten, Lösung durch Umformen der 1. Gleichung nach R4 und einsetzen von Ue2i=0 (freundlicherweise fällt die 2. Unbekannte dabei raus)&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;R4 = 100k&#039;&#039;&#039;&lt;br /&gt;
|restliche Werte eingesetzt&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;math&amp;gt;Rc=\frac{R6*U_{e1}*U_{e2ii}}{U_{aii}*U_{e1}-U_{ai}*(U_{e1}-U_{e2ii})-U_{e1}*U_{e2ii}}&amp;lt;/math&amp;gt;&lt;br /&gt;
|Ergebnis für R4 in die 2. Gleichung einsetzen und Umformen nach Rc&lt;br /&gt;
|-&lt;br /&gt;
|&#039;&#039;&#039;Rc = 41.6k&#039;&#039;&#039;&lt;br /&gt;
|Werte eingesetzt&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=== Der Instrumenten-Verstärker ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Instrument.png]]&lt;br /&gt;
&lt;br /&gt;
Ein Nachteil des Subtrahierer ist sein geringer Eingangswiderstand. Um den nahezu unendlichen Eingangswiderstand des verwendeten Operationsverstärkers zu erreichen, kann man einfach vor beide Eingänge je einen Impedanzwandler vorschalten.&lt;br /&gt;
Die hier beschriebene Schaltung ist um drei Widerstände erweitert und ermöglicht die Einstellung der Differenz-Verstärkung über nur einen Widerstand, nämlich R2.&lt;br /&gt;
&lt;br /&gt;
Am invertierenden Eingang von IC1A gilt (Knotenregel):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{U_{a1}-U_{e1}}{R_1}-\frac{U_{e1}-U_{e2}}{R_2}=0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Am invertierenden Eingang von IC1C gilt (Knotenregel):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;\frac{U_{a2}-U_{e2}}{R_1}+\frac{U_{e1}-U_{e2}}{R_2}=0&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Subtrahiert man die beiden Gleichungen voneinander, erhält man:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;U_{a2}-U_{a1}=(U_{e2}-U_{e1})\cdot\left (1+\frac{2\cdot R_1}{R_2}\right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Letztere Differenz ist die Eingangsspannung eines normalen Subtrahierers mit der Verstärkung 1.&lt;br /&gt;
&lt;br /&gt;
Also ergibt sich als Ausgangsspannung:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;U_a=(U_{e2}-U_{e1}) \cdot \left (1+\frac{2\cdot R_1}{R_2}\right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Differenzverstärkung beträgt demnach:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;V=\left (1+\frac{2\cdot R_1}{R_2} \right )&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Anwendung: Auswertung von Brückenschaltungen, wie Drucksensoren oder Dehnungsmessstreifen, die durch den Eingangswiderstand der Messschaltung nicht belastet werden dürfen.&amp;lt;br&amp;gt;&lt;br /&gt;
Instrumenten-Verstärker kann man auch fertig kaufen. Im INA102 ist die komplette Schaltung integriert. Für R2 sind 3 verschiedene Werte eingebaut, die bei passender Verschaltung eine Verstärkung von 1, 10, 100 oder 1000 ermöglichen.&lt;br /&gt;
&lt;br /&gt;
=== Der Multiplizierer (Mischer) ===&lt;br /&gt;
&lt;br /&gt;
=== Der Logarithmierer ===&lt;br /&gt;
&lt;br /&gt;
= Spannungsversorgung und Beschaltung =&lt;br /&gt;
&lt;br /&gt;
== Betrieb mit einfacher Versorgungsspannung ==&lt;br /&gt;
&lt;br /&gt;
Häufig möchte man Wechselspannung (z. B. Audiosignale) die auch negative Spannungen enthält mit einem Opamp verstärken, hat aber nur eine einfache Versorgungsspannung, eine positive in Bezug zu Masse, zur Verfügung. Dafür bieten sich folgende Schaltungen an, die in der Literatur leider häufig vernachlässigt werden.&lt;br /&gt;
&lt;br /&gt;
=== Nichtinvertierender Verstärker ===&lt;br /&gt;
&lt;br /&gt;
[[Bild: Ss_opamp1.png]]&lt;br /&gt;
&lt;br /&gt;
Der negative Eingang wird mit einem Spannungsteiler auf die halbe Betriebsspannung gelegt und das Signal mit Kondensatoren am Ein- und Ausgang entkoppelt.&lt;br /&gt;
Die Verstärkung ist in diesem Beispiel für Wechselspannung 11 (Formel wie oben), für Gleichspannung aber 1, da C4 für Gleichspannung einen unendlichen Widerstand darstellt. C3 sollte dorthin gehen, wo das Eingangssignal seinen Bezugspunkt hat, also die Abschirmung der Chinch-Buchse, während R5 dorthin geht, wo der Operationsverstärker seine negative Versorgungsspannung her bekommt, falls das nicht die gleichen Pontentiale, hier GND, sein sollten.&lt;br /&gt;
&lt;br /&gt;
=== Invertierender Verstärker ===&lt;br /&gt;
&lt;br /&gt;
Das Prinzip funktioniert analog auch für die invertierende Beschaltung:&lt;br /&gt;
&lt;br /&gt;
[[Bild: Ss_opamp2.png]]&lt;br /&gt;
&lt;br /&gt;
= Kaufempfehlung =&lt;br /&gt;
LM 158/258/358 2 OPs in einem Gehäuse Preis ca. 0,30€.&lt;br /&gt;
&lt;br /&gt;
Siehe auch [[Standardbauelemente#Operationsverst.C3.A4rker|Standardbauelemente - Operationsverstärker]].&lt;br /&gt;
&lt;br /&gt;
Wer Audio OpAmps sucht - tangentsoft.net hat mal welche unter die Lupe genommen: [http://www.tangentsoft.net/audio/opamps.html Notes on Audio OpAmps]&lt;br /&gt;
&lt;br /&gt;
= Weblinks =&lt;br /&gt;
*[http://www.eetkorea.com/ARTICLES/2003SEP/A/2003SEP19_AMD_AN07.PDF Op Amp Circuit Collection] - National Semiconductor Application Note 31 mit vielen weiteren OP-Schaltungen&lt;br /&gt;
*[http://www-s.ti.com/sc/psheets/slod006b/slod006b.pdf Op Amps for Everyone] - englischsprachiges, sehr umfangreiches Dokument zu OPV und deren Anwendung (empfehlenswert)&lt;br /&gt;
* [http://www.elektronik-kompendium.de/sites/bau/0209092.htm Operationsverstärker im ElKo]&lt;br /&gt;
*[http://www.inf.fu-berlin.de/lehre/WS00/peg/folien/Peg_v7a.pdf OP Teil 1], [http://www.inf.fu-berlin.de/lehre/WS00/peg/folien/Peg_v7b.pdf OP Teil 2] - OP-Schaltungen (deutsch)&lt;br /&gt;
*[http://www.blecken.de/download/opverst.zip Schaltungstechnik mit Operationsverstärkern] - Prof. K. Blecken, Skript zur Vorlesung (deutsch, *.doc-Format)&lt;br /&gt;
* [http://www.roboternetz.de/wissen/index.php/Operationsverst%C3%A4rker RN-Wissen Operationsverstärker]&lt;br /&gt;
* [http://www.national.com/onlineseminar/#amps Online Seminar] von National Semiconductor&lt;br /&gt;
* [http://www.franzis.de/elo-das-magazin/grundlagen-und-ausbildung/operationsverstaerker/der-operationsverstaerker ELO-Online-Magazin, Franzis-Verlag], [http://www.franzis.de/online-shop/elektronik/lernpakete-elektronik/lernpaket-elektronik-mit-ics Lernpaket Elektronik mit ICs] &amp;quot;Elektronische Experimente mit integriertem Schaltkreis&amp;quot;, Kasten mit Steckbrett/Bauelementen (ca. 40EUR), &lt;br /&gt;
* [[Schmitt-Trigger]]&lt;br /&gt;
* [[Aktiver RC-Bandpass|Aktiver RC-Bandpass auf Operationsverstärker-Basis]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Grundlagen]]&lt;br /&gt;
[[Category:Bauteile]]&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Diskussion:Frequenzumrichter_mit_Raumzeigermodulation&amp;diff=61127</id>
		<title>Diskussion:Frequenzumrichter mit Raumzeigermodulation</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Diskussion:Frequenzumrichter_mit_Raumzeigermodulation&amp;diff=61127"/>
		<updated>2011-10-18T16:11:16Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: /* Rampen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Fragen ==&lt;br /&gt;
&lt;br /&gt;
Ein paar Fragen die ich gerne im Artikel beantwortet sehen würde:&lt;br /&gt;
&lt;br /&gt;
Wie wird der Motoranlauf realisiert?&lt;br /&gt;
Wie wird die Istdrehzahl erfasst?&lt;br /&gt;
Wie wird die Iststromaufnahme erfasst?&lt;br /&gt;
Warum kommt man ohne p-Kanal FETs aus?&lt;br /&gt;
&lt;br /&gt;
Danke für die Anregungen.&lt;br /&gt;
&lt;br /&gt;
Habe die Fragen unter Steuerung und Leistungsteil ausfürlich beantwortet. &lt;br /&gt;
&lt;br /&gt;
Hier in Kürze:&lt;br /&gt;
&lt;br /&gt;
Es gibt einen Hochlaufgeber in Programm. &lt;br /&gt;
&lt;br /&gt;
Die Istdrehzahl kann mit einem Hallgeber erfasst werden, ist aber noch nicht getestet.&lt;br /&gt;
&lt;br /&gt;
Ist-Strom wird nur im Zwischenkreis gemessen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Rampen ==&lt;br /&gt;
&lt;br /&gt;
Erstmal Respekt für dieses Projekt, normalerweise wird &amp;quot;FU selberbauen&amp;quot; mit einem &amp;quot;schau dir mal richtige FU&#039;s an das ist unmöglich...&amp;quot; abgetan.&lt;br /&gt;
&lt;br /&gt;
Ich habe Interesse am Nachbau, jedoch einige Fragen:&lt;br /&gt;
Gibt es eine einstellbare Start-Stop Rampe? Weil von 0 auf 100 in 0s ist nicht gut für n Motor... zweitens, wie genau wird beim Stoppen Bremsenergie vernichtet?&lt;br /&gt;
&lt;br /&gt;
Des weiteren: Das ganze ist ja auch für &amp;quot;richtige Motoren&amp;quot; ausgelegt, hast du es mal mit nem z.b. 0,75kW Drehstrommotor getestet?&lt;br /&gt;
&lt;br /&gt;
Danke für die Lorbeeren.&lt;br /&gt;
&lt;br /&gt;
Getestet habe ich mit einem 0,5KW Drehstromgebläse, da bekam ich die Leistung am einfachsten für den Dauerbetrieb &amp;quot;vernichtet&amp;quot;. Nebenbei war auch der Staub aus den Ecken in meinem Bastelschuppen verschwunden bzw verteilt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Hoch- und Rücklauframpe ist gleich und wird per Timer 0 im Mega 32 gebildet. Ist leider (noch) nicht konfortabel einstellbar, da muss am Timerwert geändert werden. Beim schnellen Verringern der Ausgangsfrequenz steigt automatisch die Zwischenkreisspannung an. Das liegt im Wesen des Wechselrichters. In der Einspeiseeinheit wird die Zwischenkreisspannung gemessen und ab 340V wird auf eine 100W Glühlampe geschoppt. Da das Gebläse am Ausgang nicht so viel Schwungmasse hatte, hat die Lampe nur kurz aufgeleuchtet. Reicht aber für den Funktionstest.&lt;br /&gt;
&lt;br /&gt;
Axel&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Diverse Fragen ==&lt;br /&gt;
&lt;br /&gt;
Aus der Mailkommunikation mit Axel:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;1. zum Ladewiderstand (R16)&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
R16 in der Einspeisung ist mit 5Ohm bei 5W angegeben... wie kommst du auf den Wert?&lt;br /&gt;
&lt;br /&gt;
Antwort:&lt;br /&gt;
Das ist der Ladewiderstand der Kondensatoren, sonst fließe ein zu großer Ladestrom und die Sicherung geht flitzen. Wenn der R größer ist dauert das Laden halt länger.&lt;br /&gt;
&lt;br /&gt;
Rückfrage:&lt;br /&gt;
Soweit ist das schon klar... nur 5 Ohm bei 230V entsprechen 46A!? Also sind die 5W doch etwas klein!? Oder hält sich das in Grenzen, weil die Kondensatoren so schnell geladen werden?&lt;br /&gt;
&lt;br /&gt;
Antwort:&lt;br /&gt;
hast Recht, nimm 20 Ohm, zur Zeit habe ich dort eine Glühlampe eingebaut.&lt;br /&gt;
&lt;br /&gt;
Rückfrage:&lt;br /&gt;
Warum wird R16 bei erreichen einer best. Spannung überbrückt? Das verstehe ich nicht ganz.&lt;br /&gt;
&lt;br /&gt;
Damit der Ladewiderstand im Betrieb nicht stört.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;2. Dimensionierung Zwischenkreis Kondensatoren:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Die Zwischenkreis Kondensatoren haben bei dir keine angegebenen größen...  Ich brauche wohl Elkos, die &amp;gt;400V aushalten, also müssten 450V Typen doch ausreichend sicher gewählt sein!?&lt;br /&gt;
&lt;br /&gt;
Antwort: Ja&lt;br /&gt;
&lt;br /&gt;
Zur Kapazität: Sie müssen doch lediglich die &amp;quot;Totzeiten&amp;quot; der gleichgerichteten Wechselspannung ausgleichen, also brauchen sie ja garnicht so extrem groß sein... wie groß hast du deine dimensioniert? Und wo bekomme ich die Dinger einigermaßen erschwinglich her?&lt;br /&gt;
&lt;br /&gt;
Anwtort: habe ca 2000µF&amp;lt;br /&amp;gt;&lt;br /&gt;
alte Schaltnetzteile, da habe ich meine her.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;3. Bezugsquelle IR Chips&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
wo hast du die ganzen IR Chips und Mosfets her? Hab mal kurz bei Conrad geguckt, die haben zwar alles, was ich bisher gesucht habe, aber zu astronomischen Preisen :-/ Reichelt ist da besser, hat aber nicht alles... hast du ne bessere Quelle?&lt;br /&gt;
&lt;br /&gt;
Antwort: auch von diesen Beiden &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;4. Unterschiedliche Mos-Fets in Leistungsteil&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Im Leistungsteil hast du je einen IRFP460 und einen IRFPC40 parallel geschaltet. Hat das einen Grund?&lt;br /&gt;
&lt;br /&gt;
Antwort: Reserve, muss nicht bestückt werden&lt;br /&gt;
&lt;br /&gt;
Rückfrage:schon klar - aber warum gerade diese beiden? Ich könnte doch auch einen Typ nehmen, oder? der muss nur halt die Belastung aushalten... also genügend spannungsfest und entsprechend leistungsstark sein.&lt;br /&gt;
&lt;br /&gt;
Antwort: Stimmt, das ist ein Fehler in Plan.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;5. Dimensionierung der Widerstände R5-7 &amp;amp; R9&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
nochmal zurück zur Einspeisung: dort sind als Spannungsteiler (?) 3 &lt;br /&gt;
Widerstände und ein Poti (R5-R7, R9) verrätst du mir die Werte?&lt;br /&gt;
&lt;br /&gt;
Antwort: 270K, 3Stück wegen der Spannungsfestigkeit&lt;br /&gt;
&lt;br /&gt;
Rückfrage: Das Poti hat auch 270k?&lt;br /&gt;
&lt;br /&gt;
Das Poti hat 10K&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
== Treiber ==&lt;br /&gt;
&lt;br /&gt;
Kann man statt den ir2109 auch ir2104 nehmen, worauf kommt es bei der auswahl an? Diese beiden sind recht ähnlich. Den ir2104 gibt es aber auch bei tme und das wesentlich preiswerter als den ir2109 bei Conrad.&lt;br /&gt;
&lt;br /&gt;
Würde sagen, der 2104 ist noch etwas besser.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Gratuliere dir. Ist schon beachtlich was du in einem Hobbyprojekt geleistet hast. Hast du Beruflich auch etwas mit dieser Materie zu tun?&lt;br /&gt;
 &lt;br /&gt;
Die Ausgangsmodulation ist noch nicht Optimal aber schon sehr gut. Für weitere Anregungen kann ich dir das Buch von Felix Jenni und Dieter Wüest über „Steuerverfahren für selbstgeführte Stromrichter„ empfehlen wenn du das nicht sowieso schon kennst.&lt;br /&gt;
 &lt;br /&gt;
Mfg Michael&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Hallo, Finde es super das du dir die Arbeit gemacht hast das Projekt online zustellen.&lt;br /&gt;
Ich habe eine Frage zu den Zener Dioden Am Gate der MosFets und der Spannungs Teiler R1,3,5 zu R7,9,11 (47 zu 47k). Erstens warum setzt du die Diode dort nur als Spannungs begrenzung? Brauche ich die auch wenn ich nur 12V auf dem Zwischenkreis habe? Zweitens du belastest den Bootstrap mit dem 47K Widerstand, ist der PullDown so wichtig das du es in Kauf nimmst den Bootstrap zu belasten?&lt;br /&gt;
(Hintergrund Mir rauchen in meiner Schaltun die IR2184 ab die fast gleich zu den 2109 oder 2104 sind)&lt;br /&gt;
&lt;br /&gt;
Danke&lt;br /&gt;
&lt;br /&gt;
Hallo,&lt;br /&gt;
&lt;br /&gt;
Die Z-Diode ist eine reine Angst Diode. Habe ich in einer App-Note gefunden, Platz auf der Platine gehabt und somit reingebaut. Ob die Lebenswichtig ist glaube ich nicht, es gibt auch andere Schltpläne ohne diese Diode.&lt;br /&gt;
&lt;br /&gt;
Der 47K Pull-Down verhindert ein Durchschalten beider Transistoren, wenn der IR2109 nicht steckt oder mal abgeraucht ist. Also wohl auch ein Angtwiderstand.&lt;br /&gt;
Da aber mit 2,5 Khz geschaltet wird, ist der Bootstrap Kondensator nie leer.&lt;br /&gt;
&lt;br /&gt;
Axel&lt;br /&gt;
&lt;br /&gt;
== Andere Spannungsversorgung ==&lt;br /&gt;
&lt;br /&gt;
Hallo,&lt;br /&gt;
&lt;br /&gt;
Ich will den Frequenzumrichter nachbauen, möchte ihn aber etwas kompakter machen. Bis jetzt habe ich es geschafft, den Hochspannungsteil komplett auf einer Platine (Eagle-freie-version-maximum) unterzubringen, aber für den Trafo finde ich einfach keinen Platz mehr. Ich möchte die 12 V aus den 325 V mit einer einfachen Schaltung herunterregeln (z.B. Mit einem MOSFET und einer Z-Diode). Weiß jemand wieviel Strom die Schaltung normalerweise von 15V zieht? Ist das lastabhängig (ich meine Motorlast)?&lt;br /&gt;
&lt;br /&gt;
Falls es erwünscht ist, werde ich natürlich meine modifizierte Schaltung hier veröffentlichen, wenn sie fertig ist.&lt;br /&gt;
&lt;br /&gt;
Mit freundlichen Grüßen,&lt;br /&gt;
Rupert Eibauer&lt;br /&gt;
&lt;br /&gt;
Hallo Rupert,&lt;br /&gt;
es fleißen zwischen 50 und 100mA.&lt;br /&gt;
Das wären bei einem Längsregler 15 bis 30W Verlustleistung.&lt;br /&gt;
Such lieber einen Platz für den Trafo.&lt;br /&gt;
&lt;br /&gt;
Deine Schaltung ist natürlich erwünscht, füge sie einfach unter einer neuen Überschrift an.&lt;br /&gt;
&lt;br /&gt;
Axel&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Sektoren ==&lt;br /&gt;
Hallo Axel, &lt;br /&gt;
ich weis nicht ob ich hier an der richtigen stelle bin um ne frage zu stellen, aber ich tus mal naiiver weise ;)&lt;br /&gt;
&lt;br /&gt;
hier ist die rede von raumzeigermodulation, aber im text habe ich irgendwas von &amp;quot;sechs sektoren&amp;quot; gelesen, ich vermute du meinst die sechs bitmuster die du verwendest.  ich will nicht spitzfindig sein, aber in wie viele mikroschritte wird denn per elektrischen umdrehung des motors unterschieden, sprich, aus wievielen &amp;quot;schritten&amp;quot; besteht dein sinus (und somit der raumzeiger)?  das oszi-bild zeigt ja, dass es sich hier nicht um sechs &amp;quot;plumpe schritte&amp;quot; wie in der block-kommutierung handelt.  (kann man bei einer asynchron-maschine von kommutierung reden?)&lt;br /&gt;
&lt;br /&gt;
wie dem auch sei, ein sehr schönes projekt, gefällt mir, obwohl ich lieber mit spannungen unter 48VDC arbeite und mit wechselspannung nix am hut habe ;)&lt;br /&gt;
&lt;br /&gt;
hast du schon mal daran gedacht eine synchronmaschine zu kommutieren?  das wäre mal eine echte herausforderung mit einem (oder mehreren) AVRs die d- und q-ströme in den griff zu bekommen.  wenn man das aber hinkriegt und den kommutierungswinkel auf 90° regeln kann hätte man die synchronmaschine in die bastelwelt aller hier lesenden gehoben!&lt;br /&gt;
&lt;br /&gt;
sicherlich nicht trivial, aber sportlich ;)&lt;br /&gt;
gruss, und nochmal respekt,&lt;br /&gt;
&lt;br /&gt;
heinz&lt;br /&gt;
&lt;br /&gt;
Hallo Heinz,&lt;br /&gt;
&lt;br /&gt;
das Programm macht alle 400µs einen &amp;quot;Schritt&amp;quot;. Dass heißt, je niedriger die Ausgangsfrequenz ist, umso besser wird der Sinus nachgebildet.&lt;br /&gt;
&lt;br /&gt;
Eine Syncronmaschine geht mehr in den Bereich BLDC Motor. Der Artikel hier im Forum ist aber leider irgendwie nicht fertig geworden. Sollte ein Gemeinschaftswerk werden und obwohl zuerst alle recht begeistert bei der Sache waren, haben viele Köche doch den Brei verdorben.&lt;br /&gt;
&lt;br /&gt;
Axel&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Einige Fragen ==&lt;br /&gt;
&lt;br /&gt;
Hallo Axel,&lt;br /&gt;
&lt;br /&gt;
Erstmal danke dafür, dass du dir die ganze Mühe gemacht hast, die Dokumentation deines Projektes zu schreiben, hier einzustellen und auch noch zu pflegen - vielen Dank!&lt;br /&gt;
&lt;br /&gt;
Ich beschäftige mich leider erst einige Monate mit Elektronik, da ich damals ins Auge gefasst habe, einen Drehstrom-Asynchronmotor mit Steuerung zu entwerfen und zu bauen. Ich bin Physik-Student im 6. Semester und habe dementsprechend Basiswissen über die physikalischen Hintergründe, jedoch nur sehr wenig praktisches, angewandtes Wissen. Dafür bin ich aber in der außerordentlichen Position an meiner Uni das Studenten-Elektroniklabor zu leiten, das gerade eben erst von den Studiengebühren eingerichtet worden ist. Das heißt konkret, dass ich auch die Bauteile bestelle und deswegen Geld für mich nur eine untergeordnete Rolle spielt. Um einen Nachbau realisieren zu können, brauche ich allerdings noch ein paar Antworten auf ein paar Fragen, die ich im Internet noch nicht gefunden habe.&lt;br /&gt;
&lt;br /&gt;
Ich entschuldige mich schonmal, da bestimmt einige Fragen dabei sind, die ziemlich dämlich bzw. mit einigem Suchen doch noch im Netz zu finden wären. Falls jemand trotzdem die Antworten zu ein paar der folgenden Antworten weiß und sie hier aufschreibt, wäre ich äußerst dankbar! Los gehts:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zum Bremschopper:&lt;br /&gt;
&lt;br /&gt;
1. Aus dem Netz kommen 230V Wechselspannung mit 50Hz. Um andere Frequenzen rauszufiltern, bilden die Spule und der Kondensator einen Bandpass. Wie groß wählt man z.B. den Q-Faktor des Bandpasses? Oder einfacher: Welche Werte haben C11 und L1? Muss man bei den großen Spannungen auf besondere Eigenschaften der beiden Bauteile achten? Spannungsfestigkeit von C11&amp;gt;325V? &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;C11, L1 und C12 sind ein Filter um Störungen &#039;&#039; &#039;&#039;&#039;zurück&#039;&#039;&#039; &#039;&#039; ins Netz zu minimieren. C11,C12 befinden sich auf der Wechselspannungsseite vor dem Gleichrichter! Daher 450V ~ . Bei der Dimensionierung habe ich mich an alte Computernetzteile angelehnt, leider ohne jede Berechnung .&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
2. Kann man statt C4 und C2 nicht einen Kondensator mit der Gesamtkapazität nehmen? Warum ist bei C4+C2 die Polung wichtig, und bei C12 nicht? Haben C2 und C4 jeweils einzeln 2000mikroFarrad, oder beide zusammen? Stimmt es, dass C2, C4 und C11 450V-Typen sind? &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ich hatte leider keine unbegrenzten Geldmittel zur Verfügung, daher habe ich die Zwischenkreiskondensatoren aus alten Computernetzteilen ausgebaut. Es kann natürlich ein großer Kondensator 450V- verwendet werden. ( C11 siehe zu 1) &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
3. Warum braucht man zwei Relais (P1 und P2)? Ist das Relais, dass am ATTiny hängt, stellvertretend für diese beiden Relais? &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;P1 und P2 sind die Kontakte des&#039;&#039; &#039;&#039;&#039;einen&#039;&#039;&#039; &#039;&#039;Relais K2. Hatte gerade ein solches Relais in der Bastelkiste. (siehe 2) &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
4. Aus den 230V werden auch 9V transformiert, so dass diese 9V für die Chips zur Verfügung steht. An manchen Stellen steht VCC im Plan, an anderen +12V. Woher kommen diese 12V? Woher nimmt man 5V und 15V? &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Aus 9V~ entstehen nach Gleichrichtung und Glättung 12V bis 15V DC. Die 5V werden durch den 7805 erzeugt. &#039;&#039; &lt;br /&gt;
&lt;br /&gt;
5. Jetzt mal ne ganz blöde Frage: Wie funktioniert das mit den X1-3 usw. Anschlüssen? Sind das Verbindungen zu den anderen Platinen bzw. Klemmanschlüsse? &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Sind Klemmanschlüsse zur Wechselrichter-Platine. X1-1 ist 15VDC;  X1-3 ist: Zwischenkreis OK, Ladung der Kondensatoren abgeschlossen. &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
6. Welche Anforderungen müssen die Gleichrichter erfüllen? &lt;br /&gt;
&#039;&#039;B2 ist aus einem alten Schaltnetzteil ein 230V Typ! B1: 30V 100mA &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
7. Wieviele Zwischenkreiskondensatoren mit Spannungsfestigkeit &amp;gt; 450V brauche ich im Endeffekt, bzw. was für eine Kapazität muss ich erreichen?&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;Das ist wie beim Hubraum bei Autos, viel hilft viel und bewahrt einen evtl. vor seltsamen Effekten. 2000µF sollten reichen. &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Schonmal vielen Dank an jeden, der sich die Mühe macht, meine Fragen zu beantworten! &lt;br /&gt;
Ich habe übrigens das Schema der Einspeisung und des Bremschoppers ein wenig übersichtlicher gestaltet und die 270k-Angaben der drei Widerstände, die 20R vom Ladewiderstand, die 10k vom Poti und die 2mF bzw. 2000µF der Zwischenkreiskondensatoren im Plan ergänzt. Hier ist der Link:&lt;br /&gt;
 &lt;br /&gt;
http://www.uni-bonn.de/~maschoe/Bremsshopper_mod.sch &lt;br /&gt;
http://www.uni-bonn.de/~maschoe/Bremsshopper_mod. -&amp;gt; png &lt;br /&gt;
&lt;br /&gt;
Soll ich den alten Plan einfach ersetzen? Natürlich werde ich auch in Zukunft alle Verbesserungen, die mir auffallen, ins Wiki fließen lassen. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Kannst Du einstellen, ändere die +12V in +15V damit es sich mit den Bezeichnungen der Leistungsteilplatine nicht beißt. &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Achja, und übrigens: Die Eagle-Dateien in der zip-File vom Leistungsteil sind irgendwie leer, jedenfalls bei mir - liegt das an meinem Rechner oder an den Dateien? &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Lässt sich bei mir entpacken: Wechselrichter 4.sch , Wechselrichter 4.brd und der Ordner WR88_RZM mit dem Steuerprogramm &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viele Grüße, &lt;br /&gt;
Matthias &lt;br /&gt;
1000fragen 19:28, 18. Mär. 2009 (CET) &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hallo Matthias,&lt;br /&gt;
habe die Antworten kursiv unter die Fragen geschrieben.&lt;br /&gt;
&lt;br /&gt;
Axel&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hey Axel,&lt;br /&gt;
&lt;br /&gt;
Viele Dank für die Hinweise! Ich habe sie im Artikel verwurstet.&lt;br /&gt;
&lt;br /&gt;
Matthias&lt;br /&gt;
&lt;br /&gt;
[[Benutzer:1000fragen|1000fragen]] 21:12, 22. Mär. 2009 (CET)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hi Axel,&lt;br /&gt;
&lt;br /&gt;
Wegen der Eagle-Dateien: Das Archiv lässt sich bei mir auch entpacken und die Dateien sind auch da, aber wenn ich die dann in Eagle öffne, sind die Pläne leer - Könntest du nochmal kurz nachsehen ob das bei dir auch so ist? Habs unter Windows und unter Linux getestet...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Habe ein zweites Zip File hochgeladen, schau mal ob dieses geht.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Außerdem noch eine Frage zum Schaltplan: Es sind ja einige Kondensatoren parallel geschaltet, z.B. gepolt 100u und ungepolt 100n. Sind die ungepolt 100n-Kondensatoren da, um die gepolten 100u-Kondensatoren vor eventuell falsch gepolten Spannungsspitzen zu schützen? Könnte ich also auch einfach 100u ungepolte Kondensatoren nehmen?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Es geht hier nicht um dir Polung, sondern um die Geschwindigkeit mit der die unterschiedlichen Kondensatoren Ladung aufnehmen können. Die 100n sind für schnelle Änderungen.&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Was den Wechselrichter angeht:&lt;br /&gt;
&lt;br /&gt;
Die Kondensatoren C8, C10, C12, C13: Ist C8+C10=2000uF? Was ist C12+C13? &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Da sind einige optionale Kondensatoren auf den Platinen, je nach dem welche Kondensatoren verügbar sind. Wie schon gesagt, es kann nicht schaden etwas mehr zu haben.&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
Ich nehme mal an, dass die Dioden alle vom Typ 1N4004 sind, oder?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Die Dioden sind 1N4004&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Edit: Hat der Hochstromanschluss ein anderes Massepotential als die IR2109?&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;Ist das gleiche Potential. Weiss auch nicht, warum ich die Linie nicht  herunter gezeichnet habe. &#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Matthias&lt;br /&gt;
&lt;br /&gt;
[[Benutzer:1000fragen|1000fragen]] 16:49, 25. Mär. 2009 (CET)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Hey Axel,&lt;br /&gt;
&lt;br /&gt;
Vielen Dank für deine Antworten! Ich habe jetzt auch das Schema vom Wechselrichter öffnen können - Es lag am Leerzeichen im Dateinamen, das hat die Linux-Version von Eagle wohl nicht so gerne... naja, lernen durch Schmerzen. Ich hab in den letzten Tagen ein Lochrasterplatinenlayout erstellt, dass ich morgen anfangen werde, zusammenzulöten. Ich berichte dann, wie es läuft!&lt;br /&gt;
&lt;br /&gt;
Matthias&lt;br /&gt;
&lt;br /&gt;
[[Benutzer:1000fragen|1000fragen]] 19:16, 31. Mär. 2009 (CEST)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Zeichne bitte noch ein Massesymbol unter R16 und an X3/2 , sodass man sieht, dass hier eine Verbindung besteht.&lt;br /&gt;
&lt;br /&gt;
Ich hoffe Du hast den Leistungsteil mit den 325 V nicht auf eine Lochrasterplatine aufgebaut.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Axel&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hallo Axel,&lt;br /&gt;
&lt;br /&gt;
Habe gerade das Bild aktualisiert. Die Einspeisung habe ich fast fertig (bis auf die Zenerdiode und Anschlüsse), ich hoffe in den nächsten Tagen fertig zu werden und 325V Gleichspannung zu messen. Zu der Zenerdiode noch ne Frage: Was für eine ist das? BZX55 ist ja nur eine Serie von verschiedenen, oder?&lt;br /&gt;
&lt;br /&gt;
Den Leistungsteil wollte ich ursprünglich auch auf eine Lochrasterplatine machen, werde statt dessen aber doch ein PCB nehmen. An welche Probleme hast du bei einer Lochrasterplatine gedacht? &lt;br /&gt;
&lt;br /&gt;
Matthias&lt;br /&gt;
[[Benutzer:1000fragen|1000fragen]] 18:49, 28. Apr. 2009 (CEST)&lt;br /&gt;
&lt;br /&gt;
Die Z Diode soll die max Gate Spannung auf 15V begrenzen, ist nur eine Angst-Diode, wenn die Eingangsspannung OK ist, geht es auch ohne.&lt;br /&gt;
&lt;br /&gt;
Bei der Lochrasterplatine währen mir die Leiterbahnabstände für 325V  viel zu klein&lt;br /&gt;
&lt;br /&gt;
Axel&lt;br /&gt;
&lt;br /&gt;
Mit dem Abstand der Leiterbahnen hast du wahrscheinlich Recht - die Abstände sind bei mir wirklich nicht groß, deswegen mach ich das ganze lieber nochmal als PCB mittels Toner-Transfer-Methode (wird hier im Forum ja ganz gut beschrieben). Ich melde mich dann nochmal, wenn ich das realisiert habe.&lt;br /&gt;
&lt;br /&gt;
Matthias&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
== Einige Fragen II ==&lt;br /&gt;
&lt;br /&gt;
So, wollte mich nur nochmal melden dass ich noch am Ball bin. Hab heute den Drucker geschrottet, weil ich testweise ne Folie bedrucken wollte, und die sich um die Trommel gewickelt hab. Beim Versuch die rauszuziehen hab ich dann die Trommel zerkratzt *narf* . Aber ich werd mich weiter Stückcken für Stückchen vorarbeiten! Bis zum 24. Juli werde ich nicht viel weiter kommen, aber an dem Tag ist meine letzte Klausur - Dann sollte ich etwas schneller vorankommen. Ich schreib dann nochmal in zwei Monaten oder so, wie es aussieht. Irgendwann krieg ich das Teil zusammengebaut!&lt;br /&gt;
&lt;br /&gt;
Matthias&lt;br /&gt;
&lt;br /&gt;
--[[Benutzer:131.220.221.230|131.220.221.230]] 15:47, 29. Jun. 2009 (CEST)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Viel Erfolg bei den Klausuren (Glück brauchen nur die Faulen)&lt;br /&gt;
Axel&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Danke, habs zum Glück geschafft, noch neben den Klausuren was zu machen! Ich habe die drei Platinen per TTF-Verfahren geätzt und angefangen, den Einspeiseteil zu bestücken. Da sind noch ein paar Fragen aufgetaucht:&lt;br /&gt;
&lt;br /&gt;
Steuerungsteil:&lt;br /&gt;
&lt;br /&gt;
Was ist IC7 - ein 7805?&lt;br /&gt;
&lt;br /&gt;
Ist R17 ein 10k-linear-Poti?&lt;br /&gt;
&lt;br /&gt;
Welche Werte haben C5,6 und 14?&lt;br /&gt;
&lt;br /&gt;
Was ist PL2?&lt;br /&gt;
&lt;br /&gt;
Einspeiseteil:&lt;br /&gt;
&lt;br /&gt;
Ich schätze mal, D2 ist auch eine N4001, oder?&lt;br /&gt;
&lt;br /&gt;
Noch ne Frage zu den 470nF-Kondensatoren auf dem Leistungsteil: Die liegen ja zwischen 15V Steuerspannung und der Spannung der Hochstromanschlüsse. Was für ne Spannungsfestigkeit müssen die haben?&lt;br /&gt;
&lt;br /&gt;
Matthias&lt;br /&gt;
&lt;br /&gt;
IC7 ist ein 7805&lt;br /&gt;
&lt;br /&gt;
R17 ist ein 10k-linear-Poti&lt;br /&gt;
&lt;br /&gt;
C5=C6 = 47µF 25V oder was sonst so in der Bastelkiste herumliegt.&lt;br /&gt;
&lt;br /&gt;
C14 100nF&lt;br /&gt;
&lt;br /&gt;
D2 ist auch eine 1N4001, normale Freilaufdiode für das Relais&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Bootstrap Kondensatoren liegen wenn die Low Side geschaltet hat an 15V. Wenn Low Side sperrt werden sie entladen, also kleiner 15V. Daher reichen 25-35V Spannungsfertigkeit&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Axel&lt;br /&gt;
&lt;br /&gt;
== Drehzahlregelung ==&lt;br /&gt;
&lt;br /&gt;
Ich hab noch ein paar Fragen.&lt;br /&gt;
-Ich habe den Frequensumrichter nachgebaut, aber die Drehzahregelung geht nicht.&lt;br /&gt;
Es ist egal welche Spannung ich am Analogeingang anlege(0-5V) der Motor dreht immer gleich schnell.&lt;br /&gt;
-Wo kann man die Drehrichtung einstellen?&lt;br /&gt;
-Wofür sind die LEDs auf der Steuerplatine da?&lt;br /&gt;
&lt;br /&gt;
Edit:Drehzahlregelung geht jetzt. Es war nur der Mega 32 kaputt der Motor dreht aber trotzdem nur sehr langsam(1U/sec)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Eine Drehzahlregelung findet nicht statt, nur eine Drehzahlverstellung ( eine Regelung hat eine Istwert-Rückführung)&lt;br /&gt;
&lt;br /&gt;
Läuft der Mega 88 mit 20 Mhz? Alle Timer sind darauf abgestellt.&lt;br /&gt;
&lt;br /&gt;
Der Sollwert wird im Mega32 am Analogeingang 2 eingelesen:&lt;br /&gt;
&lt;br /&gt;
// ****** Einlesen Sollwert  *********************************&lt;br /&gt;
ADMUX=0x02;		// PortA2 = ADC2 = Analog Eingang&lt;br /&gt;
      ADCSRA |= _BV(6);  // single conversion mode ein&lt;br /&gt;
      while(ADCSRA &amp;amp; (1&amp;lt;&amp;lt;6));  // warten bis Konvertierung abgeschlosen&lt;br /&gt;
      sollwert_f_sample+=ADCW;  // Aufsummierung der Samplewerte&lt;br /&gt;
&lt;br /&gt;
Die Drehrichtung ist im Programm fest vorgegeben : das Bit liegt auf Bit 7 am Port D des Mega 32&lt;br /&gt;
Wenn beide Richtungen gefordert sind, dann über einen Eingang die Varable:&lt;br /&gt;
volatile unsigned char richtung=0; 	// Drehrichtung&lt;br /&gt;
verändern&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Weiterhin viel Erfolg &lt;br /&gt;
Axel&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Mega 88 läuft mit 16 Mhz wie im Schaltplan. Im Programm steht aber 20Mhz.&lt;br /&gt;
Das hat mich  etwas verwirrt. Ich werde Montag mal einen 20Mhz Quarz besorgen.&lt;br /&gt;
Könnte man nicht einen der freien Eingange des Mega 32 für die Drehrichtung verwenden?&lt;br /&gt;
&lt;br /&gt;
Julian&lt;br /&gt;
&lt;br /&gt;
Hallo Julian,&lt;br /&gt;
wenn im Schaltplan 16 Mhz steht ist das falsch, 20 Mhz sind richtig. Aber zwischen 16 und 20 Mhz sollte der Unterschied in der Ausgangsfrequenz nicht so groß sein.&lt;br /&gt;
&lt;br /&gt;
Hast Du ein LCD am Mega 32? dort kann man den Sollwert ablesen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es sollte ein freier Eingang des Mega 32 für die Drehrichtung verwendet werden.&lt;br /&gt;
&lt;br /&gt;
Axel&lt;br /&gt;
&lt;br /&gt;
Ich hatte keien Mega 32 mehr, desshalb habe ich einen Mega 16 genommen aber jetzt geht das Display nicht mehr. Ich werde morgen dann auch gleich einen neuen Mega32 besorgen.&lt;br /&gt;
&lt;br /&gt;
Julian&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hast Du schon folgende grundsätzliche Test durchgeführt:&lt;br /&gt;
&lt;br /&gt;
Zwischenkreisspannung ca. 30 V aus einem Labornetzteil anlegen.&lt;br /&gt;
&lt;br /&gt;
Ansteuerung der FET Treiber mit dem Scope prüfen&lt;br /&gt;
&lt;br /&gt;
dann drei Leistungswiderstände 10Ohm im Stern schalten und die Spannung an den Widerständen messen. Sollte so wie im Artikel &amp;quot;Spannung an ohmschen Widerstand&amp;quot; aussehen.&lt;br /&gt;
&lt;br /&gt;
Falls kein Scope vorhanden drei LED´s mit entsprechenden Vorwiderständen im Stern schalten und an die Ausgänge klemmen (evtl drei zusätzliche LED´s antiparallel). Bei niedriger Freguenz sollte man das Drehfeld am Blinken der LED´s erkennen können.( Evtl den Timervorteiler am Mega88 für den Test herunterstellen).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Danke schon mal für die Hilfe.&lt;br /&gt;
Es hat leider etwas länger gedauert. Pollin hat es in 2 Wochen leider nicht geschaft mir 2 Teile zu schicken. Der Mega88 läuft jetzt mit 20 MHz aber der Motor dreht trotzdem nicht viel schneller(1,5 U/min). Die Treiberansteuerung ist Ok und die LED´s blinken auch korrekt. Auf dem Display steht:&lt;br /&gt;
&lt;br /&gt;
S=61U=20R=0e=1  5&lt;br /&gt;
U=012I=043n=000&lt;br /&gt;
&lt;br /&gt;
Eingangsspannung:12V&lt;br /&gt;
Strom: 0,4A&lt;br /&gt;
Analogeingang: 4,9V&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Julian&lt;br /&gt;
&lt;br /&gt;
Hallo Julian,&lt;br /&gt;
die Anzeige auf dem Display bedeutet:&lt;br /&gt;
&lt;br /&gt;
S=61 (Sollwert 61 entspricht 100%)&lt;br /&gt;
&lt;br /&gt;
U=20 (Spannungssollwert 20 entspricht 100%)&lt;br /&gt;
&lt;br /&gt;
R=0 (Richtungssollwert)&lt;br /&gt;
&lt;br /&gt;
e=1 (1= Enablesignal steht an, Umrichter soll laufen)&lt;br /&gt;
&lt;br /&gt;
Zweite Zeile:&lt;br /&gt;
&lt;br /&gt;
U=12 (aktuelle Zwischenkreisspannung ist 12V)&lt;br /&gt;
&lt;br /&gt;
I=043 (es fließt ein Strom im Zwischenkreis, Stromumrechnung hängt vom Shuntwiderstand ab)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Sieht alls soweit korrekt aus. &lt;br /&gt;
&lt;br /&gt;
Was für ein Motor ist angeschlossen? Bei 12V Zwischenkreisspannung kannst Du den Phasenstrom über einen Shuntwiderstand messen, was kommt da raus?&lt;br /&gt;
&lt;br /&gt;
Piepst der Motor?&lt;br /&gt;
Gibt es etwas Drehmoment, wenn man die Motorwelle mit der Hand dreht?&lt;br /&gt;
&lt;br /&gt;
In der Interruptroutine von Timer 0 wird der Hochlaufgeber gebildet, der bestimmt, wie schnell der Motor beschleunigt.&lt;br /&gt;
Ändere sie wie folgt ab, dann wird lamgsamer beschleunigt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
SIGNAL(SIG_OVERFLOW0)            // signal handler for tcnt0 overflow interrupt&lt;br /&gt;
{				// alle 10,24ms    &lt;br /&gt;
 &lt;br /&gt;
hlg++;&lt;br /&gt;
if (hlg &amp;gt;=20) {&lt;br /&gt;
&lt;br /&gt;
		if (sollvh &amp;gt; sollnh) sollnh++;&lt;br /&gt;
		if (sollvh &amp;lt; sollnh) sollnh--;&lt;br /&gt;
		hlg=0;&lt;br /&gt;
		}&lt;br /&gt;
&lt;br /&gt;
TCNT0 = 215;  // Timer auf 10,24ms stellen&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Axel&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hallo&lt;br /&gt;
Es ist ein alter Motor aus einem CD laufwerk angschlossen. Der Motor piepst nicht und läuft sauber an. Nach der Programmänderung läuft der Motor langsamer an und das Display geht nicht mehr. Der Phasenstrom liegt bei 0,6A. Kann man im Programm irgendwo die max. Ausgangsfrequens einstellen? &lt;br /&gt;
&lt;br /&gt;
Gruß Julian&lt;br /&gt;
&lt;br /&gt;
Hallo Julian,&lt;br /&gt;
stell doch den Timer wieder zurück und mach den Wert &amp;quot;if (hlg &amp;gt;=20)&amp;quot; auf 200. Das ist der Vorteiler nach welchen der Sollwert auf oder ab integriert wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die max Frequenz ist ziemlich tief im Programm des Mega88 verwurstelt.&lt;br /&gt;
&lt;br /&gt;
Am Anfang des Programms gibt eine Tabelle:&lt;br /&gt;
&lt;br /&gt;
const unsigned char fbwfl[67]=&lt;br /&gt;
&lt;br /&gt;
dort sind Timerwerte abgelegt aus denen sich die jeweilige Frequenz ergibt. Ist zur Zeit auf 66 Hz festgelegt. Lässt sich bestimmt ändern, ist aber aufwändig.&lt;br /&gt;
Bei höheren Frequenzen wird natürlich der sinus des Motorstroms schlechter, da es nur einen Pulsfrequenz von 2,5Khz gibt. Lässt sich auch ändern, muss man nur tiefer ins Programm einsteigen.&lt;br /&gt;
&lt;br /&gt;
Mich erstaunt, dass der Motor keinerlei Geräusche macht. Mein Testmotor hat fürchterlich gepiepst.&lt;br /&gt;
&lt;br /&gt;
Axel&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ich hab das Programm noch einmal geändert, aber das hat gar keinen Einfluss auf den Motor. Zum Test hab ich auch noch einen Lenze 0,4kw Motor genommen. Der dreht aber auch nicht schneller. Beide Motoren laufen sauber an ohne piepsen oder so.&lt;br /&gt;
&lt;br /&gt;
Gruß Julian&lt;br /&gt;
&lt;br /&gt;
Hallo Julian,&lt;br /&gt;
&lt;br /&gt;
die niedrige Drehzahl und keine Geräusche läßt mich vermuten, dass der Mega88 nicht auf 20Mhz läuft. Mache mal ein kleines Testprogramm, welches die LED im Sekundentakt blinken lasst und dann rein in den Mega88.&lt;br /&gt;
&lt;br /&gt;
Der Lenze Motor ist sicherlich ein 230/400V Motor, betreibst Du den auch mit den 12V Zwischenkreisspanung? Das währe natürlich ziemlich wenig.&lt;br /&gt;
&lt;br /&gt;
Hast Du ein Scope zur verfügung?&lt;br /&gt;
&lt;br /&gt;
Axel&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hallo&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Danke für die Hilfe. Es geht jetzt alles. Das war wieder so ein blöder Fehler, weil ich eine fuse falsch gesetzt habe. Er hat den Takt immer durch 8 geteilt.&lt;br /&gt;
Muss ich einfach nur die Tabelle erweitern, damit der Motor noch schneller dreht? &lt;br /&gt;
&lt;br /&gt;
Gruß Julian&lt;br /&gt;
&lt;br /&gt;
Hallo Julian,&lt;br /&gt;
schön wenn es nun geht.&lt;br /&gt;
&lt;br /&gt;
Der Umlaufzähler für Omega ist &amp;quot;verantwotlich&amp;quot; für die Ausgangsfrequenz. Er wird im Timerinterrupt 0  &amp;quot;SIGNAL(SIG_OVERFLOW0)&amp;quot; hochgezählt. Die Ausgangsfrequenz ist der Kehrwert des Timerwert. Der 16 Bit Timer ist schon anderwertig gebraucht.&lt;br /&gt;
&lt;br /&gt;
Das heißt nach 360 Durchläufen von Timer 0 hat sich der Motor einmal gedreht. Nun ist der Timer 0 leider ein 8 Bit Timer mit einer begrenzten Auflösung. Wenn der Motor sich schneller drehen soll muss der Vorteiler geändert werden und die Werte in der Tabelle müssen angepasst werden. Am besten mit Excel rechnen und die Werte in die Tabelle &amp;quot;const unsigned char fbwfl[67]&amp;quot; kopieren. Zur Zeit wird z.B. der Timerwert 183 für eine Ausgangsfrequenz von 12 Hz geladen.&lt;br /&gt;
&lt;br /&gt;
Axel&lt;br /&gt;
&lt;br /&gt;
Hallo&lt;br /&gt;
&lt;br /&gt;
Wo änder ich denn der Vorteiler und wie weit darf ich ihn verändern?&lt;br /&gt;
&lt;br /&gt;
Gruß Julian&lt;br /&gt;
&lt;br /&gt;
es steht dort wo es immer steht:&lt;br /&gt;
void initial(void)&lt;br /&gt;
{&lt;br /&gt;
//.......    &lt;br /&gt;
TCCR0B = 3; // count with cpu clock/64   CS02 CS01 CS00 = 0 1 1 clkI/O/64 (From prescaler)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hallo&lt;br /&gt;
&lt;br /&gt;
Ich habe den Vorteile von dem 8 Bit timer jetzt auf 2(Systemtakt/16)gesetzt.&lt;br /&gt;
Nach welcher Formel wurden die Werte in der Tabelle errechnet?&lt;br /&gt;
Der Motor läuft so auch schneller ohne die anpassung der Tabelle, aber er verbaucht sehr viel Strom und läuf unsauber.&lt;br /&gt;
&lt;br /&gt;
Gruß Julian&lt;br /&gt;
&lt;br /&gt;
Hallo Julian,&lt;br /&gt;
eine 2 bedeutet : clkI/O/8 (From prescaler)Steht auf Seite 106 im Datenblatt.&lt;br /&gt;
 woher hast Du Systemtakt/16??&lt;br /&gt;
&lt;br /&gt;
Durch die Änderung läuft der Motor 8 mal schneller (Vorher Systemtakt / 64 nun Systemtakt / 8). Das heisst, bei vollem Sollwert sind es 8*66Hz = 528 Hz! Das ist natürlich viel zu schnell bei einer Pulsfrequenz von 2,5Khz. Natürlich auch viel zu schnell für den Motor. Die Reibung wird den Motor schon voll auslasten, er kann auch mechanisch auseianderfliegen.&lt;br /&gt;
&lt;br /&gt;
Daher sollte die Tabelle mit den Timerwerten angepasst werden, damit vernünftige max Frequenzen herauskommen. Wenn der Timer 360 mal durchlaufen wurde hat sich der Motor ein mal gedreht (OK der Anker).&lt;br /&gt;
&lt;br /&gt;
Du hast den Systemtakt 20Mhz geteilt durch 8, dann hast Du die Zeit für den zwischen den Aufrufen der Timerroutine wenn der Timerwert 254 ist (oder255?). Wenn der Timerwert 253 ist wird der Interrupt nur noch halb so oft aufgerufen usw.usw.usw. Kann man schön in Excel ausrechnen und im AVR Studio ausprobieren.&lt;br /&gt;
&lt;br /&gt;
Axel&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hallo&lt;br /&gt;
Ich hab den FU jetzt das erste Mal an 230 V getestet mit dem Originalprogramm und der Motor läuft grauenhaft. Er verbraucht im Leerlauf schon 3 A und läuft&lt;br /&gt;
ruppig.&lt;br /&gt;
&lt;br /&gt;
Lenze&lt;br /&gt;
50Hz&lt;br /&gt;
0,37kw&lt;br /&gt;
910 U/min&lt;br /&gt;
&lt;br /&gt;
Hier noch ein Video bei max Drehzahl.Wenn ich ihn langsamer drehen lasse wir es noch schlimmer.&lt;br /&gt;
http://www.youtube.com/watch?v=ywVAQz2g2JA&lt;br /&gt;
&lt;br /&gt;
Gruß Julian&lt;br /&gt;
&lt;br /&gt;
Hallo Julian,&lt;br /&gt;
der Motor hört sich wirklich grauselig an. Konntest Du schon die Ausgangsspannung an drei Widerständen bei 30V Zwischenkreisspannung mit dem Scope messen?&lt;br /&gt;
&lt;br /&gt;
Axel&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hallo&lt;br /&gt;
Ich hab mal über einen 470 Ohm Widerstand gemessen zwischen einer Phase und dem Sternpunkt bei 30V.&lt;br /&gt;
Hier das Bild:&lt;br /&gt;
&lt;br /&gt;
[IMG=http://img15.imageshack.us/img15/1184/dsc01796i.th.jpg][/IMG][/URL]&lt;br /&gt;
&lt;br /&gt;
Hab leider kein Speicherscope.&lt;br /&gt;
&lt;br /&gt;
Gruß Julian&lt;br /&gt;
&lt;br /&gt;
Hallo Julian,&lt;br /&gt;
Achtung Fehlerteufel in: void initial(void)&lt;br /&gt;
&lt;br /&gt;
DDRB = 0x2b; // PortB2 ist ein Eingang der Rest sind Ausgänge&lt;br /&gt;
Achtung: Hier stand fälschlicherweise DDRB = 0x1b !!!! geändert am 14.03.2010 &lt;br /&gt;
&lt;br /&gt;
Das könnte die Erklärung für deinen seltsamen Motorlauf sein.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Axel&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Danke nochmal für die Hilfe, aber es geht immer noch nicht .  Das kann aber auch an dem mega88 liegen der ist teilweise kaputt. Ich werden den nochmal tauschen&lt;br /&gt;
und ein Speicherscope besorgen .&lt;br /&gt;
&lt;br /&gt;
Gruß  Julian&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es geht jetzt. Hatte eine Halbbrücke an die LED angeklemmt, wie es Programm steht. Jetzt hab ich einen anderen Ausgang genommen nund das Programm umgeschrieben.Der Motor läuft sauber hoch und runterund zieht 1A im Dreieck, aber manchmal &amp;quot;verschluckt&amp;quot; er sich alles 10-20 sekunden. &lt;br /&gt;
&lt;br /&gt;
Gruß Julian&lt;br /&gt;
&lt;br /&gt;
Hallo Julian,&lt;br /&gt;
klasse dass es jetzt läuft, freut mich echt.&lt;br /&gt;
Diesen Rucker hatte ich auch mal gehabt, bei mir hat ein 4,7K Pull Up an den Steuereingängen geholfen. Die internen Pull Up reichen in der verseuchten Umgebung nicht.&lt;br /&gt;
&lt;br /&gt;
Axel&lt;br /&gt;
&lt;br /&gt;
== Spannung an ohmschen Widerstand ==&lt;br /&gt;
Es wurde eine Zwischenkreisspannung von ca. 24V angelegt.&lt;br /&gt;
Am Ausgang des FU werden drei Widerstände 470 Ohm im Stern geschaltet. Die Spannung wird über einen Widerstand gegen den Sternpunkt der Widerstände gemessen.&lt;br /&gt;
&lt;br /&gt;
Je nach dem aktuellen Sektor sehen die Spanungsverläufe so oder invers aus.&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Spannug_an_ohmschen_Widerstand_P1020274a_.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Spannug_an_ohmschen_Widerstand_P1020265a_.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Hallo&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hab das genau so gemessen wie oben beschrieben, aber ich bekomme das nicht getriggert. Deshalb sieht das etwas komisch aus.(siehe Bild oben)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
MfG Julian&lt;br /&gt;
&lt;br /&gt;
Hallo Julian,&lt;br /&gt;
habe die Triggerlevel klein eingestellt und mit der Speichertaste gespielt bis ich die Bilder hatte.&lt;br /&gt;
&lt;br /&gt;
Axel&lt;br /&gt;
&lt;br /&gt;
== Brückengleichrichter so wirklich OK? ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Wenn ich richtig sehe wird eine Diode des Brückengleichrichters kurzgeschlossen und ist damit unnötig (OK ist auch nicht weiter schlimm). Eine andere Diode schließt negative Halbwellen von P nach N durch und dürfte vermutlich recht war werden oder schnell aufgeben und kaputt gehen.&lt;br /&gt;
&lt;br /&gt;
Ich denke es wäre besser nur 2 Dioden, bzw. nur den halben Brückengleichrichter zu benutzen. &lt;br /&gt;
Das Netz wird hier übrigens nur unsymmetrisch belastet, da die negative Halbwelle überhaupt nicht benutzt wird.&lt;br /&gt;
&lt;br /&gt;
Oder übersehe ich etwas? (Siehe Grafik)&lt;br /&gt;
&lt;br /&gt;
[[Datei:Kurzschluss.JPG]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Der Minus vom Zwischenkreis liegt natürlich nicht auf Erde. Da gibt es zwar ein Massesymbol, dies ist nicht mit der Erdungssymblol zu verwechseln.&lt;br /&gt;
&lt;br /&gt;
Der Zwischenkreis Minus liegt auf 127V gegen Erde.&lt;br /&gt;
&lt;br /&gt;
Axel&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hmm, ok. Ich sehe gerade das das ganze in dem Eagle file OK ist. Der Schaltplan &amp;quot;Bremschopper_3.png&amp;quot; im Artikel selbst ist aber scheinbar verkehrt weil er diesen Kurzschluss hat.&lt;br /&gt;
&lt;br /&gt;
Viele Grüße, Kai (der gerade eine 2 Phasen Variante mit 90 Grad Phasenverschiebung baut für Kondensatormotoren).&lt;br /&gt;
&lt;br /&gt;
Ich hab die stellen hier mal markiert:&lt;br /&gt;
[[Datei:ausschnitt.jpg]]&lt;br /&gt;
&lt;br /&gt;
OK, der untere Masseanschluss ist natürlich Unfug.&lt;br /&gt;
Axel&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Treiber&amp;diff=60755</id>
		<title>Treiber</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Treiber&amp;diff=60755"/>
		<updated>2011-09-27T06:33:27Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: /* Beispiele zu Low-Side Treibern */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ein &#039;&#039;&#039;Transistor-Treiber&#039;&#039;&#039; ist eine Schaltung, welche den nötigen Strom zur Verfügung stellt, um einen großen [[Transistor]] in der erforderlichen Zeit ein- bzw. auszuschalten. Es handelt sich dabei meist um einen Verstärker mit zusätzlichem [[Pegelwandler]]. Dadurch ist es möglich, mit einem Logikausgang, welcher meist mit 5 oder 3,3V betrieben wird, große Lasten mit [[FET|MOSFETs]] bzw. [[IGBT|IGBTs]] zu schalten. Dieser Treiber kann analog (linear) oder digital arbeiten.&lt;br /&gt;
&lt;br /&gt;
In diesem Artikel wird hauptsächlich auf die Besonderheiten zur Ansteuerung von MOSFETs und IGBTs in der Leistungselektronik Bezug genommen, welche geschaltet betrieben werden. Diese Treiber sind digitale [[MOSFET-Übersicht#Mosfet-Treiber | MOSFET-Treiber]]&lt;br /&gt;
&lt;br /&gt;
==Anwendung ==&lt;br /&gt;
&lt;br /&gt;
[[FET | MOSFETs]] und [[IGBT]]s werden mit einer Spannung gesteuert. Bei einer Gate-Source bzw. Gate-Emitter Spannung von 0V ist das Bauteil gesperrt bzw. hochohmig. Steigt die Spannung über die sogenannte &amp;quot;Schwellenspannung&amp;quot; (engl. threshold voltage) – die für Leistungsbauteile zwischen ca. 3 und 4,5V liegt – &lt;br /&gt;
geht das Bauteil langsam vom gesperrten in den leitenden Zustand über. Bei einem weiteren Spannungsanstieg bis zu einem Level von ca. 12V verringert sich der Einschaltwiderstand beim MOSFET bzw. der Kollektor-Emitter Spannungsabfall beim IGBT auf den im Datenblatt angegebenen minimalen Wert. Eine weitere Erhöhung führt nur zu einer vergleichsweise geringen Reduktion des Widerstandes bzw. Spannungsabfalls und erhöht die Energiemenge, die beim Schalten durch den Treiber &lt;br /&gt;
umgeladen werden muß dramatisch (P~U² !). Praktisch beschränkt man sich daher meist auf Gatespannungen zwischen 12...18V. Aufgrund von unvermeidbaren, sehr kleinen parasitären Effekten tritt meist ein geringes Überschwingen der Gatespannung auf. Zusammen mit diesem Überschwingen darf die Gatespannung bei nicht &amp;quot;Logic-Level&amp;quot; FETs 20V nie überschreiten.&lt;br /&gt;
&lt;br /&gt;
Im Betrieb fällt an einem Leistungstransistor immer eine bestimmte Verlustleistung an. Diese Verluste teilen sich auf in &amp;quot;Schaltverluste&amp;quot; und &amp;quot;Leitend- bzw. ON-Verluste&amp;quot;. Die ON-Verluste sind hauptsächlich vom Leistungsschalter selbst abhängig, die Schaltverluste hingegen von der Schaltgeschwindigkeit. Je schneller ein FET/IGBT ein- bzw. ausgeschaltet wird, desto geringer sind die Schaltverluste.&lt;br /&gt;
&lt;br /&gt;
Leider gibt es hier neben physikalischen Grenzen insbesondere unerwünschte Nebenwirkungen, nämlich die EMV (&#039;&#039;&#039;E&#039;&#039;&#039;lektro &#039;&#039;&#039;M&#039;&#039;&#039;agnetische &#039;&#039;&#039;V&#039;&#039;&#039;erträglichkeit). Je schneller geschaltet wird, desto stärker sind die Störungen die dadurch erzeugt werden. Diese Störungen sind sehr schnell so stark, daß andere Schaltungen im Umkreis von einigen Metern beeinflußt werden d.h. die USB Maus leuchtet plötzlich auf, ohne daß sie bewegt wurde bzw. der eigene Mikrocontroller macht nicht mehr was er eigentlich sollte. EMV ist Heute eines der wichtigsten &amp;quot;Krisenthemen&amp;quot; während der Entwicklungsphase, daher nicht auf die leichte Schulter nehmen.&lt;br /&gt;
&lt;br /&gt;
=== Gatebeschaltung ===&lt;br /&gt;
&lt;br /&gt;
Zwischen Treiberstufe und Schalter sind in fast allen Fällen einige passive Bauteile vorhanden. Dies wird hier im Weiteren als &amp;quot;Gatebeschaltung&amp;quot; bezeichnet.&lt;br /&gt;
&amp;lt;br&amp;gt; Hier ein Beispiel mit &amp;quot;Vollausstattung&amp;quot; und die dazugehörige Erklärung:&lt;br /&gt;
&lt;br /&gt;
# Gatewiderstand &amp;quot;R_g1&amp;quot;, um die Schaltgeschwindigkeit den Erfordernissen anzupassen. Je schneller die Schaltflanke, desto geringer die Schaltverluste. ABER Je schneller die Schaltflanke, desto größer die erzeugten Störungen (EMV). Gleichzeitig hat ein schnelles &amp;quot;Abschalten&amp;quot; auch einen starken Überschwinger (snap-off einer Diode und/oder Selbstinduktion (inductive kick)) zur Folge. Aus diesem Grund wird häufig&lt;br /&gt;
# ein Widerstand &amp;quot;R&amp;quot;_g2 und eine Diode &amp;quot;D&amp;quot; in Serienschaltung dem o.g. Gatewiderstand &amp;quot;R_g1&amp;quot; parallelgeschaltet, und zwar so, daß ein langsames ausschalten (D gesperrt) aber ein schnelles einschalten (D leitend und damit R_g1 parallel zu R_g2) ermöglicht wird, d.h. R_g1 || (R_g2+D).&lt;br /&gt;
# Um das empfindliche Gate zu schützen, wird oft eine Z-Diode, besser eine schnellere Transil-Diode (Transient Suppressor Diode) so zwischen &amp;quot;Gate&amp;quot; und &amp;quot;Source&amp;quot; bzw. &amp;quot;Emitter&amp;quot; geschaltet (&amp;quot;Kathode&amp;quot; am &amp;quot;Gate&amp;quot;), daß das &amp;quot;Gate&amp;quot; vor Spannungen &amp;gt; 20V geschützt wird. Bei einem sauberen Aufbau kann diese Sicherheitsfunktion normalerweise entfallen. Bei Testaufbauten ist eine 16V Transil-Diode Aufgrund der dort häufig vorkommenden Induktivitäten (Drahtverhau ;-) SEHR zu empfehlen. Das gleiche gilt für die&lt;br /&gt;
# Klemmdiodenkombination (Z- bzw. Transil Diode, antiseriell mit einer normalen Diode) zwischen &amp;quot;Drain&amp;quot; bzw. &amp;quot;Kollektor&amp;quot; und Gate so (&amp;quot;Kathode&amp;quot; der Z-Diode an &amp;quot;Drain&amp;quot; bzw. &amp;quot;Kollektor&amp;quot;), daß die Diode das Gatepotential anhebt, wenn die &amp;quot;Drain-Source&amp;quot; bzw. &amp;quot;Kollektor-Emitter&amp;quot; Potential in die Nähe der maximalen Blockierspannung (Spannungsfestigkeit) des Schalters kommt bzw. den vom Entwickler definierten, maximalen Spannungslevel erreicht. Dieses &amp;quot;anheben&amp;quot; führt dann zu einem vergleichsweise hochohmigen Einschalten des Schalters und damit zum VERLUSTBEHAFTETEN Energieabbau. Bei einem 30V FET verwendet man üblicherweise z.&amp;amp;nbsp;B. eine 24V Transil-Diode, bei 150V FET z.&amp;amp;nbsp;B. eine 130V Transil-Diode und bei einem 600V IGBT z.&amp;amp;nbsp;B. eine 540V Transil-Diode. Die antiserielle Diode, die verhindert, daß die Gatespannung bei fehlender Leistungsversorgung über die Transildiode abfließt, muß die gleiche Spannungsfestigkeit wie der Schalter aufweisen.&lt;br /&gt;
&lt;br /&gt;
=== Treiberleistung ===&lt;br /&gt;
&lt;br /&gt;
IGBT und FET sind zwar spannungsgesteuerte Bauelemente, trotzdem muß bei jedem Einschalten und bei jedem Ausschalten die Gatekapazität umgeladen werden, wozu &#039;&#039;Strom&#039;&#039; erforderlich ist. Der Energiegehalt eines Kondensators wird mit&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;E= \frac{1}{2} \cdot C \cdot U^2&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
berechnet. Es ist jedoch der Energiebedarf bei jedem Aufladen und Entladen zu berücksichtigen. Zur Ermittlung der wirksamen Kapazität, welche in der Formel benötigt wird, hat es sich bewährt, die Datenblattangabe für &amp;quot;Cies&amp;quot; beim IGBT, bzw. den Datenblattwert für &amp;quot;Ciss&amp;quot; beim FET mit dem Faktor&amp;amp;nbsp;5 zu multiplizieren.&lt;br /&gt;
&lt;br /&gt;
Daher ergibt sich die Treiberleistung wie folgt:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;P_\text{treiber} = 5 \cdot Cx \cdot U_g^2 \cdot f_\text{schalt}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zum Beispiel bei U&amp;lt;sub&amp;gt;g&amp;lt;/sub&amp;gt;=18V, Cies=4nF und ƒ&amp;lt;sub&amp;gt;schalt&amp;lt;/sub&amp;gt;=5kHz  beträgt P&amp;lt;sub&amp;gt;treiber&amp;lt;/sub&amp;gt;=32mW.&lt;br /&gt;
&lt;br /&gt;
Bei größeren Strömen mit einer höheren Frequenz – z.&amp;amp;nbsp;B. Induktionsheizung – wird die Ansteuerleistung schon sehr interessant, z.&amp;amp;nbsp;B. Ug = 18V, Cies=20nF und ƒ&amp;lt;sub&amp;gt;schalt&amp;lt;/sub&amp;gt;=250kHz, hier beträgt P&amp;lt;sub&amp;gt;treiber&amp;lt;/sub&amp;gt;=8,1W. Zusätzlich muß der Eigenverbrauch des Treibers berücksichtigt werden, der durchaus zwischen 0,5 und 1&amp;amp;nbsp;W liegen kann.&lt;br /&gt;
&lt;br /&gt;
=== Definition zu Low- und High-Side Schalter=== &lt;br /&gt;
 &lt;br /&gt;
;Low-Side–Schalter: Der FET schaltet eine Last gegen GND – auch als &#039;&#039;LS-Schalter&#039;&#039; bezeichnet.&lt;br /&gt;
&lt;br /&gt;
;High-Side–Schalter: Der FET schaltet eine Last an die Versorgungsspannung – auch als &#039;&#039;HS-Schalter&#039;&#039; bezeichnet.&lt;br /&gt;
&lt;br /&gt;
===Beispiele zu Low-Side Treibern===&lt;br /&gt;
&lt;br /&gt;
Nachfolgend ein paar Beispiele, die sowohl für FETs, als auch für IGBTs verwendet werden können. Achtung! Auch wenn bei FETs eine Diode (Bodydiode) implementiert ist, muß bei induktiven Lasten oder langen Zuleitungen sowohl bei FETs als auch bei IGBTs eine schnelle Diode parallel zum Leistungsschalter eingesetzt werden. Diese Diode – die hier im Beispiel nicht gezeigt ist – muß räumlich direkt neben dem Leistungsschalter platziert werden. Bitte beachten, daß jede Treiberschaltung sowohl an den Leistungsschalter, als auch an den gesamten Lastkreis individuell angepaßt werden muß.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Beispiel_LS_Treiber_1_2.png|miniatur|ohne|600px|Beispiele zu diskreten LS-Treibern ]]&lt;br /&gt;
&lt;br /&gt;
Treiber-1 eignet sich eher dazu langsamere Schaltvorgänge mit Kleinsignal-FETs durchzuführen, aber auch höhere Leistungen sind prinzipiell so machbar, wenn man sich die höhere Verluste durch die langsame Ansteuerung erlauben kann.&lt;br /&gt;
Der Widerstand R26 sollte an das gewünschte Schaltverhalten angepaßt werden, weniger als ca. 100Ohm ist wegen der Stromtragfähigkeit des gewählen T4 nicht zu empfehlen. Das Schaltverhalten ist hier sehr unsymmetrisch (&amp;quot;langsam ein&amp;quot;, sehr schnell &amp;quot;aus&amp;quot;). Sollten größere Ströme geschaltet werden wird eine andere Ansteuermöglichkeit empfohlen.&lt;br /&gt;
&lt;br /&gt;
Treiber-2 ist durchaus in der Lage höhere Impulsleistungen an den Leistungstransistor zu liefern.&lt;br /&gt;
Letztendlich ist der maximale Strom von der Stromtragfähigkeit von T1&amp;amp;T2 abhängig. Die Gatewiderstände sind für schnelles (stromloses!) Einschalten und etwas langsameres Abschalten ausgelegt. Das oben gezeigte Beispiel kann so angepaßt werden, daß beim Abschalten nur ein kleiner Spannungsüberschwinger (10..20% der Betriebsspannung) zu sehen ist. Die Anbindung von C1 ist relativ kritisch, auf kürzest mögliche Anbindung ist zu achten&lt;br /&gt;
&lt;br /&gt;
Zu beachten ist, daß Treiber 2 am Eingang vor R4 ein Signal erwartet, welches für &amp;quot;An&amp;quot; bereits auf der benötigten Gate-Spannung des FETs (typischerweise 10V) liegt. Steht dagegen nur ein Logik-Signal mit 5V oder 3.3V zur Verfügung, so muß diese zuerst über eine weitere Stufe erhöht werden. Folgende Schaltung erledigt dies. Zu beachten ist aber, daß dadurch das Eingangssignal invertiert wird.&lt;br /&gt;
[[Bild:Beispiel_LS_Treiber2_LogicLevel.png|miniatur|ohne|600px|Diskreter LS-Treiber 2 für LogicLevel-Signal]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:Beispiel_LS_Treiber_3.png|miniatur|ohne|600px|Beispiel eines LS-Treibers mit Logikbausteinen]]&lt;br /&gt;
&lt;br /&gt;
Dieses Schaltungsbeispiel ist gut geeignet, um Leistungsfets mit einer mittleren Leistung anzusteuern. Es ist zu empfehlen einen Leistungsschalter mit geringer Gateladung (Qg) auszusuchen. Achtung auf den Maximalstrom den der Inverter liefern kann. Der 4069 sollte mit ca. 12V, max. 15V betrieben werden. Wenn ein Logic-Level Schalter ausgesucht wird, ist ein auch 74AC14 (kein AHC) zu empfehlen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Beispiel_LS_Treiber_4.png|miniatur|ohne|600px|Beispiele eines LS-Treibers mit einem fertigen IC]]&lt;br /&gt;
&lt;br /&gt;
Oben im Bild ist ein kommerzieller Treiber-IC zu sehen – hier im Beispiel 2127 von IR. Hierzu gibt es jedoch sehr viele Alternativen, sowohl von IR, als auch von anderen Firmen. Die Beschaltung ist jedoch immer relativ ähnlich, siehe dazu [[MOSFET-Übersicht#Mosfet-Treiber | MOSFET-Treiber]].&lt;br /&gt;
&lt;br /&gt;
Achtung! Der GND-Zweig des Leistungskreises hat bei unsachgemäßem Aufbau einen recht großen Einfluß auf die beim Schalter ankommende Gatespannung. Je nach Aufbau führt das zu einer zu geringen Gatespannung im Schaltmoment – U_gs direkt am Schalter bricht beim Einschalten ein – oder zu einer Überspannung am Gate – U_gs schwingt über die Gatetreiberversorgung hinaus. Beides führt vermutlich früher oder später zu einer Zerstörung des Leistungsschalters. Letzters kann oft durch eine 15V-Z-Diode direkt am Schalter zwischen Gate und Source bzw. Emitter verhindert werden, eine Optimierung des Layouts bzw. der Verdrahtung ist jedoch zielführender. Beschreibungen hierzu im weiteren Verlauf des Artikels.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die oben gezeigte Masseführung ist nicht zum Spaß &#039;&#039;genau so&#039;&#039; gezeichnet. Durch eine unsaubere Masseführung – und dazu zählt z.&amp;amp;nbsp;B. auch schon der Anschluß der Treiber-Masse direkt am GND-Symbol statt direkt am Schalter – kann der Treiber oder der Schalter durch Überspannung zerstört werden. Auch ein zu starkes &amp;quot;Unterschwingen&amp;quot; des GND-Potentials gegenüber des gerade auf Masse gelegten Gatesignals führt unweigerlich zur Zerstörung des Treibers. Viele Bausteine sind bis zu einer Spannungsdifferenz von ca. –5V betriebsfähig.&amp;lt;br&amp;gt;&lt;br /&gt;
10cm Kabel besitzen eine parasitäre Induktivität von ca. 100nH. Werden 50A in 1µs geschaltet – was schon relativ langsam ist – entsteht bei jedem Schalten eine Selbstinduktionsspannung von 100nH·50A/1µs = 5V.&lt;br /&gt;
&lt;br /&gt;
===Beispiele zu High-Side Treibern===&lt;br /&gt;
&lt;br /&gt;
Nachfolgend ein paar Beispiele zu HS-Treibern, die sowohl für FETs, als auch für IGBTs verwendet werden können. Bitte beachten, daß jede Treiberschaltung sowohl an den Leistungsschalter, alsauch an den gesamten Lastkreis individuell angepaßt werden muß.&lt;br /&gt;
High-Side Treiber sind etwas komplexer aufgebaut. Der Versorgungsspannungskreis muss isoliert zur restlichen Beschaltung aufgebaut werden. Auf die Isolationsabstände ist besonders zu achten.&lt;br /&gt;
&lt;br /&gt;
Achtung: Auch wenn bei FETs eine – meist unzureichende – Diode implementiert ist, sollte bei induktiven Lasten (oder langen Zuleitungen) sowohl bei FETs, als auch bei IGBTs eine schnelle Diode parallel zum Leistungsschalter eingesetzt werden. Diese Diode – die hier im Beispiel nicht gezeigt ist – muß räumlich direkt neben dem Leistungsschalter implementiert werden. &lt;br /&gt;
&lt;br /&gt;
[[Bild:Beispiel_HS_Treiber_1.png|miniatur|ohne|600px|Beispiel eines diskreten HS-Treibers ]]&lt;br /&gt;
&lt;br /&gt;
Hier im ersten Beispiel eine diskrete Ansteuerung für einen HS-Schalter. Achtung, das Signal durch die Push-Pull-Stufe invertiert. Statt Q5/Q6 wird empfohlen einen integrierten high speed Treiber wie z.&amp;amp;nbsp;B. die sehr preisgünstigen MC34151 oder MC34152 zu verwenden.&lt;br /&gt;
Die hier abgebildete Beschaltung – die ohne weitere Veränderung bei geringerer Schaltleistung auch ohne die Push-Pull Stufe betrieben werden kann – ist für eine Betriebsspannung von ca. 400V ausgelegt. Der Widerstand R12 (hier 4k7) muß an eine geänderte Spannung angepaßt werden. Für 40V beträgt er in dieser Beschaltung 3k3. Diese Schaltung kann auch sehr einfach simuliert werden.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Beispiel_HS_Treiber_2.png|miniatur|ohne|600px|Beispiel eines HS-Treibers mit einem fertigen IC ]]&lt;br /&gt;
&lt;br /&gt;
Das zweite Beispiel verwendet einen integrierten HS-Schalter von International Rectifier (IR) und eine separate, isolierte Versorgungsspannung. Zum IC gibt es sehr viele Alternativen, sowohl von IR, als auch von anderen Firmen. Die Beschaltung ist jedoch immer relativ ähnlich, siehe dazu [[MOSFET-Übersicht#Mosfet-Treiber|MOSFET-Treiber]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:Beispiel_HS_Treiber_3.png|miniatur|ohne|600px|Beispiel eines HS-Treibers mit Bootstrap Versorgung ]]&lt;br /&gt;
&lt;br /&gt;
Das dritte Beipiel unterscheidet sich zum vorhergehenden nur dadurch, daß die Versorgungsspannung für den Treiber über eine Bootstrap-Schaltung gewonnen wird. Näheres im weiteren Verlauf dieses Artikels.&lt;br /&gt;
&lt;br /&gt;
Die oben gezeigte Leitungsführung für Treiberbezugspotential und GND-Potential ist auch hier nicht zum Spaß &#039;&#039;genau so&#039;&#039; gezeichnet. Durch eine unsaubere Leitungsführung – und dazu zählt z.&amp;amp;nbsp;B. auch schon der Anschluß des Treiber-Bezugspotentials nicht direkt an Emitter bzw. Source – kann der Treiber oder der Schalter durch Überspannung zerstört werden. Auch ein zu starkes &amp;quot;Unterschwingen&amp;quot; des GND-Potentials gegenüber des gerade auf Bezugspotential gelegten Gatesignals führt unweigerlich zur Zerstörung des Treibers. Viele Bausteine sind bis zu einer Spannungsdifferenz von ca. –5V betriebsfähig.&lt;br /&gt;
10cm Kabel besitzen eine parasitäre Induktivität von ca. 100nH. Werden 50A in 1µs geschaltet – was schon relativ langsam ist – entsteht bei jedem Schalten eine Selbstinduktionsspannung von 100nH*50A/1µs = 5V.&lt;br /&gt;
&lt;br /&gt;
=== Stromversorgung eines High-Side Treibers ===&lt;br /&gt;
&lt;br /&gt;
Jede Treiberstufe benötigt eine entsprechende Spannungsversorgung.&lt;br /&gt;
Bei einem LS-Schalter gestaltet sich dies relativ einfach, da die Versorgungsspannung im Bereich von 12..15V über dem GND Potential&lt;br /&gt;
liegt. &lt;br /&gt;
&lt;br /&gt;
Bei einem High Side N-Kanal Schalter ist deutlich mehr Aufwand nötig, da hier die Treiberspannung 12..15V über dem Sourcepotential des HS-Schalters liegen muß. Das Source-Potential liegt beim HS-Schalter je nach Anwendungsfall auf 12V bis 400V, manchmal sogar noch höher.&lt;br /&gt;
&lt;br /&gt;
==== Versorgung über isolierte DCDC Wandler ====&lt;br /&gt;
&lt;br /&gt;
Die Versorgung hierfür kann relativ einfach mit integrierten DCDC-Wandlermodulen aufgebaut werden, wie sie für wenig Geld bei Conrad oder Reichelt verfügbar sind (Leistung und Isolationsspannung beachten!).&lt;br /&gt;
&lt;br /&gt;
==== Versorgung durch eine Bootstrap Schaltung====&lt;br /&gt;
&lt;br /&gt;
Wenn es sich bei der Applikation um eine Halbbrücke handelt und der HS-Schalter nicht dauerhaft eingeschaltet sein muß (Tastverhältnis &amp;lt;100%), sondern regelmäßig getaktet wird ([[PWM]]), kann die Versorgung des HS-Schalters auch aus der massebezogenen Versorgung des LS-Schalters generiert werden. Diese Schaltung nennt sich &#039;&#039;Bootstrap&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Immer wenn der LS einer Halbbrücke eingeschaltet ist, liegt das Source Potential des High Side Schalters auf GND. In diesem Zeitraum kann der Kondensator am Treiber des HS-Schalters über eine Diode aufgeladen werden. Energiequelle ist hierbei die Spannungsversorgung des LS-Schalters. Siehe dazu eines der Beispiele oben.&lt;br /&gt;
&lt;br /&gt;
=====Bootstrapkondensator=====&lt;br /&gt;
&lt;br /&gt;
Der Bootstrapkondensator soll eine niederinduktive und niederohmige Pufferung des Energiebedarfes für einen Schaltvorgang bereitstellen, daher ist ein Keramikkondensator oder auch ein Folienkondensator erforderlich. Den Energiebedarf eines Schaltvorganges ergibt sich recht einfach:&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt; C = \frac{Q_\text{gate}}{\Delta U}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beispiel: Als erlaubten Spannungseinbruch während der Energieentnahme wird hier 0,5V festgelegt. Die gesamte Gateladung Q&amp;lt;sub&amp;gt;gate&amp;lt;/sub&amp;gt; (Total gate charge) ist hier z.&amp;amp;nbsp;B. 58nC bei U&amp;lt;sub&amp;gt;g&amp;lt;/sub&amp;gt;=10V. Daraus errechnet sich eine Minimalkapazität von 58nC / 0,5V = 116nF. Die Erfahrung zeigt, daß ein großzügiges erhöhen um den Faktor 3..8 sinnvoll ist, da in der Rechnung weder Leckströme des FETs und des Kondensators noch der Energieverbrauch der Treiberschaltung selbst berücksichtigt wird. Des Weiteren ist die Gateladung nur für 10V angegeben. Höhere Gatespannungen erfordern eine höhere Energiemenge. Achtung: je größer der Kondensator gewählt wird, desto mehr Zeit wird zum Laden des Kondensators über die strombegrenzende Bootstrapdiode benötigt.&lt;br /&gt;
&lt;br /&gt;
Auch wenn der Kerko für die Pufferung der Schaltenergie ausreichend ist, ist es meist sinnvoll einen Elko/Tako parallel zu schalten. Die dort gespeicherte Energie hilft z.&amp;amp;nbsp;B. wenn eine längere &amp;quot;on&amp;quot; Zeit erforderlich ist. Genauso verringert der zusätzliche Energiespeicher den zum Ladungsausgleich erforderlichen Strompuls des Kerkos. Dadurch verbessert sich das EMV-Verhalten des Treibers meßbar.&lt;br /&gt;
&lt;br /&gt;
=====Auslegung des Bootstrapdiodenzweiges =====&lt;br /&gt;
&lt;br /&gt;
# Die Spannungsfestigkeit der Diode muß größer sein, als die auftretende Maximalspannung des Lastkreises. &lt;br /&gt;
# Im ersten Ansatz muß die Recovery-Zeit der Diode (t&amp;lt;sub&amp;gt;rr&amp;lt;/sub&amp;gt;) mindestens um den Faktor 10 kürzer sein, als die minimale &amp;quot;on&amp;quot; Zeit des LS-FETs. Ist z.&amp;amp;nbsp;B. der LS-FET immer für mindestens 10ms ein, ist eine 1N4007 (t&amp;lt;sub&amp;gt;rr&amp;lt;/sub&amp;gt; ca. 1µs) ausreichend. Bei höheren Schaltfrequenzen genügt oft eine UF4007 (t&amp;lt;sub&amp;gt;rr&amp;lt;/sub&amp;gt; ca. 75ns). In einer Halbbrücke bedeutet eine längere t&amp;lt;sub&amp;gt;rr&amp;lt;/sub&amp;gt;-Zeit jedoch, daß der Bootstrapkondensator des HS-Treibers beim Einschalten solange entladen wird, bis die Diode wieder sperrt. In diesem Fall muß die schnellere Diode unabhängig von der &amp;quot;on&amp;quot; Zeit ausgewählt werden&lt;br /&gt;
#Der zulässige Strom durch die Diode ist das letzte Auswahlkriterium. Da der Strom kaum kontrollierbar ist muß er mit einem Widerstand begrenzt werden. Bei einer 1N4007 beträgt der wiederholbare Maximalstrom 1A. Die Diode hat als sogenannten &#039;&#039;Single pulse&#039;&#039; aber eine deutlich größere Strombelastung (Datenblattangabe UF4007 = 30A). Da der Kondensator nur beim ersten Einschalten komplett vollgeladen, im Betrieb aber wie hier im Beispiel berechnet nur um &amp;lt;0,5V  aufgeladen wird, kann der Widerstand kleiner ausfallen. Daher ist in diesem Beispiel bei 15V Versorgungsspannung und Ausnutzung eines 50% = 15A Peaks für das erste Aufladen ein Minimalwiderstand von (15V – 1,5V) / 15A = 0,9Ω erforderlich. Der Widerstand wird auf 1Ω festgelegt. Die 1,5V stammen vom Spannungsabfall an der Diode bei 1A, bei höheren Strömen steigt der Spannungsabfall an.&lt;br /&gt;
&lt;br /&gt;
Aus dem Wert des Bootstrap-Kondensators, des -widerstandes  und des Tastverhältnisses (hier im Beispiel auf 2% festgelegt) ergibt sich eine minimale &amp;quot;on&amp;quot; Zeit für den LS-Schalter von&lt;br /&gt;
: t = R&amp;lt;sub&amp;gt;bt&amp;lt;/sub&amp;gt; · C&amp;lt;sub&amp;gt;bt&amp;lt;/sub&amp;gt; / D&lt;br /&gt;
d.h. 1Ω · 470nF / 0,02 = 23,5µs. Schneller als gut 40kHz sollte in diesem Beispiel also nicht geschaltet werden, da sonst der Bootstrapkondensator nur unzureichend nachgeladen werden kann.&lt;br /&gt;
&lt;br /&gt;
===Besonderheiten beim Treiberaufbau===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Gatekreis_Bild1.png|miniatur|left|300px|Gatekreis, wie im Schaltplan gezeichnet]] &lt;br /&gt;
Fast jeder, der schon einmal eine geschaltete Leistungsendstufe in Betrieb genommen hat, mußte feststellen, daß der Leistungsschalter nicht immer genau das macht, was man vorher geplant hatte. Die Hauptursache ist meist – neben Problemen mit der Leistungsversorgung selbst, siehe weiter unten – der Gatekreis.&lt;br /&gt;
&lt;br /&gt;
Die abgebildete Schaltung zeigt einen Aufbau wie er – unabhängig wie die Treiberstufe selbst umgesetzt wird – standardmäßig im Schaltplan implementiert ist. &lt;br /&gt;
&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
[[Bild:Gatekreis_Bild2.png|miniatur|rechts|350px|Gatekreis, wie er real auf der PCB vorhanden ist]]&lt;br /&gt;
&lt;br /&gt;
Rechts ist der Gatekreis so gezeichnet, wie er sich unter realen Bedingungen wirklich darstellt.&lt;br /&gt;
&lt;br /&gt;
Es ist hier nicht die Frage, ob diese parasitären Einflüsse wirklich vorhanden sind oder nicht, sondern nur wie groß die Werte sind. Hier sind unterschiedliche Einflüsse dargestellt, die sich teilweise gegenseitig beeinflussen.&lt;br /&gt;
&lt;br /&gt;
# R &amp;amp; L zwischen Source und GND:&amp;lt;br/&amp;gt;Das &amp;quot;Treiber GND&amp;quot; Signal ist wie deutlich zu sehen DIREKT am Source Anschluß des FETs angeschlossen, und nicht am GND-Fußpunkt des Leistungspfades von &amp;quot;Vcc&amp;quot; zu &amp;quot;GND&amp;quot;.Jeder Zentimeter der Leitung zwischen Source und GND beeinflußt den Gatekreis. Sobald der FET durchschaltet entsteht an den o.g. parasitären Bauteilen (Induktivität und Widerstand) ein Spannungsabfall, der dem Gatesignal entgegenwirkt, und damit z.&amp;amp;nbsp;B. beim Einschalten die am FET anliegende Gatespannung reduziert.&lt;br /&gt;
# R &amp;amp; L zwischen den Treiberausgängen &amp;quot;Gate Signal&amp;quot; und &amp;quot;Treiber GND&amp;quot;:&amp;lt;br/&amp;gt;Da der Widerstand im unteren mΩ-Bereich liegt kann dieser Einfluß hier ignoriert werden. Die Induktivität im Gatekreis bremst jedoch den Signalanstieg am Gate, sodaß auch das Schaltverhalten beeinflußt wird. Hier besteht auch die Gefahr, daß die Induktivität mit der Gatekapazität einen Schwingkreis bildet.&lt;br /&gt;
# Überkopplung über Ciss:&amp;lt;br/&amp;gt;Wenn das Drainpotential z.&amp;amp;nbsp;B. beim abschalten plötzlich von &amp;quot;GND&amp;quot; auf &amp;quot;Vcc&amp;quot; springt, findet über Ciss eine überkopplung auf das Gatesignal statt. Diese Potentialanhebung kann im schlimmsten Fall zum wiedereinschalten des FETs oder zu Oszillationen führen. &lt;br /&gt;
&lt;br /&gt;
;Fazit: Die Schleife zwischen den Treiberausgängen &amp;quot;Gate Signal&amp;quot; und &amp;quot;Treiber GND&amp;quot; muß &#039;&#039;unbedingt&#039;&#039; so klein wie möglich gehalten werden. Sitzt der Treiber nicht direkt am Leistungs-FET, ist es empfehlenswert die zwei Kabel so kurz wie möglich halten und zu verdrillen. Auf eine direkte Anbindung an Source bzw. Emitter ist zu achten!&lt;br /&gt;
&lt;br /&gt;
;FAQ:&lt;br /&gt;
&lt;br /&gt;
FET wird zu heiß:&lt;br /&gt;
*Verlustleistung zu hoch, Ursache könnte sein daß &lt;br /&gt;
**die Gatespannung zu niedrig ist, &lt;br /&gt;
**die Schaltgeschwindigkeit und damit die Treiberleistung zu gering ist oder  &lt;br /&gt;
**Schwingungen auf der Gateleitung vorhanden sind.&lt;br /&gt;
*Die Kühlung ist unzureichend&lt;br /&gt;
**da keine oder falsche Isolierfolie oder,&lt;br /&gt;
**ein zu kleiner Kühlkörper verwendet wird.&lt;br /&gt;
&lt;br /&gt;
== Leistungselektronik ==&lt;br /&gt;
&lt;br /&gt;
=== Parallelschalten von Leistungstransistoren===&lt;br /&gt;
&lt;br /&gt;
FETs und IGBTs lassen sich relativ einfach parallelschalten, wenn ein paar wenige Grundsätze beachtet werden:&lt;br /&gt;
# Jeder Transistor bekommt einen eigenen Gate-Vorwiderstand bzw. eine eigene R||RD Beschaltung (Gatebeschaltung).&lt;br /&gt;
# Die Gatebeschaltung wird möglichst nahe am Gate- und Source-Anschluß angebracht und bezüglich Leitungslänge (Induktivität) symmetriert. Die Zuleitung zu den Gatebeschaltungen ist unkritischer.&lt;br /&gt;
# Die Leistungsanbindung an Drain und Source – hier zählt &amp;quot;mΩ&amp;quot; und &amp;quot;nH&amp;quot; - wird symmetrisch aufgebaut.&lt;br /&gt;
# Die Schleife &amp;quot;Kondensator — Last — FET — Kondensator&amp;quot; wird minimiert.&lt;br /&gt;
# Jedes Bauteil wird nur zu &amp;lt;80% des maximal Möglichen ausgelastet. Trotz der hier genannten Maßnahmen können Asymmetrieen auftreten.&lt;br /&gt;
&lt;br /&gt;
Sollten auf den Gateleitungen Schwingungen zu beobachten sein, kann es helfen, in &#039;&#039;jede&#039;&#039; Verbindung von Gatetreiber-Source zum Sourceanschluß des Schalters je einen Widerstand zu integrieren. Der Wert sollte bei etwa 10..30% des Gatewiderstandes liegen.&lt;br /&gt;
&lt;br /&gt;
=== Stützkondensator ===&lt;br /&gt;
&lt;br /&gt;
==== Einführung ====&lt;br /&gt;
&lt;br /&gt;
[[Bild:Leistungsteil_Bild1.png|miniatur|left|350px|Einfache Endstufe wie im Schaltplan gezeichnet]]&lt;br /&gt;
Im nebenstehenden Bild ist der &amp;quot;Standard-Schaltplan&amp;quot; einer Endstufe mit ohmscher Last zu sehen.&lt;br /&gt;
&lt;br /&gt;
Nehmen wir an, der Entwickler hat eine neue Autobatterie mit 13,5V als Stromquelle, und einen Heizwiderstand (L des Widerstandes hier vernachlässigt) mit 0,1 Ω. Der FET und die je 1m langen Zuleitungen haben zusammen 4mΩ. Dies ergibt einen Maximalstrom von ca. 130A.&lt;br /&gt;
&lt;br /&gt;
Die Leistung des Heizwiderstandes soll mit einer PWM-Frequenz von 10kHz geregelt werden. In den nachfolgenden Beispielen wird ein Tastverhältnis von 50% fest vorgegeben&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
[[Bild:Zwischenkreiskondensator_Ideal.png|miniatur|left|350px|Idealer Spannung- und Stromverlauf an einer ohmschen Last]]&lt;br /&gt;
Und hier der &#039;&#039;&#039;ideale&#039;&#039;&#039; Spannungs- und Stromverlauf zwischen FET und Lastwiderstand.&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
[[Bild:Zwischenkreiskondensator_Real1.png|miniatur|left|350px|Annähernd realer Spannung- und Stromverlauf an der ohmschen Last mit Induktivitäten in der Zuleitung]]&lt;br /&gt;
Jetzt blicken wir der Realität ins Auge, und fügen bei unveränderter Gateansteuerung für die je 1m langen Versorgungsleitungen von- und zu der Batterie eine Induktivität von 1µH in das Simulationsmodell ein. Ohne genaue Kentniss des Lastkreises bzw. der Verdrahtung kann eine parasitäre Induktivität von 10nH/cm angenommen werden.&lt;br /&gt;
&lt;br /&gt;
Deutlich ist zu erkennen, daß der Strom gerade einmal 120A anstatt 130A erreicht. Die Stromformen ist nicht vergleichbar. &lt;br /&gt;
Des Weiteren erreicht die Spannung am Drain des 30V FETs knapp 900V, was schnell zu einem zerstörten Bauelement führt.&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
Ist kein Stützkondensator vorhanden, wird der gesammte AC-Stromrippel direkt aus der Batterie gezogen, was&lt;br /&gt;
# einen hohen Überspannungsimpuls erzeugt.&lt;br /&gt;
# die Zuleitungen als Sendeantenne mißbraucht (EMV).&lt;br /&gt;
# nicht den gewünschten Strom und Stromverlauf im Widerstand erzeugt.&lt;br /&gt;
# die Batterie selbst mit Mikrozyklen belastet.&lt;br /&gt;
# mit höchster Warscheinlichkeit einen häßlichen Ausschwinvorgang erzeugt (EMV).&lt;br /&gt;
&lt;br /&gt;
[[Bild:Zwischenkreiskondensator_Real2.png|miniatur|left|350px|Annähernd kompensierter Spannung- und Stromverlauf an der ohmschen Last mit Induktivitäten in der Zuleitung ]]&lt;br /&gt;
Hier ein Beispiel mit einem Stützkondensator. Die beim Kondensator vorhandenen, parasitären Einflüsse sind in dieser Simulation nicht berücksichtigt um die Komplexität zu minimieren.&lt;br /&gt;
&lt;br /&gt;
Designkriterien für den Kondensator folgen.&lt;br /&gt;
&lt;br /&gt;
Der Einfluß des Kondensators ist deutlich sichtbar. Der rechteckförmige Stromverlauf ist schon fast wieder erkennbar... genauso wie eine Schwingneigung im entstandenen LC-Kreis ;-(&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
==== Design des Stützkondensators ====&lt;br /&gt;
&lt;br /&gt;
Den im Vergleich zwischen den beiden obigen Simulationen fehlende Strom liefert der Kondensator. Die parasitären Elemente dieses Bauteiles haben je nach Typ mehr oder weniger Einfluß in dieser Anwendung.&lt;br /&gt;
&lt;br /&gt;
=====Ersatzschaltbild eines Kondensators=====&lt;br /&gt;
&lt;br /&gt;
[[Bild:Kondensator_Ersatzschaltbild_einfach.png|miniatur|right|350px|Vereinfachtes Ersatzschaltbild eines Kondensators]]&lt;br /&gt;
Unabhängig vom Kondensatortyp besitzt jeder Kondensator nicht nur die aufgedruckte Kapazität, sondern auch einen internen Widerstand (ESR), und eine interne Induktivität (ESL).&lt;br /&gt;
&lt;br /&gt;
Bei gewickelten Kondenstoren (fast alle Elkos und viele Folienkondensatoren) ist die parasitäre Induktivität aufbaubedingt größer, als bei geschichteten Folienkondensatoren. Für die meisten Anwendungen genügen jedoch Elektrolytkondensatoren, die bezahlbar und mit fast beliebigen Werten verfügbar sind.&lt;br /&gt;
&lt;br /&gt;
Häufig ist es einfacher und preiswerter, mehrere Elkos parallel zu schalten, als auf Folienkondensatoren umzusteigen.  Achtung: auf symmetrische Anbindung der parallelgeschalteten Bauteile zum Leistungsschalter achten! Es gibt jedoch einige Anwendungen – meist mit höherer Frequenz oder sehr kurzer Impulszeit (Induktionsheizung [Resonanz-C], elektromagnetische Beschleuniger, Coin-Schrinker, ... ) die die Verwendung von impulsfesten Folienkondensatoren (z.&amp;amp;nbsp;B. MKP10, FKP1,... ) erforderlich machen.&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
=====Kondensatorauswahl=====&lt;br /&gt;
&lt;br /&gt;
Die Bestimmung der benötigten Kapazität und Anzahl der Kondensatoren hängt ab von...&lt;br /&gt;
&lt;br /&gt;
# Frequenz (Schaltfrequenz × 2)&lt;br /&gt;
# Flankensteilheit (t&amp;lt;sub&amp;gt;rise&amp;lt;/sub&amp;gt;, t&amp;lt;sub&amp;gt;fall&amp;lt;/sub&amp;gt;)&lt;br /&gt;
# Tastverhältnis = Effektive Strombelastung (nicht Mittelwert!)&lt;br /&gt;
# Kühlmöglichkeiten (Verluste im Kondensator, Temperaturerhöhung, Kühlanbindung)&lt;br /&gt;
# ESR&lt;br /&gt;
# Betriebsspannung&lt;br /&gt;
&lt;br /&gt;
[[Bild:RMS-Berechnung.png|miniatur|right|350px|Berechnung der RMS-Ströme für die am häufigsten vorkommenden Signalformen]]&lt;br /&gt;
Aufgrund der vielfältigen Möglichkeiten wird ein stark vereinfachter Ansatz verfolgt, der für den nicht professionellen Anwendungsfall als ausreichend erscheint. (Verbesserungsvorschläge sind jederzeit erwünscht! bitte über PN)&lt;br /&gt;
&lt;br /&gt;
# Betriebsspannung definieren. Diese Spannung nur zu ca. 80% ausnutzen.&lt;br /&gt;
# Betriebspunkte festlegen: a) Wie lange dauert die Stromentnahme (dt in s), b) wie hoch ist der Peakstrom (I in A) und c) um welchen Wert darf die Spannung dadurch einbrechen (dU in V)? &lt;br /&gt;
# Über die Näherung C = I·dt/dU die dafür benötige Kapazität in Farad berechnen.&amp;lt;br/&amp;gt;Den nächsten, größeren Wert als minimum Wert wählen.&lt;br /&gt;
# Effektivwert der Strombelastung berechnen – siehe die folgende Übersicht unten – Wenn die Stromform im Augenblick unbekannt ist wäre der Versuch angebracht die ungefähre Stromform und damit die Belastung durch eine Simulation zu ermitteln. Ansonsten bleibt nur der Ansatz die Kondensatoren zuerst auf den Peakstrom auszulegen, was bei entsprechendem Geldbeutel der sichere Ansatz ist, und dann Stück für Stück die Anzahl der Kondensatoren zu reduzieren (siehe Punkt 8). &lt;br /&gt;
# Maximalstrom des Kondensators (bei Elkos bei 100Hz) aus dem Datenblatt auslesen. (Bei Folienkondensatoren den nächsten Punkt überspringen)&lt;br /&gt;
# Umrechnen des Datenblattwertes auf die Schaltfrequenz der eigenen Applikation (Umrechnungsbeispiel gilt nur für Elkos!): (von 100Hz auf 10Hz: I[10Hz] = I[100Hz]·0,8; von 100Hz auf 1kHz: I[1kHz] = I[100Hz]·1,3. Eine weitere Vergrößerung für höhere Frequenzen &amp;gt;1kHz ist so nicht zulässig, der 1kHz Wert bleibt bestehen.&lt;br /&gt;
# Wenn die Strombelastung größer als die im Datenblatt angegebene ist, mehrere Kondensatoren parallel schalten oder anderen Kondensatortyp wählen.&lt;br /&gt;
# Kondensator im Betrieb testen.&amp;lt;br/&amp;gt;Dazu wird der Kondensator in der Schaltung betrieben und dabei die Minimalspannung, die Maximalspannung und die Temperatur gemessen. Der Spannungseinbruch muß im selbst gewählten Rahmen bleiben, die Maximalspannung darf nie erreicht werden (Sicherheitsabstand!) und die maximal zulässige Betriebstemperatur des Bauteiles darf nicht erreicht werden (Messungen Anfangs in kurzen, dann je nach Änderungsgeschwindigkeit der Temperatur in längeren Abständen aufnehmen, bis sich die Temperatur auch nach einigen Minuten nicht mehr erhöht, sofortiger Abbruch bei erreichen der Maximaltemperatur!).&amp;lt;br/&amp;gt;Als Daumenregel gilt: Kann das Bauteil nicht mehr angefaßt werden (Vorsicht bei Spannungen über 40V!) ist es vermutlich überbelastet.&lt;br /&gt;
# Den Test unter Punkt 8. an mehreren Betriebspunkten wiederholen.&lt;br /&gt;
&lt;br /&gt;
Auslegungskriterium bei Elkos ist die max. Rippelstrombelastbarkeit, bei Folienkondensatoren der erlaubte Spannungsrippel bzw. -einbruch. Nur in den seltensten Fällen wird die Verwendung von einem einzelnen Kondensator alle Probleme lösen. Die Parallelschaltung von mehreren Kondensatoren des gleichen Typs ist daher grundsätzlich zu empfehlen. Lieber mehrere Elko mit dem besten Preis-Leistungs Verhältnis, als ein Spezialtyp.&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
=== Anbindung des Stützkondensators an den Leistungsteil ===&lt;br /&gt;
[[Bild:Leistungsteil_Bild2.png|miniatur|rechts|350px|Einfache Endstufe wie mit Verdrahtung und PCB umgesetzt ]]&lt;br /&gt;
Im Bild ist der Leistungspfad – bestehend aus Zuleitungen, Kondensator und Endstufe – mit den wirksamen parasitären Einflüssen dargestellt.&lt;br /&gt;
Die dort gezeigten parasitären Elemente zwischen Kondensator und Leistungsschalter stellen den kompletten Leistungszweig dar, der im Schaltvorgang belastet wird.&lt;br /&gt;
&lt;br /&gt;
Die Optimierung der im Bild gezeigte Schleife – d.h. kürzest mögliche Verbindung mit minimierter Induktivität – muß beim Design oberste Priorität besitzen.&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
===Kühlung der Leistungshalbleiter===&lt;br /&gt;
&lt;br /&gt;
Beim Betrieb von Leistungshalbleitern wird Abwärme erzeugt. Dies geschieht sowohl im eingeschalteten Zustand, als auch bei jedem Ein- und Ausschalten.&lt;br /&gt;
Um eine Überhitzung und damit eine Zerstörung des Bauteiles zu verhindern muß diese Wärmeenergie entsprechend abgeführt werden. Ab einer Verlustleistung von 1..5W - je nach Größe des Bauteiles - ist es nicht mehr ausreichend wenn das Bauteil diese Energie nur abstrahlt. Am häufigsten werden diese Bauteile auf einen [[Kühlkörper]] geschraubt oder geklemmt, selten geklebt. &lt;br /&gt;
&lt;br /&gt;
Sowohl die Oberfläche des Kühlkörpers als auch des wärmeerzeugende Bauteiles sind nicht eben und weisen eine gewisse Rauhigkeit auf. Dies bedeutet, daß sich die zwei Oberflächen nur punktuell berühren (meist nur mit wenigen Prozent der Gesamtfläche) und nicht auf der gesamten Fläche. &lt;br /&gt;
&lt;br /&gt;
Luft hat eine sehr schlechte Wärmeleitfähigkeit und die Luft, die zwischen den zwei Oberflächen liegt, verhindert eine Wärmeleitung zwischen den zwei Teilen sehr effektiv. Als Daumenwert kann man sagen, daß 1µm Luft in etwa einem absoluten Wärmewiderstand von ca. 1K/W entspricht... jedoch wird es sich nur in den seltensten Fällen nur um einen Mikrometer handeln, sondern meistens deutlich mehr. &lt;br /&gt;
&lt;br /&gt;
====Wärmeleitmaterialien:====&lt;br /&gt;
&lt;br /&gt;
Diese Materialien verbessern die thermische Verbindung zwischen einem Bauteil, das Wärme erzeugt, und dem Bauteil, das diese Wärme durch Wärmestrahlung, Konvektion oder Wärmeleitung in ein Kühlmittel (Zwangskühlung durch Luft oder Wasser) abführt. Diese Materialien werden zwar &amp;quot;wärmeleit&amp;quot; -Folie bzw. -Paste genannt, leiten die Wärme jedoch nicht besonders gut...aber immer noch um mindestens den Faktor 100 besser als Luft... und genau das ist der Grund, warum diese verwendet werden müssen. (Kupfer leitet Wärme um den Faktor 15400 besser als Luft) Die Pasten enthalten meist Öle bzw. Wachse und Fette als Bindemittel und zur besseren Wärmeleitung Metalloxide bzw. Metall- oder Kohlenstoffpartikel als wärmeleitende Füllstoffe. Achtung: Die meisten Pasten neigen zur Austrocknung, verlieren also nach ca. 5 Jahren ihre wärmeleitenden Fähigkeiten und sind nur mehr als &amp;quot;Krümel&amp;quot; sichtbar.&lt;br /&gt;
&lt;br /&gt;
Besondere Beachtung finden die Wärmeleitfolien, die auf beiden Seiten eine thermisch leitfähige, wachsartige Beschichtung aufweisen. Diese Beschichtung schmilzt unter Wärmeeinwirkung auf und füllt die Spalten zwischen den Oberflächen besonders gut. Folien dieser Art werden &#039;&#039;Phase Change Material&#039;&#039; genannt. Dieser erste Schmelzprozeß erfordert unter Umständen ein Nachspannen des Bauteiles nach dem ersten Aufheizen, da sich durch den Druck die Schichtdicke verringern kann. Achtung: &#039;&#039;Vor&#039;&#039; dem Aufheizen und Nachspannen hat die Wärmeleitfähigkeit noch nicht die möglichen Minimalwerte erreicht. Zum Teil ist die Wärmeanbindung noch um Faktoren schlechter, daher beim ersten Einschalten noch nicht voll belasten.&lt;br /&gt;
&lt;br /&gt;
Hier eine Übersicht über die Wärmeleitfähigkeit von verschiedenen Materialien:&lt;br /&gt;
&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:left&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
! Material || Wärmeleitfähigkeit&amp;lt;br/&amp;gt; [W/(m·K)] || Kommentar&lt;br /&gt;
|-&lt;br /&gt;
|Kupfer		|| 370 || schwankt zwischen ca. 350..400&lt;br /&gt;
|-&lt;br /&gt;
|Aluminium		|| 220 || &lt;br /&gt;
|-&lt;br /&gt;
|Stahl		|| 50 || hochlegierte Stähle &amp;lt;20&lt;br /&gt;
|-&lt;br /&gt;
|Eisen          	|| 80||&lt;br /&gt;
|-&lt;br /&gt;
|Silber		|| 430 ||&lt;br /&gt;
|-&lt;br /&gt;
|Zinn		||  67 ||&lt;br /&gt;
|-&lt;br /&gt;
|Blei		|| 35||&lt;br /&gt;
|-&lt;br /&gt;
|Wärmeleitpasten	|| 3..10 ||&lt;br /&gt;
|-&lt;br /&gt;
|Luft		|| 0,024 ||&lt;br /&gt;
|-&lt;br /&gt;
|Wasser		|| 0,6||&lt;br /&gt;
|-&lt;br /&gt;
|Öl		|| 0,15||&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Hier eine Übersicht über die Wärmeleitfähigkeit von &#039;&#039;ausgewählten&#039;&#039; Isolierfolien&amp;lt;ref&amp;gt;Wenn jemand gute und bezahlbare Folien findet/kennt, bitte hier mit allen Daten angeben.&amp;lt;/ref&amp;gt; um dem Nutzer die Entscheidung zu erleichtern:&lt;br /&gt;
&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:left&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
! Material || Wärmeleitfähigkeit&amp;lt;br/&amp;gt;[W/(m·K)] || Größe / Menge ||Bezugsquelle || ungefähre&amp;lt;br/&amp;gt;Kosten&lt;br /&gt;
|-&lt;br /&gt;
|WÄRMELEITFOL.86/82 ROT ||6,5 ||100×;100×0,25mm || C|| 14€&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
;Hinweis: Die Wärmeleitfähigkeit von Folien bezieht sich ausschließlich auf die Folie selbst. Selbst unter besten Bedingungen wird man die genannten Werte nicht erreichen, da durch den Übergang vom Bauteil in die Folie und von dort in den Kühlkörper ein zusätzlicher Wärmewiderstand entsteht. Eine Verschlechterung von ca. 30% oder mindestens 0,5K/W bei einem TO220-Bauteil ist zu erwarten.&lt;br /&gt;
&lt;br /&gt;
Hier eine Übersicht über die Wärmeleitfähigkeit von &#039;&#039;ausgewählten&#039;&#039; Wärmeleitpasten&amp;lt;ref&amp;gt;Wenn jemand gute und bezahlbare Pasten findet/kennt, bitte hier mit allen Daten angeben.&amp;lt;/ref&amp;gt; um dem Nutzer die Entscheidung zu erleichtern:&lt;br /&gt;
&lt;br /&gt;
:{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:left&amp;quot; &lt;br /&gt;
|-&lt;br /&gt;
! Material || Wärmeleitfähigkeit&amp;lt;br&amp;gt;[W/(m·K)] || Größe / Menge ||Bezugsquelle || ungefähre&amp;lt;br/&amp;gt;Kosten&lt;br /&gt;
|-&lt;br /&gt;
|Artic Silver  	||8,9  ||  3,5g || C || 13,95€ &lt;br /&gt;
|-&lt;br /&gt;
|Standard Pasten auf Silikonbasis ||3,0|| 3g..150g|| C / Rei / ... || wenige €/g &lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Montagerichtlinien:&lt;br /&gt;
* Die so beliebten Bohrungen in eine blanken Kühlfahne des Transistors wie z.&amp;amp;nbsp;B. beim TO-220 Gehäuse suggerieren eine fantastisch einfache Montierbarkteit. Wird die Schraube aber nur ein klein wenig zu fest angezogen, verformt sich das Kupfer der Kühlfahne und sorgt dafür, daß sich der Kunststoff umpresste Teil des Transistors ein klein wenig abhebt. Dies hat eine deutlich schlechtere Wärmeanbindung zur Folge. Die isolierte Bohrung bei vollständig umspritzten – nicht zu verwechseln mit auch auf der Rückseite isolierten – Bauteilen umgeht dieses Risiko, genauso wie der nachfolgende Montagevorschlag.&lt;br /&gt;
* Bei hohen Verlustleistungen ist zu empfehlen, das Bauteil gegenüber der Stelle aufzupressen, an der die Verlustleistung entsteht, also direkt auf dem Kunststoff des Transistors über dem Chip.&lt;br /&gt;
* Werden mehrere Bauteile parallel auf dem Kühlkörper montiert sollte zwischen den Bauteilen &#039;&#039;mindestend&#039;&#039; soviel Abstand vorgesehen werden, wie die Breite des Bauteiles beträgt. Dies vermindert die gegenseitige, thermische Beeinflussing der Bauteile und ermöglicht eine bessere Wärmeabfuhr&lt;br /&gt;
* Zur Montage mehrerer Bauteile eignet sich eine Metallschiene die direkt auf den Kunststoff drückt sehr gut. Zwischen &#039;&#039;jedem&#039;&#039; Bauteil ist ein Verschraubungspunkt vorzusehen, damit jedes Bauteil gleichmäßig aufgedrückt wird.&lt;br /&gt;
* Vor dem Aufbringen der Paste/Folie sowohl Bauteil als auch Kühlkörper mit Alkohol reinigen.&lt;br /&gt;
* Die Wärmeleitwerte für eine Paste beziehen sich auf eine meist nicht genannte  aber trotzdem &#039;&#039;minimale&#039;&#039; Schichtdicke. Diese gelingt relativ reproduzierbar, wenn die Paste mit einem flachen Gegenstand (Rasierklinge, Lineal, ...) aufgebracht, verteilt und vorsichtig abgezogen wird, sodaß nur eine &#039;&#039;dünne&#039;&#039; Schicht auf dem [[Kühlkörper]] verbleibt. Dies erfordert einige Übung. Paste aufhäufeln, Bauteil eindrücken und befestigen erzielt bei weitem nicht die optimale Kühlleistung.&lt;br /&gt;
&lt;br /&gt;
== Zusätzliche Hinweise ==&lt;br /&gt;
&lt;br /&gt;
Anregungen oder Fragen auch gerne per Email an [http://www.mikrocontroller.net/user/show/powerfreak Powerfreak]. Dieser Artikel kann dadurch regelmäßig erweitert und ggf. durch ein FAQ ergänzt werden.&lt;br /&gt;
&lt;br /&gt;
== Fußnoten ==&lt;br /&gt;
&amp;lt;references/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
* [[Mosfet-Übersicht]]&lt;br /&gt;
* [[IGBT]]&lt;br /&gt;
* [[FET]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Bauteile]]&lt;br /&gt;
[[Kategorie:Leistungselektronik]]&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Frequenzumrichter_mit_Raumzeigermodulation&amp;diff=60747</id>
		<title>Frequenzumrichter mit Raumzeigermodulation</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Frequenzumrichter_mit_Raumzeigermodulation&amp;diff=60747"/>
		<updated>2011-09-26T15:41:42Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: /* Modulation */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;von Axel Jeromin&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_WR_und_Steuerung.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Die FETs befinden sich auf der Unterseite der Platine, so ließ sich der Kühlkörper leicher montieren. Trotz der waagerechten Ausrichtung der Kühlrippen wird der Kühlkörper nach 30 min Betrieb nur ca. 40° C warm.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Achtung Fehlerteufel in: void initial(void) im Programm WR88rzm3.c&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
DDRB = 0x&#039;&#039;&#039;2b&#039;&#039;&#039;;      // PortB2 ist ein Eingang der Rest sind Ausgänge &lt;br /&gt;
&lt;br /&gt;
Achtung: Hier stand fälschlicherweise DDRB = 0x&#039;&#039;&#039;1b&#039;&#039;&#039; !!!! geändert am 14.03.2010&lt;br /&gt;
&lt;br /&gt;
Danke an Uwe Scholz für den Hinweis. Der Fehler war mir nicht aufgefallen, weil ich in meiner Schaltung den Ausgang B5 am Mega88 mit einer Messspitze gekillt hatte und per Drahtbrücke den Ausgang B1 benutzt habe. War leider zu geizig den Controller zu wechseln.&lt;br /&gt;
&lt;br /&gt;
Noch ein Hinweis von Uwe: Im Programm für den Mega32 muss die Reihenfolge der Intialisierung des LCD und des übrigen Controllers gedreht werden. Das heißt zuerst die Ports und dann das LCD initialisieren. Sonst hängen die Ausgänge während der langen Wartezeiten zur Initialisierung des LCD undefiniert in der Luft. Nochmal Danke an Uwe.&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Ein Frequenzumrichter ist ein Gerät zur Veränderung der Drehzahl eines Drehstrom Asynchronmotors.&lt;br /&gt;
Die Drehzahl eines Drehstrom Asynchronmotors ist nur von der Frequenz der angelegten Spannung abhängig. Eine Verringerung der Netzspannung bei konstanter Frequenz über einen Trafo oder Vorwiderstände verändert durch den zunehmen Schlupf irgendwann auch die Drehzahl, das Ganze ist dann aber stark lastabhängig und somit unbrauchbar. Diese Methode wurde mal vor sehr vielen Jahren für einen Sanftanlauf genutzt.&lt;br /&gt;
Ebenfall vor vielen Jahren nutzte man zur Frequenzänderung einen Umformer bestehend aus einem Gleichstrommotor und einem Drehstromgenerator. (Hier und Dort auch Heute noch im Einsatz, z.&amp;amp;nbsp;B. Walzwerk).&lt;br /&gt;
&lt;br /&gt;
Heute wird die Netzspannung gleichgerichtet, geglättet und eine Leistungselektronik erzeugt dann die dreiphasige Wechselspannung mit variabler Frequenz und Spannung.&lt;br /&gt;
&lt;br /&gt;
Die nachfolgend beschriebene Schaltung war zuerst für den Einsatz in einem Eigenbau Elektroauto gedacht. Da Drehstrommotoren wesentlich häufiger in Gebrauchtmarkt anzutreffen sind, sind diese auch günstiger als Gleichstrommotoren. Der Gedanke war, einen vorhandenen Motor anders zu verschalten oder neu zu wickeln, sodass dieser an einer geringeren Spannung betrieben werden kann.&lt;br /&gt;
&lt;br /&gt;
Die Schaltung eignet sich für DC-Spannungen von 30V bis 325V. Mit 30V kann z.&amp;amp;nbsp;B. ein Motor einer Festplatte betrieben werden (dies war mein Testmotor, bevor es an die höheren Spannungen ging) und 325V für einen 230/400V Motor in Dreieckschaltung. Natürlich kann man so ein Gerät mittlerweile für kleines Geld fertig kaufen, aber bei nicht gebräuchlichen Spannungen (Elektroauto) oder ungewöhnlichen Anwendungen ist man mit einem Selbstbau flexibler. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Achtung: die Schaltung ist potentialbehaftet. D.h das Massepotentional der Steuerspannung liegt bei Betrieb mit 230V auf ca. 127V gegen Erde! Daher ist bei Progammmodifikationen die Schaltung unbedingt von Netz zu trennen und aus einer Batterie zu speisen.&lt;br /&gt;
&lt;br /&gt;
== Allgemeines ==&lt;br /&gt;
Ein moderner Frequenzumrichter besitzt in der Regel einen Gleichrichter, einen Zwischenkreis und einen Wechselrichter. Davor kommt noch ein Filter zur Verminderung von Störungen zurück in das einspeisende Netz. Der Gleichrichter soll die angelegte Wechselspannung gleichrichten. Die erzeugte pulsierende Gleichspannung ist bei einer 2 phasigen Einspeisung mit 230V ==&amp;gt; UDC = 230V * Wurzel 2 = 325V. &lt;br /&gt;
&lt;br /&gt;
Der Zwischenkreis glättet und puffert die Gleichspannung. Er besteht aus einem oder mehreren Glättungskondensatoren. Bei Spezialanwendungen wie z.&amp;amp;nbsp;B. einem Elektroauto wird auf die Einspeisung verzichtet und der Zwischenkreis direkt an die Akkus angeschlossen. &lt;br /&gt;
&lt;br /&gt;
Der Wechselrichter besteht aus drei Halbbrücken. Jede Halbbrücke hat zwei Mos-Fet Transistoren. Je nachdem welcher FET der Halbbrücke leitet, liegt der Brückenabgriff an Plus oder Minus. Sind beide Transistoren leitend, gibt es einen prima Kurzschluss, den es zu vermeiden gilt.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
=== Einspeisung und Bremschopper ===&lt;br /&gt;
Die Einspeisung besteht aus: den Eingangsklemmen, dem Filter, dem Gleichrichter und dem ersten Zwischenkreiskondensator.&lt;br /&gt;
Im Eingangskreis ist ein Ladewiderstand, welcher mittels eines Relais überbrückt werden kann. Das Relais wird ab einer eingestellten Zwischenkreisspannung vom Tiny45 geschaltet, um die Kondensatoren zuerst über den Widerstand langsam zu laden.&lt;br /&gt;
Anmerkung zu den Kondensatoren: sie müssen ausreichend spannungsfest sein (&amp;gt;400V aushalten). 450V Typen dürften reichen. Kondensatoren, die geeignet sind finden sich z.&amp;amp;nbsp;B. in Schaltnetzteilen. eBay hat auch öfters welche.&lt;br /&gt;
Die Kapazität ist abhängig von der Last. Hier wurden insgesamt 2000µF verwendet.&lt;br /&gt;
&lt;br /&gt;
C11, C12 und die Drossel sind ein Filter um Störungen  zurück  ins Netz zu minimieren. Laut Wikipedia sind gute Werte: C11=100nF, C12=4,4nF und eine 1:1 Drossel mit 1 mH pro Spule.&lt;br /&gt;
&lt;br /&gt;
Arbeitet der Motor generatorisch, d.h. die Motordrehzahl ist größer als der Umrichtersollwert, wird Energie in den Zwischenkreis gespeist. Da die Energie nicht durch den Einspeisegleichrichter zurück ins Netz gelangen kann, steigt in diesen Fall die Zwischenkreisspannung. Die Zwischenkreisspannung muss daher überwacht werden, ab einem bestimmten Wert wird ein sogenannter Bremswiderstand eingeschaltet, in welchen die überschüssige Energie in Wärme umgewandelt wird.&lt;br /&gt;
&lt;br /&gt;
Der Bremschopper FET wird vom Low-Side Teil eines IR2101 getrieben. Als Bremswiderstand nutze ich eine Glühlampe.&lt;br /&gt;
&lt;br /&gt;
Von einem Tiny45 wird die Zwischenkreisspannung gemessen. Ist die Spannung grösser 243V und kleiner 408V wird die Meldung “Zwischenkreis OK” herausgegeben. Ab einer Spannung von 243V wird das Relais zur Überbrückung des Ladewiderstands geschaltet. Ab 375V wird der Bremswiderstand gepulst. 375V entspricht 0% PWM, 400V entspricht 100% PWM. Die PWM Frequenz ist 150Hz. Zum Messen der Zwischenkreisspannung wurde ein Spannungsteiler mit 3 Widerständen je 270k (3 Stk. zur Erhöhung der Spannungsfestigkeit) und einem Poti zum justieren gearbeitet. Das Poti hat 10K, dadurch kann die Spannung am Analogeingang nicht so hoch werden.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Bremschopper_3.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Die Schaltung ist für eine 2 phasige Einspeisung mit 230V gedacht. Bei anderen Eingangsspannungen muss die Erzeugung der Steuerspannung von der Gleichrichtung getrennt werden. Die 15V und 5V können dann über ein Steckernetzteil oder DC/DC Wandler gewonnen werden.&lt;br /&gt;
&lt;br /&gt;
=== Leistungsteil ===&lt;br /&gt;
Der Leistungsteil besteht im Wesentlichen aus drei Halbbrücken. Jeweils zwei FET´s in einer Halbbrücke werden von einem IR2109 getrieben, welcher wieder direkt durch den Atmel Mega 88 auf der Steuerungsplatine angesteuert wird. Der IR 2109 steuert immer in Abhängigkeit vom Eingang “IN” entweder den High side- oder den Low side FET durch. Zwischen dem Wechsel liegt immer eine Totzeit von 540ns. Dadurch ist der Programmierer von der Kurzschlussproblematik befreit.&lt;br /&gt;
 &lt;br /&gt;
In den Halbbrücken sind auch auf der High-Side N-Kanal Fet´s eingesetzt. Diese haben den Vorteil, dass sie günstiger und leistungsfähiger gegenüber P-Kanal Fet´s sind. „Problematisch“ ist an ihnen jedoch, dass ihre Gatespannung oberhalb der Zwischenkreisspannung liegen muss. Zur Erzeugung dieser Spannung wird bei jedem Schalten des Low side FET über eine Diode ein Kondensator geladen, aus welchem die Spannungsversorgung zur Ansteuerung des High side FET gewonnen wird. Low und Highside werden über eine Periode der Ausgangsspannung gleich oft geschaltet, so kann der sogenannte Bootstrap Kondensator immer nachgeladen werden. (&#039;&#039; Bootstrap ist lt. Wikipedia: englisch für Stiefelschlaufe, sinngemäß: sich an den eigenen Stiefeln [aus dem Sumpf] herausziehen &#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
Der Ausgangsstrom ist natürlich von den eingesetzten Leistungsschaltern abhängig. Die Schaltung ist mit  IRPF 460 (500V Rds&amp;lt; 0.27 Ohm 18.4A) bestückt. Da jeder Transistor durch die Ansteuerung mit Raumzeigermodulation über eine Sinusschwingung zu 50% eingeschaltet ist, kommt man an einen theoretischen Ausgangsstrom von 36,8A. Mit einigen Sicherheitsfaktoren sollten 5-10A Dauerphasenstrom möglich sein, getestet habe ich aber nur mit einem 500W Drehstromgebläse.  &lt;br /&gt;
Die Platine ist zusätzlich mit Lack isoliert, in sauberer Umgebung reicht der Leiterbahnabstand auch so, aber bei etwas Luftfeuchte ist Lack besser als ein Loch in der Platine.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Leistungshalbleiter:&#039;&#039;&#039;&lt;br /&gt;
In der Schaltung sind zwei Satz FET´s parallel geschaltet. Der zweite Satz braucht nur bei größerem Strombedarf bestückt werden. Die FET´s werden nach der Zwischenkreisspannung und dem Ausgangestrom ausgewählt. Bei 325V sind IRFP460 eine gute Wahl. &lt;br /&gt;
Im Schaltplan sind unterschiedliche Mos-Fet´s angegeben, es sollten aber alle gleich sein.&lt;br /&gt;
Die Leiterbahnen müssen evtl. durch Auflöten von Kupferdraht verstärkt werden. Reines Verzinnen bringt durch den relativ hohen spez. Widerstand von Zinn nicht so viel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Wechselrichter.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
=== Steuerung ===&lt;br /&gt;
Die Ansteuerung des Leistungskreis wird mittels Software-PWM realisiert. Zu einer präzisen Bildung der notwendigen Steuersignale ist eine kurze Programmlaufzeit notwendig. Eine LCD Ausgabe oder das Einlesen von Analogwerten sprengt den möglichen Rahmen. Daher ist die Steuerung auf zwei Prozessoren aufgeteilt.&lt;br /&gt;
&lt;br /&gt;
Ein Mega 88 @20Mhz steuert die Halbbrücken. Er erhält den Frequenz- und Motorspannungssollwert über parallele Eingänge von einem Mega32. Dadurch konnte das Programm und damit auch die Zykluszeit kurz gehalten werden (12,15µs im Hauptprogramm).&lt;br /&gt;
&lt;br /&gt;
Der Mega 32 ist der gemütliche Verwalter. Er liest den analogen Sollwert, Ist-Zwischenkreisspannung, Ist-Zwischenkreisstrom , Ist-Drehzahl ein und stellt die Werte auf dem LCD dar.&lt;br /&gt;
&lt;br /&gt;
Der analoge Sollwert ändert sich durch die Rampe des Hoch- und Rücklaufgebers entsprechend langsam, sodass Sollwertsprünge und damit Stromspitzen z.&amp;amp;nbsp;B. beim Motoranlauf vermieden werden. Zur Zeit ist eine Rampe von 2 Sekunden für eine Änderung von 0 auf 50 Hz eingestellt. Der Wert kann im Programm angepasst werden.&lt;br /&gt;
 &lt;br /&gt;
Die Ist-Drehzahlerfassung soll mit einem Hallgeber und einem Magneten an der Motorachse realisiert werden. Dieser Programmteil ist aber noch nicht getestet. Ein Drehzahl von 3000U/min ergibt 50U/sec, dies sollte sich über einen normalen Portpin erfassen lassen.&lt;br /&gt;
&lt;br /&gt;
Der Ist-Strom wird nur im Zwischenkreis gemessen. Ein OP verstärkt den Spannungsabfall über einen Shunt. Durch die Zwischenkreiskondensatoren ist der Strom hier einigermaßen glatt und lässt sich mit dem Analogeingang messen. Eine Messung der Phasenstromes hab ich nicht mehr auf der Platine unterbekommen und müsste extern erfolgen.&lt;br /&gt;
&lt;br /&gt;
=== Verbindung Steuerung Leistungsteil ===&lt;br /&gt;
Auf der Steuerungsplatinne liegen auf dem Wannenstecker PL2, der auch für die Programmierung genutzt werden kann die folgenden Portpins:&lt;br /&gt;
&lt;br /&gt;
Pin 1 am Stecker --&amp;gt; PB3  --&amp;gt; in1 auf dem Leistungsteil&lt;br /&gt;
&lt;br /&gt;
Pin 9 am Stecker --&amp;gt; PB4  --&amp;gt; in3 auf dem Leistungsteil&lt;br /&gt;
&lt;br /&gt;
Pin 7 am Stecker --&amp;gt; PB5  --&amp;gt; in2 auf dem Leistungsteil&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pin 3 am Stecker --&amp;gt; PD7  --&amp;gt; SD 1 bis 3 auf dem Leistungsteil (mit Brücken weiter verbinden)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In dem Wannenstecker ist eine Buchse mit einem Flachbandkabel. Das Kabel ist aufgetrennt und die notwendigen vier Leitungen sind mit den Anschlüssen auf dem Leistungsteil verlötet. Die anderen Adern sind isoliert. &lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Steuerung_Anschluss.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Achtung: mittels Flachbandkabel keine weiteren Masserverbindungen zwischen Steuerung und Leistungsteil herstellen, da sonst eine Masseschleife entsteht und größere Ströme über die dünne Leitung fließen könnten.&lt;br /&gt;
&lt;br /&gt;
=== Verbindung Steuerung LCD ===&lt;br /&gt;
In dem Wannenstecker LCD Port ist eine Buchse mit einem Flachbandkabel. Das Flachbandkabel ist wie folgt mit dem LCD verbunden:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
PORT B 0  =&amp;gt; LCD PORT 1 =&amp;gt; Pin am Display 11 =&amp;gt;	DB4&lt;br /&gt;
&lt;br /&gt;
PORT B 1  =&amp;gt; LCD PORT 2 =&amp;gt; Pin am Display 12 =&amp;gt;	DB5&lt;br /&gt;
&lt;br /&gt;
PORT B 2  =&amp;gt; LCD PORT 3 =&amp;gt; Pin am Display 13 =&amp;gt;	DB6&lt;br /&gt;
&lt;br /&gt;
PORT B 3  =&amp;gt; LCD PORT 4 =&amp;gt; Pin am Display 14 =&amp;gt;	DB7&lt;br /&gt;
&lt;br /&gt;
PORT B 4  =&amp;gt; LCD PORT 5 =&amp;gt; Pin am Display 4  =&amp;gt;	RS&lt;br /&gt;
&lt;br /&gt;
PORT B 5  =&amp;gt; LCD PORT 6 =&amp;gt; Pin am Display 6  =&amp;gt;	E&lt;br /&gt;
&lt;br /&gt;
Siehe auch : [[Uc-wiki:AVR-Tutorial: LCD|AVR-Tutorial: LCD]]&lt;br /&gt;
&lt;br /&gt;
== Steuerprogramm ==&lt;br /&gt;
&lt;br /&gt;
Da der IR 2109 immer den High &#039;&#039;&#039;oder&#039;&#039;&#039; Low Side FET ansteuert, sind &#039;&#039;&#039;immer drei&#039;&#039;&#039; der sechs FET´s des Leistungsteils leitend. Es ergeben sich die folgenden Ausgangsmuster, wobei z.&amp;amp;nbsp;B. 001 bedeutet, dass den Halbbrücken 1 und 2 der Low Side FET und in der Halbbrücke 3 der High Side FET leitet. Je nach Motorschaltung (Stern oder Dreieck) ergeben sich unterschiedliche Spannungen an den Motorwicklungen &#039;&#039;&#039;u&#039;&#039;&#039; , &#039;&#039;&#039;v&#039;&#039;&#039; und &#039;&#039;&#039;w&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| Stern&lt;br /&gt;
| &lt;br /&gt;
|&lt;br /&gt;
| &lt;br /&gt;
|Dreieck&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
|  &lt;br /&gt;
|&lt;br /&gt;
|  &lt;br /&gt;
| u&lt;br /&gt;
| v&lt;br /&gt;
| w&lt;br /&gt;
|&lt;br /&gt;
| u&lt;br /&gt;
| v&lt;br /&gt;
| w&lt;br /&gt;
|-&lt;br /&gt;
| Muster 1&lt;br /&gt;
|&#039;&#039;&#039;001&#039;&#039;&#039;&lt;br /&gt;
|&lt;br /&gt;
| -1/3 Udc&lt;br /&gt;
| -1/3 Udc&lt;br /&gt;
| +2/3 Udc&lt;br /&gt;
|&lt;br /&gt;
| 0 V&lt;br /&gt;
| - Udc&lt;br /&gt;
| + Udc&lt;br /&gt;
|-&lt;br /&gt;
|Muster 2&lt;br /&gt;
|&#039;&#039;&#039;011&#039;&#039;&#039;&lt;br /&gt;
|&lt;br /&gt;
| -2/3 Udc&lt;br /&gt;
| +1/3 Udc&lt;br /&gt;
| +1/3 Udc&lt;br /&gt;
|&lt;br /&gt;
| - Udc&lt;br /&gt;
| 0 V&lt;br /&gt;
| + Udc&lt;br /&gt;
|-&lt;br /&gt;
|Muster 3&lt;br /&gt;
|&#039;&#039;&#039;010&#039;&#039;&#039;&lt;br /&gt;
|&lt;br /&gt;
| -1/3 Udc&lt;br /&gt;
| +2/3 Udc&lt;br /&gt;
| -1/3 Udc&lt;br /&gt;
|&lt;br /&gt;
| - Udc&lt;br /&gt;
| + Udc&lt;br /&gt;
| 0 V&lt;br /&gt;
|-&lt;br /&gt;
|Muster 4&lt;br /&gt;
|&#039;&#039;&#039;110&#039;&#039;&#039;&lt;br /&gt;
|&lt;br /&gt;
| +1/3 Udc&lt;br /&gt;
| +1/3 Udc&lt;br /&gt;
| -2/3 Udc&lt;br /&gt;
|&lt;br /&gt;
| 0 V&lt;br /&gt;
| + Udc&lt;br /&gt;
| - Udc&lt;br /&gt;
|-&lt;br /&gt;
|Muster 5&lt;br /&gt;
|&#039;&#039;&#039;100&#039;&#039;&#039;&lt;br /&gt;
|&lt;br /&gt;
| +2/3 Udc&lt;br /&gt;
| -1/3 Udc&lt;br /&gt;
| -1/3 Udc&lt;br /&gt;
|&lt;br /&gt;
| + Udc&lt;br /&gt;
| 0 V&lt;br /&gt;
| - Udc&lt;br /&gt;
|-&lt;br /&gt;
|Muster 6&lt;br /&gt;
|&#039;&#039;&#039;101&#039;&#039;&#039;&lt;br /&gt;
|&lt;br /&gt;
| +1/3 Udc&lt;br /&gt;
| -2/3 Udc&lt;br /&gt;
| +1/3 Udc&lt;br /&gt;
|&lt;br /&gt;
| + Udc&lt;br /&gt;
| -Udc	&lt;br /&gt;
| 0 V&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Motorspannungen.PNG|600px]]&lt;br /&gt;
&lt;br /&gt;
Im obigen Bild sind die geschalteten Ventile zur Vereinfachung weggelassen. Durch die Parallelschaltung von jeweils zwei Motorwicklungen in der Sternschaltung teilt sich die Zwischenkreisspannung im Verhältnis 1/3 zu 2/3 auf. Bei der Dreiecksschaltung wird jeweils eine Wicklung kurzgeschlossen, die Spannung ist hier 0 Volt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Werden die Ausgangsmuster der Reihe nach ausgegeben, so wird der Rotor des angeschlossenen Motors seine Lage um jeweils 60 Grad verändern. Man spricht von den sechs Spannungsvektoren oder Raumzeigern. Hinzu kommen noch die Muster 000 und 111 bei welchen die Motorspannung 0V ist, da alle Wicklungen an + Udc oder - Udc hängen (Nullspannungsvektor). &lt;br /&gt;
Gibt man nun die Ausgangsmuster 1 bis 6 mit der entsprechenden Frequenz heraus, bekommt man eine Drehbewegung des Motors hin. Der Lauf des Motors ist aber ruckelig und der Motor erwärmt sich, da durch das Schalten der Rechtecke eine Menge Blindstrom im Motor unterwegs ist.&lt;br /&gt;
&lt;br /&gt;
== Raumzeigermodulation ==&lt;br /&gt;
Für einen runden Lauf des Motors und natürlich zur Minimierung der Verluste, muss der Motorstrom möglichst sinusförmig sein. Eine Ansteuerung durch eine analoge Verstärkerschaltung würde immense Verlustleistung hervorrufen. Daher kommt nur eine Realisierung mittels PWM in Frage.&lt;br /&gt;
&lt;br /&gt;
=== Pulsfrequenz ===&lt;br /&gt;
Die Höhe der PWM Frequenz ist immer ein Spagat zwischen Schaltverlusten und einer sauberen Nachbildung des Sinus. Je höher die Pulsfrequenz umso besser wird der Sinus getroffen, aber die Schaltverluste in den Leistungshalbleitern steigen ebenfalls.  Bei Profigeräten sind Pulsfrequenzen zwischen 5KHz und 16 KHz üblich.&lt;br /&gt;
&lt;br /&gt;
Realisiert ist in meinem Projekt eine &#039;&#039;&#039;Software PWM&#039;&#039;&#039;. In der Interrupt-Routine von Timer1 werden die Ausgänge entsprechend gesetzt.  Durch die Normierung der nachfolgend erläuterten Tabelle mit den Sinuswerten, der Normierung der Spannungssollwerte und dem Prescaler (TCCR1B=2;  // use CLK/8 prescale value, entspricht 0,4 µsec bei 20 MHz) kann die Pulsfrequenz verändert bzw erhöht werden. Dies habe ich aber noch nicht getestet. Für Ausgangsfrequenzen bis 50 Hz sind die 2,5Khz ganz OK. (Siehe Stromverlauf weiter unten)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ausgabe wird in meinem Programm in 400µs lange Stücke geteilt. =&amp;gt; Pulsfrequenz = 2,5KHz. Die Auflösung durch den Timer 1 ist 1000 Schritte (1000*0,4µs = 400µs).&lt;br /&gt;
&lt;br /&gt;
=== Modulation ===&lt;br /&gt;
&lt;br /&gt;
Die Raumzeigermodulation beruht auf folgenden Vorraussetzungen:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039; 1) &#039;&#039;&#039; Durch den Halbbrückentreiber ist &#039;&#039;&#039;immer einer der beiden&#039;&#039;&#039; FET´s einer Halbbrücke leitend. (Totzeit vernachlässigt)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039; 2) &#039;&#039;&#039; Gemäß der obigen Tabelle ergibt sich zum Beispiel bei einem im Stern geschaltetem Motor und einem Ausgangsmuster von 001 eine &#039;&#039;&#039; statische &#039;&#039;&#039; Spannung von -1/3 Udc in der Wicklung &#039;&#039;&#039;u&#039;&#039;&#039; des Motors (-1/3 Udc in &#039;&#039;&#039;v&#039;&#039;&#039; und  +2/3 Udc in &#039;&#039;&#039;w&#039;&#039;&#039;). Bei dem Muster 011 eine Spannung von -2/3Udc in &#039;&#039;&#039;u&#039;&#039;&#039;, +1/3 Udc in &#039;&#039;&#039;v&#039;&#039;&#039;  und +1/3 Udc in &#039;&#039;&#039;w&#039;&#039;&#039; .&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039; 3) &#039;&#039;&#039;Gibt man die beiden Muster abwechselnd aus, so ergibt sich in der Motorwicklung ein &#039;&#039;&#039;Mittelwert&#039;&#039;&#039; aus den beiden Spannungen. Vorausgesetzt man macht es schnell genug, so dass die Induktivität der Motorwicklung den Strom glättet.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039; 4) &#039;&#039;&#039; Je nach zeitlichem Anteil der beiden Schaltzustände kann die Spannung im &#039;&#039;&#039;Verhältnis zu den beiden Zeitanteilen&#039;&#039;&#039; variiert werden. Wird z.&amp;amp;nbsp;B. das Muster 001 zu 25% der Zeit und das Muster 011 zu 75% der Zeit ausgegeben so ist die Spannung in der Wicklung &#039;&#039;&#039;u&#039;&#039;&#039;: (0,25*-1/3Udc + 0,75*-2/3Udc)/2 = -0,58Udc&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039; 5) &#039;&#039;&#039; Der  zeitliche Verlauf der Ausgangsspannung wird in &#039;&#039;&#039;gleich lange&#039;&#039;&#039; Blöcke, entsprechend der Pulsfrequenz aufgeteilt. In hier beschriebenen Programm sind dies 400µs. (siehe Pulsfrequenz) &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039; 6) &#039;&#039;&#039; In jedem dieser Blöcke werden vier unterschiedliche Ausgangsmuster mit meist unterschiedlichen &#039;&#039;&#039;Zeitanteilen&#039;&#039;&#039; ausgegeben. Die Zeitanteile der Muster heißen: To, Ta, Te und To. Die Berechnung der Zeitanteile wird nachfolgend beschrieben.&lt;br /&gt;
&lt;br /&gt;
Für einen sinusförmigen Verlauf der Ausgangsspannung werden die Zeitanteile der beiden jeweiligen Ausgangsmuster in Verhältnis zu Sinus des Umlaufwinkels bewertet. &lt;br /&gt;
&lt;br /&gt;
Durch die 6 Raumzeiger ist die Periode einer kompletten Sinusschwingung (und damit auch eine gesamte Motorumdrehung) in 6 Sektoren von jeweils 60 Grad Länge geteilt. Jeder Sektor hat eine Anfangsvektor und einen Endvektor mit dem entsprechenden Ausgangsmuster. Je nach dem Wert des Umlaufwinkels Omega wird der Anfangsvektor oder der Endvektor länger, bzw. kürzer eingeschaltet. Durch die Induktivität des Motors bildet sich ein Mittelwert der Spannung in der jeweiligen Motorwicklung proportional zu den Einschaltzeiten. &lt;br /&gt;
Im Programm läuft ein Zähler für Omega von 0 bis 59, dann wird der Sektorzähler erhöht und der Omega Zähler auf 0 gesetzt.&lt;br /&gt;
&lt;br /&gt;
Ta = Zeit Anfangsvektor = proportional zu: sin (60-omega)&lt;br /&gt;
&lt;br /&gt;
Te = Zeit Endvektor = proportional zu: sin (omega)&lt;br /&gt;
&lt;br /&gt;
Da jedes Ausgangsmuster alle drei Wicklungen beeinflusst, braucht zur Erzeugung der benötigten Spannungen nur eine Berechnung der Schaltzeiten für alle drei Wicklungen stattfinden. Die Spannung in den anderen beiden Wicklungen ändern sich genauso. &lt;br /&gt;
&lt;br /&gt;
Da der induktive Widerstand der Motorwicklungen frequenzabhängig ist, muss die Motorspannung umgekehrt proportional zur Frequenz verändert werden. Dies wird durch Verkleinerung der Einschaltdauer der spannungsführenden Vektoren und Ausgabe eines Nullspannungsvektors (Muster 000 oder 111) erreicht.&lt;br /&gt;
&lt;br /&gt;
Ta = Zeit Anfangsvektor = proportional zu:  sin (60-omega)* Motorspannung in %&lt;br /&gt;
&lt;br /&gt;
Te = Zeit Endvektor = proportional zu:   sin (omega)* Motorspannung in %&lt;br /&gt;
&lt;br /&gt;
To = Zeit Nullspannungsvektor = Pulsperiode-(Zeit Anfangsvektor + Zeit Endvektor)&lt;br /&gt;
&lt;br /&gt;
Für eine bessere Symmetrie wird To halbiert und jeweils vor und nach den Spannungsvektoren ausgegeben. &lt;br /&gt;
Die Nullspannung kann mit dem Muster 000 oder 111 erreicht werden. Zur Minimierung der Schaltverluste in den FET´s wird das Nullspannungsmuster gewählt, bei welchem nur eine Halbbrücke umgeschaltet werden muss. Die Schaltvorgänge werden ebenfalls minimiert, wenn in zwei aufeinander folgenden Pulsperioden die Muster in umgekehrter Reihenfolge ausgegeben werden. Der Mittelwert der erzeugten Spannung wird hierdurch nicht verändert.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|Nullspannungsvektor&lt;br /&gt;
|Anfangsvektor&lt;br /&gt;
|Endvektor&lt;br /&gt;
|Nullspannungsvektor&lt;br /&gt;
|Nullspannungsvektor&lt;br /&gt;
|Endvektor&lt;br /&gt;
|Anfangsvektor&lt;br /&gt;
|Nullspannungsvektor&lt;br /&gt;
|-&lt;br /&gt;
|000&lt;br /&gt;
|010&lt;br /&gt;
|110&lt;br /&gt;
|111&lt;br /&gt;
|111&lt;br /&gt;
|110&lt;br /&gt;
|010&lt;br /&gt;
|000&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Werden anstelle eines Motors drei im Dreieck geschaltete Widerstände angeschlossen erhält man folgenden Spannungsverlauf:&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Spannung_an_ohmschen_Widerstand.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Es ist zu erkennen, wie der Anteil der positiven Spannungsanteile mit jeder Pulsperiode (0,4ms oder 2 Einheiten lang) zunimmt.&lt;br /&gt;
&lt;br /&gt;
=== Programm für Atmel Mega 32 ===&lt;br /&gt;
Der Prozessor bekommt über 8 Eingänge (analog oder digital) die Steuerbefehle und gibt über parallele Ausgänge die Steuerbefehle an den Mega88 für die Raumzeigermodulation. Angesteuert wird auch ein LCD zur Anzeige vom Ist-Spannung, Ist-Strom, Ist-Drehzahl und Sollwerten.&lt;br /&gt;
&lt;br /&gt;
Da sich die Ausgangssignale nur relativ langsam ändern, wird der Prozessor mit 1Mhz internem Oszillator betrieben&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Timerinterrupts&#039;&#039;&#039;&lt;br /&gt;
Timer 0 = Hoch- und Rücklaufgeber. Sollwertintegraton, damit bei Sollwertsprüngen die Motordrehzahl langsam geändert wird. Der Eingangssollwert sollvh wird intergriert zum vorzeichenbehafteten Sollwert sollnh&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hauptprogrammablauf: &#039;&#039;&#039;&lt;br /&gt;
Einlesen des Sollwerts sollvh, Bildung des absoluten Sollwerts sollabs, Bildung des Richtungssignals und Bildung des Freigabesignals.&lt;br /&gt;
&lt;br /&gt;
Einlesen von Ist-Spannung, Ist-Strom, und analogen Sollwerten.&lt;br /&gt;
&lt;br /&gt;
Ausgaben an des LCD&lt;br /&gt;
&lt;br /&gt;
Messung der Ist-Drehzahl&lt;br /&gt;
&lt;br /&gt;
Und wieder nach oben in der Endlosschleife&lt;br /&gt;
&lt;br /&gt;
=== Programm für Atmel Mega 88 ===&lt;br /&gt;
Der Prozessor bekommt den Frequenzsollwert, den Spannungssollwert, die Drehrichtung und das Freigabesignal über parallele Eingänge übermittelt. Angesteuert werden die drei Halbbrücken (IN), die Freigabeeingänge der Brückentreiber (SD) über einen gemeinsamen Ausgang und zwei LED`s.&lt;br /&gt;
Hochgezählt wird im Programm der Zeiger für den aktuellen Stand Sinusschwingung am Ausgang (Omega), aufgeteilt in 6 Sektoren. Daraus berechnet werden die Einschaltzeiten der Halbbrücken für jeweils zwei PWM-Perioden (Pulsperioden, zur Unterscheidung von der Periode der Ausgangsspannung). &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Timerinterrupts&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Timer 1&#039;&#039;&#039; = Ausgabe der Ausgangsmuster.&lt;br /&gt;
 &lt;br /&gt;
Die Timerwerte werden im Hauptprogramm berechnet und in drei Arrays abgelegt (pzh[8]; pzl[8]; pm[8]).&lt;br /&gt;
 &lt;br /&gt;
Es wird der „pulszykluszaehler“ für die Ausgabe des gewünschten Ausgangsmusters über die dazugehörige Zeit von 0 bis 7 hochgezählt. 7 entspricht dem Ende der zweiten Pulsperiode. &lt;br /&gt;
&lt;br /&gt;
Pulszykluszaehler 0 ==&amp;gt; Nullspannungsvektor&lt;br /&gt;
&lt;br /&gt;
Pulszykluszaehler 1 ==&amp;gt; Anfangsvektorvektor&lt;br /&gt;
&lt;br /&gt;
Pulszykluszaehler 2 ==&amp;gt; Endvektor&lt;br /&gt;
&lt;br /&gt;
Pulszykluszaehler 3 ==&amp;gt; Nullspannungsvektor&lt;br /&gt;
&lt;br /&gt;
Pulszykluszaehler 4 ==&amp;gt; Nullspannungsvektor&lt;br /&gt;
&lt;br /&gt;
Pulszykluszaehler 5 ==&amp;gt; Endvektor&lt;br /&gt;
&lt;br /&gt;
Pulszykluszaehler 6 ==&amp;gt; Anfangsvektorvektor&lt;br /&gt;
&lt;br /&gt;
Pulszykluszaehler 7 ==&amp;gt; Nullspannungsvektor&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Timer 0&#039;&#039;&#039; = Zähler für dem Umlaufwinkel und für den aktuellen Sektor. Die Timerwerte sind in einer Tabelle gespeichert und werden im Abhängigkeit vom Sollwert  sollabs an den Timer gegeben Es wird omega bis 59 und sektor bis 6 hochgezählt.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hauptprogrammablauf:&#039;&#039;&#039;&lt;br /&gt;
Einlesen des Sollwerts sollabs, der Ausgangsspannung spg, des Richtungssignals richtung und des Freigabesignals enable&lt;br /&gt;
Laden der Timerwerte aus der Tabelle fbwfl[sollabs] für den Timer 0 zum Zählen von Omega und den Sektoren&lt;br /&gt;
Zwischenspeicherung von Omega und Sektor, damit während der Berechnungen mit den gleichen Werten gerechnet wird. Berechnung der Timerwerte für Timer 1: Ta, Te, To gemäss Raumzeigermodulation mit den dazugehörigen Ausgangsmustern. Die Werte für Sinus Omega 0 bis 59 sind in der Tabelle sin[omega] gespeichert, die Werte für Sinus (60-omega) in der Tabelle sinkomp[omega].&lt;br /&gt;
&lt;br /&gt;
Ta= (sinkomp[omega]*spannung[sollabs]);&lt;br /&gt;
&lt;br /&gt;
Te= (sin[omega]*spannung[sollabs]);&lt;br /&gt;
&lt;br /&gt;
To= ((1000-(Ta+Te))/2);&lt;br /&gt;
&lt;br /&gt;
Speicherung der Ausgangsmuster und Timerwerte für zwei Pulsperioden&lt;br /&gt;
 &lt;br /&gt;
Und wieder nach oben in der Endlosschleife&lt;br /&gt;
&lt;br /&gt;
== Funktionstest ==&lt;br /&gt;
=== Spannung an ohmschen Widerstand ===&lt;br /&gt;
Es wurde eine Zwischenkreisspannung von ca. 24V angelegt.&lt;br /&gt;
Am Ausgang des FU werden drei Widerstände 470 Ohm im Stern geschaltet. Die Spannung wird über einen Widerstand gegen den Sternpunkt der Widerstände gemessen.&lt;br /&gt;
&lt;br /&gt;
Je nach dem aktuellen Sektor sehen die Spanungsverläufe so oder invers aus.&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Spannug_an_ohmschen_Widerstand_P1020274a_.jpg|300px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Spannug_an_ohmschen_Widerstand_P1020265a_.jpg|300px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Motorstrom ===&lt;br /&gt;
&lt;br /&gt;
Hier das Ergebnis aller Bemühungen:&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Motorstrom_30Hz.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Motorstrom in einem angeschossenen Drehstrommotor über einen Shunt gemessen bei 30Hz Ausgangsfrequenz.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Testkandidaten.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Hier die Testkandidaten, die alle thermischen Misshandlungen ausgehalten haben.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
* Einspeisung   [[Media:FU_Einspeisung.zip‎|download zip-File]]&lt;br /&gt;
 &lt;br /&gt;
* Leistungsteil [[Media:FU_Wechselrichter.zip‎|download zip-File]]&lt;br /&gt;
* Leistungsteil Schaltplan [[Media:FU_Wechselr_Schaltplan.zip‎|download zip-File]]&lt;br /&gt;
&lt;br /&gt;
* Steuerung     [[Media:FU_Steuerung.zip|download zip-File]]&lt;br /&gt;
‎&lt;br /&gt;
&lt;br /&gt;
== Verluste ==&lt;br /&gt;
&lt;br /&gt;
3 Stück IR2109 , 1 Stück Mega 8 , 1 Stück Mega 88 , 4 Stück IRFP150 verstarben in treuer Pflichterfüllung durch Unachtsamkeiten des Benutzers&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Umrichter von Uwe Scholz =&lt;br /&gt;
Steuerung und Bremsschopper sind weitgehend gleich geblieben, nur im Dickstromteil gab es größere Änderungen. Der mußte auch zweiseitig werden, da Drahtbrücken unter dem Kühlkörper nicht gegangen wären. &lt;br /&gt;
&lt;br /&gt;
Der Trafo ist auch eine Numer größer, 0,5W war mir gefühlsmäßig etwas zu wenig. Falls ich noch einen bauen sollte, dann würde ich aber schon wieder ein paar Sachen anders machen;-)&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Uwe_Scholz_1.jpg‎|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Uwe_Scholz_2.jpg‎|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Uwe_Scholz_3.jpg‎|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Uwe_Scholz_4.jpg‎|400px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Umrichter von Patrick Leube = &lt;br /&gt;
Die Steuerung wurde über zwei Atmega 88 realisiert.&lt;br /&gt;
Die sechspuls Brückenschaltung ist etwas Abgespeckt worden.&lt;br /&gt;
Da dieser Umrichter für Akkupacks von 36V-60V ausgelegt wurde muste noch eine &amp;quot;Netzteil&amp;quot; gebastelt werden das 15V und 5V generiert.&lt;br /&gt;
Die Bedinung erfolgt über Taster für Sollwertvorgabe +/- RUN / STOP.&lt;br /&gt;
Als LCD kam ein 4*20 zum Einsatz.&lt;br /&gt;
&lt;br /&gt;
Verluste: 1* LT1074HV = 12€ &lt;br /&gt;
&lt;br /&gt;
Da dieses Projekt mein erstes wirkliches Projekt mit µC und Elektronik im tieferen Sinne war möchte mich an dieser stelle auch nochmal bei Axel für seine Unterstützung bedanken.&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Patrick_1.jpg|300px]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Patrick_2.jpg|300px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;br /&gt;
[[Kategorie:Leistungselektronik]]&lt;br /&gt;
[[Category:1. Wettbewerb]]&lt;br /&gt;
[[Kategorie:Spannungsversorgung und Energiequellen]]&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Frequenzumrichter_mit_Raumzeigermodulation&amp;diff=60746</id>
		<title>Frequenzumrichter mit Raumzeigermodulation</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Frequenzumrichter_mit_Raumzeigermodulation&amp;diff=60746"/>
		<updated>2011-09-26T15:40:21Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: /* Steuerprogramm */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;von Axel Jeromin&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_WR_und_Steuerung.jpg|600px]]&lt;br /&gt;
&lt;br /&gt;
Die FETs befinden sich auf der Unterseite der Platine, so ließ sich der Kühlkörper leicher montieren. Trotz der waagerechten Ausrichtung der Kühlrippen wird der Kühlkörper nach 30 min Betrieb nur ca. 40° C warm.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Achtung Fehlerteufel in: void initial(void) im Programm WR88rzm3.c&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
DDRB = 0x&#039;&#039;&#039;2b&#039;&#039;&#039;;      // PortB2 ist ein Eingang der Rest sind Ausgänge &lt;br /&gt;
&lt;br /&gt;
Achtung: Hier stand fälschlicherweise DDRB = 0x&#039;&#039;&#039;1b&#039;&#039;&#039; !!!! geändert am 14.03.2010&lt;br /&gt;
&lt;br /&gt;
Danke an Uwe Scholz für den Hinweis. Der Fehler war mir nicht aufgefallen, weil ich in meiner Schaltung den Ausgang B5 am Mega88 mit einer Messspitze gekillt hatte und per Drahtbrücke den Ausgang B1 benutzt habe. War leider zu geizig den Controller zu wechseln.&lt;br /&gt;
&lt;br /&gt;
Noch ein Hinweis von Uwe: Im Programm für den Mega32 muss die Reihenfolge der Intialisierung des LCD und des übrigen Controllers gedreht werden. Das heißt zuerst die Ports und dann das LCD initialisieren. Sonst hängen die Ausgänge während der langen Wartezeiten zur Initialisierung des LCD undefiniert in der Luft. Nochmal Danke an Uwe.&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Ein Frequenzumrichter ist ein Gerät zur Veränderung der Drehzahl eines Drehstrom Asynchronmotors.&lt;br /&gt;
Die Drehzahl eines Drehstrom Asynchronmotors ist nur von der Frequenz der angelegten Spannung abhängig. Eine Verringerung der Netzspannung bei konstanter Frequenz über einen Trafo oder Vorwiderstände verändert durch den zunehmen Schlupf irgendwann auch die Drehzahl, das Ganze ist dann aber stark lastabhängig und somit unbrauchbar. Diese Methode wurde mal vor sehr vielen Jahren für einen Sanftanlauf genutzt.&lt;br /&gt;
Ebenfall vor vielen Jahren nutzte man zur Frequenzänderung einen Umformer bestehend aus einem Gleichstrommotor und einem Drehstromgenerator. (Hier und Dort auch Heute noch im Einsatz, z.&amp;amp;nbsp;B. Walzwerk).&lt;br /&gt;
&lt;br /&gt;
Heute wird die Netzspannung gleichgerichtet, geglättet und eine Leistungselektronik erzeugt dann die dreiphasige Wechselspannung mit variabler Frequenz und Spannung.&lt;br /&gt;
&lt;br /&gt;
Die nachfolgend beschriebene Schaltung war zuerst für den Einsatz in einem Eigenbau Elektroauto gedacht. Da Drehstrommotoren wesentlich häufiger in Gebrauchtmarkt anzutreffen sind, sind diese auch günstiger als Gleichstrommotoren. Der Gedanke war, einen vorhandenen Motor anders zu verschalten oder neu zu wickeln, sodass dieser an einer geringeren Spannung betrieben werden kann.&lt;br /&gt;
&lt;br /&gt;
Die Schaltung eignet sich für DC-Spannungen von 30V bis 325V. Mit 30V kann z.&amp;amp;nbsp;B. ein Motor einer Festplatte betrieben werden (dies war mein Testmotor, bevor es an die höheren Spannungen ging) und 325V für einen 230/400V Motor in Dreieckschaltung. Natürlich kann man so ein Gerät mittlerweile für kleines Geld fertig kaufen, aber bei nicht gebräuchlichen Spannungen (Elektroauto) oder ungewöhnlichen Anwendungen ist man mit einem Selbstbau flexibler. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Achtung: die Schaltung ist potentialbehaftet. D.h das Massepotentional der Steuerspannung liegt bei Betrieb mit 230V auf ca. 127V gegen Erde! Daher ist bei Progammmodifikationen die Schaltung unbedingt von Netz zu trennen und aus einer Batterie zu speisen.&lt;br /&gt;
&lt;br /&gt;
== Allgemeines ==&lt;br /&gt;
Ein moderner Frequenzumrichter besitzt in der Regel einen Gleichrichter, einen Zwischenkreis und einen Wechselrichter. Davor kommt noch ein Filter zur Verminderung von Störungen zurück in das einspeisende Netz. Der Gleichrichter soll die angelegte Wechselspannung gleichrichten. Die erzeugte pulsierende Gleichspannung ist bei einer 2 phasigen Einspeisung mit 230V ==&amp;gt; UDC = 230V * Wurzel 2 = 325V. &lt;br /&gt;
&lt;br /&gt;
Der Zwischenkreis glättet und puffert die Gleichspannung. Er besteht aus einem oder mehreren Glättungskondensatoren. Bei Spezialanwendungen wie z.&amp;amp;nbsp;B. einem Elektroauto wird auf die Einspeisung verzichtet und der Zwischenkreis direkt an die Akkus angeschlossen. &lt;br /&gt;
&lt;br /&gt;
Der Wechselrichter besteht aus drei Halbbrücken. Jede Halbbrücke hat zwei Mos-Fet Transistoren. Je nachdem welcher FET der Halbbrücke leitet, liegt der Brückenabgriff an Plus oder Minus. Sind beide Transistoren leitend, gibt es einen prima Kurzschluss, den es zu vermeiden gilt.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
=== Einspeisung und Bremschopper ===&lt;br /&gt;
Die Einspeisung besteht aus: den Eingangsklemmen, dem Filter, dem Gleichrichter und dem ersten Zwischenkreiskondensator.&lt;br /&gt;
Im Eingangskreis ist ein Ladewiderstand, welcher mittels eines Relais überbrückt werden kann. Das Relais wird ab einer eingestellten Zwischenkreisspannung vom Tiny45 geschaltet, um die Kondensatoren zuerst über den Widerstand langsam zu laden.&lt;br /&gt;
Anmerkung zu den Kondensatoren: sie müssen ausreichend spannungsfest sein (&amp;gt;400V aushalten). 450V Typen dürften reichen. Kondensatoren, die geeignet sind finden sich z.&amp;amp;nbsp;B. in Schaltnetzteilen. eBay hat auch öfters welche.&lt;br /&gt;
Die Kapazität ist abhängig von der Last. Hier wurden insgesamt 2000µF verwendet.&lt;br /&gt;
&lt;br /&gt;
C11, C12 und die Drossel sind ein Filter um Störungen  zurück  ins Netz zu minimieren. Laut Wikipedia sind gute Werte: C11=100nF, C12=4,4nF und eine 1:1 Drossel mit 1 mH pro Spule.&lt;br /&gt;
&lt;br /&gt;
Arbeitet der Motor generatorisch, d.h. die Motordrehzahl ist größer als der Umrichtersollwert, wird Energie in den Zwischenkreis gespeist. Da die Energie nicht durch den Einspeisegleichrichter zurück ins Netz gelangen kann, steigt in diesen Fall die Zwischenkreisspannung. Die Zwischenkreisspannung muss daher überwacht werden, ab einem bestimmten Wert wird ein sogenannter Bremswiderstand eingeschaltet, in welchen die überschüssige Energie in Wärme umgewandelt wird.&lt;br /&gt;
&lt;br /&gt;
Der Bremschopper FET wird vom Low-Side Teil eines IR2101 getrieben. Als Bremswiderstand nutze ich eine Glühlampe.&lt;br /&gt;
&lt;br /&gt;
Von einem Tiny45 wird die Zwischenkreisspannung gemessen. Ist die Spannung grösser 243V und kleiner 408V wird die Meldung “Zwischenkreis OK” herausgegeben. Ab einer Spannung von 243V wird das Relais zur Überbrückung des Ladewiderstands geschaltet. Ab 375V wird der Bremswiderstand gepulst. 375V entspricht 0% PWM, 400V entspricht 100% PWM. Die PWM Frequenz ist 150Hz. Zum Messen der Zwischenkreisspannung wurde ein Spannungsteiler mit 3 Widerständen je 270k (3 Stk. zur Erhöhung der Spannungsfestigkeit) und einem Poti zum justieren gearbeitet. Das Poti hat 10K, dadurch kann die Spannung am Analogeingang nicht so hoch werden.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Bremschopper_3.png|400px]]&lt;br /&gt;
&lt;br /&gt;
Die Schaltung ist für eine 2 phasige Einspeisung mit 230V gedacht. Bei anderen Eingangsspannungen muss die Erzeugung der Steuerspannung von der Gleichrichtung getrennt werden. Die 15V und 5V können dann über ein Steckernetzteil oder DC/DC Wandler gewonnen werden.&lt;br /&gt;
&lt;br /&gt;
=== Leistungsteil ===&lt;br /&gt;
Der Leistungsteil besteht im Wesentlichen aus drei Halbbrücken. Jeweils zwei FET´s in einer Halbbrücke werden von einem IR2109 getrieben, welcher wieder direkt durch den Atmel Mega 88 auf der Steuerungsplatine angesteuert wird. Der IR 2109 steuert immer in Abhängigkeit vom Eingang “IN” entweder den High side- oder den Low side FET durch. Zwischen dem Wechsel liegt immer eine Totzeit von 540ns. Dadurch ist der Programmierer von der Kurzschlussproblematik befreit.&lt;br /&gt;
 &lt;br /&gt;
In den Halbbrücken sind auch auf der High-Side N-Kanal Fet´s eingesetzt. Diese haben den Vorteil, dass sie günstiger und leistungsfähiger gegenüber P-Kanal Fet´s sind. „Problematisch“ ist an ihnen jedoch, dass ihre Gatespannung oberhalb der Zwischenkreisspannung liegen muss. Zur Erzeugung dieser Spannung wird bei jedem Schalten des Low side FET über eine Diode ein Kondensator geladen, aus welchem die Spannungsversorgung zur Ansteuerung des High side FET gewonnen wird. Low und Highside werden über eine Periode der Ausgangsspannung gleich oft geschaltet, so kann der sogenannte Bootstrap Kondensator immer nachgeladen werden. (&#039;&#039; Bootstrap ist lt. Wikipedia: englisch für Stiefelschlaufe, sinngemäß: sich an den eigenen Stiefeln [aus dem Sumpf] herausziehen &#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
Der Ausgangsstrom ist natürlich von den eingesetzten Leistungsschaltern abhängig. Die Schaltung ist mit  IRPF 460 (500V Rds&amp;lt; 0.27 Ohm 18.4A) bestückt. Da jeder Transistor durch die Ansteuerung mit Raumzeigermodulation über eine Sinusschwingung zu 50% eingeschaltet ist, kommt man an einen theoretischen Ausgangsstrom von 36,8A. Mit einigen Sicherheitsfaktoren sollten 5-10A Dauerphasenstrom möglich sein, getestet habe ich aber nur mit einem 500W Drehstromgebläse.  &lt;br /&gt;
Die Platine ist zusätzlich mit Lack isoliert, in sauberer Umgebung reicht der Leiterbahnabstand auch so, aber bei etwas Luftfeuchte ist Lack besser als ein Loch in der Platine.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Leistungshalbleiter:&#039;&#039;&#039;&lt;br /&gt;
In der Schaltung sind zwei Satz FET´s parallel geschaltet. Der zweite Satz braucht nur bei größerem Strombedarf bestückt werden. Die FET´s werden nach der Zwischenkreisspannung und dem Ausgangestrom ausgewählt. Bei 325V sind IRFP460 eine gute Wahl. &lt;br /&gt;
Im Schaltplan sind unterschiedliche Mos-Fet´s angegeben, es sollten aber alle gleich sein.&lt;br /&gt;
Die Leiterbahnen müssen evtl. durch Auflöten von Kupferdraht verstärkt werden. Reines Verzinnen bringt durch den relativ hohen spez. Widerstand von Zinn nicht so viel.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Wechselrichter.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
=== Steuerung ===&lt;br /&gt;
Die Ansteuerung des Leistungskreis wird mittels Software-PWM realisiert. Zu einer präzisen Bildung der notwendigen Steuersignale ist eine kurze Programmlaufzeit notwendig. Eine LCD Ausgabe oder das Einlesen von Analogwerten sprengt den möglichen Rahmen. Daher ist die Steuerung auf zwei Prozessoren aufgeteilt.&lt;br /&gt;
&lt;br /&gt;
Ein Mega 88 @20Mhz steuert die Halbbrücken. Er erhält den Frequenz- und Motorspannungssollwert über parallele Eingänge von einem Mega32. Dadurch konnte das Programm und damit auch die Zykluszeit kurz gehalten werden (12,15µs im Hauptprogramm).&lt;br /&gt;
&lt;br /&gt;
Der Mega 32 ist der gemütliche Verwalter. Er liest den analogen Sollwert, Ist-Zwischenkreisspannung, Ist-Zwischenkreisstrom , Ist-Drehzahl ein und stellt die Werte auf dem LCD dar.&lt;br /&gt;
&lt;br /&gt;
Der analoge Sollwert ändert sich durch die Rampe des Hoch- und Rücklaufgebers entsprechend langsam, sodass Sollwertsprünge und damit Stromspitzen z.&amp;amp;nbsp;B. beim Motoranlauf vermieden werden. Zur Zeit ist eine Rampe von 2 Sekunden für eine Änderung von 0 auf 50 Hz eingestellt. Der Wert kann im Programm angepasst werden.&lt;br /&gt;
 &lt;br /&gt;
Die Ist-Drehzahlerfassung soll mit einem Hallgeber und einem Magneten an der Motorachse realisiert werden. Dieser Programmteil ist aber noch nicht getestet. Ein Drehzahl von 3000U/min ergibt 50U/sec, dies sollte sich über einen normalen Portpin erfassen lassen.&lt;br /&gt;
&lt;br /&gt;
Der Ist-Strom wird nur im Zwischenkreis gemessen. Ein OP verstärkt den Spannungsabfall über einen Shunt. Durch die Zwischenkreiskondensatoren ist der Strom hier einigermaßen glatt und lässt sich mit dem Analogeingang messen. Eine Messung der Phasenstromes hab ich nicht mehr auf der Platine unterbekommen und müsste extern erfolgen.&lt;br /&gt;
&lt;br /&gt;
=== Verbindung Steuerung Leistungsteil ===&lt;br /&gt;
Auf der Steuerungsplatinne liegen auf dem Wannenstecker PL2, der auch für die Programmierung genutzt werden kann die folgenden Portpins:&lt;br /&gt;
&lt;br /&gt;
Pin 1 am Stecker --&amp;gt; PB3  --&amp;gt; in1 auf dem Leistungsteil&lt;br /&gt;
&lt;br /&gt;
Pin 9 am Stecker --&amp;gt; PB4  --&amp;gt; in3 auf dem Leistungsteil&lt;br /&gt;
&lt;br /&gt;
Pin 7 am Stecker --&amp;gt; PB5  --&amp;gt; in2 auf dem Leistungsteil&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pin 3 am Stecker --&amp;gt; PD7  --&amp;gt; SD 1 bis 3 auf dem Leistungsteil (mit Brücken weiter verbinden)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In dem Wannenstecker ist eine Buchse mit einem Flachbandkabel. Das Kabel ist aufgetrennt und die notwendigen vier Leitungen sind mit den Anschlüssen auf dem Leistungsteil verlötet. Die anderen Adern sind isoliert. &lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Steuerung_Anschluss.PNG|800px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Achtung: mittels Flachbandkabel keine weiteren Masserverbindungen zwischen Steuerung und Leistungsteil herstellen, da sonst eine Masseschleife entsteht und größere Ströme über die dünne Leitung fließen könnten.&lt;br /&gt;
&lt;br /&gt;
=== Verbindung Steuerung LCD ===&lt;br /&gt;
In dem Wannenstecker LCD Port ist eine Buchse mit einem Flachbandkabel. Das Flachbandkabel ist wie folgt mit dem LCD verbunden:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
PORT B 0  =&amp;gt; LCD PORT 1 =&amp;gt; Pin am Display 11 =&amp;gt;	DB4&lt;br /&gt;
&lt;br /&gt;
PORT B 1  =&amp;gt; LCD PORT 2 =&amp;gt; Pin am Display 12 =&amp;gt;	DB5&lt;br /&gt;
&lt;br /&gt;
PORT B 2  =&amp;gt; LCD PORT 3 =&amp;gt; Pin am Display 13 =&amp;gt;	DB6&lt;br /&gt;
&lt;br /&gt;
PORT B 3  =&amp;gt; LCD PORT 4 =&amp;gt; Pin am Display 14 =&amp;gt;	DB7&lt;br /&gt;
&lt;br /&gt;
PORT B 4  =&amp;gt; LCD PORT 5 =&amp;gt; Pin am Display 4  =&amp;gt;	RS&lt;br /&gt;
&lt;br /&gt;
PORT B 5  =&amp;gt; LCD PORT 6 =&amp;gt; Pin am Display 6  =&amp;gt;	E&lt;br /&gt;
&lt;br /&gt;
Siehe auch : [[Uc-wiki:AVR-Tutorial: LCD|AVR-Tutorial: LCD]]&lt;br /&gt;
&lt;br /&gt;
== Steuerprogramm ==&lt;br /&gt;
&lt;br /&gt;
Da der IR 2109 immer den High &#039;&#039;&#039;oder&#039;&#039;&#039; Low Side FET ansteuert, sind &#039;&#039;&#039;immer drei&#039;&#039;&#039; der sechs FET´s des Leistungsteils leitend. Es ergeben sich die folgenden Ausgangsmuster, wobei z.&amp;amp;nbsp;B. 001 bedeutet, dass den Halbbrücken 1 und 2 der Low Side FET und in der Halbbrücke 3 der High Side FET leitet. Je nach Motorschaltung (Stern oder Dreieck) ergeben sich unterschiedliche Spannungen an den Motorwicklungen &#039;&#039;&#039;u&#039;&#039;&#039; , &#039;&#039;&#039;v&#039;&#039;&#039; und &#039;&#039;&#039;w&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
|&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
| Stern&lt;br /&gt;
| &lt;br /&gt;
|&lt;br /&gt;
| &lt;br /&gt;
|Dreieck&lt;br /&gt;
| &lt;br /&gt;
| &lt;br /&gt;
|-&lt;br /&gt;
|  &lt;br /&gt;
|&lt;br /&gt;
|  &lt;br /&gt;
| u&lt;br /&gt;
| v&lt;br /&gt;
| w&lt;br /&gt;
|&lt;br /&gt;
| u&lt;br /&gt;
| v&lt;br /&gt;
| w&lt;br /&gt;
|-&lt;br /&gt;
| Muster 1&lt;br /&gt;
|&#039;&#039;&#039;001&#039;&#039;&#039;&lt;br /&gt;
|&lt;br /&gt;
| -1/3 Udc&lt;br /&gt;
| -1/3 Udc&lt;br /&gt;
| +2/3 Udc&lt;br /&gt;
|&lt;br /&gt;
| 0 V&lt;br /&gt;
| - Udc&lt;br /&gt;
| + Udc&lt;br /&gt;
|-&lt;br /&gt;
|Muster 2&lt;br /&gt;
|&#039;&#039;&#039;011&#039;&#039;&#039;&lt;br /&gt;
|&lt;br /&gt;
| -2/3 Udc&lt;br /&gt;
| +1/3 Udc&lt;br /&gt;
| +1/3 Udc&lt;br /&gt;
|&lt;br /&gt;
| - Udc&lt;br /&gt;
| 0 V&lt;br /&gt;
| + Udc&lt;br /&gt;
|-&lt;br /&gt;
|Muster 3&lt;br /&gt;
|&#039;&#039;&#039;010&#039;&#039;&#039;&lt;br /&gt;
|&lt;br /&gt;
| -1/3 Udc&lt;br /&gt;
| +2/3 Udc&lt;br /&gt;
| -1/3 Udc&lt;br /&gt;
|&lt;br /&gt;
| - Udc&lt;br /&gt;
| + Udc&lt;br /&gt;
| 0 V&lt;br /&gt;
|-&lt;br /&gt;
|Muster 4&lt;br /&gt;
|&#039;&#039;&#039;110&#039;&#039;&#039;&lt;br /&gt;
|&lt;br /&gt;
| +1/3 Udc&lt;br /&gt;
| +1/3 Udc&lt;br /&gt;
| -2/3 Udc&lt;br /&gt;
|&lt;br /&gt;
| 0 V&lt;br /&gt;
| + Udc&lt;br /&gt;
| - Udc&lt;br /&gt;
|-&lt;br /&gt;
|Muster 5&lt;br /&gt;
|&#039;&#039;&#039;100&#039;&#039;&#039;&lt;br /&gt;
|&lt;br /&gt;
| +2/3 Udc&lt;br /&gt;
| -1/3 Udc&lt;br /&gt;
| -1/3 Udc&lt;br /&gt;
|&lt;br /&gt;
| + Udc&lt;br /&gt;
| 0 V&lt;br /&gt;
| - Udc&lt;br /&gt;
|-&lt;br /&gt;
|Muster 6&lt;br /&gt;
|&#039;&#039;&#039;101&#039;&#039;&#039;&lt;br /&gt;
|&lt;br /&gt;
| +1/3 Udc&lt;br /&gt;
| -2/3 Udc&lt;br /&gt;
| +1/3 Udc&lt;br /&gt;
|&lt;br /&gt;
| + Udc&lt;br /&gt;
| -Udc	&lt;br /&gt;
| 0 V&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Motorspannungen.PNG|600px]]&lt;br /&gt;
&lt;br /&gt;
Im obigen Bild sind die geschalteten Ventile zur Vereinfachung weggelassen. Durch die Parallelschaltung von jeweils zwei Motorwicklungen in der Sternschaltung teilt sich die Zwischenkreisspannung im Verhältnis 1/3 zu 2/3 auf. Bei der Dreiecksschaltung wird jeweils eine Wicklung kurzgeschlossen, die Spannung ist hier 0 Volt.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Werden die Ausgangsmuster der Reihe nach ausgegeben, so wird der Rotor des angeschlossenen Motors seine Lage um jeweils 60 Grad verändern. Man spricht von den sechs Spannungsvektoren oder Raumzeigern. Hinzu kommen noch die Muster 000 und 111 bei welchen die Motorspannung 0V ist, da alle Wicklungen an + Udc oder - Udc hängen (Nullspannungsvektor). &lt;br /&gt;
Gibt man nun die Ausgangsmuster 1 bis 6 mit der entsprechenden Frequenz heraus, bekommt man eine Drehbewegung des Motors hin. Der Lauf des Motors ist aber ruckelig und der Motor erwärmt sich, da durch das Schalten der Rechtecke eine Menge Blindstrom im Motor unterwegs ist.&lt;br /&gt;
&lt;br /&gt;
== Raumzeigermodulation ==&lt;br /&gt;
Für einen runden Lauf des Motors und natürlich zur Minimierung der Verluste, muss der Motorstrom möglichst sinusförmig sein. Eine Ansteuerung durch eine analoge Verstärkerschaltung würde immense Verlustleistung hervorrufen. Daher kommt nur eine Realisierung mittels PWM in Frage.&lt;br /&gt;
&lt;br /&gt;
=== Pulsfrequenz ===&lt;br /&gt;
Die Höhe der PWM Frequenz ist immer ein Spagat zwischen Schaltverlusten und einer sauberen Nachbildung des Sinus. Je höher die Pulsfrequenz umso besser wird der Sinus getroffen, aber die Schaltverluste in den Leistungshalbleitern steigen ebenfalls.  Bei Profigeräten sind Pulsfrequenzen zwischen 5KHz und 16 KHz üblich.&lt;br /&gt;
&lt;br /&gt;
Realisiert ist in meinem Projekt eine &#039;&#039;&#039;Software PWM&#039;&#039;&#039;. In der Interrupt-Routine von Timer1 werden die Ausgänge entsprechend gesetzt.  Durch die Normierung der nachfolgend erläuterten Tabelle mit den Sinuswerten, der Normierung der Spannungssollwerte und dem Prescaler (TCCR1B=2;  // use CLK/8 prescale value, entspricht 0,4 µsec bei 20 MHz) kann die Pulsfrequenz verändert bzw erhöht werden. Dies habe ich aber noch nicht getestet. Für Ausgangsfrequenzen bis 50 Hz sind die 2,5Khz ganz OK. (Siehe Stromverlauf weiter unten)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die Ausgabe wird in meinem Programm in 400µs lange Stücke geteilt. =&amp;gt; Pulsfrequenz = 2,5KHz. Die Auflösung durch den Timer 1 ist 1000 Schritte (1000*0,4µs = 400µs).&lt;br /&gt;
&lt;br /&gt;
=== Modulation ===&lt;br /&gt;
&lt;br /&gt;
Die Raumzeigermodulation beruht auf folgenden Vorraussetzungen:&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039; 1) &#039;&#039;&#039; Durch den Halbbrückentreiber ist &#039;&#039;&#039;immer einer der beiden&#039;&#039;&#039; FET´s einer Halbbrücke leitend. (Totzeit vernachlässigt)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039; 2) &#039;&#039;&#039; Gemäß der obigen Tabelle ergibt sich zum Beispiel bei einem im Stern geschaltetem Motor und einem Ausgangsmuster von 001 eine &#039;&#039;&#039; statische &#039;&#039;&#039; Spannung von -1/3 Udc in der Wicklung &#039;&#039;&#039;u&#039;&#039;&#039; des Motors (-1/3 Udc in &#039;&#039;&#039;v&#039;&#039;&#039; und  +2/3 Udc in &#039;&#039;&#039;w&#039;&#039;&#039;). Bei dem Muster 011 eine Spannung von -2/3Udc in &#039;&#039;&#039;u&#039;&#039;&#039;, +1/3 Udc in &#039;&#039;&#039;v&#039;&#039;&#039;  und +1/3 Udc in &#039;&#039;&#039;w&#039;&#039;&#039; .&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039; 3) &#039;&#039;&#039;Gibt man die beiden Muster abwechselnd aus, so ergibt sich in der Motorwicklung ein &#039;&#039;&#039;Mittelwert&#039;&#039;&#039; aus den beiden Spannungen. Vorausgesetzt man macht es schell genug, so dass die Induktivität der Motorwicklung den Strom glättet.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039; 4) &#039;&#039;&#039; Je nach zeitlichem Anteil der beiden Schaltzustände kann die Spannung im &#039;&#039;&#039;Verhältnis zu den beiden Zeitanteilen&#039;&#039;&#039; variiert werden. Wird z.&amp;amp;nbsp;B. das Muster 001 zu 25% der Zeit und das Muster 011 zu 75% der Zeit ausgegeben so ist die Spannung in der Wicklung &#039;&#039;&#039;u&#039;&#039;&#039;: (0,25*-1/3Udc + 0,75*-2/3Udc)/2 = -0,58Udc&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039; 5) &#039;&#039;&#039; Der  zeitliche Verlauf der Ausgangsspannung wird in &#039;&#039;&#039;gleich lange&#039;&#039;&#039; Blöcke, entsprechend der Pulsfrequenz aufgeteilt. In hier beschriebenen Programm sind dies 400µs. (siehe Pulsfrequenz) &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039; 6) &#039;&#039;&#039; In jedem dieser Blöcke werden vier unterschiedliche Ausgangsmuster mit meist unterschiedlichen &#039;&#039;&#039;Zeitanteilen&#039;&#039;&#039; ausgegeben. Die Zeitanteile der Muster heißen: To, Ta, Te und To. Die Berechnung der Zeitanteile wird nachfolgend beschrieben.&lt;br /&gt;
&lt;br /&gt;
Für einen sinusförmigen Verlauf der Ausgangsspannung werden die Zeitanteile der beiden jeweiligen Ausgangsmuster in Verhältnis zu Sinus des Umlaufwinkels bewertet. &lt;br /&gt;
&lt;br /&gt;
Durch die 6 Raumzeiger ist die Periode einer kompletten Sinusschwingung (und damit auch eine gesamte Motorumdrehung) in 6 Sektoren von jeweils 60 Grad Länge geteilt. Jeder Sektor hat eine Anfangsvektor und einen Endvektor mit dem entsprechenden Ausgangsmuster. Je nach dem Wert des Umlaufwinkels Omega wird der Anfangsvektor oder der Endvektor länger, bzw. kürzer eingeschaltet. Durch die Induktivität des Motors bildet sich ein Mittelwert der Spannung in der jeweiligen Motorwicklung proportional zu den Einschaltzeiten. &lt;br /&gt;
Im Programm läuft ein Zähler für Omega von 0 bis 59, dann wird der Sektorzähler erhöht und der Omega Zähler auf 0 gesetzt.&lt;br /&gt;
&lt;br /&gt;
Ta = Zeit Anfangsvektor = proportional zu: sin (60-omega)&lt;br /&gt;
&lt;br /&gt;
Te = Zeit Endvektor = proportional zu: sin (omega)&lt;br /&gt;
&lt;br /&gt;
Da jedes Ausgangsmuster alle drei Wicklungen beeinflusst, braucht zur Erzeugung der benötigten Spannungen nur eine Berechnung der Schaltzeiten für alle drei Wicklungen stattfinden. Die Spannung in den anderen beiden Wicklungen ändern sich genauso. &lt;br /&gt;
&lt;br /&gt;
Da der induktive Widerstand der Motorwicklungen frequenzabhängig ist, muss die Motorspannung umgekehrt proportional zur Frequenz verändert werden. Dies wird durch Verkleinerung der Einschaltdauer der spannungsführenden Vektoren und Ausgabe eines Nullspannungsvektors (Muster 000 oder 111) erreicht.&lt;br /&gt;
&lt;br /&gt;
Ta = Zeit Anfangsvektor = proportional zu:  sin (60-omega)* Motorspannung in %&lt;br /&gt;
&lt;br /&gt;
Te = Zeit Endvektor = proportional zu:   sin (omega)* Motorspannung in %&lt;br /&gt;
&lt;br /&gt;
To = Zeit Nullspannungsvektor = Pulsperiode-(Zeit Anfangsvektor + Zeit Endvektor)&lt;br /&gt;
&lt;br /&gt;
Für eine bessere Symmetrie wird To halbiert und jeweils vor und nach den Spannungsvektoren ausgegeben. &lt;br /&gt;
Die Nullspannung kann mit dem Muster 000 oder 111 erreicht werden. Zur Minimierung der Schaltverluste in den FET´s wird das Nullspannungsmuster gewählt, bei welchem nur eine Halbbrücke umgeschaltet werden muss. Die Schaltvorgänge werden ebenfalls minimiert, wenn in zwei aufeinander folgenden Pulsperioden die Muster in umgekehrter Reihenfolge ausgegeben werden. Der Mittelwert der erzeugten Spannung wird hierdurch nicht verändert.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot;&lt;br /&gt;
|Nullspannungsvektor&lt;br /&gt;
|Anfangsvektor&lt;br /&gt;
|Endvektor&lt;br /&gt;
|Nullspannungsvektor&lt;br /&gt;
|Nullspannungsvektor&lt;br /&gt;
|Endvektor&lt;br /&gt;
|Anfangsvektor&lt;br /&gt;
|Nullspannungsvektor&lt;br /&gt;
|-&lt;br /&gt;
|000&lt;br /&gt;
|010&lt;br /&gt;
|110&lt;br /&gt;
|111&lt;br /&gt;
|111&lt;br /&gt;
|110&lt;br /&gt;
|010&lt;br /&gt;
|000&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Werden anstelle eines Motors drei im Dreieck geschaltete Widerstände angeschlossen erhält man folgenden Spannungsverlauf:&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Spannung_an_ohmschen_Widerstand.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Es ist zu erkennen, wie der Anteil der positiven Spannungsanteile mit jeder Pulsperiode (0,4ms oder 2 Einheiten lang) zunimmt.&lt;br /&gt;
&lt;br /&gt;
=== Programm für Atmel Mega 32 ===&lt;br /&gt;
Der Prozessor bekommt über 8 Eingänge (analog oder digital) die Steuerbefehle und gibt über parallele Ausgänge die Steuerbefehle an den Mega88 für die Raumzeigermodulation. Angesteuert wird auch ein LCD zur Anzeige vom Ist-Spannung, Ist-Strom, Ist-Drehzahl und Sollwerten.&lt;br /&gt;
&lt;br /&gt;
Da sich die Ausgangssignale nur relativ langsam ändern, wird der Prozessor mit 1Mhz internem Oszillator betrieben&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Timerinterrupts&#039;&#039;&#039;&lt;br /&gt;
Timer 0 = Hoch- und Rücklaufgeber. Sollwertintegraton, damit bei Sollwertsprüngen die Motordrehzahl langsam geändert wird. Der Eingangssollwert sollvh wird intergriert zum vorzeichenbehafteten Sollwert sollnh&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hauptprogrammablauf: &#039;&#039;&#039;&lt;br /&gt;
Einlesen des Sollwerts sollvh, Bildung des absoluten Sollwerts sollabs, Bildung des Richtungssignals und Bildung des Freigabesignals.&lt;br /&gt;
&lt;br /&gt;
Einlesen von Ist-Spannung, Ist-Strom, und analogen Sollwerten.&lt;br /&gt;
&lt;br /&gt;
Ausgaben an des LCD&lt;br /&gt;
&lt;br /&gt;
Messung der Ist-Drehzahl&lt;br /&gt;
&lt;br /&gt;
Und wieder nach oben in der Endlosschleife&lt;br /&gt;
&lt;br /&gt;
=== Programm für Atmel Mega 88 ===&lt;br /&gt;
Der Prozessor bekommt den Frequenzsollwert, den Spannungssollwert, die Drehrichtung und das Freigabesignal über parallele Eingänge übermittelt. Angesteuert werden die drei Halbbrücken (IN), die Freigabeeingänge der Brückentreiber (SD) über einen gemeinsamen Ausgang und zwei LED`s.&lt;br /&gt;
Hochgezählt wird im Programm der Zeiger für den aktuellen Stand Sinusschwingung am Ausgang (Omega), aufgeteilt in 6 Sektoren. Daraus berechnet werden die Einschaltzeiten der Halbbrücken für jeweils zwei PWM-Perioden (Pulsperioden, zur Unterscheidung von der Periode der Ausgangsspannung). &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Timerinterrupts&#039;&#039;&#039; &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Timer 1&#039;&#039;&#039; = Ausgabe der Ausgangsmuster.&lt;br /&gt;
 &lt;br /&gt;
Die Timerwerte werden im Hauptprogramm berechnet und in drei Arrays abgelegt (pzh[8]; pzl[8]; pm[8]).&lt;br /&gt;
 &lt;br /&gt;
Es wird der „pulszykluszaehler“ für die Ausgabe des gewünschten Ausgangsmusters über die dazugehörige Zeit von 0 bis 7 hochgezählt. 7 entspricht dem Ende der zweiten Pulsperiode. &lt;br /&gt;
&lt;br /&gt;
Pulszykluszaehler 0 ==&amp;gt; Nullspannungsvektor&lt;br /&gt;
&lt;br /&gt;
Pulszykluszaehler 1 ==&amp;gt; Anfangsvektorvektor&lt;br /&gt;
&lt;br /&gt;
Pulszykluszaehler 2 ==&amp;gt; Endvektor&lt;br /&gt;
&lt;br /&gt;
Pulszykluszaehler 3 ==&amp;gt; Nullspannungsvektor&lt;br /&gt;
&lt;br /&gt;
Pulszykluszaehler 4 ==&amp;gt; Nullspannungsvektor&lt;br /&gt;
&lt;br /&gt;
Pulszykluszaehler 5 ==&amp;gt; Endvektor&lt;br /&gt;
&lt;br /&gt;
Pulszykluszaehler 6 ==&amp;gt; Anfangsvektorvektor&lt;br /&gt;
&lt;br /&gt;
Pulszykluszaehler 7 ==&amp;gt; Nullspannungsvektor&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Timer 0&#039;&#039;&#039; = Zähler für dem Umlaufwinkel und für den aktuellen Sektor. Die Timerwerte sind in einer Tabelle gespeichert und werden im Abhängigkeit vom Sollwert  sollabs an den Timer gegeben Es wird omega bis 59 und sektor bis 6 hochgezählt.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hauptprogrammablauf:&#039;&#039;&#039;&lt;br /&gt;
Einlesen des Sollwerts sollabs, der Ausgangsspannung spg, des Richtungssignals richtung und des Freigabesignals enable&lt;br /&gt;
Laden der Timerwerte aus der Tabelle fbwfl[sollabs] für den Timer 0 zum Zählen von Omega und den Sektoren&lt;br /&gt;
Zwischenspeicherung von Omega und Sektor, damit während der Berechnungen mit den gleichen Werten gerechnet wird. Berechnung der Timerwerte für Timer 1: Ta, Te, To gemäss Raumzeigermodulation mit den dazugehörigen Ausgangsmustern. Die Werte für Sinus Omega 0 bis 59 sind in der Tabelle sin[omega] gespeichert, die Werte für Sinus (60-omega) in der Tabelle sinkomp[omega].&lt;br /&gt;
&lt;br /&gt;
Ta= (sinkomp[omega]*spannung[sollabs]);&lt;br /&gt;
&lt;br /&gt;
Te= (sin[omega]*spannung[sollabs]);&lt;br /&gt;
&lt;br /&gt;
To= ((1000-(Ta+Te))/2);&lt;br /&gt;
&lt;br /&gt;
Speicherung der Ausgangsmuster und Timerwerte für zwei Pulsperioden&lt;br /&gt;
 &lt;br /&gt;
Und wieder nach oben in der Endlosschleife&lt;br /&gt;
&lt;br /&gt;
== Funktionstest ==&lt;br /&gt;
=== Spannung an ohmschen Widerstand ===&lt;br /&gt;
Es wurde eine Zwischenkreisspannung von ca. 24V angelegt.&lt;br /&gt;
Am Ausgang des FU werden drei Widerstände 470 Ohm im Stern geschaltet. Die Spannung wird über einen Widerstand gegen den Sternpunkt der Widerstände gemessen.&lt;br /&gt;
&lt;br /&gt;
Je nach dem aktuellen Sektor sehen die Spanungsverläufe so oder invers aus.&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Spannug_an_ohmschen_Widerstand_P1020274a_.jpg|300px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Spannug_an_ohmschen_Widerstand_P1020265a_.jpg|300px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Motorstrom ===&lt;br /&gt;
&lt;br /&gt;
Hier das Ergebnis aller Bemühungen:&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Motorstrom_30Hz.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Motorstrom in einem angeschossenen Drehstrommotor über einen Shunt gemessen bei 30Hz Ausgangsfrequenz.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Testkandidaten.jpg|400px]]&lt;br /&gt;
&lt;br /&gt;
Hier die Testkandidaten, die alle thermischen Misshandlungen ausgehalten haben.&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
&lt;br /&gt;
* Einspeisung   [[Media:FU_Einspeisung.zip‎|download zip-File]]&lt;br /&gt;
 &lt;br /&gt;
* Leistungsteil [[Media:FU_Wechselrichter.zip‎|download zip-File]]&lt;br /&gt;
* Leistungsteil Schaltplan [[Media:FU_Wechselr_Schaltplan.zip‎|download zip-File]]&lt;br /&gt;
&lt;br /&gt;
* Steuerung     [[Media:FU_Steuerung.zip|download zip-File]]&lt;br /&gt;
‎&lt;br /&gt;
&lt;br /&gt;
== Verluste ==&lt;br /&gt;
&lt;br /&gt;
3 Stück IR2109 , 1 Stück Mega 8 , 1 Stück Mega 88 , 4 Stück IRFP150 verstarben in treuer Pflichterfüllung durch Unachtsamkeiten des Benutzers&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Umrichter von Uwe Scholz =&lt;br /&gt;
Steuerung und Bremsschopper sind weitgehend gleich geblieben, nur im Dickstromteil gab es größere Änderungen. Der mußte auch zweiseitig werden, da Drahtbrücken unter dem Kühlkörper nicht gegangen wären. &lt;br /&gt;
&lt;br /&gt;
Der Trafo ist auch eine Numer größer, 0,5W war mir gefühlsmäßig etwas zu wenig. Falls ich noch einen bauen sollte, dann würde ich aber schon wieder ein paar Sachen anders machen;-)&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Uwe_Scholz_1.jpg‎|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Uwe_Scholz_2.jpg‎|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Uwe_Scholz_3.jpg‎|400px]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Uwe_Scholz_4.jpg‎|400px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
= Umrichter von Patrick Leube = &lt;br /&gt;
Die Steuerung wurde über zwei Atmega 88 realisiert.&lt;br /&gt;
Die sechspuls Brückenschaltung ist etwas Abgespeckt worden.&lt;br /&gt;
Da dieser Umrichter für Akkupacks von 36V-60V ausgelegt wurde muste noch eine &amp;quot;Netzteil&amp;quot; gebastelt werden das 15V und 5V generiert.&lt;br /&gt;
Die Bedinung erfolgt über Taster für Sollwertvorgabe +/- RUN / STOP.&lt;br /&gt;
Als LCD kam ein 4*20 zum Einsatz.&lt;br /&gt;
&lt;br /&gt;
Verluste: 1* LT1074HV = 12€ &lt;br /&gt;
&lt;br /&gt;
Da dieses Projekt mein erstes wirkliches Projekt mit µC und Elektronik im tieferen Sinne war möchte mich an dieser stelle auch nochmal bei Axel für seine Unterstützung bedanken.&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Patrick_1.jpg|300px]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:FU_Patrick_2.jpg|300px]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Projekte]]&lt;br /&gt;
[[Kategorie:Leistungselektronik]]&lt;br /&gt;
[[Category:1. Wettbewerb]]&lt;br /&gt;
[[Kategorie:Spannungsversorgung und Energiequellen]]&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;diff=57108</id>
		<title>AVR-GCC-Tutorial/Der UART</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR-GCC-Tutorial/Der_UART&amp;diff=57108"/>
		<updated>2011-05-09T05:26:59Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: /* Software-UART */  Link aktualisiert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Über den [[UART]] kann ein [[AVR]] leicht mit einer [[RS-232]]-Schnittstelle eines PC oder sonstiger Geräte mit &amp;quot;[[seriell]]er Schnittstelle&amp;quot; verbunden werden. &lt;br /&gt;
&lt;br /&gt;
== Allgemeines zum UART ==&lt;br /&gt;
&lt;br /&gt;
Mögliche Anwendungen des UART:&lt;br /&gt;
&lt;br /&gt;
;Debug-Schnittstelle: z.&amp;amp;nbsp;B. zur Anzeige von Zwischenergebnissen (&amp;quot;printf-debugging&amp;quot; - hier besser &amp;quot;Logging&amp;quot; oder &amp;quot;UART-debugging&amp;quot;) über [[RS-232]] auf einem PC. Auf dem Rechner reicht dazu ein [[RS-232#Terminalprogramme|Terminalprogramm]] (MS-Windows: Hyperterm oder besser [https://sites.google.com/site/terminalbpp/], [http://www.der-hammer.info/terminal/ HTerm]; Unix/Linux z.&amp;amp;nbsp;B. minicom). Ein direkter Anschluss ist aufgrund unterschiedlicher Pegel nicht möglich, jedoch sind entsprechende Schnittstellen-ICs wie z.&amp;amp;nbsp;B. ein MAX232 günstig und leicht zu integrieren. Rechner ohne serielle Schnittstelle können über fertige USB-seriell-Adapter angeschlossen werden. &lt;br /&gt;
;Mensch-Maschine Schnittstelle: z.&amp;amp;nbsp;B. Konfiguration und Statusabfrage über eine &amp;quot;Kommandozeile&amp;quot; oder Menüs (siehe z.&amp;amp;nbsp;B. Forumsbeitrag [http://www.mikrocontroller.net/topic/52985 Auswertung RS232-Befehle] und Artikel [[Tinykon]]) &lt;br /&gt;
;Übertragen von gespeicherten Werten: z.&amp;amp;nbsp;B. bei einem Datenlogger&lt;br /&gt;
;Anschluss von Geräten: mit serieller Schnittstelle (z.&amp;amp;nbsp;B. (Funk-)Modems, Mobiltelefone, Drucker, Sensoren, &amp;quot;intelligente&amp;quot; LC-Displays, GPS-Empfänger). &lt;br /&gt;
;&amp;quot;Feldbusse&amp;quot;: auf RS485/RS422-Basis mittels entsprechenden Bustreiberbausteinen (z.&amp;amp;nbsp;B. MAX485)&lt;br /&gt;
;DMX, Midi: etc.&lt;br /&gt;
;LIN-Bus: &#039;&#039;&#039;L&#039;&#039;&#039;ocal &#039;&#039;&#039;I&#039;&#039;&#039;nterconnect &#039;&#039;&#039;N&#039;&#039;&#039;etwork: Preiswerte Sensoren/Aktoren in der Automobiltechnik und darüber hinaus&lt;br /&gt;
&lt;br /&gt;
Einige AVR-Controller haben ein bis zwei vollduplexfähige UART (&#039;&#039;&#039;U&#039;&#039;&#039;niversal &#039;&#039;&#039;A&#039;&#039;&#039;synchronous &#039;&#039;&#039;R&#039;&#039;&#039;eceiver and &#039;&#039;&#039;T&#039;&#039;&#039;ransmitter) schon eingebaut (&amp;quot;Hardware-UART&amp;quot;). &lt;br /&gt;
Übrigens: Vollduplex heißt nichts anderes, als dass der Baustein gleichzeitig senden und empfangen kann.&lt;br /&gt;
&lt;br /&gt;
Neuere AVRs (ATmega, ATtiny) verfügen über einen bis vier U&#039;&#039;&#039;S&#039;&#039;&#039;ART(s), dieser unterscheidet sich vom UART hauptsächlich durch interne FIFO-Puffer für Ein- und Ausgabe und erweiterte Konfigurationsmöglichkeiten. Die Puffergröße ist allerdings nur 1 Byte.&lt;br /&gt;
&lt;br /&gt;
== Die Hardware ==&lt;br /&gt;
&lt;br /&gt;
Der UART basiert auf normalem TTL-Pegel mit 0V (logisch 0) und 5V (logisch 1). Die Schnittstellenspezifikation für RS-232 definiert jedoch -3V ... -12V (logisch 1) und&lt;br /&gt;
+3 ... +12V (logisch 0). Daher muss der Signalaustausch zwischen AVR und Partnergerät invertiert werden. Für die Anpassung der Pegel und das Invertieren der Signale gibt es fertige Schnittstellenbausteine. Der bekannteste davon ist wohl der MAX232. &lt;br /&gt;
&amp;lt;!-- &amp;quot;Hackerloesung&amp;quot; auskommentiert - nicht so gut in einem &amp;quot;Einsteiger-Tutorial&amp;quot; - mthomas&lt;br /&gt;
Allerdings kostet der auch wieder Geld und benötigt&lt;br /&gt;
zusätzlich immerhin 4 externe Elkos.&lt;br /&gt;
&lt;br /&gt;
Die in den PC eingebauten Schnittstellen vertragen ohne Klagen auch den TTL-Pegel vom AVR. Allerdings müssen wir immer noch die Signale invertieren. Im einfachtesn Fall verwenden wir dazu jeweils einen einfachen NPN-Transistor und 2 Widerstände. Näheres dazu erfahrt ihr in den folgenden Übungen.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Streikt die Kommunikation per UART, so ist oft eine fehlerhafte Einstellung der Baudrate die Ursache. Die Konfiguration auf eine bestimmte Baudrate ist abhängig von der Taktfrequenz des Controllers. Gerade bei neu aufgebauten Schaltungen (bzw. neu gekauften Controllern) sollte man sich daher noch einmal vergewissern, dass der Controller auch tatsächlich mit der vermuteten Taktrate arbeitet und nicht z.&amp;amp;nbsp;B. den bei einigen Modellen werksseitig eingestellten internen [[Oszillator]] statt eines externen Quarzes nutzt. Die Werte der verschiedenen fuse-bits im Fehlerfall also beispielsweise mit &#039;&#039;[[AVRDUDE]]&#039;&#039; kontrollieren und falls nötig anpassen. Grundsätzlich empfiehlt sich auch immer ein Blick in die [[AVR_Checkliste]].&lt;br /&gt;
&lt;br /&gt;
== Die UART-Register ==&lt;br /&gt;
&lt;br /&gt;
Der UART wird über vier separate Register angesprochen. Die USARTs der ATMEGAs verfügen über mehrere zusätzliche Konfigurationsregister. Das Datenblatt gibt darüber Auskunft. Die folgende Tabelle gibt nur die Register für die UARTs der ATmega8/16/32 u.ä. wieder.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;UCSRA&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;U&#039;&#039;&#039;ART &#039;&#039;&#039;C&#039;&#039;&#039;ontrol and &#039;&#039;&#039;S&#039;&#039;&#039;tatus &#039;&#039;&#039;R&#039;&#039;&#039;egister &#039;&#039;&#039;A&#039;&#039;&#039;.&amp;lt;br /&amp;gt;&lt;br /&gt;
Hier teilt uns der UART mit, was er gerade so macht.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
! Bit&lt;br /&gt;
| 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|- &lt;br /&gt;
! Name&lt;br /&gt;
| &#039;&#039;&#039;RXC&#039;&#039;&#039;|| &#039;&#039;&#039;TXC&#039;&#039;&#039;|| &#039;&#039;&#039;UDRE&#039;&#039;&#039;|| &#039;&#039;&#039;FE&#039;&#039;&#039;|| &#039;&#039;&#039;DOR&#039;&#039;&#039;|| &#039;&#039;&#039;PE&#039;&#039;&#039;|| &#039;&#039;&#039;U2X&#039;&#039;&#039;|| &#039;&#039;&#039;MPCM&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
! R/W&lt;br /&gt;
| R|| R/W|| R|| R|| R|| R|| R/W|| R/W&lt;br /&gt;
|- &lt;br /&gt;
! Initialwert&lt;br /&gt;
| 0|| 0|| 1|| 0|| 0|| 0|| 0|| 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RXC&#039;&#039;&#039; (UART Receive Complete)&lt;br /&gt;
:Dieses Bit wird vom AVR gesetzt, wenn ein empfangenes Zeichen vom Empfangs-Schieberegister in das Empfangs-Datenregister transferiert wurde.&lt;br /&gt;
:Das Zeichen muss nun schnellstmöglich aus dem Datenregister ausgelesen werden. Falls dies nicht erfolgt, bevor ein weiteres Zeichen komplett empfangen wurde, wird eine Überlauf-Fehlersituation eintreten. Mit dem Auslesen des Datenregisters wird das Bit automatisch gelöscht.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TXC&#039;&#039;&#039; (UART Transmit Complete)&lt;br /&gt;
:Dieses Bit wird vom AVR gesetzt, wenn das im Sende-Schieberegister befindliche Zeichen vollständig ausgegeben wurde und kein weiteres Zeichen im Sendedatenregister ansteht. Dies bedeutet also, dass die Kommunikation vollumfänglich abgeschlossen ist.&lt;br /&gt;
:Dieses Bit ist wichtig bei Halbduplex-Verbindungen, wenn das Programm nach dem Senden von Daten auf Empfang schalten muss. Im Vollduplexbetrieb brauchen wir dieses Bit nicht zu beachten.&lt;br /&gt;
:Das Bit wird nur dann automatisch gelöscht, wenn der entsprechende Interrupthandler aufgerufen wird, ansonsten müssen wir das Bit selber löschen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UDRE&#039;&#039;&#039; (&#039;&#039;&#039;U&#039;&#039;&#039;ART &#039;&#039;&#039;D&#039;&#039;&#039;ata &#039;&#039;&#039;R&#039;&#039;&#039;egister &#039;&#039;&#039;E&#039;&#039;&#039;mpty)&lt;br /&gt;
:Dieses Bit zeigt an, ob der Sendepuffer bereit ist, um ein zu sendendes Zeichen aufzunehmen. Das Bit wird vom AVR gesetzt (1), wenn der Sendepuffer leer ist. Es wird gelöscht (0), wenn ein Zeichen im Sendedatenregister vorhanden ist und noch nicht in das Sende-Schieberegister übernommen wurde. Atmel empfiehlt aus Kompatibilitätsgründen mit kommenden µC, UDRE auf 0 zu setzen, wenn das UCSRA Register beschrieben wird.&lt;br /&gt;
:Das Bit wird automatisch gelöscht, wenn ein Zeichen in das Sendedatenregister geschrieben wird.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;FE&#039;&#039;&#039; (&#039;&#039;&#039;F&#039;&#039;&#039;raming &#039;&#039;&#039;E&#039;&#039;&#039;rror)&lt;br /&gt;
:Dieses Bit wird vom AVR gesetzt, wenn der UART einen Zeichenrahmenfehler detektiert, d.h. wenn das Stopbit eines empfangenen Zeichens 0 ist.&lt;br /&gt;
:Das Bit wird automatisch gelöscht, wenn das Stopbit des empfangenen Zeichens 1 ist.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;DOR&#039;&#039;&#039; (&#039;&#039;&#039;D&#039;&#039;&#039;ata &#039;&#039;&#039;O&#039;&#039;&#039;ver &#039;&#039;&#039;R&#039;&#039;&#039;un)&lt;br /&gt;
:Dieses Bit wird vom AVR gesetzt, wenn unser Programm das im Empfangsdatenregister bereit liegende Zeichen nicht abholt bevor das nachfolgende Zeichen komplett empfangen wurde.&lt;br /&gt;
:Das nachfolgende Zeichen wird verworfen.&lt;br /&gt;
:Das Bit wird automatisch gelöscht, wenn das empfangene Zeichen in das Empfangsdatenregister transferiert werden konnte.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;PE&#039;&#039;&#039; (&#039;&#039;&#039;P&#039;&#039;&#039;arity &#039;&#039;&#039;E&#039;&#039;&#039;rror&#039;&#039;&#039;)&lt;br /&gt;
:Dieses Bit wird vom AVR gesetzt, wenn das im Empfangsdatenregister bereit liegende Zeichen eine Paritätsfehler aufweist.&lt;br /&gt;
:Das Bit wird automatisch gelöscht, wenn das empfangene Zeichen in das Empfangsdatenregister transferiert werden konnte.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;U2X&#039;&#039;&#039; (Double the transmission speed)&lt;br /&gt;
:Dieses Bit wird lediglich im asynchronen Modus genutzt. Im synchronen Modus ist es 0 zu setzen. Wird das Bit gesetzt, so wird der Baudraten Divisor von 16 auf 8 reduziert, was einer Verdopplung der Transferrate gleich kommt.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;MPCM&#039;&#039;&#039; (&#039;&#039;&#039;M&#039;&#039;&#039;ulti &#039;&#039;&#039;P&#039;&#039;&#039;rozessor &#039;&#039;&#039;C&#039;&#039;&#039;ommunication &#039;&#039;&#039;M&#039;&#039;&#039;ode)&lt;br /&gt;
:Dieses Bit aktiviert die Multi-Prozessor-Kommunikation. Jeder eintreffende Frame der keine Adressinformation enthält wird dadurch ignoriert.&lt;br /&gt;
&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;UCSRB &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;U&#039;&#039;&#039;ART &#039;&#039;&#039;C&#039;&#039;&#039;ontrol and &#039;&#039;&#039;S&#039;&#039;&#039;tatus &#039;&#039;&#039;R&#039;&#039;&#039;egister &#039;&#039;&#039;B&#039;&#039;&#039;.&amp;lt;br /&amp;gt;&lt;br /&gt;
In diesem Register stellen wir ein, wie wir den UART verwenden möchten.&amp;lt;br /&amp;gt;&lt;br /&gt;
Das Register ist wie folgt aufgebaut:&lt;br /&gt;
&lt;br /&gt;
{|  class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
! Bit&lt;br /&gt;
| 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|- &lt;br /&gt;
! Name&lt;br /&gt;
| &#039;&#039;&#039;RXCIE&#039;&#039;&#039;|| &#039;&#039;&#039;TXCIE&#039;&#039;&#039;|| &#039;&#039;&#039;UDRIE&#039;&#039;&#039;|| &#039;&#039;&#039;RXEN&#039;&#039;&#039;|| &#039;&#039;&#039;TXEN&#039;&#039;&#039;|| &#039;&#039;&#039;UCSZ2&#039;&#039;&#039;|| &#039;&#039;&#039;RXB8&#039;&#039;&#039;|| &#039;&#039;&#039;TXB8&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
! R/W&lt;br /&gt;
| R/W|| R/W|| R/W|| R/W|| R/W|| R/W|| R|| R/W&lt;br /&gt;
|- &lt;br /&gt;
! Initialwert&lt;br /&gt;
| 0|| 0|| 0|| 0|| 0|| 0|| 0|| 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RXCIE&#039;&#039;&#039; (&#039;&#039;&#039;RX&#039;&#039;&#039; &#039;&#039;&#039;C&#039;&#039;&#039;omplete &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;E&#039;&#039;&#039;nable)&lt;br /&gt;
:Wenn dieses Bit gesetzt ist, wird ein UART RX Complete Interrupt ausgelöst, wenn ein Zeichen vom UART empfangen wurde. Das Global Enable Interrupt Flag muss selbstverständlich auch gesetzt sein.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TXCIE&#039;&#039;&#039; (&#039;&#039;&#039;TX&#039;&#039;&#039; &#039;&#039;&#039;C&#039;&#039;&#039;omplete &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;E&#039;&#039;&#039;nable)&lt;br /&gt;
:Wenn dieses Bit gesetzt ist, wird ein UART TX Complete Interrupt ausgelöst, wenn ein Zeichen vom UART gesendet wurde. Das Global Enable Interrupt Flag muss selbstverständlich auch gesetzt sein.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UDRIE&#039;&#039;&#039; (&#039;&#039;&#039;U&#039;&#039;&#039;ART &#039;&#039;&#039;D&#039;&#039;&#039;ata &#039;&#039;&#039;R&#039;&#039;&#039;egister &#039;&#039;&#039;E&#039;&#039;&#039;mpty &#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;E&#039;&#039;&#039;nable)&lt;br /&gt;
:Wenn dieses Bit gesetzt ist, wird ein UART Datenregister Leer Interrupt ausgelöst, wenn der UART wieder bereit ist um ein neues zu sendendes Zeichen zu übernehmen. Das Global Enable Interrupt Flag muss selbstverständlich auch gesetzt sein.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RXEN&#039;&#039;&#039; (&#039;&#039;&#039;R&#039;&#039;&#039;eceiver &#039;&#039;&#039;E&#039;&#039;&#039;nable)&lt;br /&gt;
:Nur wenn dieses Bit gesetzt ist, arbeitet der Empfänger des UART überhaupt. Wenn das Bit nicht gesetzt ist, kann der entsprechende Pin des AVR als normaler I/O-Pin verwendet werden. &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TXEN&#039;&#039;&#039; (&#039;&#039;&#039;T&#039;&#039;&#039;ransmitter &#039;&#039;&#039;E&#039;&#039;&#039;nable)&lt;br /&gt;
:Nur wenn dieses Bit gesetzt ist, arbeitet der Sender des UART überhaupt. Wenn das Bit nicht gesetzt ist, kann der entsprechende Pin des AVR als normaler I/O-Pin verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UCSZ2&#039;&#039;&#039; (Characters Size)&lt;br /&gt;
:Dieses Bit setzt in Verbindung mit dem UCSZ1:0 Bits im UCSRC Register die Anzahl von Datenbits eines Frames beim Empfang oder Senden.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;RXB8&#039;&#039;&#039; (Receive Data Bit 8)&lt;br /&gt;
:Wenn das vorher erwähnte CHR9-Bit gesetzt ist, dann enthält dieses Bit das 9. Datenbit eines empfangenen Zeichens.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TXB8&#039;&#039;&#039; (Transmit Data Bit 8)&lt;br /&gt;
:Wenn das vorher erwähnte CHR9-Bit gesetzt ist, dann muss in dieses Bit das 9. Bit des zu sendenden Zeichens eingeschrieben werden bevor das eigentliche Datenbyte in das Datenregister geschrieben wird.&lt;br /&gt;
|-&lt;br /&gt;
| &#039;&#039;&#039;UCSRC &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;U&#039;&#039;&#039;ART &#039;&#039;&#039;C&#039;&#039;&#039;ontrol and &#039;&#039;&#039;S&#039;&#039;&#039;tatus &#039;&#039;&#039;R&#039;&#039;&#039;egister &#039;&#039;&#039;C&#039;&#039;&#039;.&amp;lt;br /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|  class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
! Bit&lt;br /&gt;
| 7 || 6 || 5 || 4 || 3 || 2 || 1 || 0&lt;br /&gt;
|- &lt;br /&gt;
! Name&lt;br /&gt;
| &#039;&#039;&#039;URSEL&#039;&#039;&#039;|| &#039;&#039;&#039;UMSEL&#039;&#039;&#039;|| &#039;&#039;&#039;UPM1&#039;&#039;&#039;|| &#039;&#039;&#039;UPM0&#039;&#039;&#039;|| &#039;&#039;&#039;USBS&#039;&#039;&#039;|| &#039;&#039;&#039;UCSZ1&#039;&#039;&#039;|| &#039;&#039;&#039;UCSZ0&#039;&#039;&#039;|| &#039;&#039;&#039;UCPOL&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
! R/W&lt;br /&gt;
| R/W|| R/W|| R/W|| R/W|| R/W|| R/W|| R/W|| R/W&lt;br /&gt;
|- &lt;br /&gt;
! Initialwert&lt;br /&gt;
| 1|| 0|| 0|| 0|| 0|| 1|| 1|| 0&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;URSEL&#039;&#039;&#039; (Register Select)&lt;br /&gt;
:Dieses Bit selektiert die Auswahl des UCSRC- bzw. des UBRRH Registers. Beim Lesen von UCSRC wird es als 1 gelesen. Beim Schreiben auf UCSRC muss es auf 1 gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
:Achtung: Manche Prozessoren verfügen über dieses Bit, andere wiederrum nicht. Was hat es damit auf sich?&amp;lt;br&amp;gt;Um Zugriffsadressen einzusparen, wurde von Atmel ein etwas seltsamer Weg gewählt. Das UCSRC Register und das High-Byte des Baudratenregisters teilen sich dieselbe Registeradresse! Um der Hardware mitzuteilen, welche Bedeutung ein zugewiesener Wert haben soll, entweder neue Belegung des Baudratenregisters oder eben Konfiguration des UCSRC Registers, dient dieses Bit. Ist es nicht gesetzt, dann wird eine Zuweisung immer als Zuweisung an das High-Byte des Baudratenregisters angesehen, selbst wenn das so nicht beabsichtigt war. Nur dann wenn dieses Bit gesetzt ist, dann wird eine Zuweisung auch tatsächlich als eine Zuweisung an das UCSRC Register gewertet und die Konfiguration verändert. Lässt man das Bit irrtümlich weg, dann verursacht eine Zuweisung an UCSRC eine Veränderung der Baudrateneinstellung!&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UMSEL&#039;&#039;&#039; (USART Mode Select)&lt;br /&gt;
:Durch dieses Bit kann eine asynchrone oder synchrone Übertragung eingestellt werden. Durch Setzen des Bits wird eine synchrone Übertragung eingestellt.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UPM1:0&#039;&#039;&#039; (Parity Mode)&lt;br /&gt;
{|  class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;UPM1&#039;&#039;&#039;|| &#039;&#039;&#039;UPM0&#039;&#039;&#039;|| &#039;&#039;&#039;Parity Mode&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| 0|| 0|| Disabled&lt;br /&gt;
|- &lt;br /&gt;
| 0|| 1|| Reserved&lt;br /&gt;
|- &lt;br /&gt;
| 1|| 0|| Enabled, Even Priority&lt;br /&gt;
|- &lt;br /&gt;
| 1|| 1|| Enabled, OddPriority&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;USBS&#039;&#039;&#039; (&#039;&#039;&#039;U&#039;&#039;&#039;SART &#039;&#039;&#039;S&#039;&#039;&#039;top &#039;&#039;&#039;B&#039;&#039;&#039;it &#039;&#039;&#039;S&#039;&#039;&#039;elect)&lt;br /&gt;
:Diese Bits setzen die Anzahl der zu sendenden Stopbits eines Frames. Beim Setzen werden 2 Stopbits übertragen, andernfalls nur 1 Stopbit.&lt;br /&gt;
{|  class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;USBS&#039;&#039;&#039;|| &#039;&#039;&#039;Anzahl der Stop Bits&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
|  0|| 1&lt;br /&gt;
|- &lt;br /&gt;
|  1|| 2&lt;br /&gt;
&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UCSZ1:0&#039;&#039;&#039; (Character Size)&lt;br /&gt;
:Diese Bits setzen in Verbindung mit UCSZ2 aus dem UCSRB Register die Anzahl der Datenbits eines Frames.&lt;br /&gt;
:Diese Bits setzen den entsprechenden Paritätsmodus.&lt;br /&gt;
{|  class=&amp;quot;wikitable&amp;quot; style=&amp;quot;text-align:center&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;UCSZ2&#039;&#039;&#039;|| &#039;&#039;&#039;UCSZ1&#039;&#039;&#039;|| &#039;&#039;&#039;UCSZ0&#039;&#039;&#039;|| &#039;&#039;&#039;Character Size&#039;&#039;&#039;&lt;br /&gt;
|- &lt;br /&gt;
| 0|| 0|| 0|| 5-Bit&lt;br /&gt;
|- &lt;br /&gt;
| 0|| 0|| 1|| 6-Bit&lt;br /&gt;
|- &lt;br /&gt;
| 0|| 1|| 0|| 7-Bit&lt;br /&gt;
|- &lt;br /&gt;
| 0|| 1|| 1|| 8-Bit&lt;br /&gt;
|- &lt;br /&gt;
| 1|| 0|| 0|| Reserved&lt;br /&gt;
|- &lt;br /&gt;
| 1|| 0|| 1|| Reserved&lt;br /&gt;
|- &lt;br /&gt;
| 1|| 1|| 0|| Reserved&lt;br /&gt;
|- &lt;br /&gt;
| 1|| 1|| 1|| 9-Bit&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;UCPOL&#039;&#039;&#039; (Clock Polarity)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;UDR&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;U&#039;&#039;&#039;ART &#039;&#039;&#039;D&#039;&#039;&#039;ata &#039;&#039;&#039;R&#039;&#039;&#039;egister.&amp;lt;br /&amp;gt;&lt;br /&gt;
Hier werden Daten zwischen UART und CPU übertragen. Da der UART im&lt;br /&gt;
Vollduplexbetrieb gleichzeitig empfangen und senden kann, handelt es sich&lt;br /&gt;
hier physikalisch um 2 Register, die aber über die gleiche I/O-Adresse&lt;br /&gt;
angesprochen werden. Je nachdem, ob ein Lese- oder ein Schreibzugriff auf&lt;br /&gt;
den UART erfolgt wird automatisch das richtige UDR angesprochen.&lt;br /&gt;
|- &lt;br /&gt;
| &#039;&#039;&#039;UBRR&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;U&#039;&#039;&#039;ART &#039;&#039;&#039;B&#039;&#039;&#039;aud &#039;&#039;&#039;R&#039;&#039;&#039;ate &#039;&#039;&#039;R&#039;&#039;&#039;egister.&amp;lt;br /&amp;gt;&lt;br /&gt;
In diesem Register müssen wir dem UART mitteilen, wie schnell wir gerne kommunizieren möchten. Der Wert, der in dieses Register geschrieben werden muss, errechnet sich nach folgender Formel (wenn U2X Bit 0 gesetzt ist):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
\mathrm{UBRR} = \frac{\mathrm{Taktfrequenz}}{\mathrm{Baudrate} \cdot 16} - 1&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es sind Baudraten bis über 115200 Baud möglich, je nach Controller und CPU-Frequenz. Siehe Datenblatt.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== UART initialisieren ==&lt;br /&gt;
&lt;br /&gt;
Wir wollen nun Daten mit dem UART auf die serielle Schnittstelle ausgeben. Dazu müssen wir den UART zuerst mal initialisieren. Dazu setzen wir je nach gewünschter Funktionsweise die benötigten Bits im &#039;&#039;&#039;U&#039;&#039;&#039;ART &#039;&#039;&#039;C&#039;&#039;&#039;ontrol &#039;&#039;&#039;R&#039;&#039;&#039;egister.&lt;br /&gt;
&lt;br /&gt;
Da wir vorerst nur senden möchten und noch keine Interrupts auswerten wollen, gestaltet sich die Initialisierung wirklich sehr einfach, da wir lediglich das &#039;&#039;&#039;Transmitter Enable&#039;&#039;&#039; Bit setzen müssen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
  UCSRB |= (1&amp;lt;&amp;lt;TXEN);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Neuere AVRs mit USART haben mehrere Konfigurationsregister und erfordern eine etwas andere Konfiguration. Für einen ATmega16 z.&amp;amp;nbsp;B.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
  UCSRB |= (1&amp;lt;&amp;lt;TXEN);                           // UART TX einschalten&lt;br /&gt;
  UCSRC = (1&amp;lt;&amp;lt;URSEL)|(1 &amp;lt;&amp;lt; UCSZ1)|(1 &amp;lt;&amp;lt; UCSZ0); // Asynchron 8N1&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nun ist noch das Baudratenregister &#039;&#039;&#039;UBRR&#039;&#039;&#039; einzustellen. Bei neueren AVRs besteht es aus zwei Registern &#039;&#039;&#039;UBRRL&#039;&#039;&#039; und &#039;&#039;&#039;UBRRH&#039;&#039;&#039;. Der Wert dafür ergibt sich aus der angegebenen Formel durch Einsetzen der Taktfrequenz und der gewünschten Übertragungsrate. Das Berechnen der Formel wird dem [[C-Präprozessor|Präprozessor]] überlassen. Dabei ist zu beachten, dass der Präprozessor keine Floating Point Ergebnisse liefert, sondern Integer Ergebnisse. Das bedeutet, dass wenn durch Division auf einen Integer Wert 1.99 zugewiesen wird, 0.99 abgeschnitten werden und das Ergebnis 1.0 ist - obwohl 2.0 viel näher wäre. Aus diesem Grund kann man sich einem kleinen Trick bedienen, indem vor der eigentlichen Division bei der Zuweisung die Hälfte des Wertes dazu addiert wird. Allgemein formuliert bedeutet das: &amp;lt;c&amp;gt;int i = ( a + b/2 ) / b;&amp;lt;/c&amp;gt; Dies wird in der unten angegebenen Berechnung von UBRR_VAL ausgenutzt um den Fehler zu minimieren. &lt;br /&gt;
&lt;br /&gt;
Eine ausführliche Erklärung zum &#039;&#039;cleveren Runden&#039;&#039; findet sich in der Forumsdiskussion [http://www.mikrocontroller.net/topic/170617#1631916]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/* &lt;br /&gt;
  UART-Init: &lt;br /&gt;
Berechnung des Wertes für das Baudratenregister &lt;br /&gt;
aus Taktrate und gewünschter Baudrate&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#ifndef F_CPU&lt;br /&gt;
/* In neueren Version der WinAVR/Mfile Makefile-Vorlage kann&lt;br /&gt;
   F_CPU im Makefile definiert werden, eine nochmalige Definition&lt;br /&gt;
   hier wuerde zu einer Compilerwarnung fuehren. Daher &amp;quot;Schutz&amp;quot; durch&lt;br /&gt;
   #ifndef/#endif &lt;br /&gt;
&lt;br /&gt;
   Dieser &amp;quot;Schutz&amp;quot; kann zu Debugsessions führen, wenn AVRStudio &lt;br /&gt;
   verwendet wird und dort eine andere, nicht zur Hardware passende &lt;br /&gt;
   Taktrate eingestellt ist: Dann wird die folgende Definition &lt;br /&gt;
   nicht verwendet, sondern stattdessen der Defaultwert (8 MHz?) &lt;br /&gt;
   von AVRStudio - daher Ausgabe einer Warnung falls F_CPU&lt;br /&gt;
   noch nicht definiert: */&lt;br /&gt;
#warning &amp;quot;F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000&amp;quot;&lt;br /&gt;
#define F_CPU 4000000UL  // Systemtakt in Hz - Definition als unsigned long beachten &lt;br /&gt;
                         // Ohne ergeben sich unten Fehler in der Berechnung&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#define BAUD 9600UL      // Baudrate&lt;br /&gt;
&lt;br /&gt;
// Berechnungen&lt;br /&gt;
#define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1)   // clever runden&lt;br /&gt;
#define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1)))     // Reale Baudrate&lt;br /&gt;
#define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler.&lt;br /&gt;
&lt;br /&gt;
#if ((BAUD_ERROR&amp;lt;990) || (BAUD_ERROR&amp;gt;1010))&lt;br /&gt;
  #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! &lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Makros sind sehr praktisch, da sie sowohl automatisch den Wert für UBRR als auch den Fehler in der generierten Baudrate berechnen und im Falle einer Überschreitung (+/-1%) einen Fehler und somit Abbruch im Compilerablauf generieren. Damit können viele Probleme mit &amp;quot;UART sendet komische Zeichen&amp;quot; vermieden werden. Ausserdem kann man mühelos die Einstellung an eine neue Taktfrequenz bzw. Baudrate anpassen, ohne selber rechnen oder in Tabellen nachschlagen zu müssen.&lt;br /&gt;
&lt;br /&gt;
Inzwischen gibt es in der avr-libc Makros für obige Berechnung der UBRR Registerwerte aus Taktrate F_CPU und Baudrate BAUD in der Includedatei &amp;lt;util/setbaud.h&amp;gt; ([http://www.nongnu.org/avr-libc/user-manual/group__util__setbaud.html]). Der berechnete Wert kann dann einfach über das Makro UBRR_VALUE aufgerufen werden.&lt;br /&gt;
&lt;br /&gt;
Die eigentliche Initialisierung der UART Register kann im Hauptprogramm main() vorgenommen werden. Öfters wird jedoch eine Funktion z.&amp;amp;nbsp;B. uart_init() dafür geschrieben, die in der eigenen Codesammlung in mehreren Projekten verwendet werden kann.&lt;br /&gt;
&lt;br /&gt;
Für einige AVR (z.&amp;amp;nbsp;B. ATmega169, ATmega48/88/168, AT90CAN jedoch nicht für z.&amp;amp;nbsp;B. ATmega16/32, ATmega128, ATtiny2313) wird durch die Registerdefinitionen der avr-libc (io*.h) auch für Controller mit zwei UBRR-Registern (UBRRL/UBRRH) ein UBRR bzw. UBRR0 als &amp;quot;16-bit-Register&amp;quot; definiert und man kann den Wert direkt per UBRR = UBRR_VAL zuweisen. Intern werden dann zwei Zuweisungen für UBRRH und UBRRL generiert. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/* UART-Init Bsp. ATmega48 */&lt;br /&gt;
&lt;br /&gt;
void uart_init(void)&lt;br /&gt;
{&lt;br /&gt;
  UBRR0 = UBRR_VAL;&lt;br /&gt;
  UCSR0B |= (1&amp;lt;&amp;lt;TXEN0);&lt;br /&gt;
  // Frame Format: Asynchron 8N1&lt;br /&gt;
  UCSR0C = (1&amp;lt;&amp;lt;UCSZ01)|(1&amp;lt;&amp;lt;UCSZ00);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die einzelne Anweisung ist nicht bei allen Controllern möglich, da die beiden Register nicht bei allen aufeinanderfolgende Addressen aufweisen. Die getrennte Zuweisung an UBRRH und UBRRL wie im nächsten Beispiel gezeigt, ist universeller und portabler und daher vorzuziehen. Wichtig ist, dass UBRRH &#039;&#039;&#039;vor&#039;&#039;&#039; UBRRL geschrieben wird:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/* UART-Init Bsp. ATmega16 */&lt;br /&gt;
&lt;br /&gt;
void uart_init(void)&lt;br /&gt;
{&lt;br /&gt;
  UCSRB |= (1&amp;lt;&amp;lt;TXEN);  // UART TX einschalten&lt;br /&gt;
  UCSRC = (1&amp;lt;&amp;lt;URSEL)|(1&amp;lt;&amp;lt;UCSZ1)|(1&amp;lt;&amp;lt;UCSZ0);  // Asynchron 8N1 &lt;br /&gt;
&lt;br /&gt;
  UBRRH = UBRR_VAL &amp;gt;&amp;gt; 8;&lt;br /&gt;
  UBRRL = UBRR_VAL &amp;amp; 0xFF;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Siehe auch:&lt;br /&gt;
* [http://www.wormfood.net/avrbaudcalc.php WormFood&#039;s AVR Baud Rate Calculator] online.&lt;br /&gt;
* [http://www.gjlay.de/helferlein/avr-uart-rechner.html AVR Baudraten-Rechner] in JavaScript&lt;br /&gt;
&lt;br /&gt;
== Senden mit dem UART ==&lt;br /&gt;
&lt;br /&gt;
=== Senden einzelner Zeichen ===&lt;br /&gt;
&lt;br /&gt;
Um nun ein Zeichen auf die Schnittstelle auszugeben, müssen wir dasselbe&lt;br /&gt;
lediglich in das &#039;&#039;&#039;U&#039;&#039;&#039;ART &#039;&#039;&#039;D&#039;&#039;&#039;ata &#039;&#039;&#039;R&#039;&#039;&#039;egister schreiben. Vorher ist zu prüfen, ob das UART-Modul bereit ist, das zu sendende Zeichen entgegenzunehmen. Die Bezeichnungen des/der Statusregisters mit dem Bit UDRE ist abhängig vom Controllertypen (vgl. Datenblatt).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
// bei neueren AVRs steht der Status in UCSRA/UCSR0A/UCSR1A, hier z.&amp;amp;nbsp;B. fuer ATmega16:&lt;br /&gt;
    while (!(UCSRA &amp;amp; (1&amp;lt;&amp;lt;UDRE)))  /* warten bis Senden moeglich                   */&lt;br /&gt;
    {&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    UDR = &#039;x&#039;;                    /* schreibt das Zeichen x auf die Schnittstelle */&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Schreiben einer Zeichenkette (String) ===&lt;br /&gt;
&lt;br /&gt;
Die Aufgabe &amp;quot;String senden&amp;quot; wird durch zwei Funktionen abgearbeitet. Die universelle/controllerunabhängige Funktion uart_puts übergibt jeweils ein Zeichen der Zeichenkette an eine Funktion uart_putc, die abhängig von der vorhandenen Hardware implementiert werden muss. In der Funktion zum Senden eines Zeichens ist darauf zu achten, dass vor dem Senden geprüft wird, ob der UART bereit ist den &amp;quot;Sendeauftrag&amp;quot; entgegenzunehmen. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/* ATmega16 */&lt;br /&gt;
int uart_putc(unsigned char c)&lt;br /&gt;
{&lt;br /&gt;
    while (!(UCSRA &amp;amp; (1&amp;lt;&amp;lt;UDRE)))  /* warten bis Senden moeglich */&lt;br /&gt;
    {&lt;br /&gt;
    }                             &lt;br /&gt;
&lt;br /&gt;
    UDR = c;                      /* sende Zeichen */&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/* puts ist unabhaengig vom Controllertyp */&lt;br /&gt;
void uart_puts (char *s)&lt;br /&gt;
{&lt;br /&gt;
    while (*s)&lt;br /&gt;
    {   /* so lange *s != &#039;\0&#039; also ungleich dem &amp;quot;String-Endezeichen&amp;quot; */&lt;br /&gt;
        uart_putc(*s);&lt;br /&gt;
        s++;&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die in uart_putc verwendeten Schleifen, in denen gewartet wird bis die UART-Hardware zum senden bereit ist, sind insofern etwas kritisch, da während des Sendens eines Strings nicht mehr auf andere Ereignisse reagiert werden kann. Universeller ist die Nutzung von FIFO(first-in first-out)-Puffern, in denen die zu sendenden bzw. empfangenen Zeichen/Bytes zwischengespeichert und in Interruptroutinen an die U(S)ART-Hardware weitergegeben bzw. von ihr ausgelesen werden. Dazu existieren fertige Komponenten (Bibliotheken, Libraries), die man recht einfach in eigene Entwicklungen integrieren kann. Es empfiehlt sich, diese Komponenten zu nutzen und das Rad nicht neu zu erfinden.&lt;br /&gt;
&lt;br /&gt;
=== Schreiben von Variableninhalten ===&lt;br /&gt;
&lt;br /&gt;
Sollen Inhalte von Variablen (Ganzzahlen, Gleitkomma) in &amp;quot;menschenlesbarer&amp;quot; Form gesendet werden, ist vor dem Transfer eine Umwandlung in Zeichen (&amp;quot;ASCII&amp;quot;) erforderlich. Bei nur einer Ziffer ist diese Umwandlung relativ einfach: man addiert den ASCII-Wert von Null zur Ziffer und kann diesen Wert direkt senden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
//...&lt;br /&gt;
&lt;br /&gt;
// hier uart_putc (s.o.)&lt;br /&gt;
&lt;br /&gt;
int main (void) &lt;br /&gt;
{&lt;br /&gt;
   // Ausgabe von 0123456789&lt;br /&gt;
   char c;&lt;br /&gt;
&lt;br /&gt;
   uart_init();&lt;br /&gt;
&lt;br /&gt;
   for (uint8_t i=0; i&amp;lt;=9; ++i) {&lt;br /&gt;
      c = i + &#039;0&#039;;&lt;br /&gt;
      uart_putc( c );&lt;br /&gt;
      // verkuerzt: uart_putc( i + &#039;0&#039; );&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   while (1) {&lt;br /&gt;
      ;&lt;br /&gt;
   }&lt;br /&gt;
 &lt;br /&gt;
   return 0; // never reached &lt;br /&gt;
&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Soll mehr als eine Ziffer ausgegeben werden, bedient man sich zweckmäßigerweise vorhandener Funktionen zur Umwandlung von Zahlen in Zeichenketten/Strings. Die Funktion der avr-libc zur Umwandlung von vorzeichenbehafteten 16bit-Ganzzahlen (int16_t) in Zeichenketten heißt &#039;&#039;itoa&#039;&#039; (Integer to ASCII). Man muss der Funktion einen Speicherbereich zur Verarbeitung (buffer) mit Platz für alle Ziffern, das String-Endezeichen (&#039;\0&#039;) und evtl. das Vorzeichen bereitstellen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//...&lt;br /&gt;
&lt;br /&gt;
// hier uart_init, uart_putc, uart_puts (s.o.)&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
   char s[7];&lt;br /&gt;
   int16_t i = -12345;&lt;br /&gt;
   &lt;br /&gt;
   uart_init();&lt;br /&gt;
&lt;br /&gt;
   itoa( i, s, 10 ); // 10 fuer radix -&amp;gt; Dezimalsystem&lt;br /&gt;
   uart_puts( s );&lt;br /&gt;
&lt;br /&gt;
   // da itoa einen Zeiger auf den Beginn von s zurueckgibt verkuerzt auch:&lt;br /&gt;
   uart_puts( itoa( i, s, 10 ) );&lt;br /&gt;
&lt;br /&gt;
   while (1) {&lt;br /&gt;
      ;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   return 0; // never reached &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Für vorzeichenlose 16bit-Ganzzahlen (uint16_t) exisitert &#039;&#039;utoa&#039;&#039;. Die Funktionen für 32bit-Ganzzahlen (int32_t und uint32_t) heißen &#039;&#039;ltoa&#039;&#039; bzw. &#039;&#039;ultoa&#039;&#039;. Da 32bit-Ganzzahlen mehr Stellen aufweisen können, ist ein entsprechend größerer Pufferspeicher vorzusehen.&lt;br /&gt;
&lt;br /&gt;
Auch Gleitkommazahlen (float/double) können mit bereits vorhandenen Funktionen in Zeichenfolgen umgewandelt werden, dazu existieren die Funktionen &#039;&#039;dtostre&#039;&#039; und &#039;&#039;dtostrf&#039;&#039;. dtostre nutzt Exponentialschreibweise (&amp;quot;engineering&amp;quot;-Format). (Hinweis: z.Zt. existiert im avr-gcc kein &amp;quot;echtes&amp;quot; double, intern wird immer mit &amp;quot;einfacher Genauigkeit&amp;quot;, entsprechend float, gerechnet.) &lt;br /&gt;
&lt;br /&gt;
dtostrf und dtostre benötigen die libm.a der avr-libc. Bei Nutzung von Makefiles ist der Parameter -lm in in LDFLAGS anzugeben (Standard in den WinAVR/mfile-Makefilevorlagen). Nutzt man AVRStudio als IDE für den GNU-Compiler (gcc-Plugin) ist die libm.a unter Libaries auszuwählen: Project -&amp;gt; Configurations Options -&amp;gt; Libaries -&amp;gt; libm.a mit dem Pfeil nach rechts einbinden. Siehe auch die [[FAQ#Aktivieren_der_Floating_Point_Version_von_sprintf_beim_WinAVR_mit_AVR-Studio|FAQ]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//...&lt;br /&gt;
&lt;br /&gt;
// hier uart_init, uart_putc, uart_puts (s.o.)&lt;br /&gt;
&lt;br /&gt;
/* lt. avr-libc Dokumentation:&lt;br /&gt;
char* dtostrf(&lt;br /&gt;
  double __val,&lt;br /&gt;
  char   __width,&lt;br /&gt;
  char   __prec,&lt;br /&gt;
  char * __s&lt;br /&gt;
)  &lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
   // Pufferspeicher ausreichend groß&lt;br /&gt;
   // evtl. Vorzeichen + width + Endezeichen:&lt;br /&gt;
   char s[8]; &lt;br /&gt;
   float f = -12.345;&lt;br /&gt;
   &lt;br /&gt;
   uart_init();&lt;br /&gt;
&lt;br /&gt;
   dtostrf( f, 6, 3, s ); &lt;br /&gt;
   uart_puts( s );&lt;br /&gt;
   // verkürzt: uart_puts( dtostrf( f, 7, 3, s ) );&lt;br /&gt;
&lt;br /&gt;
   while (1) {&lt;br /&gt;
      ;&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   return 0; // never reached &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Empfangen ==&lt;br /&gt;
=== Einzelne Zeichen empfangen ===&lt;br /&gt;
&lt;br /&gt;
Zum Empfang von Zeichen muss der Empfangsteil des UART bei der Initialisierung aktiviert werden, indem das RXEN-Bit im jeweiligen Konfigurationsregister (UCSRB bzw UCSR0B/UCSR1B) gesetzt wird. Im einfachsten Fall wird solange gewartet, bis ein Zeichen empfangen wurde, dieses steht dann im UART-Datenregister (UDR bzw. UDR0 und UDR1 bei AVRs mit 2 UARTS) zur Verfügung (sogen. &amp;quot;Polling-Betrieb&amp;quot;). Ein Beispiel für den ATmega16:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;inttypes.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
/* Siehe auch obere Baudrateneinstellung */&lt;br /&gt;
/* USART-Init beim ATmega16 */&lt;br /&gt;
&lt;br /&gt;
void uart_init(void)&lt;br /&gt;
{&lt;br /&gt;
    UCSRB |= (1&amp;lt;&amp;lt;RXEN);                         // UART RX einschalten&lt;br /&gt;
    UCSRC = (1&amp;lt;&amp;lt;URSEL)|(1&amp;lt;&amp;lt;UCSZ1)|(1&amp;lt;&amp;lt;UCSZ0);  // Asynchron 8N1 &lt;br /&gt;
&lt;br /&gt;
    UBRRH = UBRR_VAL &amp;gt;&amp;gt; 8;&lt;br /&gt;
    UBRRL = UBRR_VAL &amp;amp; 0xFF;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/* Zeichen empfangen */&lt;br /&gt;
uint8_t uart_getc(void)&lt;br /&gt;
{&lt;br /&gt;
    while (!(UCSRA &amp;amp; (1&amp;lt;&amp;lt;RXC)))   // warten bis Zeichen verfuegbar&lt;br /&gt;
        ;&lt;br /&gt;
    return UDR;                   // Zeichen aus UDR an Aufrufer zurueckgeben&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Und die Anwendung in einem Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// hier Makro für die Baudratenberechnung &lt;br /&gt;
&lt;br /&gt;
// hier uart_init, uart_getc (s.o.)&lt;br /&gt;
 &lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
  uart_init();&lt;br /&gt;
  while (1) &lt;br /&gt;
  {&lt;br /&gt;
    uint8_t c;&lt;br /&gt;
    c = uart_getc();&lt;br /&gt;
&lt;br /&gt;
    // hier etwas mit c machen z.B. auf PORT ausgeben&lt;br /&gt;
    DDRC = 0xFF; // PORTC Ausgang&lt;br /&gt;
    PORTC = c;&lt;br /&gt;
  }&lt;br /&gt;
  return 0; // never reached &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Funktion uart_getc() blockiert allerdings den Programmablauf, denn es wird gewartet, bis ein Zeichen empfangen wird! Möchte man das Warten vermeiden, kann das RXC-Bit in einer Programmschleife abgefragt werden und dann nur bei gesetztem RXC-Bit UDR ausgelesen werden. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// hier Makro für die Baudratenberechnung &lt;br /&gt;
&lt;br /&gt;
// hier uart_init, uart_getc (s.o.)&lt;br /&gt;
 &lt;br /&gt;
int main(void)&lt;br /&gt;
{&lt;br /&gt;
  uart_init();&lt;br /&gt;
  while (1) &lt;br /&gt;
  {&lt;br /&gt;
    if ( (UCSRA &amp;amp; (1&amp;lt;&amp;lt;RXC)) )&lt;br /&gt;
    {&lt;br /&gt;
      // Zeichen wurde empfangen, jetzt abholen&lt;br /&gt;
      uint8_t c;&lt;br /&gt;
      c = uart_getc();&lt;br /&gt;
      // hier etwas mit c machen z.B. auf PORT ausgeben&lt;br /&gt;
      DDRC = 0xFF; // PORTC Ausgang&lt;br /&gt;
      PORTC = c;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
      // Kein Zeichen empfangen, Restprogramm ausführen...&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  return 0; // never reached &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eleganter und in den meisten Anwendungsfällen &amp;quot;stabiler&amp;quot; ist die Vorgehensweise, die empfangenen Zeichen in einer Interrupt-Routine einzulesen und zur späteren Verarbeitung in einem Eingangsbuffer (FIFO-Buffer) zwischenzuspeichern. Dazu existieren fertige und gut getestete [[Libraries|Bibliotheken]] &amp;lt;!-- &amp;quot;echte Libraries&amp;quot; (.a) wie im Verweis beschrieben sind hier eigentlich nicht gemeint, verwirrt hier etwas, da AVR-&amp;quot;Libraries&amp;quot; meist per #defines anpassbare Source-Codes sind, vielleicht so: --&amp;gt; und Quellcodekomponenten (z.&amp;amp;nbsp;B. UART-Library von P. Fleury, procyon-avrlib und einige in der &amp;quot;Academy&amp;quot; von avrfreaks.net).&lt;br /&gt;
&lt;br /&gt;
Siehe auch:&lt;br /&gt;
* [http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html Dokumenation der avr-libc/stdlib.h]&lt;br /&gt;
* [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Die_Nutzung_von_sprintf_und_printf Die Nutzung von sprintf und printf]&lt;br /&gt;
* [http://homepage.hispeed.ch/peterfleury/ Peter Fleurys] UART-Bibiliothek fuer avr-gcc/avr-libc&lt;br /&gt;
&amp;lt;!-- nimmermehr: * siehe auch: Weiterführende Informationen inkl. Beispielen für die Nutzung von stdio-Funktionen (printf etc.) im [[AVR-Tutorial:_UART]]. --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
TODO: 9bit&lt;br /&gt;
&lt;br /&gt;
=== Empfang von Zeichenketten (Strings) ===&lt;br /&gt;
&lt;br /&gt;
Beim Empfang von Zeichenketten, muß man sich zunächst darüber im klaren sein, daß es ein Kriterium geben muß, an dem der µC erkennen kann, wann ein Text zu Ende ist. Sehr oft wird dazu das Zeichen &#039;Return&#039; benutzt, um das Ende eines Textes zu markieren. Dies ist vom Benutzer einfach eingebbar und er ist auch daran gewöhnt, daß er eine Eingabezeile mit einem Druck auf die Return Taste abgeschlossen wird.&lt;br /&gt;
&lt;br /&gt;
Prinzipiell gibt es jedoch keine Einschränkung bezüglich dieses speziellen Zeichens. Es muß nur sichergestellt werden, daß dieses spezielle &#039;Ende eines Strings&#039; - Zeichen nicht mit einem im Text vorkommenden Zeichen verwechselt werden kann. Wenn also im zu übertragenden Text beispielsweise kein &#039;;&#039; vorkommt, dann spricht nichts dagegen, den Benutzer die Eingabe eines Textes mit einem &#039;;&#039; abschließen zu lassen.&lt;br /&gt;
&lt;br /&gt;
Im Folgenden wird die durchaus übliche Annahme getroffen, daß eine Stringübertragung identisch ist mit der Übertragung einer Textzeile und daher mit einem Return (&#039;\n&#039;) abgeschlossen wird.&lt;br /&gt;
&lt;br /&gt;
Das Problem der Übertragung eines Strings reduziert sich damit auf die Aufgabenstellung: Empfange und sammle Zeichen in einem char Array, bis entweder das Array voll ist oder das Text Ende Zeichen&#039; empfangen wurde. Danach wird der empfangene Text noch mit einem &#039;\0&#039; Zeichen abgeschlossen um einen Standard C-String daraus zu machen, mit dem dann weiter gearbeitet werden kann.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;C&amp;gt;&lt;br /&gt;
/* Zeichen empfangen */&lt;br /&gt;
uint8_t uart_getc(void)&lt;br /&gt;
{&lt;br /&gt;
    while (!(UCSRA &amp;amp; (1&amp;lt;&amp;lt;RXC)))   // warten bis Zeichen verfuegbar&lt;br /&gt;
        ;&lt;br /&gt;
    return UDR;                   // Zeichen aus UDR an Aufrufer zurueckgeben&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void uart_gets( char* Buffer, uint8_t MaxLen )&lt;br /&gt;
{&lt;br /&gt;
  uint8_t NextChar;&lt;br /&gt;
  uint8_t StringLen = 0;&lt;br /&gt;
&lt;br /&gt;
  NextChar = uart_getc();         // Warte auf und empfange das nächste Zeichen&lt;br /&gt;
&lt;br /&gt;
                                  // Sammle solange Zeichen, bis:&lt;br /&gt;
                                  // * entweder das String Ende Zeichen kam&lt;br /&gt;
                                  // * oder das aufnehmende Array voll ist&lt;br /&gt;
  while( NextChar != &#039;\n&#039; &amp;amp;&amp;amp; StringLen &amp;lt; MaxLen - 1 ) {&lt;br /&gt;
    *Buffer++ = NextChar;&lt;br /&gt;
    StringLen++;&lt;br /&gt;
    NextChar = uart_getc();&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
                                  // Noch ein &#039;\0&#039; anhängen um einen Standard&lt;br /&gt;
                                  // C-String daraus zu machen&lt;br /&gt;
  *Buffer = &#039;\0&#039;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Beim Aufruf ist darauf zu achten, dass das empfangende Array auch mit einer&lt;br /&gt;
vernünftigen Größe definiert wird.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
  char Line[40];      // String mit maximal 39 zeichen&lt;br /&gt;
&lt;br /&gt;
  uart_gets( Line, sizeof( Line ) );&lt;br /&gt;
&amp;lt;/C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Bei der Benutzung von sizeof() ist allerdings zu beachten, dass sizeof() nicht die Anzahl der Elemente des Arrays liefert, sondern die Länge in Byte. Da ein char nur ein Byte lang ist, passt der Aufruf &#039;uart_gets(Line, sizeof( Line ) );&#039; in diesem Fall. Falls man - aus welchen Gründen auch immer - andere Datentypen benutzen möchte, sollte man zur korrekten Angabe der Array-Länge folgende Vorgehensweise bevorzugen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;C&amp;gt;&lt;br /&gt;
  int Line[40];      // Array vom Typ int&lt;br /&gt;
&lt;br /&gt;
  uart_gets( Line, sizeof( Line ) / sizeof( Line[0] ) );&lt;br /&gt;
&amp;lt;/C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Interruptbetrieb==&lt;br /&gt;
&lt;br /&gt;
Hier wird das Grundwissen des Artikels [[Interrupt]] und des Abschnitts [[AVR-GCC-Tutorial#Programmieren_mit_Interrupts|AVR-GCC-Tutorial: Programmieren_mit_Interrupts]] vorausgesetzt.&lt;br /&gt;
&lt;br /&gt;
=== Empfangen (RX) ===&lt;br /&gt;
&lt;br /&gt;
Beim ATmega8 muss das &#039;&#039;&#039;RXCIE&#039;&#039;&#039; Bit im Register UCSRB gesetzt werden, damit ein Interrupt beim Empfang eines Zeichens ausgelöst werden kann.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/* siehe auch obere Baudrateneinstellung */&lt;br /&gt;
/* USART-Init beim ATmega16 */&lt;br /&gt;
void uart_init(void)&lt;br /&gt;
{&lt;br /&gt;
  UCSRB |= (1&amp;lt;&amp;lt;RXEN)|(1&amp;lt;&amp;lt;TXEN)|(1&amp;lt;&amp;lt;RXCIE);  // UART RX, TX und RX Interrupt einschalten&lt;br /&gt;
  UCSRC = (1&amp;lt;&amp;lt;URSEL)|(1&amp;lt;&amp;lt;UCSZ1)|(1&amp;lt;&amp;lt;UCSZ0);  // Asynchron 8N1 &lt;br /&gt;
&lt;br /&gt;
  UBRRH = UBRR_VAL &amp;gt;&amp;gt; 8;&lt;br /&gt;
  UBRRL = UBRR_VAL &amp;amp; 0xFF;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Natürlich muss &amp;quot;Global Interrupt Enable&amp;quot; aktiviert sein (sei()). Interrupt-spezifische Definitionen werden über die Includedatei eingebunden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Interrupt wird immer ausgelöst, wenn ein Zeichen erfolgreich empfangen wurde. Zusätzlich braucht man die Interruptserviceroutine (ISR). &lt;br /&gt;
&lt;br /&gt;
In diesem Beispiel enthält die ISR einen FIFO-Puffer (First in, First out). Dafür werden ein paar globale Variablen und Makros benötigt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#define UART_MAXSTRLEN 10&lt;br /&gt;
&lt;br /&gt;
volatile uint8_t uart_str_complete = 0;     // 1 .. String komplett empfangen&lt;br /&gt;
volatile uint8_t uart_str_count = 0;&lt;br /&gt;
volatile char uart_string[UART_MAXSTRLEN + 1] = &amp;quot;&amp;quot;;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
ISR(USART_RXC_vect)&lt;br /&gt;
{&lt;br /&gt;
  unsigned char nextChar;&lt;br /&gt;
&lt;br /&gt;
  // Daten aus dem Puffer lesen&lt;br /&gt;
  nextChar = UDR;&lt;br /&gt;
  if( uart_str_complete == 0 ) {	// wenn uart_string gerade in Verwendung, neues Zeichen verwerfen&lt;br /&gt;
&lt;br /&gt;
    // Daten werden erst in string geschrieben, wenn nicht String-Ende/max Zeichenlänge erreicht ist/string gerade verarbeitet wird&lt;br /&gt;
    if( nextChar != &#039;\n&#039; &amp;amp;&amp;amp;&lt;br /&gt;
        nextChar != &#039;\r&#039; &amp;amp;&amp;amp;&lt;br /&gt;
        uart_str_count &amp;lt; UART_MAXSTRLEN - 1 ) {&lt;br /&gt;
      uart_string[uart_str_count] = nextChar;&lt;br /&gt;
      uart_str_count++;&lt;br /&gt;
    }&lt;br /&gt;
    else {&lt;br /&gt;
      uart_string[uart_str_count] = &#039;\0&#039;;&lt;br /&gt;
      uart_str_count = 0;&lt;br /&gt;
      uart_str_complete = 1;&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zur Funktion: Wurde eine komplette Zeichenkette empfangen, also das Ende (\n oder \r) erkannt oder die maximale Länge &#039;&#039;UART_MAXSTRLEN&#039;&#039; erreicht, wird die globale Variable &#039;&#039;uart_str_complete&#039;&#039; auf &#039;1&#039; gesetzt. Damit wird dem Hauptprogramm, welches auf diese Variable pollt, mitgeteil, dass die Zeichenkette &#039;&#039;uart_string&#039;&#039; zur Verarbeitung bereit steht. Nach der Verarbeitung der Zeichenkette in der entsprechenden main-Routine, muss die Variable &#039;&#039;uart_str_complete&#039;&#039; wieder auf &#039;0&#039; zurück gesetzt werden. Dadurch werden alle neu empfangenen Zeichen wieder in den globalen Puffer geschrieben.&lt;br /&gt;
&lt;br /&gt;
=== (Baustelle) ===&lt;br /&gt;
&lt;br /&gt;
* Empfangen (Receive) (Anm.: z.T. erledigt)&lt;br /&gt;
** ggf. Fallstricke ([http://www.mikrocontroller.net/topic/84256#707214 UDR in der ISR lesen!])&lt;br /&gt;
** Komplettes, einfaches Beispiel ([http://www.mikrocontroller.net/topic/84228#707052 Echo] (noch buggy beim Datenzugriff, siehe Lit. 2+3!)), ggf. LED zur ISR-Empfangsanzeige oder Overflow-Anzeige&lt;br /&gt;
&lt;br /&gt;
* Senden (Transmit)&lt;br /&gt;
** Variante &amp;quot;UART Data Register Empty&amp;quot; (UDRE) [http://www.mikrocontroller.net/topic/101472#882716]&lt;br /&gt;
** Variante &amp;quot;UART Transmit Complete&amp;quot; (TXC) &lt;br /&gt;
&lt;br /&gt;
* FIFO-Puffer [http://www.mikrocontroller.net/topic/101472#882716], Ringpuffer (Byte Buffering (circular))&lt;br /&gt;
&lt;br /&gt;
* UART-Bibliotheken &lt;br /&gt;
** [http://homepage.hispeed.ch/peterfleury/avr-software.html UART-Library] von Peter Fleury (UART (interrupt driven), Byte Buffering (circular))&lt;br /&gt;
** [http://hubbard.engr.scu.edu/embedded/avr/avrlib/ Procyon AVRlib] von Pascal Stang (UART (interrupt driven), Byte Buffering (circular), VT100 Terminal Output)&lt;br /&gt;
&lt;br /&gt;
* Literatur &lt;br /&gt;
** [http://www.avrfreaks.net/index.php?name=PNphpBB2&amp;amp;file=viewtopic&amp;amp;t=48188 avrfreaks.net Tutorial] inkl. Diskussion (engl.)&lt;br /&gt;
** avr-libc FAQ: [http://www.nongnu.org/avr-libc/user-manual/FAQ.html#faq_16bitio Why do some 16-bit timer registers sometimes get trashed?]&lt;br /&gt;
&lt;br /&gt;
==Software-UART==&lt;br /&gt;
&lt;br /&gt;
Falls die Zahl der vorhandenen Hardware-UARTs nicht ausreicht, können weitere Schnittstellen über sogennante Software-UARTs ergänzt werden. Es gibt dazu (mindestens) zwei Ansätze: &lt;br /&gt;
* Der bei AVRs üblichste Ansatz basiert auf dem Prinzip, dass ein externer Interrupt-Pin für den Empfang (&amp;quot;RX&amp;quot;) genutzt wird. Das Startbit löst den Interrupt aus, in der Interrupt-Routine (ISR) wird der externe Interrupt deaktiviert und ein Timer aktiviert. In der Interrupt-Routine des Timers wird der Zustand des Empfangs-Pins entsprechend der Baudrate abgetastet. Nach Empfang des Stop-Bits wird der externe Interrupt wieder aktiviert. Senden kann über einen beliebigen Pin (&amp;quot;TX&amp;quot;) erfolgen, der entsprechend der Baudrate und dem zu sendenden Zeichen auf 0 oder 1 gesetzt wird. Die Implementierung ist nicht ganz einfach, es existieren dazu aber fertige Bibliotheken (z.&amp;amp;nbsp;B. bei [http://www.avrfreaks.net/ avrfreaks] oder in der [http://www.procyonengineering.com/embedded/avr/avrlib/ Procyon avrlib]).&lt;br /&gt;
* Ein weiterer Ansatz erfordert keinen Pin mit &amp;quot;Interrupt-Funktion&amp;quot; aber benötigt mehr Rechenzeit. Jeder Input-Pin kann als Empfangspin (RX) dienen. Über einen Timer wird der Zustand des RX-Pins mit einem vielfachen der Baudrate abgetastet (dreifach scheint üblich) und High- bzw. Lowbits anhand einer Mindestanzahl identifiziert. (Beispiel: &amp;quot;Generic Software Uart&amp;quot; Application-Note von IAR)&lt;br /&gt;
&lt;br /&gt;
Neuere AVRs (z.&amp;amp;nbsp;B. ATtiny26 oder ATmega48,88,168,169) verfügen über ein Universal Serial Interface (USI), das teilweise UART-Funktion übernehmen kann. Atmel stellt eine Application-Note bereit, in der die Nutzung des USI als UART erläutert wird (im Prinzip &amp;quot;Hardware-unterstützter Software-UART&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
==Handshaking==&lt;br /&gt;
Wenn der Sender ständig sendet, wird irgendwann der Fall eintreten, daß der Empfänger nicht bereit ist, neue Zeichen zu empfangen. In diesem Fall muß durch ein &#039;&#039;&#039;Handshake-Verfahren&#039;&#039;&#039; die Situation bereinigt werden. Handshake bedeutet nichts anderes, als daß der Empfänger dem Sender mitteilt, daß er zur Zeit keine Daten annehmen kann und der Sender die Übertragung der nächsten Zeichen solange einstellen soll, bis der Empfänger signalisiert, daß er wieder Zeichen aufnehmen kann.&lt;br /&gt;
===Hardwarehandshake (RTS/CTS)===&lt;br /&gt;
Beim Hardwarehandshake werden zusätzlich zu den beiden Daten-Übertragungsleitungen noch 2 weitere Leitungen benötigt: &#039;&#039;&#039;RTS&#039;&#039;&#039; (&#039;&#039;&#039;R&#039;&#039;&#039;equest &#039;&#039;&#039;T&#039;&#039;&#039;o &#039;&#039;&#039;S&#039;&#039;&#039;end) und &#039;&#039;&#039;CTS&#039;&#039;&#039; (&#039;&#039;&#039;C&#039;&#039;&#039;lear &#039;&#039;&#039;T&#039;&#039;&#039;o &#039;&#039;&#039;S&#039;&#039;&#039;end). Jeder der beiden Kommunikationspartner ist verpflichtet, bevor ein Zeichen gesendet wird, den Zustand der &#039;&#039;&#039;RTS&#039;&#039;&#039; Leitung zu überprüfen. Nur wenn die Gegenstelle darauf Empfangsbereitschaft signalisiert, darf das Zeichen gesendet werden. Um der Gegenstelle zu signalisieren, daß sie zur Zeit keine Zeichen schicken soll, wird die Leitung &#039;&#039;&#039;CTS&#039;&#039;&#039; benutzt.&lt;br /&gt;
&lt;br /&gt;
===Softwarehandshake (XON/XOFF)===&lt;br /&gt;
Beim Softwarehandshake sind keine speziellen Leitungen notwendig. Statt dessen werden besondere ASCII-Zeichen benutzt, die der Gegenstelle signalisieren, daß Senden einzustellen bzw. wieder aufzunehmen.&amp;lt;br /&amp;gt;&lt;br /&gt;
* &#039;&#039;&#039;XOFF&#039;&#039;&#039; Aufforderung das Senden einzustellen&lt;br /&gt;
* &#039;&#039;&#039;XON&#039;&#039;&#039;  Gegenstelle darf wieder senden&lt;br /&gt;
&lt;br /&gt;
Nachteilig bei einem Softwarehandshake ist es, dass dadurch keine direkte binäre Datenübertragung mehr möglich ist. Von den möglichen 256 Bytewerten werden ja 2 (nämlich &#039;&#039;&#039;XON&#039;&#039;&#039; und &#039;&#039;&#039;XOFF&#039;&#039;&#039;) für besondere Zwecke benutzt und fallen daher aus.&lt;br /&gt;
&lt;br /&gt;
==Galvanische Trennung==&lt;br /&gt;
Für eine geringe Überspannungsfestigkeit empfielt es sich, die Datenkanäle über Optokoppler zu führen. Es bietet sich z.b. der 6N138 an, ein &amp;quot;normaler&amp;quot; CNY-17 ist für hohe Baudraten nicht brauchbar.&lt;br /&gt;
&lt;br /&gt;
==Fehlersuche==&lt;br /&gt;
Erstaunlich oft wird im Forum der Hilferuf laut: &amp;quot;Meine UART funktioniert nicht, was mache ich falsch&amp;quot;. In der überwiegenden Mehrzahl der Fälle stellt sich dann heraus, daß es sich um ein Hardwareproblem handelt, wobei da wiederrum der Löwenanteil auf das Konto einer nicht korrekt eingestellten Taktrate geht: Der µC benutzt nicht einen angeschlossenen Quarz, so wie er auch im Programm eingetragen ist, sondern läuft immer noch mit dem internen RC-Takt. Daraus resultiert aber auch, daß der Baudraten Konfigurationswert falsch berechnet wird.&lt;br /&gt;
&lt;br /&gt;
Hilfreich zum Aufspüren solcher Fehler ist auch die [[AVR_Checkliste#UART/USART|AVR-Checkliste]].&lt;br /&gt;
&lt;br /&gt;
==Links==&lt;br /&gt;
Tipps zur Verarbeitung von Strings sind in den [[FAQ]].&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:avr-gcc Tutorial]]&lt;br /&gt;
[[Kategorie:UART und RS232]]&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVRDUDE&amp;diff=56967</id>
		<title>AVRDUDE</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVRDUDE&amp;diff=56967"/>
		<updated>2011-05-02T12:04:42Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: /* Weblinks */  link entfernt da er nur noch auf Hauptseite führt und keine Info´s zu avrdude enthält.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Beschreibung ==&lt;br /&gt;
AVRDUDE (http://www.nongnu.org/avrdude/) ist eine Programmiersoftware für Atmel [[AVR]] Controller. &lt;br /&gt;
&lt;br /&gt;
Funktionen unter Anderem: &lt;br /&gt;
&lt;br /&gt;
* Übertragen von Programmcode in den Flash-Speicher&lt;br /&gt;
* Auslesen ungeschützen Codes aus dem Flash&lt;br /&gt;
* Setzen und Lesen von Fuse- und Lockbits (Siehe auch: [[AVR_Fuses#Vergleich_der_Fuses_bei_verschiedenen_Programmen|Vergleich der Fuses bei verschiedenen Programmen]])&lt;br /&gt;
* Schreiben und Lesen des EEPROMs&lt;br /&gt;
&lt;br /&gt;
AVRDUDE kann das [[STK500]] (auch mit Firmware 2.x als stk500v2), das Atmel AVRISP (auch mit Firmware 2.x als avrispv2 o.ä.), das Atmel AVRISP MKII (USB Ansteuerung mittels lib-usb bzw. lib-usb-W32), [[AVR_In_System_Programmer#USB | AVR910-kompatible]] Programmierer, den [[AVR Butterfly]]/AVR109-kompatible Bootloader, [[STK200]]-Programmierdongles und verschiedene andere Parallelport-Adapter sowie &amp;quot;serielle Statusportprogrammierer&amp;quot; (Siprog) ansteuern. Auch das Atmel JTAGICE (oder Nachbauten wie Bootice oder Evertool), Atmel JTAGICE-MKII und der AVR Dragon können als Programmierhardware genutzt werden.&lt;br /&gt;
&lt;br /&gt;
Das Programm ist unter MS-Windows (Cygwin nicht erforderlich), Linux, BSD, Solaris und Mac OS X lauffähig. Die Version für MS-Windows ist im [[WinAVR]]-Paket enthalten. Der Quellcode ist frei verfügbar (Lizenz beachten).&lt;br /&gt;
&lt;br /&gt;
Da alle AVRDUDE-Funktionen über Kommandozeilenparamter gesteuert werden können, eignet es sich gut zur Integration in Makefiles. Beispiele finden sich in der Makefile-Vorlage von [[WinAVR]] und Mfile. &lt;br /&gt;
&lt;br /&gt;
Die gesamte Konfiguration liegt in einer Textdatei (avrdude.conf), so dass sich bei Bedarf ein beliebiger neuer Parallelport-Programmierdongle oder auch ein noch nicht unterstützter AVR-Controller ergänzen lassen. Die Syntax für die Definition eines AVR-Controllers lehnt sich an die Datenblatt-Tabelle für die serielle Programmierung an, so dass man praktisch nur das Datenblatt &amp;quot;intelligent&amp;quot; abtippen muss.&lt;br /&gt;
&lt;br /&gt;
Für die Ansteuerung von Parallelport-Adaptern unter MS-Windows NT/2000/XP wird ein spezieller Porttreiber (giveio) mitgeliefert. Bei der Installation von [[WinAVR]] wird giveio bereits mitinstalliert. &lt;br /&gt;
&lt;br /&gt;
Programmer mit üblicher serieller Schnittstelle (RS232) benötigen keine zusätzliche Software oder Treiber zum Betrieb mit AVRDUDE. &lt;br /&gt;
&lt;br /&gt;
Für Hardware mit USB-Anschluss muss die lib-usb bzw. lib-usb-win32 installiert sein.&lt;br /&gt;
&lt;br /&gt;
===GUIs===&lt;br /&gt;
Bei [[WinAVR]] wird die grafische Oberfläche avrdude-gui.exe mitgeliefert.&lt;br /&gt;
&lt;br /&gt;
Für Windows, Linux und andere Betriebssysteme gibt zwei weitere GUIs: den in Java geschriebene [[Burn-o-mat|AVR Burn-O-Mat]] und den [http://www.soft-land.de/index.php?page=avrburner avrburner].&lt;br /&gt;
&lt;br /&gt;
Für Mac OS X gibt es noch [http://www.vonnieda.org/software/avrfuses AVRFuses.app]. AVRFuses muss beim ersten Starten auf den verwendeten Programmer und den Speicherort von AVRDUDE eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
GUIs vereinfachen vor allem Programmieren der Fuses.&lt;br /&gt;
&lt;br /&gt;
== Kurzanleitung für Linux und STK200 ==&lt;br /&gt;
&lt;br /&gt;
Dazu muss erst ein Hardware-Link auf die Printerport-Treiber eingerichtet werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
su&lt;br /&gt;
mknod /dev/parport0 c 99 0&lt;br /&gt;
chmod a+rw /dev/parport0&lt;br /&gt;
avrdude -p m8535 -c stk200 -e -U qqtraff.hex&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hinweis :&lt;br /&gt;
Bei USB Programmern ist zu beachten, dass diese durch das Betriebssystem auf einen anderen Port gelegt werden können, als im Beispiel angegeben.&lt;br /&gt;
Diesen Port kann man unter Anderem &amp;quot;im Terminal&amp;quot; mit dem Befehl&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
user@server: dmesg&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
ermitteln.&lt;br /&gt;
Alternativ kann man sich eine Auflistung der Ports, im Verzeichnis &amp;quot;/dev&amp;quot; anzeigen lassen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
user@server: ls /dev/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sollte man nicht sicher sein, auf welchem Port der Programmer liegt, kann man den Programmer nochmals ausstecken und &amp;quot;ls /dev/&amp;quot; ausführen. Der nun Fehlende Port, ist der Programmerport.&lt;br /&gt;
Diesen Port muss man statt &amp;quot;parport0&amp;quot; in die oben beschriebenen Terminalkommandos einsetzen.&lt;br /&gt;
&lt;br /&gt;
Siehe auch : &lt;br /&gt;
* [http://wiki.ctbot.de/index.php/AVR_ISP_Programmer#BlueMP3_bzw._STK200_kompatible_Flasher weitere Beispiele für avrdude Kommandos (http://wiki.ctbot.de/index.php)]&lt;br /&gt;
* [[AVR_In_System_Programmer#STK200-kompatibel]]&lt;br /&gt;
* http://www.mikrocontroller.net/topic/200390#new&lt;br /&gt;
&lt;br /&gt;
== Tipps + Tricks ==&lt;br /&gt;
&lt;br /&gt;
=== [[AVR_In_System_Programmer#Parallelport|Parallelport-Programmer]] an aktuellen PCs ===&lt;br /&gt;
Aktuelle PCs sind einfach zu schnell mit dem Bitgewackel an der parallelen Schnittstelle, vor allem für AVRs, die noch mit den 1 MHz im Auslieferungszustand laufen (maximal zulässiger ISP-Takt &amp;lt; 250 kHz). Neuere Versionen von avrdude unterstützen zu diesem Zweck eine Option &#039;&#039;&#039;-i &amp;lt;N&amp;gt;&#039;&#039;&#039;, wobei &amp;lt;N&amp;gt; die Anzahl der Mikrosekunden bezeichnet, die beim Bitwackeln zusätzlich zu warten ist. Einfach mal mit -i 10 anfangen und dann entweder die Fuses auf die Ziel-Taktfrequenz umstellen (falls diese wesentlich höher sein wird als die 1 MHz), oder sukkzessive mit kleineren Werten testen ([http://www.mikrocontroller.net/topic/83524#699933 Forenbeitrag von Jörg]).&lt;br /&gt;
&lt;br /&gt;
Die Option -i ist auch nützlich bei AVRs, die für einen langsamen Takt konfiguriert sind. Bei einem ATmega8, der mit einem 32.768 kHz Quarz läuft, kann es z.B. notwendig sein, die Option -i 90 zu verwenden. Den Zahlenwert ggf. ausprobieren.&lt;br /&gt;
&lt;br /&gt;
Manche Programmer werten die Option -i manchmal nicht aus, dann sollte man einen anderen Programmer versuchen.&lt;br /&gt;
&lt;br /&gt;
Beim USBTINY und USBASP kann man die Geschwindigkeit der SPI-Schnittstelle mit dem Parameter -B [Periodendauer in Mikrosekunden] begrenzen. Da beide Geräte durch Interrupts der Software-USB-Schnittstelle stark belastet werden, handelt es sich hier um die Maximalbitrate.&lt;br /&gt;
&lt;br /&gt;
Unter WinXPsp2 auf einem Thinkpad T40 lies sich die &amp;quot;avrdude: AVR device not responding&amp;quot;-Meldung beheben durch Ändern von Gerätemanager--&amp;gt;Ltp1--&amp;gt;Eigenschaften--&amp;gt;Anschlusseinstellungen--&amp;gt;Interrupt-nie-verwenden in &amp;quot;Jeden dem Anschluss zugewiesenem Interrupt verwenden&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===USB Programmer===&lt;br /&gt;
Ein Selbstbau USB-Programmer ist unter&lt;br /&gt;
[http://www.rototron.info/?Page=USBAVR/USBAVR.aspx http://www.rototron.info]&lt;br /&gt;
zu finden. Er läuft auch unter VISTA und benötigt mit der neuesten AVRDUDE Version keinen Treiber, da er im HID-Modus betrieben wird.&lt;br /&gt;
&lt;br /&gt;
==== libusb0.dll wird bei WinAvr 20070525 nicht gefunden====&lt;br /&gt;
[http://www.mikrocontroller.net/topic/83524#701461 Forenbeitrag von Paul]: Habe leider noch etwas zu bemängeln, und zwar meckerte avrdude, dass es die &amp;quot;libusb0.dll&amp;quot; nicht fand. Musste dann erst noch manuell den Pfad c:\winavr\utils\libusb\bin in die autoxecec.bat eintragen. Siehe auch [http://www.avrfreaks.net/index.php?name=PNphpBB2&amp;amp;file=viewtopic&amp;amp;p=373283 Diskussion bei www.avrfreaks.net]&lt;br /&gt;
&lt;br /&gt;
====Aufruf unter Linux als user (non-root)====&lt;br /&gt;
&lt;br /&gt;
Unter Linux kann häufig avrdude nur als user &#039;root&#039; auf den USB-Programmer zugreifen. Als normaler User bekommt man eine Fehlermeldung wie:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#avrdude -c usbtiny -p m8&lt;br /&gt;
 &lt;br /&gt;
avrdude: error: usbtiny_transmit: &lt;br /&gt;
error sending control message: &lt;br /&gt;
Operation not permitted&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dies liegt daran, dass die device-nodes, die beim Einstecken des USB-Programmers von udev angelegt werden, root zugeordnet sind. Man kann dies ändern, indem man udev-Regeln für die verwendeten Programmer anlegt. Unter Debian muß man dazu nur eine neue Datei, z.&amp;amp;nbsp;B. 015_usbprog.rules unter /etc/udev/rules.d anlegen, z.&amp;amp;nbsp;B. mit folgenden Inhalt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Atmel AVR ISP mkII&lt;br /&gt;
SUBSYSTEM==&amp;quot;usb&amp;quot;, SYSFS{idVendor}==&amp;quot;03eb&amp;quot;, SYSFS{idProduct}==&amp;quot;2104&amp;quot;, GROUP=&amp;quot;users&amp;quot;, MODE=&amp;quot;0660&amp;quot; &lt;br /&gt;
&lt;br /&gt;
# usbprog bootloader&lt;br /&gt;
ATTRS{idVendor}==&amp;quot;1781&amp;quot;, ATTRS{idProduct}==&amp;quot;0c62&amp;quot;, GROUP=&amp;quot;users&amp;quot;, MODE=&amp;quot;0660&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
# USBasp programmer&lt;br /&gt;
ATTRS{idVendor}==&amp;quot;16c0&amp;quot;, ATTRS{idProduct}==&amp;quot;05dc&amp;quot;, GROUP=&amp;quot;users&amp;quot;, MODE=&amp;quot;0660&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
# USBtiny programmer&lt;br /&gt;
ATTRS{idVendor}==&amp;quot;1781&amp;quot;, ATTRS{idProduct}==&amp;quot;0c9f&amp;quot;, GROUP=&amp;quot;users&amp;quot;, MODE=&amp;quot;0660&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
habe den alten Inhalt nur auskommentiert, weil ich das ganze nur mit dem mkII testen konnte. ...Nur falls sich jemand beschweren sollte.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Atmel AVR ISP mkII&lt;br /&gt;
ATTRS{idVendor}==&amp;quot;03eb&amp;quot;, ATTRS{idProduct}==&amp;quot;2104&amp;quot;, GROUP=&amp;quot;users&amp;quot;, MODE=&amp;quot;0660&amp;quot; &lt;br /&gt;
 &lt;br /&gt;
# usbprog bootloader&lt;br /&gt;
ATTRS{idVendor}==&amp;quot;1781&amp;quot;, ATTRS{idProduct}==&amp;quot;0c62&amp;quot;, GROUP=&amp;quot;users&amp;quot;, MODE=&amp;quot;0660&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
# USBasp programmer&lt;br /&gt;
ATTRS{idVendor}==&amp;quot;16c0&amp;quot;, ATTRS{idProduct}==&amp;quot;05dc&amp;quot;, GROUP=&amp;quot;users&amp;quot;, MODE=&amp;quot;0660&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
# USBtiny programmer&lt;br /&gt;
ATTRS{idVendor}==&amp;quot;1781&amp;quot;, ATTRS{idProduct}==&amp;quot;0c9f&amp;quot;, GROUP=&amp;quot;users&amp;quot;, MODE=&amp;quot;0660&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach muss in der Regel der udev-Dienst neu gestartet werden, was -- je nach System -- mit einem der beiden folgenden Befehle funktionieren sollte (natürlich nur als root):&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 /etc/init.d/udev restart&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
oder &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 service udev restart&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo /sbin/udevadm control --reload-rules&amp;lt;/pre&amp;gt; bei aktueller udev-version, oder&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo /sbin/udevcontrol --reload-rules&amp;lt;/pre&amp;gt;, bei älteren udev-versionen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Danach sollte der USB-Programmer erneut angeschlossen werden. Falls es immer noch nicht funktioniert kann es helfen, als GROUP &amp;quot;plugdev&amp;quot; statt &amp;quot;users&amp;quot; zu verwenden.&lt;br /&gt;
&lt;br /&gt;
Hiermit werden der AVR ISP mkII, der usbprog Bootloader, USBasp und USBtiny bekannt gemacht, so daß alle User in der Gruppe &amp;quot;users&amp;quot; darauf zugreifen können.&lt;br /&gt;
&lt;br /&gt;
Für weitere USB-Programmer muß man die entsprechende Zeile (mit ATTRS...) anlegen und die passenden Vendor und Product IDs eintragen.&lt;br /&gt;
&lt;br /&gt;
Siehe auch:&lt;br /&gt;
* [http://www.reactivated.net/writing_udev_rules.html Writing udev rules]&lt;br /&gt;
&lt;br /&gt;
=== Anzeige unterstützter AVRs ===&lt;br /&gt;
Wie die anderen Atmels bei avrdude heißen zeigt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrdude -?&lt;br /&gt;
avrdude -p ?&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== neuere AVRs hinzufügen ===&lt;br /&gt;
Manch neueres Silizium wird nicht erkannt da sich z.T. die IDs geändert haben. Um diese erfolgreich zu Programmieren empfiehlt sich ein eigenes config-File zu verwenden. Darin werden die &#039;fehlenden&#039; CPUs ergänzt:&lt;br /&gt;
&lt;br /&gt;
z.B. ATmega168P (Programmierung wie ATmega168): einfach den ATmega168 Teil duplizieren und die entsprechenden Änderungen (id, desc, signature) vornehmen&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#------------------------------------------------------------&lt;br /&gt;
# ATmega168P&lt;br /&gt;
#------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
part&lt;br /&gt;
    id              = &amp;quot;m168p&amp;quot;;&lt;br /&gt;
    desc            = &amp;quot;ATMEGA168P&amp;quot;;&lt;br /&gt;
     has_debugwire = yes;&lt;br /&gt;
     flash_instr   = 0xB6, 0x01, 0x11;&lt;br /&gt;
     eeprom_instr  = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00,&lt;br /&gt;
	             0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF,&lt;br /&gt;
	             0x99, 0xF9, 0xBB, 0xAF;&lt;br /&gt;
    stk500_devcode  = 0x86;&lt;br /&gt;
    # avr910_devcode = 0x;&lt;br /&gt;
    signature       = 0x1e 0x94 0x0b;&lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
danach kann, unter Angabe des neuen config-Files, auch ein ATmega168P programmiert werden, z.B.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrdude -pm168p -C ~/.avrdude.config.neu -cstk500v2 -v  -U flash:w:main.hex&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Anschluss an COM10 und höher (Windows) ===&lt;br /&gt;
&lt;br /&gt;
Wenn AVRDUDE unter Windows an COM10 und höher betrieben werden soll, ist eine andere Schreibweise für die Schnittstelle in der Kommandozeile nötig. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrdude -c stk500v2 -p m16 -P \\.\com13 -uF -vvvv 2&amp;gt; logfile.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In diesem Beispiel wird statt der gewohnten Schreibweise &#039;&#039;&#039;com13&#039;&#039;&#039; die spezielle Schreibweise  &#039;&#039;&#039;\\.\com13&#039;&#039;&#039; verwendet und es wird mit &#039;&#039;-vvvv 2&amp;gt; logfile.txt&#039;&#039; eine ausführliche Debugausgabe für Fragen im Forum erzeugt. Näheres hierzu in der  [http://www.mikrocontroller.net/topic/90401 Forumsdiskussion].&lt;br /&gt;
&lt;br /&gt;
=== AVRISPmkII + AVRDUDE + Window Vista (32) ===&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/topic/126594#1157327&lt;br /&gt;
&lt;br /&gt;
=== &amp;quot;avrdude was compiled without usb support&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Offenbar enthielt WinAVR-20100110 zunächst fälschlicherweise eine AVRDUDE Version ohne USB Support [http://www.mikrocontroller.net/topic/163022#1554907].&lt;br /&gt;
&lt;br /&gt;
Abhilfe:&lt;br /&gt;
 &lt;br /&gt;
1. WinAVR deinstallieren, gleiches Release (WinAVR-20100110) nocheinmal herunterladen und installieren (mindestens seit Anfang März 2010 enthält dieses Release avrdude in der Version 5.10 und bringt USB-Support mit).&lt;br /&gt;
&lt;br /&gt;
2. AVRDUDE selbst compilieren: http://www.mikrocontroller.net/topic/163675&lt;br /&gt;
&lt;br /&gt;
3. Compilierte Version 5.10 downloaden: http://www.mikrocontroller.net/topic/163675#1594689&lt;br /&gt;
&lt;br /&gt;
=== Textausgabe in Datei umleiten? ===&lt;br /&gt;
&lt;br /&gt;
Die Windows-&amp;quot;Shell&amp;quot; &#039;&#039;cmd&#039;&#039; benutzt für die Ausgabeumleitung die gleiche Syntax wie die Bourne-Shell (und damit auch&lt;br /&gt;
Bash): &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
programm &amp;gt;datei 2&amp;gt;&amp;amp;1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
zur Umleitung von STDOUT und STDERR in die gleiche Datei (Yalu in [http://www.mikrocontroller.net/topic/124509#1135568]).&lt;br /&gt;
&lt;br /&gt;
Beispiel für Windows ([http://www.mikrocontroller.net/topic/124509#1136322], [http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/redirection.mspx?mfr=true M$]):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrdude -c avrispmkII -p m8 -P usb:xx -v &amp;gt; &amp;quot;C:\output.txt&amp;quot; 2&amp;gt;&amp;amp;1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
oder nur STDERR in Datei umleiten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrdude -c avrispmkII -p m8 -P usb:xx -v 2&amp;gt; &amp;quot;C:\output.txt&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [http://www.franzis.de/elektronik/lernpakete-elektronik/lernpaket-mikrocontroller Franzis] bzw. [http://www.elo-web.de/elo/mikrocontroller-und-programmierung/avr-grundlagen/experimente-mit-dem-attiny13 ELO] Lernpaket Mikrocontroller (Attiny13) ===&lt;br /&gt;
&lt;br /&gt;
Markus hat in [http://www.mikrocontroller.net/topic/169549#1649459] einen Weg beschrieben, wie man den einfachen Programmieradapter des Lernpakets mit AVRDUDE ansteuern kann.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Anleitung [http://www.elektronik-labor.de/AVR/AVRdude.html LP Mikrocontroller und Attiny45 mit Avrdude] gibt es von Ralf Beesner auf der Webseite des Entwicklers Burkhard Kainka. In &#039;&#039;avrdude.conf&#039;&#039; wird dabei ein neuer Programmieradapter namens &#039;&#039;burkhard&#039;&#039; hinzugefügt. Ein zweiter Eintrag &#039;&#039;burkhard2&#039;&#039; in dieser &#039;&#039;&#039;avrdude.conf&#039;&#039;&#039; ist für die Programmierung des Atmega8 auf dem Franzis Retro-Pong Bausatz mit Hilfe des &amp;quot;Mega8-ISP-Programmer&amp;quot; (Layout siehe ELO-Webseite) vorgesehen.&lt;br /&gt;
&lt;br /&gt;
=== AVRDUDE mit Arduino Bootloader benutzen ===&lt;br /&gt;
&lt;br /&gt;
Mit der Option &#039;&#039;-c stk500v1&#039;&#039; kann AVRDUDE den [[Bootloader]] in Arduino Boards ansprechen [http://www.mikrocontroller.net/topic/195963#1919654].&lt;br /&gt;
&lt;br /&gt;
Es existieren auch modifizierte Versionen von AVRDUDE, die einen Programmer namens &#039;&#039;arduino&#039;&#039; kennen (avrdude.conf untersuchen!). Damit lautet die Kommandozeile für ein Arduinoboard mit Atmega168 beispielsweise [http://www.neuraladvance.com/2010/04/08/using-avrdude-with-the-arduino-duemilanove/]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrdude -c arduino -p m168 -P usb -U flash:w:&amp;lt;filename&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Bootloader-Hacks von [http://www.ladyada.net/library/arduino/bootloader.html Ladyada] arbeiten nochmal etwas anders.&lt;br /&gt;
&lt;br /&gt;
Gelegentlich gibt es unter Windows Probleme mit der allgemeinen AVRDUDE Version und deren Handling der DTR/RTS Leitung ([[RS232]]). Es kann helfen unmittelbar von dem Absenden der Kommandozeile einen RESET auf dem Arduinoboard durchzuführen.&lt;br /&gt;
Ein kurzes letzen der DTR Leitung auf HIGH bewirkt ein RESET. So ist es möglich eine .bat Datei zu erstellen mit folgendem Code: (com6 ist ein Virtueller USB Comport) &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mode com6 dtr=on&lt;br /&gt;
avrdude -c arduino -p m168 -P \\.\com6 -U flash:w:&amp;lt;filename&amp;gt;&lt;br /&gt;
if %ERRORLEVEL%==0 goto fertig&lt;br /&gt;
Pause&lt;br /&gt;
:fertig&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== mysmartUSB V2.11 und ATtiny 13 ===&lt;br /&gt;
&lt;br /&gt;
mysmartUSB V2.11 verlangt -cavr910 als Programmer. Leider ist in avrdude&lt;br /&gt;
5.10 immer noch nich der ATtiny13 damit zu programmieren. Also in die&lt;br /&gt;
avrdude.conf folgendes mit unter ATtiny13 aufnehmen, so kann er dann&lt;br /&gt;
korrekt programmiert werden(inkl. Fuse Bits).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#------------------------------------------------------------&lt;br /&gt;
# ATtiny13&lt;br /&gt;
#------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
part&lt;br /&gt;
    id                  = &amp;quot;t13&amp;quot;;&lt;br /&gt;
    desc                = &amp;quot;ATtiny13&amp;quot;;&lt;br /&gt;
     has_debugwire = yes;&lt;br /&gt;
     flash_instr   = 0xB4, 0x0E, 0x1E;&lt;br /&gt;
     eeprom_instr  = 0xBB, 0xFE, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D,&lt;br /&gt;
               0xBC, 0x0E, 0xB4, 0x0E, 0xBA, 0x0D, 0xBB, 0xBC,&lt;br /&gt;
               0x99, 0xE1, 0xBB, 0xAC;&lt;br /&gt;
    stk500_devcode      = 0x14;&lt;br /&gt;
    avr910_devcode      = 0x55;&lt;br /&gt;
......&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Achtung! Programmieren geht auch mit -cavr911. Allerdings geht das Fuse&lt;br /&gt;
setzen nicht und man bekommt eine Fehlermeldung.(Programm läuft aber)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Reading | ################################################## | 100%&lt;br /&gt;
0.12s&lt;br /&gt;
&lt;br /&gt;
avrdude: verifying ...&lt;br /&gt;
avrdude: 226 bytes of flash verified&lt;br /&gt;
avrdude: reading input file &amp;quot;0x7a&amp;quot;&lt;br /&gt;
avrdude: writing lfuse (1 bytes):&lt;br /&gt;
&lt;br /&gt;
Writing |  ***failed;&lt;br /&gt;
################################################## | 100% 0.00s&lt;br /&gt;
&lt;br /&gt;
avrdude: 1 bytes of lfuse written&lt;br /&gt;
avrdude: verifying lfuse memory against 0x7a:&lt;br /&gt;
avrdude: load data lfuse data from input file 0x7a:&lt;br /&gt;
avrdude: input file 0x7a contains 1 bytes&lt;br /&gt;
avrdude: reading on-chip lfuse data:&lt;br /&gt;
&lt;br /&gt;
Reading | ################################################## | 100%&lt;br /&gt;
0.00s&lt;br /&gt;
&lt;br /&gt;
avrdude: verifying ...&lt;br /&gt;
avrdude: 1 bytes of lfuse verified&lt;br /&gt;
avrdude: reading input file &amp;quot;0xff&amp;quot;&lt;br /&gt;
avrdude: writing hfuse (1 bytes):&lt;br /&gt;
&lt;br /&gt;
Writing |  ***failed;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* Offizielle AVRDUDE Homepage unter http://www.nongnu.org/avrdude/&lt;br /&gt;
* User Manual (engl.) unter http://www.nongnu.org/avrdude/user-manual/avrdude.html#Top&lt;br /&gt;
* Kompilierte Windows Version mit USB Support http://yuki-lab.jp/hw/avrdude-GUI/avrdude-5.5-win32-bin.zip&lt;br /&gt;
* Kompilierte Windows Version avrdude 5.10 mit USB Support http://www.mikrocontroller.net/topic/163675#1594689&lt;br /&gt;
* Wer Interesse an der modifizierten Version von AVRDUDE und des AVR910-Programmer hat, kann sich bei http://www.fischl.de/thomas/elektronik/avr910e/ informieren. Der Programmer bleibt auch mit der Modifikation weiterhin kompatibel zu anderer Programmiersoftware.&lt;br /&gt;
* [[Burn-o-mat|AVR Burn-O-Mat]] GUI (Graphic User Interface) für AVRDUDE http://burn-o-mat.net mit FUSE-Editor (Java, für Windows und Linux)&lt;br /&gt;
* [http://www.soft-land.de/index.php?page=avrburner AVRBurner] Ponyprog ähnliche Oberfläche für AVRDUDE.&lt;br /&gt;
* [http://www.microstar.ir/download/SinaProg.zip SinaProg] SinaProg - avrdude GUI mit AVR Fuse Calculator.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Programmer und -Bootloader]]&lt;br /&gt;
[[Kategorie:Entwicklungstools]]&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVRDUDE&amp;diff=56966</id>
		<title>AVRDUDE</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVRDUDE&amp;diff=56966"/>
		<updated>2011-05-02T12:01:51Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: /* mysmartUSB V2.11 und ATtiny 13 */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Beschreibung ==&lt;br /&gt;
AVRDUDE (http://www.nongnu.org/avrdude/) ist eine Programmiersoftware für Atmel [[AVR]] Controller. &lt;br /&gt;
&lt;br /&gt;
Funktionen unter Anderem: &lt;br /&gt;
&lt;br /&gt;
* Übertragen von Programmcode in den Flash-Speicher&lt;br /&gt;
* Auslesen ungeschützen Codes aus dem Flash&lt;br /&gt;
* Setzen und Lesen von Fuse- und Lockbits (Siehe auch: [[AVR_Fuses#Vergleich_der_Fuses_bei_verschiedenen_Programmen|Vergleich der Fuses bei verschiedenen Programmen]])&lt;br /&gt;
* Schreiben und Lesen des EEPROMs&lt;br /&gt;
&lt;br /&gt;
AVRDUDE kann das [[STK500]] (auch mit Firmware 2.x als stk500v2), das Atmel AVRISP (auch mit Firmware 2.x als avrispv2 o.ä.), das Atmel AVRISP MKII (USB Ansteuerung mittels lib-usb bzw. lib-usb-W32), [[AVR_In_System_Programmer#USB | AVR910-kompatible]] Programmierer, den [[AVR Butterfly]]/AVR109-kompatible Bootloader, [[STK200]]-Programmierdongles und verschiedene andere Parallelport-Adapter sowie &amp;quot;serielle Statusportprogrammierer&amp;quot; (Siprog) ansteuern. Auch das Atmel JTAGICE (oder Nachbauten wie Bootice oder Evertool), Atmel JTAGICE-MKII und der AVR Dragon können als Programmierhardware genutzt werden.&lt;br /&gt;
&lt;br /&gt;
Das Programm ist unter MS-Windows (Cygwin nicht erforderlich), Linux, BSD, Solaris und Mac OS X lauffähig. Die Version für MS-Windows ist im [[WinAVR]]-Paket enthalten. Der Quellcode ist frei verfügbar (Lizenz beachten).&lt;br /&gt;
&lt;br /&gt;
Da alle AVRDUDE-Funktionen über Kommandozeilenparamter gesteuert werden können, eignet es sich gut zur Integration in Makefiles. Beispiele finden sich in der Makefile-Vorlage von [[WinAVR]] und Mfile. &lt;br /&gt;
&lt;br /&gt;
Die gesamte Konfiguration liegt in einer Textdatei (avrdude.conf), so dass sich bei Bedarf ein beliebiger neuer Parallelport-Programmierdongle oder auch ein noch nicht unterstützter AVR-Controller ergänzen lassen. Die Syntax für die Definition eines AVR-Controllers lehnt sich an die Datenblatt-Tabelle für die serielle Programmierung an, so dass man praktisch nur das Datenblatt &amp;quot;intelligent&amp;quot; abtippen muss.&lt;br /&gt;
&lt;br /&gt;
Für die Ansteuerung von Parallelport-Adaptern unter MS-Windows NT/2000/XP wird ein spezieller Porttreiber (giveio) mitgeliefert. Bei der Installation von [[WinAVR]] wird giveio bereits mitinstalliert. &lt;br /&gt;
&lt;br /&gt;
Programmer mit üblicher serieller Schnittstelle (RS232) benötigen keine zusätzliche Software oder Treiber zum Betrieb mit AVRDUDE. &lt;br /&gt;
&lt;br /&gt;
Für Hardware mit USB-Anschluss muss die lib-usb bzw. lib-usb-win32 installiert sein.&lt;br /&gt;
&lt;br /&gt;
===GUIs===&lt;br /&gt;
Bei [[WinAVR]] wird die grafische Oberfläche avrdude-gui.exe mitgeliefert.&lt;br /&gt;
&lt;br /&gt;
Für Windows, Linux und andere Betriebssysteme gibt zwei weitere GUIs: den in Java geschriebene [[Burn-o-mat|AVR Burn-O-Mat]] und den [http://www.soft-land.de/index.php?page=avrburner avrburner].&lt;br /&gt;
&lt;br /&gt;
Für Mac OS X gibt es noch [http://www.vonnieda.org/software/avrfuses AVRFuses.app]. AVRFuses muss beim ersten Starten auf den verwendeten Programmer und den Speicherort von AVRDUDE eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
GUIs vereinfachen vor allem Programmieren der Fuses.&lt;br /&gt;
&lt;br /&gt;
== Kurzanleitung für Linux und STK200 ==&lt;br /&gt;
&lt;br /&gt;
Dazu muss erst ein Hardware-Link auf die Printerport-Treiber eingerichtet werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
su&lt;br /&gt;
mknod /dev/parport0 c 99 0&lt;br /&gt;
chmod a+rw /dev/parport0&lt;br /&gt;
avrdude -p m8535 -c stk200 -e -U qqtraff.hex&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hinweis :&lt;br /&gt;
Bei USB Programmern ist zu beachten, dass diese durch das Betriebssystem auf einen anderen Port gelegt werden können, als im Beispiel angegeben.&lt;br /&gt;
Diesen Port kann man unter Anderem &amp;quot;im Terminal&amp;quot; mit dem Befehl&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
user@server: dmesg&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
ermitteln.&lt;br /&gt;
Alternativ kann man sich eine Auflistung der Ports, im Verzeichnis &amp;quot;/dev&amp;quot; anzeigen lassen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
user@server: ls /dev/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sollte man nicht sicher sein, auf welchem Port der Programmer liegt, kann man den Programmer nochmals ausstecken und &amp;quot;ls /dev/&amp;quot; ausführen. Der nun Fehlende Port, ist der Programmerport.&lt;br /&gt;
Diesen Port muss man statt &amp;quot;parport0&amp;quot; in die oben beschriebenen Terminalkommandos einsetzen.&lt;br /&gt;
&lt;br /&gt;
Siehe auch : &lt;br /&gt;
* [http://wiki.ctbot.de/index.php/AVR_ISP_Programmer#BlueMP3_bzw._STK200_kompatible_Flasher weitere Beispiele für avrdude Kommandos (http://wiki.ctbot.de/index.php)]&lt;br /&gt;
* [[AVR_In_System_Programmer#STK200-kompatibel]]&lt;br /&gt;
* http://www.mikrocontroller.net/topic/200390#new&lt;br /&gt;
&lt;br /&gt;
== Tipps + Tricks ==&lt;br /&gt;
&lt;br /&gt;
=== [[AVR_In_System_Programmer#Parallelport|Parallelport-Programmer]] an aktuellen PCs ===&lt;br /&gt;
Aktuelle PCs sind einfach zu schnell mit dem Bitgewackel an der parallelen Schnittstelle, vor allem für AVRs, die noch mit den 1 MHz im Auslieferungszustand laufen (maximal zulässiger ISP-Takt &amp;lt; 250 kHz). Neuere Versionen von avrdude unterstützen zu diesem Zweck eine Option &#039;&#039;&#039;-i &amp;lt;N&amp;gt;&#039;&#039;&#039;, wobei &amp;lt;N&amp;gt; die Anzahl der Mikrosekunden bezeichnet, die beim Bitwackeln zusätzlich zu warten ist. Einfach mal mit -i 10 anfangen und dann entweder die Fuses auf die Ziel-Taktfrequenz umstellen (falls diese wesentlich höher sein wird als die 1 MHz), oder sukkzessive mit kleineren Werten testen ([http://www.mikrocontroller.net/topic/83524#699933 Forenbeitrag von Jörg]).&lt;br /&gt;
&lt;br /&gt;
Die Option -i ist auch nützlich bei AVRs, die für einen langsamen Takt konfiguriert sind. Bei einem ATmega8, der mit einem 32.768 kHz Quarz läuft, kann es z.B. notwendig sein, die Option -i 90 zu verwenden. Den Zahlenwert ggf. ausprobieren.&lt;br /&gt;
&lt;br /&gt;
Manche Programmer werten die Option -i manchmal nicht aus, dann sollte man einen anderen Programmer versuchen.&lt;br /&gt;
&lt;br /&gt;
Beim USBTINY und USBASP kann man die Geschwindigkeit der SPI-Schnittstelle mit dem Parameter -B [Periodendauer in Mikrosekunden] begrenzen. Da beide Geräte durch Interrupts der Software-USB-Schnittstelle stark belastet werden, handelt es sich hier um die Maximalbitrate.&lt;br /&gt;
&lt;br /&gt;
Unter WinXPsp2 auf einem Thinkpad T40 lies sich die &amp;quot;avrdude: AVR device not responding&amp;quot;-Meldung beheben durch Ändern von Gerätemanager--&amp;gt;Ltp1--&amp;gt;Eigenschaften--&amp;gt;Anschlusseinstellungen--&amp;gt;Interrupt-nie-verwenden in &amp;quot;Jeden dem Anschluss zugewiesenem Interrupt verwenden&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===USB Programmer===&lt;br /&gt;
Ein Selbstbau USB-Programmer ist unter&lt;br /&gt;
[http://www.rototron.info/?Page=USBAVR/USBAVR.aspx http://www.rototron.info]&lt;br /&gt;
zu finden. Er läuft auch unter VISTA und benötigt mit der neuesten AVRDUDE Version keinen Treiber, da er im HID-Modus betrieben wird.&lt;br /&gt;
&lt;br /&gt;
==== libusb0.dll wird bei WinAvr 20070525 nicht gefunden====&lt;br /&gt;
[http://www.mikrocontroller.net/topic/83524#701461 Forenbeitrag von Paul]: Habe leider noch etwas zu bemängeln, und zwar meckerte avrdude, dass es die &amp;quot;libusb0.dll&amp;quot; nicht fand. Musste dann erst noch manuell den Pfad c:\winavr\utils\libusb\bin in die autoxecec.bat eintragen. Siehe auch [http://www.avrfreaks.net/index.php?name=PNphpBB2&amp;amp;file=viewtopic&amp;amp;p=373283 Diskussion bei www.avrfreaks.net]&lt;br /&gt;
&lt;br /&gt;
====Aufruf unter Linux als user (non-root)====&lt;br /&gt;
&lt;br /&gt;
Unter Linux kann häufig avrdude nur als user &#039;root&#039; auf den USB-Programmer zugreifen. Als normaler User bekommt man eine Fehlermeldung wie:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#avrdude -c usbtiny -p m8&lt;br /&gt;
 &lt;br /&gt;
avrdude: error: usbtiny_transmit: &lt;br /&gt;
error sending control message: &lt;br /&gt;
Operation not permitted&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dies liegt daran, dass die device-nodes, die beim Einstecken des USB-Programmers von udev angelegt werden, root zugeordnet sind. Man kann dies ändern, indem man udev-Regeln für die verwendeten Programmer anlegt. Unter Debian muß man dazu nur eine neue Datei, z.&amp;amp;nbsp;B. 015_usbprog.rules unter /etc/udev/rules.d anlegen, z.&amp;amp;nbsp;B. mit folgenden Inhalt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Atmel AVR ISP mkII&lt;br /&gt;
SUBSYSTEM==&amp;quot;usb&amp;quot;, SYSFS{idVendor}==&amp;quot;03eb&amp;quot;, SYSFS{idProduct}==&amp;quot;2104&amp;quot;, GROUP=&amp;quot;users&amp;quot;, MODE=&amp;quot;0660&amp;quot; &lt;br /&gt;
&lt;br /&gt;
# usbprog bootloader&lt;br /&gt;
ATTRS{idVendor}==&amp;quot;1781&amp;quot;, ATTRS{idProduct}==&amp;quot;0c62&amp;quot;, GROUP=&amp;quot;users&amp;quot;, MODE=&amp;quot;0660&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
# USBasp programmer&lt;br /&gt;
ATTRS{idVendor}==&amp;quot;16c0&amp;quot;, ATTRS{idProduct}==&amp;quot;05dc&amp;quot;, GROUP=&amp;quot;users&amp;quot;, MODE=&amp;quot;0660&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
# USBtiny programmer&lt;br /&gt;
ATTRS{idVendor}==&amp;quot;1781&amp;quot;, ATTRS{idProduct}==&amp;quot;0c9f&amp;quot;, GROUP=&amp;quot;users&amp;quot;, MODE=&amp;quot;0660&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
habe den alten Inhalt nur auskommentiert, weil ich das ganze nur mit dem mkII testen konnte. ...Nur falls sich jemand beschweren sollte.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Atmel AVR ISP mkII&lt;br /&gt;
ATTRS{idVendor}==&amp;quot;03eb&amp;quot;, ATTRS{idProduct}==&amp;quot;2104&amp;quot;, GROUP=&amp;quot;users&amp;quot;, MODE=&amp;quot;0660&amp;quot; &lt;br /&gt;
 &lt;br /&gt;
# usbprog bootloader&lt;br /&gt;
ATTRS{idVendor}==&amp;quot;1781&amp;quot;, ATTRS{idProduct}==&amp;quot;0c62&amp;quot;, GROUP=&amp;quot;users&amp;quot;, MODE=&amp;quot;0660&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
# USBasp programmer&lt;br /&gt;
ATTRS{idVendor}==&amp;quot;16c0&amp;quot;, ATTRS{idProduct}==&amp;quot;05dc&amp;quot;, GROUP=&amp;quot;users&amp;quot;, MODE=&amp;quot;0660&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
# USBtiny programmer&lt;br /&gt;
ATTRS{idVendor}==&amp;quot;1781&amp;quot;, ATTRS{idProduct}==&amp;quot;0c9f&amp;quot;, GROUP=&amp;quot;users&amp;quot;, MODE=&amp;quot;0660&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach muss in der Regel der udev-Dienst neu gestartet werden, was -- je nach System -- mit einem der beiden folgenden Befehle funktionieren sollte (natürlich nur als root):&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 /etc/init.d/udev restart&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
oder &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 service udev restart&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo /sbin/udevadm control --reload-rules&amp;lt;/pre&amp;gt; bei aktueller udev-version, oder&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo /sbin/udevcontrol --reload-rules&amp;lt;/pre&amp;gt;, bei älteren udev-versionen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Danach sollte der USB-Programmer erneut angeschlossen werden. Falls es immer noch nicht funktioniert kann es helfen, als GROUP &amp;quot;plugdev&amp;quot; statt &amp;quot;users&amp;quot; zu verwenden.&lt;br /&gt;
&lt;br /&gt;
Hiermit werden der AVR ISP mkII, der usbprog Bootloader, USBasp und USBtiny bekannt gemacht, so daß alle User in der Gruppe &amp;quot;users&amp;quot; darauf zugreifen können.&lt;br /&gt;
&lt;br /&gt;
Für weitere USB-Programmer muß man die entsprechende Zeile (mit ATTRS...) anlegen und die passenden Vendor und Product IDs eintragen.&lt;br /&gt;
&lt;br /&gt;
Siehe auch:&lt;br /&gt;
* [http://www.reactivated.net/writing_udev_rules.html Writing udev rules]&lt;br /&gt;
&lt;br /&gt;
=== Anzeige unterstützter AVRs ===&lt;br /&gt;
Wie die anderen Atmels bei avrdude heißen zeigt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrdude -?&lt;br /&gt;
avrdude -p ?&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== neuere AVRs hinzufügen ===&lt;br /&gt;
Manch neueres Silizium wird nicht erkannt da sich z.T. die IDs geändert haben. Um diese erfolgreich zu Programmieren empfiehlt sich ein eigenes config-File zu verwenden. Darin werden die &#039;fehlenden&#039; CPUs ergänzt:&lt;br /&gt;
&lt;br /&gt;
z.B. ATmega168P (Programmierung wie ATmega168): einfach den ATmega168 Teil duplizieren und die entsprechenden Änderungen (id, desc, signature) vornehmen&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#------------------------------------------------------------&lt;br /&gt;
# ATmega168P&lt;br /&gt;
#------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
part&lt;br /&gt;
    id              = &amp;quot;m168p&amp;quot;;&lt;br /&gt;
    desc            = &amp;quot;ATMEGA168P&amp;quot;;&lt;br /&gt;
     has_debugwire = yes;&lt;br /&gt;
     flash_instr   = 0xB6, 0x01, 0x11;&lt;br /&gt;
     eeprom_instr  = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00,&lt;br /&gt;
	             0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF,&lt;br /&gt;
	             0x99, 0xF9, 0xBB, 0xAF;&lt;br /&gt;
    stk500_devcode  = 0x86;&lt;br /&gt;
    # avr910_devcode = 0x;&lt;br /&gt;
    signature       = 0x1e 0x94 0x0b;&lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
danach kann, unter Angabe des neuen config-Files, auch ein ATmega168P programmiert werden, z.B.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrdude -pm168p -C ~/.avrdude.config.neu -cstk500v2 -v  -U flash:w:main.hex&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Anschluss an COM10 und höher (Windows) ===&lt;br /&gt;
&lt;br /&gt;
Wenn AVRDUDE unter Windows an COM10 und höher betrieben werden soll, ist eine andere Schreibweise für die Schnittstelle in der Kommandozeile nötig. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrdude -c stk500v2 -p m16 -P \\.\com13 -uF -vvvv 2&amp;gt; logfile.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In diesem Beispiel wird statt der gewohnten Schreibweise &#039;&#039;&#039;com13&#039;&#039;&#039; die spezielle Schreibweise  &#039;&#039;&#039;\\.\com13&#039;&#039;&#039; verwendet und es wird mit &#039;&#039;-vvvv 2&amp;gt; logfile.txt&#039;&#039; eine ausführliche Debugausgabe für Fragen im Forum erzeugt. Näheres hierzu in der  [http://www.mikrocontroller.net/topic/90401 Forumsdiskussion].&lt;br /&gt;
&lt;br /&gt;
=== AVRISPmkII + AVRDUDE + Window Vista (32) ===&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/topic/126594#1157327&lt;br /&gt;
&lt;br /&gt;
=== &amp;quot;avrdude was compiled without usb support&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Offenbar enthielt WinAVR-20100110 zunächst fälschlicherweise eine AVRDUDE Version ohne USB Support [http://www.mikrocontroller.net/topic/163022#1554907].&lt;br /&gt;
&lt;br /&gt;
Abhilfe:&lt;br /&gt;
 &lt;br /&gt;
1. WinAVR deinstallieren, gleiches Release (WinAVR-20100110) nocheinmal herunterladen und installieren (mindestens seit Anfang März 2010 enthält dieses Release avrdude in der Version 5.10 und bringt USB-Support mit).&lt;br /&gt;
&lt;br /&gt;
2. AVRDUDE selbst compilieren: http://www.mikrocontroller.net/topic/163675&lt;br /&gt;
&lt;br /&gt;
3. Compilierte Version 5.10 downloaden: http://www.mikrocontroller.net/topic/163675#1594689&lt;br /&gt;
&lt;br /&gt;
=== Textausgabe in Datei umleiten? ===&lt;br /&gt;
&lt;br /&gt;
Die Windows-&amp;quot;Shell&amp;quot; &#039;&#039;cmd&#039;&#039; benutzt für die Ausgabeumleitung die gleiche Syntax wie die Bourne-Shell (und damit auch&lt;br /&gt;
Bash): &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
programm &amp;gt;datei 2&amp;gt;&amp;amp;1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
zur Umleitung von STDOUT und STDERR in die gleiche Datei (Yalu in [http://www.mikrocontroller.net/topic/124509#1135568]).&lt;br /&gt;
&lt;br /&gt;
Beispiel für Windows ([http://www.mikrocontroller.net/topic/124509#1136322], [http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/redirection.mspx?mfr=true M$]):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrdude -c avrispmkII -p m8 -P usb:xx -v &amp;gt; &amp;quot;C:\output.txt&amp;quot; 2&amp;gt;&amp;amp;1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
oder nur STDERR in Datei umleiten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrdude -c avrispmkII -p m8 -P usb:xx -v 2&amp;gt; &amp;quot;C:\output.txt&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [http://www.franzis.de/elektronik/lernpakete-elektronik/lernpaket-mikrocontroller Franzis] bzw. [http://www.elo-web.de/elo/mikrocontroller-und-programmierung/avr-grundlagen/experimente-mit-dem-attiny13 ELO] Lernpaket Mikrocontroller (Attiny13) ===&lt;br /&gt;
&lt;br /&gt;
Markus hat in [http://www.mikrocontroller.net/topic/169549#1649459] einen Weg beschrieben, wie man den einfachen Programmieradapter des Lernpakets mit AVRDUDE ansteuern kann.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Anleitung [http://www.elektronik-labor.de/AVR/AVRdude.html LP Mikrocontroller und Attiny45 mit Avrdude] gibt es von Ralf Beesner auf der Webseite des Entwicklers Burkhard Kainka. In &#039;&#039;avrdude.conf&#039;&#039; wird dabei ein neuer Programmieradapter namens &#039;&#039;burkhard&#039;&#039; hinzugefügt. Ein zweiter Eintrag &#039;&#039;burkhard2&#039;&#039; in dieser &#039;&#039;&#039;avrdude.conf&#039;&#039;&#039; ist für die Programmierung des Atmega8 auf dem Franzis Retro-Pong Bausatz mit Hilfe des &amp;quot;Mega8-ISP-Programmer&amp;quot; (Layout siehe ELO-Webseite) vorgesehen.&lt;br /&gt;
&lt;br /&gt;
=== AVRDUDE mit Arduino Bootloader benutzen ===&lt;br /&gt;
&lt;br /&gt;
Mit der Option &#039;&#039;-c stk500v1&#039;&#039; kann AVRDUDE den [[Bootloader]] in Arduino Boards ansprechen [http://www.mikrocontroller.net/topic/195963#1919654].&lt;br /&gt;
&lt;br /&gt;
Es existieren auch modifizierte Versionen von AVRDUDE, die einen Programmer namens &#039;&#039;arduino&#039;&#039; kennen (avrdude.conf untersuchen!). Damit lautet die Kommandozeile für ein Arduinoboard mit Atmega168 beispielsweise [http://www.neuraladvance.com/2010/04/08/using-avrdude-with-the-arduino-duemilanove/]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrdude -c arduino -p m168 -P usb -U flash:w:&amp;lt;filename&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Bootloader-Hacks von [http://www.ladyada.net/library/arduino/bootloader.html Ladyada] arbeiten nochmal etwas anders.&lt;br /&gt;
&lt;br /&gt;
Gelegentlich gibt es unter Windows Probleme mit der allgemeinen AVRDUDE Version und deren Handling der DTR/RTS Leitung ([[RS232]]). Es kann helfen unmittelbar von dem Absenden der Kommandozeile einen RESET auf dem Arduinoboard durchzuführen.&lt;br /&gt;
Ein kurzes letzen der DTR Leitung auf HIGH bewirkt ein RESET. So ist es möglich eine .bat Datei zu erstellen mit folgendem Code: (com6 ist ein Virtueller USB Comport) &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mode com6 dtr=on&lt;br /&gt;
avrdude -c arduino -p m168 -P \\.\com6 -U flash:w:&amp;lt;filename&amp;gt;&lt;br /&gt;
if %ERRORLEVEL%==0 goto fertig&lt;br /&gt;
Pause&lt;br /&gt;
:fertig&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== mysmartUSB V2.11 und ATtiny 13 ===&lt;br /&gt;
&lt;br /&gt;
mysmartUSB V2.11 verlangt -cavr910 als Programmer. Leider ist in avrdude&lt;br /&gt;
5.10 immer noch nich der ATtiny13 damit zu programmieren. Also in die&lt;br /&gt;
avrdude.conf folgendes mit unter ATtiny13 aufnehmen, so kann er dann&lt;br /&gt;
korrekt programmiert werden(inkl. Fuse Bits).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#------------------------------------------------------------&lt;br /&gt;
# ATtiny13&lt;br /&gt;
#------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
part&lt;br /&gt;
    id                  = &amp;quot;t13&amp;quot;;&lt;br /&gt;
    desc                = &amp;quot;ATtiny13&amp;quot;;&lt;br /&gt;
     has_debugwire = yes;&lt;br /&gt;
     flash_instr   = 0xB4, 0x0E, 0x1E;&lt;br /&gt;
     eeprom_instr  = 0xBB, 0xFE, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D,&lt;br /&gt;
               0xBC, 0x0E, 0xB4, 0x0E, 0xBA, 0x0D, 0xBB, 0xBC,&lt;br /&gt;
               0x99, 0xE1, 0xBB, 0xAC;&lt;br /&gt;
    stk500_devcode      = 0x14;&lt;br /&gt;
    avr910_devcode      = 0x55;&lt;br /&gt;
......&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Achtung! Programmieren geht auch mit -cavr911. Allerdings geht das Fuse&lt;br /&gt;
setzen nicht und man bekommt eine Fehlermeldung.(Programm läuft aber)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Reading | ################################################## | 100%&lt;br /&gt;
0.12s&lt;br /&gt;
&lt;br /&gt;
avrdude: verifying ...&lt;br /&gt;
avrdude: 226 bytes of flash verified&lt;br /&gt;
avrdude: reading input file &amp;quot;0x7a&amp;quot;&lt;br /&gt;
avrdude: writing lfuse (1 bytes):&lt;br /&gt;
&lt;br /&gt;
Writing |  ***failed;&lt;br /&gt;
################################################## | 100% 0.00s&lt;br /&gt;
&lt;br /&gt;
avrdude: 1 bytes of lfuse written&lt;br /&gt;
avrdude: verifying lfuse memory against 0x7a:&lt;br /&gt;
avrdude: load data lfuse data from input file 0x7a:&lt;br /&gt;
avrdude: input file 0x7a contains 1 bytes&lt;br /&gt;
avrdude: reading on-chip lfuse data:&lt;br /&gt;
&lt;br /&gt;
Reading | ################################################## | 100%&lt;br /&gt;
0.00s&lt;br /&gt;
&lt;br /&gt;
avrdude: verifying ...&lt;br /&gt;
avrdude: 1 bytes of lfuse verified&lt;br /&gt;
avrdude: reading input file &amp;quot;0xff&amp;quot;&lt;br /&gt;
avrdude: writing hfuse (1 bytes):&lt;br /&gt;
&lt;br /&gt;
Writing |  ***failed;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* Offizielle AVRDUDE Homepage unter http://www.nongnu.org/avrdude/&lt;br /&gt;
* User Manual (engl.) unter http://www.nongnu.org/avrdude/user-manual/avrdude.html#Top&lt;br /&gt;
* Kompilierte Windows Version mit USB Support http://yuki-lab.jp/hw/avrdude-GUI/avrdude-5.5-win32-bin.zip&lt;br /&gt;
* Kompilierte Windows Version avrdude 5.10 mit USB Support http://www.mikrocontroller.net/topic/163675#1594689&lt;br /&gt;
* Wer Interesse an der modifizierten Version von AVRDUDE und des AVR910-Programmer hat, kann sich bei http://www.fischl.de/thomas/elektronik/avr910e/ informieren. Der Programmer bleibt auch mit der Modifikation weiterhin kompatibel zu anderer Programmiersoftware.&lt;br /&gt;
* [[Burn-o-mat|AVR Burn-O-Mat]] GUI (Graphic User Interface) für AVRDUDE http://burn-o-mat.net mit FUSE-Editor (Java, für Windows und Linux)&lt;br /&gt;
* [http://myavr.de/myForum/viewtopic.php?t=1913 mysmartusb AVR910-Devcodes] für moderne AVRs (Firmware 2.3). Kann zur Anpassung von AVRDUDE in avrdude.conf verwendet werden.&lt;br /&gt;
* [http://www.soft-land.de/index.php?page=avrburner AVRBurner] Ponyprog ähnliche Oberfläche für AVRDUDE.&lt;br /&gt;
* [http://www.microstar.ir/download/SinaProg.zip SinaProg] SinaProg - avrdude GUI mit AVR Fuse Calculator.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Programmer und -Bootloader]]&lt;br /&gt;
[[Kategorie:Entwicklungstools]]&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVRDUDE&amp;diff=56965</id>
		<title>AVRDUDE</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVRDUDE&amp;diff=56965"/>
		<updated>2011-05-02T12:01:19Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: &amp;quot;mysmartUSB V2.11 und ATtiny 13&amp;quot; hinzugefügt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Beschreibung ==&lt;br /&gt;
AVRDUDE (http://www.nongnu.org/avrdude/) ist eine Programmiersoftware für Atmel [[AVR]] Controller. &lt;br /&gt;
&lt;br /&gt;
Funktionen unter Anderem: &lt;br /&gt;
&lt;br /&gt;
* Übertragen von Programmcode in den Flash-Speicher&lt;br /&gt;
* Auslesen ungeschützen Codes aus dem Flash&lt;br /&gt;
* Setzen und Lesen von Fuse- und Lockbits (Siehe auch: [[AVR_Fuses#Vergleich_der_Fuses_bei_verschiedenen_Programmen|Vergleich der Fuses bei verschiedenen Programmen]])&lt;br /&gt;
* Schreiben und Lesen des EEPROMs&lt;br /&gt;
&lt;br /&gt;
AVRDUDE kann das [[STK500]] (auch mit Firmware 2.x als stk500v2), das Atmel AVRISP (auch mit Firmware 2.x als avrispv2 o.ä.), das Atmel AVRISP MKII (USB Ansteuerung mittels lib-usb bzw. lib-usb-W32), [[AVR_In_System_Programmer#USB | AVR910-kompatible]] Programmierer, den [[AVR Butterfly]]/AVR109-kompatible Bootloader, [[STK200]]-Programmierdongles und verschiedene andere Parallelport-Adapter sowie &amp;quot;serielle Statusportprogrammierer&amp;quot; (Siprog) ansteuern. Auch das Atmel JTAGICE (oder Nachbauten wie Bootice oder Evertool), Atmel JTAGICE-MKII und der AVR Dragon können als Programmierhardware genutzt werden.&lt;br /&gt;
&lt;br /&gt;
Das Programm ist unter MS-Windows (Cygwin nicht erforderlich), Linux, BSD, Solaris und Mac OS X lauffähig. Die Version für MS-Windows ist im [[WinAVR]]-Paket enthalten. Der Quellcode ist frei verfügbar (Lizenz beachten).&lt;br /&gt;
&lt;br /&gt;
Da alle AVRDUDE-Funktionen über Kommandozeilenparamter gesteuert werden können, eignet es sich gut zur Integration in Makefiles. Beispiele finden sich in der Makefile-Vorlage von [[WinAVR]] und Mfile. &lt;br /&gt;
&lt;br /&gt;
Die gesamte Konfiguration liegt in einer Textdatei (avrdude.conf), so dass sich bei Bedarf ein beliebiger neuer Parallelport-Programmierdongle oder auch ein noch nicht unterstützter AVR-Controller ergänzen lassen. Die Syntax für die Definition eines AVR-Controllers lehnt sich an die Datenblatt-Tabelle für die serielle Programmierung an, so dass man praktisch nur das Datenblatt &amp;quot;intelligent&amp;quot; abtippen muss.&lt;br /&gt;
&lt;br /&gt;
Für die Ansteuerung von Parallelport-Adaptern unter MS-Windows NT/2000/XP wird ein spezieller Porttreiber (giveio) mitgeliefert. Bei der Installation von [[WinAVR]] wird giveio bereits mitinstalliert. &lt;br /&gt;
&lt;br /&gt;
Programmer mit üblicher serieller Schnittstelle (RS232) benötigen keine zusätzliche Software oder Treiber zum Betrieb mit AVRDUDE. &lt;br /&gt;
&lt;br /&gt;
Für Hardware mit USB-Anschluss muss die lib-usb bzw. lib-usb-win32 installiert sein.&lt;br /&gt;
&lt;br /&gt;
===GUIs===&lt;br /&gt;
Bei [[WinAVR]] wird die grafische Oberfläche avrdude-gui.exe mitgeliefert.&lt;br /&gt;
&lt;br /&gt;
Für Windows, Linux und andere Betriebssysteme gibt zwei weitere GUIs: den in Java geschriebene [[Burn-o-mat|AVR Burn-O-Mat]] und den [http://www.soft-land.de/index.php?page=avrburner avrburner].&lt;br /&gt;
&lt;br /&gt;
Für Mac OS X gibt es noch [http://www.vonnieda.org/software/avrfuses AVRFuses.app]. AVRFuses muss beim ersten Starten auf den verwendeten Programmer und den Speicherort von AVRDUDE eingestellt werden.&lt;br /&gt;
&lt;br /&gt;
GUIs vereinfachen vor allem Programmieren der Fuses.&lt;br /&gt;
&lt;br /&gt;
== Kurzanleitung für Linux und STK200 ==&lt;br /&gt;
&lt;br /&gt;
Dazu muss erst ein Hardware-Link auf die Printerport-Treiber eingerichtet werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
su&lt;br /&gt;
mknod /dev/parport0 c 99 0&lt;br /&gt;
chmod a+rw /dev/parport0&lt;br /&gt;
avrdude -p m8535 -c stk200 -e -U qqtraff.hex&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hinweis :&lt;br /&gt;
Bei USB Programmern ist zu beachten, dass diese durch das Betriebssystem auf einen anderen Port gelegt werden können, als im Beispiel angegeben.&lt;br /&gt;
Diesen Port kann man unter Anderem &amp;quot;im Terminal&amp;quot; mit dem Befehl&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
user@server: dmesg&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
ermitteln.&lt;br /&gt;
Alternativ kann man sich eine Auflistung der Ports, im Verzeichnis &amp;quot;/dev&amp;quot; anzeigen lassen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
user@server: ls /dev/&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Sollte man nicht sicher sein, auf welchem Port der Programmer liegt, kann man den Programmer nochmals ausstecken und &amp;quot;ls /dev/&amp;quot; ausführen. Der nun Fehlende Port, ist der Programmerport.&lt;br /&gt;
Diesen Port muss man statt &amp;quot;parport0&amp;quot; in die oben beschriebenen Terminalkommandos einsetzen.&lt;br /&gt;
&lt;br /&gt;
Siehe auch : &lt;br /&gt;
* [http://wiki.ctbot.de/index.php/AVR_ISP_Programmer#BlueMP3_bzw._STK200_kompatible_Flasher weitere Beispiele für avrdude Kommandos (http://wiki.ctbot.de/index.php)]&lt;br /&gt;
* [[AVR_In_System_Programmer#STK200-kompatibel]]&lt;br /&gt;
* http://www.mikrocontroller.net/topic/200390#new&lt;br /&gt;
&lt;br /&gt;
== Tipps + Tricks ==&lt;br /&gt;
&lt;br /&gt;
=== [[AVR_In_System_Programmer#Parallelport|Parallelport-Programmer]] an aktuellen PCs ===&lt;br /&gt;
Aktuelle PCs sind einfach zu schnell mit dem Bitgewackel an der parallelen Schnittstelle, vor allem für AVRs, die noch mit den 1 MHz im Auslieferungszustand laufen (maximal zulässiger ISP-Takt &amp;lt; 250 kHz). Neuere Versionen von avrdude unterstützen zu diesem Zweck eine Option &#039;&#039;&#039;-i &amp;lt;N&amp;gt;&#039;&#039;&#039;, wobei &amp;lt;N&amp;gt; die Anzahl der Mikrosekunden bezeichnet, die beim Bitwackeln zusätzlich zu warten ist. Einfach mal mit -i 10 anfangen und dann entweder die Fuses auf die Ziel-Taktfrequenz umstellen (falls diese wesentlich höher sein wird als die 1 MHz), oder sukkzessive mit kleineren Werten testen ([http://www.mikrocontroller.net/topic/83524#699933 Forenbeitrag von Jörg]).&lt;br /&gt;
&lt;br /&gt;
Die Option -i ist auch nützlich bei AVRs, die für einen langsamen Takt konfiguriert sind. Bei einem ATmega8, der mit einem 32.768 kHz Quarz läuft, kann es z.B. notwendig sein, die Option -i 90 zu verwenden. Den Zahlenwert ggf. ausprobieren.&lt;br /&gt;
&lt;br /&gt;
Manche Programmer werten die Option -i manchmal nicht aus, dann sollte man einen anderen Programmer versuchen.&lt;br /&gt;
&lt;br /&gt;
Beim USBTINY und USBASP kann man die Geschwindigkeit der SPI-Schnittstelle mit dem Parameter -B [Periodendauer in Mikrosekunden] begrenzen. Da beide Geräte durch Interrupts der Software-USB-Schnittstelle stark belastet werden, handelt es sich hier um die Maximalbitrate.&lt;br /&gt;
&lt;br /&gt;
Unter WinXPsp2 auf einem Thinkpad T40 lies sich die &amp;quot;avrdude: AVR device not responding&amp;quot;-Meldung beheben durch Ändern von Gerätemanager--&amp;gt;Ltp1--&amp;gt;Eigenschaften--&amp;gt;Anschlusseinstellungen--&amp;gt;Interrupt-nie-verwenden in &amp;quot;Jeden dem Anschluss zugewiesenem Interrupt verwenden&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===USB Programmer===&lt;br /&gt;
Ein Selbstbau USB-Programmer ist unter&lt;br /&gt;
[http://www.rototron.info/?Page=USBAVR/USBAVR.aspx http://www.rototron.info]&lt;br /&gt;
zu finden. Er läuft auch unter VISTA und benötigt mit der neuesten AVRDUDE Version keinen Treiber, da er im HID-Modus betrieben wird.&lt;br /&gt;
&lt;br /&gt;
==== libusb0.dll wird bei WinAvr 20070525 nicht gefunden====&lt;br /&gt;
[http://www.mikrocontroller.net/topic/83524#701461 Forenbeitrag von Paul]: Habe leider noch etwas zu bemängeln, und zwar meckerte avrdude, dass es die &amp;quot;libusb0.dll&amp;quot; nicht fand. Musste dann erst noch manuell den Pfad c:\winavr\utils\libusb\bin in die autoxecec.bat eintragen. Siehe auch [http://www.avrfreaks.net/index.php?name=PNphpBB2&amp;amp;file=viewtopic&amp;amp;p=373283 Diskussion bei www.avrfreaks.net]&lt;br /&gt;
&lt;br /&gt;
====Aufruf unter Linux als user (non-root)====&lt;br /&gt;
&lt;br /&gt;
Unter Linux kann häufig avrdude nur als user &#039;root&#039; auf den USB-Programmer zugreifen. Als normaler User bekommt man eine Fehlermeldung wie:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#avrdude -c usbtiny -p m8&lt;br /&gt;
 &lt;br /&gt;
avrdude: error: usbtiny_transmit: &lt;br /&gt;
error sending control message: &lt;br /&gt;
Operation not permitted&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dies liegt daran, dass die device-nodes, die beim Einstecken des USB-Programmers von udev angelegt werden, root zugeordnet sind. Man kann dies ändern, indem man udev-Regeln für die verwendeten Programmer anlegt. Unter Debian muß man dazu nur eine neue Datei, z.&amp;amp;nbsp;B. 015_usbprog.rules unter /etc/udev/rules.d anlegen, z.&amp;amp;nbsp;B. mit folgenden Inhalt:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Atmel AVR ISP mkII&lt;br /&gt;
SUBSYSTEM==&amp;quot;usb&amp;quot;, SYSFS{idVendor}==&amp;quot;03eb&amp;quot;, SYSFS{idProduct}==&amp;quot;2104&amp;quot;, GROUP=&amp;quot;users&amp;quot;, MODE=&amp;quot;0660&amp;quot; &lt;br /&gt;
&lt;br /&gt;
# usbprog bootloader&lt;br /&gt;
ATTRS{idVendor}==&amp;quot;1781&amp;quot;, ATTRS{idProduct}==&amp;quot;0c62&amp;quot;, GROUP=&amp;quot;users&amp;quot;, MODE=&amp;quot;0660&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
# USBasp programmer&lt;br /&gt;
ATTRS{idVendor}==&amp;quot;16c0&amp;quot;, ATTRS{idProduct}==&amp;quot;05dc&amp;quot;, GROUP=&amp;quot;users&amp;quot;, MODE=&amp;quot;0660&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
# USBtiny programmer&lt;br /&gt;
ATTRS{idVendor}==&amp;quot;1781&amp;quot;, ATTRS{idProduct}==&amp;quot;0c9f&amp;quot;, GROUP=&amp;quot;users&amp;quot;, MODE=&amp;quot;0660&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
habe den alten Inhalt nur auskommentiert, weil ich das ganze nur mit dem mkII testen konnte. ...Nur falls sich jemand beschweren sollte.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Atmel AVR ISP mkII&lt;br /&gt;
ATTRS{idVendor}==&amp;quot;03eb&amp;quot;, ATTRS{idProduct}==&amp;quot;2104&amp;quot;, GROUP=&amp;quot;users&amp;quot;, MODE=&amp;quot;0660&amp;quot; &lt;br /&gt;
 &lt;br /&gt;
# usbprog bootloader&lt;br /&gt;
ATTRS{idVendor}==&amp;quot;1781&amp;quot;, ATTRS{idProduct}==&amp;quot;0c62&amp;quot;, GROUP=&amp;quot;users&amp;quot;, MODE=&amp;quot;0660&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
# USBasp programmer&lt;br /&gt;
ATTRS{idVendor}==&amp;quot;16c0&amp;quot;, ATTRS{idProduct}==&amp;quot;05dc&amp;quot;, GROUP=&amp;quot;users&amp;quot;, MODE=&amp;quot;0660&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
# USBtiny programmer&lt;br /&gt;
ATTRS{idVendor}==&amp;quot;1781&amp;quot;, ATTRS{idProduct}==&amp;quot;0c9f&amp;quot;, GROUP=&amp;quot;users&amp;quot;, MODE=&amp;quot;0660&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach muss in der Regel der udev-Dienst neu gestartet werden, was -- je nach System -- mit einem der beiden folgenden Befehle funktionieren sollte (natürlich nur als root):&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 /etc/init.d/udev restart&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
oder &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 service udev restart&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo /sbin/udevadm control --reload-rules&amp;lt;/pre&amp;gt; bei aktueller udev-version, oder&lt;br /&gt;
&amp;lt;pre&amp;gt;sudo /sbin/udevcontrol --reload-rules&amp;lt;/pre&amp;gt;, bei älteren udev-versionen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Danach sollte der USB-Programmer erneut angeschlossen werden. Falls es immer noch nicht funktioniert kann es helfen, als GROUP &amp;quot;plugdev&amp;quot; statt &amp;quot;users&amp;quot; zu verwenden.&lt;br /&gt;
&lt;br /&gt;
Hiermit werden der AVR ISP mkII, der usbprog Bootloader, USBasp und USBtiny bekannt gemacht, so daß alle User in der Gruppe &amp;quot;users&amp;quot; darauf zugreifen können.&lt;br /&gt;
&lt;br /&gt;
Für weitere USB-Programmer muß man die entsprechende Zeile (mit ATTRS...) anlegen und die passenden Vendor und Product IDs eintragen.&lt;br /&gt;
&lt;br /&gt;
Siehe auch:&lt;br /&gt;
* [http://www.reactivated.net/writing_udev_rules.html Writing udev rules]&lt;br /&gt;
&lt;br /&gt;
=== Anzeige unterstützter AVRs ===&lt;br /&gt;
Wie die anderen Atmels bei avrdude heißen zeigt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrdude -?&lt;br /&gt;
avrdude -p ?&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== neuere AVRs hinzufügen ===&lt;br /&gt;
Manch neueres Silizium wird nicht erkannt da sich z.T. die IDs geändert haben. Um diese erfolgreich zu Programmieren empfiehlt sich ein eigenes config-File zu verwenden. Darin werden die &#039;fehlenden&#039; CPUs ergänzt:&lt;br /&gt;
&lt;br /&gt;
z.B. ATmega168P (Programmierung wie ATmega168): einfach den ATmega168 Teil duplizieren und die entsprechenden Änderungen (id, desc, signature) vornehmen&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#------------------------------------------------------------&lt;br /&gt;
# ATmega168P&lt;br /&gt;
#------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
part&lt;br /&gt;
    id              = &amp;quot;m168p&amp;quot;;&lt;br /&gt;
    desc            = &amp;quot;ATMEGA168P&amp;quot;;&lt;br /&gt;
     has_debugwire = yes;&lt;br /&gt;
     flash_instr   = 0xB6, 0x01, 0x11;&lt;br /&gt;
     eeprom_instr  = 0xBD, 0xF2, 0xBD, 0xE1, 0xBB, 0xCF, 0xB4, 0x00,&lt;br /&gt;
	             0xBE, 0x01, 0xB6, 0x01, 0xBC, 0x00, 0xBB, 0xBF,&lt;br /&gt;
	             0x99, 0xF9, 0xBB, 0xAF;&lt;br /&gt;
    stk500_devcode  = 0x86;&lt;br /&gt;
    # avr910_devcode = 0x;&lt;br /&gt;
    signature       = 0x1e 0x94 0x0b;&lt;br /&gt;
&lt;br /&gt;
 ...&lt;br /&gt;
;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
danach kann, unter Angabe des neuen config-Files, auch ein ATmega168P programmiert werden, z.B.:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrdude -pm168p -C ~/.avrdude.config.neu -cstk500v2 -v  -U flash:w:main.hex&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Anschluss an COM10 und höher (Windows) ===&lt;br /&gt;
&lt;br /&gt;
Wenn AVRDUDE unter Windows an COM10 und höher betrieben werden soll, ist eine andere Schreibweise für die Schnittstelle in der Kommandozeile nötig. Beispiel:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrdude -c stk500v2 -p m16 -P \\.\com13 -uF -vvvv 2&amp;gt; logfile.txt&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In diesem Beispiel wird statt der gewohnten Schreibweise &#039;&#039;&#039;com13&#039;&#039;&#039; die spezielle Schreibweise  &#039;&#039;&#039;\\.\com13&#039;&#039;&#039; verwendet und es wird mit &#039;&#039;-vvvv 2&amp;gt; logfile.txt&#039;&#039; eine ausführliche Debugausgabe für Fragen im Forum erzeugt. Näheres hierzu in der  [http://www.mikrocontroller.net/topic/90401 Forumsdiskussion].&lt;br /&gt;
&lt;br /&gt;
=== AVRISPmkII + AVRDUDE + Window Vista (32) ===&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/topic/126594#1157327&lt;br /&gt;
&lt;br /&gt;
=== &amp;quot;avrdude was compiled without usb support&amp;quot; ===&lt;br /&gt;
&lt;br /&gt;
Offenbar enthielt WinAVR-20100110 zunächst fälschlicherweise eine AVRDUDE Version ohne USB Support [http://www.mikrocontroller.net/topic/163022#1554907].&lt;br /&gt;
&lt;br /&gt;
Abhilfe:&lt;br /&gt;
 &lt;br /&gt;
1. WinAVR deinstallieren, gleiches Release (WinAVR-20100110) nocheinmal herunterladen und installieren (mindestens seit Anfang März 2010 enthält dieses Release avrdude in der Version 5.10 und bringt USB-Support mit).&lt;br /&gt;
&lt;br /&gt;
2. AVRDUDE selbst compilieren: http://www.mikrocontroller.net/topic/163675&lt;br /&gt;
&lt;br /&gt;
3. Compilierte Version 5.10 downloaden: http://www.mikrocontroller.net/topic/163675#1594689&lt;br /&gt;
&lt;br /&gt;
=== Textausgabe in Datei umleiten? ===&lt;br /&gt;
&lt;br /&gt;
Die Windows-&amp;quot;Shell&amp;quot; &#039;&#039;cmd&#039;&#039; benutzt für die Ausgabeumleitung die gleiche Syntax wie die Bourne-Shell (und damit auch&lt;br /&gt;
Bash): &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
programm &amp;gt;datei 2&amp;gt;&amp;amp;1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
zur Umleitung von STDOUT und STDERR in die gleiche Datei (Yalu in [http://www.mikrocontroller.net/topic/124509#1135568]).&lt;br /&gt;
&lt;br /&gt;
Beispiel für Windows ([http://www.mikrocontroller.net/topic/124509#1136322], [http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/redirection.mspx?mfr=true M$]):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrdude -c avrispmkII -p m8 -P usb:xx -v &amp;gt; &amp;quot;C:\output.txt&amp;quot; 2&amp;gt;&amp;amp;1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
oder nur STDERR in Datei umleiten:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrdude -c avrispmkII -p m8 -P usb:xx -v 2&amp;gt; &amp;quot;C:\output.txt&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== [http://www.franzis.de/elektronik/lernpakete-elektronik/lernpaket-mikrocontroller Franzis] bzw. [http://www.elo-web.de/elo/mikrocontroller-und-programmierung/avr-grundlagen/experimente-mit-dem-attiny13 ELO] Lernpaket Mikrocontroller (Attiny13) ===&lt;br /&gt;
&lt;br /&gt;
Markus hat in [http://www.mikrocontroller.net/topic/169549#1649459] einen Weg beschrieben, wie man den einfachen Programmieradapter des Lernpakets mit AVRDUDE ansteuern kann.&lt;br /&gt;
&lt;br /&gt;
Eine weitere Anleitung [http://www.elektronik-labor.de/AVR/AVRdude.html LP Mikrocontroller und Attiny45 mit Avrdude] gibt es von Ralf Beesner auf der Webseite des Entwicklers Burkhard Kainka. In &#039;&#039;avrdude.conf&#039;&#039; wird dabei ein neuer Programmieradapter namens &#039;&#039;burkhard&#039;&#039; hinzugefügt. Ein zweiter Eintrag &#039;&#039;burkhard2&#039;&#039; in dieser &#039;&#039;&#039;avrdude.conf&#039;&#039;&#039; ist für die Programmierung des Atmega8 auf dem Franzis Retro-Pong Bausatz mit Hilfe des &amp;quot;Mega8-ISP-Programmer&amp;quot; (Layout siehe ELO-Webseite) vorgesehen.&lt;br /&gt;
&lt;br /&gt;
=== AVRDUDE mit Arduino Bootloader benutzen ===&lt;br /&gt;
&lt;br /&gt;
Mit der Option &#039;&#039;-c stk500v1&#039;&#039; kann AVRDUDE den [[Bootloader]] in Arduino Boards ansprechen [http://www.mikrocontroller.net/topic/195963#1919654].&lt;br /&gt;
&lt;br /&gt;
Es existieren auch modifizierte Versionen von AVRDUDE, die einen Programmer namens &#039;&#039;arduino&#039;&#039; kennen (avrdude.conf untersuchen!). Damit lautet die Kommandozeile für ein Arduinoboard mit Atmega168 beispielsweise [http://www.neuraladvance.com/2010/04/08/using-avrdude-with-the-arduino-duemilanove/]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrdude -c arduino -p m168 -P usb -U flash:w:&amp;lt;filename&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Bootloader-Hacks von [http://www.ladyada.net/library/arduino/bootloader.html Ladyada] arbeiten nochmal etwas anders.&lt;br /&gt;
&lt;br /&gt;
Gelegentlich gibt es unter Windows Probleme mit der allgemeinen AVRDUDE Version und deren Handling der DTR/RTS Leitung ([[RS232]]). Es kann helfen unmittelbar von dem Absenden der Kommandozeile einen RESET auf dem Arduinoboard durchzuführen.&lt;br /&gt;
Ein kurzes letzen der DTR Leitung auf HIGH bewirkt ein RESET. So ist es möglich eine .bat Datei zu erstellen mit folgendem Code: (com6 ist ein Virtueller USB Comport) &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
mode com6 dtr=on&lt;br /&gt;
avrdude -c arduino -p m168 -P \\.\com6 -U flash:w:&amp;lt;filename&amp;gt;&lt;br /&gt;
if %ERRORLEVEL%==0 goto fertig&lt;br /&gt;
Pause&lt;br /&gt;
:fertig&lt;br /&gt;
exit&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== mysmartUSB V2.11 und ATtiny 13 ==&lt;br /&gt;
&lt;br /&gt;
mysmartUSB V2.11 verlangt -cavr910 als Programmer. Leider ist in avrdude&lt;br /&gt;
5.10 immer noch nich der ATtiny13 damit zu programmieren. Also in die&lt;br /&gt;
avrdude.conf folgendes mit unter ATtiny13 aufnehmen, so kann er dann&lt;br /&gt;
korrekt programmiert werden(inkl. Fuse Bits).&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#------------------------------------------------------------&lt;br /&gt;
# ATtiny13&lt;br /&gt;
#------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
part&lt;br /&gt;
    id                  = &amp;quot;t13&amp;quot;;&lt;br /&gt;
    desc                = &amp;quot;ATtiny13&amp;quot;;&lt;br /&gt;
     has_debugwire = yes;&lt;br /&gt;
     flash_instr   = 0xB4, 0x0E, 0x1E;&lt;br /&gt;
     eeprom_instr  = 0xBB, 0xFE, 0xBB, 0xEE, 0xBB, 0xCC, 0xB2, 0x0D,&lt;br /&gt;
               0xBC, 0x0E, 0xB4, 0x0E, 0xBA, 0x0D, 0xBB, 0xBC,&lt;br /&gt;
               0x99, 0xE1, 0xBB, 0xAC;&lt;br /&gt;
    stk500_devcode      = 0x14;&lt;br /&gt;
    avr910_devcode      = 0x55;&lt;br /&gt;
......&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Achtung! Programmieren geht auch mit -cavr911. Allerdings geht das Fuse&lt;br /&gt;
setzen nicht und man bekommt eine Fehlermeldung.(Programm läuft aber)&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Reading | ################################################## | 100%&lt;br /&gt;
0.12s&lt;br /&gt;
&lt;br /&gt;
avrdude: verifying ...&lt;br /&gt;
avrdude: 226 bytes of flash verified&lt;br /&gt;
avrdude: reading input file &amp;quot;0x7a&amp;quot;&lt;br /&gt;
avrdude: writing lfuse (1 bytes):&lt;br /&gt;
&lt;br /&gt;
Writing |  ***failed;&lt;br /&gt;
################################################## | 100% 0.00s&lt;br /&gt;
&lt;br /&gt;
avrdude: 1 bytes of lfuse written&lt;br /&gt;
avrdude: verifying lfuse memory against 0x7a:&lt;br /&gt;
avrdude: load data lfuse data from input file 0x7a:&lt;br /&gt;
avrdude: input file 0x7a contains 1 bytes&lt;br /&gt;
avrdude: reading on-chip lfuse data:&lt;br /&gt;
&lt;br /&gt;
Reading | ################################################## | 100%&lt;br /&gt;
0.00s&lt;br /&gt;
&lt;br /&gt;
avrdude: verifying ...&lt;br /&gt;
avrdude: 1 bytes of lfuse verified&lt;br /&gt;
avrdude: reading input file &amp;quot;0xff&amp;quot;&lt;br /&gt;
avrdude: writing hfuse (1 bytes):&lt;br /&gt;
&lt;br /&gt;
Writing |  ***failed;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* Offizielle AVRDUDE Homepage unter http://www.nongnu.org/avrdude/&lt;br /&gt;
* User Manual (engl.) unter http://www.nongnu.org/avrdude/user-manual/avrdude.html#Top&lt;br /&gt;
* Kompilierte Windows Version mit USB Support http://yuki-lab.jp/hw/avrdude-GUI/avrdude-5.5-win32-bin.zip&lt;br /&gt;
* Kompilierte Windows Version avrdude 5.10 mit USB Support http://www.mikrocontroller.net/topic/163675#1594689&lt;br /&gt;
* Wer Interesse an der modifizierten Version von AVRDUDE und des AVR910-Programmer hat, kann sich bei http://www.fischl.de/thomas/elektronik/avr910e/ informieren. Der Programmer bleibt auch mit der Modifikation weiterhin kompatibel zu anderer Programmiersoftware.&lt;br /&gt;
* [[Burn-o-mat|AVR Burn-O-Mat]] GUI (Graphic User Interface) für AVRDUDE http://burn-o-mat.net mit FUSE-Editor (Java, für Windows und Linux)&lt;br /&gt;
* [http://myavr.de/myForum/viewtopic.php?t=1913 mysmartusb AVR910-Devcodes] für moderne AVRs (Firmware 2.3). Kann zur Anpassung von AVRDUDE in avrdude.conf verwendet werden.&lt;br /&gt;
* [http://www.soft-land.de/index.php?page=avrburner AVRBurner] Ponyprog ähnliche Oberfläche für AVRDUDE.&lt;br /&gt;
* [http://www.microstar.ir/download/SinaProg.zip SinaProg] SinaProg - avrdude GUI mit AVR Fuse Calculator.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Programmer und -Bootloader]]&lt;br /&gt;
[[Kategorie:Entwicklungstools]]&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_-_Die_genaue_Sekunde_/_RTC&amp;diff=39112</id>
		<title>AVR - Die genaue Sekunde / RTC</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_-_Die_genaue_Sekunde_/_RTC&amp;diff=39112"/>
		<updated>2009-09-18T13:20:19Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: /* RTC mit wenig Stromverbrauch */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
Oftmals sieht man Projekte, bei denen ein externer RTC-Baustein (engl. &#039;&#039;&#039;R&#039;&#039;&#039;eal &#039;&#039;&#039;T&#039;&#039;&#039;ime &#039;&#039;&#039;C&#039;&#039;&#039;lock, Echtzeituhr; z.B. PCF8583 mit [[I2C]]-Anschluss [http://www-us.semiconductors.philips.com/acrobat/datasheets/PCF8583_5.pdf Datenblatt (PDF)]) angeschlossen ist, ohne dessen Vorteil wirklich zu nutzen.&lt;br /&gt;
Der einzige Vorteil einer externen RTC ist nämlich nur, dass man die Zeitzählung während eines Ausfalls der Hauptstromversorgung über eine kleine Stützbatterie bei geringem Strombedarf fortsetzen kann.&lt;br /&gt;
 &lt;br /&gt;
Der Strombedarf eines externen RTC ist in der Regel etwas niedriger als die RTC Funktion eines Prozessors. Als Vergleich diene ein DS1302(300nA@2V) zu einem Mega32(5uA@2.7V) als nicht ganz neuer Vertreter, bzw. ein Mega324P(500nA@1.8V) als moderner Vertreter. Dieser Vorteil kommt bei Datenschreibern (engl. data logger) zum Tragen, welche die meiste Zeit inaktiv im [[Sleep Mode]] sind.&lt;br /&gt;
&lt;br /&gt;
In allen anderen Fällen ist die zusätzliche Hardware völlig unnötig und man kann eine präzise Zeitbasis bequem mit dem Hauptquarz des Mikrokontrollers programmieren. Daraus ergeben sich sogar noch zusätzliche Vorteile, wie eine geringere Temperaturabhängigkeit und höhere Güte, die Quarze im MHz-Bereich gegenüber Quarzen im kHz-Bereich besitzen. Ich möchte hiermit die Angst vor dem bisschen Mathematik nehmen, welche zur Berechnung der Teilerfaktoren benötigt wird.&lt;br /&gt;
&lt;br /&gt;
==Lösung==&lt;br /&gt;
&lt;br /&gt;
Speziell für den AVR kommen Quarze im Bereich 1MHz bis 16MHz zum Einsatz, d.h. in einer Sekunde werden 1.000.000 bis 16.000.000 Zyklen durchlaufen (Zyklen pro Sekunde = Frequenz). Möchte man eine Sekunde messen, kann man somit die entsprechende Anzahl Zyklen von Null an hochzählen oder von dem entsprechenden Wert bis auf 0 runterzählen. Für das Zählen bietet sich im µC der Compare-Modus eines Timers an.&lt;br /&gt;
&lt;br /&gt;
Die obigen Zahlen lassen sich jedoch nicht in einer 16 Bit Variablen ausdrücken da sie zu gross sind und somit ist ein direktes Setzen des Compare-Wertes des Timers T1 im AVR nicht möglich. Deshalb unterteilt man die Quarzfrequenz in zwei Faktoren; der erste (Softwareteiler) bestimmt die Periode des Timers T1 und der zweite den Reloadwert eines Registers, welches im Timerinterrupt runtergezählt wird.&lt;br /&gt;
&lt;br /&gt;
==Beispiel== &lt;br /&gt;
&lt;br /&gt;
Im Beispiel AVR wird ein 11,0592-MHz-Quarz verwendet, was einem üblichen [[Baudratenquarz]] entspricht, d.h. damit können die UART-Standardbaudraten erzeugt werden.&lt;br /&gt;
&lt;br /&gt;
Der Softwareteiler wird mit 256 gewählt, d.h. 256 Timerinterrupts pro Sekunde, und kann somit mit nur einem einzigen Byte realisiert werden. Für größere Werte muß der Softwareteiler als int (2 Byte) deklariert werden. Bei kleineren Werten als 256 muss man beachten, dass der zweite Faktor immer noch in 2 Byte passt, um als Comparewert für den 16-Bit-Timer 1 verwendet werden zu können. &lt;br /&gt;
&lt;br /&gt;
Die Timerroutine wird in einer Sekunde Softwareteiler-Mal aufgerufen. Mit diesen 256 Hz ergibt sich eine Timerinterruptzeit von ca. 4ms, die auch sehr gut zum Entprellen von Tasten benutzt werden kann. Eine Entprellroutine kann also bequem in den Timerinterrupt mit eingefügt werden. Beachten muss man nur noch, dass das Nullsetzen des Timers erst einen Zyklus nach dem Comparematch erfolgt. D.h. der Comparewert ist der gewünschte Teilerfaktor minus eins.&lt;br /&gt;
&lt;br /&gt;
==Berechnung==&lt;br /&gt;
&lt;br /&gt;
Die Berechnung des Comparewertes ist sehr einfach: &lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
Comparewert OCR1A = 11059200 / 256 - 1 = 43199, Rest 0. &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da haben wir ja noch mal Glück gehabt, es gibt keinen Rest bei der Division und die Sekunde ist exakt&lt;br /&gt;
256 * 43200 = 11059200 Zyklen lang.&amp;lt;br&amp;gt;&lt;br /&gt;
Theoretisch.&amp;lt;br&amp;gt;&lt;br /&gt;
Denn selbst wenn auf dem Quarz eine Frequenz von 11,0592 Mhz aufgedruckt ist, so schwingt er doch auf&lt;br /&gt;
einer etwas anderen Frequenz. Der Grund dafür sind Fertigungstoleranzen und natürlich die Tatsache, &lt;br /&gt;
dass die Frequenz eines Quarzes auch von der Temperatur abhängig ist. Es gilt also zunächst einmal&lt;br /&gt;
herauszufinden, auf welcher Frequenz der Quarz wirklich schwingt.&lt;br /&gt;
&lt;br /&gt;
Dazu wird eine Uhr programmiert und mit dem theoretischen Wert laufen gelassen. Nun habe ich die Uhr&lt;br /&gt;
einen Tag laufen lassen und festgestellt, dass sie 1,5 s nach geht (Dazu kann man beispielsweise die Tagesschau nutzen, welche jeden Tag um 20:00 (+einer konstanten Zeitverschiebung durch das Übertragungsmedium SAT,DVB-T, ...) beginnt und sogar eine Uhr dabei einblendet). D.h. die Quarzfrequenz beträgt in&lt;br /&gt;
Wirklichkeit: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
11059200 * (1 - 1,5 / 24 / 60 / 60) = 11059008 Hz. &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Ausführliche Rechnung:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
(Zyklen in 24h - Zyklen Verspätung) / Sekunden pro 24h = korrekte Frequenz&lt;br /&gt;
((24 * 60 * 60 * 256 * 43200) - (1,5 * 256 * 43200)) / (24 * 60 * 60) = 11059008 Hz.&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Also die ganze Rechnung nochmal: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
OCR1A = 11059008 / 256 - 1 = 43198, Rest 64. &lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Nun haben wir einen Rest und es würden uns jede Sekunde 64 Zyklen fehlen. Das geht natürlich nicht. &lt;br /&gt;
&lt;br /&gt;
Deshalb wird jedesmal, wenn der Softwareteiler Null ist und die Sekunde weitergezählt wird, ein&lt;br /&gt;
anderer Comparewert geladen. Dieser ist dann um den Rest größer. Und beim nächsten Timerinterrupt&lt;br /&gt;
wird dann wieder der Comparewert geladen, der das Ergebnis der Division war. &lt;br /&gt;
&lt;br /&gt;
Es ergeben sich somit: &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
255 * (43198 + 1) + 1 * (43198 + 64  + 1) = 11059008 Zyklen&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Exakt so, wie wir es wollten.&lt;br /&gt;
&lt;br /&gt;
==Das Programm== &lt;br /&gt;
&lt;br /&gt;
Nachfolgend nun das C-Programm. Da wir ja alle nicht gerne rechnen, lassen wir das einfach den C-Compiler erledigen. D.h. wir brauchen nur noch per Definition für XTAL den entsprechenden Wert eintragen und der Compiler rechnet alle nötigen Konstanten ganz alleine aus. &lt;br /&gt;
&lt;br /&gt;
So ein Compiler ist auch ziemlich faul, der merkt sofort, wenn die Operanden für eine Berechnung alles Konstanten sind. Und ehe er sich damit abquält, extra Code für diese Berechnungen zu erzeugen, rechnet er es lieber selber aus und fügt das Ergebnis direkt in den Code ein. &lt;br /&gt;
&lt;br /&gt;
Der Assembler kann auch 32-Bit Konstanten-Berechnungen ausführen. Allerdings muß man dann die entsprechenden Präprozessoroperationen benutzen. Man könnte auch eine Divisionsroutine aufrufen, aber dann würde ja echter Code erzeugt. &lt;br /&gt;
&lt;br /&gt;
===Beispiel in C===&lt;br /&gt;
&lt;br /&gt;
Wichtig: Ab Ver.1.4.0 haben sich Namen/Funktionen geändert: &amp;lt;br&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;quot;There are currently two different styles present for naming the vectors. One form uses names starting with SIG_, followed by a relatively verbose but arbitrarily chosen name describing the interrupt vector. This has been the only available style in avr-libc up to version 1.2.x.&lt;br /&gt;
&lt;br /&gt;
Starting with avr-libc version 1.4.0, a second style of interrupt vector names has been added, where a short phrase for the vector description is followed by _vect. The short phrase matches the vector name as described in the datasheet of the respective device (and in Atmel&#039;s XML files), with spaces replaced by an underscore and other non-alphanumeric characters dropped. Using the suffix _vect is intented to improve portability to other C compilers available for the AVR that use a similar naming convention....&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Quelle: http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/************************************************************************/&lt;br /&gt;
/*                                                                      */&lt;br /&gt;
/*          Precise 1 Second Timebase           */&lt;br /&gt;
/*                                                                      */&lt;br /&gt;
/*              Author: Peter Dannegger                                 */&lt;br /&gt;
/*                      danni@specs.de                                  */&lt;br /&gt;
/*                                                                      */&lt;br /&gt;
/************************************************************************/&lt;br /&gt;
// Target: Mega8, 2313&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;signal.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#ifndef OCR1A&lt;br /&gt;
#define OCR1A OCR1  // 2313 support&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#ifndef WGM12&lt;br /&gt;
#define WGM12 CTC1  // 2313 support&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#ifndef PINC&lt;br /&gt;
#define KEY_INPUT   PIND    // 2313&lt;br /&gt;
#else&lt;br /&gt;
#define KEY_INPUT   PINC    // Mega8&lt;br /&gt;
#endif&lt;br /&gt;
#define LED_DIR     DDRB&lt;br /&gt;
&lt;br /&gt;
//#define XTAL      11059201L   // nominal value&lt;br /&gt;
#define XTAL        11059008L   // after measuring deviation: 1.5s/d&lt;br /&gt;
&lt;br /&gt;
#define DEBOUNCE    256L        // debounce clock (256Hz = 4msec)&lt;br /&gt;
&lt;br /&gt;
#define uchar unsigned char&lt;br /&gt;
#define uint unsigned int&lt;br /&gt;
&lt;br /&gt;
uchar prescaler;&lt;br /&gt;
uchar volatile second;          // count seconds&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
SIGNAL (SIG_OUTPUT_COMPARE1A)&lt;br /&gt;
{&lt;br /&gt;
/************************************************************************/&lt;br /&gt;
/*          Insert Key Debouncing Here          */&lt;br /&gt;
/************************************************************************/&lt;br /&gt;
&lt;br /&gt;
#if XTAL % DEBOUNCE                     // bei rest&lt;br /&gt;
  OCR1A = XTAL / DEBOUNCE - 1;      // compare DEBOUNCE - 1 times&lt;br /&gt;
#endif&lt;br /&gt;
  if( --prescaler == 0 ){&lt;br /&gt;
    prescaler = (uchar)DEBOUNCE;&lt;br /&gt;
    second++;               // exact one second over&lt;br /&gt;
#if XTAL % DEBOUNCE         // handle remainder&lt;br /&gt;
    OCR1A = XTAL / DEBOUNCE + XTAL % DEBOUNCE - 1; // compare once per second&lt;br /&gt;
#endif&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main( void )&lt;br /&gt;
{&lt;br /&gt;
  LED_DIR = 0xFF;&lt;br /&gt;
  while( KEY_INPUT &amp;amp; 1 );               // start with key 0 pressed&lt;br /&gt;
&lt;br /&gt;
  TCCR1B = (1&amp;lt;&amp;lt;WGM12) | (1&amp;lt;&amp;lt;CS10);      // divide by 1&lt;br /&gt;
                    // clear on compare&lt;br /&gt;
  OCR1A = XTAL / DEBOUNCE - 1;          // Output Compare Register&lt;br /&gt;
  TCNT1 = 0;                            // Timmer startet mit 0&lt;br /&gt;
  second = 0;&lt;br /&gt;
  prescaler = (uchar)DEBOUNCE;          //software teiler&lt;br /&gt;
&lt;br /&gt;
  TIMSK = 1&amp;lt;&amp;lt;OCIE1A;                    // beim Vergleichswertes Compare Match                    &lt;br /&gt;
                                        // Interrupt (SIG_OUTPUT_COMPARE1A)&lt;br /&gt;
  sei();&lt;br /&gt;
&lt;br /&gt;
  for(;;){&lt;br /&gt;
    if( second == 60 )&lt;br /&gt;
      second = 0;&lt;br /&gt;
    PORTB = second;         // display second (binary)&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Beispiel in Assembler===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
;************************************************************************/&lt;br /&gt;
;*                                                                      */&lt;br /&gt;
;*          Precise 1 Second Timebase           */&lt;br /&gt;
;*                                                                      */&lt;br /&gt;
;*              Author: Peter Dannegger                                 */&lt;br /&gt;
;*                      danni@specs.de                                  */&lt;br /&gt;
;*                                                                      */&lt;br /&gt;
;************************************************************************/&lt;br /&gt;
.nolist&lt;br /&gt;
.include &amp;quot;m8def.inc&amp;quot;&lt;br /&gt;
&lt;br /&gt;
.equ    xtal      = 11059008&lt;br /&gt;
.equ    debounce  = 256&lt;br /&gt;
.equ    remainder = xtal - xtal / debounce * debounce&lt;br /&gt;
&lt;br /&gt;
.def    isreg     = r15&lt;br /&gt;
.def    wr0       = r16&lt;br /&gt;
.def    iwr0      = r17&lt;br /&gt;
.def    prescaler = r18&lt;br /&gt;
.def    second    = r19&lt;br /&gt;
&lt;br /&gt;
.list&lt;br /&gt;
    rjmp    init&lt;br /&gt;
.org    OC1Aaddr&lt;br /&gt;
    rjmp    OC1Aint&lt;br /&gt;
;-------------------------------------------------------------------------&lt;br /&gt;
OC1Aint:&lt;br /&gt;
    in  isreg, sreg&lt;br /&gt;
;************************************************************************/&lt;br /&gt;
;*          Insert Key Debouncing Here          */&lt;br /&gt;
;************************************************************************/&lt;br /&gt;
&lt;br /&gt;
    ldi iwr0, high( xtal / debounce - 1 )&lt;br /&gt;
    out ocr1ah, iwr0&lt;br /&gt;
    ldi iwr0, low( xtal / debounce - 1 )&lt;br /&gt;
    out ocr1al, iwr0&lt;br /&gt;
&lt;br /&gt;
    dec prescaler&lt;br /&gt;
    brne    _oci1&lt;br /&gt;
&lt;br /&gt;
    ldi prescaler, debounce&lt;br /&gt;
    inc second&lt;br /&gt;
&lt;br /&gt;
    ldi iwr0, high( xtal / debounce + remainder - 1 )&lt;br /&gt;
    out ocr1ah, iwr0&lt;br /&gt;
    ldi iwr0, low( xtal / debounce + remainder - 1 )&lt;br /&gt;
    out ocr1al, iwr0&lt;br /&gt;
_oci1:&lt;br /&gt;
    out sreg, isreg&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;
    sbic    pinc, 0&lt;br /&gt;
    rjmp    init&lt;br /&gt;
&lt;br /&gt;
    ldi wr0, high( ramend )&lt;br /&gt;
    out sph, wr0&lt;br /&gt;
    ldi wr0, low( ramend )&lt;br /&gt;
    out spl, wr0&lt;br /&gt;
&lt;br /&gt;
    ldi wr0, 1&amp;lt;&amp;lt;WGM12^1&amp;lt;&amp;lt;CS10&lt;br /&gt;
    out TCCR1B, wr0&lt;br /&gt;
&lt;br /&gt;
    ldi wr0, high( xtal / debounce - 1 )&lt;br /&gt;
    out ocr1ah, wr0&lt;br /&gt;
    ldi wr0, low( xtal / debounce - 1 )&lt;br /&gt;
    out ocr1al, wr0&lt;br /&gt;
    out tcnt1l, wr0&lt;br /&gt;
    ldi prescaler, debounce&lt;br /&gt;
&lt;br /&gt;
    ldi wr0, 1&amp;lt;&amp;lt;OCIE1A&lt;br /&gt;
    out TIMSK, wr0&lt;br /&gt;
    sei&lt;br /&gt;
main:&lt;br /&gt;
    ldi second, 0&lt;br /&gt;
_mai1:&lt;br /&gt;
    cpi second, 60&lt;br /&gt;
    breq    main&lt;br /&gt;
    out ddrb, second&lt;br /&gt;
    rjmp    _mai1&lt;br /&gt;
;------------------------------------&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Verbesserte Version mit durchlaufendem Hardwarezähler===&lt;br /&gt;
&lt;br /&gt;
Hier sind trotzdem kleine Verbesserungsvorschläge.&lt;br /&gt;
&lt;br /&gt;
Wird im Timer die Option &amp;quot;Clear On Compare Match&amp;quot; verwendet, so verliert man den Overflow Interrupt. Oder möchte man nebenher noch eine Zeit mit dem Capture Interrupt messen, so benötigt man einen durchlaufenden Timer. Um dies zu erreichen, wird OCR1A nicht fest eingestellt, sondern bei jedem Aufruf um den gleichen Wert erhöht.&lt;br /&gt;
&lt;br /&gt;
In Peters Code wurde der Rest auf einmal abgearbeitet. Damit erspart man sich bei jedem Interrupt einen Vergleich und die Verarbeitungszeit verkürzt sich in seinem Code. Der Unterschied zwischen kurzem und langem Interrupt ist hier der Rest. Bei den geänderten Codeschnipseln wird der Rest gleichmäßiger abgearbeitet. Der Unterschied zwischen kurzem und langem Interrupt beträgt 1 Takt.&lt;br /&gt;
&lt;br /&gt;
ungetesteter Code für den durchlaufenden Timer:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
SIGNAL (SIG_OUTPUT_COMPARE1A) {&lt;br /&gt;
/************************************************************************/&lt;br /&gt;
/*      Insert Key Debouncing Here      */&lt;br /&gt;
/************************************************************************/&lt;br /&gt;
&lt;br /&gt;
  if( --prescaler == 0 ){ &lt;br /&gt;
    prescaler = (uchar) DEBOUNCE;&lt;br /&gt;
    second++;      // exact one second over  &lt;br /&gt;
  }  &lt;br /&gt;
#if XTAL % DEBOUNCE&lt;br /&gt;
  if (prescaler &amp;lt;= XTAL % DEBOUNCE)&lt;br /&gt;
    OCR1A += XTAL / DEBOUNCE +1;   /* um 1 Takt längere Periode um den Rest abzutragen */&lt;br /&gt;
  else&lt;br /&gt;
#endif&lt;br /&gt;
    OCR1A += XTAL / DEBOUNCE;   /* kurze Periode */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Durchlaufender Hardwarezähler und fortlaufende Addition===&lt;br /&gt;
&lt;br /&gt;
Gänzlich ohne Hin- und Hertogglen eines Bits kommt man aus, wenn irgendein Timer mit einer Überlauf-Interruptfrequenz &amp;gt; 1Hz arbeitet. Dann kann die ISR eine 32-bit-Konstante auf einen 32-bit-Akkumulator addieren; bei Überlauf ist eine Sekunde vergangen. Zugegeben, es gibt &amp;quot;lange&amp;quot; und &amp;quot;kurze&amp;quot; Sekunden, aber der Fehler summiert sich nicht, und der Code ist sehr einfach.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel:&lt;br /&gt;
&lt;br /&gt;
Es gibt ein Programm gettick(), das einen Wert holt. Dieser Wert wird von Zeit zu Zeit von der Hardware (Beispiel AVR: der Timer) oder dem Betriebssystem (Beispiel Linux: gettick ruft getmsec, getmsec ruft gettimeofday)&lt;br /&gt;
&lt;br /&gt;
Dieser aufgerufene Wert sollte pro Sekunde um TICKPERSEC erhöht werden, was aber mit einer gewissen Ungenauigkeit geschieht.&lt;br /&gt;
&lt;br /&gt;
Die Laufzeitkorrektur wird dadurch ausgeführt, dass der von gettick() zurückgegebene Wert mit einem Faktor TFAK multipliziert wird. Der Faktor sollte so gewählt werden, dass:&lt;br /&gt;
&lt;br /&gt;
* Das Ergebnis actual_value immer in 32 Bit hineinpasst.&lt;br /&gt;
* Die Multiplikation durch Schiebeopertionen ersetzt werden kann, weil der Faktor eine 2-er-Potenz ist. (Das erledigt avr-gcc)&lt;br /&gt;
&lt;br /&gt;
Immer wenn tsdaytim_calibrated() erkennt, dass eine Sekunde vergangen, wird last_value um die Zahl onesecond erhöht.&lt;br /&gt;
&lt;br /&gt;
Der Zahlenwert onsecond wird mit TICKPERSEC*TFAK initalisiert und kann angezeigt oder neu eingegeben werden (Die Bedienung der seriellen Schnittstelle hierfür ist in diesem Beispiel nicht enthalten).&lt;br /&gt;
&lt;br /&gt;
Wenn festgestellt wird, dass die Uhr pro Zeit (P) um (E) zu schnell geht, dann kann der Wert onsecond korrigiert werden.&lt;br /&gt;
&lt;br /&gt;
c = d *  (P+E)/P&lt;br /&gt;
Beispiel Pro 7 Tage 120 Sekunden zu viel:&lt;br /&gt;
&lt;br /&gt;
7 Tage = 7*86400= 604800 sekunden&lt;br /&gt;
c = 992000000 * (604800+120)/604800=991803175&lt;br /&gt;
Dann wird die Uhr genauer gehen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/****************************************************************/&lt;br /&gt;
/* File home/cc/qq/danclock.cpp                                 */&lt;br /&gt;
/*          Precise 1 Second Timebase                           */&lt;br /&gt;
/*                                                              */&lt;br /&gt;
/*      Author: Peter Dannegger / Hjherbert                     */&lt;br /&gt;
/*          danni@specs.de                                      */&lt;br /&gt;
/*                                                              */&lt;br /&gt;
/****************************************************************/&lt;br /&gt;
// Target: atmega8, (2313?)&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
// #include &amp;lt;avr/signal.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#ifndef OCR1A&lt;br /&gt;
#define OCR1A OCR1  // 2313 support&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#ifndef WGM12&lt;br /&gt;
#define WGM12 CTC1  // 2313 support&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
#ifndef PINC&lt;br /&gt;
#define KEY_INPUT   PIND    // 2313&lt;br /&gt;
#else&lt;br /&gt;
#define KEY_INPUT   PINC    // Mega8&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
//#define F_CPU     11059201L   // nominal value&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define DIVISOR 256&lt;br /&gt;
&lt;br /&gt;
#define TICKPERSEC  (F_CPU/DIVISOR)&lt;br /&gt;
&lt;br /&gt;
uint8_t volatile second;            // count seconds&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
// TFAK ? TICKPERSEC must not exceed 2^32&lt;br /&gt;
#define TM (0x7FFFFFFFUL/2/TICKPERSEC)  // max of TFAK&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#define TFAK ( (  (TM&amp;gt;&amp;gt;1) | (TM&amp;gt;&amp;gt;2) | (TM&amp;gt;&amp;gt;3)  | (TM&amp;gt;&amp;gt;4)  | (TM&amp;gt;&amp;gt;5)  | (TM&amp;gt;&amp;gt;6)  | (TM&amp;gt;&amp;gt;7) \&lt;br /&gt;
           | (TM&amp;gt;&amp;gt;8) | (TM&amp;gt;&amp;gt;9) | (TM&amp;gt;&amp;gt;10) | (TM&amp;gt;&amp;gt;11)  | (TM&amp;gt;&amp;gt;12)  | (TM&amp;gt;&amp;gt;13)  | (TM&amp;gt;&amp;gt;14)  | (TM&amp;gt;&amp;gt;15) \&lt;br /&gt;
           | (TM&amp;gt;&amp;gt;16) | (TM&amp;gt;&amp;gt;17) | (TM&amp;gt;&amp;gt;18) | (TM&amp;gt;&amp;gt;19)  | (TM&amp;gt;&amp;gt;20)  | (TM&amp;gt;&amp;gt;21)  | (TM&amp;gt;&amp;gt;22)  | (TM&amp;gt;&amp;gt;23) \&lt;br /&gt;
           | (TM&amp;gt;&amp;gt;24) | (TM&amp;gt;&amp;gt;25) | (TM&amp;gt;&amp;gt;26) | (TM&amp;gt;&amp;gt;27)  | (TM&amp;gt;&amp;gt;28)  | (TM&amp;gt;&amp;gt;29)  | (TM&amp;gt;&amp;gt;30)  | (TM&amp;gt;&amp;gt;31) \&lt;br /&gt;
           ) + 1 )&lt;br /&gt;
// TFAK is a power the biggest power of two which is less than TM&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
uint32_t onesecond = 1*TICKPERSEC*TFAK ;    // correct this value if see the clock is late / too fast&lt;br /&gt;
uint32_t last_value ;&lt;br /&gt;
uint32_t ticks ;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
SIGNAL (SIG_OUTPUT_COMPARE1A)&lt;br /&gt;
{&lt;br /&gt;
++ticks ;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
uint32_t gettick( void )&lt;br /&gt;
{&lt;br /&gt;
uint32_t l ;&lt;br /&gt;
cli();&lt;br /&gt;
l = ticks ;&lt;br /&gt;
sei();&lt;br /&gt;
return l ;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void tsdaytim_calibrated(void)&lt;br /&gt;
// Keep the time-of-the-day actual&lt;br /&gt;
// Add a second, if a second if gone&lt;br /&gt;
{&lt;br /&gt;
uint32_t actual_value ;         // gettick() multiplied by factor 2^n&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
actual_value = gettick() * TFAK ;   // because TFAK is a power of two&lt;br /&gt;
                                    // The compiler will create some shift commands&lt;br /&gt;
&lt;br /&gt;
if ( actual_value - last_value &amp;gt; onesecond )&lt;br /&gt;
    {                           // once per second&lt;br /&gt;
    if ( ++second &amp;gt;= 60 )&lt;br /&gt;
        {&lt;br /&gt;
        second = 0 ;&lt;br /&gt;
        }&lt;br /&gt;
    last_value += onesecond ;   // One second more&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main( void )&lt;br /&gt;
{&lt;br /&gt;
DDRB = 0xFF;&lt;br /&gt;
while( KEY_INPUT &amp;amp; 1 );         // start with key 0 pressed&lt;br /&gt;
&lt;br /&gt;
TCCR1B = 1&amp;lt;&amp;lt;WGM12^1&amp;lt;&amp;lt;CS10;      // divide by 1&lt;br /&gt;
                                // clear on compare&lt;br /&gt;
OCR1A = DIVISOR ;               // Output Compare Register&lt;br /&gt;
TCNT1 = 0;                      // Timer start value&lt;br /&gt;
second = 0;&lt;br /&gt;
&lt;br /&gt;
TIMSK = 1&amp;lt;&amp;lt;OCIE1A;              // beim Vergleichswertes Compare Match&lt;br /&gt;
                                // Interrupt (SIG_OUTPUT_COMPARE1A)&lt;br /&gt;
sei();&lt;br /&gt;
last_value = gettick() * TFAK ;&lt;br /&gt;
for(;;)&lt;br /&gt;
    {&lt;br /&gt;
    tsdaytim_calibrated();&lt;br /&gt;
    PORTB = second;             // display second (binary)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Echtzeituhr mit Uhrenquarz ==&lt;br /&gt;
&lt;br /&gt;
=== RTC mit wenig Stromverbrauch ===&lt;br /&gt;
&lt;br /&gt;
Das vorgestellte Verfahren ist leider nicht direkt anwendbar, wenn man eine RTC mit einem 32,768 KHz Uhrenquarz realisieren möchte. Dieser Weg ist dann notwendig, wenn der Controller [[Ultra low power | batteriebetrieben]] sehr lange laufen soll und durch Verwendung des [[Sleep Mode]] Strom gespart wird.&lt;br /&gt;
&lt;br /&gt;
=== Begrenzung der Auflösung ===&lt;br /&gt;
&lt;br /&gt;
Wo liegt das Problem? Das obige Verfahren nutzt recht hochfrequente Quarze mit 1 MHz und mehr. Wenn man die Frequenz eines Quarzes von 1 MHz = 1.000.000 Hz mit einer [[Auflösung und Genauigkeit| Auflösung]] von 1 Hz angibt, entspricht das einem maximalen Fehler von 1/1.000.000 oder 1ppm (engl. parts per million, millionstel Teil). Das ist sehr wenig. Eine RTC mit einem Fehler von 1ppm hat eine Gangabweichung von 86,4ms pro Tag, oder 2,5s pro Monat. Das ist ein sehr guter Wert. Wenn ich nun aber die Frequenz 32768 Hz mit 1 Hz Auflösung angebe, ist das schlimmstenfalls ein Fehler von 1/32768 = 30,5ppm, was einer Abweichung von 2,5s pro Tag und 75s pro Monat entspricht!&lt;br /&gt;
&lt;br /&gt;
=== Uhrentakt genau messen und digital korrigieren ===&lt;br /&gt;
&lt;br /&gt;
Wie kann man das Problem lösen? Die AVRs können im [[Sleep Mode]] den Uhrenquarz nur am Timer 2 betreiben, welcher ein 8 Bit Timer ist. D.H. ein Überlauf passiert alle 256 Takte, sprich 7,8125ms (=128 Hz). Man kann auch einen Prescaler verwenden, welcher das Problem aber nicht löst.&lt;br /&gt;
&lt;br /&gt;
Wie bereits festgestellt, müssen wir die Frequenz des 32768Hz Uhrenquarzes genauer messen und darstellen. Wir wollen hier annehmen, dass wir die Frequenz auf 0,001Hz = 1mHz (Millihertz) auflösen, ein guter Frequenzzähler kann das problemlos und ist auch so [[Auflösung und Genauigkeit|&#039;&#039;&#039;genau&#039;&#039;&#039;]]. Wir können beispielsweise feststellen, dass ein Quarz mit 32768,423Hz schwingt, das entspricht einem Fehler von &lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;F_r=(\frac{f_{ist}}{f_{soll}} -1 )\cdot 10^6=(\frac{32768,423}{32768} -1 )\cdot 10^6=12,9ppm&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dabei ist zu beachten, daß diese Messung &#039;&#039;&#039;nicht&#039;&#039;&#039; direkt am Quarz erfolgen darf, auch nicht mit kapazitätsarmen 10:1 Tastköpfen! Denn so ein Quarz wird von kleinsten Kapazitäten im Bereich von weniger als ein pF messbar verstimmt. Darum muss man in so einem Fall den Uhrentakt auf ein anderes IO-Pin ausgeben und dort messen. Beim [[MSP430]] ist das einfach, man kann ACLK auf ein Pin direkt ausgeben. Der [[AVR]] kann das leider nicht. Hier muss man zu einem Trick greifen. Man benutzt die Output Compare Funktion, um mit Timer 2 einen 128 Hz Takt zu erzeugen. Dieser ist fest mit dem Uhrentakt verbunden und kann anstellte dessen gemessen werden, ohne den Quarz zu verstimmmen. Die Messung ergibt in diesem Fall eine Frequenz von 128,00165 Hz.&lt;br /&gt;
&lt;br /&gt;
OK, jetzt haben wir den Takt gemessen, wir wissen, daß pro Sekunde 128 Timerüberläufe passieren (Prescaler =1). Wir wissen, dass unser Quarz pro Sekunde um 0,423 Takte zu schnell ist. Wir können aber keine halben Takte mehr oder weniger zählen? Doch! Mit [[Festkommaarithmetik]]! Denn nach 1000s ist unser Quarz um 423 Takte zu weit gelaufen und muss um diese Anzahl zurückgestellt werden. Also könnte man im ersten Ansatz nach 1000 Sekunden den Timer 2 um diesen Betrag korrigieren. Das Problem dabei ist nur, dass der Zähler nur 8 Bit breit ist. Ein Addieren oder Subtrahieren von 423 würde mehrfache Überläufe verursachen, welche programmtechnisch nur schwer zu handhaben wären. Also muss eine etwas bessere Methode her.&lt;br /&gt;
&lt;br /&gt;
=== Bresenham für RTCs ===&lt;br /&gt;
&lt;br /&gt;
Wenn man sich die Idee der [[Festkommaarithmetik]] mal eine Weile durch den Kopf gehen lässt, kommt man vielleicht auf folgende Idee. Der Frequenzfehler beträgt in unserem Beispiel 0,423 Hz, also Takte pro Sekunde. Oder aber 423 Tausendstel Takte pro Sekunde. Nach drei Sekunden sind es schon 1,269 Takte oder 1269 Tausendstel Takte. Moment! &#039;&#039;&#039;Einen&#039;&#039;&#039; Takt können wir korrigieren, indem wir den Zähler um 1 Takt zurück setzen. Den Restfehler von 269 Tausendstel merken wir uns und akkumulieren weiter. Wenn dann wieder die 1000er Marke überschritten wird machen wir das Gleiche. Analog dazu natürlich auch bei negativem Vorzeichen, sprich wenn der Quarz zu langsam schwingt wird er um einen Takt vorgestellt. É Voilà! Dieses Verfahren ist sehr ähnlich zum [http://de.wikipedia.org/wiki/Bresenham-Algorithmus Bresenham-Algorithmus] zum Zeichnen von Linien auf Computermonitoren.&lt;br /&gt;
&lt;br /&gt;
=== Beispielprogramm ===&lt;br /&gt;
&lt;br /&gt;
Das folgende Beispiel stellt eine RTC mit sehr niedrigem Stromverbrauch zur Verfügung. Laut Datenblatt beträgt die Stromaufnahme nur ca. 6µA bei 3V Versorgungsspannung, besser als einige kommerzielle RTCs! Möglich macht das die Nutzung des Power Save [[Sleep Mode]]s. Die Frequenz kann auf &amp;lt;math&amp;gt;10^{-5}&amp;lt;/math&amp;gt; Hz genau abgeglichen werden, was in diesem Fall bei einer Messfrequenz von 128Hz einer Auflösung von 0,078ppm entspricht. Das bedeutet eine Abweichung von 6,7ms pro Tag, 0,2s pro Monat oder 2,46s pro Jahr!&lt;br /&gt;
&lt;br /&gt;
Die Abweichung des Quarzes wird in einer vorzeichenbehafteten 16 Bit Variable in der Einheit &amp;lt;math&amp;gt;10^{-3}&amp;lt;/math&amp;gt; Hz gespeichert. D.h. es kann ein Frequenzfehler von +/- 32,768 Hz korrigiert werden, das sind 1000ppm! Normale Quarze haben Abweichungen von max. 100ppm, meist viel weniger. Jede Sekunde wird der Frequenzfehler neu berechnet und in den darauffolgenden 128 Interrupts ggf. mehrfach korrigiert. Wichtig ist dabei, dass die Korrektur wirklich ganz am Anfang der ISR steht, weil hier das Timing wirklich kritisch ist. Denn innerhalb eines Uhrenquarztaktes von ~30us muss der Timer 2 neu beschrieben werden. Bei 1 MHz RC-Oszillatortakt sind das nur 30 Takte, wovon 6 zum Aufwachen und 4 zum Anspringen der ISR benötigt werden. Dazu kommen noch das Sichern einiger Register am Anfang der ISR, was man im C nicht direkt sieht. Sicherheitshalber sollte man auch einen höheren Takt einstellen, z.B. 2 MHz, dann ist das Timing wesentlich entspannter.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
************************************************************************&lt;br /&gt;
*&lt;br /&gt;
* Stromsparende Echtzeituhr mit 32768Hz Uhrenquarz&lt;br /&gt;
*&lt;br /&gt;
* ATmega88 mit internem 2 MHz Oszillator + 32,768 kHz Quarz&lt;br /&gt;
*&lt;br /&gt;
* Fuses bleiben auf Standardeistellungen&lt;br /&gt;
* LOW Fuse Byte = 0x62&lt;br /&gt;
* HIGH Fuse Byte = 0xDF&lt;br /&gt;
* EXT Fuse Byte = 0xF9&lt;br /&gt;
*&lt;br /&gt;
* LED mit 1K Vorwiderstand an PB5&lt;br /&gt;
* Kalibriertaktausgang an PB3&lt;br /&gt;
************************************************************************&lt;br /&gt;
*/&lt;br /&gt;
&lt;br /&gt;
#define F_CPU 2000000L          // Systemtakt in Hz&lt;br /&gt;
#define F_CAL 12800000L         // gemessener Kalibriertakt in 10^-5 Hz&lt;br /&gt;
                                // Endung L ist wichtig!&lt;br /&gt;
&lt;br /&gt;
#define LED_TOGGLE PORTB ^= (1&amp;lt;&amp;lt;PB5);&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/sleep.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/eeprom.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// EEPROM Daten&lt;br /&gt;
&lt;br /&gt;
int16_t ee_rtc_cal EEMEM = (F_CAL-12800000)*256/100;        // Kalibrierung für RTC, Frequenzfehler in 1/1000 Hz&lt;br /&gt;
&lt;br /&gt;
// globale Variablen&lt;br /&gt;
&lt;br /&gt;
// beidseitiger Zugriff durch ISR und Hauptprogramm&lt;br /&gt;
&lt;br /&gt;
volatile uint32_t time;             // 24h Zeitstempel, 1s Auflösung&lt;br /&gt;
volatile int16_t rtc_cal;           // Kalibrierung des 32K Quarzes&lt;br /&gt;
volatile uint8_t flag_1s;           // Flag für 1s Intervall&lt;br /&gt;
&lt;br /&gt;
void long_delay(uint16_t ms) {&lt;br /&gt;
    for (; ms&amp;gt;0; ms--) _delay_ms(1);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main (void) {&lt;br /&gt;
&lt;br /&gt;
// Clock divider auf /4&lt;br /&gt;
&lt;br /&gt;
    CLKPR = 0x80;       // update  enable&lt;br /&gt;
    CLKPR = 2;          // Prescaler /4&lt;br /&gt;
&lt;br /&gt;
// IO konfigurieren&lt;br /&gt;
&lt;br /&gt;
    DDRB  = (1&amp;lt;&amp;lt;PB3) | (1&amp;lt;&amp;lt;PB5);&lt;br /&gt;
    PORTB = ~((1&amp;lt;&amp;lt;PB3) | (1&amp;lt;&amp;lt;PB5)); // Pull ups &lt;br /&gt;
    PORTC = 0xFF;       &lt;br /&gt;
    PORTD = 0xFF;&lt;br /&gt;
&lt;br /&gt;
// Analogcomparator ausschalten&lt;br /&gt;
&lt;br /&gt;
    ACSR = 0x80;&lt;br /&gt;
&lt;br /&gt;
// Timer2 konfigurieren&lt;br /&gt;
&lt;br /&gt;
    ASSR   = (1&amp;lt;&amp;lt; AS2);             // Timer2 asynchron takten&lt;br /&gt;
    long_delay(1000);               // Einschwingzeit des 32kHz Quarzes&lt;br /&gt;
    TCCR2A = (1&amp;lt;&amp;lt;COM2A1) | (1&amp;lt;&amp;lt;WGM21) | (1&amp;lt;&amp;lt;WGM20); // Fast PWM, non inverted&lt;br /&gt;
    TCCR2B = 1;                     // Vorteiler 1 -&amp;gt; 7,8ms Überlaufperiode&lt;br /&gt;
    OCR2A  = 128;                   // PWM, Tastverhältnis 50%&lt;br /&gt;
    while((ASSR &amp;amp; (1&amp;lt;&amp;lt; TCR2BUB)));  // Warte auf das Ende des Zugriffs&lt;br /&gt;
    TIFR2  &amp;amp;= ~(1&amp;lt;&amp;lt;TOV2);           // Interrupts löschen&lt;br /&gt;
    TIMSK2 |= (1&amp;lt;&amp;lt;TOIE2);           // Timer overflow Interrupt freischalten&lt;br /&gt;
&lt;br /&gt;
// EEPROM Werte auslesen&lt;br /&gt;
&lt;br /&gt;
    rtc_cal= eeprom_read_word(&amp;amp;ee_rtc_cal);&lt;br /&gt;
&lt;br /&gt;
// Interrupts freigeben&lt;br /&gt;
&lt;br /&gt;
    sei();&lt;br /&gt;
&lt;br /&gt;
// Endlose Hauptschleife&lt;br /&gt;
&lt;br /&gt;
    while(1) {&lt;br /&gt;
&lt;br /&gt;
        while((ASSR &amp;amp; (1&amp;lt;&amp;lt; OCR2AUB)));  // Warte auf das Ende des Zugriffs&lt;br /&gt;
        set_sleep_mode(SLEEP_MODE_PWR_SAVE);&lt;br /&gt;
        sleep_mode();                   // in den Schlafmodus wechseln&lt;br /&gt;
&lt;br /&gt;
        // hier wachen wir wieder auf, nach Ausführung des 7,8ms Timerinterupt&lt;br /&gt;
&lt;br /&gt;
        if (flag_1s) {  &lt;br /&gt;
            flag_1s =0;&lt;br /&gt;
            LED_TOGGLE                      // Test&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// Timer2 overflow Interrupt&lt;br /&gt;
&lt;br /&gt;
ISR(TIMER2_OVF_vect) {&lt;br /&gt;
    static uint8_t ticks;               // Hilfsvariable für Messintervall&lt;br /&gt;
    static int16_t time_error;          // RTC Fehlerkompensation&lt;br /&gt;
&lt;br /&gt;
    // Zeitkritische Dinge, welche am Anfang der ISR stehen müssen!&lt;br /&gt;
&lt;br /&gt;
    OCR2A=128;                          // Dummy-Write zur Sicherung des Timings&lt;br /&gt;
                                        // von Timer 2 im asynchronen Modus &lt;br /&gt;
&lt;br /&gt;
    // RTC Fehler korrigieren&lt;br /&gt;
&lt;br /&gt;
    if (time_error&amp;gt;999) {               // RTC zu schnell&lt;br /&gt;
        TCNT2 = 2;                      // Zähler einen Schritt zurück setzen (2 Takte Verzögerung!)&lt;br /&gt;
        time_error -= 1000;&lt;br /&gt;
    } else if (time_error&amp;lt;-999) {       // RTC zu langsam&lt;br /&gt;
        TCNT2 = 4;                      // Zähler einen Schritt vor setzen (2 Takte Verzögerung!)&lt;br /&gt;
        time_error += 1000;     &lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    // ab hier ist es nicht mehr zeitkritisch&lt;br /&gt;
&lt;br /&gt;
    // Echtzeituhr&lt;br /&gt;
    ticks++;                            // 1/128tel Sekunde&lt;br /&gt;
    if (ticks==128) {                   // Sekundenintervall&lt;br /&gt;
        time_error += rtc_cal;          // RTC Fehler akkumulieren&lt;br /&gt;
&lt;br /&gt;
        // 24h Timer&lt;br /&gt;
        time++;&lt;br /&gt;
        if (time==86400) time=0;        // 24h Überlauf&lt;br /&gt;
&lt;br /&gt;
        ticks=0;&lt;br /&gt;
        flag_1s =1;                     // setzte Flag für 1s Verarbeitung in main Endlosschleife&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Weitere Verbesserungen ===&lt;br /&gt;
&lt;br /&gt;
Der Algorithmus ermöglicht eine sehr hochauflösende Kalibrierung der RTC. Allerdings heisst das leider noch lange nicht, daß die RTC dann auch wirklich so genau ist. Denn diese Kalibrierung gilt nur für eine exakte Temperatur! Auch ein Quarz hat eine Temperaturabhängigkeit der Schwingfrequenz. Wenn man nun eine sehr genaue RTC bauen möchte, welche über einen grossen Temperaturbereich genau läuft, muss man periodisch die Temperatur messen und in die Kalibrierung einbeziehen. Einen typischen Temperaturverlauf des Frequenzfehlers zeigt das folgende Bild.&lt;br /&gt;
&lt;br /&gt;
[[bild:rtc_tk.gif|thumb|260px|left|Temperaturgang eines Uhrenquarzes]]&lt;br /&gt;
&amp;lt;br clear=&amp;quot;all&amp;quot; /&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Weiterhin kann man natürlich die Kalibrierung ohne erneutes Kompilieren des Quelltextets vornehmen, indem man den Kalibrierwert per [[UART]] oder [[I2C]] an den AVR sendet und im [[Speicher#EEPROM | EEPROM]] speichert.&lt;br /&gt;
&lt;br /&gt;
Kernpunkt der Kalibrierung ist natürlich die Messung der realen Quarzfrequenz. Die oben beschriebene Methode per Tagesschau und 1 Tag warten ist sehr zeitaufwändig und hat eine begrenzte Genauigkeit von ca. 1/2 Sekunde, das entspricht 5,8ppm. Hier muss zwangsläufig ein guter Frequenzzähler her. Da dieser nicht jedem Hobbybastler zur Verfügung steht, muss man sich in Lehrwerkstätten, Universitäten oder Firmen im Elektronikbereich umsehen und nachfragen, ob man einen Frequenzzähler vor Ort kurze Zeit nutzen kann.&lt;br /&gt;
&lt;br /&gt;
== Links ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.maxim-ic.com/appnotes.cfm/an_pk/617 Real-Time-Clock Selection and Optimization, MAXIM Application Note (engl.)]&lt;br /&gt;
*[http://www.mikrocontroller.net/articles/Uhr Implementierung einer Uhr mit Siebensegmentausgabe auf einem AVR ATTiny2313]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:AVR]]&lt;br /&gt;
[[Category:Timer und Uhren]]&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR-Tutorial:_Mehrfachverzweigung&amp;diff=39111</id>
		<title>AVR-Tutorial: Mehrfachverzweigung</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR-Tutorial:_Mehrfachverzweigung&amp;diff=39111"/>
		<updated>2009-09-18T13:02:28Z</updated>

		<summary type="html">&lt;p&gt;Jackfritt: /* Lange Sprungtabelle */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Oft ist es in einem Programm notwendig, eine Variable auf mehrere Werte zu prüfen und abhängig vom Ergebnis verschiedene Aktionen auszulösen. Diese Konstruktion nennt man Mehrfachverzweigung. In einem Struktogramm sieht das so aus.&lt;br /&gt;
&lt;br /&gt;
[[bild:mv_struktogramm.png|350px]]&lt;br /&gt;
&lt;br /&gt;
In C gibt es direkt dafür eine Konstruktion namens &#039;&#039;&#039;switch&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
switch (variable) {&lt;br /&gt;
  case 1:       // Anweisungen für diesen Zweig, wenn variable == 1&lt;br /&gt;
    break;&lt;br /&gt;
  case 17:      // Anweisungen für diesen Zweig, wenn variable == 17&lt;br /&gt;
    break;&lt;br /&gt;
  case 33:      // Anweisungen für diesen Zweig, wenn variable == 33&lt;br /&gt;
    break;&lt;br /&gt;
  case 9:       // Anweisungen für diesen Zweig, wenn variable == 9&lt;br /&gt;
    break;&lt;br /&gt;
  case 22:      // Anweisungen für diesen Zweig, wenn variable == 22&lt;br /&gt;
    break;&lt;br /&gt;
  default:      // Anweisungen wenn keine der oben definierten Bedingungen erfüllt ist&lt;br /&gt;
    break;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In Assembler muss man so etwas &amp;quot;zu Fuß&amp;quot; programmieren. Die verschiedene Lösungen sollen hier betrachtet werden.&lt;br /&gt;
&lt;br /&gt;
== Einfacher Ansatz ==&lt;br /&gt;
&lt;br /&gt;
Im einfachsten Fall verwendet man eine lange Kette von &#039;&#039;&#039;cpi&#039;&#039;&#039; und &#039;&#039;&#039;breq&#039;&#039;&#039; Befehlen. Für jeden Zweig benötigt man zwei Befehle.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
; Mehrfachverzeigung Version A&lt;br /&gt;
&lt;br /&gt;
; Einfacher Ansatz, mit vielen CPI&lt;br /&gt;
&lt;br /&gt;
start_vergleich:&lt;br /&gt;
&lt;br /&gt;
    cpi     r16,1&lt;br /&gt;
    brne    zweig_0&lt;br /&gt;
&lt;br /&gt;
; hier stehen jetzt alle Anweisungen für diesen Zweig r16=1&lt;br /&gt;
&lt;br /&gt;
    rjmp    ende_vergleich&lt;br /&gt;
zweig_0:&lt;br /&gt;
    cpi     r16,17&lt;br /&gt;
    brne    zweig_1&lt;br /&gt;
&lt;br /&gt;
; hier stehen jetzt alle Anweisungen für diesen Zweig r16=17&lt;br /&gt;
&lt;br /&gt;
    rjmp    ende_vergleich&lt;br /&gt;
zweig_1:&lt;br /&gt;
    cpi     r16,33&lt;br /&gt;
    brne    zweig_2&lt;br /&gt;
&lt;br /&gt;
; hier stehen jetzt alle Anweisungen für diesen Zweig r16=33&lt;br /&gt;
&lt;br /&gt;
    rjmp    ende_vergleich&lt;br /&gt;
zweig_2:&lt;br /&gt;
    cpi     r16,9&lt;br /&gt;
    brne    zweig_3&lt;br /&gt;
&lt;br /&gt;
; hier stehen jetzt alle Anweisungen für diesen Zweig r16=9&lt;br /&gt;
&lt;br /&gt;
    rjmp    ende_vergleich&lt;br /&gt;
zweig_3:&lt;br /&gt;
    cpi     r16,22&lt;br /&gt;
    brne    kein_Treffer&lt;br /&gt;
&lt;br /&gt;
; hier stehen jetzt alle Anweisungen für diesen Zweig r16=22&lt;br /&gt;
&lt;br /&gt;
    rjmp    ende_vergleich&lt;br /&gt;
kein_Treffer:&lt;br /&gt;
&lt;br /&gt;
; hier stehen jetzt alle Anweisungen für den Fall, dass keiner der Vergleiche erfolgreich war&lt;br /&gt;
&lt;br /&gt;
ende_vergleich:&lt;br /&gt;
&lt;br /&gt;
    rjmp    ende_vergleich          ; nur für Simulationszwecke! ENTFERNEN!&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;Eigenschaften&#039;&#039;&#039;&lt;br /&gt;
* Programmspeicherbedarf: 6*N Bytes (N = Anzahl der Zweige)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vorteile&#039;&#039;&#039;&lt;br /&gt;
* leicht verständlich&lt;br /&gt;
* Es können beliebige Vergleichswerte geprüft werden&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Nachteile&#039;&#039;&#039;&lt;br /&gt;
* relativ hoher Programmspeicherbedarf&lt;br /&gt;
* die Größe der Zweige ist stark begrenzt, weil der Befehl &#039;&#039;&#039;breq&#039;&#039;&#039; maximal 63 Worte weit springen kann!&lt;br /&gt;
* die einzelnen Zweige haben unterschiedliche Durchlaufzeiten, der letzte Zweig ist am langsamsten&lt;br /&gt;
* nur bedingt übersichtlicher Quellcode&lt;br /&gt;
&lt;br /&gt;
== Sprungtabelle ==&lt;br /&gt;
&lt;br /&gt;
Oft liegen die einzelnen Vergleichswerte nebeneinander (z.B. 7..15), z.B. bei der Übergabe von Parametern, Zustandsautomaten, Menueinträgen etc. . In so einem Fall kann man mittels einer &#039;&#039;&#039;Sprungtabelle&#039;&#039;&#039; das Programm verkürzen, beschleunigen und übersichtlicher gestalten.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
.include &amp;quot;m8def.inc&amp;quot;&lt;br /&gt;
&lt;br /&gt;
; Mehrfachverzweigung Version B&lt;br /&gt;
&lt;br /&gt;
; Clevere Version mit Sprungtabelle&lt;br /&gt;
; minimum und maximum sind auf 0..255 begrenzt!&lt;br /&gt;
&lt;br /&gt;
.equ minimum = 3&lt;br /&gt;
.equ maximum = 7&lt;br /&gt;
&lt;br /&gt;
start_vergleich:&lt;br /&gt;
&lt;br /&gt;
    subi    r16,minimum                 ; Nullpunkt verschieben&lt;br /&gt;
    cpi     r16,(maximum-minimum+1)     ; Index auf Maximum prüfen&lt;br /&gt;
    brsh    kein_Treffer                ; Index zu gross -&amp;gt; Fehler&lt;br /&gt;
    ldi     ZL,low(Sprungtabelle)       ; Tabellenzeiger laden, 16 Bit&lt;br /&gt;
    ldi     ZH,high(Sprungtabelle)&lt;br /&gt;
    add     ZL,r16                      ; Index addieren, 16 Bit&lt;br /&gt;
    ldi     r16,0                   &lt;br /&gt;
    adc     ZH,r16&lt;br /&gt;
    ijmp                                ; indirekter Sprung in Sprungtabelle&lt;br /&gt;
&lt;br /&gt;
kein_treffer:&lt;br /&gt;
&lt;br /&gt;
; hier stehen jetzt alle Anweisungen für den Fall, dass keiner der Vergleiche erfolgreich war&lt;br /&gt;
&lt;br /&gt;
    rjmp    ende_vergleich&lt;br /&gt;
&lt;br /&gt;
Sprungtabelle:&lt;br /&gt;
    rjmp    zweig_0&lt;br /&gt;
    rjmp    zweig_1&lt;br /&gt;
    rjmp    zweig_2&lt;br /&gt;
    rjmp    zweig_3&lt;br /&gt;
    rjmp    zweig_4&lt;br /&gt;
&lt;br /&gt;
zweig_0:&lt;br /&gt;
&lt;br /&gt;
; hier stehen jetzt alle Anweisungen für diesen Zweig&lt;br /&gt;
&lt;br /&gt;
    rjmp    ende_vergleich&lt;br /&gt;
&lt;br /&gt;
zweig_1:&lt;br /&gt;
&lt;br /&gt;
; hier stehen jetzt alle Awneisungen für diesen Zweig&lt;br /&gt;
&lt;br /&gt;
    rjmp    ende_vergleich&lt;br /&gt;
&lt;br /&gt;
zweig_2:&lt;br /&gt;
&lt;br /&gt;
; hier stehen jetzt alle Anweisungen für diesen Zweig&lt;br /&gt;
&lt;br /&gt;
    rjmp    ende_vergleich&lt;br /&gt;
&lt;br /&gt;
zweig_3:&lt;br /&gt;
&lt;br /&gt;
; hier stehen jetzt alle Anweisungen für diesen Zweig&lt;br /&gt;
&lt;br /&gt;
    rjmp    ende_vergleich&lt;br /&gt;
&lt;br /&gt;
zweig_4:&lt;br /&gt;
&lt;br /&gt;
; hier stehen jetzt alle Anweisungen für diesen Zweig&lt;br /&gt;
&lt;br /&gt;
    rjmp    ende_vergleich&lt;br /&gt;
&lt;br /&gt;
ende_vergleich:&lt;br /&gt;
&lt;br /&gt;
; hier geht das Programm weiter&lt;br /&gt;
&lt;br /&gt;
    rjmp    ende_vergleich          ; nur für Simulationszwecke! ENTFERNEN!&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039; Programmbeschreibung &#039;&#039;&#039;&amp;lt;BR&amp;gt;&lt;br /&gt;
Wie ist dieses Programm nun zu verstehen? Das Prinzip beruht darauf, daß in einer gleichmässigen Tabelle Sprungbefehle auf einzelne Programmzweige abgelegt werden. Das ist praktisch genauso wie der AVR [[AVR-Tutorial: Interrupts | Interrupts]] verarbeitet. Über einen Index (0...N) wird ein Sprungbefehl ausgewählt und ausgeführt.Der entscheidende Befehl dazu ist &#039;&#039;&#039;ijmp&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Zunächst muss der Wertebereich, auf welchen die Variable geprüft werden soll (minimum bis maximum), normiert werden (0 bis (Maximum-Minimum)). Dazu wird einfach das Minimum subtrahiert.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
    subi    r16,minimum                 ; Nullpunkt verschieben&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach muss geprüft werden, ob der maximale Index nicht überschritten wird. Denn ein Sprung auf nichtexistierende Einträge oberhalb der Sprungtabelle wäre fatal!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
    cpi     r16,(maximum-minimum+1)     ; Index auf Maximum prüfen&lt;br /&gt;
    brsh    kein_Treffer                ; Index zu gross -&amp;gt; Fehler&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach muss der indirekte Sprung vorbereitet werden. Dazu wird die Adresse der Sprungtabelle in das Z-Register geladen, welches ein 16 Bit Register ist und gleichbedeutend mit r30 und r31.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
    ldi     ZL,low(Sprungtabelle)       ; Tabellenzeiger laden, 16 Bit&lt;br /&gt;
    ldi     ZH,high(Sprungtabelle)&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Danach muss der Index addiert werden, dies ist eine 16-Bit Addition.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
    add     ZL,r16                      ; Index addieren, 16 Bit&lt;br /&gt;
    ldi     r16,0                   &lt;br /&gt;
    adc     ZH,r16&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zu guter Letzt wird der indirekte Sprung in die Sprungtabelle ausgeführt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
    ijmp                                ; indirekter Sprung in Sprungtabelle&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In der Sprungtabelle wird dann zum jeweiligen Zweig verzweigt.&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
Sprungtabelle:&lt;br /&gt;
    rjmp    zweig_0&lt;br /&gt;
    rjmp    zweig_1&lt;br /&gt;
    rjmp    zweig_2&lt;br /&gt;
    rjmp    zweig_3&lt;br /&gt;
    rjmp    zweig_4&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Zweig für einen ungültigen Index folgt direkt nach dem &#039;&#039;&#039;ijmp&#039;&#039;&#039;, weil der Befehl &#039;&#039;&#039;brsh&#039;&#039;&#039; nur maximal 63 Worte weit springen kann.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Eigenschaften&#039;&#039;&#039;&lt;br /&gt;
* Programmspeicherbedarf: 2*N +18 Bytes (N = Anzahl der Zweige)&lt;br /&gt;
* maximale Gesamtgröße der Zweige wird durch den Befehl rjmp begrenzt (+/-4kB). Das sollte aber nur in sehr wenigen Fällen ein Problem sein (Man wird kaum einen AVR mit 8 kB FLASH mit einer einzigen Mehrfachverzweigung füllen!)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vorteile&#039;&#039;&#039;&lt;br /&gt;
* relativ niedriger Programmspeicherbedarf&lt;br /&gt;
* die einzelnen Zweige haben unabhängig von der Grösse der Sprungtabelle eine konstante und kurze Durchlaufzeit von 12 Takten.&lt;br /&gt;
* übersichtlicher Quellcode&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Nachteile&#039;&#039;&#039;&lt;br /&gt;
* Die Vergleichswerte müssen lückenlos aufeinander folgen&lt;br /&gt;
&lt;br /&gt;
== Lange Sprungtabelle ==&lt;br /&gt;
Wenn man doch mal eine GIGA-Mehrfachverzweigung braucht, dann hilft die Version C.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
.include &amp;quot;m16def.inc&amp;quot;&lt;br /&gt;
&lt;br /&gt;
; Mehrfachverzweigung Version C&lt;br /&gt;
&lt;br /&gt;
; Clevere Version mit langer Sprungtabelle&lt;br /&gt;
; funktioniert nur mit AVRs mit mehr als 8KB FLASH&lt;br /&gt;
; minimum und maximum sind auf 0..127 begrenzt!&lt;br /&gt;
&lt;br /&gt;
.equ minimum = 3&lt;br /&gt;
.equ maximum = 7&lt;br /&gt;
&lt;br /&gt;
start_vergleich:&lt;br /&gt;
&lt;br /&gt;
    subi    r16,minimum                 ; Nullpunkt verschieben&lt;br /&gt;
    cpi     r16,(maximum-minimum+1)     ; Index auf Maximum prüfen&lt;br /&gt;
    brsh    kein_Treffer                ; Index zu gross -&amp;gt; Fehler&lt;br /&gt;
    ldi     ZL,low(Sprungtabelle*2)     ; Tabellenzeiger laden, 16 Bit&lt;br /&gt;
    ldi     ZH,high(Sprungtabelle*2)&lt;br /&gt;
    lsl     r16                         ; Index mit 2 multiplizieren&lt;br /&gt;
    add     zl,r16                      ; Index addieren, 16 Bit&lt;br /&gt;
    ldi     r16,0                   &lt;br /&gt;
    adc     zh,r16&lt;br /&gt;
    lpm     r16,Z+                      ; Low Byte laden und Pointer erhöhen&lt;br /&gt;
    lpm     ZH,Z                        ; zweites Byte laden&lt;br /&gt;
    mov     ZL,r16                      ; erstes Byte in Z-Pointer kopieren&lt;br /&gt;
    ijmp                                ; indirekter Sprung&lt;br /&gt;
&lt;br /&gt;
kein_treffer:&lt;br /&gt;
&lt;br /&gt;
; hier stehen jetzt alle Anweisungen für den Fall, dass keiner der Vergleiche erfolgreich war&lt;br /&gt;
&lt;br /&gt;
    jmp     ende_vergleich&lt;br /&gt;
&lt;br /&gt;
Sprungtabelle:&lt;br /&gt;
.dw zweig_0&lt;br /&gt;
.dw zweig_1&lt;br /&gt;
.dw zweig_2&lt;br /&gt;
.dw zweig_3&lt;br /&gt;
.dw zweig_4&lt;br /&gt;
&lt;br /&gt;
zweig_0:&lt;br /&gt;
&lt;br /&gt;
; hier stehen jetzt alle Anweisungen für diesen Zweig&lt;br /&gt;
&lt;br /&gt;
    jmp    ende_vergleich&lt;br /&gt;
&lt;br /&gt;
zweig_1:&lt;br /&gt;
&lt;br /&gt;
; hier stehen jetzt alle Awneisungen für diesen Zweig&lt;br /&gt;
&lt;br /&gt;
    jmp    ende_vergleich&lt;br /&gt;
&lt;br /&gt;
zweig_2:&lt;br /&gt;
&lt;br /&gt;
; hier stehen jetzt alle Anweisungen für diesen Zweig&lt;br /&gt;
&lt;br /&gt;
    jmp    ende_vergleich&lt;br /&gt;
&lt;br /&gt;
zweig_3:&lt;br /&gt;
&lt;br /&gt;
; hier stehen jetzt alle Anweisungen für diesen Zweig&lt;br /&gt;
&lt;br /&gt;
    jmp    ende_vergleich&lt;br /&gt;
&lt;br /&gt;
zweig_4:&lt;br /&gt;
&lt;br /&gt;
; hier stehen jetzt alle Anweisungen für diesen Zweig&lt;br /&gt;
&lt;br /&gt;
ende_vergleich:&lt;br /&gt;
&lt;br /&gt;
; hier geht das Programm weiter&lt;br /&gt;
&lt;br /&gt;
    jmp    ende_vergleich          ; nur für Simulationszwecke! ENTFERNEN!&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039; Programmbeschreibung &#039;&#039;&#039;&amp;lt;BR&amp;gt;&lt;br /&gt;
Diese Version ist der Version B sehr ähnlich. Der Unterschied besteht darin, daß in Version B die Sprungtabelle mit Sprungbefehlen gefüllt ist (rjmp) während in Version C die Startadressen der Funktionen ablegt sind. D.H. man kann nicht in die Sprungtabelle springen, sondern muss sich mit Hilfe des Index die richtige Adresse aus der Sprungtabelle lesen und mit &#039;&#039;&#039;ijmp&#039;&#039;&#039; anspringen. Klingt sehr ähnlich, ist aber dennoch verschieden.&lt;br /&gt;
&lt;br /&gt;
Die ersten drei Befehle sind identisch, es wird der Index normiert und auf das Maximum geprüft.&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
    subi    r16,minimum                 ; Nullpunkt verschieben&lt;br /&gt;
    cpi     r16,(maximum-minimum+1)     ; Index auf Maximum prüfen&lt;br /&gt;
    brsh    kein_Treffer                ; Index zu gross -&amp;gt; Fehler&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
Die nächsten zwei Befehle laden wieder die Anfangsadresse der Sprungtabelle. Doch halt, hier wird die Adresse der Sprungtabelle mit zwei multipliziert. Des Rätsels Lösung gibt es weiter unten.&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
    ldi     ZL,low(Sprungtabelle*2)     ; Tabellenzeiger laden, 16 Bit&lt;br /&gt;
    ldi     ZH,high(Sprungtabelle*2)&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
Der Index wird ebenfalls mit zwei multipliziert.&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
    lsl     r16                         ; Index mit 2 multiplizieren&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
Danach erfolgt eine 16-Bit Addition.&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
    add     zl,r16                      ; Index addieren, 16 Bit&lt;br /&gt;
    ldi     r16,0                   &lt;br /&gt;
    adc     zh,r16&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
Nun zeigt unser Z-Zeiger auf den richtigen Tabelleneintrag. Jetzt müssen zwei Bytes aus dem FLASH geladen werden. Das geschieht mit Hilfe des &#039;&#039;&#039;lpm&#039;&#039;&#039;-Befehls (&#039;&#039;&#039;L&#039;&#039;&#039;oad &#039;&#039;&#039;P&#039;&#039;&#039;rogram &#039;&#039;&#039;M&#039;&#039;&#039;emory). Hier wird die erweiterte Version des lpm-Befehls verwendet, wie sie nur auf grösseren AVRs verfügbar ist. Dabei wird ein Byte in Register r16 geladen und gleichzeitig der Z-Pointer um eins erhöht. Damit zeigt er wunderbar auf das nächste Byte, welches auch geladen werden muss.&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
    lpm     r16,Z+                      ; Low Byte laden und Zeiger erhöhen&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
Der zweite lpm-Befehl ist etwas ungewöhnlich, denn er überschreibt einen Teil des Z-Pointers! In den meisten Programmen wäre das ein Schuss ins Knie (Programmierfehler!), da wir aber den Z-Pointer danach sowieso mit neuen Daten laden ist das OK.&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
    lpm     ZH,Z                        ; zweites Byte laden&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
Das zuerst gelesene Byte wird in den Z-Pointer kopiert. Nun steht die Startadresse des gewählten Zweigs im Z-Pointer.&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
    mov     ZL,r16                      ; erstes Byte in Z-zeiger kopieren&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
Zu guter Letzt wird der indirekte Sprung ausgeführt und bringt uns direkt in den Programmzweig.&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
    ijmp                                ; indirekter Sprung direkt in den Programmzweig&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der Zweig für einen ungültigen Index folgt direkt nach dem &#039;&#039;&#039;ijmp&#039;&#039;&#039;, weil der Befehl &#039;&#039;&#039;brsh&#039;&#039;&#039; nur maximal 63 Worte weit springen kann.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Eigenschaften&#039;&#039;&#039;&lt;br /&gt;
* Programmspeicherbedarf: 2*N +26 Bytes (N = Anzahl der Zweige)&lt;br /&gt;
* unbegrenzte Sprungweite&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vorteile&#039;&#039;&#039;&lt;br /&gt;
* relativ niedriger Programmspeicherbedarf&lt;br /&gt;
* die einzelnen Zweige haben unabhängig von der Grösse der Sprungtabelle eine konstante und kurze Durchlaufzeit von 18 Takten&lt;br /&gt;
* übersichtlicher Quellcode&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Nachteile&#039;&#039;&#039;&lt;br /&gt;
* Die Vergleichswerte müssen lückenlos aufeinander folgen&lt;br /&gt;
* geringfügig höherer Programmspeicherbedarf (8 Byte mehr) und grössere Durchlaufzeit (6 Takte mehr)als Version B&lt;br /&gt;
&lt;br /&gt;
== Z-Pointer leicht verständlich ==&lt;br /&gt;
&lt;br /&gt;
Auf den ersten Blick scheint es sonderbar, daß Version B die Adresse der Sprungtabelle direkt lädt, während Version C sowohl Anfangsadresse als auch Index mit zwei multipliziert. Warum ist das so?&lt;br /&gt;
&lt;br /&gt;
Version B verwendet nur den Befehl &#039;&#039;&#039;ijmp&#039;&#039;&#039;. Dieser erwartet im Z-Register eine Adresse zur Programmausführung, eine &#039;&#039;&#039;Wort-Adresse&#039;&#039;&#039;. Da der Programmspeicher des AVR 16 Bit breit ist (=1 Wort = 2 Bytes), werden nur Worte adressiert, nicht jedoch Bytes! Genauso arbeitet der Assembler. Jedes Label entspricht einer Wort-Adresse. Damit kann man mit einer 12 Bit-Adresse 4096 Worte adressieren (=8192 Bytes). Wenn man sich die Befehle der einzelnen AVRs anschaut wird klar, daß alle AVRs mit 8KB und weniger FLASH nur die Befehle rjmp und rcall besitzen. Denn sie brauchen nicht mehr! (Hinweis: Der Atmega8 besitzt die Befehle ijmp und icall).&lt;br /&gt;
&lt;br /&gt;
Mit 12 Adressbits, welche direkt in einem Wort im Befehl rjmp bzw. rcall kodiert sind, kann der gesamte Programmspeicher erreicht werden. Größere AVRs besitzen call und jmp, dort ist die Adresse als 22 bzw. 16 Bit Zahl kodiert, deshalb brauchen diese Befehle auch 2 Worte Programmspeicher.&lt;br /&gt;
&lt;br /&gt;
Der Befehl &#039;&#039;&#039;lpm&#039;&#039;&#039; dient zum Laden einzelner Bytes aus dem Programmspeicher. Das ist vor allem für Tabellen mit konstanten Werten sehr nützlich (7-Segmentdekoder, Zeichensätze, Kennlinien, Parameter Texte, etc.) Doch wie kommt man nun in dem wortweise adressierten Programmspeicher an einzelne Bytes? Ganz einfach. Der AVR &amp;quot;mogelt&amp;quot; hier und erwartet im Z-Register eine &#039;&#039;&#039;Byte-Adresse&#039;&#039;&#039;. Von dieser Adresse bilden die Bits 15..1 die Wortadresse, welche zur Adressierung des Programmspeichers verwendet wird. Bit 0 entscheidet dann, ob das hoch- oder niederwertige Byte in das Zielregister kopiert werden soll (0=niederwertiges Byte; 1=höherwertiges Byte).&lt;br /&gt;
&lt;br /&gt;
Darum muss bei Verwendung des Befehls lpm die Anfangsadresse immer mit zwei multipliziert werden.&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
    ldi     ZL,low(Sprungtabelle*2)     ; Tabellenzeiger laden, 16 Bit&lt;br /&gt;
    ldi     ZH,high(Sprungtabelle*2)&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
In Version C muss zusätzlich der Index mit zwei multipliziert werden, weil jeder Tabelleneintrag (Adresse des Programmzweigs) ein Wort breit ist. Damit wird aus einem Index von 0,1,2,3,4 ein Offset von 0,2,4,6,8.&lt;br /&gt;
&lt;br /&gt;
{{Navigation_zurückhochvor|&lt;br /&gt;
zurücktext=Vergleiche|&lt;br /&gt;
zurücklink=AVR-Tutorial: Vergleiche|&lt;br /&gt;
hochtext=Inhaltsverzeichnis|&lt;br /&gt;
hochlink=AVR-Tutorial|&lt;br /&gt;
vortext=UART|&lt;br /&gt;
vorlink=AVR-Tutorial: UART}}&lt;br /&gt;
&lt;br /&gt;
[[Category:AVR-Tutorial]]&lt;/div&gt;</summary>
		<author><name>Jackfritt</name></author>
	</entry>
</feed>