<?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=Chrisu</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=Chrisu"/>
	<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/articles/Spezial:Beitr%C3%A4ge/Chrisu"/>
	<updated>2026-04-10T23:15:06Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.39.7</generator>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=MP2103-Stick:_Ein_Mini-Mikrocontroller-Board_mit_USB_und_bis_zu_4MB_Datenspeicher&amp;diff=56556</id>
		<title>MP2103-Stick: Ein Mini-Mikrocontroller-Board mit USB und bis zu 4MB Datenspeicher</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=MP2103-Stick:_Ein_Mini-Mikrocontroller-Board_mit_USB_und_bis_zu_4MB_Datenspeicher&amp;diff=56556"/>
		<updated>2011-04-15T15:22:45Z</updated>

		<summary type="html">&lt;p&gt;Chrisu: /* Elektrische Inbetriebnahme */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von Mario Pieschel&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Der MP2103-Stick ist ein kleines Arm7-Mikrocontroller-Board, welches sehr einfach und damit sehr billig gehalten wurde. Jeglicher Schnickschnack wurde weggelassen und möglichst viele Pins des Mikrocontrollers zu den beiden Steckverbindern geführt. Als Mikrocontroller kommt der LPC2103 von NXP zum Einsatz. Viele Mikrocontroller-Anwendungen sind als Stand-Alone-Anwendungen konzipiert – der MP2103-Stick nicht!!! Er soll mehr als Interface-Baustein für den PC gesehen werden.&lt;br /&gt;
Anwendungsbereiche sehe ich überall dort, wo irgendetwas mit dem PC elektrisch verbunden werden soll, was sich sonst nicht mit diesem über die herkömmlichen PC-Schnittstellen verbinden lässt. Da der LPC2103 über eine mannigfaltige Peripherie verfügt  (digitale Ein/Ausgänge,  ADC,  Timer, I2C, SPI/SSP, PWM, RTC), sehe ich fast keine Grenzen in seinem Einsatzspektrum. Überall wo der PC steuern, regeln und/oder messen soll, könnte der MP2103-Stick zum Einsatz kommen. Die Daten feuern vom und zum PC mit einer Datenübertragungsgeschwindigkeit von fast bis zu 1 Megabit pro Sekunde! Für eventuelle Kalibrierdaten oder andere individuelle Daten für das zu betreibende Gerät steht ein bis zu 4 Megabyte großer Datenspeicher zur Verfügung. Für den MP2103-Stick wird kein spezielles Programmiergerät benötigt – er wird einfach an einen USB-Anschluss eines PCs angeschlossen und das war’s. An ein bestimmtes Betriebssystem des Ziel-PCs ist man ebenfalls nicht gebunden, da für den eingesetzten USB-Baustein (FT232) Treiber für alle gängigen Betriebssysteme vom Hersteller FTDI-Chip angeboten werden.&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/articles/MP32F103-Stick:_Ein_Mini-Mikrocontroller-Board_mit_USB_und_bis_zu_4MB_Datenspeicher LINK: MP-Stick mit ARM Cortex-M3 (STM32F103CBT6)]&lt;br /&gt;
&lt;br /&gt;
[[Bild:MP2103Stick.jpg]]&lt;br /&gt;
&lt;br /&gt;
== Funktionsmodell des MP2103-Stick ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:MP2103 Model.PNG]]&lt;br /&gt;
&lt;br /&gt;
[http://www.nxp.com/acrobat_download/datasheets/LPC2101_02_03_2.pdf LINK: Datasheet vom LPC2103]&lt;br /&gt;
&lt;br /&gt;
[http://www.nxp.com/acrobat/usermanuals/UM10161_2.pdf LINK: Usermanual vom LPC2103]&lt;br /&gt;
&lt;br /&gt;
[http://www.nxp.com/acrobat/erratasheets/ES_LPC2103_4.pdf LINK: Erratasheet vom LPC2103]&lt;br /&gt;
&lt;br /&gt;
[http://atmel.com/dyn/products/devices.asp?family_id=616#1802 LINK: Datasheet und Anwendung vom AT45DBxxx]&lt;br /&gt;
&lt;br /&gt;
== Schaltungsbeschreibung ==&lt;br /&gt;
&lt;br /&gt;
Die Schaltung des MP2103-Sticks gliedert sich in fünf Funktionsgruppen.&lt;br /&gt;
&lt;br /&gt;
1.	Dem Mikrocontroller LPC2103 von NXP (IC3) mit seiner Grundbeschaltung (dem so genannten Hühnerfutter), den beiden Quarzen (Q2: 14,7456MHz und Q1: 32,768kHz), dem Anschluss für eine Real-Time-Clock-Batterie und den beiden Anschlussleisten CON1 und CON2 für externe Elektronik.&lt;br /&gt;
&lt;br /&gt;
2.	Dem USB-IC FT232RL (IC4) mit Hühnerfutter und der USB-Buchse.&lt;br /&gt;
&lt;br /&gt;
3.	Dem 4 Megabyte großen Datenspeicher AT45DB321 von Atmel (IC2) mit Hühnerfutter.&lt;br /&gt;
Es sind auch die kleineren Varianten z.&amp;amp;nbsp;B. AT45DB161 (2MB) und AT45DB081 (1MB) möglich. Der AT45DB642 (8MB) hat leider ein anderes Gehäuse - Das Löten geht dann nur mit etwas Geschick.&lt;br /&gt;
&lt;br /&gt;
4.	Der Reset-Automatik für Normalbetrieb und Programmiermodus mit Signal-LED (die Schaltung oben rechts).&lt;br /&gt;
&lt;br /&gt;
5.	And last but not least die Mikrocontroller-Core-Spannungsversorgungsschaltung von 1,8 Volt mit LM317D oben links.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Schaltplan ==&lt;br /&gt;
&lt;br /&gt;
[[Media:MP2103stick_schematic.GIF|LINK: Schaltplan gesamt]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:MP2103stick_schematic_LPC2103.GIF]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:MP2103stick_schematic_USB.GIF]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:MP2103stick_schematic_AT45DBxxx.GIF]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:MP2103stick_schematic_RESET.GIF]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:MP2103stick_schematic_LM317.GIF]]&lt;br /&gt;
&lt;br /&gt;
Der Mikrocontroller benötigt vier Betriebsspannungen:&lt;br /&gt;
&lt;br /&gt;
–	VDD1.8, für den Core an Pin 5 (1,8 Volt)&lt;br /&gt;
&lt;br /&gt;
–	VDD3.3, für dessen Peripherie an Pin 17 und 40 (3,3 Volt)&lt;br /&gt;
&lt;br /&gt;
–	VDDA, für die analogen Komponenten an Pin 42 (3,3 Volt)&lt;br /&gt;
&lt;br /&gt;
–	VBAT, für die Real Time Clock an Pin 4 (3,3 Volt)&lt;br /&gt;
&lt;br /&gt;
Die Core-Spannung wird mit dem LM317 erzeugt und mit den Widerständen R1 und R2 fest eingestellt. Die 3,3 Volt werden im FT232RL erzeugt. VDDA wird über den Widerstand R10 von VDD3.3 bezogen. VBAT wird über die Diode D2 von VDD3.3 oder von einer externen Backup-Batterie versorgt. Die Kondensatoren an den Versorgungsspannungen dienen der Entkopplung von Störsignalen und damit dem sicheren Betrieb des LPC2103. R1! und R2! mit je Null Ohm in den beiden Spannungsversorgungsleitungen VDD1.8 und VDD3.3 dienen dem Schutz des Mikrocontrollers bei Inbetriebnahme des MP2103-Sticks. Sie sollten erst ganz zum Schluss eingelötet werden – erst wenn alle Spannungen überprüft und OK sind.&lt;br /&gt;
Dem Mikrocontroller wird mit dem Quarz Q2 (14,7456 MHz Grundton) sozusagen das Leben eingehaucht. Er erzeugt den Takt für den LPC2103. Durch den Multiplier in diesem kann das System mit bis zu 4 x 14,7456MHz = 58,9824MHz betrieben werden. Der krumme Wert von 14,7456MHz ist einzig und allein für die Kommunikation zum PC über die UART0 und USB von Nöten. Q1 ist ein normaler Uhren-Quarz mit 32KHz für die interne Echtzeituhr.&lt;br /&gt;
An CON1 und CON2 gehen fast alle Pins des Mikrocontrollers. CON1 und CON2 sind im Raster 2,54mm auf der Leiterplatte angeordnet, so dass eine Lochraster-Leiterplatte auf den Stick gesteckt werden kann.&lt;br /&gt;
Die Kommunikation mit einem PC/Labtop erfolgt mit dem seriellen Port UART0 des LPC2103 (Pin 13 und 14)  über den USB-zu-seriell-Umsetzer FT232RL (IC4). Dort gehen die beiden Signale (Leitungen) RXD und TXD gekreuzt an die Pins 1 und 5. Die beiden Handshake-Signale RTS und DTR sind über den Dip-Schalter S2 mit der Reset-Automatik oben rechts verbunden. Die beiden Datenleitungen USBDM (Pin 16) und USBDP (Pin 15) sind direkt mit der USB-B-Buchse (Pin 2 und 3) verbunden. VDD (5 Volt) kommt von Pin 1 der USB-B-Buchse über L1 (Entstörung) und geht an Pin 20 von IC4 und an Pin 16 von CON2 zur Außenwelt. Aus Sicherheitsgründen sind die 3.3 Volt nicht nach außen geführt. Wenn man auf seiner externen Schaltung 3,3 Volt benötigt, kann man dieses sehr einfach mit einem weiteren LM317 mit angepassten Widerständen bewerkstelligen.&lt;br /&gt;
Die Reset-Automatik oben rechts im Schaltplan sorgt bei geöffnetem Dip-Schalter S2 und nicht gestecktem Jumper auf BSL_HAND (BSL = Bootstrap Loader: Urlader) für ein ordnungsgemäßes Starten des Mikrocontrollers im Normalbetrieb. LED1 kann dann in einem Programm als Signallampe benutzt werden. Wird der Jumper BSL_HAND gesteckt geht der Mikrocontroller sofort nach einem Reset-Impuls an Pin 6 in den Bootloader-Modus. Es kann sofort eine Firmware (das Anwenderprogramm) mit einer Programmer-Software hochgeladen werden. Damit man nicht immer bei der Softwareentwicklung diesen Jumper ständig stecken und abziehen muss,  gibt es noch die Programmier-Automatik mittels der beiden Handshake-Leitungen RTS und DTR. Eine Programmer-Software kann diese beiden Leitungen der RS232-Schnittstelle schalten und damit den Mikrocontroller gezielt in den Bootloader-Modus bringen, die Firmware übertragen und anschließend das Programm starten. Der MP2103-Stick muss bei der Softwareentwicklung nicht angefasst werden. Alles geschieht vom PC aus. Im endgültigen Normalbetrieb müssen S2 offen und BSL_HAND nicht gesteckt sein. In welchen Modus der Mikrocontroller geschaltet werden soll entscheidet der Signalpegel an Pin 44 des LPC2103 bei einem Reset-Impuls. High = Normalbetrieb, Low = Bootloader.&lt;br /&gt;
Sehr einfach gestaltet sich die Beschaltung des externen seriellen Flash-Speichers IC2. &lt;br /&gt;
Es können die ICs AT45DB321D-SU (4MB), AT45DB161D-SU (2MB) oder AT45DB081D-SU (1MB) eingelötet werden.  Dieser ist mit der SPI des LPC2103 verbunden. Wichtig ist R3! Er wird nur bestückt wenn der Speicher schreibgeschützt sein soll.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Eagle-Files ==&lt;br /&gt;
&lt;br /&gt;
[[Media:MP2103Stick_v1.0.zip‎|LINK: MP2103Stick_v1.0.zip‎]]&lt;br /&gt;
&lt;br /&gt;
== Mechanische Realisierung ==&lt;br /&gt;
&lt;br /&gt;
Die Leiterplatte sollte von einem Leiterplattenhersteller gefertigt werden. Ich habe die Erfahrung gemacht, dass Anbieter mit Preis-Berechnungen auf Quadratdezimeter-Basis egal mit welchem Inhalt die günstigsten sind. Wichtig ist, dass die Leiterplatten mit Durchkontaktierungen gefertigt werden. Aus Erfahrung rate ich die Leiterplatten mit Lötstopplack fertigen zu lassen. Einfach die Datei „MP03Stick_v1.0.brd“ dem Hersteller schicken.&lt;br /&gt;
&lt;br /&gt;
Board top:&lt;br /&gt;
&lt;br /&gt;
[[Bild:MP03Stick_board_top_klein.GIF]]&lt;br /&gt;
&lt;br /&gt;
Board bottom:&lt;br /&gt;
&lt;br /&gt;
[[Bild:MP03Stick_board_bottom_klein.GIF]]&lt;br /&gt;
&lt;br /&gt;
Stueckliste:&lt;br /&gt;
&lt;br /&gt;
[[Bild:MP2103Stick_Stueckliste.PNG]]&lt;br /&gt;
&lt;br /&gt;
== Bestückung der Leiterplatte ==&lt;br /&gt;
&lt;br /&gt;
Elektronische Bauteile sind durch elektrostatische Ladungen gefährdet. Deshalb ab jetzt mit ESD-Armband und ESD-Unterlage arbeiten!!!&lt;br /&gt;
Beim Arbeiten mit den kleinen Bauteilen hilft auf jeden Fall ein Briefmarken-Lupen-Headset oder ein Stereo-Mikroskop mit Verstärkungsfaktor 10 (bei ebey ca. 200,- €).&lt;br /&gt;
Zuerst die beiden großen ICs, IC3 (LPC2103) und IC4 (FT232RL), bestücken. Da es sich um ziemlich kleine und mit hoher Pin-Anzahl versehene elektronische Bauteile handelt, empfehle ich folgende Vorgehensweise: Die Lötpads auf der Leiterplatte für das entsprechende IC reichlich mit dem Lötkolben und Lötzinn (&amp;lt;= 0,5 mm Durchmesser) verzinnen. Die Lötpads sollten glänzen und um ca. 0,1 bis 0,2 mm erhaben sein. Nun die Leiterplatte mit handelsüblichem Brennspiritus reinigen. Jetzt das IC mit ein wenig Klebstoff auf der Leiterplatte fixieren. Ich nehme dafür handelsüblichen Klebestift (Pr…-Stift). Eine kleine Messerspitze voll vom Klebestift auf die Mitte der IC-Position auf die Leiterplatte auftragen, das IC auf die Leiterplatte aufsetzen und positionieren. Es darf auf keinen Fall Klebstoff bis zu den Lötanschlüssen des ICs quellen. Erst mit dem Festlöten beginnen, wenn das IC korrekt auf den Lötpads sitzt und etwas angetrocknet ist. Ab jetzt wird nicht mehr mit Lötzinn gearbeitet – dieses am besten so weit wie möglich weglegen. Die Kapillarwirkung der IC-Anschlüsse ist viel zu groß, diese würden eine weitere Zugabe von Lötzinn sofort dieses zwischen die Lötpins ziehen und damit für reichlich Kurzschlüsse sorgen. Ab jetzt wird nur noch mit Flussmittel gearbeitet, entweder handelsübliches Flux oder Kolofonium (in Brennspiritus aufgelöst) nehmen. Ist das IC korrekt positioniert und fixiert mit dem Festlöten beginnen. Jeden einzelnen IC-Anschluss mit dem heißen Lötkolben und wenig Druck in Richtung Leiterplatte anlöten. Wichtig ist wirklich, sich damit Zeit zu lassen und darauf zu achten, dass das Lötzinn richtig fließt. Sollte bei einem der hier beschriebenen Arbeitsschritte etwas schief gehen, unbedingt die Arbeiten abbrechen, alles reinigen und von Anfang beginnen. Sind IC3 und IC4 erfolgreich auf die Leiterplatte gelötet können alle anderen Bauteile bestückt und gelötet werden. Wichtig: „R1!“, „R2!“ und „R3!“ nicht bestücken!!! Die voll bestückte Leiterplatte gründlich mit Brennspiritus und einem kleinen Pinsel reinigen. Die Leiterplatte wegen der Buchsen und Schalter/Taster nicht im Reinigungsmittel baden. Das Reinigungsmittel nicht abtrocknen lassen sondern mit Druckluft entfernen. Es werden so unschöne Flecken vermieden. Sollte der Stick in rauer Umgebung betrieben werden ist das Lackieren mit farblosem Leiterplattenlack sinnvoll.&lt;br /&gt;
&lt;br /&gt;
== Optische Prüfung ==&lt;br /&gt;
&lt;br /&gt;
Jetzt sollte eine ausgiebige Fehlersuche auf Kurzschlüsse, kalte Lötstellen, Verpolung von Bauteilen und richtiger Bestückung erfolgen. Entweder mit einer großen Lupe oder einem Stereo-Mikroskop mit Vergrößerungsfaktor 10.&lt;br /&gt;
	&lt;br /&gt;
Alle weiteren Arbeitsschritt erst nach vollständiger Trocknung des Stick durchführen.&lt;br /&gt;
&lt;br /&gt;
== Elektrische Inbetriebnahme ==&lt;br /&gt;
&lt;br /&gt;
Für erste Tests ist es am Besten den Stick mit einem Strom geregelten Netzteil über die USB-Buchse (Pin1 +5V, Pin4 Masse) zu verbinden; den Strom auf 50 mA begrenzen und 5 Volt einstellen. Nach Einschalten sollte ein Strom von ca. 10 bis 20 mA fließen und die anliegende Spannung weiterhin 5 Volt betragen. Bricht die Spannung zusammen auf keinen Fall die Strombegrenzung erhöhen sondern auf Kurzschlusssuche gehen. Fließt zu wenig Strom oder keiner kalte Lötstellen suchen. Ist kein Netzteil vorhanden, einfach drei kleine billige Knopfzellen á 1,5 Volt in Reihe schalten und den Strom mit einem Multimeter messen. Stimmt der Strom und liegen die 5 Volt an, die Spannungen an den Testpunkten TP1 bis TP4 überprüfen. Bezugspunkt ist TPM (Masse). Folgende Spannungen sollten gemessen werden:&lt;br /&gt;
&lt;br /&gt;
TP1 = 1,8 Volt&lt;br /&gt;
&lt;br /&gt;
TP2 = 3,3 Volt&lt;br /&gt;
&lt;br /&gt;
TP3 = 5 Volt (oder 4,5V bei der Variante mit den drei 1,5V Knopfzellen)&lt;br /&gt;
&lt;br /&gt;
TP4 = 3,3 Volt&lt;br /&gt;
&lt;br /&gt;
Wenn diese Spannungen OK sind kann der Stick an den PC/Notebook über ein USB-Kabel angeschlossen werden. Nun sollte das Betriebssystem (Windows, für WinCE, Linux und Mac weiß ich es nicht) melden, dass neue Hardware erkannt wurde. Jetzt kann der Treiber für den FT232RL installiert werden. Den Treiber (Virtual COM Port, VCP) von der [http://ftdichip.com Herstellerseite] downloaden – die Vorgehensweise ist dort ausführlich beschrieben. Nach erfolgreicher Installation des Treibers sollte im Hardwaremanager ein neuer COMx-Port zu sehen sein. Die COM-Nummer sollte man sich merken. Windows registriert für jede USB-Schnittstelle eine andere COM-Port-Nummer, was zu Verwirrung beim Umstecken führen kann. Damit sind aber auch mehrere Sticks anschließbar.&lt;br /&gt;
&lt;br /&gt;
[http://ftdichip.com/Drivers/VCP.htm LINK: die Treiber für den FT232RL]&lt;br /&gt;
&lt;br /&gt;
[http://ftdichip.com/Documents/InstallGuides.htm LINK: Driver Installation Guides]&lt;br /&gt;
&lt;br /&gt;
Sind alle Tests und Arbeitsschritte bis hier OK können die beiden Widerstände „R1!“ und „R2!“ eingelötet werden um den Mikrocontroller mit Strom zu versorgen. Es sollte ein Strom zwischen 20 und 40 mA fließen, wenn nicht: Fehlersuche nach Kurzschlüssen, kalten Lötstellen, verpolten Bauteilen und falscher Bestückung. Sind die beiden Dip-Schalter von S2 offen (nicht auf ON) und der Jumper BSL_Hand gezogen sollte die LED leuchten.&lt;br /&gt;
&lt;br /&gt;
== Firmware Upload ==&lt;br /&gt;
&lt;br /&gt;
Zum Hochladen der Firmware benötigt man das Programm Flash-Magic-Tool.&lt;br /&gt;
&lt;br /&gt;
[http://www.flashmagictool.com/ LINK: Flash Magig Tool]&lt;br /&gt;
&lt;br /&gt;
Die Einstellungen sind folgende:&lt;br /&gt;
&lt;br /&gt;
Unter „Step 1 - Communications“:&lt;br /&gt;
&lt;br /&gt;
Com Port:	der COMx-Port, an dem der MP2103-Stick angeschlossen ist. Im Hardwaremanager nachsehen!&lt;br /&gt;
&lt;br /&gt;
Baud Rate: 115200&lt;br /&gt;
&lt;br /&gt;
Device: LPC2103&lt;br /&gt;
&lt;br /&gt;
Interface: None (ISP) &lt;br /&gt;
&lt;br /&gt;
Oscillator Freq. (MHz): 14.7456&lt;br /&gt;
&lt;br /&gt;
Unter „Step 2 - Erase“:&lt;br /&gt;
&lt;br /&gt;
Ein Hägchen hinter: „Erase all Flash+Code Rd Prot“&lt;br /&gt;
&lt;br /&gt;
Ùnter „Step 3 – Hex File“:&lt;br /&gt;
&lt;br /&gt;
Das Hex-File, welches hochgeladen werden soll.&lt;br /&gt;
&lt;br /&gt;
Unter „Step 4 – Options“:&lt;br /&gt;
&lt;br /&gt;
Hinter „Verify after programming“&lt;br /&gt;
&lt;br /&gt;
Unter Adanced Options im Formular „Hardware Options“ ein Häckchen hinter „Use DTR and RTS to control RTS and P0.14“&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Bild:FlashMagicFlashen.GIF]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:FlashMagicAdvanstOption.GIF]]&lt;br /&gt;
&lt;br /&gt;
Jetzt am Besten erst einmal testen, ob sich der Mikrocontroller meldet. Die beiden Dip-Schalter von S2 müssen auf „ON“ stehen und Jumper „BSL_HAND“ muss gezogen sein. Flash Magic starten, die Einstellungen wie oben und in der Menüleiste „ISP“ den Menüpunk „Read Device Signatur“ anwählen. Der Mikrocontroller muss in dem sich öffnenden Fenster die Divice-ID und die Bootloaderversion liefern. Meldet Magic Flash einen Fehler: Fehlersuche. :O(&lt;br /&gt;
&lt;br /&gt;
[[Bild:FlashMagicReadDeviceSegnature.GIF]]&lt;br /&gt;
&lt;br /&gt;
[[Bild:FlashMagicDeviceSignature.GIF]]&lt;br /&gt;
&lt;br /&gt;
Den Firmware-Upload startet man mit dem Button &amp;quot;Start&amp;quot; unter &amp;quot;Step 5 - Start!&amp;quot; im Falsh Magic. &lt;br /&gt;
&lt;br /&gt;
Ein weiteres Flash-Tool ist das „LPC2000 Flash Utility“ von Philips, welches leider nicht mehr weiterentwickelt wird. Es ist aber in der Auswahl der COM-Ports begrenzt (COM1 bis COM5). Im Geräte-Manager von Windows müssen bei Bedarf Änderungen an der COM-Port-Nummerierung vorgenommen werden. Bis auf diesen Makel ist dieses Tool schnell und unkompliziert.&lt;br /&gt;
&lt;br /&gt;
[http://www.lpctools.com/downloads/LPC2000%20Flash%20ISP%20Utility%20v2.2.3.zip LINK: LPC2000 Flash Utility]&lt;br /&gt;
&lt;br /&gt;
[[Bild:MP2103Stick_LPC2000Flasher.PNG]]&lt;br /&gt;
&lt;br /&gt;
== Testprojekt ==&lt;br /&gt;
&lt;br /&gt;
Hier ein kleines Testprogramm als Basis für eigene Projekte.&lt;br /&gt;
Es lässt die LED blinken und kommuniziert über die serielle Schnittstelle.&lt;br /&gt;
&lt;br /&gt;
[[Media:MP2103-Stick_Test.zip‎|LINK: MP2103-Stick_Test.zip‎]]&lt;br /&gt;
&lt;br /&gt;
Einstellungen im Hyperterminal:&lt;br /&gt;
&lt;br /&gt;
Baud Rate (Bits pro Sekunde): 921600&lt;br /&gt;
&lt;br /&gt;
Einstellungen/Emulation: ANSI&lt;br /&gt;
&lt;br /&gt;
Die genauen Einstellungen befinden sich im Projekt unter MP2103-Stick_921600_baud.ht.&lt;br /&gt;
 &lt;br /&gt;
[[Bild:MP2103_Terminal.GIF]]&lt;br /&gt;
&lt;br /&gt;
Compiliert wird das Projekt mit WinARM oder Yagarto.&lt;br /&gt;
&lt;br /&gt;
[http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/ LINK: WinARM]&lt;br /&gt;
&lt;br /&gt;
[http://www.yagarto.de/ LINK: Yagarto]&lt;br /&gt;
&lt;br /&gt;
== Compiler und IDE (neu) ==&lt;br /&gt;
&lt;br /&gt;
Die Integrierte Entwicklungsumgebung  von Raisonance, Ride7 und RKit-ARM, umfasst einen voll funktionsfähigen und Code unbegrenzten GNU C/C++-Compiler und das Raisonance Integrated Development Environment (RIDE). Über eine grafische Benutzeroberfläche wird die Bedienung der Softwareentwicklungs-Tools (Compiler, Assembler, Linker und Simulator) ermöglicht. Für die Softwareentwicklung und Kompilierung vom C-Source-Code bis hin zum endgültigen HEX-File besteht keine Codegrößenbegrenzung, lediglich das Debugging ist bis 32kByte begrenzt. Das ist aber hier nicht von Belang, da mit dem Bootloader des Mikrocontrollers geflasht wird.&lt;br /&gt;
&lt;br /&gt;
[[Bild:MP2103Stick_Ripe7.PNG]]&lt;br /&gt;
&lt;br /&gt;
Auf der Page von Raisonance.com anmelden und die Files &amp;quot;RKit-ARM&amp;quot; (GCC) und &amp;quot;Ride7&amp;quot; (IDE) downloaden und installieren. Zuerst RKit-ARM dann Ride7. Der Umgang mit diesen Programmen ist super einfach - keine Rumquälerei mit Makefiles und solcherlei Teufelszeug - alles ist bereits Mundgerecht von Raisonance zugeschneidert. Sehr empfehlenswert! Ride7 ist eigentlich nicht für den LPC2103 ausgelegt, aber mit ein wenig Überredungskunst geht dieses auch.&lt;br /&gt;
&lt;br /&gt;
[http://www.mcu-raisonance.com/mcu_downloads.html LINK: Compiler und IDE Ride7 von Raisonance.com]&lt;br /&gt;
&lt;br /&gt;
[http://www.mcu-raisonance.com/tzr/scripts/downloader2.php?filename=T020/file/d8/cd/4datj7g5d1wr&amp;amp;mime=application/pdf&amp;amp;originalname=GettingStartedARM_Ride7.pdf LINK: Getting Started with ARM &amp;amp; Ride7 User manual]&lt;br /&gt;
&lt;br /&gt;
Und wie einfach alles ist zeigt dieses Beipiel-Projekt:&lt;br /&gt;
&lt;br /&gt;
[[Media:MP2103Stick_Hello_World.zip|LINK: Hello-World-Projekt mit Ride7]]&lt;br /&gt;
&lt;br /&gt;
Da in Ride7 kein serielles Upload-Tool für den MP2103-Stick integriert ist, kann zum Hochladen der Firmware (Hello_World.hex) „LPC2000 Flash Utility“ von Philips oder Flash-Magic genommen werden.&lt;br /&gt;
&lt;br /&gt;
== Fazit ==&lt;br /&gt;
&lt;br /&gt;
Es wurde ein kleines Arm7-Mikrocontroller-Board mit beachtlichen Leistungsmerkmalen und sehr geringen Herstellungskosten vorgestellt.&lt;br /&gt;
&lt;br /&gt;
32-Bit-Mikrocontroller 14,7456 bis 58,9824 MHz&lt;br /&gt;
&lt;br /&gt;
32 kByte Flash-ROM&lt;br /&gt;
&lt;br /&gt;
8 kByte RAM&lt;br /&gt;
&lt;br /&gt;
bis zu 4MByte Flash-Datenspeicher&lt;br /&gt;
&lt;br /&gt;
jeder Menge Peripherie&lt;br /&gt;
&lt;br /&gt;
Es kann als Standard-Interface-Modul für den PC eingesetzt werden. Es ist so konzipiert, dass es in ein Gehäuse eingebaut und mit vier M2-Schrauben befestigt werden kann. Auf den beiden Wannensteckerleisten CON1 und CON2 kann ein Tochterboard über zwei 16-polige Pfostenbuchsenleisten mit individueller Elektronik aufgesteckt werden (conrad.de Artikel-Nr.: 738501-62).&lt;br /&gt;
&lt;br /&gt;
Ich stelle mir folgende Einsatzbeispiele vor:&lt;br /&gt;
&lt;br /&gt;
Interface für einen Roboter&lt;br /&gt;
&lt;br /&gt;
Logik-Analysator&lt;br /&gt;
&lt;br /&gt;
Datenlogger für analoge Signale&lt;br /&gt;
&lt;br /&gt;
Oszilloskop&lt;br /&gt;
&lt;br /&gt;
Einsatz in Computer gesteuerten Messgeräten&lt;br /&gt;
&lt;br /&gt;
CNC-Maschinen&lt;br /&gt;
&lt;br /&gt;
usw.&lt;br /&gt;
&lt;br /&gt;
Überall, wo ein Interface für den PC benötigt wird, kann der MP2103-Stick eingesetzt werden. Im Stick laufen nur die Treiber für die Peripherie und eine Transport-Routine für die Rohdaten vom und zum PC - die eigentliche Software läuft auf dem PC.&lt;br /&gt;
&lt;br /&gt;
Übrigens:&lt;br /&gt;
&lt;br /&gt;
Der Board-Computer der Mondlandefähre von Apollo 11, der [http://www.ibiblio.org/apollo/ &amp;quot;Apollo Guidance Computer&amp;quot;], hatte einen 16-Bit-Computer mit 2,048 MHz, 72 kByte ROM und 4 kByte RAM.&lt;br /&gt;
&lt;br /&gt;
[[Category:ARM-Boards]]&lt;br /&gt;
[[Category:USB]]&lt;/div&gt;</summary>
		<author><name>Chrisu</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=STM32&amp;diff=55839</id>
		<title>STM32</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=STM32&amp;diff=55839"/>
		<updated>2011-03-13T19:39:38Z</updated>

		<summary type="html">&lt;p&gt;Chrisu: /* Evaluation Boards */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Allgemeine Infos ==&lt;br /&gt;
&lt;br /&gt;
Der STM32 ist ein Mikrocontroller von [http://www.st.com/mcu/inchtml-pages-stm32.html ST] mit einer 32-Bit [http://www.arm.com/products/processors/cortex-m/index.php ARM Cortex-M3] CPU. Diese Architektur ist speziell für den Einsatz in Microcontrollern neu entwickelt, und löst damit die bisherigen ARM7 basierten Controller weitestgehend ab. Den STM32 gibt es von ST in unzähligen Varianten mit variabler Peripherie und verschiedenen Gehäusegrössen und -formen. Durch die geringe Chipfläche des Cores ist es ST möglich, eine 32 Bit-CPU für weniger als 1 EUR anzubieten.&lt;br /&gt;
&lt;br /&gt;
Bisher gibt es drei STM32-Familien, wobei sich die Größte (STM32F) in weitere Unterfamilien (Linien) aufteilt:&lt;br /&gt;
* [http://www.st.com/internet/mcu/subclass/1169.jsp STM32F1]&lt;br /&gt;
** Connectivity line&lt;br /&gt;
** Performance line&lt;br /&gt;
** USB Access line&lt;br /&gt;
** Access Line&lt;br /&gt;
** Value line (teilweise verfügbar)&lt;br /&gt;
* Demnächst: [http://www.st.com/internet/mcu/product/250173.jsp STM32F2]&lt;br /&gt;
** Wie die STM32F1 Serie, jedoch 120MHz, Camera-Interface, 32-Bit Timer, ...&lt;br /&gt;
* [http://www.st.com/mcu/inchtml-pages-stm32l.html STM32L] (LowPower) (auf ST-Webseite gelistet, noch in Entwicklung)&lt;br /&gt;
** mit LCD Treiber&lt;br /&gt;
* STM32T (Touch)  &lt;br /&gt;
* [http://www.st.com/mcu/inchtml-pages-stm32w.html STM32W] (RF-MCU) &lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Features&#039;&#039;&#039;&lt;br /&gt;
* Cortex-M3 Kern&lt;br /&gt;
* 16KB ... 1MB [[Flash-ROM]] und bis zu 96KB [[Speicher#SRAM|SRAM]] und bis zu 4KB [[Speicher#EEPROM|EEPROM]] (STM32L)&lt;br /&gt;
* [[IC-Gehäuseformen | Gehäuse]] 36 ... 144 Pins als QFN, LQFP und BGA&lt;br /&gt;
* Derzeit sind über &#039;&#039;&#039;110&#039;&#039;&#039; STM32 Derivate/Varianten verfügbar&lt;br /&gt;
* Derzeit bis 72MHz CPU-Takt, Modelle bis 120MHz (mit 0 Wait-States) sind angekündigt; der CPU-Takt wird über einen Multiplikator aus dem internen RC-Takt oder einem externen Quarz-Takt abgeleitet.&lt;br /&gt;
* Externes Businterface (nur bei Gehäusen ab 100 Pin und nicht bei alle Serien)&lt;br /&gt;
* LCD Treiber für 8x40 Punkte&lt;br /&gt;
* Spannungsbereich 1,65 ... 3,6V, nur eine Betriebsspannung nötig&lt;br /&gt;
* Temperaturbereich bis 125 °C&lt;br /&gt;
* Bis zu 112 IOs, viele davon [[Pegelwandler|5V-tolerant]]&lt;br /&gt;
* Interner, kalibrierter RC-Oszillator mit 8MHz&lt;br /&gt;
* Externer Quarz&lt;br /&gt;
* Real Time Clock mit eigenem Quarz und separater Stromversorgung&lt;br /&gt;
* Bis zu 14 [[Timer]], je Timer bis zu 4 IC/OC/PWM Ausgänge. Davon 2x Motion Control Timer (bei STM32F103xF/G)&lt;br /&gt;
* Systick Counter&lt;br /&gt;
* Bis zu 3 12-Bit [[AD-Wandler]] mit insgesamt 21 AD-Eingängen, integrierter [[Temperatursensor]]&lt;br /&gt;
* Bis zu 2 12-Bit [[DA-Wandler]]&lt;br /&gt;
* Bis zu 2 [[DMA]] Controller mit bis zu 12 Kanälen&lt;br /&gt;
* Bis zu 2x [[I2C|I²C]]&lt;br /&gt;
* Bis zu 5x [[UART|USART]] mit LIN, IrDA und Modem Control&lt;br /&gt;
* Bis zu 3x [[SPI]]&lt;br /&gt;
* Bis zu 2x [[I2S|I²S]]&lt;br /&gt;
* Bis zu 2x [[CAN]]&lt;br /&gt;
* [[USB]] 2.0 Full Speed / OTG&lt;br /&gt;
* SDIO Interface (z.B. SD-Card Reader)&lt;br /&gt;
* Ethernet&lt;br /&gt;
* Watchdog mit Window-Mode&lt;br /&gt;
* Jedes Peripheriemodul ist separat einschaltbar, wodurch sich erheblich [[Ultra low power|Strom sparen]] lässt&lt;br /&gt;
* [[JTAG]] und SWD (Serial Wire Debug) Interface&lt;br /&gt;
* Bis zu 6 Hardware-Breakpoints für Debuggen&lt;br /&gt;
* und vieles mehr . . .&lt;br /&gt;
&lt;br /&gt;
[[bild:stm32F103xc.png]]&lt;br /&gt;
&lt;br /&gt;
== Struktur der Dokumentation: ==&lt;br /&gt;
&lt;br /&gt;
Als Beispiel der Dokumentation soll stellvertretend der [http://www.st.com/mcu/devicedocs-STM32F103RC-110.html STM32F103RC] genannt werden. Die Seite von ST beinhaltet alle nötigen Informationen passend zu diesem Prozessor.&lt;br /&gt;
&lt;br /&gt;
Diese Dokumente von ST beschreiben den Controller:&lt;br /&gt;
&lt;br /&gt;
* [http://www.st.com/stonline/products/literature/ds/14611.pdf Datasheet STM32F103xC/D/E]&lt;br /&gt;
* [http://www.st.com/stonline/products/literature/rm/13902.pdf Reference Manual]&lt;br /&gt;
* [http://www.st.com/stonline/products/literature/pm/15491.pdf Cortex-M3 Programming Manual]&lt;br /&gt;
* [http://www.st.com/stonline/products/literature/pm/13259.pdf Flash Programming Reference]&lt;br /&gt;
&lt;br /&gt;
Im Datasheet sind die speziellen Eigenschaften einer bestimmten Modellreihe beschrieben und die exakten Daten und Pinouts aufgeführt. Die Peripheriemodule werden nur aufgeführt, nicht detailliert beschrieben. In der Referenz ist der gesamte Controller mit Peripheriemodulen im Detail beschrieben, gültig für alle STM32 Controller. Details zum Prozessorkern selbst und den nicht STM32-spezifischen mit dem Cortex-M3 Core assoziierten Modulen wie dem Interrupt-Controller und dem Systick-Timer findet man jedoch nicht dort, sondern im Cortex-M3 Manual. Wer nicht die ST Firmware-Library verwendet, der benötigt zusätzlich die Flash Programming Reference für die Betriebsart des Flash-ROMs, d.h. die frequenzabhängige Konfiguration der Waitstates. Hinzu kommen optionale Dokumente von ARM, die den [http://infocenter.arm.com/help/topic/com.arm.doc.ddi0337-/ Cortex-M3 Kern] beschreiben. Hier gibt es den Opcode wenn man ihn in [http://infocenter.arm.com/help/topic/com.arm.doc.ddi0403-/ Assembler] programmieren möchte. Zusätzlich sollten auch die [http://www.st.com/stonline/products/literature/es/14732.pdf Errata Sheets] beachtet werden. Empfohlen sei auch die Appnote &amp;quot;[http://www.st.com/stonline/products/literature/an/13675.pdf STM32F10xxx hardware development: getting started]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== ‎STM32F10x Standard Peripherals Library ==&lt;br /&gt;
&lt;br /&gt;
ST bietet eine umfangreiche Firmwarebibliothek, eine einzige Bibliothek für alle STM32 Derivate. Das ist der große Vorteil von ST (gibt es beispielsweise auf den Cortex-M3 Controllern von TI auch, ist teilweise in einem separaten ROM untergebracht). Einmal programmieren und in allen STM32 verwendbar. Alle Funktionen sind gekapselt in einfache Strukturen und Funktionsaufrufe. Somit muss man sich nicht selbst um die Peripherieregister kümmern. Diese Library und ihre Dokumentation setzen das grundlegende Verständnis der Funktion des jeweiligen Peripheriemoduls voraus, wie es die o.A. Referenz und diverse Appnotes vermitteln.&lt;br /&gt;
&lt;br /&gt;
Details siehe: [[‎STM32F10x Standard Peripherals Library]].&lt;br /&gt;
&lt;br /&gt;
Mit [https://sourceforge.net/projects/libopenstm32/ libopenstm32] ist derzeit auch eine Open-Source Alternative (GPL, Version 3 oder höher) zur ST Library in Entwicklung.&lt;br /&gt;
&lt;br /&gt;
== CMSIS ==&lt;br /&gt;
&lt;br /&gt;
Parallel zur Firmware-Library gibt es für die &amp;quot;Selbermacher&amp;quot; die CMSIS, die einen Teil der HW und den Core Support abdeckt.&lt;br /&gt;
Im Rahmen des CMSIS Standard ([http://www.onARM.com www.onARM.com]) wurden die Headerfiles standardisiert, der Zugriff auf die Register erfolgt per &#039;&#039;&#039;Peripheral-&amp;gt;Register&#039;&#039;&#039;. Weiterhin existieren eine Zahl von Helferfunktionen für den NVIC, als auch eine SystemInit - Funktion, welche sich um die PLL kümmert.&lt;br /&gt;
Die CMSIS ist im Download der FW-Lib enthalten.&lt;br /&gt;
&lt;br /&gt;
Der Sys-Tick Counter ist ebenfalls in der CMSIS enthalten da er Bestandteil des Cortex-M3 ist.&lt;br /&gt;
&lt;br /&gt;
== Debug-Interface ==&lt;br /&gt;
&lt;br /&gt;
Als Debug Interface stehen zwei Varianten zur Auswahl:&lt;br /&gt;
* [[JTAG]]&lt;br /&gt;
* SWD (Serial Wire Debug)&lt;br /&gt;
&lt;br /&gt;
Für JTAG sind 6 Steuerleitungen nötig, für SWD 2 (zzgl GND/3,3V).&lt;br /&gt;
Die SWD Schnittstelle verfügt außerdem über eine weitere Leitung, SWO. Über diesen Kanal kann ein vereinfachtes Trace des Core ermöglicht werden, sowie &amp;quot;printf-ähnlich&amp;quot; Daten über den ITM Channel 0 geschickt und im Debugger ausgegeben werden.&lt;br /&gt;
&lt;br /&gt;
Die Coresight-Debug-Architektur ermöglicht ein non-invasive debugging, d.h. es können während des Betriebes ohne Beeinflussung des Prozessors Daten vom Speicher gelesen und in selbigen geschrieben werden.&lt;br /&gt;
&lt;br /&gt;
Standard-JTAG Steckerbelegungen: http://www.keil.com/support/man/docs/ulink2/ulink2_hw_connectors.htm&lt;br /&gt;
&lt;br /&gt;
=== Der 10polige JTAG-Stecker von mmvisual ===&lt;br /&gt;
mmvisual hat mit dieser Steckerbelegung die Standard JTAG Schnittstelle erweitert:&lt;br /&gt;
&lt;br /&gt;
Ich habe diesen Part in den Artikel [http://www.mikrocontroller.net/articles/JTAG#Der_10-Polige_JTAG_Stecker_von_mmvisual JTAG] verschoben.&lt;br /&gt;
Hinzu gekommen ist die Adapterplatine 10-Polig auf Standard JTAG 20 Polig mit TTL/V24 Wandler. [http://www.mikrocontroller.net/articles/JTAG#Die_Adapterplatine Siehe hier.]&lt;br /&gt;
&lt;br /&gt;
=== STM32 Programmiertool ===&lt;br /&gt;
&lt;br /&gt;
Details sind hier im Forum: [http://www.mikrocontroller.net/topic/141711 STM32 Programmiertool]&lt;br /&gt;
&lt;br /&gt;
== Vorteile ==&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vorteile gegenüber ARM7:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Interrupt-Controller jetzt Teil des Prozessors (als Core Peripheral), die Vector Table ist jetzt eine echte Vektortabelle, keine Sprungleiste wie bei ARM7). Durch Automatismen zwischen Core und NVIC (auto register save r0..r3, lr, sp, pc) bei Interrupt Entry wird eine deutlich schnellere Ausführungszeit bei Interrupts erreicht. Der Interrupt Code muss sich nicht mehr selbst um die Sicherung der o.g. Register kümmern und eine besondere Konfiguration der Handler im Compiler entfällt. Sind vor Beendigung einer ISR (d.h. Rücksprung zum User Code) weitere Interrupts pending, so werden diese ausgeführt, ohne dass eine komplette pop-push-sequenz der Register notwendig ist. Schön beschrieben ist es hier im [http://www.st.com/mcu/files/mcu/1221142709.pdf Insider&#039;s Guide] unter 2.4.5 / Seite 20.&lt;br /&gt;
* Thumb-2 Befehlssatz, deutlich schneller als Thumb-1 und ebenso kompakt&lt;br /&gt;
* Weniger Pins für Debugging benötigt durch SWD&lt;br /&gt;
* Mehr Hardware Breakpoints machen debuggen einfacher&lt;br /&gt;
* Software ist einfacher weil die Umschaltung zwischen ARM Mode und Thumb Mode wegfällt&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Vorteile gegenüber LPC1700 und LPC1300:&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Flexiblere Gehäuseformen mit mehr Peripherie bei kleinen Gehäusen&lt;br /&gt;
* FW-Lib für alle STM32 gleich, alle AppNotes/Demos beziehen sich auf diese eine FW-Lib was die Entwicklung der eigenen Applikation sehr beschleunigt.&lt;br /&gt;
* Genauerer und flexiblerer ADC, insbesondere gegenüber LPC1300&lt;br /&gt;
* Flexiblere Varianten der Peripherie &amp;gt;&amp;gt; bei weniger einen deutlichen Preisvorteil&lt;br /&gt;
* ab 0,85 EUR (Stand 2010) Allerdings gibts den LPC1100 mit Cortex-M0 schon ab 0,65 $!&lt;br /&gt;
&#039;&#039;&#039;Nachteil gegenüber LPC1700:&#039;&#039;&#039;&lt;br /&gt;
* Nur 72 MHz statt 100 MHz (LPC1759: 120 MHz) Taktfrequenz (120 MHz Versionen sind von ST angekündigt)&lt;br /&gt;
* Der LPC1700 besitzt deutlich mehr Mechanismen, um die Auswirkung der Waitstates des Flash-ROMs auf Code- und Datenzugriffe zu reduzieren und das bedeutet mehr Performance bei gleicher Taktfrequenz.&lt;br /&gt;
* Alle LPC1xxx haben 32 Bit Timer.&lt;br /&gt;
&#039;&#039;&#039;Vorteile gegenüber anderen &amp;quot;Kleinen&amp;quot; wie z.B. PIC, Atmel usw.&#039;&#039;&#039;&lt;br /&gt;
* nahezu gleicher Preis bei Hobby Anwendungen&lt;br /&gt;
* 32 Bit ohne Umwege in Assembler rechenbar&lt;br /&gt;
* bessere Peripherie&lt;br /&gt;
* ... und weitere 1000 Punkte ...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Nachteil für Hobby-Anwender&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
* Nicht direkt &amp;quot;Steckbrettauglich&amp;quot;, da kein DIL Gehäuse verfügbar. Der ebay-Shop dipmicro führt jedoch sehr günstige Lötadapter für Umsetzung von LQFP48 auf DIP48.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Programmierung ==&lt;br /&gt;
&lt;br /&gt;
Als Programmieroberfläche kann eine kostenlose Struktur verwendet werden. Es ist für den Einsteiger schwierig herauszufinden welche Open-Source Programme man braucht damit es funktioniert, daher hier eine Zusammenstellung:&lt;br /&gt;
&lt;br /&gt;
* Eclipse&lt;br /&gt;
* Yagarto Tools&lt;br /&gt;
* Codesourcery Light&lt;br /&gt;
* OpenOCD&lt;br /&gt;
* Eclipse Plugin &amp;quot;GDB Hardware Debugging&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Folgende kommerzielle Umgebungen sind verfügbar:&lt;br /&gt;
&lt;br /&gt;
* [http://www.keil.com Keil µVision] (Demo max. 32KB Code)&lt;br /&gt;
* [http://www.iar.com IAR] (Demo max. 32KB Code)&lt;br /&gt;
* [http://www.raisonance.com Raisonance Ride7] (GCC Compiler, kostenlose Version auf Debugging von max. 32KB Code limitiert, keine Limitierung beim Complilieren)&lt;br /&gt;
* [http://www.atollic.com Atollic] (Lite Version ohne Code-Limit, auf GCC basierend)&lt;br /&gt;
* [http://www.rowley.co.uk/arm/ Rowley Crossworks] (Demo 30 Tage unbeschränkt, 150$ für nichtkommerzielle Nutzung, auf GCC basierend)&lt;br /&gt;
&lt;br /&gt;
Programmieradapter&lt;br /&gt;
* [http://www.segger.com J-Link / J-Trace] Cortex-M3, als [http://www.segger.com/cms/j-link-edu.html NonComercial] J-Link für ca. 60,- zu haben, läuft in µVision, IAR, gdb&lt;br /&gt;
* [http://olimex.com/dev/index.html Olimex] ARM-USB-OCD (ca. 60.-)&lt;br /&gt;
* Keil [http://www.keil.com/arm/ulink2/ ULINK2], [http://www.keil.com/arm/ulinkpro/ ULINK pro]&lt;br /&gt;
* [http://www.st.com/mcu/contentid-126-110-ST_LINK.html ST-Link]&lt;br /&gt;
* [http://www.raisonance.com/~rlink-debugger-programmer__microcontrollers__tool~tool__T018:4cn9ziz4bnx6.html Raisonance RLink]&lt;br /&gt;
* [http://www.amontec.com Amontec]&lt;br /&gt;
* [http://www.hjtag.com H-JTAG] Personal Edition für ca. 60,- zu haben, läuft mit ADS, SDT, IAR, Vision und RVDS &lt;br /&gt;
&lt;br /&gt;
Programmieradapter Open-Source&lt;br /&gt;
* [http://www.oocdlink.com/ OOCDLink]&lt;br /&gt;
* [http://www.openpilot.org/Floss-JTAG Floss-JTAG]&lt;br /&gt;
* [http://capitanio.org/mlink/ Linux Demo Code für die Discovery&#039;s ST-Link Programmierung]&lt;br /&gt;
&lt;br /&gt;
Der Controller hat auch einen fest eingebauten Boot-Lader. Damit läßt er sich auch über eine gewöhnliche serielle Schnittstelle programmieren, ohne daß man einen JTAG-Adapter benötigt.&lt;br /&gt;
&lt;br /&gt;
=== Installation für STM32 ===&lt;br /&gt;
&lt;br /&gt;
* Eclipse &amp;quot;Helios&amp;quot; installieren mit GNU ARM Eclipse Plug-in&lt;br /&gt;
    Eclipse IDE for C/C++ Developers downloaden und installieren&lt;br /&gt;
    http://www.eclipse.org/downloads/packages/eclipse-ide-cc-developers/heliosr&lt;br /&gt;
&lt;br /&gt;
    GNU ARM Eclipse Plug-in runterladen und installieren&lt;br /&gt;
    Download: http://sourceforge.net/projects/gnuarmeclipse/&lt;br /&gt;
    Infos: http://sourceforge.net/apps/mediawiki/gnuarmeclipse/index.php?title=Main_Page&lt;br /&gt;
&lt;br /&gt;
    Wird CodeSourcery G++ Lite verwendet so muss die PATH Variable angepasst &lt;br /&gt;
    werden damit das Plugin die CodeSourcery exe Files findet (für Discovery notwendig). &lt;br /&gt;
    Alternativ das eclipse von einem script aus starten und zuerst den PATH erweitern.&lt;br /&gt;
&lt;br /&gt;
    Soll das ST-LINK verwendet werden so kann der Atollic ST-LINK&lt;br /&gt;
    GDBSERVER aus der Atollic free version genutzt werden. &lt;br /&gt;
    Mit dem gdbserver im eclipse kann damit problemlos geflasht und &lt;br /&gt;
    gedebuggt werden (JTAG und SWD).&lt;br /&gt;
&lt;br /&gt;
    Die Startup und Linkerscripts der Atollic free version können für&lt;br /&gt;
    ein Projekt in dieser Konstallation genutzt werden.&lt;br /&gt;
&lt;br /&gt;
* Eclipse &amp;quot;Galileo&amp;quot; installation:&lt;br /&gt;
    http://www.eclipse.org/ &amp;gt;&amp;gt; Downloads &amp;gt;&amp;gt; &amp;quot;Eclipse IDE for C/C++ Developers (79 MB)&amp;quot;&lt;br /&gt;
    Und das Servicepack 1: [http://www.eclipse.org/downloads/download.php?file=/technology/epp/downloads/release/galileo/SR1/eclipse-cpp-galileo-SR1-win32.zip Eclipse SR1]&lt;br /&gt;
    Entpacken der Datei eclipse-cpp-galileo-SR1-win32.zip nach &amp;quot;C:\WinARM\&amp;quot; (Ordner neu erstellen)&lt;br /&gt;
&lt;br /&gt;
* Eclipse PlugIn hinzufügen:&lt;br /&gt;
    Help &amp;gt;&amp;gt; Install New Software... &amp;gt;&amp;gt; http://download.eclipse.org/tools/cdt/releases/galileo&lt;br /&gt;
    &amp;quot;Eclipse C/C++ Development Tools&amp;quot; + &amp;quot;Eclipse C/C++ GDB Hardware Debugging&amp;quot; installieren&lt;br /&gt;
&lt;br /&gt;
* Yagarto Tools:&lt;br /&gt;
    http://www.yagarto.de/ &amp;gt;&amp;gt; &amp;quot;Download (for Windows)&amp;quot; &amp;gt;&amp;gt; &amp;quot;YAGARTO Tools&amp;quot;&lt;br /&gt;
    http://www.yagarto.de/download/yagarto/yagarto-tools-20091223-setup.exe&lt;br /&gt;
    Installieren, Auswahl Verzeichnis &amp;quot;C:\WinARM\yagarto-tools&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* CodeSourcery:&lt;br /&gt;
    Achtung! Die Memustruktur ändert sich durchaus mal, dann suchen gehen.&lt;br /&gt;
    http://www.codesourcery.com/ &amp;gt;&amp;gt; Products&amp;gt;Sourcery G++ &amp;gt;&amp;gt; Editions&amp;gt;Lite Edition &amp;gt;&amp;gt; ARM &amp;gt;&amp;gt; Downloads&lt;br /&gt;
    Direkter Download: [http://www.codesourcery.com/sgpp/lite/arm/portal/package6496/public/arm-none-eabi/arm-2010q1-188-arm-none-eabi.exe hier]&lt;br /&gt;
    Installieren, Auswahl Verzeichnis &amp;quot;C:\WinARM\CodeSourcery&amp;quot;&lt;br /&gt;
&lt;br /&gt;
* OpenOCD:&lt;br /&gt;
    Kompilierte Version für Windows:&lt;br /&gt;
    http://www.freddiechopin.info/  &amp;gt;&amp;gt; Download &amp;gt;&amp;gt; Software &amp;gt;&amp;gt; OpenOCD&lt;br /&gt;
    installieren nach &amp;quot;C:\WinARM\OpenOCD_0_4_0&amp;quot;&lt;br /&gt;
    ist auch auf der Seite [http://yagarto.de/#ocd Yagarto.de] beschrieben.&lt;br /&gt;
    PS: Sollte der Olimex ARM-USB-OCD verwendet werden, dann darf nicht der Treiber von Olimex verwendet werden,&lt;br /&gt;
    sondern der vom OpenOCD Download. [http://www.mikrocontroller.net/topic/173753#1668913 Siehe hier.]&lt;br /&gt;
&lt;br /&gt;
* ST Firmware:&lt;br /&gt;
    http://www.st.com &amp;gt;&amp;gt; Auswahl CPU STM32F103xxx &amp;gt;&amp;gt; &amp;quot;Firmware&amp;quot; &amp;quot;STM32F10x_StdPeriph_Lib&amp;quot;&lt;br /&gt;
    http://www.st.com/mcu/devicedocs-STM32F103RC-110.html&lt;br /&gt;
    Das ZIP &amp;quot;stm32f10x_stdperiph_lib.zip&amp;quot; Entpacken nach &amp;quot;C:\WinARM\examples\stm32_FW3.4.0\&lt;br /&gt;
&lt;br /&gt;
=== Installation für STM32 auf einem zweiten Rechner===&lt;br /&gt;
&lt;br /&gt;
* Kopieren des Verzeichnisses C:\WinARM\ (Zuvor wurden aus diesem Grund alle Setup-Pakete nach C:\WinARM\... installiert)&lt;br /&gt;
* Die PATH-Variable in der Systemsteuerung mit den C:\WinARM\.... Verzeichnissen nachführen&lt;br /&gt;
* Fertig.&lt;br /&gt;
&lt;br /&gt;
=== Installation für STM32 mit AtollicTrueStudio===&lt;br /&gt;
* Installation + Demo: [[STM32 LEDBlinken AtollicTrueStudio]]&lt;br /&gt;
&lt;br /&gt;
== Demo-Projekte ==&lt;br /&gt;
&lt;br /&gt;
* [[prog_bsp_timer_1_timer2|Programmbeispiel für die Verwendung von Timer2 zusammen mit dem Interrupt]]&lt;br /&gt;
* [[Cortex_M3_OCM3U]]&lt;br /&gt;
* Martin Thomas hat ein umfangreiches Projekt erstellt, in der die Eclipse Einstellungen enthalten sind:&lt;br /&gt;
** [http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/arm_memcards/index.html &amp;quot;ChaN&#039;s FAT-Module with STM32 SPI&amp;quot;]&lt;br /&gt;
* [[STM32 USB-FS-Device Lib]]&lt;br /&gt;
&lt;br /&gt;
== Errata, Tipps und Tricks ==&lt;br /&gt;
&lt;br /&gt;
* AD-Wandler PA0: Im Errata steht, dass hier Fehler in der Wandlung entstehen könnten, also einen anderen Pin verwenden.&lt;br /&gt;
* CAN-Bus PD0/PD1: Remap geht erst ab der 100-Pin-Version. Steht im RM0008 unter 8.3.3. Alle Infos von RM0008 8.3.x sind interssant&lt;br /&gt;
* CAN und USB sind nur bei der &amp;quot;◦Connectivity-Line&amp;quot; gleichzeitig nutzbar. Siehe Datenblätter.&lt;br /&gt;
* Mit internem RC-Oszillator kann die CPU mit maximal 64MHz betrieben werden. Mit einem externen Quarz sind dann 72MHz möglich.&lt;br /&gt;
* Für USB Betrieb muss die CPU mit 48MHz oder 72MHz betrieben werden.&lt;br /&gt;
&lt;br /&gt;
=== Tipps für Umsteiger von Atmel/PIC/8051 ===&lt;br /&gt;
* Prozessortakt hat unterschiedliche Taktquellen und eine PLL.&lt;br /&gt;
* Alle Peripheriemodule haben einen extra Clock, den man aktivieren muss.&lt;br /&gt;
* Wenn man z.B. einen UART benutzen möchte, so muss man den Clock vom UART, Alternate Function IO (AFIO) und dem GPIO-Port aktivieren.&lt;br /&gt;
* Ansonsten hat man nahezu doppelt so viele Möglichkeiten in den Peripheriemodulen.&lt;br /&gt;
* Forum zu [http://www.mikrocontroller.net/topic/175888 Interrupts vs. Events]&lt;br /&gt;
&lt;br /&gt;
== Bezugsquellen ==&lt;br /&gt;
&lt;br /&gt;
=== Controller ===&lt;br /&gt;
&lt;br /&gt;
Versandhäuser für Privatpersonen&lt;br /&gt;
&lt;br /&gt;
* [http://darisusgmbh.de/shop/index.php?cat=c2692_ARM-Cortex.html Darisus]&lt;br /&gt;
* [http://www.hbe-shop.de HBE (Farnell Programm für Private)] &lt;br /&gt;
* [http://www.sander-electronic.de/be00069.html Sander]&lt;br /&gt;
* [http://www.tme.eu/de/katalog/index.phtml#cleanParameters%3D1%26search%3DSTM32F10%26bf_szukaj%3D+ TME] &lt;br /&gt;
* [https://www.distrelec.de/ishopWebFront/catalog/product.do/para/keywords/is/STM32_ARM-Microcontroller/and/language/is/de/and/shop/is/DE/and/series/is/1/and/id/is/01/and/node/is/34910.html Distrelec]&lt;br /&gt;
&lt;br /&gt;
Gewerblich liefern natürlich viele wie Farnell, Digikey usw..&lt;br /&gt;
&lt;br /&gt;
=== Evaluation Boards ===&lt;br /&gt;
&lt;br /&gt;
* [http://shop.embedded-projects.net/index.php?module=artikel&amp;amp;action=gruppe&amp;amp;id=14 Im Shop von Embedded Projects]&lt;br /&gt;
* [http://www.watterott.com/de/Boards-Kits/ARM/ARM-Cortex-M3 Cortex M3 bei Watterott]&lt;br /&gt;
* [http://www.raisonance.com/~primer-starter-kits__microcontrollers__tool~tool__T018:4enfvamuxbtp.html Primer und Primer2 von Raisonance]&lt;br /&gt;
* [http://www.sander-electronic.de/es0028.html Sander Electronic]&lt;br /&gt;
* [http://www.mikrocontroller.net/articles/MP32F103-Stick:_Ein_Mini-Mikrocontroller-Board_mit_USB_und_bis_zu_4MB_Datenspeicher Artikel im Wiki, ARM mit USB und 4MB Speicher]&lt;br /&gt;
* [http://www.futurlec.com/STM32_Development_Board.shtml Futurlec Evalboard, ebenso Header-Board]&lt;br /&gt;
* [http://www.propox.com/products/t_174.html Propox, Header-Boards für 103R und 103V sowie Trägerplatine dafür]&lt;br /&gt;
* [http://www.mikrocontroller.net/articles/Cortex_M3_OCM3U Cortex M3 Artikel im Wiki]&lt;br /&gt;
* [http://olimex.com/dev/index.html STM32 bei Olimex]&lt;br /&gt;
* [http://de.farnell.com/jsp/displayProduct.jsp?sku=1824325&amp;amp;action=view&amp;amp;CMP=GRHS-1000962 STM32Discovery bei Farnell] Mikrocontroller Board (STM32F100RBT6B) mit onboard USB-Programming Interface für ca. 12,50€&lt;br /&gt;
* [http://www.steitec.net/ARM-Boards/ Steitec, STM32F103 Cortex M3 Board 34,80€]&lt;br /&gt;
* [http://www.mcu-raisonance.com/~open4-development-platform__microcontrollers__tool~tool__T018:g65gu6ghg2n.html/ Open 4 oder auch genannt Evo-Primer]&lt;br /&gt;
&lt;br /&gt;
== Weblinks, Foren, Communities ==&lt;br /&gt;
&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/173753 Diskussion zum Artikel]&lt;br /&gt;
* [http://www.mikrocontroller.net/forum/mikrocontroller-elektronik?filter=ARM*+STM32*+Cortex* Suche im Forum]&lt;br /&gt;
* [https://my.st.com/public/STe2ecommunities/mcu/Lists/ARM%20CortexM3%20STM32/AllItems.aspx Forum auf der ST Homepage] &lt;br /&gt;
* [http://www.stm32circle.com/hom/index.php STM32 Community] &lt;br /&gt;
&lt;br /&gt;
[[Kategorie:ARM]]&lt;br /&gt;
[[Kategorie:STM32| ]]&lt;/div&gt;</summary>
		<author><name>Chrisu</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Benutzer_Diskussion:Chrisu&amp;diff=55835</id>
		<title>Benutzer Diskussion:Chrisu</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Benutzer_Diskussion:Chrisu&amp;diff=55835"/>
		<updated>2011-03-13T16:48:39Z</updated>

		<summary type="html">&lt;p&gt;Chrisu: Die Seite wurde geleert.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Chrisu</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=RS-485&amp;diff=54103</id>
		<title>RS-485</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=RS-485&amp;diff=54103"/>
		<updated>2011-01-09T15:26:41Z</updated>

		<summary type="html">&lt;p&gt;Chrisu: /* Einleitung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
RS485 ist die physikalische Spezifikation einer bidirektionalen Verbindung über ein differentiales Leitungspaar. Die Leitung ist idealerweise ein twisted Pair mit 120 Ohm [[Wellenwiderstand]]. Es können zwei oder mehrere Teilnehmer angeschlossen sein. Der Leitungsaufbau ist immer eine Linie, kein Stern und ohne Stichleitungen. Die Leitung ist idealerweise an beiden Enden terminiert. Idealerweise bedeutet hier für höhere Geschwindigkeiten und Distanzen zwingend, bei kurzen Leitungen und niedrigen Geschwindigkeiten nicht, siehe Artikel [[Wellenwiderstand]]. Das Interface ist ein RS485 Transceiver, der beinhaltet einen Sender und einen Empfaenger. &amp;lt;br&amp;gt;&lt;br /&gt;
[[Datei:RS485.png | Transceiver ]]&amp;lt;br&amp;gt;&lt;br /&gt;
Links ist CMOS/TTL Logik, rechts die RS485 Leitung.&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;&lt;br /&gt;
Da nicht mehrere Sender gleichzeitig auf die Leitung aufgeschaltet sein dürfen, muss der jeweilige Sender nach Bedarf eingeschaltet werden ([http://de.wikipedia.org/wiki/Duplex_%28Nachrichtentechnik%29 Halbduplex]). Dies wird auf Protokollebene definiert. Der Sender steuert das differentielle Leitungspaar voll aus, d.h. geht unbelastet auf 0V/Vcc, wobei es 3.3V, sowie 5V Bausteine gibt. Unter Last nimmt die Amplitude dann ab. Der Empfaenger braucht minimal 70mV Differenzspannung in einem Gleichtaktbereich von -7...+12V. Es gibt auch Bausteine mit höheren Gleichtaktspannungen. Während der Standard von bis zu 32 Bausteinen pro Leitung ausgeht, sind Viertel- und Achtelpower Bausteine erhältlich, wovon dann 128 bzw. 256 Stück an eine Leitung angeschlossen werden können. Die Geschwindigkeit und die Reichweite sind nicht im Standard definiert. &amp;lt;b&amp;gt;Bisher sind alle Transceiver pinkomptibel.&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Meist genutzte RS485-Bausteine ==&lt;br /&gt;
* SN75176, günstig und leicht zu beschaffen, aber ein Stromfresser (28-50mA!)&lt;br /&gt;
* LTC485&lt;br /&gt;
* MAX485 Moderne CMOS-Variante mit weniger als 1mA Eigenverbrauch&lt;br /&gt;
* ADM485 &lt;br /&gt;
* ADM483 von Analog Devics, 250kBit, supply 350uA plus load, SO8, 1.14$@100&lt;br /&gt;
&lt;br /&gt;
== Speziellere Ausführungen ==&lt;br /&gt;
&lt;br /&gt;
* SN65HVD23D   von TI, extended common mode -20 to +25V, 25MBit @160m, 64nodes, supply 7mA plus load, SO8, 4.05$@1&lt;br /&gt;
* SN65HVD24D   von TI, extended common mode -20 to +25V, 3MBit @500m, 256 nodes, supply 10mA plus load, SO8, 4.05$ @1&lt;br /&gt;
&lt;br /&gt;
== Weitere Hinweise ==&lt;br /&gt;
&lt;br /&gt;
[[bild:rs485_term.png | framed | RS485 Terminierung mit Pull-Up/Down Widerständen]]&lt;br /&gt;
&lt;br /&gt;
* Failsafe - was passier auf dem Bus, wenn kein Sender aktiv ist? Dann muss man mittles Pull Up und Pull Down Widerstand für definierte Pegel sorgen. Das ist vor allem dann nötig, wenn man mittles [[UART]] Daten überträgt, was bei 90% der RS485 Anwendungen der Fall ist. Arbeitet man mit Terminierung, so werden klassisch die Werte wie im nebenstehenden Bild verwendet. Ohne Terminierung entfällt R2 und R1=R3=1k&amp;amp;Omega;. Diese Terminierung gibt es nur einmal auf dem Bus, nicht an jedem Teilnehmer!&lt;br /&gt;
* Verlustleistung - die Terminierung (100..120 Ohm) verbraucht einiges an Strom, den man mit einem 1uF in Serie unterdrücken kann (AC-Terminierung, siehe Artikel [[Wellenwiderstand]]).&lt;br /&gt;
* [[Galvanische Trennung]] - speziell bei ausgedehnten Systemen können die -7...+12V Gleichtaktbereich nicht genügen, speziell in einem industriellen Umfeld nicht. Dann sollte man eine galvanische Trennung einführen.&lt;br /&gt;
* Die Masse als Referenz sollte man IMMER im Kabel mitführen, auch wenn es scheinbar oft auch ohne funktioniert.&lt;br /&gt;
&lt;br /&gt;
{{Clear}}&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&lt;br /&gt;
* [http://de.wikipedia.org/wiki/RS485 RS485 auf Wikipedia]&lt;br /&gt;
* Slla036b (TI) Interface Circuits for TIA/EIA-485 (RS-485)&lt;br /&gt;
* Slla70c (TI) 422 and 485 Standards Overview and System Configurations&lt;br /&gt;
* Slla169 (TI) Use receiver equalization to extend RS485 data communication&lt;br /&gt;
* AN-1057 (National) Ten Ways to Bulletproof RS-485 Interfaces&lt;br /&gt;
* [http://focus.ti.com/lit/an/slyt324/slyt324.pdf RS-485: Passive failsafe for an idle bus], Application Note slyt324 von TI&lt;br /&gt;
* [http://pdfserv.maxim-ic.com/en/an/AN1090.pdf Methods for Trimming the Power Required in RS-485 Systems], Application Note 1090 von Maxim&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Datenübertragung]]&lt;/div&gt;</summary>
		<author><name>Chrisu</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_Arithmetik/Saturierung&amp;diff=52757</id>
		<title>AVR Arithmetik/Saturierung</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_Arithmetik/Saturierung&amp;diff=52757"/>
		<updated>2010-11-13T23:24:37Z</updated>

		<summary type="html">&lt;p&gt;Chrisu: /* Umsetzung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von [[Benutzer:gjlayde|gjlayde]]&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Unter &#039;&#039;&#039;Saturierung&#039;&#039;&#039; (von engl. &#039;&#039;to saturate&#039;&#039;, wörtlich &#039;&#039;Sättigen&#039;&#039;) versteht man die Eigenschaft bestimmter Operatoren, bei Überschreitung der Bereichs-Grenzen den Maximal- bzw. Minimalwert zu liefern, anstatt überzulaufen und einen Wert zu liefen, der sehr weit vom erwarteten Ergebnis entfernt liegt.&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Bei vielen Anwendungen wie der digitalen Signalverarbeitung ist es wichtig, daß ein Wert an den Rändern seines Wertebereiches nicht überläuft. Ist eine Größe &#039;&#039;x&#039;&#039; zum Beispiel als 8-Bit Wert mit Vorzeichen gespeichert, so führt die Operation&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
    char x = 127; // x =  127&lt;br /&gt;
    char y = x+1; // y = -128&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
zum Ergebnis &#039;&#039;y&#039;&#039;=−128. Solch ein riesiger Sprung ist in vielen Anwendungen fatal. Anstatt an den Bereichsgrenzen überzulaufen ist dann erforderlich daß der Wert an der Maximalgrenze stehen bleibt, d.h. daß das Ergebnis in dem Falle &#039;&#039;y&#039;&#039;=127 ist anstatt −128. Die Variable kann ab dieser Grenze nichts mehr aufnehmen: sie hat ihre &amp;quot;Sättigung&amp;quot; erreicht.&lt;br /&gt;
&lt;br /&gt;
Um saturierte Addition von der üblichen Addition zu unterscheiden, wird hier das Symbol &amp;lt;math&amp;gt;\oplus&amp;lt;/math&amp;gt; verwendet.&lt;br /&gt;
&lt;br /&gt;
Eine saturierte Addition hat eine sehr wichtige Eigenschaft der gewohnten Addition, nämlich die &#039;&#039;Monotonie&#039;&#039;:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
a \geqslant 0 \;\Rightarrow\; x + a \geqslant x \quad\text{sowie}\quad &lt;br /&gt;
a \leqslant 0 \;\Rightarrow\; x + a \leqslant x &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Analoge Zusammenhänge gibt es für die Monotonie der (saturierten) Subtraktion&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
a \geqslant 0 \;\Rightarrow\; x - a \leqslant x \quad\text{sowie}\quad &lt;br /&gt;
a \leqslant 0 \;\Rightarrow\; x - a \geqslant x &lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
sowie für andere saturierte Operatoren wie Negation, Betragsbildung, Multiplikation und Division, welche die gleichen Monotonie-Eigenschaften haben wie die &amp;quot;nativen&amp;quot; mathematischen Operatoren.&lt;br /&gt;
&lt;br /&gt;
Durch Zugewinn der Monotonie verliert man allerdings die &#039;&#039;Assoziativität&#039;&#039;, so daß die Reihenfolge, in der saturierte Operatoren anwandt werden, wie im folgenden Beispiel einen Einfluß auf das Ergebnis haben kann:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
126 = (127 \oplus 1) \ominus 1  \;\neq\; 127 \oplus (1 \ominus 1) = 127&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
Das ist bei Verwendung von saturierten Operatoren immer zu bedenken!&lt;br /&gt;
&lt;br /&gt;
Neber der Saturierung, welche bei den Werte an den Bereichsgrenzen &amp;amp;ndash; also dort, wo ein Überlauf stattfinden würde &amp;amp;ndash; stehen bleibt, gibt es auch Saturierungen, die zB auf den Wertebereich &amp;amp;minus;100...100 begrenzen. Letztere lässt sich zusammensetzen aus einer &amp;quot;normalen&amp;quot; Saturierung, wie sie hier im weiteren besprochen wird, und einer Maximum- bzw. Minimum-Bildung gegen den gewünschten Wertebereich.&lt;br /&gt;
&lt;br /&gt;
== Umsetzung == &lt;br /&gt;
&lt;br /&gt;
Zur konkreten Umsetzung der Saturierung gibt es mehrere Möglichkeiten:&lt;br /&gt;
&lt;br /&gt;
;A priori: Bereits bevor das Ergebnis berechnet wurde wird anhand der Eingabe entschieden, ob der Wertebereich verlassen und ein Über- oder Unterlauf entstehen wird.&lt;br /&gt;
;A posteriori: Erst nach der Berechnung wird anhand des Ergebnisses entschieden, ob ein Über- oder Unterlauf auftrat.&lt;br /&gt;
&lt;br /&gt;
Sind vorzeichenbehaftete Operanden beteiligt, so fällt die Entscheidung strenggenommen automatisch zugunsten der a priori-Variante aus: In C führt der Überlauf von vorzeichenbehafteten Zahlen explizit zu undefiniertem Verhalten; es steht dem Compiler frei, in einem solchen Fall Instruktionen zu generieren, die beispielsweise den Prozessor anhalten oder neustarten.&lt;br /&gt;
&lt;br /&gt;
Am gebräuchlichsten und effizientesten für kleine Typen sind (wenn möglich) A-posteriori-Methoden, da hier das Ergebnis als Entscheidungsgrundlage mit einbezogen werden kann. Das Ergebnis wird unbedingt berechnet und im Fall eines Überlaufs wieder verworfen. Dieser Mehraufwand muss bei aufwändigen Operatoren mit dem Aufwand von a-priori-Methoden abgewogen werden.&lt;br /&gt;
&lt;br /&gt;
Die A-posteriori-Verfahren lassen sich wiederum untergliedern in unterschiedliche Strategien, die je nach Einsatzfeld mehr oder minder effizient oder garnicht anwendbar sind:&lt;br /&gt;
&lt;br /&gt;
;Erweiterter Zahlenbereich: Die Operation wird in einem erweiterten Zahlenbereich ausgeführt in dem kein Überlauf auftreten kann. Das Ergebnis wird dann gegen die Grenzen getestet und ggf. beschnitten. Die Saturierung eines 32-Bit Wertes wird damit sehr aufwändig, weil der nächstgrößere Typ in Hochsprachen 64 Bits breit ist. Irgendwo ist eine Grenze erreicht, ab der es keinen nächstgrößeren Typ mehr gibt. Eine 8-Bit signed Saturierung könnte in C so aussehen:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
char add_signed_sat8 (char x, char y)&lt;br /&gt;
{&lt;br /&gt;
    short x_y = (short) x + y;&lt;br /&gt;
    &lt;br /&gt;
    return MAX (MIN (x_y, 127), -128);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;Auswertung von Flags: Viele Rechenwerke produzieren Flags, die Auskunft über Eigenschaften des Ergebnisses enthalten. Dazu gehören Carry-, Overflow-, Negative-, Zero-Flag etc. Von einer Hochsprache aus hat man auf diese Flags keinen Zugriff, man muss also Assembler zu ihrer Auswertung heranziehen.&lt;br /&gt;
&lt;br /&gt;
;Test auf Ergebnis-Überlauf ohne Flags: Hier wird die Monotonie ausgenutzt: Falls eine positive Zahle addiert wird, so muß das Ergebnis größer werden. Falls nicht, muß ein Überlauf aufgetreten sein. Eine Formulierung in C:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
char add_signed_sat8 (char x, char y)&lt;br /&gt;
{&lt;br /&gt;
    char x_y = x + y;&lt;br /&gt;
&lt;br /&gt;
    if (y &amp;gt; 0  &amp;amp;&amp;amp;  x_y &amp;lt; x)&lt;br /&gt;
        return 127;&lt;br /&gt;
&lt;br /&gt;
    if (y &amp;lt; 0  &amp;amp;&amp;amp;  x_y &amp;gt; x)&lt;br /&gt;
        return -128;&lt;br /&gt;
&lt;br /&gt;
    return x_y;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Auf AVR ===&lt;br /&gt;
&lt;br /&gt;
Saturierung ist eine Eigenschaft eines Operators und &#039;&#039;nicht&#039;&#039; die einer Zahl, wie bei unsigned/signed, welche nur von der Interpretation des Ergebnisses abhängt. Während für signed/unsigned-Addition die gleichen Befehle verwendet werden, ist dies bei Saturierung nicht der Fall, und wir müssen unterscheiden zwischen verschiedenen Ausprägungen der Saturierung, was in unterschiedlichen Implementierungen resultiert.&lt;br /&gt;
&lt;br /&gt;
Wie im vorhergehenden Abschitt zu sehen, kann Saturierung im Vergleich zu einer gewohnten Addition, die in einem Maschinenbefehl umsetzbar ist, sehr aufwändig sein. Daher versuchen wir nach Möglichkeit Status-Flags des AVR zu verwenden, um einen Überlauf zu erkennen. Dies ist von einer Hochsprache aus leider nicht möglich, so daß wir auf (Inline-)Assembler zurückgreifen müssen, um eine effiziente Implementierung zu erhalten. &lt;br /&gt;
&lt;br /&gt;
Angemerkt sei noch, daß in einer Hochsprache wie C auch bei Verwendung von Assembler die Portabilität erhalten bleibt, wenn maschinenabhängige Sequenzen z.&amp;amp;nbsp;B. per &amp;lt;tt&amp;gt;#ifdef&amp;lt;/tt&amp;gt; parametrisiert werden.&lt;br /&gt;
&lt;br /&gt;
==== Unsigned ====&lt;br /&gt;
&lt;br /&gt;
;Addition:&lt;br /&gt;
&lt;br /&gt;
Das ist der einfachste Fall. Die Addition zweier vorzeichenloser Zahlen liefert immer ein nicht-kleineres Ergebnis. Ein Überlauf ist am Carry erkennbar:&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
;; unsigned R16&lt;br /&gt;
;; unsigned R0&lt;br /&gt;
;; R16 := R16 + R0 mit Saturierung&lt;br /&gt;
add  R16, R0&lt;br /&gt;
brcc 0f&lt;br /&gt;
; Falls es einen signed Überlauf gab (C=1) Maximalwert laden&lt;br /&gt;
ldi  R16, 0xff    &lt;br /&gt;
0:&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Als Inline-Assembler-Schnippel für avr-gcc, der in eine Inline-Funktion gefasst ist, sieht das so aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;stdint.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// x += y mit Saturierung&lt;br /&gt;
static inline uint8_t add_usat8 (uint8_t x, uint8_t y)&lt;br /&gt;
{&lt;br /&gt;
    asm (&amp;quot;add  %[x], %[y]&amp;quot;   &amp;quot;\n\t&amp;quot;&lt;br /&gt;
         &amp;quot;brcc 0f&amp;quot;           &amp;quot;\n\t&amp;quot;&lt;br /&gt;
         &amp;quot;ldi  %[x], 0xff&amp;quot;   &amp;quot;\n\t&amp;quot;&lt;br /&gt;
         &amp;quot;0:&amp;quot;&lt;br /&gt;
         : [x] &amp;quot;+d&amp;quot; (x)&lt;br /&gt;
         : [y] &amp;quot;r&amp;quot;  (y));&lt;br /&gt;
&lt;br /&gt;
    return x;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zu beachten ist, daß x wegen dem LDI in Registerklasse &amp;lt;tt&amp;gt;&amp;quot;d&amp;quot;&amp;lt;/tt&amp;gt; (R16&amp;amp;ndash;R31) liegen muss, während für y jedes Register erlaubt ist, es also in Klasse &amp;lt;tt&amp;gt;&amp;quot;r&amp;quot;&amp;lt;/tt&amp;gt; (R0&amp;amp;ndash;R31) liegen kann.&lt;br /&gt;
&lt;br /&gt;
Ein &amp;lt;tt&amp;gt;volatile&amp;lt;/tt&amp;gt; ist hier übrigens nicht notwendig: der Schnippel hat den Compiler nämlich bereits über &#039;&#039;alle&#039;&#039; Nebeneffekte informiert. Der Compiler darf den Schnippel (bzw. die Inline-Funktion) also wegoptmieren, wenn das Ergebnis nicht verwendet wird &amp;amp;ndash; was hier vollkommen in Ordnung ist.&lt;br /&gt;
&lt;br /&gt;
;Subtraktion:&lt;br /&gt;
&lt;br /&gt;
Ganz analog verläuft die Subtraktion:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
;; unsigned R1&lt;br /&gt;
;; unsigned R0&lt;br /&gt;
;; R1 := R1 - R0 mit Saturierung&lt;br /&gt;
sub  R1, R0&lt;br /&gt;
brcc 0f&lt;br /&gt;
; Falls es einen unsigned Unterlauf gab (C=1) Minimalwert laden&lt;br /&gt;
clr  R1&lt;br /&gt;
0:&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Signed ====&lt;br /&gt;
Mehr Aufwand erfordern die signed-Operatoren, weil diese in zwei Richtungen überlaufen können.&lt;br /&gt;
&lt;br /&gt;
;Addition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
;; signed R16&lt;br /&gt;
;; signed R0&lt;br /&gt;
;; R16 := R16 + R0 mit Saturierung&lt;br /&gt;
add  R16, R0&lt;br /&gt;
brvc 0f&lt;br /&gt;
; Falls es einen signed Überlauf gab (V=1) Maximalwert laden&lt;br /&gt;
ldi  R16, 0x7f&lt;br /&gt;
sbrc R0, 7&lt;br /&gt;
; R0 ist negativ, daher muss der Minimalwert geladen werden&lt;br /&gt;
ldi  R16, 0x80&lt;br /&gt;
0:&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Subtraktion:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
;; signed R16&lt;br /&gt;
;; signed R0&lt;br /&gt;
;; R16 := R16 - R0 mit Saturierung&lt;br /&gt;
sub  R16, R0&lt;br /&gt;
brvc 0f&lt;br /&gt;
; Falls es einen signed Überlauf gab (V=1) Minimalwert laden&lt;br /&gt;
ldi  R16, 0x80&lt;br /&gt;
sbrc R0, 7&lt;br /&gt;
; R0 ist negativ, daher muss der Maximalwert geladen werden&lt;br /&gt;
ldi  R16, 0x7f&lt;br /&gt;
0:&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; Negation&lt;br /&gt;
&lt;br /&gt;
Vorsicht ist geboten beim Negieren einer Zahl und bei Betragsbildung, weil der Wert &amp;lt;tt&amp;gt;0x80&amp;lt;/tt&amp;gt;=&amp;amp;minus;128 kein positives Pendant hat:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
;; signed R0&lt;br /&gt;
;; R0 := -R0 mit Saturierung&lt;br /&gt;
neg  R0&lt;br /&gt;
brvc 0f&lt;br /&gt;
; Signed Überlauf (V=1): Das Ergebnis ist 0x80 und wird verändert zu 0x7f&lt;br /&gt;
dec  R0&lt;br /&gt;
0:&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
; Betrag&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
;; signed R0&lt;br /&gt;
;; R0 := Abs (R0) mit Saturierung&lt;br /&gt;
sbrc R0, 7&lt;br /&gt;
neg  R0        ; R0 &amp;lt; 0: negieren&lt;br /&gt;
sbrc R0, 7&lt;br /&gt;
dec  R0        ; R0 ist immer noch &amp;lt; 0 (also 0x80): lade 0x7f&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Unsigned + Signed ====&lt;br /&gt;
&lt;br /&gt;
Diese Kombination ist am aufwändigsten in der Behandlung und geschieht am einfachsten durch Umskalierung auf zwei signed-Werte, signed-saturierter Operation und nachfolgender Rückskalierung. Zu beachten ist, daß dieser Operator nicht kommutativ ist, d.h. a+b liefert i.A. ein anderes Ergebnis als b+a.&lt;br /&gt;
&lt;br /&gt;
;Addition:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
;; unsigned R16&lt;br /&gt;
;; signed   R0&lt;br /&gt;
;; R16 := R16 + R0 mit Saturierung&lt;br /&gt;
; Transformation [0x00, 0xff] -&amp;gt; [0x80, 0x7f]&lt;br /&gt;
subi R16, 0x80&lt;br /&gt;
add  R16, R0&lt;br /&gt;
brvc 0f&lt;br /&gt;
; Falls es einen signed Überlauf gab (V=1) Maximalwert laden&lt;br /&gt;
ldi  R16, 0x7f&lt;br /&gt;
sbrc R0, 7&lt;br /&gt;
; R0 ist negativ, daher muss der Minimalwert geladen werden&lt;br /&gt;
ldi  R16, 0x80&lt;br /&gt;
0:&lt;br /&gt;
; Rücktransformation [0x80, 0x7f] -&amp;gt; [0x00, 0xff]&lt;br /&gt;
subi R16, 0x80&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;Subtraktion:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;avrasm&amp;gt;&lt;br /&gt;
;; unsigned R16&lt;br /&gt;
;; signed   R0&lt;br /&gt;
;; R16 := R16 - R0 mit Saturierung&lt;br /&gt;
; Transformation [0x00, 0xff] -&amp;gt; [0x80, 0x7f]&lt;br /&gt;
subi R16, 0x80&lt;br /&gt;
sub  R16, R0&lt;br /&gt;
brvc 0f&lt;br /&gt;
; Falls es einen signed Überlauf gab (V=1) Minimalwert laden&lt;br /&gt;
ldi  R16, 0x80&lt;br /&gt;
sbrc R0, 7&lt;br /&gt;
; R0 ist negativ, daher muss der Maximalwert geladen werden&lt;br /&gt;
ldi  R16, 0x7f&lt;br /&gt;
0:&lt;br /&gt;
; Rücktransformation [0x80, 0x7f] -&amp;gt; [0x00, 0xff]&lt;br /&gt;
subi R16, 0x80&lt;br /&gt;
&amp;lt;/avrasm&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
Im [[AVR-Tutorial]]:&lt;br /&gt;
* [[AVR-Tutorial: Arithmetik8|8-Bit Arithmetik]]&lt;br /&gt;
* [[AVR-Tutorial: Vergleiche|Vergleiche]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Arithmetik|S]]&lt;/div&gt;</summary>
		<author><name>Chrisu</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=FAQ&amp;diff=47903</id>
		<title>FAQ</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=FAQ&amp;diff=47903"/>
		<updated>2010-05-25T09:05:14Z</updated>

		<summary type="html">&lt;p&gt;Chrisu: /* Datentypen in Operationen */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ein Verzeichnis von im Forum oft gestellten und immer wieder beantworteten Fragen und den zugehörigen Antworten:&lt;br /&gt;
&lt;br /&gt;
=Wie kann ich Zahlen auf [[LCD]]/[[UART]] ausgeben?=&lt;br /&gt;
&lt;br /&gt;
Aber die Bibliothek, die du benutzt, stellt nur eine Funktion zur Verfügung, mit der man einen String ausgeben kann... Was tun? &lt;br /&gt;
&lt;br /&gt;
In den folgenden Beispielen wird eine selbstgeschriebene Funktion zur Stringausgabe auf LCD - die Funktion lcd_string() - aus dem [[AVR-GCC-Tutorial/LCD-Ansteuerung|LCD-Teil des AVR-GCC-Tutorials]] verwendet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
lcd_string( &amp;quot;Hallo Welt&amp;quot; );  // ggf. auch lcd_out() o.ä. in anderen Libraries&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um also eine Zahl (numerische Konstante oder Variableninhalt) auszugeben, muss von dieser Zahl zunächst ihre String-Repräsentation ermittelt werden. Hier geht es aber nur darum, zu zeigen wie man diese String Repräsenation erzeugen kann. Was man dann mit diesem String weiter macht, ob das dann eine LCD-Ausgabe oder eine UART-Übertragung oder das Abspeichern auf SD-Karte oder ... ist, spielt eine untergeordnete Rolle.&lt;br /&gt;
&lt;br /&gt;
Es gibt mehrere Möglichkeiten, sich die Stringrepräsentation zu erzeugen:&lt;br /&gt;
&lt;br /&gt;
===itoa()===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;itoa()&amp;lt;/b&amp;gt; ist keine C-Standardfunktion (wohl aber ihre Umkehrung &amp;lt;b&amp;gt;atoi()&amp;lt;/b&amp;gt; ). Auf manchen Compilern heisst diese Funktion dann folgerichtig &amp;lt;b&amp;gt;_itoa()&amp;lt;/b&amp;gt;, wobei der führende _ eben anzeigt, dass es sich um eine Erweiterung des C-Standards handelt. Bei [[WinAVR]] ist itoa() Bestandteil der mitgelieferten Library avr-libc, in der Libary [http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html&#039;&#039;stdlib.h&#039;&#039;].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
  #include &amp;lt;stdlib.h&amp;gt;&lt;br /&gt;
  char Buffer[20];&lt;br /&gt;
  int i = 25;&lt;br /&gt;
&lt;br /&gt;
  itoa( i, Buffer, 10 );&lt;br /&gt;
  lcd_string( Buffer ); // ggf. auch lcd_out() o.ä. in anderen Libraries&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;itoa( i, Buffer, 10 );&amp;lt;/b&amp;gt; - Die Zahl i wird nach ASCII gewandelt und die String Repräsentierung davon wird in Buffer abgelegt. Die Basis, in der diese Wandlung erfolgt, ist das 10-er System. Wird das dritte Argument von 10 in zb. 2 oder auch 16 abgewandelt, erhält man die binäre oder eben eine hexadezimale Repräsentierung des Wertes. Auch wenn 10, 2 und 16 die häufigsten Angaben an dieser Stelle sind, kann itoa aber grundsätzlich in jedes beliebige Zahlensystem wandlen.&lt;br /&gt;
&lt;br /&gt;
Wichtig ist, darauf zu achten, dass das Array &amp;lt;i&amp;gt;Buffer&amp;lt;/i&amp;gt; groß genug dimensioniert wird, um alle Zeichen der Textrepräsentation der Zahl aufzunehmen - inklusive der 0, die den String abschließt, sowie ein mögliches Vorzeichen.&lt;br /&gt;
&lt;br /&gt;
Anzumerken bleibt weiter, dass es normalerweise für alle Datentypen entsprechende Umwandlungsfunktionen gibt, wenn es sie für einen Datentyp gibt. Die Namensgebung lehnt sich an das Schema an: &#039;&#039;Kürzel_für_den_Datentyp to a&#039;&#039;. Eine Funktion die einen unsigned int wandelt, heißt dann utoa (oder _utoa), Floating Point heißt dann ftoa (oder _ftoa), etc.&lt;br /&gt;
&lt;br /&gt;
===sprintf()===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
  char Buffer[20];&lt;br /&gt;
  int i = 25;&lt;br /&gt;
&lt;br /&gt;
  sprintf( Buffer, &amp;quot;%d&amp;quot;, i );&lt;br /&gt;
  lcd_string( Buffer ); // ggf. auch lcd_out() o.ä. in anderen Libraries&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Diese Methode funktioniert auch bei long oder float Werten. Unbedingt beachtet werden muss allerdings, dass die Typkennzeichnungen im sog. Format-String (hier &amp;quot;%d&amp;quot;) mit den tatsächlichen Typen der auszugebenden Werten übereinstimmt. Und dass der Buffer, der den Text aufnimmt, auch groß genug dimensioniert wird. Dabei sollte die 0, die den String terminiert, nicht vergessen werden.&lt;br /&gt;
&lt;br /&gt;
Mit sprintf() hat man dieselben Möglichkeiten zur Formatierung wie bei &amp;lt;b&amp;gt;printf()&amp;lt;/b&amp;gt; (siehe unten). Insbesondere gibt es natürlich die Möglichkeit die Zahl gleich in einen umgebenden Text einzubetten bzw. Formatierungen anzugeben:&lt;br /&gt;
  &lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
  char Buffer[20];&lt;br /&gt;
  int i = 25;&lt;br /&gt;
&lt;br /&gt;
  sprintf( Buffer, &amp;quot;Anzahl: %d Stueck&amp;quot;, i );&lt;br /&gt;
  lcd_out( Buffer );&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Der &amp;quot;Haken&amp;quot; an der mächtigen Funktion sprintf() ist, daß sie auch bei minimalisierter Konfiguration verhältnismäßig viel Programmspeicher (Flash-ROM) belegt und relativ viel Prozesszeit benötigt. Daher sollte man sprintf() nur verwenden, wenn kein Speicher- und Prozesszeitmangel besteht. Sonst sollte itoa() oder eine eigene, auf die Bedürfnisse optimierte Implementierung auf jeden Fall vorgezogen werden.&lt;br /&gt;
&lt;br /&gt;
====Formatierungen mit printf====&lt;br /&gt;
&lt;br /&gt;
Für jedes auszugebende Argument muss es im Formatstring einen entsprechenden Formatbezeichner geben. Der Aufbau eines Formatbezeichners ist immer&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;b&amp;gt;%[Modifizierer][Feldbreite][.Präzision]Typ&amp;lt;/b&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;Typ&amp;lt;/b&amp;gt; ist dabei eine Kennung, der mit dem Datentyp des jeweiligen auszugebenden Argumentes übereinstimmen muss. Einige oft benutzte Kennungen, ohne Anspruch auf Vollständigkeit, sind:&lt;br /&gt;
  &amp;lt;b&amp;gt;c&amp;lt;/b&amp;gt;    char&lt;br /&gt;
  &amp;lt;b&amp;gt;d&amp;lt;/b&amp;gt;    int&lt;br /&gt;
  &amp;lt;b&amp;gt;f&amp;lt;/b&amp;gt;    float, double&lt;br /&gt;
  &amp;lt;b&amp;gt;ld&amp;lt;/b&amp;gt;   long&lt;br /&gt;
  &amp;lt;b&amp;gt;u&amp;lt;/b&amp;gt;    unsigned int&lt;br /&gt;
  &amp;lt;b&amp;gt;lu&amp;lt;/b&amp;gt;   unsigned long&lt;br /&gt;
  &amp;lt;b&amp;gt;p&amp;lt;/b&amp;gt;    pointer&lt;br /&gt;
  &amp;lt;b&amp;gt;s&amp;lt;/b&amp;gt;    string&lt;br /&gt;
  &amp;lt;b&amp;gt;x&amp;lt;/b&amp;gt;    ein int wird ausgegeben, die Ausgabe erfolgt aber als Hexadezimalzahl&lt;br /&gt;
  &amp;lt;b&amp;gt;X&amp;lt;/b&amp;gt;    ein int wird ausgegeben, die Ausgabe erfolgt aber als Hexadezimalzahl, wobei Grossbuchstaben verwendet werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Die &amp;lt;b&amp;gt;Feldbreite&amp;lt;/b&amp;gt; gibt die Breite des Ausgabefeldes an, in die die Ausgabe durchgeführt werden soll. Reicht die angegebene Feldbreite nicht aus, so vergrößert printf diese Breite eigenmächtig. Die Feldbreite muß nicht angegeben werden. In diesem Fall bestimmt printf selbst die Feldbreite, so dass die Ausgabe darin Platz findet. Mit der Feldbreite hat man eine simple Möglichkeit dafür zu sorgen, dass der erzeugte String immer eine konstante Länge hat, selbst wenn die auszugebende Zahl diese Länge gar nicht benötigen würde (wichtig zb. bei Tabellen).&lt;br /&gt;
&lt;br /&gt;
Der &amp;lt;b&amp;gt;Modifizierer&amp;lt;/b&amp;gt; bestimmt, wie und womit nicht benutzte Felder des Ausgabefeldes gefüllt werden sollen, wie die Ausrichtung innerhalb des Feldes erfolgen soll und ob ein Vorzeichen auch dann ausgegeben werden soll wenn die auszugebende Zahl positiv ist. Wird kein Modifizierer angegeben, so werden nicht benutzte Felder mit einem Leerzeichen gefüllt, positive Vorzeichen unterdrückt und die Ausgabe im Feld rechts ausgerichtet.&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;b&amp;gt;+&amp;lt;/b&amp;gt;    Vorzeichen wird immer ausgegeben&lt;br /&gt;
  &amp;lt;b&amp;gt;-&amp;lt;/b&amp;gt;    Die Ausgabe wird im Ausgabefeld linksbündig ausgerichtet&lt;br /&gt;
  &amp;lt;b&amp;gt;0&amp;lt;/b&amp;gt;    anstelle von Leerzeichen werden führende 0-en ausgegeben&lt;br /&gt;
&lt;br /&gt;
Die &amp;lt;b&amp;gt;Präzision&amp;lt;/b&amp;gt; kommt nur bei float oder double Zahlen zum Einsatz. Sie legt fest, wieviele Positionen der kompletten Feldbreite für die Ausgabe von Nachkommastellen reserviert werden sollen. Auch sie muss wiederrum nicht angegeben werden und printf benutzt in so einem Fall Standardvorgaben.&lt;br /&gt;
&lt;br /&gt;
===== Beispiele =====&lt;br /&gt;
* &amp;lt;b&amp;gt;&amp;quot;%d&amp;quot;&amp;lt;/b&amp;gt; Ausgabe eines Integer&lt;br /&gt;
* &amp;lt;b&amp;gt;&amp;quot;%5d&amp;quot;&amp;lt;/b&amp;gt; Ausgabe eines Integer in einem Feld mit 5 Zeichen Breite&lt;br /&gt;
* &amp;lt;b&amp;gt;&amp;quot;%05d&amp;quot;&amp;lt;/b&amp;gt; Ausgabe eines Integer in einem Feld mit 5 Zeichen Breite, wobei das Feld links mit führenden Nullen auf 5 Zeichen aufgefüllt wird&lt;br /&gt;
* &amp;lt;b&amp;gt;&amp;quot;%-5d&amp;quot;&amp;lt;/b&amp;gt; Ausgabe eines Integer in einem Feld mit 5 Zeichen Breite. Die Zahl wird linksbündig in das Feld gestellt.&lt;br /&gt;
* &amp;lt;b&amp;gt;&amp;quot;%6.3f&amp;quot;&amp;lt;/b&amp;gt; Ausgabe eines float (oder double). DIe Ausgabe erfolgt in einem Feld mit 6 Zeichen Breite, wobei 3 Nachkommastellen ausgegeben werden. Achtung: In der Feldbreite ist auch ein eventuelles Vorzeichen sowie der Dezimalpunkt enthalten. Bei einer Feldbreite von 6 Zeichen und 3 Nachkommastellen, bleiben bei einer positiven Zahl daher nur 2 Positionen für den Vorkommaanteil, bei negativen sogar nur 1 Stelle ( 6 - 3 Nachkommastellen - 1 Dezimalpunkt - 1 Vorzeichen == 1 )&lt;br /&gt;
&lt;br /&gt;
===Eigene Umwandlungsfunktionen===&lt;br /&gt;
&lt;br /&gt;
Möchte man &amp;lt;b&amp;gt;itoa()&amp;lt;/b&amp;gt; nicht benutzen oder hat es gar auf seinem System nicht zur Verfügung, dann ist es auch nicht schwer, sich selbst eine Funktion dafür zu schreiben:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
void ItoA( int z, char* Buffer )&lt;br /&gt;
{&lt;br /&gt;
  int i = 0;&lt;br /&gt;
  int j;&lt;br /&gt;
  char tmp;&lt;br /&gt;
  unsigned u;    // In u bearbeiten wir den Absolutbetrag von z.&lt;br /&gt;
  &lt;br /&gt;
    // ist die Zahl negativ?&lt;br /&gt;
    // gleich mal ein - hinterlassen und die Zahl positiv machen&lt;br /&gt;
    if( z &amp;lt; 0 ) {&lt;br /&gt;
      Buffer[0] = &#039;-&#039;;&lt;br /&gt;
      Buffer++;&lt;br /&gt;
      // -INT_MIN ist idR. größer als INT_MAX und nicht mehr &lt;br /&gt;
      // als int darstellbar! Man muss daher bei der Bildung &lt;br /&gt;
      // des Absolutbetrages aufpassen.&lt;br /&gt;
      u = ( (unsigned)-(z+1) ) + 1; &lt;br /&gt;
    }&lt;br /&gt;
    else { &lt;br /&gt;
      u = (unsigned)z;&lt;br /&gt;
    }&lt;br /&gt;
    // die einzelnen Stellen der Zahl berechnen&lt;br /&gt;
    do {&lt;br /&gt;
      Buffer[i++] = &#039;0&#039; + u % 10;&lt;br /&gt;
      u /= 10;&lt;br /&gt;
    } while( u &amp;gt; 0 );&lt;br /&gt;
&lt;br /&gt;
    // den String in sich spiegeln&lt;br /&gt;
    for( j = 0; j &amp;lt; i / 2; ++j ) {&lt;br /&gt;
      tmp = Buffer[j];&lt;br /&gt;
      Buffer[j] = Buffer[i-j-1];&lt;br /&gt;
      Buffer[i-j-1] = tmp;&lt;br /&gt;
    }&lt;br /&gt;
    Buffer[i] = &#039;\0&#039;;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das Grundprinzip ist einfach:&amp;lt;br&amp;gt;&lt;br /&gt;
Die Ermittlung der einzelnen Stellen erfolgt in der zentralen Schleife&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
    do {&lt;br /&gt;
      Buffer[i++] = &#039;0&#039; + u % 10;&lt;br /&gt;
      u /= 10;&lt;br /&gt;
    } while( u &amp;gt; 0 );&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
durch fortgesetzte Division durch 10 und Restbildung.&lt;br /&gt;
&lt;br /&gt;
    8392&lt;br /&gt;
&lt;br /&gt;
    8392 % 10           -&amp;gt; &amp;lt;b&amp;gt;2&amp;lt;/b&amp;gt;&lt;br /&gt;
    8392 / 10  -&amp;gt; 839&lt;br /&gt;
&lt;br /&gt;
     839 % 10           -&amp;gt; &amp;lt;b&amp;gt;9&amp;lt;/b&amp;gt;&lt;br /&gt;
     839 / 10  -&amp;gt; 83&lt;br /&gt;
&lt;br /&gt;
      83 % 10           -&amp;gt; &amp;lt;b&amp;gt;3&amp;lt;/b&amp;gt;&lt;br /&gt;
      83 / 10  -&amp;gt; 8&lt;br /&gt;
&lt;br /&gt;
       8 % 10           -&amp;gt; &amp;lt;b&amp;gt;8&amp;lt;/b&amp;gt;&lt;br /&gt;
       8 / 10  -&amp;gt; 0&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Nur leider erhält man dadurch die einzelnen Ziffern der Zahl in umgekehrter Reihenfolge im String (&#039;2&#039; &#039;9&#039; &#039;3&#039; &#039;8&#039; anstelle von &#039;8&#039; &#039;3&#039; &#039;9&#039; &#039;2&#039;). Dies ist aber kein Problem, die nachfolgende Schleife&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
  for( j = 0; j &amp;lt; i / 2; ++j ) {&lt;br /&gt;
    tmp = Buffer[j];&lt;br /&gt;
    Buffer[j] = Buffer[i-j-1];&lt;br /&gt;
    Buffer[i-j-1] = tmp;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
spiegelt den String in sich, sodass danach der String eine korrekte Repräsentation der ursprünglichen Zahl darstellt. Der Funktionsteil vor der &#039;Zerlegeschleife&#039; behandelt den Sonderfall daß die Zahl negativ ist. Negative Zahlen werden behandelt indem im Endergebnis ein &#039;-&#039; vermerkt wird und danach die Zahl positiv gemacht wird.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Siehe auch:&lt;br /&gt;
* Forenbeitrag [http://www.mikrocontroller.net/topic/67405#541885 Integer-Zahl in String mit bestimmter Zeichenlänge]&lt;br /&gt;
* Forenbeitrag [http://www.mikrocontroller.net/topic/84005#704736 (Resourcenschonend) Wert einer Variable am LCD ausgeben] von Niels Hüsken &lt;br /&gt;
* [[Festkommaarithmetik]]&lt;br /&gt;
&lt;br /&gt;
=Datentypen in Operationen=&lt;br /&gt;
Ein häufiges Problem betrifft die Auswertung von Ausdrücken. Konkret die Frage nach den beteiligten Datentypen.&lt;br /&gt;
zb&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
double i;&lt;br /&gt;
int j, k;&lt;br /&gt;
&lt;br /&gt;
i = j / k;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Die Frage lautet dann: Warum erhalte ich keine Kommastellen, ich weise doch das Ergebnis einem double zu?&lt;br /&gt;
&lt;br /&gt;
Dazu ist zu sagen, dass C nicht so funktioniert. Die Tatsache dass i eine double Variable ist, ist für die Auswahl der Operation, welche die Division durchführt, völlig irrelevant. C orientiert sich ausschliesslich an den &lt;br /&gt;
Datentypen der beteiligten Operanden, um zu entscheiden ob die Division als Integer- oder als Gleitkommadivision durchzuführen ist. Und da sowohl j als auch k ein Integer sind, wird die Division als Integerdivision durchgeführt&lt;br /&gt;
unabhängig davon, was mit dem Ergebnis weiter passiert. Erst nach der Division wird das Ergebnis in einen double überführt, um es an i zuweisen zu können. Zu diesem Zeitpunkt gibt es aber keine Kommastellen mehr, eine Integerdivision erzeugt keine. Und damit tauchen klarerweise auch im Ergebnis keine auf.&lt;br /&gt;
&lt;br /&gt;
Aus genau diesem Grund ist zb das Ergebnis von&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
double i;&lt;br /&gt;
i = 5 / 8;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
eine glatte 0 und nicht 0.625. Die Division 5 / 8 wird als Integer Division gemacht und liefert als solche keine Nachkommastellen.&lt;br /&gt;
&lt;br /&gt;
Will man den Compiler dazu zwingen, die Division als Gleitkommadivision durchzuführen, so muss man daher dafür sorgen, dass mindestens einer der beteiligten Operanden ein double Wert ist. Dann bleibt dem Compiler nichts anderes übrig, als auch den zweiten Operanden, so er nicht sowieso schon ein double Wert ist, ebenfalls zu einem double zu machen und die Operation als Gleitkommaoperation durchzuführen.&lt;br /&gt;
&lt;br /&gt;
Generell implementiert der Compiler eine Operation immer im &#039;höchsten&#039; Datentyp, der in einer Operation vorkommt. Operanden in einem &#039;niedrigeren&#039; Datentyp werden automatisch immer in diesen &#039;höchsten&#039; Datentyp umgewandelt, zumindest aber int. Die Reihung orientiert sich dabei an der Regel: Ein &#039;höherer&#039; Datentyp kann alle Werte eines &#039;niedrigeren&#039; Datentyps aufnehmen.&lt;br /&gt;
&lt;br /&gt;
    int&lt;br /&gt;
    unsigned int&lt;br /&gt;
    long&lt;br /&gt;
    unsigned long&lt;br /&gt;
    long long&lt;br /&gt;
    unsigned long long&lt;br /&gt;
    double&lt;br /&gt;
    &lt;br /&gt;
float kommt in dieser Tabelle gar nicht vor, da Gleitkommaoperationen grundsätzlich immer als double-Operationen durchgeführt werden. Wohl kann es aber sein, dass double und float dieselbe Anzahl an Bits benutzen. Damit reduziert sich eine double Operation effektiv auf eine float Operation.&lt;br /&gt;
&lt;br /&gt;
Hat man also in einer Operation 2 Operanden der Datentypen int und long, so wird der int implizit zu einem long gemacht und die Operation als long Operation durchgeführt. Das Ergebnis hat dann den Datentyp long.&lt;br /&gt;
&lt;br /&gt;
==Welche Datentypen haben Konstante?==&lt;br /&gt;
&lt;br /&gt;
Auch Zahlenkonstante besitzen einen Datentyp, der selbstverständlich vom Compiler bei der Auswahl der Operation berücksichtigt wird. Hier gilt die Regel: Benutzt wird der Datentyp, der die Zahl gerade noch aufnehmen kann. Eine Zahlenkonstante 5 hat daher den Datentyp int. Die Zahl 32767 passt gerade noch in einen int, und hat daher den Datentyp int. 32768 ist für einen int bereits zu groß und hat daher den Datentyp long. 5.0 ist hingegem immer eine double-Konstante. Der Dezimalpunkt erzwingt dieses.&lt;br /&gt;
&lt;br /&gt;
Eine kleine Feinheit gibt es noch zu beachten. Konstanten in dezimaler Schreibweise haben immer einen signed Datentyp, während Konstante in hexadezimaler bzw. oktaler Schreibweise immer einen unsigned Datentyp haben.&lt;br /&gt;
&lt;br /&gt;
Möchte man einer Konstanten einen bestimmten Datentyp aufzwingen, so gibt es dazu 2 (ein halb) Möglichkeiten:&lt;br /&gt;
* Entweder man castet die Konstante in den gewünschten Datentyp&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
   (long)5&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
* oder man benutzt die in C dafür vorgesehene Schreibweise, indem man der Konstanten einen Suffix anhängt, der den gewünschten Datentyp beschreibt&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
    5L&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Beides ergibt eine dezimale 5, die vom Datentyp long ist.&lt;br /&gt;
&lt;br /&gt;
* eine Zahl in mit einem Dezimalkomma&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
    5.0&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
ist immer eine double Zahl. Es sei denn sie hat explizit eien Suffix&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
    5.0F&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
dann hat man es mit einer float Zahl zu tun.&lt;br /&gt;
&lt;br /&gt;
Die gültigen Suffixe für Zahlen sind U, L und F:&lt;br /&gt;
&lt;br /&gt;
* U wie unsigned; dabei wird zuerst int angenommen. Es erfolgt eine automatische Ausweitung auf long, wenn die Zahl den Wertebereich eines unsigned int überschreitet. &lt;br /&gt;
* L wie long; die Zahl selbst kann int oder double sein.&lt;br /&gt;
* F wie float.&lt;br /&gt;
&lt;br /&gt;
=Aktivieren der Floating Point Version von sprintf beim WinAVR mit AVR-Studio=&lt;br /&gt;
Beim WinAVR/AVR-Studio wird standardmässig eine Version der printf-Bibliothek verwendet, die keine Floating Point Verarbeitung unterstützt. Die meisten Programme benötigen keine Floating Point Unterstützung, sodass hier wertvoller Programmspeicherplatz gespart werden kann.&lt;br /&gt;
&lt;br /&gt;
Benutzt man dann allerdings eine printf Variante für die Ausgabe von Floating Point Zahlen, so erscheint an Stelle der korrekt formatierten Zahl lediglich ein &#039;?&#039;. Dies ist ein Indiz, dass die Floating Point Verarbeitung im Projekt aktiviert werden muss.&lt;br /&gt;
&lt;br /&gt;
Um die Floating Point Verarbeitung zu aktivieren, geht man im AVR-Studio wie folgt vor:&lt;br /&gt;
Menüpunkt: &amp;quot;&amp;lt;b&amp;gt;Project&amp;lt;/b&amp;gt;&amp;quot;/&amp;quot;&amp;lt;b&amp;gt;Configuration Options&amp;lt;/b&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Im sich öffnenden Dialog wird in der linken Navigationsleiste der Eintrag &amp;quot;&amp;lt;b&amp;gt;Libraries&amp;lt;/b&amp;gt;&amp;quot; ausgewählt.&lt;br /&gt;
Unter &#039;&amp;lt;b&amp;gt;&amp;lt;i&amp;gt;Available Link Objects&amp;lt;/i&amp;gt;&amp;lt;/b&amp;gt;&#039; werden alle möglichen Bibliotheken angeboten. Für die Aktivierung der Floating Point Unterstützung sind 2 interessant: &lt;br /&gt;
* &amp;lt;b&amp;gt;libprintf_flt.a&amp;lt;/b&amp;gt;&lt;br /&gt;
* &amp;lt;b&amp;gt;libm.a&amp;lt;/b&amp;gt;&lt;br /&gt;
Beide Bibliotheken werden durch aktivieren und einen Druck auf &amp;quot;&amp;lt;b&amp;gt;Add Library --&amp;gt;&amp;lt;/b&amp;gt;&amp;quot; in die rechte Spalte übernommen.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;libc.a&amp;lt;/b&amp;gt; sollte übrigens &amp;lt;u&amp;gt;nicht&amp;lt;/u&amp;gt; zu den Bibliotheken hinzugefügt werden da sie automatisch eingebunden wird. Etwas Hintergrundinformationen gibt es in [http://www.mikrocontroller.net/topic/173630 diesem Thread.]&lt;br /&gt;
&lt;br /&gt;
[[Bild:AVR_Studio_float1.gif]]&lt;br /&gt;
&lt;br /&gt;
Danach wählt man in der Navigationsleiste den Eintrag &amp;quot;&amp;lt;b&amp;gt;Custom Options&amp;lt;/b&amp;gt;&amp;quot;. Unter &#039;&amp;lt;b&amp;gt;&amp;lt;i&amp;gt;Custom Compilation Options&amp;lt;/i&amp;gt;&amp;lt;/b&amp;gt;&#039; wird &#039;&amp;lt;i&amp;gt;[Linker Options]&amp;lt;/i&amp;gt;&#039; ausgewählt und in das Textfeld rechts/unten wird der Text&lt;br /&gt;
&amp;lt;b&amp;gt;-Wl,-u,vfprintf&amp;lt;/b&amp;gt;&lt;br /&gt;
eingegeben. Ein Druck auf &amp;quot;&amp;lt;b&amp;gt;Add&amp;lt;/b&amp;gt;&amp;quot; befördert die Zeile in das Listenfeld darüber, welches die Kommandos an den Linker enthält.&lt;br /&gt;
&lt;br /&gt;
[[Bild:AVR_Studio_float2.gif]]&lt;br /&gt;
&lt;br /&gt;
Damit ist die Konfiguration abgeschlossen, &amp;quot;&amp;lt;b&amp;gt;OK&amp;lt;/b&amp;gt;&amp;quot;&lt;br /&gt;
&lt;br /&gt;
=Wie funktioniert String-Verarbeitung in C?=&lt;br /&gt;
&lt;br /&gt;
In C gibt es, anders als in anderen Programmiersprachen, keinen eigenen String-Datentyp. Als Ersatz dafür werden Character-Arrays benutzt, in denen die einzelnen Character (=Zeichen) gespeichert werden. Allerdings gibt es noch einen Zusatz: Das letzte Zeichen eines Strings ist immer ein &#039;\0&#039;-Zeichen, dass das Ende des Strings markiert. Schlieslich kann ja das Array wesentlich größer sein, als der in ihm gespeicherte String und irgendwie müssen ja diverse Funktionen das tatsächliche Ende eines Strings erkennen können.&lt;br /&gt;
&lt;br /&gt;
Möchte man also die Zeichenkette &amp;quot;Hello World&amp;quot; in einem String speichern, so wird dafür ein Array mit mindestens der Länge 12 benötigt. 11 für die Zeichen die &amp;quot;Hello World&amp;quot; bilden, plus eine zusätzliche Position für das abschliesende &#039;\0&#039;-Zeichen.&lt;br /&gt;
&lt;br /&gt;
Da Strings in char-Arrays gespeichert werden, können selbstverständlich normale Array Operationen dafür benutzt werden:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
  char Test[12];&lt;br /&gt;
&lt;br /&gt;
  Test[0] = &#039;H&#039;;&lt;br /&gt;
  Test[1] = &#039;e&#039;;&lt;br /&gt;
  Test[2] = &#039;l&#039;;&lt;br /&gt;
  Test[3] = &#039;l&#039;;&lt;br /&gt;
  Test[4] = &#039;o&#039;;&lt;br /&gt;
  Test[5] = &#039; &#039;;&lt;br /&gt;
  Test[6] = &#039;W&#039;;&lt;br /&gt;
  Test[7] = &#039;o&#039;;&lt;br /&gt;
  Test[8] = &#039;r&#039;;&lt;br /&gt;
  Test[9] = &#039;l&#039;;&lt;br /&gt;
  Test[10] = &#039;d&#039;;&lt;br /&gt;
  Test[11] = &#039;\0&#039;;   // das abschliessende \0 nicht vergessen! Sonst ist&lt;br /&gt;
                     // das kein String!&lt;br /&gt;
&lt;br /&gt;
  char Temp[6];&lt;br /&gt;
&lt;br /&gt;
  for( i = 0; i &amp;lt; 6; ++i )&lt;br /&gt;
    Temp[i] = Test[ i + 6 ];&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Hinweis:&#039;&#039;&#039; Das &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;blue&amp;quot;&amp;gt;&#039;&#039;&#039;\0&#039;&#039;&#039;&amp;lt;/font&amp;gt;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&amp;lt;/font&amp;gt; ist nichts anderes als eine binäre Null. Diese spezielle Schreibweise soll explizit die Verwendung dieser &#039;&#039;0&#039;&#039; als Stringende - Character &#039;&#039;(char)0&#039;&#039; hervorheben.&lt;br /&gt;
&lt;br /&gt;
Wird im C-Quelltext ein String in der Form &amp;quot;Hello World&amp;quot; geschrieben, also nicht als einzelne Zeichen, so muss man sich um das abschliessende &#039;\0&#039; Zeichen nicht kümmern. Der Compiler ergänzt das stillschweigend von selbst.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Einige Stringfunktionen ==&lt;br /&gt;
Arrays sind in C keine vollwertigen Datentypen, z.&amp;amp;nbsp;B. ist es nicht möglich einem Array in einem Rutsch ein anderes Array zuzuweisen oder 2 Arrays miteinander zu vergleichen. Genau das möchte man aber in der Stringverarbeitung häufig, sodass es dafür Standardfunktionen gibt, die allesamt im Headerfile &amp;quot;string.h&amp;quot; zusammengefasst sind und deren Namen alle mit str... beginnen. Allen diesen Funktionen gemeinsam ist, dass sie sich &amp;lt;font color=FF0000&amp;gt;&amp;lt;b&amp;gt;nicht&amp;lt;/b&amp;gt;&amp;lt;/font&amp;gt; um die korrekte Bereitstellung von Arrays kümmern, sondern davon ausgehen, dass dies vom Programmierer korrekt erledigt wird.&lt;br /&gt;
&lt;br /&gt;
=== strcpy( char* dest, const char* src ) ===&lt;br /&gt;
Kopieren eines Strings von der Speicherfläche auf die src zeigt, zur Speicherfläche, auf die dest zeigt.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
  char Ziel1[20];&lt;br /&gt;
  char Ziel2[20];&lt;br /&gt;
&lt;br /&gt;
  strcpy( Ziel1, &amp;quot;Hallo Welt&amp;quot; );&lt;br /&gt;
  strcpy( Ziel2, Ziel1 );&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== strcat( char* dest, const char* src ) ===&lt;br /&gt;
Anhängen eines Strings an einen bestehenden String.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
  char Ziel[20];&lt;br /&gt;
  char Temp[20];&lt;br /&gt;
&lt;br /&gt;
  strcpy( Ziel, &amp;quot;Hallo &amp;quot; );    // Ziel enthält jetzt den String &amp;quot;Hallo &amp;quot;&lt;br /&gt;
  strcat( Ziel, &amp;quot;Welt&amp;quot; );      // Ziel enthält jetzt den String &amp;quot;Hallo Welt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  strcpy( Temp, &amp;quot; !&amp;quot; );&lt;br /&gt;
  strcat( Ziel, Temp );        // Ziel enthält jetzt den String &amp;quot;Hallo Welt !&amp;quot;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== strcmp( const char* str1, const char* str2 ) ===&lt;br /&gt;
Vergleichen 2-er Strings. Das Ergebnis ist 0, wenn die beiden Strings identisch sind.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
  char Ziel[20];&lt;br /&gt;
&lt;br /&gt;
  strcpy( Ziel, &amp;quot;Hallo Welt&amp;quot; );  // Ziel enthält jetzt den String &amp;quot;Hallo Welt&amp;quot;&lt;br /&gt;
&lt;br /&gt;
  if( strcmp( Ziel, &amp;quot;Hallo Welt&amp;quot; ) == 0 )&lt;br /&gt;
    printf( &amp;quot;Ziel war &#039;Hallo Welt&#039;\n&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
  if( strcmp( Ziel, &amp;quot;test&amp;quot; ) != 0 )&lt;br /&gt;
    printf( &amp;quot;Ziel war NICHT &#039;test&#039;\n&amp;quot; );&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== strlen( const char* str ) ===&lt;br /&gt;
Die Länge eines Strings feststellen. Die Länge beinhaltet nicht das abschliessende &#039;\0&#039; Zeichen.&lt;br /&gt;
&lt;br /&gt;
Unter &#039;Länge&#039; wird hier die tatsächliche Länge des Strings (also die Anzahl der im String gespeicherten Zeichen) verstanden und nicht die &#039;Länge&#039; des Arrays in dem der String gespeichert ist. Wird der Text &amp;quot;test&amp;quot; in einem char-Array der Größe 20 gespeichert, so lautet das Ergebnis von strlen() 4 und nicht etwa 20&lt;br /&gt;
&lt;br /&gt;
&amp;lt;C&amp;gt;&lt;br /&gt;
  char string[20];&lt;br /&gt;
  strcpy( string, &amp;quot;test&amp;quot; );&lt;br /&gt;
  i = strlen( string );      // i bekommt hier den Wert 4&lt;br /&gt;
&amp;lt;/C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Beispiele ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;quot;string.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
  char Meldung[14];&lt;br /&gt;
  strcpy( Meldung, &amp;quot;Hello World&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Mittels der Definition&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
  char Meldung[14];&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
wird ein Array bereitgestellt, welches maximal 14 Zeichen aufnehmen kann. &amp;lt;b&amp;gt;Hello World&amp;lt;/b&amp;gt; verbraucht für die lesbaren Zeichen 11 Array-Positionen, dazu noch das obligatorische abschliessende &#039;\0&#039; Zeichen, macht in Summe 12 Positionen. Eine Definition von 14 Zeichen ist also mehr als minimal notwendig&lt;br /&gt;
wäre. Das macht aber nichts, da durch das abschliessende &#039;\0&#039; Zeichen immer feststellbar ist, an welcher Stelle der tatsächliche String zu Ende ist. Die restlichen 2 Array-Positionen sind zur Zeit halt einfach unbenutzt.&lt;br /&gt;
&amp;lt;b&amp;gt;strcpy()&amp;lt;/b&amp;gt; kopiert den 2.ten angegebenen String an die Position auf die sein erstes Argument zeigt. Im obigen Beispiel zeigt das 1.te Argument auf den Beginn von &amp;lt;i&amp;gt;Meldung&amp;lt;/i&amp;gt;, also auf das Array. Folgerichtig wird der String &amp;quot;Hello World&amp;quot; in das Array &amp;lt;i&amp;gt;Meldung&amp;lt;/i&amp;gt; umkopiert. Man beachte auch, dass der Compiler den direkt angegebenen String &amp;quot;Hello World&amp;quot; automatisch mit einem &#039;\0&#039; Zeichen ergänzt hat.&lt;br /&gt;
Nach Ausführung der &amp;lt;b&amp;gt;strcpy()&amp;lt;/b&amp;gt; Funktion enthält also &amp;lt;i&amp;gt;Meldung&amp;lt;/i&amp;gt; den Inhalt:&lt;br /&gt;
&lt;br /&gt;
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+&lt;br /&gt;
     | H | e | l | l | o |   | W | o | r | l | d | \0|   |   |&lt;br /&gt;
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+&lt;br /&gt;
     &lt;br /&gt;
Möchte man an diesen Text jetzt noch etwas anfügen, z.&amp;amp;nbsp;B. ein &amp;quot;?&amp;quot;, so würde das so aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;quot;string.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
  char Meldung[14];&lt;br /&gt;
  strcpy( Meldung, &amp;quot;Hello World&amp;quot; );&lt;br /&gt;
  strcat( Meldung, &amp;quot;?&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;FF0000&amp;quot;&amp;gt;&lt;br /&gt;
Man beachte: auch wenn hier scheinbar nur ein einzelnes Zeichen angehängt wird, so handelt es sich doch um einen String. Strings werden in C immer mit einem &amp;quot; eingeleitet und abgeschlossen. Im Gegensatz zu einzelnen Zeichen, die in einfache &#039; eingefasst werden. &amp;quot;?&amp;quot; ist also nicht dasselbe wie &#039;?&#039;! Das&lt;br /&gt;
erste ist ein String (der mit dem obligatorischen &#039;\0&#039; Zeichen insgesamt aus 2 Zeichen besteht), während letzteres ein einzelnes Zeichen darstellt! Die meisten str... Funktionen arbeiten nur mit Strings!&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Da &amp;lt;i&amp;gt;Meldung&amp;lt;/i&amp;gt; maximal 14 Zeichen umfassen kann, der Text &amp;quot;Hello World?&amp;quot; aber nur aus 13 Zeichen besteht, funktioniert Obiges auch ohne Probleme. Der Array-Inhalt sieht dann wie folgt aus:&lt;br /&gt;
&lt;br /&gt;
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+&lt;br /&gt;
     | H | e | l | l | o |   | W | o | r | l | d | ? | \0|   |&lt;br /&gt;
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+&lt;br /&gt;
&lt;br /&gt;
Ein schwerwiegender Fehler wäre es, wenn der komplette String nach dem &amp;lt;b&amp;gt;strcat()&amp;lt;/b&amp;gt; aus mehr als 14 Zeichen (das &#039;\0&#039;-Zeichen nicht vergessen!) bestehen würde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;quot;string.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
  char Meldung[14];&lt;br /&gt;
  strcpy( Meldung, &amp;quot;Hello World&amp;quot; );&lt;br /&gt;
  strcat( Meldung, &amp;quot; von mir&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
würde also das Array überlaufen lassen.&lt;br /&gt;
&lt;br /&gt;
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+&lt;br /&gt;
     | H | e | l | l | o |   | W | o | r | l | d |   | v | o | n       m   i   r   \0&lt;br /&gt;
     +---+---+---+---+---+---+---+---+---+---+---+---+---+---+&lt;br /&gt;
&lt;br /&gt;
Man sieht sehr schön, daß in diesem Fall die weiteren Zeichen einfach an die Folgepositionen im Speicher geschrieben werden und dadurch ungewollt Speicher verändern, der nicht zu &amp;lt;i&amp;gt;Meldung&amp;lt;/i&amp;gt; gehört. Abhängig von den Details des Programmes können aber an dieser Stelle im Speicher z.&amp;amp;nbsp;B. ganz andere Variablen liegen, die dann verändert werden. &amp;lt;b&amp;gt;strcpy()&amp;lt;/b&amp;gt;, &amp;lt;b&amp;gt;strcat()&amp;lt;/b&amp;gt; oder alle anderen String-Funktionen können den Programmierer gegen diesen Fall nicht schützen! Dazu müssten sie die Größe des Speicherbereichs kennen, was sie nicht tun. Es obliegt einzig und alleine der Sorgfalt des Programmierers, das Programm gegen solche Fälle abzusichern!&lt;br /&gt;
&lt;br /&gt;
Seit einiger Zeit wurde das Sammelsurium der str... Funktionen durch Varianten ergänzt, die sich anschicken dieses Manko zu entschärfen. Diesen Funktionen wird die maximale Anzahl der zu bearbeitenden Zeichen mitgegeben. Mit der Kenntnis der Größe des Zielbereichs und der Länge des bereits darin enthaltenen Strings ist es damit möglich eine Obergrenze auszurechnen, wieviele Zeichen von einer Funktion gefahrlos bearbeitet werden dürfen, ehe der Zielbereich überlaufen würde.&lt;br /&gt;
&lt;br /&gt;
Diese Funktionen heißen grundsätzlich gleich wie die str... Funktionen, nur befindet sich ein kleines &#039;n&#039; im Funktionsnamen. Aus &amp;lt;b&amp;gt;strcpy&amp;lt;/b&amp;gt; wird so &amp;lt;b&amp;gt;strncpy&amp;lt;/b&amp;gt;, aus &amp;lt;b&amp;gt;strcat&amp;lt;/b&amp;gt; wird &amp;lt;b&amp;gt;strncat&amp;lt;/b&amp;gt; usw. Für Details dazu sei auf Literatur oder Web-Recherche verwiesen. Auch wenn einen diese Funktionen gegen die gefürchteten Array-Overflows schützen können, so muß man sich trotzem klarmachen, daß dieser Schutz nur die halbe Miete ist. Denn was soll &amp;lt;b&amp;gt;strncpy&amp;lt;/b&amp;gt; denn tun, wenn der zu kopierende String nicht in das Zielarray passt? &amp;lt;b&amp;gt;strncpy&amp;lt;/b&amp;gt; kopiert soviel wie es kann und gibt dann auf. Aber: Dadurch ist der String aber nicht zur Gänze in den Zielbereich kopiert worden. Programmteile die darauf angewiesen sind, daß der String vollständig kopiert wurde, werden dann nicht mehr oder nicht richtig funktionieren usw. Auch wenn die strn... Funktionen eine gewisse Abhilfe bringen und zumindest den Absturz eines Programmes verhindern können, stellen sie dennoch keine Allheilmittel dar. Um die korrekte Abschätzung der benötigten Arraygrößen kommt man nicht umhin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;strlen()&amp;lt;/b&amp;gt; liefert die Länge eines Strings. Die Längenangabe beinhaltet dabei nicht das abschliessende &#039;\0&#039; Zeichen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;quot;string.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
  char Meldung[14];&lt;br /&gt;
  int  Len;&lt;br /&gt;
  &lt;br /&gt;
  strcpy( Meldung, &amp;quot;Hello World&amp;quot; );&lt;br /&gt;
  Len = strlen( Meldung );&lt;br /&gt;
  &lt;br /&gt;
  /* Hier enthaelt Len den Wert 11 */&lt;br /&gt;
&lt;br /&gt;
  Len = strlen( &amp;quot;Hallo Welt&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
  /* Hier enthält Len den Wert 10 */&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;strcmp()&amp;lt;/b&amp;gt; schlussendlich vergleicht 2 Strings auf Gleichheit. Der Rückgabewert spiegelt dabei die Position des ersten Unterschiedes in den beiden Strings wieder. Folgerichtig sagt ein Wert von 0 daher aus, dass die beiden Strings identisch sind:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
#include &amp;quot;string.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
  char Meldung1[14];&lt;br /&gt;
  char Meldung2[14];&lt;br /&gt;
&lt;br /&gt;
  strcpy( Meldung1, &amp;quot;Hello World&amp;quot; );&lt;br /&gt;
  strcpy( Meldung2, &amp;quot;Hallo Welt&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
  if( strcmp( Meldung1, Meldung2 ) == 0 ) {&lt;br /&gt;
    /* die Strings sind identisch */&lt;br /&gt;
  }&lt;br /&gt;
  else {&lt;br /&gt;
    /* die Strings sind nicht identisch */&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  if( strcmp( Meldung2, &amp;quot;Hallo Welt&amp;quot; ) == 0 ) {&lt;br /&gt;
    /* Meldung2 war &amp;quot;Hallo Welt&amp;quot; */&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Es gibt noch weitere String-Funktionen, dafür sei aber auf die Verwendung der zum Compiler gehörenden Dokumentation bzw. auf einführende Literatur zum Thema &#039;Programmieren in C&#039; verwiesen.&lt;br /&gt;
&lt;br /&gt;
=Funktionszeiger=&lt;br /&gt;
Um Menüs oder ähnliche Dinge aufzubauen ist es oft praktisch ein Array von Funktionszeigern zu definieren. Der Aufruf einer Funktion kann dann indirekt über eine Variable erfolgen, wobei die Variable die Adresse der aufzurufenden Funktion enthält.&lt;br /&gt;
&lt;br /&gt;
Um mit Funktionszeigern zu arbeiten ist es in der Praxis sinnvoll sich einen &amp;lt;b&amp;gt;typedef&amp;lt;/b&amp;gt; für den Typ des Funktionszeigers zu definieren. Ein &amp;lt;b&amp;gt;typedef&amp;lt;/b&amp;gt; definiert einen neuen (kürzeren) Namen für einen Datentyp. Und wie wir sehen werden, ist der Datentyp eines Funktionszeigers in der Schreibweise ganz schön umfangreich.&lt;br /&gt;
&lt;br /&gt;
==typedef==&lt;br /&gt;
Einen &amp;lt;b&amp;gt;typedef&amp;lt;/b&amp;gt; zu definieren ist eigentlich ganz einfach: Man schreibt die Deklaration so, als ob man eine Variable definieren würde. Vor das ganze Konstrukt kommt das Schlüsselwort &amp;lt;b&amp;gt;typedef&amp;lt;/b&amp;gt;. Es bewirkt, dass der Name an der Position des Variablennamens zum Namen für den neuen Datentyp wird, der dann in weiterer Folge wie jeder andere Datentyp benutzt werden kann.&lt;br /&gt;
&lt;br /&gt;
Wir wollen einen Funktionszeiger auf eine Funktion definieren, die keine Argumente entgegen nimmt und auch nichts liefert. Also Funktionen nach&lt;br /&gt;
dem Muster:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
void foo( void )&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ein entsprechender &amp;lt;b&amp;gt;typedef&amp;lt;/b&amp;gt; würde zB so aussehen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef void (*VoidFnct)( void );&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das vereinbart einen neuen Datentyp &amp;lt;b&amp;gt;VoidFnct&amp;lt;/b&amp;gt;. Dieser ist ein Funktionszeiger auf Funktionen, die keine Argumente nehmen und auch nichts zurückliefern.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef int (*IntFnct)( void );&lt;br /&gt;
typedef int (*IntFnct2)( int );&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;b&amp;gt;IntFnct&amp;lt;/b&amp;gt; ist ein Zeiger auf eine Funktion, die keine Argumente nimmt aber einen &amp;lt;b&amp;gt;int&amp;lt;/b&amp;gt; zurückliefert. &amp;lt;b&amp;gt;IntFnct2&amp;lt;/b&amp;gt; hingegen ist ein Zeiger auf eine Funktion, die einen &amp;lt;b&amp;gt;int&amp;lt;/b&amp;gt; als Argument nimmt und einen &amp;lt;b&amp;gt;int&amp;lt;/b&amp;gt; zurückliefert. Andere Argumenttypen bzw. Rückgabetypen folgen dem gleichen Muster. Wichtig ist, dass sowohl Argumenttypen als auch Rückgabetypen Teil der Signatur eines Funktionszeigers ist. Es ist also nicht möglich einen Funktionszeigertyp zu vereinbaren, der auf beliebige Funktionen mit beliebigen Argumenttypen bzw. Rückgabetypen verweist. Hier muss man ev. auf einen cast ausweichen. Generell ist das aber meist keine gute Idee.&lt;br /&gt;
&lt;br /&gt;
Die Bildung des Datentyps ist im Grunde eigentlich sehr einfach: Man nimmt in Gedanken den Funktionskopf her.&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
double CelsiusToFahrenheit( double Celsius )&lt;br /&gt;
{&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Dann werden in der Argumentliste alle Argumentnamen entfernt&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
double CelsiusToFahrenheit( double )&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Der Funktionsname durch den Namen des Datentyps getauscht&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
double CallbackFnct( double )&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Vor den Datentypnamen kommt ein * (wie bei allen Zeigerdefinitionen) und rund um dieses Gebilde kommen Klammern (die den * an den Datentypnamen binden und nicht an den Datentyp des Returnwertes)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
double (*CallbackFnct)( double )&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
und fertig ist der Datentyp einer Funktion die einen double als Argument annimmt und einen double als Returnwert liefert. Davor noch der typedef und das abschliessende ; und wir haben einen neuen Datentyp namens CallbackFnct, der einen Funktionszeiger auf Funktionen mit genau dieser Signatur darstellt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef double (*CallbackFnct)( double );&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Funktionszeigertabellen==&lt;br /&gt;
Mit einem &amp;lt;b&amp;gt;typedef&amp;lt;/b&amp;gt; ist es nun ein leichtes ein Array von Funktionszeigern zu vereinbaren:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef void (*VoidFnct)( void );&lt;br /&gt;
&lt;br /&gt;
VoidFnct MeineFunktionen[5];&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Dies vereinbart &amp;lt;i&amp;gt;MeineFunktionen&amp;lt;/i&amp;gt; als ein Array von Funktionszeigern, wobei jeder Funktionszeiger auf eine Funktion vom Typ void-void zeigt.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef void (*VoidFnct)( void );&lt;br /&gt;
&lt;br /&gt;
void Funct1()&lt;br /&gt;
{&lt;br /&gt;
  printf( &amp;quot;Dies ist Funktion 1\n&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void Funct2()&lt;br /&gt;
{&lt;br /&gt;
  printf( &amp;quot;Dies ist Funktion 2\n&amp;quot; );&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
VoidFnct MeineFunktionen[] = { Funct1, Funct2 };&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
  //&lt;br /&gt;
  // ruft die Funktion auf, deren Adresse in MeineFunktionen[0]&lt;br /&gt;
  // steht. In diesem Fall wäre das Funct1()&lt;br /&gt;
  //&lt;br /&gt;
  MeineFunktionen[0]();&lt;br /&gt;
&lt;br /&gt;
  //&lt;br /&gt;
  // und jetzt die MeineFunktionen[1]&lt;br /&gt;
  //&lt;br /&gt;
  MeineFunktionen[1]();&lt;br /&gt;
&lt;br /&gt;
  //&lt;br /&gt;
  // jetzt wird MeineFunktionen[0] umgeleitet auf Funct2()&lt;br /&gt;
  // Achtung: Auf der rechten Seite wird kein () angegeben.&lt;br /&gt;
  // Ansonsten würde ja die Funktione Funct2 aufgerufen. Wir&lt;br /&gt;
  // wollen aber nur ihre Speicheradresse haben! Daher unterbleibt&lt;br /&gt;
  // das ()&lt;br /&gt;
  //&lt;br /&gt;
  MeineFunktionen[0] = Funct2;&lt;br /&gt;
&lt;br /&gt;
  //&lt;br /&gt;
  // welche Funktion wird jetzt aufgerufen?&lt;br /&gt;
  //&lt;br /&gt;
  MeineFunktionen[0]();&lt;br /&gt;
  // Richtig: Die Funktion, deren Adresse in MeineFunktionen[0]&lt;br /&gt;
  //          steht. Und das ist jetzt Funct2.&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Menüs mit Funktionszeigern==&lt;br /&gt;
Besonders bei Menüs ist es oft hilfreich, sich eine Struktur bestehend&lt;br /&gt;
aus dem Menütext und der aufzurufenden Funktion zu definieren. Dazu kann man sich dann auch gleich noch irgendwelche Argumente mit in die Struktur mit aufnehmen, die beim Funktionsaufruf an die Funktion übergeben werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
typedef void (*MenuFnct)( int);&lt;br /&gt;
&lt;br /&gt;
struct MenuEntry {&lt;br /&gt;
  char     Text[20];&lt;br /&gt;
  MenuFnct Function;&lt;br /&gt;
  int      ArgumentToFunction;&lt;br /&gt;
};&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ein Menü ist dann einfach ein Array aus derartigen Strukturelementen&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
void HandleEdit( int arg )&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void HandleCopy( int arg )&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
void HandlePaste( int arg )&lt;br /&gt;
{&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
struct MenuEntry MainMenu[] = {&lt;br /&gt;
 { &amp;quot;Edit&amp;quot;,  HandleEdit,  23 },   // Der Funktion HandleEdit soll beim Aufruf 23 mitgegeben werden&lt;br /&gt;
 { &amp;quot;Copy&amp;quot;,  HandleCopy,   0 },&lt;br /&gt;
 { &amp;quot;Paste&amp;quot;, HandlePaste,  0 }&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
#define ARRAY_SIZE(X) ( sizeof(X) / sizeof(*(X)) )&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
void DoMenu( int NrEntries, struct MenuEntry Menu[] )&lt;br /&gt;
{&lt;br /&gt;
  int i;&lt;br /&gt;
  int Auswahl;&lt;br /&gt;
  &lt;br /&gt;
  do {&lt;br /&gt;
    //&lt;br /&gt;
    // Das Menue anzeigen. Für jeden Menuepunkt noch eine Zahl&lt;br /&gt;
    // davor stellen, damit der Benutzer auch was zum Eingeben hat&lt;br /&gt;
    //&lt;br /&gt;
    for( i = 0; i &amp;lt; NrEntries; ++i )&lt;br /&gt;
      printf( &amp;quot;%d) %s\n&amp;quot;, i + 1, Menu[i].Text ); &lt;br /&gt;
&lt;br /&gt;
    printf( &amp;quot;9) Exit\n\n&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
    // &lt;br /&gt;
    // Jetzt die Benutzereingabe abwarten ...&lt;br /&gt;
    //&lt;br /&gt;
    printf( &amp;quot;Ihre Eingabe: &amp;quot; );&lt;br /&gt;
    scanf( &amp;quot;%d&amp;quot;, &amp;amp;Auswahl );&lt;br /&gt;
&lt;br /&gt;
    //&lt;br /&gt;
    // ... und auswerten&lt;br /&gt;
    //&lt;br /&gt;
    if( Auswahl == 9 )&lt;br /&gt;
      return;&lt;br /&gt;
&lt;br /&gt;
    Auswahl = Auswahl - 1;&lt;br /&gt;
    if( Auswahl &amp;lt; 0 || Auswahl &amp;gt; NrEntries )&lt;br /&gt;
      printf( &amp;quot;Ungültige Eingabe\n&amp;quot; );&lt;br /&gt;
&lt;br /&gt;
    else&lt;br /&gt;
      //&lt;br /&gt;
      // Die Eingabe war gültig. Zugehörige Funktion aufrufen und der Funktion&lt;br /&gt;
      // den in der Menüdefinition vermerkten Wert mitgeben&lt;br /&gt;
      //&lt;br /&gt;
      Menu[Auswahl].Function( Menu[Auswahl].ArgumentToFunction );&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
  // Das Menü arbeiten lassen.&lt;br /&gt;
  // Die Funktion DoMenu ruft selbsttätig die zu den jeweiligen&lt;br /&gt;
  // Menüpunkten gehörenden Funktionen auf. DoMenu kommt erst&lt;br /&gt;
  // dann wieder zurück, wenn der Benutzer den Menüpunkt&lt;br /&gt;
  // 9) Exit&lt;br /&gt;
  // ausgewählt hat.&lt;br /&gt;
&lt;br /&gt;
  DoMenu( ARRAY_SIZE( MainMenu ), MainMenu );&lt;br /&gt;
&lt;br /&gt;
  while( 1 )&lt;br /&gt;
    ;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auf einem Mikrocontroller wird man natürlich die Ein/Ausgabe nicht über &amp;lt;b&amp;gt;printf&amp;lt;/b&amp;gt;/&amp;lt;b&amp;gt;scanf&amp;lt;/b&amp;gt; abwickeln. Hier geht es aber um das Prinzip der Funktionszeiger und wie man mit ihnen arbeitet, daher wurde die allereinfachste Art der Benutzerinteraktion gewählt. Gegebenenfalls muss &amp;lt;b&amp;gt;printf&amp;lt;/b&amp;gt; und &amp;lt;b&amp;gt;scanf&amp;lt;/b&amp;gt; durch die Möglichkeiten auf dem konkreten System ersetzt werden. Auch ist die Art und Weise wie das Menü präsentiert bzw. die Benutzereingabe ausgewertet wird, nicht der Weisheit letzter Schluss. Anstatt den Benutzer Zahlen eingeben zu lassen, könnte man auch einen Auswahl-Balken vom Benutzer mit 2 Tasten über die Menüeinträge bewegen lassen. Oder einen Drehencoder nehmen, ...&lt;br /&gt;
&lt;br /&gt;
=Ich hab da mehrere *.c und *.h Dateien. Was mache ich damit?=&lt;br /&gt;
Zunächst ist es wichtig, sich zu vergegenwärtigen wie denn der C Compiler/Linker überhaupt arbeitet. Ein komplettes Programmier-Projekt kann und wird im Normalfall aus mehreren Source Code Dateien bestehen die alle zusammengenommen das komplette Programm bilden.&lt;br /&gt;
&lt;br /&gt;
Der Prozess des Erstellens des Programmes geschieht in mehrerern Schritten:&lt;br /&gt;
* zunächst werden alle Einzelteile (jede *.c Datei) für sich &#039;&#039;compiliert&#039;&#039;. Dabei ensteht für jede *.c Datei eine sog. Object-Datei in der bereits der Maschinencode für die im *.c programmierten Funktionen enthalten ist&lt;br /&gt;
* danach werden die einzelnen Object-Dateien zusammen mit zusätzlichen Bibliotheken zum fertigen Programm &#039;&#039;gelinkt&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Angenommen das komplette Projekt besteht aus 2 Dateien&lt;br /&gt;
&lt;br /&gt;
Datei: &amp;lt;b&amp;gt;main.c&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
int twice(int i);&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
  twice( 5 );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Datei: &amp;lt;b&amp;gt;func.c&amp;lt;/b&amp;gt;&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
int twice( int number )&lt;br /&gt;
{&lt;br /&gt;
  return 2 * number;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
dann werden &amp;lt;b&amp;gt;main.c&amp;lt;/b&amp;gt; und &amp;lt;b&amp;gt;func.c&amp;lt;/b&amp;gt; &amp;lt;i&amp;gt;unabhängig&amp;lt;/i&amp;gt; voneinander compiliert. Als Ergebnis erhält man die Dateien &amp;lt;b&amp;gt;main.o&amp;lt;/b&amp;gt; und &amp;lt;b&amp;gt;func.o&amp;lt;/b&amp;gt; die den besagten Object-Code enthalten. Erst diese beiden Zwischenergebnisse werden dann zusammen mit eventuellen Bibliotheken zum fertigen Programm gebunden (gelinkt), das dann ausgeführt werden kann.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
        +---------+                         +----------+&lt;br /&gt;
        | main.c  |                         | func.c   |&lt;br /&gt;
        +---------+                         +----------+&lt;br /&gt;
             |                                   |&lt;br /&gt;
             |                                   |&lt;br /&gt;
             v                                   v&lt;br /&gt;
         Compiler                            Compiler&lt;br /&gt;
             |                                   |&lt;br /&gt;
             |                                   |&lt;br /&gt;
             v                                   v&lt;br /&gt;
        +---------+                         +----------+&lt;br /&gt;
        | main.o  |                         | func.o   |&lt;br /&gt;
        +---------+                         +----------+&lt;br /&gt;
             |                                   |&lt;br /&gt;
             +-----------+   +-------------------+&lt;br /&gt;
                         |   |&lt;br /&gt;
                         v   v&lt;br /&gt;
                         Linker  &amp;lt;------ zus. Bibliotheken&lt;br /&gt;
                           |&lt;br /&gt;
                           v&lt;br /&gt;
                      +----------+&lt;br /&gt;
                      | fertiges |&lt;br /&gt;
                      | Programm |&lt;br /&gt;
                      +----------+&lt;br /&gt;
&lt;br /&gt;
Bekommt man also von irgendwo bereits fertige *.c (und zugehörige *.h) Dateien, so genügt es, die *.c Dateien ganz einfach in das Projekt mit aufzunehmen. Daduch wird das entsprechende *.c File compiliert und das Ergebnis davon, das Object-file, wird dann in das fertige Programm mit eingelinkt.&lt;br /&gt;
&lt;br /&gt;
Wie eine *.c Datei in das Projekt mit aufgenommen wird, hängt im wesentlichen von der benutzten Entwicklungsumgebung ab.&lt;br /&gt;
&lt;br /&gt;
==Makefile==&lt;br /&gt;
Die zusätzliche *.c Datei wird in die SRC Zeile im makefile eingetragen.&lt;br /&gt;
==AVR-Studio==&lt;br /&gt;
Hier ist es besonders einfach eine Datei in das Projekt mit aufzunehmen. Dazu wird im Projektbaum einfach der Knoten &amp;quot;Source Files&amp;quot; aktiviert und mit der rechten Maustaste das Kontextmenü geöffnet. Im Menü wird der Punkt &amp;quot;Add existing Source File(s)&amp;quot; ausgewählt und anschliessend zeigt man AVR-Studio das zusätzliche *.c File. AVR-Studio berücksicht dann dieses File bei der Projekterzeugung, compiliert es und sorgt dafür, daß es zum fertigen Programm dazugelinkt wird.&lt;br /&gt;
&lt;br /&gt;
=Globale Variablen über mehrere Dateien=&lt;br /&gt;
Ein häufige Problemkreis in der C Programmierung sind auch globale Variablen, die von mehreren *.c Dateien aus benutzt werden sollen. Was hat es damit auf sich?&lt;br /&gt;
&lt;br /&gt;
Zunächst mal muß man bei der Vereinbarung von Variablen zwischen &amp;lt;b&amp;gt;Definition&amp;lt;/b&amp;gt; und &amp;lt;b&amp;gt;Deklaration&amp;lt;/b&amp;gt; unterscheiden. Worin besteht der Unterschied?&lt;br /&gt;
* &amp;lt;b&amp;gt;Definition&amp;lt;/b&amp;gt;: Mit einer Definition wird der Compiler angewiesen eine Variable tatsächlich zu erzeugen. Damit er das kann, muß ihm selbstverständlich der exakte Datentyp und auch der Name der Variablen zur Verfügung stehen. Eine Definition sorgt also dafür, daß im späteren Programm Speicherplatz für diese Variable reserviert wird&lt;br /&gt;
* &amp;lt;b&amp;gt;Deklaration&amp;lt;/b&amp;gt;: Mit einer Deklaration teilt man dem Compiler lediglich mit, dass eine Variable existiert. An dieser Stelle soll der Compiler also keinen Speicherplatz reservieren (das muß an anderer Stelle geschehen sein), sondern der Compiler soll einfach nur zur Kenntniss nehmen, daß es eine Variable mit einem bestimmten Namen gibt und von welchem Datentyp sie ist.&lt;br /&gt;
&lt;br /&gt;
Aus obigem folgt sofort, dass eine Definition auch immer eine Deklaration ist. Denn dadurch daß der Compiler angewiesen wird eine Variable auch tatsächlich zu erzeugen folgt, dass er dazu auch dieselben Informationen benötigt, die auch in einer Deklaration angegeben werden müssen. Der einzige Unterschied: Bei einer Deklaration trägt der Compiler nur in seinen internen Tabellen ein, dass es diese Variable tatsächlich gibt, während er bei einer Definition zusätzlich auch noch dafür sorgt, dass im fertigen Programm auch noch Speicher für diese Variable bereitgestellt wird.&lt;br /&gt;
&lt;br /&gt;
Warum ist diese Unterscheidung jetzt wichtig?&lt;br /&gt;
&lt;br /&gt;
Weil es in C die sog. &amp;lt;b&amp;gt;One Definition Rule&amp;lt;/b&amp;gt; oder kurz &amp;lt;b&amp;gt;ODR&amp;lt;/b&amp;gt; gibt. Sie besagt, dass in einem vollständigem Programm, also über alle *.c Dateien gesehen, es für eine Variable nur &amp;lt;b&amp;gt;eine&amp;lt;/b&amp;gt; Definition geben darf. Es darf allerdings beliebig viele Deklarationen geben, solange diese Deklarationen alle im Datentyp übereinstimmen. Kurz gesagt: Man darf den Compiler nur einmal auffordern eine Variable zu erzeugen (Definition), kann sich aber beliebig oft auf diese eine Variable beziehen (Deklarationen). Aber Vorsicht! Da der Compiler jede einzelne *.c Datei für sich alleine übersetzt und dabei kein Wissen von ausserhalb benutzt, obliegt es der Verantwortung des Programmierers dafür zu sorgen, dass alle Deklarationen im Datentyp übereinstimmen. Der Compiler kann diese Einhaltung prinzipbedingt nicht überwachen!&lt;br /&gt;
&lt;br /&gt;
Woran erkennt man eine Definition bzw. Deklaration?&lt;br /&gt;
&lt;br /&gt;
Eine Definition einer globalen Variable steht immer ausserhalb eines Funktionsblocks. Zb.&lt;br /&gt;
&amp;lt;C&amp;gt;&lt;br /&gt;
int  MyData;         // Globale Variable namens MyData. Sie ist vom Typ int&lt;br /&gt;
char Name[30];       // Globales Array&lt;br /&gt;
long NrElements = 5; // Globale Variable, die auch noch initialisiert wird&lt;br /&gt;
&amp;lt;/C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Eine Deklaration unterscheidet sich von einer Definition in 2 Punkten&lt;br /&gt;
* Es wird das Schlüsselwort &amp;lt;b&amp;gt;extern&amp;lt;/b&amp;gt; vorangestellt.&lt;br /&gt;
* Es kann keine Initialisierung geben. Sobald eine Initialisierung vorhanden ist, wird das Schlüsselwort &amp;lt;b&amp;gt;extern&amp;lt;/b&amp;gt; ignoriert und aus der Deklaration wird eine Definition.&lt;br /&gt;
&lt;br /&gt;
Beispiele für Deklarationen&lt;br /&gt;
&amp;lt;C&amp;gt;&lt;br /&gt;
extern int  MyData;&lt;br /&gt;
extern char Name[30];&lt;br /&gt;
extern long NrElements;&lt;br /&gt;
extern long NrElements = 5;  // Achtung: Dies ist keine Deklaration!&lt;br /&gt;
&amp;lt;/C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Besitzt man also 2 *.c Dateien, main.c und helpers.c, und sollen sich diese beiden Dateien eine globale Variable teilen, so muss in eine Datei eine Definition hinein, während in die andere Datei eine Deklaration derselben Variablen erfolgen muß. Traditionell werden die Definitionen in der Datei gemacht, die auch die main() Funktion enthält. Das muss nicht so sein, ist aber eine Konvention, die oft Sinn macht. Alternativ wird auch gerne oft eine eigene *.c Datei (zb. globals.c) gemacht, die einzig und alleine die Defintionen der globalen Variablen enthält.&lt;br /&gt;
&lt;br /&gt;
main.c&lt;br /&gt;
&amp;lt;C&amp;gt;&lt;br /&gt;
int  AnzahlElemente;        // Dies ist die Definition. Hier wird die globale&lt;br /&gt;
                            // Variable AnzahlElemente tatsächlich erzeugt.&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
  AnzahlElemente = 8;&lt;br /&gt;
  ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
helpers.c&lt;br /&gt;
&amp;lt;C&amp;gt;&lt;br /&gt;
extern int AnzahlElemente;   // Dies ist die Deklaration die auf die globale&lt;br /&gt;
                             // Variable AnzahlElemente in main.c verweist.&lt;br /&gt;
                             // Wichtig: Der Datentyp muss mit dem in main.c&lt;br /&gt;
                             // angegebenen übereinstimmen&lt;br /&gt;
&lt;br /&gt;
void foo()&lt;br /&gt;
{&lt;br /&gt;
   ...&lt;br /&gt;
  j = AnzahlElemente;&lt;br /&gt;
  AnzahlElemente = 9;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Praktische Durchführung==&lt;br /&gt;
Besteht ein vollständiges Programm aus mehreren *.c Dateien, dann kann man sich vorstellen, daß es mühsam ist, alle Deklarationen immer auf gleich zu halten. Hier bietet sich der Einsatz eines Header Files an, in der die Deklarationen stehen und welches in die jeweiligen *.c Dateien inkludiert wird&lt;br /&gt;
&lt;br /&gt;
Bsp:&lt;br /&gt;
&lt;br /&gt;
Global.h&lt;br /&gt;
&amp;lt;C&amp;gt;&lt;br /&gt;
extern int Anzahl;&lt;br /&gt;
&amp;lt;/C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
main.c&lt;br /&gt;
&amp;lt;C&amp;gt;&lt;br /&gt;
#include &amp;quot;Global.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int Anzahl;      // auch wenn Global.h inkludiert wurde, so muss es eine&lt;br /&gt;
                 // Definition der Variablen geben. In Global.h sind ja nur&lt;br /&gt;
                 // Deklarationen.&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
  ...&lt;br /&gt;
  Anzahl = 5;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
foo.c&lt;br /&gt;
&amp;lt;C&amp;gt;&lt;br /&gt;
#include &amp;quot;Global.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void foo()&lt;br /&gt;
{&lt;br /&gt;
  ...&lt;br /&gt;
  Anzahl = 8;&lt;br /&gt;
  ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
bar.c&lt;br /&gt;
&amp;lt;C&amp;gt;&lt;br /&gt;
#include &amp;quot;Global.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void bar()&lt;br /&gt;
{&lt;br /&gt;
  ...&lt;br /&gt;
  j = Anzahl;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Auf diese Art kann man erreichen, dass zumindest alle Deklarationen ein und derselben Variablen in einem Programm übereinstimmen. Die Datei Global.h wird auch in main.c inkludiert, obwohl man das eigentlich nicht müsste, denn dort wird die Variable ja definiert. Durch die Inclusion ermöglicht man aber dem Compiler die Überprüfung ob die Deklaration auch tatsächlich mit der Definition übereinstimmt.&lt;br /&gt;
&lt;br /&gt;
Solange kein Initialisierungen der globalen Variablen notwendig sind, gibt es noch einen weiteren Trick, um sich selbst das Leben und die Verwaltung der globalen Variablen zu erleichtern.&lt;br /&gt;
Worin besteht das Problem?&lt;br /&gt;
Das Problem besteht darin, dass man bei Einführung einer neuen globalen Variablen an 2 Stellen erweitern muss: Zum einen in der Header-Datei, die die &#039;extern&#039;-Deklaration der Variablen enthält, zum anderen muss in einer C-Datei die Definition der Variablen erfolgen. Das kann man sich mit etwas Präprozessorarbeit auch einfacher machen:&lt;br /&gt;
&lt;br /&gt;
Global.h&lt;br /&gt;
&amp;lt;C&amp;gt;&lt;br /&gt;
#ifndef EXTERN&lt;br /&gt;
#define EXTERN extern&lt;br /&gt;
#endif&lt;br /&gt;
&lt;br /&gt;
EXTERN int Anzahl;&lt;br /&gt;
&amp;lt;/C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
main.c&lt;br /&gt;
&amp;lt;C&amp;gt;&lt;br /&gt;
#define EXTERN&lt;br /&gt;
#include &amp;quot;Global.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
  ...&lt;br /&gt;
  Anzahl = 5;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
foo.c&lt;br /&gt;
&amp;lt;C&amp;gt;&lt;br /&gt;
#include &amp;quot;Global.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
void foo()&lt;br /&gt;
{&lt;br /&gt;
  ...&lt;br /&gt;
  Anzahl = 8;&lt;br /&gt;
  ...&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/C&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wie funktioniert das Ganze? Im Grunde muss man nur dafür sorgen, dass der Compiler an &#039;&#039;einer&#039;&#039; Stelle das Schlüsselwort &#039;&#039;&#039;extern&#039;&#039;&#039; ignoriert (hier in main.c) und bei allen anderen Inclusionen beibehält. Dadurch das ein Präprozessor-ifndef benutzt wird, kann dieses erreicht werden. Wird das Header File includiert und ist zu diesem Zeitpunkt das Makro &#039;&#039;&#039;EXTERN&#039;&#039;&#039; noch nicht definiert, so wird innerhalb des Header Files &#039;&#039;&#039;EXTERN&#039;&#039;&#039; zu &#039;&#039;&#039;extern&#039;&#039;&#039; definiert und damit in weiterer Folge im Quelltext &#039;&#039;&#039;EXTERN&#039;&#039;&#039; durch &#039;&#039;&#039;extern&#039;&#039;&#039; ersetzt. Wenn daher foo.c das Header File inkludiert, wird die Zeile&lt;br /&gt;
&amp;lt;C&amp;gt;&lt;br /&gt;
EXTERN int Anzahl;&lt;br /&gt;
&amp;lt;/C&amp;gt;&lt;br /&gt;
vom Präprozessor zu&lt;br /&gt;
&amp;lt;C&amp;gt;&lt;br /&gt;
extern int Anzahl;&lt;br /&gt;
&amp;lt;/C&amp;gt;&lt;br /&gt;
umgewandelt.&lt;br /&gt;
&lt;br /&gt;
In main.c hingegen sieht die Include-Sequenz so aus&lt;br /&gt;
&amp;lt;C&amp;gt;&lt;br /&gt;
#define EXTERN&lt;br /&gt;
#include &amp;quot;Global.h&amp;quot;&lt;br /&gt;
&amp;lt;/C&amp;gt;&lt;br /&gt;
Wenn Global.h bearbeitet wird, existiert bereits ein Makro &#039;&#039;&#039;EXTERN&#039;&#039;&#039;, das auf einen leeren Text expandiert. Dadurch wird verhindert, dass innerhalb von Global.h das Makro &#039;&#039;&#039;EXTERN&#039;&#039;&#039; mit dem Text &#039;&#039;&#039;extern&#039;&#039;&#039; belegt wird und&lt;br /&gt;
&amp;lt;C&amp;gt;&lt;br /&gt;
EXTERN int Anzahl;&lt;br /&gt;
&amp;lt;/C&amp;gt;&lt;br /&gt;
wird daher vom Präprozessor zu&lt;br /&gt;
&amp;lt;C&amp;gt;&lt;br /&gt;
int Anzahl;&lt;br /&gt;
&amp;lt;/C&amp;gt;&lt;br /&gt;
erweitert, genau wie es benötigt wird.&lt;br /&gt;
&lt;br /&gt;
= Konstanten an fester Flash-Adresse =&lt;br /&gt;
&lt;br /&gt;
Wie kann man eine Konstante an entsprechender Adresse im Flash ablegen?&lt;br /&gt;
&lt;br /&gt;
Mehmet Kendi hat eine Lösung für [[AVR Studio]] &amp;amp; [[WinAVR]] in &lt;br /&gt;
[http://www.mikrocontroller.net/topic/142704#1453079] angegeben.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Grundlagen]]&lt;br /&gt;
[[Kategorie:C]]&lt;/div&gt;</summary>
		<author><name>Chrisu</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=LPC2000&amp;diff=47437</id>
		<title>LPC2000</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=LPC2000&amp;diff=47437"/>
		<updated>2010-05-13T10:42:10Z</updated>

		<summary type="html">&lt;p&gt;Chrisu: /* Verwendung des Bootloaders */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Die LPC2000 von NXP (ehemals Philips) waren die ersten wegen ihrer einfachen Handhabung hobbytauglichen [[ARM]]-basierten Mikrocontroller. Entsprechend sind auch zum LPC2000 mehr Informationen verfügbar als z.&amp;amp;nbsp;B. zum [[AT91SAM]]7, und man findet leichter Hilfe bei Problemen. Ein weiterer Vorteil des LPC2000 ist der einfach zu benutzende serielle Bootloader, mit dem sich der Controller auch ohne JTAG-Interface einfach programmieren lässt. Ansonsten ist die Hardwareausstattung recht ähnlich im Vergleich zum AT91SAM7. Hervorzuhebende Unterschiede sind das schnellere Flash-ROM des LPC2000, die etwas höhere Taktfrequenz, beim gleichen Gehäuse mehr I/O-Pins und die größere Auswahl von Modellen im Low-End-Bereich (LPC2103).&lt;br /&gt;
&lt;br /&gt;
* 2-96 kB [[RAM|SRAM]].&lt;br /&gt;
* bis zu 512 kB [[Flash-ROM]]-Programmspeicher (LPC2138/2148/2368/2378/LPC2387/LPC2388/2468/2478)&lt;br /&gt;
* vorinstallierter serieller [[Bootloader]] mit automatischer [[Baud]]rate-Erkennung&lt;br /&gt;
* [[JTAG]]-Interface&lt;br /&gt;
* ETM Trace-Interface&lt;br /&gt;
* 2-4 [[UART]]-Schnittstellen (bei einigen Modellen auch mit allen &amp;quot;Modem&amp;quot;-Leitungen (Handshake, Ring, DTR etc.)&lt;br /&gt;
* 1-2 [[SPI]]-Schnittstelle(n), bei einigen Modellen auch SSP-Schnittstelle(n) (erweiterte Konfigurationsmöglichkeiten und Funktionen)&lt;br /&gt;
* Hardware-[[I2C]](I²C)-Schnittstelle(n)&lt;br /&gt;
* teilw. mit CAN-Schnittstellen&lt;br /&gt;
* Mit Ausnahme der ersten Chips LPC2104/5/6 haben alle Typen einen integrierten A/D-Wandler&lt;br /&gt;
* teilw. mit D/A-Wandler (LPC2132/34/36/38, LPC2142/44/46/48)&lt;br /&gt;
* 2 32 Bit [[Timer]], zusätzlicher 32-bit [[Timer]] mit 6 [[Pulsweitenmodulation|PWM]]-Ausgängen, RTC, [[Watchdog]]&lt;br /&gt;
* bis 75 MHz Taktfrequenz&lt;br /&gt;
* [[IC-Gehäuseformen|LQFP48]]-Gehäuse (LPC210x) bis LQFP208 (LPC24xx)&lt;br /&gt;
* LPC213x und LPC214x benötigen zum Betrieb 3V&lt;br /&gt;
* Für die anderen Typen werden Core-Spannung 1,65-1,95V und IO-Spannung 3,0-3,6V benötigt (d.h. zum Betrieb sind 2 Versorgungsspannungen erforderlich)&lt;br /&gt;
* geringe Leistungsaufnahme (ca. 60 mW bei 60 MHz und Endlosschleife)&lt;br /&gt;
* 5V-tolerante IOs&lt;br /&gt;
* USB 2.0 Full-Speed (LPC214x und LPC23xx/24xx)&lt;br /&gt;
* Ethernet MAC (LPC23xx/24xx)&lt;br /&gt;
* Jeweils eigene DMA und eigener AHB-Bus für Ethernet, USB und sonstige schnelle Schnittstellen (LPC23xx und LPC24xx)&lt;br /&gt;
* RTC (teilweise mit eigenem Oszillator)&lt;br /&gt;
&lt;br /&gt;
== Verwendung des Bootloaders ==&lt;br /&gt;
&lt;br /&gt;
Benötigte Software gibt es unter http://sourceforge.net/projects/lpc21isp/ zum Download.&lt;br /&gt;
&lt;br /&gt;
# BSL-Jumper setzen&lt;br /&gt;
# Reset-Knopf drücken&lt;br /&gt;
# lpc21isp starten&lt;br /&gt;
#* Linux: lpc21isp programm.hex /dev/ttyS0 115200 14746&lt;br /&gt;
#* Windows: lpc21isp programm.hex com1 115200 14746&lt;br /&gt;
&lt;br /&gt;
Die Übertragung des Programms zum Controller sollte jetzt beginnen. Um das Programm zu starten den &#039;&#039;&#039;BSL-Jumper entfernen&#039;&#039;&#039; und Reset drücken.&lt;br /&gt;
&lt;br /&gt;
Alternativ kann unter MS-Windows das von Philips bereitgestellte &amp;quot;Flash-Tool&amp;quot; oder Flash Magic von Embedded Systems Academy genutzt werden. Diese Programmiersoftware bieten eine grafische Benutzeroberfläche.&lt;br /&gt;
&lt;br /&gt;
Sowohl lpc21isp also auch das Philips-Tool und Flash Magic können Reset und BSL per DTR/RTS-Signal steuern, bei entsprechender Beschaltung auf dem Board muss man somit keine Jumper setzen (vgl. z.&amp;amp;nbsp;B. Schaltpläne der Evaluation-Boards von [http://www.keil.com Keil]).&lt;br /&gt;
&lt;br /&gt;
Eine weitere Alternative ist [http://home.arcor.de/bernhard.michelis/LPC/index.html LPCProg 0.3], welches speziel für auf die Verwendung eines FTDI-232 Chips hin optimiert wurde. Auf der Website gibt es auch ein Layout für einen USB-zu-Seriel-Adapter. Die Software/Hardware ist zu den obigen Programmen Pinkompatibel und kann beliebig damit gemixt werden.&lt;br /&gt;
&lt;br /&gt;
== Allgemeine Hinweise ==&lt;br /&gt;
* Der Softwareschutz bei den LPC2104/5/6 ist nicht implementiert (Stand 4/2005). Dies wird Anfang 2007 geändert. Ein Schutz des geistigen Eigentums ist also bei diesen 3 Controllern derzeit nicht gewährleistet. Andere Controller aus der LPC2000-Serie sind davon nicht betroffen.&lt;br /&gt;
* Auf vielen (Stand 4/2005) LPC2000 existiert ein Fehler bei der Verwaltung der Interrupt-Flags (&amp;quot;race condition&amp;quot;, &amp;quot;timer issue&amp;quot;). Der Fehler und mögliche Abhilfen sind in den Errata von NXP erläutert.&lt;br /&gt;
* Die CAN Controller in den LPC2100,2200 sind so gründlich mit Bugs und Designfehlern gespickt, dass letztlich nur ein kleiner Bruchteil der dokumentierten Funktionen nutzbar ist. Die Bugs finden sich im Errata Sheet, die Konstruktionsfehler darf man selber finden. &lt;br /&gt;
* Bei Nutzung des SPI-Interfaces im &amp;quot;Master-Mode&amp;quot; ist bei einigen LPC2000-Typen auf die richtige Beschaltung des &amp;quot;Chip-Select&amp;quot;-Pins zu achten (vgl. Manuals und Erratas). &lt;br /&gt;
* Viele Fehler in der &amp;quot;ersten Generation&amp;quot; der ICs wurden bei neueren Versionen behoben. Vgl. Datenblätter/Errata zu LPC2xxx/01.&lt;br /&gt;
* Bei neueren LPCs (LPC213x/4x) sollte die aktuelle Fassung der NXP ISP-Software genutzt werden (Stand 3/2006: V2.2.2, erhältlich auf der NXP Web-Site). Ältere Versionen funktionieren nicht zuverlässig oder garnicht.&lt;br /&gt;
* LPC23xx/24xx werden von der Philips ISP-Software nicht unterstützt. Alternativen: Flashmagic oder lpc21isp.&lt;br /&gt;
* Bei Problemen immer auch das Archiv der LPC2000 yahoo-Gruppe absuchen. Dort finden sich, leider oft etwas zerstreut, sehr nützliche Hinweise. Die Anmeldung bei der Gruppe (yahoo-Account erforderlich) gewährt Zugang zum Download-Bereich der Gruppe. Dort finden sich sehr nützliche Beispielprogramme, Libraries und Dokumente.&lt;br /&gt;
* Bei Entwicklungen mit der GNU-Toolchain erweisen sich Beispiele von kommerziellen Compiler/IDE-Anbietern, die ebenfalls den GNU-Compiler nutzen, oft als gute Informationsquelle vor allem bei Einstellungen zum Startup-Code oder im Linker-Script. (vgl. u.a. Rowley, Keil, Anglia-Designs)&lt;br /&gt;
* siehe auch: [http://www.open-research.org.uk/ARMuC/index.cgi?LPC2100Tips LPC2100-Tips] im ARMuC Wiki (englisch)&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
&lt;br /&gt;
* [[ARM-elf-GCC-Tutorial]]&lt;br /&gt;
* [[Linksammlung#ARM|Linksammlung Abschnitt ARM]]&lt;br /&gt;
* [[LPC2000-Boards von Olimex]]&lt;br /&gt;
* [[MP2103-Stick: Ein Mini-Mikrocontroller-Board mit USB und bis zu 4MB Datenspeicher]]&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* [http://www.standardics.nxp.com/products/lpc2000/all/ Philips / NXP LPC2000]&lt;br /&gt;
* [http://groups.yahoo.com/group/lpc2000/ LPC2000 Yahoo Group]&lt;br /&gt;
* [http://www.dreamislife.com/arm/ LPC210x ARM7 Microcontroller Tutorial]&lt;br /&gt;
* [http://www.dontronics-shop.com/tutorials.html Dontronics Tutorials] u.a. &amp;quot;ARM Cross Development with Eclipse Version 3&amp;quot; von James P. Lynch&lt;br /&gt;
* [http://www.hitex.co.uk/arm/lpc2000book/free_downloadpage.html The Insider&#039;s Guide To The Philips ARM7-Based Microcontrollers (LPC21xx)] bei http://www.hitex.co.uk&lt;br /&gt;
* [http://groups.yahoo.com/group/lpc21isp lpc21isp] -  Kommandozeilen-ISP-Tool für Linux und MS-Windows&lt;br /&gt;
* [http://www.esacademy.com/software/flashmagic/ Flash Magic] ISP-Tool&lt;br /&gt;
* [http://www.pjrc.com/arm/lpc2k_pgm/ LPC2K_PGM] - ISP-Tool mit GUI für Linux/GTK&lt;br /&gt;
* [http://www.sandring-systems.de/index.php5?lang=en&amp;amp;p=lf4l lpcflash4linux] - ISP-Tool für Linux (Kommandozeile)&lt;br /&gt;
* [http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/ ARM projects] - LPC2000-Projekte und -Beispiele von Martin Thomas&lt;br /&gt;
* [http://www.jandspromotions.com/philips2005/DE-list.htm LPC2138 Design Contest] - Viele Beispiele mit Hard- and Software&lt;br /&gt;
* [http://www.ixbat.de/index.php?page_id=94 LPC2103 unter Linux entwickeln] - LED blink mit gcc unter Linux&lt;br /&gt;
* [http://www.thegnar.org/nav/LPCgettingstarted.html Bringing up the LPC-P212x] - Bauen einer Toolchain mit Newlib, ISP, JTAG&lt;br /&gt;
* [http://home.arcor.de/bernhard.michelis/LPC/index.html LPCProg 0.3] - Geschwindigkeitsoptimierte Version für USB-zu-Seriell-Wandler, Kommandozeilen-ISP-Tool für MS-Windows; Einfaches Demo-Board verfügbar &lt;br /&gt;
&lt;br /&gt;
[[Category:ARM]] [[Category:Mikrocontroller]]&lt;br /&gt;
__NOTOC__&lt;/div&gt;</summary>
		<author><name>Chrisu</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Benutzer:Chrisu&amp;diff=46887</id>
		<title>Benutzer:Chrisu</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Benutzer:Chrisu&amp;diff=46887"/>
		<updated>2010-04-29T11:14:02Z</updated>

		<summary type="html">&lt;p&gt;Chrisu: Die Seite wurde geleert.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Chrisu</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR-ISP-Stick&amp;diff=42468</id>
		<title>AVR-ISP-Stick</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR-ISP-Stick&amp;diff=42468"/>
		<updated>2010-01-23T00:24:32Z</updated>

		<summary type="html">&lt;p&gt;Chrisu: /* Software */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[Bild:AVR-ISP-Stick-UTIS.JPG|miniatur|rechts|350px]]&lt;br /&gt;
&lt;br /&gt;
Der AVR-ISP-Stick ist ein [[ISP]]-Programmer für Atmels [[AVR]]-Reihe. Seinen Namen hat er wegen Form und Größe, die einem USB-Sticks gleichen. Er stellt die konsequente Optimierung des bekannten USBtinyISP in Hinsicht auf kompakte Baugröße und Kosten dar. Zu letzterem Zwecke wird er als Bausatz ausgeliefert.&lt;br /&gt;
&lt;br /&gt;
Alle Informationen, die für das USBtinyISP(v1) gelten (außer natürlich der physische Aufbau), gelten auch für den AVR-ISP-Stick. Der USBtinyISP ist die Erfindung von Lady Ada, ihre [http://www.ladyada.net/make/usbtinyisp/index.html &amp;lt;Seite&amp;gt;] ist ein nützlicher Anlaufpunkt bei Fragen.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
[[Bild:AVR-ISP-Stick-bottom.png|miniatur|rechts|280px|Layout Bottom]]&lt;br /&gt;
Der Programmer ist auf das wesentliche reduziert, d.h. er besteht im wesentlichen aus einem Attiny2313, einem USB-Stecker und dem ISP-Anschluss. Für USB braucht man einen genauen Takt, der aus einem 12MHz Quarz gewonnen wird. Außerdem kann man mit dem Jumper das Target mit Strom versorgen. Der Stick selbst bezieht seinen Strom aus dem USB-Port.&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
Der Controller des AVR-ISP-Sticks ist bei der Auslieferung bereits fertig programmiert und muss nicht weiter bearbeitet werden.&lt;br /&gt;
&lt;br /&gt;
Für den Betrieb des Sticks wird ein Treiber benötigt. Auffindbar unter &amp;quot;Drivers&amp;quot;&lt;br /&gt;
[http://www.ladyada.net/make/usbtinyisp/download.html Treiberdownload]&lt;br /&gt;
&lt;br /&gt;
Ein kleines Schmankerl des Sticks besteht darin, dass er sich mit ein bisschen Zusatzsoftware nicht nur unter AVRdude, sondern auch unter dem AVR Studio benutzen lässt. Dazu sind zwei Programme notwendig. Eine gute Anleitung findet sich hier: [http://www.ladyada.net/make/usbtinyisp/stk500compat.html Externer Link]&lt;br /&gt;
[[Bild:AVR-ISP-Stick-top.png|miniatur|rechts|410px|Layout Top]]&lt;br /&gt;
&lt;br /&gt;
== FAQ ==&lt;br /&gt;
Einige Antworten auf häufig gestellte Fragen:&lt;br /&gt;
 - Die LED2 leuchtet ständig im Betrieb. LED1 ist nur während dem Programmieren an&lt;br /&gt;
 - Betriebssysteme: Windows XP (32Bit), Windows ??? BITTE ERGÄNZEN!!!&lt;br /&gt;
 - Mögliche Programmierumgebungen: AVR Studio 4, AVRdude, BITTE ERGÄNZEN!!!&lt;br /&gt;
 - NEIN, ES GIBT KEIN GEHÄUSE!!!&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
* Schaltplan: Eagle-Files: [[Datei:Stick.zip]]&lt;br /&gt;
* Schaltplan als PNG Bild: [[Datei:StickPNG.zip]]&lt;br /&gt;
* [http://www.ladyada.net/make/usbtinyisp/download.html Treiber]&lt;br /&gt;
* [http://www.ladyada.net/media/usbtinyisp/usbtinyisp%20v1.0%20firm.zip Quellcode und Hex-File von LadyAda]&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
* Diskussion: [http://www.mikrocontroller.net/topic/160107 Bausatz AVR-ISP-Stick]&lt;br /&gt;
* Diskussion: [http://www.mikrocontroller.net/topic/160025 Projektidee: Der Volks-Programmer]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Projekte|AVR-Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Programmer_und_-Bootloader]]&lt;/div&gt;</summary>
		<author><name>Chrisu</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR-ISP-Stick&amp;diff=42443</id>
		<title>AVR-ISP-Stick</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR-ISP-Stick&amp;diff=42443"/>
		<updated>2010-01-21T22:51:37Z</updated>

		<summary type="html">&lt;p&gt;Chrisu: /* FAQ */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;!-- ToDo:&lt;br /&gt;
* Treiber (erledigt?)&lt;br /&gt;
* LadyAda (erledigt?)&lt;br /&gt;
* Soft USB (für was?)&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
[[Bild:AVR-ISP-Stick-UTIS.JPG|miniatur|rechts|350px]]&lt;br /&gt;
&lt;br /&gt;
Der AVR-ISP-Stick ist ein [[ISP]]-Programmer für Atmels [[AVR]]-Reihe. Seinen Namen hat er wegen Form und Größe, die einem USB-Sticks gleichen. Er stellt die konsequente Optimierung des bekannten USBtinyISP in Hinsicht auf kompakte Baugröße und Kosten dar. Zu letzterem Zwecke wird er als Bausatz ausgeliefert.&lt;br /&gt;
&lt;br /&gt;
Alle Informationen, die für das USBtinyISP(V1) gelten (außer natürlich der physische Aufbau), gelten auch für den AVR-ISP-Stick. Die [http://www.ladyada.net/make/usbtinyisp/index.html Herstellerseite] ist ein nützlicher Anlaufpunkt bei Fragen.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
[[Bild:AVR-ISP-Stick-bottom.png|miniatur|rechts|280px|Layout Bottom]]&lt;br /&gt;
[[Bild:AVR-ISP-Stick-top.png|miniatur|rechts|410px|Layout Top]]&lt;br /&gt;
Der Programmer ist auf das wesentliche reduziert, d.h. er besteht im wesentlichen aus einem Attiny2313, einem USB-Stecker und dem ISP-Anschluss. Für USB braucht man einen genauen Takt, der aus einem 12MHz Quarz gewonnen wird. Außerdem kann man mit dem Jumper das Target mit Strom versorgen. Der Stick selbst bezieht seinen Strom aus dem USB-Port.&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
Der Controller des AVR-ISP-Sticks ist bei der Auslieferung bereits fertig programmiert und muss nicht weiter bearbeitet werden.&lt;br /&gt;
&lt;br /&gt;
Für den Betrieb des Sticks wird ein Treiber benötigt. Auffindbar unter &amp;quot;Drivers&amp;quot;&lt;br /&gt;
[http://www.ladyada.net/make/usbtinyisp/download.html Treiberdownload]&lt;br /&gt;
&lt;br /&gt;
Ein kleines Schmankerl des Sticks besteht darain, dass er sich mit ein bisschen Zusatzsoftware nicht nur unter AVRdude, sondern auch unter dem AVR Studio benutzen lässt. Dazu sind zwei Programme notwendig. Eine gute Anleitung findet sich hier: [http://www.ladyada.net/make/usbtinyisp/stk500compat.html Externer Link]&lt;br /&gt;
&lt;br /&gt;
== FAQ ==&lt;br /&gt;
Einige Antworten auf häufig gestellte Fragen:&lt;br /&gt;
 - Die LED2 leuchtet ständig im Betrieb. LED1 ist nur während dem Programmieren an&lt;br /&gt;
 - Betriebssysteme: Windows XP (32Bit), Windows ??? BITTE ERGÄNZEN!!!&lt;br /&gt;
 - Mögliche Programmierumgebungen: AVR Studio 4, AVRdude, BITTE ERGÄNZEN!!!&lt;br /&gt;
 - NEIN, ES GIBT KEIN GEHÄUSE!!!&lt;br /&gt;
&lt;br /&gt;
== Downloads ==&lt;br /&gt;
* Schaltplan: Eagle-Files: [[Datei:Stick.zip]]&lt;br /&gt;
* Schaltplan als PNG Bild: [[Datei:StickPNG.zip]]&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* Treiber&lt;br /&gt;
* Sourcecode: &lt;br /&gt;
* Hexfile:&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Siehe auch ==&lt;br /&gt;
* Diskussion: [http://www.mikrocontroller.net/topic/160107 Bausatz AVR-ISP-Stick]&lt;br /&gt;
* Diskussion: [http://www.mikrocontroller.net/topic/160025 Projektidee: Der Volks-Programmer]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Projekte|AVR-Projekte]]&lt;br /&gt;
[[Kategorie:AVR-Programmer_und_-Bootloader]]&lt;/div&gt;</summary>
		<author><name>Chrisu</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Diskussion:Linux_Webradio&amp;diff=42217</id>
		<title>Diskussion:Linux Webradio</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Diskussion:Linux_Webradio&amp;diff=42217"/>
		<updated>2010-01-14T14:13:28Z</updated>

		<summary type="html">&lt;p&gt;Chrisu: Die Seite wurde neu angelegt: „Ein paar Bilder wären interessant.“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ein paar Bilder wären interessant.&lt;/div&gt;</summary>
		<author><name>Chrisu</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Benutzer:Chrisu&amp;diff=40174</id>
		<title>Benutzer:Chrisu</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Benutzer:Chrisu&amp;diff=40174"/>
		<updated>2009-10-24T22:22:26Z</updated>

		<summary type="html">&lt;p&gt;Chrisu: Die Seite wurde neu angelegt: „Bin noch Anfänger...“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Bin noch Anfänger...&lt;/div&gt;</summary>
		<author><name>Chrisu</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Benutzer_Diskussion:Chrisu&amp;diff=40173</id>
		<title>Benutzer Diskussion:Chrisu</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Benutzer_Diskussion:Chrisu&amp;diff=40173"/>
		<updated>2009-10-24T22:21:40Z</updated>

		<summary type="html">&lt;p&gt;Chrisu: Die Seite wurde neu angelegt: „Bin noch Anfänger...“&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Bin noch Anfänger...&lt;/div&gt;</summary>
		<author><name>Chrisu</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Olimex_AT91SAM7X256-Board_SAM7-EX256&amp;diff=40170</id>
		<title>Olimex AT91SAM7X256-Board SAM7-EX256</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Olimex_AT91SAM7X256-Board_SAM7-EX256&amp;diff=40170"/>
		<updated>2009-10-24T21:05:09Z</updated>

		<summary type="html">&lt;p&gt;Chrisu: ihrgendein russischer spam scheiß, habe ich gelöscht.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[http://shop.mikrocontroller.net/csc_article_details.php?saArticle%5BID%5D=80 Olimex AT91SAM7X256-Board (SAM7-EX256)]&lt;br /&gt;
&lt;br /&gt;
[http://shop.mikrocontroller.net/csc_article_details.php?saArticle%5BID%5D=80 http://shop.mikrocontroller.net/images/sam7-ex256-small.jpg]&lt;br /&gt;
&lt;br /&gt;
== Softwarevoraussetzungen ==&lt;br /&gt;
&lt;br /&gt;
Die folgenden Anleitungen setzen das Vorhandensein einer [[ARM#Compiler|ARM-GCC-Toolchain]] voraus.&lt;br /&gt;
&lt;br /&gt;
== Minimalbeispiel ==&lt;br /&gt;
&lt;br /&gt;
Dieses einfache Beispielprojekt mit Makefile basiert auf dem GCC-Tutorial von Atmel. Enthalten ist kein OS, nur ein paar Funktionen für UART-Kommunikation.&lt;br /&gt;
&lt;br /&gt;
Download: http://www.mikrocontroller.net/attachment/25724/Olimex_SAM7_EX256_StartupMinimal_2007.08.17.zip&lt;br /&gt;
&lt;br /&gt;
== Installation von FreeRTOS ==&lt;br /&gt;
&lt;br /&gt;
Merkmale von FreeRTOS:&lt;br /&gt;
* präemptives Multitasking&lt;br /&gt;
* Unterstützung für viele Prozessoren und Controller&lt;br /&gt;
* Demos für viele verschiedene Boards enthalten&lt;br /&gt;
* Beispiele für die Anbindung verschiedener IP-Stacks enthalten (lwIP, uIP)&lt;br /&gt;
* Codequalität der Demos durchwachsen&lt;br /&gt;
&lt;br /&gt;
Funktionsumfang des Beispielprojekts:&lt;br /&gt;
* TCP/IP-Stack lwIP&lt;br /&gt;
* Webserver&lt;br /&gt;
* virtueller serieller Port über USB realisiert (CDC, Windows-Treiber enthalten)&lt;br /&gt;
&lt;br /&gt;
Als Ausgangspunkt dient das Beispiel &amp;quot;lwIP_Demo_Rowley_ARM7&amp;quot; aus [http://www.freertos.org FreeRTOS] 4.4.0. Die für das Olimex-Board angepasste (und ein bisschen aufgeräumte) Version kann man [http://www.mikrocontroller.net/attachment/25551/lwIP_Demo_olimex.zip hier] herunterladen. Die Datei muss in den Demo-Ordner von FreeRTOS entpackt werden. Die Änderungen gegenüber der Originalversion sind in der Datei changes.txt dokumentiert.&lt;br /&gt;
&lt;br /&gt;
Die IP-Adresse ist standardmäßig auf 192.168.0.111 gesetzt und lässt sich in der Datei BasicWEB.c ändern.&lt;br /&gt;
&lt;br /&gt;
Kompiliert wird das Projekt wie üblich durch Eingabe von &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Installation von Ethernut ==&lt;br /&gt;
&lt;br /&gt;
Ethernut bzw. Nut/OS ist ein Betriebssystem mit TCP/IP-Stack, das ursprünglich für AVR-Controller entwickelt wurde, später aber u.a. auf ARM portiert wurde.&lt;br /&gt;
&lt;br /&gt;
Merkmale von Nut/OS:&lt;br /&gt;
* sehr sauberer und gut kommentierter Code&lt;br /&gt;
* Buildsystem mit Konfigurations-GUI; Vorteil: einfacher Einstieg, Nachteil: Gesamtsystem manchmal etwas undurchsichtig&lt;br /&gt;
* nur kooperatives Multitasking&lt;br /&gt;
* zielt hauptsächlich auf AVR ab, ARM-Unterstützung noch nicht weit fortgeschritten&lt;br /&gt;
* im Vergleich zu lwIP spartanischer IP-Stack&lt;br /&gt;
&lt;br /&gt;
Funktionsumfang des Beispielprojekts:&lt;br /&gt;
* verschiedene Netzwerk-Beispielanwendungen (HTTP, FTP, DHCP)&lt;br /&gt;
* serieller Port&lt;br /&gt;
&lt;br /&gt;
Getestet wurde diese Anleitung mit der Ethernut-Version 4.2.1.&lt;br /&gt;
&lt;br /&gt;
Als Ausgangspunkt dient die Konfiguration at91sam7x-ek.conf. Für das Olimex-Board sind ein paar kleine Änderungen nötig.&lt;br /&gt;
&lt;br /&gt;
=== PHY-Konfiguration ändern ===&lt;br /&gt;
&lt;br /&gt;
Unter Architecture/ARM/AT91 EMAC Driver: &amp;lt;br /&amp;gt; [[Bild:olimex-sam7x-ethernut-phy-conf.png]]&lt;br /&gt;
&lt;br /&gt;
=== PHY-Initialisierung patchen ===&lt;br /&gt;
&lt;br /&gt;
In der Funktion EmacReset in der Datei at91_emac.c den Block mit dem Kommentar &amp;lt;code&amp;gt;/* For some unknown reason...&amp;lt;/code&amp;gt; durch folgenden Code ersetzen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
     /* PHY ID */&lt;br /&gt;
     #define MII_DM9161_ID_H 0x0181&lt;br /&gt;
     #define MII_DM9161_ID_L 0xb8a0&lt;br /&gt;
&lt;br /&gt;
     #define MII_AM79C875_ID_H 0x0022&lt;br /&gt;
     #define MII_AM79C875_ID_L 0x5540&lt;br /&gt;
&lt;br /&gt;
     #define MII_MICREL_ID_H 0x0022&lt;br /&gt;
     #define MII_MICREL_ID_L 0x1610 &lt;br /&gt;
&lt;br /&gt;
     /* For some unknown reason it seems to be required to read the ID registers first. */&lt;br /&gt;
     // Check for DM PHY (as used on the ATMEL EK)&lt;br /&gt;
     if (phy_inw(NIC_PHY_ID1) != MII_DM9161_ID_H ||&lt;br /&gt;
        (phy_inw(NIC_PHY_ID2) &amp;amp; 0xFFF0) != MII_DM9161_ID_L) {&lt;br /&gt;
     // Check for MICREL PHY (as used on the Olimex SAM7-EX256)   	&lt;br /&gt;
         if (phy_inw(NIC_PHY_ID1) != MII_MICREL_ID_H ||&lt;br /&gt;
            (phy_inw(NIC_PHY_ID2) &amp;amp; 0xFFF0) != MII_MICREL_ID_L) {&lt;br /&gt;
            outr(EMAC_NCR, inr(EMAC_NCR) &amp;amp; ~EMAC_MPE);&lt;br /&gt;
            return -1;&lt;br /&gt;
         }&lt;br /&gt;
     }&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Fehlende Definition ergänzen ===&lt;br /&gt;
Falls eine Fehlermeldung auftritt dass EMAC_PIO_SODR nicht definiert ist, folgenden Code in der Datei at91_emac.c vor &amp;lt;code&amp;gt;#ifdef PHY_PWRDN_BIT\n /* Disable PHY power down. */&amp;lt;/code&amp;gt; einfügen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#ifndef EMAC_PIO_SODR&lt;br /&gt;
#define EMAC_PIO_SODR PIOB_SODR&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Ausprobieren ===&lt;br /&gt;
&lt;br /&gt;
Wenn man das Beispielprogramm httpserv kompiliert (&amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; eingeben) und in den Controller geladen hat sollte man über das UART (115.2 kBaud) die erfolgreiche Initialisierung bestätigt bekommen:&lt;br /&gt;
 Nut/OS 4.2.1 HTTP Daemon...Configure eth0...OK&lt;br /&gt;
 192.168.0.21 ready&lt;br /&gt;
&lt;br /&gt;
Jetzt kann man die angezeigte IP-Adresse im Browser eingeben und sollte die Testseite zu sehen bekommen.&lt;br /&gt;
&lt;br /&gt;
== Forum ==&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/75721#new Diskussion zum Thema]&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
* http://www.sparkfun.com/tutorial/Nokia%206100%20LCD%20Display%20Driver.pdf&lt;br /&gt;
&lt;br /&gt;
[[Category:ARM-Boards]]&lt;/div&gt;</summary>
		<author><name>Chrisu</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_und_Linux&amp;diff=39822</id>
		<title>AVR und Linux</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_und_Linux&amp;diff=39822"/>
		<updated>2009-10-10T18:09:56Z</updated>

		<summary type="html">&lt;p&gt;Chrisu: Änderung 39821 von 69.120.79.115 (Diskussion) wurde rückgängig gemacht.da war SPAM!!!&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Was ist zu beachten, wenn man mit einer Linux-Distribution AVRs programmieren möchte? Hier ist eine offene Liste von verschiedenen Tipps dazu...&lt;br /&gt;
&lt;br /&gt;
==Toolchain beschaffen==&lt;br /&gt;
&lt;br /&gt;
Evtl. sind die benötigten Pakete schon in der Distribution enthalten. Es sollte unbedingt geprüft werden, ob sie aktuell sind, es hat sich einiges geändert.&lt;br /&gt;
&lt;br /&gt;
Alternativ: &lt;br /&gt;
* AVR Cross Development Kit - http://cdk4avr.sourceforge.net/&lt;br /&gt;
* Selbst kompilieren - &lt;br /&gt;
** http://www.nongnu.org/avr-libc/user-manual/install_tools.html&lt;br /&gt;
** http://www.roboternetz.de/wissen/index.php/Avr-gcc_und_avrdude_installieren&lt;br /&gt;
** http://www.linuxfocus.org/Deutsch/November2004/article352.shtml#352lf&lt;br /&gt;
** http://www.avrfreaks.net/index.php?name=PNphpBB2&amp;amp;file=viewtopic&amp;amp;t=42631&lt;br /&gt;
** http://www.mikrocontroller.net/topic/130972 (2009)&lt;br /&gt;
&lt;br /&gt;
==Editor==&lt;br /&gt;
&lt;br /&gt;
Der Editor sollte das Bearbeiten vom Programm einfach machen. Evtl. nützlich sind Features, um z.B. per Knopfdruck zu kompilieren und das Programm auf den AVR zu übertragen. Ansonsten: Editoren sind Geschmackssache, d.h. ausprobieren.&lt;br /&gt;
&lt;br /&gt;
: [http://www.gnome.org/projects/gedit/ gedit] [gnome]&lt;br /&gt;
: [http://kate-editor.org/ kate] [kde]&lt;br /&gt;
: [[AVR_Eclipse|Eclipse]] [http://www.eclipse.org/] [Java]&lt;br /&gt;
: [http://www.gnu.org/software/emacs/ Emacs] bzw. [http://www.xemacs.org/ XEmacs] [Textterminal oder X]&lt;br /&gt;
: [http://www.vim.org/ Vim bzw. GVim] [Textterminal oder X]&lt;br /&gt;
: [http://www.codeblocks.org/ Codeblocks] [gtk]&lt;br /&gt;
: [http://www.cadmaniac.org/projectMain.php?projectName=kontrollerlab Kontrollerlab] [KDE]&lt;br /&gt;
&lt;br /&gt;
Es lassen sich aber Programme auch in &#039;fremden&#039; Desktopumgebungen ausführen.&lt;br /&gt;
&lt;br /&gt;
==C-Compiler: avr-gcc==&lt;br /&gt;
&lt;br /&gt;
Macht aus dem C-Code den vom AVR ausführbaren binären Programmcode.&lt;br /&gt;
&lt;br /&gt;
Siehe auch:&lt;br /&gt;
* [[AVR-GCC]]&lt;br /&gt;
* [[AVR-GCC-Tutorial]]&lt;br /&gt;
&lt;br /&gt;
==Laufzeitbibliothek: avr-libc==&lt;br /&gt;
&lt;br /&gt;
Enthält Makros und Hardwaredefinitionen wie Registernamen für (die meisten) AVRs. Man muss sich deswegen um die echten Adressen in der Prozessor-Logik nicht mehr selbst kümmern, sondern kann direkt die Namen und Werte aus dem Datenblatt benutzen.&lt;br /&gt;
&lt;br /&gt;
http://www.nongnu.org/avr-libc/user-manual/index.html&lt;br /&gt;
&lt;br /&gt;
==Makefile==&lt;br /&gt;
&lt;br /&gt;
Enthält Informationen zum Kompilieren. Das Programm make startet damit den angegeben Compiler. Im einfachsten Fall muss man also nur &#039;&#039;&#039;make all&#039;&#039;&#039; im entsprechenden Projektverzeichnis aufrufen, der Rest läuft automatisch. Die Datei heisst einfach nur Makefile.&lt;br /&gt;
&lt;br /&gt;
Hier ein Skript, mit dem man die Einstellungen zusammenklicken kann (benötigt aber auch wieder anderes, z.B. TCL/TK, ..): http://www.sax.de/~joerg/mfile/ Dessen Aufruf erfolgt dann z.B. mit &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
$ wish mfile.tcl&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Über ein Menü kann man dann die Einstellungen zusammenklicken. Das Editieren des Makefiles für Spezialanpassungen lässt sich aktivieren.&lt;br /&gt;
&lt;br /&gt;
Wer sie von Windows kennt und sucht: Die Definition F_CPU der Taktfrequenz ist in der aktuellen Linux-Version nicht vorgesehen. Macht nichts, siehe dazu http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Taktfrequenz&lt;br /&gt;
&lt;br /&gt;
==Programmierprogramm==&lt;br /&gt;
&lt;br /&gt;
Schreibt mit entsprechender Hardware auf den Controller bzw. liest ihn aus.&lt;br /&gt;
&lt;br /&gt;
Mit mfile lässt sich auch im Makefile gleich das Programmierprogramm zur Übertragung auf den Controller festlegen ([[AVRDUDE]], [[uisp]]): http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Programmierger.C3.A4t_einstellen&lt;br /&gt;
&lt;br /&gt;
Eine Grafische Benutzerschnittstelle (GUI) für AVRDUDE steht mit [http://avr8-burn-o-mat.aaabbb.de/ avr8-burn-o-mat] zur Verfügung.&lt;br /&gt;
&lt;br /&gt;
===Fuses, Lockbits===&lt;br /&gt;
&lt;br /&gt;
Wer bislang Atmels AVR Studio unter Windows zum Programmieren der [[AVR_Fuses]] benutzt hat, kann das z.B. mit [[AVRDUDE]] machen, allerdings über die Shell.&lt;br /&gt;
Wer die Dokumentation sucht, findet sie mit Sicherheit im [http://download.savannah.gnu.org/releases/avrdude/ gepackten Programmpaket]. Ein aktuelles PDF&lt;br /&gt;
&lt;br /&gt;
Z.B. bekommt man als Resultat folgenden Aufrufes den Hexwert der lfuse eines Tiny13 über einen [http://www.mikrocontroller.net/articles/AVR_In_System_Programmer AVR-ISP] mit aktueller Firmware, der an einem USB-Seriell-Wandler angeschlossen ist.&lt;br /&gt;
&lt;br /&gt;
Durch die Option -v ([http://en.wiktionary.org/wiki/verbose verbose]) wird aber noch viel mehr [http://www.mikrocontroller.net/forum/read-1-399733.html?#399834 angezeigt]. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avrdude -p t13 -c avrispv2 -P /dev/ttyUSB0 -v -U lfuse:r:-:i&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das - anstelle von FILENAME leitet die Ausgabe auf &amp;lt;stdout&amp;gt; (Bildschirm) um.&lt;br /&gt;
&lt;br /&gt;
Frontend?&lt;br /&gt;
Shellbefehl, um die Werte binär anzuzeigen?&lt;br /&gt;
&lt;br /&gt;
Eine Anleitung zum Umgang:&lt;br /&gt;
http://www.mikrocontroller.net/forum/read-1-152502.html&lt;br /&gt;
&lt;br /&gt;
Eine 0 steht für eine gesetzte Fuse.&lt;br /&gt;
&lt;br /&gt;
Die Bedeutung der Bits findet sich im Datenblatt unter &amp;quot;Memory Programming -&amp;gt; Fuse Bytes&amp;quot; (tiny13).&lt;br /&gt;
&lt;br /&gt;
===Program/Burn Flash===&lt;br /&gt;
&lt;br /&gt;
Der Mikrocontroller wird wie beim Kompilieren mithilfe von make und der eingestellten Programmiersoftware mit dem Befehl &#039;&#039;&#039;make program&#039;&#039;&#039; geflasht&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Anwendung&lt;br /&gt;
&lt;br /&gt;
==Konfiguration, Probleme, Erfahrungen==&lt;br /&gt;
&lt;br /&gt;
===Debian===&lt;br /&gt;
&lt;br /&gt;
* Toolchain-Build: http://blog.coldtobi.de/index.php?op=ViewArticle&amp;amp;articleId=21&amp;amp;blogId=1&lt;br /&gt;
&lt;br /&gt;
==== Etch (Netinst) ====&lt;br /&gt;
* Installation: gcc-avr, libc-avr, avrdude aus Standardquellen&lt;br /&gt;
* Emacs21 als Editor&lt;br /&gt;
* Makefile&lt;br /&gt;
... läuft problemlos.&lt;br /&gt;
&lt;br /&gt;
===Gentoo===&lt;br /&gt;
Gentoo bietet mit dem Shellscript &amp;quot;crossdev&amp;quot; eine einfache automatisierte Möglichkeit die Toolchain zu erstellen. Genauere Versionen von binutils/gcc/libc können via parameter übergeben werden.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
emerge crossdev&lt;br /&gt;
crossdev --target avr&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Falls &#039;crossdev --target avr&#039; nicht fehlerfrei durchlaufen sollte mit &#039;crossdev -t avr --without-headers&#039; versuchen (2009-01-28).&lt;br /&gt;
&lt;br /&gt;
===Mandrake===&lt;br /&gt;
&lt;br /&gt;
* Toolchain-Build: http://www.avrfreaks.net/index.php?name=PNphpBB2&amp;amp;file=viewtopic&amp;amp;t=42631&lt;br /&gt;
* 2007: benötigt &amp;quot;texinfo&amp;quot; Package &lt;br /&gt;
&lt;br /&gt;
===openSUSE===&lt;br /&gt;
&lt;br /&gt;
* Seit Version 10.0 sind die Pakete avr-libc, cross-avr-gcc, cross-avr-binutils und avrdude in der Download-Version von openSUSE enthalten und können einfach über YaST bzw. zypper installiert werden.&lt;br /&gt;
&lt;br /&gt;
===Ubuntu 6.06===&lt;br /&gt;
&lt;br /&gt;
* Pakete veraltet; ist bereits als bug gemeldet&lt;br /&gt;
* Toolchain selbst kompilieren:&lt;br /&gt;
** default system path steht in /etc/environment&lt;br /&gt;
** Toolchain-Build: http://www.avrfreaks.net/index.php?name=PNphpBB2&amp;amp;file=viewtopic&amp;amp;t=42631&lt;br /&gt;
&lt;br /&gt;
===Ubuntu 7.04===&lt;br /&gt;
&lt;br /&gt;
* Toolchain-Build: http://www.avrfreaks.net/index.php?name=PNphpBB2&amp;amp;file=viewtopic&amp;amp;t=42631&lt;br /&gt;
&lt;br /&gt;
===Ubuntu 8.04===&lt;br /&gt;
* einfach eine universe-Paketquelle von Ubuntu 8.10 (Intrepid Ibex) hinzufügen. Dort gibt es dann aktuelle AVR-Pakete (gcc 4.3, libc 1.6.2 usw.). Anleitung hier: http://packages.ubuntu.com/de/intrepid/i386/gcc-avr/download&lt;br /&gt;
&lt;br /&gt;
===AVR-SLax===&lt;br /&gt;
* Einfach zu benutzende AVR-Live-CD &lt;br /&gt;
* Keine installation notwendig&lt;br /&gt;
* ISO brennen und von CD booten&lt;br /&gt;
Zu finden unter: http://www.lost-byte.de/avrslax.php&lt;br /&gt;
&lt;br /&gt;
[[Category:AVR]]&lt;/div&gt;</summary>
		<author><name>Chrisu</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Diskussion:Spule&amp;diff=38438</id>
		<title>Diskussion:Spule</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Diskussion:Spule&amp;diff=38438"/>
		<updated>2009-08-21T21:26:04Z</updated>

		<summary type="html">&lt;p&gt;Chrisu: Die Seite wurde neu angelegt: Ein Anwendungsbeispiel wäre noch interessant. Vorallendingen wenn man am Anfang liest das man viele Sachen mit Coolness Faktor machen kann. mfg Christian&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ein Anwendungsbeispiel wäre noch interessant. Vorallendingen wenn man am Anfang liest das man viele Sachen mit Coolness Faktor machen kann.&lt;br /&gt;
mfg Christian&lt;/div&gt;</summary>
		<author><name>Chrisu</name></author>
	</entry>
</feed>