<?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=Sebion7125</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=Sebion7125"/>
	<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/articles/Spezial:Beitr%C3%A4ge/Sebion7125"/>
	<updated>2026-04-10T10:37:40Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.39.7</generator>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=Reichelt-Wishlist&amp;diff=66794</id>
		<title>Reichelt-Wishlist</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=Reichelt-Wishlist&amp;diff=66794"/>
		<updated>2012-06-11T21:29:37Z</updated>

		<summary type="html">&lt;p&gt;Sebion7125: /* Controller, FPGA und CPLD */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Reichelt Wunschliste ==&lt;br /&gt;
&lt;br /&gt;
Auf dieser Seite können Wünsche zur Erweiterung des Reichelt-Lieferprogramms eingetragen werden. Es ist keine offizielle Wunschliste von Reichelt und es ist nicht bekannt, ob Reichelt-Mitarbeiter diese Seite regelmäßig sichten. Reichelt sollte sicherheitshalber regelmäßig angeschrieben werden, damit diese Liste nicht in Vergessenheit gerät.&lt;br /&gt;
&lt;br /&gt;
Damit sich die beliebtesten Artikel herauskristallisieren, macht jeder einfach &#039;&#039;&#039;einen&#039;&#039;&#039; virtuellen Strich dahinter: | (Windows: ALT-GR Taste und &amp;lt; Taste drücken, Mac OS X: Alt-Taste und 7 Taste drücken). Alle fünf Striche (|||||) bitte immer ein Leerzeichen einfügen. Blöcke von 50 Strichen werden regelmäßig gegen eingefärbte Kolonnen von Ausrufezeichen ausgetauscht, die den Reichelt-Mitarbeitern hoffentlich umso mehr auffallen ;)&lt;br /&gt;
&lt;br /&gt;
Neue Artikel einfügen darf und soll natürlich auch jeder - aber bitte die Liste vorher durchgehen (Tipp: Browser-Suchfunktion nutzen)! Einfach ganz viele Striche auf einmal hinter einem Artikel einzufügen ist zwecklos. Das erkennt man in der History und es gibt viele Leute, die diese Seite überwachen...&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Nicht sinnvoll&#039;&#039;&#039; ist etwas sehr exotisches, wie z.&amp;amp;nbsp;B. einen ganz bestimmten super schnellen AD-Wandler hier aufzulisten! Neue Artikel müssen sich für Reichelt ja auch rentieren und wirtschaftlich &amp;quot;an den Mann bringbar&amp;quot; sein. [Die Entscheidung, ob sich was rentiert und ob es exotisch ist, sollte man vielleicht Reichelt und den eventuellen späteren Strichle-Setzern überlassen, statt im Voraus die Schere im Kopf walten zu lassen.]&lt;br /&gt;
&lt;br /&gt;
= Wunschliste =&lt;br /&gt;
== Halbleiter ==&lt;br /&gt;
=== Controller, FPGA und CPLD ===&lt;br /&gt;
&lt;br /&gt;
* Ajile aj-100 (Java Real-Time Prozessor) ||||&lt;br /&gt;
* ALTERA CPLD EPM30xx - Familie |||&lt;br /&gt;
* ALTERA CPLD EPM70xx - Familie ||||| ||||| ||||| ||||| |||&lt;br /&gt;
* ALTERA Cyclone2 - Familie ||||| ||||| ||||| ||||| ||||&lt;br /&gt;
* ALTERA Cyclone3 - Familie ||||| ||&lt;br /&gt;
* ALTERA Flex10K - Familie ||||&lt;br /&gt;
* ALTERA MAX-II (CPLDs) ||||| ||||| ||||| ||||&lt;br /&gt;
* ALTERA MAX-V CPLDs |&lt;br /&gt;
* ARM: Cortex M3 Nachfolger für die LPC2x&lt;br /&gt;
* Atmel AT89LP4052 PDIP ||||| ||||| ||||&lt;br /&gt;
* Atmel AT89S2051/4051 |||||&lt;br /&gt;
* Atmel AT90PWM3B (µC für Servosteuerungen und z.b. Motorsteuerungen) ||||| ||||| ||||| ||||| ||||| |&lt;br /&gt;
* Atmel ATA6612/13 (LIN-Bus SoC) ||&lt;br /&gt;
* Atmel ATmega 1284P PDIP |||&lt;br /&gt;
* Atmel ATmega 168PA, 88PA, etc. ||||| ||||&lt;br /&gt;
* Atmel ATmega 16A und 32A in TQFP und PDIP ||||| ||||| ||||| ||||| ||||| ||||| ||||| |||||&lt;br /&gt;
* Atmel ATmega 16L und 32L in TQFP (wäre ATmega 16/32L8 TQ) ||||| ||&lt;br /&gt;
* Atmel ATmega16M1 in TQFP ||&lt;br /&gt;
* Atmel ATmega324P in TQFP und PDIP ||||| ||||| ||||| |&lt;br /&gt;
* Atmel ATmega324PV in TQFP und PDIP ||&lt;br /&gt;
* Atmel ATmega328P in TQFP und PDIP {{Reichelt50|FF0000}} ||||| ||||&lt;br /&gt;
* Atmel ATmega48P in TQFP und PDIP ||||&lt;br /&gt;
* Atmel ATmega644p(a) / ATmega1284p(a) in TQFP und PDIP ||||| ||||| ||||| ||||| ||||| ||||| ||||| |||||&lt;br /&gt;
* Atmel ATtiny2313V in SO und PDIP |||||&lt;br /&gt;
* Atmel ATtiny4313 ||&lt;br /&gt;
* Atmel ATtiny261 (auch 461 und 861; bevorzugt DIP) ||||| ||||| ||||| ||&lt;br /&gt;
* Atmel AVR Controller mit Funkanbindung z.&amp;amp;nbsp;B. AT86RF230, AT86RF211, AT86RF401, dazu passende Quarze (evtl. SMD) 18,080 MHz (Crystek P/N 016758), Spulen 39nH. {{Reichelt50|FF0000}}{{Reichelt50|00FF00}}||||| ||||| ||||| ||||| ||||| ||&lt;br /&gt;
* Atmel AVR mit USB: AT90USB82 und ATmega32u4 {{Reichelt50|FF0000}} ||&lt;br /&gt;
* Atmel AVR32 im TQFP ||||| ||||| ||||| ||||| ||||&lt;br /&gt;
* Atmel Cortex M3 SAM3S im QFN/LQFP Gehäuse |&lt;br /&gt;
* Atmel Dream Sound Synthesizer Chips, z.&amp;amp;nbsp;B. ATSAM3103 und ATSAM3308 ||||| ||||&lt;br /&gt;
* Axis Etrax 100LX Risc Processor (kostenloses Linux-System vorhanden) ||||| ||||&lt;br /&gt;
* Bessere Auswahl: statt MSP430F147, F148, F149 wenigstens einen mit DAC -&amp;gt; MSP430F16x&lt;br /&gt;
* CY7C68013A-56PVXC (Cypress EZ-USB FX2LP) ||||| ||&lt;br /&gt;
* Cypress PSoC Mikrocontroller ||||| ||||| ||||| ||&lt;br /&gt;
* Freescale DSP56F801 ||||&lt;br /&gt;
* Freescale HCS12 Controller ||||| ||||| ||||| ||||| ||||&lt;br /&gt;
* Freescale MC9S08QD4 ||&lt;br /&gt;
* Freescale MC9S08QEx |&lt;br /&gt;
* Freescale MC9S08QG8 (DIP 16) ||||| ||||| ||||| ||&lt;br /&gt;
* Freescale Prozessoren (Coldfire) (16 + 32 Bit) ||||| ||&lt;br /&gt;
* Infineon XC866 ||||| ||||| ||||| ||||| |||&lt;br /&gt;
* Lattice GAL 26V12 |&lt;br /&gt;
* Lattice ispMACH 4032C / 4064C / 4128C |||||&lt;br /&gt;
* Luminarymicro Stellaris Serie (Cortex-M3) ||||| ||&lt;br /&gt;
* Maxim/Dallas DS89C450 |&lt;br /&gt;
* Mehr FPGAs (v.a aktuellere) von Xilinx, z.&amp;amp;nbsp;B. Spartan III , ALTERA CYCLONE II (v.a. auch größere Typen, die noch im TQFP-Gehäuse zu haben sind wie z.&amp;amp;nbsp;B. XC3S400 oder XC3S500E (PQFP208)) {{Reichelt50|FF0000}}{{Reichelt50|00FF00}}{{Reichelt50|0000FF}}{{Reichelt50|00FFFF}}||||| ||||| | ||||| ||||| |||||&lt;br /&gt;
* Microchip dsPIC33FJ128GP802 ||||&lt;br /&gt;
* Microchip PIC12F1822 |&lt;br /&gt;
* NXP LPC1114 |&lt;br /&gt;
* NXP LPC1313 |&lt;br /&gt;
* NXP LPC1343 |&lt;br /&gt;
* NXP LPC1751 ||&lt;br /&gt;
* NXP LPC1754 ||&lt;br /&gt;
* NXP LPC214x-Serie ARM7-Controller ||||| ||||| |||||&lt;br /&gt;
* NXP LPC23xx/24xx ||||| ||&lt;br /&gt;
* NXP SAA5281 Videotextinterface ||||| ||||&lt;br /&gt;
* Parallax Propeller CPU, 8 Cogs - DIP 40 ||||| ||||| ||||| ||||| ||||| ||||| ||||| |&lt;br /&gt;
* PICAXE von Revolution Education Ltd ||&lt;br /&gt;
* Renesas M16C ||||| ||||&lt;br /&gt;
* Silabs C8051F320 USB Mikrocontroller ||&lt;br /&gt;
* Silabs C8051F340 USB Mikrocontroller ||&lt;br /&gt;
* Silabs Si4735 im SSOP-Gehäuse (AM/FM-Empfänger) |||&lt;br /&gt;
* SSV DIL/NetPCs [http://www.dilnetpc.com]http://www.dilnetpc.com ||||| ||||| ||||&lt;br /&gt;
* ST ST7MC... (µC für Servosteuerungen, und vor allem Brushless-Motoren) |||||  |||||&lt;br /&gt;
* ST STM32 Serie (Cortex-M3) {{Reichelt50|FF0000}}||||| ||||| |||&lt;br /&gt;
* ST STR7 Serie (ARM7TDMI) ||&lt;br /&gt;
* TI MSP430F167, TI MSP430F168 ||||&lt;br /&gt;
* TI MSP430F2001/2/3 etc. im RSA-Gehäuse (=QFN) ||||| ||&lt;br /&gt;
* TI MSP430F2618 |||&lt;br /&gt;
* TI MSP430FG4618 |&lt;br /&gt;
* TI TMS470 Arm7 ||||| ||||| ||||| ||||| |&lt;br /&gt;
* TI TUSB3210 ||||| ||&lt;br /&gt;
* Ubicom SX20 SX28 IP2022 ||&lt;br /&gt;
* Western Design Center 65c816 |||&lt;br /&gt;
* XC3S 400 TQ144 |||&lt;br /&gt;
* Zilog Z8 Encore-Microcontroller (bis 64k Flash, I²C, SPI, 2xUART, ADC, on-Chip Debugger ...) [http://www.zilog.com/products/family.asp?fam=225]www.zilog.com ||||| |&lt;br /&gt;
* Zilog ZNEO-Microcontroller (Z16Fxxx, bis 128k Flash, 4k RAM, bis zu 76 I/Os, 3 Timer, 10-bit A/D, externer Daten-/Adressbus, on-Chip Debugger) [http://www.zilog.com/products/family.asp?fam=236] www.zilog.com |&lt;br /&gt;
&lt;br /&gt;
=== Speicher ===&lt;br /&gt;
&lt;br /&gt;
* 24LC256 oder 24AA256 oder 24LC512 oder 24AA512 ||||| |||||&lt;br /&gt;
* 24AA02E48 (EEPROM mit einprogrammierter MAC-Adresse) |&lt;br /&gt;
* 3.3V async SRAM ab 16KByte ||||| |||&lt;br /&gt;
* 3.3V DRAM ||||| |&lt;br /&gt;
* Atmel DataFlash, z.&amp;amp;nbsp;B. AT45DB081B (8 MBit Flash-Speicher an seriellen Bus im 8poligen Gehäuse) {{Reichelt50|FF0000}}{{Reichelt50|00FF00}}||||| |&lt;br /&gt;
* EEPROM mit SPI Schnittstelle 25XX Serien ||||| ||||&lt;br /&gt;
* F-RAM mit SPI von RAMTRON ||||| ||||&lt;br /&gt;
* FM25L16 o. FM25L256 SPI-FRAM |&lt;br /&gt;
* FPGA Konfigurations-EEPROMS AT17LV256, AT17C65/128/256.../XCF04S/... ||||| ||||| ||||| ||||&lt;br /&gt;
* NexFlash spiFlash NX25P16 (16MBit serial Flash im SO8-Gehäuse) ||||| ||||| ||||| |||&lt;br /&gt;
* RAMs (SRAM oder DRAM) mit ordentlicher Kapazität (z.&amp;amp;nbsp;B. HY57V641620HG oder besser) ||||| ||||| ||||| ||||&lt;br /&gt;
* Schnelles statisches RAM 128kB (10, 12, 15 oder 20ns, z.&amp;amp;nbsp;B. Samsung K6R1008C1D-UI10 oder CY7C1019D-10ZSXI) (5V/3,3V) {{Reichelt50|FF0000}}||||| ||||| ||||&lt;br /&gt;
* Serielle SRAMs (Microchip 23K256) ||&lt;br /&gt;
&lt;br /&gt;
=== Einzeltransistoren, Op-Amps, MOSFET-Treiber ===&lt;br /&gt;
&lt;br /&gt;
* OPA134, OPA2134, OPA4134 low noise audio OpAmps |&lt;br /&gt;
* 2SC1971 Transistor mit hoher Frequenz und viel Leistung für Endstufen ||&lt;br /&gt;
* AD623 Single Supply,Rail-Rail, InstrOpamp ||||| |&lt;br /&gt;
* AD628 InstrOpAmp, high voltage inputs |&lt;br /&gt;
* AD8601 Rail to Rail Opamp |&lt;br /&gt;
* BSH205 P-Channel 1.5V(GS), 0.75A, 12V D-S |||&lt;br /&gt;
* BUF420AW Schaltnetzteil Transistor von STM |||||&lt;br /&gt;
* Digitaltransistoren (BCR*), auch als Pärchen NPN/PNP (BCR10, BCR08pn) ||||| ||||&lt;br /&gt;
* IPS5451S intelligenter Leistungsschalter 50 V, 35 A, 25 mΩ |&lt;br /&gt;
* IPW60R045CS Infineon MOSFET 600V 45mOhm Rdson 30ns tr+tf (niedrigster Rdson in der Klasse) |&lt;br /&gt;
* IR2011 MOSFET Treiber |||&lt;br /&gt;
* IR21844 DIL (High-Speed IGBT-Driver) |||&lt;br /&gt;
* IR3313 o.ä. Intelligenter Leistungsschalter 32V/90A, einstellbare Strombegrenzung |||&lt;br /&gt;
* IRC540 (HEXFET) | (kann ggf. durch bereits vorhandenen IRCZ 44 ersetzt werden)&lt;br /&gt;
* IRF7503/IRF7506 Dual MOSFET SMD ||||| |||||&lt;br /&gt;
* IRFI4212H-117P Doppel-MOSFET (f. Klasse D-Verstärker) |&lt;br /&gt;
* J-FET BF545 A,B,C (entspricht BF245 in SMD ) |&lt;br /&gt;
* Leistungs-OP LM675 von National ||&lt;br /&gt;
* LM397, LM321 o.ä. single op-amp in SOT23-5 5-30V supply {{Reichelt50|FF0000}}||||| ||||| ||||| ||||| ||||| ||||&lt;br /&gt;
* MAX4420 MOSFET Driver ||&lt;br /&gt;
* MAX4429 MOSFET Driver ||&lt;br /&gt;
* MC 34152 D-SMD SO8 Dual MOSFET Driver |&lt;br /&gt;
* Mehr FET-Treiber (TI UCC3372x, HIPxxx , die neueren Brückentreiber von Maxim ||||| |||&lt;br /&gt;
* mehr FETs und IGBTs (nicht nur IRF, sehr gut IXYS &amp;lt;- und sauteuer!) ||||| ||||&lt;br /&gt;
* MJD31C NPN Transistor SMD DPAK 3&lt;br /&gt;
* Niederohm-FETs in SO8, N und P ||||| ||||| ||&lt;br /&gt;
* Philips PDTD113E/123E und PDTB113E/123E (PNP und NPN im sot23 mit internen Widerständen für Basis und PullUp/Down ||&lt;br /&gt;
* Schnellere und gleichzeitig günstige OpAmps; Beispiel AD8055 ||&lt;br /&gt;
* Si4562DY N- and P-Channel 2.5-V (G-S) MOSFET SMD ||||| ||||| ||&lt;br /&gt;
* SPP20N60C3 Infineon MOSFET 600V 190mOhm Rdson &amp;lt;10ns tr+tf (Schnellste Schaltzeit in der Klasse) ||||| |&lt;br /&gt;
* TLC2264 (Quad Rail-to-Rail Operational Amplifier) ||&lt;br /&gt;
* TLV2782 (1,8V Rail-to-Rail OP) &#039;&#039;&#039;unklar: War &amp;quot;TLV27(2&amp;quot;&#039;&#039;&#039; |||||&lt;br /&gt;
* TLC3702 Komparator |&lt;br /&gt;
* TLV2382ID Rail-Rail-OP von TI |&lt;br /&gt;
* Sehr schnelle Op-Amps wie LMH6733 o.a in single und trible |&lt;br /&gt;
&lt;br /&gt;
=== Schaltregler (Buck, Boost, DC/DC,...) ===&lt;br /&gt;
&lt;br /&gt;
* 5,2V Lowdrop Längsregler LF52 im TO252AA von STM |||||&lt;br /&gt;
* generell Spannungsregler, LOW-DROP, SMD (DPAK, D2PAK) &lt;br /&gt;
* Größere Auswahl an Step-up Reglern ||||| ||||| ||||| ||||| ||||| |||||&lt;br /&gt;
* L4941 Spannungsregler 5V/1A in SMD-Ausführung (DPAK) ||||| |||||&lt;br /&gt;
* L5970 o. L5972 1 bzw. 2A, 250kHz Schaltregler im SO8 |&lt;br /&gt;
* L5973D 2,5A, 250kHz, Schaltregler im SO8 (ca. 1€) |||||&lt;br /&gt;
* LF50ABDT Spannungsregler SMD DPAK 5.0V very low drop |&lt;br /&gt;
* LM1084-ADJ (low dropout voltage positive regulator) |&lt;br /&gt;
* LM1117 (low dropout voltage regulator) - 1,8V ||&lt;br /&gt;
* LM1117MPX-1.8 und LM1117MPX-3.3 (SMD-Spannungsregler SOT-223) ||||| ||||| |||||&lt;br /&gt;
* LM2734 Schaltregler |||&lt;br /&gt;
* LM317EMP oder LM317AEMP SMD-Spannungsregler einstellbar (SMD TO-223 Gehäuse) ||||| ||||| ||||&lt;br /&gt;
* Maxim MAX629, MAX1795, MAX1703 (Aufwärtsregler / Step-Up-Konverter) ||||| ||||| |||||&lt;br /&gt;
* MAX 8865 Dual, Low-Dropout, 100mA Linear Regulator |&lt;br /&gt;
* MC78LCxx Serie - Ultra Low Drop Spannungsregler 3-5 Volt mit 1 Mikro-Ampere Ruhestrom ||||| ||&lt;br /&gt;
* MIC29300/29301 Spannungsregler 5,0V 3A im TO263(SMD) Gehäuse ||&lt;br /&gt;
* NCP3063: 1.5 A, BUCK _&amp;amp;_ BOOST Inverting Switching Regulator DIP8/SOIC8 (MC34063 upgrade) (0,32$) |&lt;br /&gt;
* R-523.3PA Schaltregler 4V - 18V Eingang, variabler Ausgang (Nominalspannung 3.3 V) mit nur 2-4 externen Bauteilen bei &amp;gt; 90% Effizienz &lt;br /&gt;
* R-723.3P Schaltregler 4V - 28V Eingang, variabler Ausgang (Nominalspannung 3.3 V) mit nur 2-4 externen Bauteilen bei &amp;gt; 90% Effizienz |&lt;br /&gt;
* R-783.3-0.5 Schaltregler 4,75V - ca. 18V Eingang; 3,3V Ausgang (Hersteller Recom) ||||| ||||&lt;br /&gt;
* R-785.0-0.5 Schaltregler 6,5V - 30V Eingang; 5,0V Ausgang (Hersteller Recom) ||||| |||&lt;br /&gt;
* R-785.0-1.0 Schaltregler, Ausgang 5,0V, 1A ||||&lt;br /&gt;
* Spannungsregler SMD in DPAK ||||| ||||| ||||| ||||| ||||&lt;br /&gt;
* ST1S10 günstiger &amp;quot;Monolithic synchronous step-down regulator&amp;quot; bis zu 3A Ausgang | &lt;br /&gt;
* TI TPS61070 3.3V-75mA-aus-einer-NiMH-Zelle (+ passende SMD-Induktivität) |&lt;br /&gt;
* ViPER Schaltregler von ST ||&lt;br /&gt;
* ViPER 12A |&lt;br /&gt;
* LM3578 sehr universeller, weil in allen Konfigurationen einsetzbarer Schaltregler (DIP8) von NS mit 1.25V Vref |&lt;br /&gt;
&lt;br /&gt;
=== Konstantstromquellen (LED, Akkus) ===&lt;br /&gt;
&lt;br /&gt;
* CCS-Akkulade-IC (z.&amp;amp;nbsp;B. CCS9620SL) (siehe [[http://bticcs.com/]]) |||||&lt;br /&gt;
* HV9910 Schaltregler für die Hochleistungs-LEDs Ub=8-450V; I beliebig; Eff. besser 90% ||||| ||||| ||||| ||||| ||||| ||||| |||&lt;br /&gt;
* LM340x High Power LED-Treiber von National ||||&lt;br /&gt;
* LTC3490 (350mA-Konstantstromquelle) ||||| |||||&lt;br /&gt;
* Max1555 - LiPo Lade IC |||||&lt;br /&gt;
* MAX7313 16 LED-PWM-Dimmer (Im Gegensatz zu den Philips-ICs ist jede einzelne LED-Dimmbar, dafür nur in 16 Schritten) ||||| ||||| |&lt;br /&gt;
* PCA9685 16Kanal 12Bit PWM LED Controller ||||| |||&lt;br /&gt;
* STP08CL596B1 DIP16 STM, LOW VOLTAGE 8-BIT CONSTANT CURRENT LED SINK DRIVER ||&lt;br /&gt;
* STP08CL596M SO16 STM, LOW VOLTAGE 8-BIT CONSTANT CURRENT LED SINK DRIVER ||||&lt;br /&gt;
* STP16CL596B1R DIP24 STM, LOW VOLTAGE 16-BIT CONSTANT CURRENT LED SINK DRIVER ||&lt;br /&gt;
* STP16CL596M SO24 STM, LOW VOLTAGE 8-BIT CONSTANT CURRENT LED SINK DRIVER |||&lt;br /&gt;
* TLC5940 16 Kanal PWM LED-Treiber ||||| |||&lt;br /&gt;
* UDN 2987 LW (Source Driver UDN2987 in SMD-Bauform) ||&lt;br /&gt;
&lt;br /&gt;
=== Ethernet, I²C (2Wire), SPI und andere Interfaces ===&lt;br /&gt;
&lt;br /&gt;
* CLC020 und CLC021 (National Semiconductor) Parallel Component nach SDI-Converter |||||&lt;br /&gt;
* CP2120 single-chip SPI to I2C bridge and GPIO port expander |&lt;br /&gt;
* CS8900A Ethernet-Controller ||||| |||&lt;br /&gt;
* CY7C67300 (Cypress) dual role USB controller mit OTG ||||| ||||| ||||| ||||| |||&lt;br /&gt;
* DP83848C (Ethernet Physical Layer Transceiver/PHY, MII/RMII-Schnittstelle, passend zu AT91SAM7X) |||&lt;br /&gt;
* Ethernet Magnetics (Auch POE) ||||| |||||&lt;br /&gt;
* Fast Ethernet-Controller (DE9000A/B/E, AX88796B, ...) |&lt;br /&gt;
* FTDI High Speed Chips, z.&amp;amp;nbsp;B. FT2232H (USB - UART/FIFO IC)||||| |&lt;br /&gt;
* Generell mehr 1-Wire-ICs ||||| ||||| ||||| ||||| ||||| ||||| ||||| |||&lt;br /&gt;
* Generell mehr I²C-ICs {{Reichelt50|FF0000}}||||| ||||| ||&lt;br /&gt;
* Generell mehr SPI IC ||||| ||||| ||||| ||||| ||||&lt;br /&gt;
* IP101 PHY von IC+ (Distri für DE [http://www.topas.de/tt/cfs/icp_cfs_mai05.htm Topas]) ||&lt;br /&gt;
* ISD 5116 (Sprachaufnahme bis 16min &amp;amp; I2C-Interface) ||||| ||||| ||||| |&lt;br /&gt;
* LTC1694-1 (I2C/SMBus Accelerator) ||||| |&lt;br /&gt;
* MAX6650 I²C-Lüftermonitor ||&lt;br /&gt;
* MAX6958 / MAX6959 (I²C 4-Digit, 9-Segment LED Display Drivers with Keyscan) ||||| ||||| ||&lt;br /&gt;
* MAX7311AWG 2Wire Interface von Maxim ||||&lt;br /&gt;
* MCP23008 8Bit I2C I/O Expander |||&lt;br /&gt;
* MCP23016 16Bit I²C I/O Expander ||||| ||||| ||| (verfügbar)&lt;br /&gt;
* MCP23S08 8BIT SPI I/O Expander |&lt;br /&gt;
* MCP23S17 16Bit SPI I/O Expander (aber ohne Schmidt-triggerd Eingänge wie der 23x16) ||&lt;br /&gt;
* P82B86 (I2C Dual Bi-Directional Bus Buffer) ||&lt;br /&gt;
* Philips PCA82C252 oder TJA1054A oder vergleichbar (&amp;quot;Fault-Tolerant&amp;quot; CAN Transceiver, 11898-3) ||||| |||||&lt;br /&gt;
* Power over Ethernet Bausteine z.&amp;amp;nbsp;B. LM5070 |||&lt;br /&gt;
* RS485 isoliert: z.&amp;amp;nbsp;B. Burr-Brown ISO485 o.ä. ||||| |||&lt;br /&gt;
* sn65hvd230/231/232 (CAN-Transceiver) in SO8 |||&lt;br /&gt;
* TH3122 K-Line Interface von Melexis ||||| ||||&lt;br /&gt;
* TH8080 LIN Transceiver von Melexis (oder vergleichbare) ||&lt;br /&gt;
* TI ISO1050 (Isolierter CAN-Transceiver) |||&lt;br /&gt;
* SC18IM700 o.ä. I2C to UART-Converter ||&lt;br /&gt;
&lt;br /&gt;
=== ADC, DAC und PWM ===&lt;br /&gt;
&lt;br /&gt;
* 16-bit A/D-Wandler (waren von Maxim schon im Programm, sind aber wieder herausgeflogen?) ||||| ||&lt;br /&gt;
* AD7524 8-Bit DAC in SMD ||||| ||||| ||||&lt;br /&gt;
* ADS8320 ADC 16 Bit seriell ||||| ||||| ||||| ||||| ||||| ||||| |&lt;br /&gt;
* CS5641 von Cirrus...The CS5461 incl. two delta-sigma A/D converters.... ||&lt;br /&gt;
* D/A Wandler mit 4 oder mehr Ausgängen, z.&amp;amp;nbsp;B. TLC5620/TLV5629/AD5325 ||||| ||||| |||&lt;br /&gt;
* DAC7612 DAC 12 Bit seriell ||||| ||||| ||||| ||||| |||&lt;br /&gt;
* DAC8830 IDT (16Bit-DAC,ser. Input) ||||| |&lt;br /&gt;
* Generell mehr DAC&#039;s (auch die teureren) von TI ||||| |&lt;br /&gt;
* Generell mehr I2C IC (ADC, DAC, DSP, u.a. Crystal, BurrBrown etc.) |||||&lt;br /&gt;
* Generell mehr PWM-SIC&#039;s |||||&lt;br /&gt;
* LTC 1655(L) N8 16 Bit DAC interne Ref 2.048/1.25V(L Type) SPI Interface ||&lt;br /&gt;
* LTC24xx (24-Bit Delta-Sigma ADC) ||||&lt;br /&gt;
* MAX127/128 8-Kanal 12bit ADC mit I2C-Interface |||&lt;br /&gt;
* MAX528 8-fach 8Bit DAC mit Output Buffer seriell |&lt;br /&gt;
* MCP4725A0 und MCP4725A1 D/A-Wandler 12 Bit I²C ||&lt;br /&gt;
* Philips TDA1543 - 2x16-Bit DAC |&lt;br /&gt;
* TI PCM1804 Audio-ADC||||&lt;br /&gt;
* TI PCM2707 USB-Audio-DAC ||&lt;br /&gt;
* Video-AD-Wandler z.&amp;amp;nbsp;B. LTC2208 (16 Bit 130 MS/s) für FPGA und SDR |&lt;br /&gt;
* IR Class-D Amplifier IRS2092 ||&lt;br /&gt;
&lt;br /&gt;
=== Sensoren und Aktoren ===&lt;br /&gt;
&lt;br /&gt;
* 4Hz Supersense µblox LEA-4S GPS module (Importer pointis.de) + Passende Passives Patch antenna (zB. von inpaq.com) ||||| ||||&lt;br /&gt;
* Allegro Stromsensoren (z.&amp;amp;nbsp;B. ACS713, ACS756) ||||| ||||| ||||| ||&lt;br /&gt;
* Allgemein mehr Sensoren ||||| ||||| ||||| ||||| ||||| |||&lt;br /&gt;
* Anemometer ||||| ||&lt;br /&gt;
* BLDC-Motoren ||||&lt;br /&gt;
* Durchflussmesser (z.&amp;amp;nbsp;B. wie Conrad Nr.155374) ||||| ||||| ||||| |||&lt;br /&gt;
* Flexinol / Nitinol (Nickel-Titanium) / NanoMuscle Aktuatoren ||||| ||||| ||||| ||||| |||&lt;br /&gt;
* Freescale/Motorola Drucksensoren, besonders die gängigen aber noch fehlenden MPX4100AP, MPX4200AP, MPX4250AP mit der robusten Automotive Spezifikation und Stutzen für Schlauchanschluss = CASE 867B-04 ||||| ||||| ||||| ||||| ||||| ||||| ||&lt;br /&gt;
* FSRs (Force Sensing Resistor) von Interlink Electronics ||||| ||||| ||||&lt;br /&gt;
* Getriebemotoren wie RB35 oder RB40 ||||| ||||| |||||&lt;br /&gt;
* günstige Temp. Sensoren TC77 ||||| ||||| ||||&lt;br /&gt;
* Gyro Sensoren  MURATA,  ENC-03J A/B    ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| |&lt;br /&gt;
* Gyro, Drehwinkelgeber, Kreiselsensoren ähnl. Tokin CG-L43 {{Reichelt50|FF0000}} |&lt;br /&gt;
* Hall-Sensor(analog) Allegro A1301, A1302 |&lt;br /&gt;
* Hall-Sensor UGN3503, KMZ51 ||||| ||||| ||||| |||&lt;br /&gt;
* Hall-Sensoren ähnlich TLE4905, aber mit Vcc 3,3V, z.&amp;amp;nbsp;B. CYD1102G (TLE 4905L Hallsensor, 3,8-24V ist lieferbar seit 20.12.11) ||   &lt;br /&gt;
* I²C-Bus Temperatursensor DS1631Z ||||| ||||| ||||| ||||| ||&lt;br /&gt;
* iMEMs Acceleration Sensors ADXL Series von Analog Devices ||||| ||||| ||||| ||||| |&lt;br /&gt;
* Induktions-Stromsensoren Coilcraft #J9199-A o.ä. ||||| |||&lt;br /&gt;
* IS471 Selbstmodulierende IR-Lichtschranke ||||| ||||| ||||| ||||| ||||| ||&lt;br /&gt;
* kleine Feuchtigkeitssensoren zur &#039;on-board-Montage&#039; ||||| ||||| ||||| ||||| |||||&lt;br /&gt;
* LEM Stromsensoren (Transducer) der HAIS-Serie, speziell HAIS 50-P und 100-P ||||| ||||| ||||| ||||&lt;br /&gt;
* Luftdruck-/ Temperatur Sensor Intersema MS5534 (mit SPI- Interface) ||||| ||||&lt;br /&gt;
* Magnetfeld-Sensor (Kompass-Anwendung) KMZ52 ||||| ||||| |||&lt;br /&gt;
* Modellbau-Servos ||&lt;br /&gt;
* Piezo Minimotoren/Linearaktoren von Elliptec/Siemens einzeln und günstig ||||| |||||&lt;br /&gt;
* PIR Bewegungsmelder ||&lt;br /&gt;
* QT160 6-fach Touch Sensor IC ||||| ||&lt;br /&gt;
* Sensirion SHT11/SHT71 (oder auch SHT15/SHT75) {{Reichelt50|FF0000}}||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| |&lt;br /&gt;
* Summer mit 20mA@5V ähnlich Conrad Nr.751553 (TDB05 kann mit 30mA@5V nicht von allen Controllern direkt getrieben werden) ||||| ||||| |||||&lt;br /&gt;
* Temperatur IC TC1047 |||&lt;br /&gt;
* Temperatursensor mit SPI-Interface LM74 ||||| ||&lt;br /&gt;
* Thermoelement Typ-K (MAX6675)/ Typ-J mit Steckverbinder und SPI ||||| ||||| ||||| ||||| ||||| ||||| |||&lt;br /&gt;
* Sensoren zur Umweltanalyse (Sauerstoffgehalt der Luft, pH-Wert, etc.) ||&lt;br /&gt;
&lt;br /&gt;
=== Funk und Signalsynthese ===&lt;br /&gt;
&lt;br /&gt;
* Clock generator IC&#039;s, z.&amp;amp;nbsp;B. PCK20?? von Philips |&lt;br /&gt;
* DDS-IC (Waveform-Generator) von Analog wie AD9833, AD9835 ||||| ||||| ||||| ||||| ||||| ||||| |||&lt;br /&gt;
* EM4095 (RFID) ||||&lt;br /&gt;
* LMX2306/LMX2316/LMX2326 PLL Synthesizer von National ||||| ||&lt;br /&gt;
* LTC5540 (RF-Mixer) |&lt;br /&gt;
* PLL Schaltkreise für Frequenzerzeugung. z.&amp;amp;nbsp;B. MC / ML145170 (SOIC16) / TSA5060A ||||| ||||| ||||| |||&lt;br /&gt;
* SI4735 Silicon Labs Radio ICs ||||&lt;br /&gt;
* TEA5757 FM-Tuner IC von Philips |||&lt;br /&gt;
* TEA5768HL FM-Tuner IC von Philips |||||&lt;br /&gt;
* TPS79318 1,8V 200mA LDO in (bestens für z.&amp;amp;nbsp;B. LPC210x µC) ||&lt;br /&gt;
&lt;br /&gt;
=== sonstige ===&lt;br /&gt;
&lt;br /&gt;
* 74HCxxxx komplette Serie ||||&lt;br /&gt;
* 74VHC-Serie komplettieren (z.&amp;amp;nbsp;B. 74VHC125D) ||||| ||&lt;br /&gt;
* 74ASxxx |&lt;br /&gt;
* 74ACTxxx |&lt;br /&gt;
* A3982 Motortreiber/Controller (1,5A, 2APeak, u.A. für RepRap&#039;s) ||&lt;br /&gt;
* Automotiv ICs z.&amp;amp;nbsp;B. LM1815, LM1915, LM1949, LM9011, LM9040, LM9044, LMD18400... ||||| |&lt;br /&gt;
* Bosch CJ125 (Lambdasonden-IC) ||||| ||||&lt;br /&gt;
* DS1616 von Dallas Datalogger-IC ||&lt;br /&gt;
* DTMF-Dekoder-Enkoder (8870, 8880) ||||| ||||| ||||| ||||| ||||| |||||&lt;br /&gt;
* HCT-Logik in SMD {{Reichelt50|FF0000}}||||| ||||| ||||| |||&lt;br /&gt;
* High Side Current Sense ICs wie MAX4172 ||||| |&lt;br /&gt;
* IRS2092 Class-D Audio Driver IC |||&lt;br /&gt;
* ISD 2560 -&amp;gt; SOIC Gehäuse (Sprachaufnahme IC) ||||| |&lt;br /&gt;
* ITS4141N o. BTS4141N Smart High-Side Power Switch (z.&amp;amp;nbsp;B. bestens für 24V geeignet!) ||&lt;br /&gt;
* Kleinere SMD-Bauformen (bes. bei ICs) ||||| ||||| ||||| ||&lt;br /&gt;
* L6205 Motortreiber (2Kanal, 2,8A, DMOS)|||||&lt;br /&gt;
* L6206N Motortreiber (Wird für OpenDCC benötigt, und ist derzeit nur SEHR schlecht erhältlich) ||&lt;br /&gt;
* LM3886 (68W Audioverstärker) ||||| |&lt;br /&gt;
* LMD18200 (H-Bridge) |&lt;br /&gt;
* LT-1117-CST-5 als Sot223 (adj und 3.3 gibts schon, 5 fehlt noch) |&lt;br /&gt;
* LTC 4411 ideale Diode 2,6 bis 5,5V max. 2,6A im SOT-23 Gehäuse&lt;br /&gt;
* LTZ1000ACH#PBF Linear Technology Präzisions-Referenz (Ersatz für LM399H) ||||&lt;br /&gt;
* Maxim Switched Capacitor Tiefpass-Filter (z.&amp;amp;nbsp;B. MAX297, MAX7410) ||||| |&lt;br /&gt;
* mehr Familien von Logik-ICs, z.&amp;amp;nbsp;B. AC, ACT, LVC (in SMD) ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||&lt;br /&gt;
* mehr SMD Bauteile  {{Reichelt50|FF0000}} {{Reichelt50|00FF00}} |||||&lt;br /&gt;
* MIC6315 von Micrel (3,3/5V Reset Baustein mit manual Reset) ||&lt;br /&gt;
* Motortreiber TLE 4205 ||||&lt;br /&gt;
* PGA2311 (Stereo Audio Volume Control) |&lt;br /&gt;
* SDT06S60 Infineon SiC 600V 6A Silizium-Carbid Schottky-Diode (kein trr, daher keine Schaltverluste) ||||&lt;br /&gt;
* SMD Doppeldiode Schottky 12A 60V im TO252AA z.&amp;amp;nbsp;B. 12CWQ06FN von IOR ||||| ||||| ||||| ||&lt;br /&gt;
* TLV320AIC23B Audio-Codec ||&lt;br /&gt;
* TPIC6B595 (oder ähnliche 74xx595 high current (150 mA) shift register) |||||  ||||&lt;br /&gt;
* uC supervisor chips + watchdog z.&amp;amp;nbsp;B.: MAX6864 ist z.Z. der beste (0.2uA!) ||||&lt;br /&gt;
* VN808 Low Treshold Octal High Side Driver 0,7A ||&lt;br /&gt;
* VS1000 Ogg Decoder von VLSI |&lt;br /&gt;
* VS1053 MP3/AAC/WMA/Ogg Decoder von VLSI ||||| ||||| ||&lt;br /&gt;
* Zarlink MT8841 Calling Number Identification Circuit |&lt;br /&gt;
* ZHB6718 (H-Bridge für 1,5V - 20V Motoren) ||||| ||||&lt;br /&gt;
* ZRA250F005 Referenzspannungsquelle 2,5V 0.5% SOT23-Gehäuse ||||| ||||| ||&lt;br /&gt;
* TXB0108 8-Bit Bidirectional Voltage-Level Translator with Auto Direction Sensing |&lt;br /&gt;
&lt;br /&gt;
== Baugruppen ==&lt;br /&gt;
&lt;br /&gt;
* Atmel ATNGW100 von [http://www.atmel.com/dyn/corporate/view_detail.asp?FileName=AVR32NGKit_3_26.html Atmel] = billiges Linux Board ($69=51.69€) --&amp;gt; [http://www.avrfreaks.net/wiki/index.php/Documentation:NGW/NGW100_Hardware_reference Dokumentation] ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||&lt;br /&gt;
* Atmel ATSTK1000 von [http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3918 Atmel] ||||| ||||| ||||| ||||&lt;br /&gt;
* Axis Etrax 100LX MCM (Multi Chip Module) A full Linux computer on a single chip!  ||||| |||||&lt;br /&gt;
* Bluetooth Funkmodul {{Reichelt50|FF0000}}{{Reichelt50|00FF00}}|||||&lt;br /&gt;
* Bluetooth Mini-Module (RS232-Bluetooth-&amp;quot;Wandler&amp;quot;-Platinchen) z.&amp;amp;nbsp;B. BTM222 ||||| ||&lt;br /&gt;
* CentiPad/DevKit Embedded Linux Modul ([http://www.centipad.de www.centipad.com]) ||||| ||&lt;br /&gt;
* DS9490R USB zu 1-Wire Dongle (auch mit Linux Treiber) ||||| |||||&lt;br /&gt;
* Easy-Radio Module zur seriellen Datenübertragung (ER400 RS/TS/RTS) ||||| ||||| ||||| ||||&lt;br /&gt;
* Foxboard = Betriebsfertiges Micro Linux System mit Axis Etrax 100LX MCM 66mm x 72mm ||||| ||||| ||||| ||||| ||||&lt;br /&gt;
* FoxVHDL = FPGA Erweiterungskarte für das ACME Foxboard ||||&lt;br /&gt;
* FPGA, low-cost Experimentierplatinen ||||| ||||| ||||| ||||| |||| &lt;br /&gt;
* Hope RF Module 433 u. 868 MHz, http://www.hoperf.com/pdf/RF12.pdf ||||| ||||| |&lt;br /&gt;
* Hope RF Module 2,4GHz, RFM70 |||||&lt;br /&gt;
* kostengünstige Funkempfänger/Funksender 433 &amp;amp; 868 Mhz ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||&lt;br /&gt;
* kostengünstige Funkschaltmodule (TLP/RLP) ||||| ||||| ||||| ||||| |||&lt;br /&gt;
* Lantronix XPort Direct |||&lt;br /&gt;
* Lantronix XPort Embedded Device Server ([http://www.lantronix.com www.lantronix.com]) ||||| ||||| ||&lt;br /&gt;
* Microchip PICkit 2 ||||| |||&lt;br /&gt;
* Microchip PICkit 2 (PG164120) ohne Demoplatine |&lt;br /&gt;
* Mini-WLan Module (RS232 zu WLan) ||||| ||||| ||||| ||||| ||||&lt;br /&gt;
* MT1390 FM Tuner-Modul von Microtune |||&lt;br /&gt;
* NetDCU8 von F &amp;amp; S Elektronik Systeme GmbH (http://www.fs-net.de) - Linux-Computerplatine mit 400MHz Samsung-ARM mit 32MB RAM, 16MB Flash und SD/Ethernet/CAN/USB/TFT/RS232 für ca. 100 Euro ||||| ||||| ||&lt;br /&gt;
* OM5610 FM Tuner-Matchbox von Philips |||&lt;br /&gt;
* ST Primer 2 (Experimentierboard fuer ARM Einsteiger) ||&lt;br /&gt;
* STM STM3210C-EVAL für &amp;lt;=214,79€ netto (wie bei Future Elektronik, Stand 18.3.2011) |&lt;br /&gt;
* TI - MSP430 Wireless Development Tool (AEC13895U) |&lt;br /&gt;
* TI eZ430-Chronos |&lt;br /&gt;
* UM232 FTDI USB - RS232 Modul für DIL sockel |||||&lt;br /&gt;
* Raspberry Pi |||&lt;br /&gt;
&lt;br /&gt;
== Passive Bauteile ==&lt;br /&gt;
&lt;br /&gt;
=== Spulen und Trafos ===&lt;br /&gt;
&lt;br /&gt;
* Die Micrometals Pulverkerne (-18 und -26) auch in größer ||||| ||&lt;br /&gt;
* Fastron 0805 AS Serie vervollständigen ||&lt;br /&gt;
* Funk-Entstördrosseln 16A, div. Werte ||||| ||||| ||||| |||&lt;br /&gt;
* Funk-Entstördrosseln 330µH / 3A |&lt;br /&gt;
* Funk-Entstördrosseln 47µH |||&lt;br /&gt;
* Magnetics CoolMu Ringkerne ||||| ||||| ||&lt;br /&gt;
* Magnetics MPP Ringkerne ||||| ||||| ||&lt;br /&gt;
* Ordentliche Trafospulen + Kerne, z.b. ETD-Serie, oder RM10 ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| |||||&lt;br /&gt;
* Passende Ferrite dazu: N27,N41,N67,N87,N97 ||||| ||||| ||||| ||||| ||||| ||&lt;br /&gt;
* Ringkertrafos &amp;gt;500VA mit höherer Spannung als 30V (Verstärkerbau) |||&lt;br /&gt;
* SEPIC-Speicherdrosseln von Würth WE-DD (Größe M u. L) ||||&lt;br /&gt;
* Übertrager für Schaltregler z.&amp;amp;nbsp;B. Epcos Typ  B78304 ||||| |||||&lt;br /&gt;
* Würth Induktivitäten ||||| ||||| ||||| ||||| ||||&lt;br /&gt;
* Würth Sortimentskästen Induktivitäten ||||| |&lt;br /&gt;
&lt;br /&gt;
=== Kondensatoren ===&lt;br /&gt;
&lt;br /&gt;
* Drehkondensatoren 20-500pf ||||| |||||&lt;br /&gt;
* Generell SMD-Kerkos im Wert &amp;gt; 100nF {{Reichelt50|FF0000}} {{Reichelt50|00FF00}} |&lt;br /&gt;
* Günstige hochkapazitive Doppelschichtkondensatoren (z.&amp;amp;nbsp;B. Maxfarad MES2245 220F 2,3V) ||||| |||&lt;br /&gt;
* Keramikkond. SMD 0603/0805/1206: mehr Zwischenwerte (56p, 82p, 560p) ||||| ||||&lt;br /&gt;
* Kleine Niedervolt-Polyproplyenkondis mit mehr Kapazität ||||&lt;br /&gt;
* Low-ESR Elkos (definiertes Fabrikat/Typ, und nicht einfach irgendwelche! (Rubycon?)) {{Reichelt50|FF0000}}||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||&lt;br /&gt;
* Low-ESR Elkos RM 3,5mm 1.000µF 6,3V (Mainboardaustausch Elko) ||||     &lt;br /&gt;
* Low-ESR SMD Tantal-Elkos (definiertes Fabrikat/Typ, und nicht einfach irgendwelche! (AVX?, Epcos?)) ||||| ||||| ||||| ||||| ||||| |&lt;br /&gt;
* Sanyo OS-Con bedrahtet und SMD |||&lt;br /&gt;
* Wima FKP02 |&lt;br /&gt;
* Wima FKP2 |&lt;br /&gt;
* Wima MKP3-X2 (~275V, klein und ideal für Kondensatornetzteile) ||&lt;br /&gt;
* Wima MKP4 |||||&lt;br /&gt;
* Zum MAX232 so20 passende SMD-Kerkos im Wert 1µF (0805,0603, 1206) ||||| ||||| ||||| ||||| |||&lt;br /&gt;
&lt;br /&gt;
=== Widerstände und Potis ===&lt;br /&gt;
&lt;br /&gt;
* 25/50/100W Hochlast-Widerstände (~20/50Ω auch weniger) ||||| ||||| ||||| ||||&lt;br /&gt;
* Digitalpoti AD5160 mit SPI in SOT23 ||&lt;br /&gt;
* Digital-Potentiometer (z.&amp;amp;nbsp;B. 2-Wire MAX546x, AD526x, X9C10x) ||||| ||||| ||||| ||||| ||||| ||||| |&lt;br /&gt;
* Durchsteck-Widerstände in kleiner Bauform 0204. ||||| ||||| |||&lt;br /&gt;
* Endlospotis als Motorgeber ||&lt;br /&gt;
* Erneut die 10k-Ohm SMD-Potis |||||&lt;br /&gt;
* Größere Auswahl an (Stereo-)Schiebepotis in log und lin, insbesondere jenseits 100K ||&lt;br /&gt;
* Hochlast NTC, z.&amp;amp;nbsp;B. 80-220Ω/1-4A (EPCOS, Ametherm) ||&lt;br /&gt;
* Hochspannuns-Widerstände (z.&amp;amp;nbsp;B. 330M/10kV) ||&lt;br /&gt;
* iPod-Wheel z.B. QT511-ISSG  ||||| ||||| |||||&lt;br /&gt;
* Kleine Ein-Gang-Trimmer unterhalb 250Ω |&lt;br /&gt;
* Leitplastikpotis im Servogehäuse |&lt;br /&gt;
* Linear- und 360° Soft-Pots (iPod-Wheel) wie von spectrasymbol ||||| |||&lt;br /&gt;
* Niederohm-Widerstände (Shunts ab 1mOhm im guten Gehäuse z.&amp;amp;nbsp;B. TO220) ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||&lt;br /&gt;
* Null-Ohm Widerstände (Drahtbrücken) Baugröße wie 1/4W ||||| ||||| |||&lt;br /&gt;
* Präzisions-Spannungsteilernetzwerke ||||| ||||| |&lt;br /&gt;
* Präzisionsspannungsteiler 1:10, 1:100, 1:1000 (10MOhm Gesamtwiderstand) |||&lt;br /&gt;
* Präzisionswiderstände 0,05% und besser, ev. drahtgewickelt ||||| ||||| ||||| ||&lt;br /&gt;
* R2R-Widerstandsnetzwerke (z. B. 10/20kOhm für DA-Wandler an Microcontrollern) ||||| ||||| ||||| ||||| ||||| ||||| ||||| |&lt;br /&gt;
* SMD-Präzisionswiderstände (0,1% TC10ppm/K =&amp;gt;0,1W indukt.arm) ||||| ||||| ||||| ||||&lt;br /&gt;
* SMD-Widerstände 0805 auch aus der E24-Reihe ||||| ||||| ||||| ||||&lt;br /&gt;
* SMD-Widerstände 0805 und 1206 auch unterhalb von 1Ω ||||| ||||| ||||| ||||| ||||| ||||| |||||&lt;br /&gt;
* SMD-Widerstände unterhalb 1Ω, andere Gehäuse als 0805/1206 (leichter erfüllbarer Wunsch) ||||| ||||| ||||| ||&lt;br /&gt;
* statt Radiohm-Potis bitte Prehostat oder Alphastat 16 63256-026xx ||||| ||||| ||||||&lt;br /&gt;
* Widerstände &amp;gt; 10MOhm (möglichst bis 100GOhm) ||||&lt;br /&gt;
* Widerstandsnetzwerke 11-Pin (für 10er Bargraphanzeige) |||&lt;br /&gt;
&lt;br /&gt;
=== Quarze, Quarzoszillatoren und Resonatoren ===&lt;br /&gt;
&lt;br /&gt;
* 13,5600 MHz Quarz (benötigt für RFID) (SMD+bedrahtet)  ||||| ||||| ||||| ||||&lt;br /&gt;
* 24,0000 MHz Standardquarz Grundton (&#039;&#039;&#039;kein 3. Oberton!!!&#039;&#039;&#039;), benötigt für USB-DMX-Interface (SMD-Grundtonquarz unter 24,0000-MA505 verfügbar) ||||| ||||| |&lt;br /&gt;
* 25,0000 MHz &#039;&#039;&#039;Grundton&#039;&#039;&#039;-Quarz, wird benötigt für Microchip TCP/IP Controller ENC28J60) (als Keramik-SMD-Quarz 25,000000-MJ verfügbar) {{Reichelt50|FF0000}}{{Reichelt50|00FF00}}||||| ||||| ||||| ||||| ||||| ||||| ||||| ||&lt;br /&gt;
* Allgemein mehr Grundtonquarze bei höheren Frequenzen ||||| |&lt;br /&gt;
* Murata Keramik-Resonator CSTLS16M0X, CSTLS20M0X (obwohl 3. OW, direkt mit µC verwendbar) |&lt;br /&gt;
* Quarze 6,500000 MHz (HF-Anwendung) ||&lt;br /&gt;
* Quarze 32 MHz 10ppm Oscillatorfrequenz 0 bis +70°C |&lt;br /&gt;
* Quarz mit 3,200 MHz  ||&lt;br /&gt;
* Quarzoszillator 9,8304 MHz  |||&lt;br /&gt;
* SMD Quarze/ Oszillatoren in flachen, kleinen SMD Gehäusen (SMX-A/-B) |||||&lt;br /&gt;
* SMD-Quarze mit Standardgehäuse (z.&amp;amp;nbsp;B. HC49/US &amp;amp; HC49/UP) ||||| ||||&lt;br /&gt;
* 32,768 kHz Quarz mit 12,5 pF ||&lt;br /&gt;
&lt;br /&gt;
=== Sonstiges ===&lt;br /&gt;
&lt;br /&gt;
* Lötfähige (SMD-) Kühlkörper (Fischer) ||||| ||||| ||||| ||&lt;br /&gt;
* Metallbrückengleichrichter für 50A ||||&lt;br /&gt;
* Netzfilter FFP Reihe Schurter ||&lt;br /&gt;
* Suppressordioden mit Spannungsbereich zwischen 15V und 30V |||&lt;br /&gt;
* Übertrager FB2022 oder 20F-001N (passend zu RTL8019AS)||&lt;br /&gt;
* Übertrager passend zu ENC28J60 |&lt;br /&gt;
* Varistoren 14V auch als bedrahtetes Bauteil (für KFZ-Bordnetz)-&amp;gt; 1,5KE 18CA ||||| ||||| ||&lt;br /&gt;
&lt;br /&gt;
== HF-Baumaterialien ==&lt;br /&gt;
&lt;br /&gt;
* Durchführungskondensatoren 1nF/160V (waren Ende &#039;06 noch im Programm) ||||&lt;br /&gt;
* Filter SFE10.7MA19 360khz SZP2026 |&lt;br /&gt;
* H155 (HF-Kabel) |||||&lt;br /&gt;
* HF-Litze(n) |&lt;br /&gt;
* Keramik / Teflon Leiterplatinen |&lt;br /&gt;
* Keramische Filter CFM455... ganzes Sortiment |||||&lt;br /&gt;
* MC68160FB&lt;br /&gt;
* MC68EN302PV20&lt;br /&gt;
* MICRF002/022, MICRF102/103 von Micrel  ||||| |&lt;br /&gt;
* MMICs und Ringmischer von Mini-Circuits&lt;br /&gt;
* MT48LC4M32B2TG-7&lt;br /&gt;
* PLL ICs z.&amp;amp;nbsp;B. von NXP und National für HF-UHF ||&lt;br /&gt;
* S3C4510B&lt;br /&gt;
* Transistoren MRFG35010 |&lt;br /&gt;
* U.FL bzw. IPEX Steckbuchsen zum Selbstkonfektionieren von HF-Kabeln ||&lt;br /&gt;
* ZF-Quarzfilter für versch. Frequenzen (10, 20, 40 MHz) ||&lt;br /&gt;
* Zirkulatoren ALD4302SB statt LM239 &lt;br /&gt;
* µP Compatible CTCSS Encoder,Decoder FX 365&lt;br /&gt;
&lt;br /&gt;
== Optoelektronik und Leuchtmittel ==&lt;br /&gt;
&lt;br /&gt;
=== Einzel-LEDs ===&lt;br /&gt;
&lt;br /&gt;
* Acriche 230V~ LEDs&lt;br /&gt;
* Edison Opto LEDs: pinkompatibel mit diversen abgekündigten LEDs von Luxeon und Co, aber deutlich günstiger im Preis und leuchtstärker da u.A. Cree LED DIEs verwendet werden&lt;br /&gt;
** Edison Opto ARC / Edixeon LEDs (da ja Luxeons abgekündigt sind) ||||&lt;br /&gt;
** Edison Opto Federal (Luxeon Rebel artig) ||||&lt;br /&gt;
** Edison Opto KLC8 (Luxeon Bauform mit Cree Die) ||||&lt;br /&gt;
** Edison S Serie -&amp;gt; Lumiled kompatibles Gehäuse aber viel leuchtstärker |||&lt;br /&gt;
** Edison Exixeon Serie -&amp;gt; Lumiled kompatibles Gehäuse aber viel leuchtstärker ||&lt;br /&gt;
** Edison Edixeon RGB |||&lt;br /&gt;
* Everlight SMD-RGB (fullcolor) 19-337/R6GHBHC-A01/2T |||||&lt;br /&gt;
* Generell: Z-Power LEDs von Seoul (günstiger und heller als Luxeon) ||||| ||&lt;br /&gt;
* IR-Diode mit viel Power ttp://www.lc-led.com/Catalog/department/36/category/49/1 ||&lt;br /&gt;
* Kühlerplatinen für Power-LEDs im Star-Format oder vergleichbar |&lt;br /&gt;
* Low Current SMD-LEDs (z.&amp;amp;nbsp;B. Osram LG T679 - Anm.: hier gleich die neuen Varianten Lx T67K bestellen, nicht die alten 9er) ||||| ||||| ||||| |||||&lt;br /&gt;
* Luxeon Rebel weiß (180 lm) auf Star-, Mini- oder normaler Platine ||&lt;br /&gt;
* OSRAM Hyper TOPLEDS gelb LY T676-S1T1-26 ||&lt;br /&gt;
* OSRAM Hyper TOPLEDS weiss LW T67C-T2U2-5K8L ||&lt;br /&gt;
* Reflektoren für 10mm LEDs ||&lt;br /&gt;
* Samsung SLS RGB W815 TS (PLCC6 RGB-LED)|&lt;br /&gt;
* Seoul Z-LED RGB auf Platine ||&lt;br /&gt;
* Seoul Zled P4 (100lm bei 350mA, 240lm bei 1A!) ||||| |||||&lt;br /&gt;
* SMD-IR-LEDs in 0603/0805/SOT23 + dazu passende IR-Fotodioden in gleicher Größe |&lt;br /&gt;
* SMD-LED Bauform 0402 rot/gelb/grün/blau/weiss  ||||| ||||| ||||| ||||| ||&lt;br /&gt;
* Superflux RGB-LED ||||&lt;br /&gt;
* warmweiße LED ||||| ||||| ||||| ||||&lt;br /&gt;
* weiße SMD-LED Bauform 0603 ||||| ||||| |||||&lt;br /&gt;
&lt;br /&gt;
=== Anzeigen und Displays ===&lt;br /&gt;
&lt;br /&gt;
* 4-Stellige Dot-Matrix LED-Anzeigen Siemens SLG 2016 oder von HP oder ähnliches ||||| |&lt;br /&gt;
* 7-Segment-Anzeige 4 DIGIT mit und ohne Doppelpunkt ||||| |&lt;br /&gt;
* 7-Segment-Anzeige, allgemein Low-Current bzw. High Efficiency Versionen anbieten ||||| ||||| ||&lt;br /&gt;
* 7-Segment-Anzeige, weiss, gem. Anode ||||| ||||| ||||| ||||| ||||| ||||| ||||| |&lt;br /&gt;
* 7-Segment-Anzeige, weiss, gem. Kathode ||||| ||||| ||||| ||||| ||||| ||||| |&lt;br /&gt;
* Generell alle 7-Segment-Anzeigen auch in Blau und bis zu 100mm Höhe ||&lt;br /&gt;
* Kingbright PSC Serie (16 Segment LED-Display, insbesondere PSC08 und PSC12) |&lt;br /&gt;
* LED Punktmatrix Anzeigen 8x8 superrot 3mm (z.&amp;amp;nbsp;B. Everlight ELM-1883SRWA) ||&lt;br /&gt;
* LED Punktmatrix bicolor 1.9mm (z.b. Betlux BL-M 07A881SG-XX )&lt;br /&gt;
* TFT/OLED Farb-Displays, wie die bereits abgekündigten OSRAM OLEDs ||||&lt;br /&gt;
* Vakuum-Fluoreszenz-Displays (Dot Matrix mit Standardcontroller, z.&amp;amp;nbsp;B. Futaba &amp;quot;LCD Emulators&amp;quot;)  ||||| ||||| |||&lt;br /&gt;
&lt;br /&gt;
=== andere Leuchtmittel ===&lt;br /&gt;
&lt;br /&gt;
* OSRAM Halogen Decostar 51 12V 20W GU5,3 statt des billigen NoName Zeugs ||&lt;br /&gt;
&lt;br /&gt;
=== sonstige Optoelektronik ===&lt;br /&gt;
&lt;br /&gt;
* BPW 34 F / FS (aus dem Sortiment gefallen, PIN-Fotodiode) |&lt;br /&gt;
* IL207AT (SMD Optokoppler von Infineon) ||||| |||&lt;br /&gt;
* ILD256T (SMD AC-Optokoppler)  ||||| |||||&lt;br /&gt;
* ILD620 (DIP Optokoppler) ||||| ||||| ||||| |||||&lt;br /&gt;
* IrDA-Tranceiver TFDS4500 (oder TFDU4100) wieder anbieten - war im 07/2005er Katalog noch drin) ||||| ||||&lt;br /&gt;
* PC923 (Opto MOSFET Gate Treiber auch für High Side) |&lt;br /&gt;
* SFH6106, SFH6206 4 Pin Optokoppler SMD ||||| |&lt;br /&gt;
* TLP 3617 Photo-Triac&lt;br /&gt;
* TLP113 (SMD Optokoppler) |||||&lt;br /&gt;
* TLP250 (Opto MOSFET Gate Treiber auch für High Side)||||&lt;br /&gt;
* TORX 178 Fiberoptik-Receiver&lt;br /&gt;
* TOTX177PL und TORX177PL (Fiberoptik-Transmitter) als Ersatz für TOTX173 und TORX173 (zwar anderes Footprint, aber dafür auch kleiner und günstiger)&lt;br /&gt;
* TSOP 1140 Infrarot-Receiver  (oder andere 40 kHz IR-Empfänger) ||&lt;br /&gt;
* TSOP 1730 Infrarot-Receiver [Achtung! TSOP17xx sind Auslaufmodelle bei Vishay] ||&lt;br /&gt;
* TSOP98200 (Breitband IR-Empfangsmodul 20-455 KHz) ||||&lt;br /&gt;
* TSOP98260 (Breitband IR-Empfangsmodul 20-60 kHz) |||||&lt;br /&gt;
* Vactrol Optokoppler (mit Fotowiderstand zur Analogsignalregelung) |||||&lt;br /&gt;
&lt;br /&gt;
== Mechanisches ==&lt;br /&gt;
&lt;br /&gt;
=== Schalter/Taster/Eingabegeräte, Relais ===&lt;br /&gt;
&lt;br /&gt;
* bistabile Relais mit 2 Wicklungen ||||| ||||| ||||| &lt;br /&gt;
* Drehimpulsgeber DDM Hopt+Schuler 427 SMD (evt auch normal, stehend &amp;amp; liegend) ||||| ||||| ||||| ||||| ||||| |||||&lt;br /&gt;
* Drehschalter Serie DS in allen Versionen nur vom Hersteller C&amp;amp;K; auch brückende Versionen anbieten  ||||| |||||&lt;br /&gt;
* Drucktastenfeld Matrix 3x4 ||||| ||||| ||||| ||||| ||||&lt;br /&gt;
* Folientastaturen {{Reichelt50|FF0000}}||||| ||||| |||||&lt;br /&gt;
* Grayhill Series 60A Joysticks mit USB-Adapter |&lt;br /&gt;
* Hohlwellen-Drehgeber (z.&amp;amp;nbsp;B. EC35B-Serie von Alps) ||&lt;br /&gt;
* kleiner Joystick wie beim Atmel Butterfly  ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||&lt;br /&gt;
* mehrpolige Fußschalter, FS 35 bitte bei Druckschalter einordnen ||||&lt;br /&gt;
* Miniaturkippschalter mit Verriegelung ||||&lt;br /&gt;
* möglichst kleine und flache Druckschalter rastend!  |||||&lt;br /&gt;
* passende Touchpanels für die coolen Blue-Line-Grafikdisplays ||||| ||||| ||&lt;br /&gt;
* Relais mit hohen Wirkungsgrad (daher nur geringer Spulenstrom nötig) ||&lt;br /&gt;
* SMD-Schiebeschalter |||||&lt;br /&gt;
* Taster Radiohm ST-1034 in rot, grün, gelb, blau, grau und schwarz |&lt;br /&gt;
* Taster und Kappen aus der Multimec-Reihe |||&lt;br /&gt;
* Taster, Schalter und LED-Fassungen aus der Mentor FEL-Reihe ||||&lt;br /&gt;
* Tastköpfe für Taster9308, wie zb Omron B32-2000 oder B32-2010 ||&lt;br /&gt;
* PhotoMOS Relay (z.&amp;amp;nbsp;B. AQV257 von Panasonic |&lt;br /&gt;
&lt;br /&gt;
=== (Steck-) Verbindungen PC- und Audiotechnik ===&lt;br /&gt;
&lt;br /&gt;
* 2.5mm-Stereo-Klinkenbuchsen (3-polig) SMD ||||&lt;br /&gt;
* Adapter 3,5mm-Klinkenbuchse auf 3,5mm-Klinkenbuchse ||&lt;br /&gt;
* Cablesharing Adapter 2x RJ45-Buchsen(1x Ethernet 1x ISDN)1xStecker |http://www.btr-netcom.com/Products/upload/ATCH-002661.pdf&lt;br /&gt;
* Floppy-Stromversorgungstecker 3,5&amp;quot; Printausführung ||||| ||&lt;br /&gt;
* Günstigere SD/MMC-Steckverbinder z.&amp;amp;nbsp;B.SDBMF-00915B0T2 von MULTICOMP(selbst bei Farnell für 1,80 Euro) ||||| ||&lt;br /&gt;
* Hochwertigere 1/4&amp;quot;-Klinkenbuchsen, z.&amp;amp;nbsp;B. von Rean oder Cliff |||||&lt;br /&gt;
* Höherwertige 3,5mm-Klinkenbuchsen / -stecker (statt &amp;quot;EBS35&amp;quot; oder &amp;quot;KK(S/M) ..&amp;quot;) ||||| ||||| |||&lt;br /&gt;
* Höherwertige Adapter für Klinke (die bisherigen 3,5 auf 6,3mm-Adapter sind nach ~2 mal Stecken völlig ausgeleiert) |&lt;br /&gt;
* Micro-USB-Steckverbinder ||||| ||||&lt;br /&gt;
* Micro-USB 2.0-Buchsen (Printmontage und SMD-Montage) ||&lt;br /&gt;
* microSD / Transflash Sockel mit Push-Push-Technik (ist nervig die immer für teuren versand aus amiland kommen zu lassen) ||||| ||||| ||||| ||||| ||||| ||||| |&lt;br /&gt;
* MiniSD Card-Connector mit Auswurffunktion für Oberflächenmontage  ||||| |&lt;br /&gt;
* Modulare Buchse RJ45 mit Übertrager und LEDs für Ethernet 10/100, z.&amp;amp;nbsp;B. SI-40138 MagJack von BEL-STEWART oder Taimag RJLBC-060TC1 {{Reichelt50|FF0000}}||||&lt;br /&gt;
* Modulare Buchse RJ45 ohne Übertrager mit LEDs (oder Lichtleiter für SMD-LEDs) ||||| |||&lt;br /&gt;
* Molex Steckerreihe Minifit Jr 4,2mm Rastermaß (verwendet als Stromstecker in Computern, Mainboard, PCI-E, P4/EPS ...) |&lt;br /&gt;
* Ordentliche Lautsprecherbuchsen &amp;quot;Strich-Punkt&amp;quot; (Print oder Wand) (die Stecker sind OK) |&lt;br /&gt;
* RJ45-Stecker 90° nach unten oder zur Seite gewinkelt ||&lt;br /&gt;
* SATA-Stromstecker/ -Buchsen für Kabel/ Printmontage ||||&lt;br /&gt;
* USB3-, e-SATA-, eSATAp (Power e-SATA)-Stecker in Printausführung (gerade und gewinkelt) [die gibts aber inzwischen, z.b. USB3 AEB] ||||&lt;br /&gt;
* vernünftige Koax-Stecker und -Kupplungen z. Bsp. von Hirschmann&lt;br /&gt;
* WOL-Verbindungskabel / -Stecker / -Print-Connectoren: ||||| |&lt;br /&gt;
&lt;br /&gt;
=== (Steck-) Verbindungen Platinen und ICs ===&lt;br /&gt;
* Buchsenleiste Fischer BL5  |&lt;br /&gt;
* Buchsenleisten zum Crimpen (allseitig anreihbar!, 1x1, 1x2, z.&amp;amp;nbsp;B. [http://www.newproduct.molex.com/datasheet.aspx?ProductID=92125 Molex 2081 ?] oder Harwin M20 )  ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| |||&lt;br /&gt;
* Carrier-IC-Sockel&lt;br /&gt;
* Die PSK-Kontakte in anderen Packungen als 20/10k.100Stk. wäre z.B. gut.1k auch. ||||| |&lt;br /&gt;
* Einpolige Steckerleiste 2.54 ||||| |||&lt;br /&gt;
* gängige Platinenverbinder einreihig RM 2mm mit 2-15 Kontakten (in vielen Geräten verwendet, z.&amp;amp;nbsp;B. [http://www.newproduct.molex.com/datasheet.aspx?ProductID=19945 Molex 51004, 53015]): ||||| Molex 71226 |||&lt;br /&gt;
* mehrpolige, hochwertige Miniatursteckverbinder (z.&amp;amp;nbsp;B. http://www.binder-connector.de/pdfs/serien/711.pdf) |||&lt;br /&gt;
* Molex C-Grid SL einreihig 2 bis &amp;gt;6 polig: Stecker, Buchsen, Buchsen-SMD, Crimp-Werkzeug |&lt;br /&gt;
* Nullkraftsockel (TEXTOOL, ARIES, Yamaichi,..) für 6-Pin SOT23 (SOT23-6) |||||&lt;br /&gt;
* Nullkraftsockel (TEXTOOL, ARIES, Yamaichi,..) für DIL20 ||||| |||||&lt;br /&gt;
* Nullkraftsockel (TEXTOOL, ARIES, Yamaichi,..) für DIL28 ||&lt;br /&gt;
* Nullkraftsockel (TEXTOOL, ARIES, Yamaichi,..) für PLCC-44 ||||| ||||| |||||&lt;br /&gt;
* Nullkraftsockel (TEXTOOL, ARIES, Yamaichi,..) für andere SO- oder TQFP-Gehäuse ||||| ||||| ||||| |||&lt;br /&gt;
* Platinensteckverbinder für Rastermass 2,00mm ||||&lt;br /&gt;
* Stapelleiste AMP 2–0827730–0, 20polig, A 24,2 mm |&lt;br /&gt;
* Stiftleisten im Rastermaß 1 mm (z.&amp;amp;nbsp;B.: Samtec FTMH-120-03-F-DV-ES) |&lt;br /&gt;
* Wannenstecker 2,54mm Raster auch als SMD ||||| ||||| ||&lt;br /&gt;
* Wannenstecker 6-Pol. gewinkelt, gibt nur gerade (WSL 6W, aber derzeit nicht lieferbar) ||||&lt;br /&gt;
* Wannenstecker (gerade) + Pfostensteckverbinder 6-Pol. (Pfostenbuchsen gibt es 6-Pol.) ( z.&amp;amp;nbsp;B. Harting SEK 18 Serie http://www.harting.com/en/en/de/sol/verbtech/prod/ios/description/03005/index.de.html) ||||| ||||| ||||| ||||| ||||| ||||| ||||&lt;br /&gt;
&lt;br /&gt;
=== (Steck-) Verbindungen sonstige ===&lt;br /&gt;
* Adapterprogramm SMA auf SMB ausbauen ||&lt;br /&gt;
* BNC-Stecker (wie UG 88U, Lötmontage) aber für RG174-Kabel ||||| |&lt;br /&gt;
* Chipkartenkontaktiereinrichtung, die die Kontakte anhebt (keine Schleifkontakte) ||||| ||||| |&lt;br /&gt;
* E10-Schraubsockel, wie sie Glühbirnen haben, mit Lötstiften (Achtung es ist nicht die Fassung gemeint) |||||&lt;br /&gt;
* Euro-Einbausteckdose (230V~, gab&#039;s früher mal) ||||| |||&lt;br /&gt;
* Foliensteckverbinder (FFC) RM1,25 (z.&amp;amp;nbsp;B. 9pol, 11pol ...) |||||&lt;br /&gt;
* Für LC-Displays: Adapterplatine mit Anschlüssen im Raster 2,54mm (EA 9907-DIP) siehe http://www.lcd-module.de/ ||||| ||||| ||||| ||||| ||||| ||||| |||&lt;br /&gt;
* Hohlstecker für Laptops 1,7 x 4,75mm gelb |||&lt;br /&gt;
* Hohlstecker für Acer-Laptops 1,7 x 5,5mm |&lt;br /&gt;
* Hohlstecker-Buchsen, ganz kleine, passend zu Handy-Netzteilen z.B.von Nokia |&lt;br /&gt;
* JST HR-Steckverbinder |||&lt;br /&gt;
* Lüsterklemmen kleiner LÜK 2,5, also z.B. LÜK 1,5: ||||&lt;br /&gt;
* Mini-Schraubklemmen Phoenix Contact MPT-Reihe RM2,54, z.B. MPT0,5/12-2,54 f. 12polig |||&lt;br /&gt;
* OBD-Stecker. |||||&lt;br /&gt;
* Polklemmen Hirschmann PKNI 10B (max. 63A), zumindest Schwarz und Weiß ||&lt;br /&gt;
* preiswerte! Hochspannungssteckverbinder &amp;gt;2kV ||||&lt;br /&gt;
* RP-SMA-Buchse/-Stecker (gewinkelt/gerade) ||||&lt;br /&gt;
* Schuko-Einbausteckdose (Maschinensteckdose) (mit oder ohne Klappdeckel); Flanschmaß möglichst klein (50mmx50mm); div. Farben (sw,grau,...) ||||| ||||| |||&lt;br /&gt;
* Steckverbinder für PICTIVA OLED-Display-Folienkabel |||||&lt;br /&gt;
* Triaxstecker /-buchse (Coax mit 2. Schirm als 3. Kontakt) ||&lt;br /&gt;
* Deutsche Stecker für PKW, LKW, LoF ||&lt;br /&gt;
&lt;br /&gt;
=== Kabel, Drähte etc. ===&lt;br /&gt;
&lt;br /&gt;
* angebotene Schaltlitze (H05VK, H07VK) um weitere Farben erweitern ||||| |&lt;br /&gt;
* das qualitativ mangelhafte 4mm Laborsteckerprogramm rausnehmen und nur noch Hirschmann anbieten  ||||| ||||| ||||| ||||| ||&lt;br /&gt;
* dickere Mantel(Feuchtraum)leitungen, z.&amp;amp;nbsp;B. NYM J5x10 |&lt;br /&gt;
* Distanzbolzen mit 2 M2,5-Innengewinden versch. Längen ||&lt;br /&gt;
* Dünner Schaltdraht (&amp;lt; 1mm Durchmesser, isoliert mit Tefzel oder Kynar)  {{Reichelt50|FF0000}}||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||&lt;br /&gt;
* Stinknormaler dünner Schaltdraht 0,3, 0,5 und/oder 0,75mm in verschiedenen Farben ||||&lt;br /&gt;
* Flachbandkabel im 1,00mm-Raster, passend für Pfostenverbinder PL 2X25G 2,00 . Wird für Notebookplatten benötigt. Ohne das ist die gesamte 2,0mm-Wannensteckerproduktgruppe sinnlos. ||||| |||&lt;br /&gt;
* Flachbandkabel im 1,27 mm-Raster, 6-polig |||&lt;br /&gt;
* Flachbandkabel im 2,54mm-Raster und dazu passende Aufpressstecker und -buchsen ||||| ||||| ||||| ||||| ||||| ||||&lt;br /&gt;
* Flexible Einzellitze, 0,5² in verschiedenen Farben ||||| ||||| ||||| ||||| ||||| |||||&lt;br /&gt;
* Folienflachkabel (FFC) RM 0,8 (z.&amp;amp;nbsp;B. 30pol., Länge 125mm) für 8&amp;quot; TFT-Monitor&lt;br /&gt;
* Folienflachkabel (FFC) RM1,25 (z.&amp;amp;nbsp;B. 9pol, 11pol ... /Länge 20cm) ||&lt;br /&gt;
* Heizdraht zB.: Kanthal A1  ||||| ||&lt;br /&gt;
* hochwertige MicroUSB-Kabel (AK 676-AB rupft einem fast die Buchse aus dem Handy) ||&lt;br /&gt;
* Kupferlackdraht auf Spulen statt lose (Artikelbild ist irreführend!) |||||&lt;br /&gt;
* kurze (10cm, 30cm, 50cm)-Kabel zB.: USB A-&amp;gt;B, A-&amp;gt;Bmini, A-&amp;gt;Bmicro; Klinke/Cinchkabel |||&lt;br /&gt;
* Litze, LiY 0,25mm^2, diverse Farben (beispielsweise von Lapp Kabel) |&lt;br /&gt;
* Low-Loss-Kabel (evtl. aus diesem Programm http://www.elspec.de/hf-kabel-technologie/download-hf-technik/hf-lowloss-kabel.html)&lt;br /&gt;
* LYIF-Litze (verschiedene Farben) ||||| |&lt;br /&gt;
* PATCHKABEL xx WS: Cat5 Patchkabel SF/UTP auch in weiß (deutlich dünner, flexibler und auch günstiger als die Cat6 PiMF) |&lt;br /&gt;
* RG214 |&lt;br /&gt;
* Schnepp &amp;quot;Laborkabel&amp;quot;-Messleitungen ||||| |&lt;br /&gt;
* versilberten Kupferdraht auch &amp;lt; 0,6mm und alle Stärken in grösserer VPE (z.&amp;amp;nbsp;B. 500g-Rolle) ||||| ||||| ||||| |&lt;br /&gt;
* Zwillingslitze 2x0.14mm, z.&amp;amp;nbsp;B.  Artikel: ZL214SWW-10M Kessler Elektronik ||||| |||||&lt;br /&gt;
&lt;br /&gt;
=== Gehäuse und Gehäusetechnik ===&lt;br /&gt;
&lt;br /&gt;
* Batteriehalter für 18650er Lithiumzellen (ähnlich dealextreme sku 100996/100997/100999) ||||&lt;br /&gt;
* Batteriehalter für 4 Mignonzellen mit Lötfahne (statt Druckknopf)  ||&lt;br /&gt;
* Bopla ABP oder ABPH 800-100 (10cm) Aluprofil Gehäuse |||&lt;br /&gt;
* Distanzbolzen M2,5 (SW4) in verschiedenen Längen aus Messing ||&lt;br /&gt;
* Distanzhülsen/-bolzen M3 in verschiedenen Längen aus Kunststoff |&lt;br /&gt;
* mehr und v.a. kleine (Hand-) Gehäuse  {{Reichelt50|FF0000}}||||| ||||| |||&lt;br /&gt;
* Muttern M2 |||&lt;br /&gt;
* Preiswertere Alu Druckgussgehäuse, wie z.&amp;amp;nbsp;B. von Hammond Manufacturing ||||| ||||| ||||| |||&lt;br /&gt;
* Stopmuttern M2 |&lt;br /&gt;
* Strangpreßprofilgehäuse von Fischer |&lt;br /&gt;
* USB-Leergehäuse (z.&amp;amp;nbsp;B. wie USB-Stick, WLAN-Dongle, o.ä.) ||||| ||||| ||||| ||||| |&lt;br /&gt;
* Zylinderkopfschrauben M2,5 x 12mm |||||&lt;br /&gt;
* Zylinderkopfschrauben M2,5 x 20mm |||||&lt;br /&gt;
* Zylinderkopfschrauben M2,5 x 30mm |||||&lt;br /&gt;
* Zylinderkopfschrauben M3 x 25mm ||||| |&lt;br /&gt;
&lt;br /&gt;
== Prototypenbau, Platinen und Chemie ==&lt;br /&gt;
&lt;br /&gt;
* Adapter QSOP (versch. Pinzahlen) auf DIL/QIL ||||| ||||| |||&lt;br /&gt;
* Adapter TQFP (versch. Pinzahlen) auf DIL/QIL ||||| ||||| ||||| ||||| ||||| | ||||| ||||| ||||| |&lt;br /&gt;
* Arbeitsschalen zum Entwickeln und Ätzen von Platinen(*)(ist im Starterkit enthalten) ||||| ||||| ||||| ||||| ||&lt;br /&gt;
* Ballistol Universalöl ||||| ||||&lt;br /&gt;
* Bungard Green Coat ||&lt;br /&gt;
* Bungard Sur-Tin ||&lt;br /&gt;
* Bungard-Fotoplatinen auch in 80x100mm (halbes Euroformat), nicht nur 75x100mm ||||| ||||| ||||| |||||&lt;br /&gt;
* Bungard-Fotoplatinen BLAU div. Formate ||||| ||||| ||||| ||||||&lt;br /&gt;
* Bungard-Fotoplatinen SCHWARZ div. Formate |&lt;br /&gt;
* Cadsoft Eagle ||||| ||||| ||&lt;br /&gt;
* chemisches Zinnbad ||||| ||||| ||||| |||||&lt;br /&gt;
* Entwickler NaOH-Frei von Bungard (SENO 4007 Universalentwickler) ||&lt;br /&gt;
* Fotoplatinen aus Hartpapier von Markenhersteller ||&lt;br /&gt;
* Fotoplatinen, zweiseitig, Hartpapier(!) |||||&lt;br /&gt;
* Hohlkehlenlötspitzen (Ersa 0832HD) ||||| |&lt;br /&gt;
* Hohlkehlenlötspitzen f. Weller MLR21 ||||| |||||&lt;br /&gt;
* Kapton-Baender, evtl auch mit Kupferbeschichtung (Flex-PCB) |||||&lt;br /&gt;
* Lötstopplaminat ||||| ||||| ||||| ||||| ||||| ||||| |||&lt;br /&gt;
* LPKF Durchkontaktierungspaste |||&lt;br /&gt;
* Messingblech/Kupferblech 0.1mm (wenn möglich Photobeschichtet) |||||&lt;br /&gt;
* Natriumpersulfat 2 kg Packung ||||| ||&lt;br /&gt;
* PCI-Express x1 Laborkarte (wie RE 430EP) ||&lt;br /&gt;
* PIC_BASIC_II || Programm mit HardwareKey [z.&amp;amp;nbsp;B. für Azubi&#039;s]&lt;br /&gt;
* SMD Testplatine (3x3 Felder) wie bei Conrad |||&lt;br /&gt;
* SOIC auf PDIP Gehäuse-Adapter zwecks Prototypen-Bau ||||| ||||| ||||| ||||| ||||| ||||| ||||| |||||&lt;br /&gt;
* Spitzenhülsen WSP-/MPR 80 (Weller) ||&lt;br /&gt;
* Steckplatinen (Breadboards) ohne Grundplatte und ohne Versorgungsleiste (wie Conrad 526827; STECKBOARD 1K2V hat beidseitig Leisten und ist daher nicht anreihbar / ist anreihbar, aber danach sind die beiden Leisten jeweils übrig) |&lt;br /&gt;
* Steckplatinenen (STECKBOARDS) im 84 x 54 Format (gibts bei Conrad ist da aber viel zu teuer) |||&lt;br /&gt;
* Target 3001 V15 Autorouter verschiedene Lizenzen |&lt;br /&gt;
* Tonerverdichter (www.Huber-Troisdorf.com) ||||| ||||| ||||| ||||| ||||| |||&lt;br /&gt;
* www.schmartboard.com hat super einfach zu lötende SMD-Adapter in allen Größen, nur leider keinen Vertriebspartner in Deutschland (doch: ELV (wo?)). Wie wäre es mit Reichelt? ||||| ||||| ||||| ||||| ||||| ||||| |||||&lt;br /&gt;
* Blanko Katalogseiten &amp;quot;weiß&amp;quot; für die Toner direkt Methode (oder 2-3 Seiten im Katalog leer lassen) ||&lt;br /&gt;
&lt;br /&gt;
== Werkzeug und Zubehör ==&lt;br /&gt;
&lt;br /&gt;
* einzelne Hartmetallbohrer in diversen Grössen (z.&amp;amp;nbsp;B. 0,8 1,0 1,3 1,5) {{Reichelt50|FF0000}}||||| ||||| |&lt;br /&gt;
* ESD-Erdungspunkte 4mm/10mm für Schuko, wie Vermason J6100 (alt) / 231125 (neu) ||&lt;br /&gt;
* Gewindebohrer M2 und M2,5 ||||| ||||| ||&lt;br /&gt;
* hochwertige 9mm Abbrechklingen ||&lt;br /&gt;
* Konturenfräser/Gravurstichel, etc. zum Fräsen von Platinenprototypen (z.&amp;amp;nbsp;B. Bungard G60N/G30N) ||||| ||||| ||&lt;br /&gt;
* M2 Gewindebohrer und Senker |||&lt;br /&gt;
* robuste Allzweck- und Teppichmesser ||||| ||||&lt;br /&gt;
* Sortimentskasten H1 und evtl. H2-Serie ||&lt;br /&gt;
* Tri-Wing Schraubendreher ||||&lt;br /&gt;
* Torx tamper resistant/tamper proof (die mit Loch) als Set und in Aufbewahrungsbox |&lt;br /&gt;
* zöllische Gewindeschneider g1/4&amp;quot; und g 1/8&amp;quot; insbesondere interessant für Wasserkühlungen ||||| ||||&lt;br /&gt;
&lt;br /&gt;
== Messgeräte, Diagnose und Stromversorgung ==&lt;br /&gt;
&lt;br /&gt;
* FS300 Messgerät Antennenanalyzer Massenpreis 50000 Stück ||&lt;br /&gt;
* Günstigere Oszilloskope z.&amp;amp;nbsp;B. Multimetrix oder Grundig ||||| ||||| |&lt;br /&gt;
* LiPoly-Zellen (aufladbare Lithiumakkus, &amp;quot;Suppentüten&amp;quot; oder prismatische Zellen) ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| |||&lt;br /&gt;
* Neuere, bessere NiMH-Akkus (z.b. GP1100 2/3A, GP2000 AF, GP2200 4/5SubC) ||||| ||||| ||&lt;br /&gt;
* OBD2 Kabel auf RJ45 Stecker |||||&lt;br /&gt;
* Smart Tweezer (SMD-Pinzette mit Komponentenmessung) siehe [http://www.trgcomponents.de/TrgDE/Internet/ProductShow.aspx?ItemID=680&amp;amp;CategoryID=2426] ||||&lt;br /&gt;
* Tektronix TDS Series Osziloskope |||&lt;br /&gt;
* Vorschaltgeräte mit G23 Fassung (zum Bau von UV-Belichtern geeigent)|||&lt;br /&gt;
&lt;br /&gt;
== Auswahl, Bestellung und Versand ==&lt;br /&gt;
&lt;br /&gt;
* bei über 10kg Gewicht nicht gleich die Versandkosten verdoppeln, sondern geringerer oder keinen Aufschlag ||||&lt;br /&gt;
* der Reichelt Katalog auf CD/DVD (durch pdf-download überflüssig:) |||||&lt;br /&gt;
* Filialen in Österreich  und der Schweiz :-) {{Reichelt50|FF0000}}||||| (man beachte das &amp;quot;:-)&amp;quot;, es gibt auch in D keine &amp;quot;Filialen&amp;quot; - mt)|&lt;br /&gt;
* Günstige Versandkonditionen für die EU ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| |&lt;br /&gt;
* In Bereichen wie Multimedia etc. (z.&amp;amp;nbsp;B. Spielekonsolen) ein aktuelleres Angebot, und nicht wie z.&amp;amp;nbsp;B. bei der PS2 erst wenn schon fast das Nachfolgemodell draussen ist (Multimedia ist hier nur ein Beispiel, einfach mal an der Konkurrenz orientieren (Zum beispiel am grossen C) |&lt;br /&gt;
* Kein Mindestbestellwert (ich bezahle eh&#039; Porto) ||||| ||||| ||||| |||| ||||&lt;br /&gt;
* Kundenkarte so wie bei ELV (Grundgebühr für ein Jahr, keine Versandkosten, evtl kleiner Rabatt) {{Reichelt50|FF0000}}{{Reichelt50|00FF00}}||||| ||||| ||||&lt;br /&gt;
* mehr Verpackungsmaterial z.&amp;amp;nbsp;B. kleine Schachteln oder die Plastik IC-&amp;quot;Schienen&amp;quot; einzeln (und unzerschnitten) verkaufen ||||| ||||| |&lt;br /&gt;
* Möglichkeit für Selbstabholen eine Bestellung unter 10 Euro abzuliefern.  |&lt;br /&gt;
* Nicht so viele Tackerklammern/Gummibänder/Tesafilm/Beutel in die Verpackungstüten machen, das nervt beim Auspacken (die kaputten Tüten kann dann auch keiner mehr brauchen, die wenigen nicht kaputt getackerten hebe ich aber gerne auf! Aber bitte weiterhin alles getrennt verpacken... oder wenigstens nicht den Zip-Verschluss tackern) {{Reichelt50|FF0000}}||||| || &lt;br /&gt;
* nicht wie die Konkurrenz jetzt schon im April den Juli-Katalog rausbringen ||||| ||||| ||||| |||&lt;br /&gt;
* Parametrische Suche aller Elektronikartikel, speziell erstmal Halbleiter, so wie bei Maxim-ic.com ||||&lt;br /&gt;
* Reichelt Katalog als PDF zum Download (siehe [[Reichelt PDF Katalog]] ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||&lt;br /&gt;
* Reichelt-Gutscheine sollten bei Online-Bestellung einlösbar sein (wie bei z.&amp;amp;nbsp;B. Amazon) ||||| ||||| |||||&lt;br /&gt;
* Selbstabholer-Option bei der Bestellung. Vergisst man es unter &amp;quot;Bemerkung&amp;quot; kommt es per Post :(   ||||  (für Plz 26xxx kommt eine Option für Abholer, Tip: falsche Plz eintragen)&lt;br /&gt;
* Skalierbarer Warenkorb für mehrfachen Aufbau gleicher Platinen |||&lt;br /&gt;
* Sortieren und Spezifizieren der Angebotsliste in Transistoren / FET (bessere Übersicht) ||||| ||||| ||||| ||||| || z.&amp;amp;nbsp;B. 400V/6A würde schonmal ganz grob helfen und senkt außerdem unnötigen Traffic, weil nicht extra jedes Datenblatt angeschaut wird&lt;br /&gt;
* Versand von Kleinteilen als Maxibrief, zwecks niedrigerem Versand {{Reichelt50|FF0000}}||||| ||||| ||||| ||||&lt;br /&gt;
* Warenkorb immer in gleicher Reihenfolge sortiert, nicht bei jedem Aufruf anders ||||| ||||| ||||&lt;br /&gt;
*Vergleichen von Ergebnissen einer Suchanfrage möglich machen |&lt;br /&gt;
&lt;br /&gt;
== Unsortiert/Unspezifisch ==&lt;br /&gt;
&lt;br /&gt;
* mehr, aber als solche gekennzeichnete billig-Alternativprodukte, nicht nur High-End ||||| |&lt;br /&gt;
* Modellbau und Zubehör ||||| ||||| ||||| ||| (Wird immer mehr, man sieht, Reichelt hört dankenswerterweise auf diese Wishlist!!)&lt;br /&gt;
* Toner für Laserdrucker Kyocera FS-1010 TK17 ||||| |  ist ja eigentlich der gängigste Kyocera Toner&lt;br /&gt;
* Toner für Kyocera FS800-S |&lt;br /&gt;
* Speicherkarten-Adapter von SD auf CF (bzw. CFII) |||||&lt;br /&gt;
* ein Abendessen mit Angela :-) (hier dürfte wohl Angelika gemeint sein) ||| bzw. mit der Blondine von der Katalogseite mit den Servicenummern |||&lt;br /&gt;
* Beamer Casio YC-400 |&lt;br /&gt;
* PCMCIA Wlan-Karten (Linux kompatibel) mit externem Antennenanschluss |&lt;br /&gt;
* Reichelt T-Shirt ||||| ||||| ||&lt;br /&gt;
* Röhrensortiment mit den wichtigsten Typen wie z.B. EL34; KT88 einführen + Sockel |||&lt;br /&gt;
* Produktmanager, die des Deutschen mächtig sind. Die Rechtschreibung / Grammatik der Produktbeschreibungen ist eine Katastrophe. ||||&lt;br /&gt;
&lt;br /&gt;
= Bereits im Sortiment =&lt;br /&gt;
&lt;br /&gt;
* Laser-Folien für die Druckformerstellung(Zweckform 3491) ||||| ||||| ||||| ||||| ||||| ||||&lt;br /&gt;
* Atmel AT91SAM7S32 53x gewünscht  (=&amp;gt; Best.: AT 91SAM7S64-AU)&lt;br /&gt;
* Atmel AT91R40008 (32bit controller 256KB-RAM 100-lead TQFP) ||||| ||||| |  (=&amp;gt; Best.: AT 91R40008)&lt;br /&gt;
* LCD: auch ein- und dreizeilige Variante der DOG-Serie (EA DOGM081 &amp;amp; 163) |||||&lt;br /&gt;
* Platinen Basismaterial, einseitig Cu-beschichtet, 0,5..1 mm dick ||||| ||||| ||| --&amp;gt;0,8mm: BEL 160x100-1-8&lt;br /&gt;
* Atmel ATtiny45 ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| =&amp;gt; ATTINY 45-20PU, ATTINY 45-20SU, ATTINY 45V-10PU, ATTINY 45V-10SU&lt;br /&gt;
* Atmel ATMEGA48 TQFP ||||| |||| =&amp;gt; ATMEGA 48-20 AU&lt;br /&gt;
* Atmel ATMEGA 88 || =&amp;gt; ATMEGA 88-20 AU, ATMEGA 88-20 PU, ATMEGA 88V-10 AU, ATMEGA 88V-10 PU&lt;br /&gt;
* Atmel ATMEGA644 ||||| ||||| ||||| ||||| =&amp;gt; ATMEGA 644-20 AU, ATMEGA 644-20 PU, ATMEGA 644V-10AU, ATMEGA 644V-10MU, ATMEGA 644V-10PU&lt;br /&gt;
* Atmel ATMEGA2560 ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| || =&amp;gt; ATMEGA 2560-16AU, ATMEGA 2560V-8AU&lt;br /&gt;
* Atmel ATMEGA2561 ||||| | =&amp;gt; ATMEGA 2561-16AU, ATMEGA 2561V-8AU&lt;br /&gt;
* Philips LPC2000-Serie ARM7-Controller (LPC214x, LPC213X, LPC21xx und LPC22xx) 57x gewünscht =&amp;gt; Bauelemente, aktiv / Controller, Speicher / Controller, Prozessoren / Philips-Controller 80C51 / 87LPC.. / 89C51&lt;br /&gt;
* TI MSP430F2xxx (Typen mit 16 MIPS) ||||| ||||| | =&amp;gt; Bauelemente, aktiv / Controller, Speicher / Controller, Prozessoren / Texas MSP430 Controller&lt;br /&gt;
* Breadboards/&amp;quot;Steckbretter&amp;quot; 115x gewünscht =&amp;gt; STECKBOARD 1K2V, STECKBOARD 2K1V, STECKBOARD 2K4V, STECKBOARD 3K5V, STECKBOARD 4K7V (zu finden unter &#039;Diverses/Spielwaren&#039; :)&lt;br /&gt;
* RS485 ESD fest: MAX3086E oder 75180 oder ISL83086E ||||| || =&amp;gt;MAX485ECPA &lt;br /&gt;
* Microchip PIC 18F2550  || =&amp;gt; PIC 18F2550-I/P&lt;br /&gt;
* Microchip PIC 16F88  ||||| | =&amp;gt; PIC 16F88-I/P&lt;br /&gt;
* Microchip dsPIC ||||| ||||| ||||| ||||| | =&amp;gt; PIC 30F2010-30 SP/SO&lt;br /&gt;
* Logicanalyzer | =&amp;gt; ME ANT 8 und ME ANT 16&lt;br /&gt;
* Atmel ATMEGA8 TQFP |||| =&amp;gt; ATMEGA 8-16 TQ&lt;br /&gt;
* 3,3V Laengsregler (LT1086-Serie z.&amp;amp;nbsp;B.)  ||||| =&amp;gt; vgl z.&amp;amp;nbsp;B. [http://reichelt.de/?ARTIKEL=LT%201086%20CM3%2C3 LT 1086 CM3,3] (SMD) oder [http://reichelt.de/?ARTIKEL=LT%201086%20CT3%2C3 LT 1086 CT3,3] (TO-220) bei Reichelt&lt;br /&gt;
* Flexible Messleitungen: Wie gesagt Reichelt bietet ja die ganze Palette an Bananen/Laborsteckern, Krokodilklemmen usw. an, nur die Leitungen dazu fehlen im Programm.  (Sind schon im Sortiment. Fertig konfektionierte z.&amp;amp;nbsp;B.: ML 100 SW, Meterware z.&amp;amp;nbsp;B.: MESSLEITUNG 10SW)&lt;br /&gt;
* FTDI USB Chips  ||||| ||||| ||||| ||||| ||||| ||| =&amp;gt; Best-Nr. FT232BL, FT232RL (sehr interessant), FT245BM und FT2232BM (2xUART auf USB)(noch nicht unter USB einsortiert)&lt;br /&gt;
* CAN-Bus Controller MCP2515  |||||&lt;br /&gt;
* VLSI MP3 Decoder  ||||| ||||| ||||| | z.Zt. unter CAN-Bus(!) einsortiert. Bitte auch die neuen Gehäuse (ROHS) und Typen mit ins Angebot nehmen.&lt;br /&gt;
* Atmel AT90CAN128 ||||| |&lt;br /&gt;
* MMC / SDC slot 50x gewünscht ==&amp;gt; Bestell-Nr.: CONNECTOR MMC 11, CONNECTOR MMC 12, CONNECTOR SD 21 und CONNECTOR SD 22&lt;br /&gt;
* lineare Potentiometer als Schiebepoti ||||| | - Bestell-Nr. PSM-LIN* (&amp;quot;mono&amp;quot;) PSS-LIN* (&amp;quot;stereo&amp;quot;)&lt;br /&gt;
* Echtzeituhr DALAS DS1307 (auch SMD) ||||| || - Bestell-Nr. DS1307/DS1307Z&lt;br /&gt;
* Konkret: Neuer PIC ... und PIC18F2550 ||||| ||| &lt;br /&gt;
* MSP430F1232 |&lt;br /&gt;
* Fädelstift, Draht und Kämme ||||| ||| - Bestell-Nr. Fädelstift/Fädeldraht/Fädelkamm (Warum sind diese Stifte ùnd der Draht nur so &amp;quot;erschreckend&amp;quot; teuer? =&amp;gt; immerhin billiger als bei C...) (vielleicht weil jeder die nur 1x kauft und dann mit Draht aus anderen Quellen selber neu bewickelt?? ;-)&lt;br /&gt;
* Mini-GPS-Module ||||| ||||| ||||| ||||| ||| - Bestell-Nr. GPS ET 102/GPS ET 202/GPS EM 401&lt;br /&gt;
* Atmel ATmega48, ATmega168, ATtiny13 ||||| ||||| ||||| | (im neuen katalog und online verfügbar!)&lt;br /&gt;
* CompactFlash Stecker ||||| ||||| ||||| || - Bestell-Nr. connector CF 01/ Connector CF 02 &lt;br /&gt;
* DCF77 Empfangsmodule 60x gewünscht (DCF77 Modul) (4.5.2005 ist jetzt verfügbar unter DCF77 MODUL, aber leider 50% teurer als bei der Konkurenz, störempfindlicher, grotesk schwache Ausgangstreiber)&lt;br /&gt;
* Microchip PIC 12F683 (8pin PIC mit PWM !) =&amp;gt; Bereits im Sortiment: Best. Nr PIC 12F683-I/P bzw. PIC 12F683-I/SN &lt;br /&gt;
* MSP430F135 ||||| ||||| ||||| |  (MSP430F135 im Programm Bestellnr.: MSP430F135 IPM)&lt;br /&gt;
* SMD 0Ω in Bauform 0805 |||| -&amp;gt; SMD-0805 0,00&lt;br /&gt;
* Shunt-Widerstände  ||||| ||||| ||||| ||||| |  (neu im Sortiment: Widerstandsdraht, Best.-Nr. &amp;quot;RD100/x,xx&amp;quot;, Leider nur in teuren 100g Spulen)&lt;br /&gt;
* dünner isolierter Draht, wie Klingeldraht nur dünner, vielleicht 0.2-0.3mm zum Fädeln von Platinen |||| =&amp;gt; Fädeldraht nun im Sortiment&lt;br /&gt;
* dünner Silberdraht zur Verdrahtung auf Lochrasterplatinen ||||| |   (mögl. bereits im Sortiment &amp;quot;SILBER 0,6MM&amp;quot; ???)Kupferlackdraht geht nicht?&lt;br /&gt;
* Hartmetallbohrer in mehr verschiedenen Größen (z.&amp;amp;nbsp;B. 0,6mm 0,8mm 1,1mm 1,2mm etc.) ||||| |||| =&amp;gt; Gibt es beides Bestellnummern: &amp;quot;Bohrerset&amp;quot; oder für einzelne Bohrer &amp;quot;Bohrer + Größe in mm&amp;quot; Bsp: &amp;quot;Bohrer 0,6&amp;quot; =&amp;gt; die kosten aber einiges, eine etwas preiswertere Alternative wäre auch nicht schlecht...&lt;br /&gt;
* 68HC908GP32 |&lt;br /&gt;
* überhaupt: Freescale 68HC908- und vor allem 68HCS08-Mikrocontroller fehlen total im Sortiment!&lt;br /&gt;
* RJ45-Buchse ||| - schon im Sortiment: MEBP 8-8&#039;&#039;x&#039;&#039; unter Modular-Stecker bei TK&lt;br /&gt;
* Elektromotoren ||||| |||| (Suche: Gleichstommotor)&lt;br /&gt;
* Microchip ICD2 || =&amp;gt; Bestell-Nr.: DV 164005 &amp;lt;= Fehlt im Papierkatalog&lt;br /&gt;
* 14,7456 MHz Quarze ||||| ||||| ||||| ||||| ||| (Bst: 14,7456-HC18)&lt;br /&gt;
* SMD Widerstande in Bauform 1206 (SMD 1/4W...)&lt;br /&gt;
* Atmel Atmega 128 in TQFP || (ATMEGA 128-16 TQ)&lt;br /&gt;
* Atmel Atmega 169 in TQFP || (ATMEGA 169-16 TQ)&lt;br /&gt;
* Atmel ATMEGA1280 ||||| ||||| ||||| |||| (ATMEGA 1280-16AU, ATMEGA 1280V-8AU)&lt;br /&gt;
* Atmel ATMEGA8515 | (ATMEGA 8515-*)&lt;br /&gt;
* Atmel ATtiny24/44 ||||| ||||| (ATTINY 24-*, ATTINY 44-*)&lt;br /&gt;
* Atmel ATtiny25/85 ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| | (ATTINY-25-*, ATTINY-85-* gelistet aber erst verfuegbar ab II/07)&lt;br /&gt;
* Atmel AT91SAM7S64, AT91SAM7S256 ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| |||| (suche AT91*)&lt;br /&gt;
* Atmel AT91SAM7X64-256 ||||| ||| (suche AT91*)&lt;br /&gt;
* TI MSP430F1611 (10k RAM, 48k Flash) ||||| ||||| ||||| ||||| ||||| ||||| || (MSP430F1611 IPM)&lt;br /&gt;
* PCA9306  Dual Bi-Directional I2C-Bus and SMBus Voltage Level-Translator ||&lt;br /&gt;
* PCA9531D  8Bit I2C_BUS LED-Dimmer ||||| |||||&lt;br /&gt;
* PCA9551D  8Bit I2C-BUS LED-Blinker ||||| ||||&lt;br /&gt;
* PCA9530D  2Bit I2C_BUS LED-Dimmer ||||| |&lt;br /&gt;
* PCA9532D 16Bit I2C_BUS LED-Dimmer ||||| |||||&lt;br /&gt;
* PCA9533D  4Bit I2C_BUS LED-Dimmer ||||| ||||&lt;br /&gt;
* PCA9550D  2Bit I2C-BUS LED-Blinker ||||| |&lt;br /&gt;
* PCA9553D  4Bit I2C-BUS LED-Blinker ||||| ||&lt;br /&gt;
* PCA9552D 16Bit I2C-BUS LED-Blinker ||||| |||&lt;br /&gt;
* Microchip PIC 18F2550 (USB, 32 KBytes Flash) | (bereits im Sortiment)&lt;br /&gt;
* Microchip PIC 16F628A (weil: besser als 16F628) ||||&lt;br /&gt;
* Microchip PIC 16F648 (weil mehr Programmspeicher, als 16F628) |||||&lt;br /&gt;
* Microchip PIC 16F684 ||||| &lt;br /&gt;
* Microchip PIC 16F688 ||||| ||&lt;br /&gt;
* Microchip PIC 16F690 ||||| ||||| |||&lt;br /&gt;
* Atmel ATtiny84 ||||| ||||| |||| (gelistet aber erst verfuegbar ab II/07)&lt;br /&gt;
* TI MSP430F169 |&lt;br /&gt;
* FT245RL (alt bekannte FTDI Chips in neuer und besserer Version, FT232RL bereits vorhanden) ||||| ||&lt;br /&gt;
* 3,3V Längsregler SMD Ultra Low drop |||| (-&amp;gt; Zetex)&lt;br /&gt;
* Schiebepotis mit passenden Knöpfen | (Bestell-Nr. PSM-LIN* (&amp;quot;mono&amp;quot;) PSS-LIN* (&amp;quot;stereo&amp;quot;) nicht passed?) |&lt;br /&gt;
* OLED-Displays (zum Beispiel: [http://www.litearray.com/products-oled.php]) || (Reichelt hat jetzt Osram Pictiva Oleds im Programm. Nach &amp;quot;Pictiva&amp;quot; suchen)&lt;br /&gt;
* OSRAM &amp;quot;Golden Dragon&amp;quot; LEDs (http://www.osram-os.com/goldendragon) ||||&lt;br /&gt;
* Microcontroller mit USB-Anschluss (von Cypress oder Atmel in PDIP z.&amp;amp;nbsp;B. AT89C5131, AT43USB355, CY7C637xx) ||||| ||||| ||||| ||||| |||||  -&amp;gt;Bereits im Sortiment: Cypress EZ-USB TQFP-44 Best. Nr AN2131 SC, Atmel AT89C5131 SO-28/PLCC-52&lt;br /&gt;
* Renesas R8C &lt;br /&gt;
* zu Schaltreglern LM257x u.a. passende Speicherspulen mit hohem L , niedrigem R und großer Strombelastbarkeit (zB. Würth WE-PD4) (keine &amp;quot;Entstörspulen&amp;quot;) 96x gewünscht (suche L-PIS*)&lt;br /&gt;
* IL300 (linear Optokoppler z.&amp;amp;nbsp;B. von Vishay egal ob DIP oder SMD) ||||| ||||&lt;br /&gt;
* IL300H (linear Optokoppler von Siemens als DIP) - andere IL300 Varianten im Programm |||&lt;br /&gt;
* &amp;quot;optische&amp;quot; Drehgeber Fabrikat Grayhill sind lieferbar (Bst. ENC 62P22-*)&lt;br /&gt;
* mechanische Drehimpulsgeber von Alps im Programm (suche STEC*)&lt;br /&gt;
** Drehimpulsgeber (konkreter Vorschlag von O.R.: PEC16-4220F-S0024 von Bourns) 173x gewünscht&lt;br /&gt;
** Drehimpulsgeber- weiterer Vorschlag: ALPS Encoder ST EC 11B  64x gewünscht Im Programm (STEC11B01)&lt;br /&gt;
* PCA9633D16 4-bit I2C-bus LED driver ||&lt;br /&gt;
* I²C-Bus to 1-Wire DALLAS DS2482-100 bzw. DS2482-800  ||||| ||||| ||||| ||||| ||||| ||||&lt;br /&gt;
* Step-Down-Konverter in SMD Bauform (z.b. MC 34063): ||||| (-&amp;gt;Artikel-Nr: MC 34063 AD)&lt;br /&gt;
* Preiswerte Kontaktierungen für SD/MMC  ||| (Bereits im Programm: Bestell-Nummern:  CONNECTOR MMC 11 / CONNECTOR MMC 12 / CONNECTOR SD 21 / CONNECTOR SD 22) // ~9 EUR sind wohl kaum preiswert!&lt;br /&gt;
* Eisen(III)-Chlorid  115x gewünscht&lt;br /&gt;
* EA DOG-M128 128x64 Grafikdisplay aufbau ähnlich EA DOGM162 |||||&lt;br /&gt;
* 3,3V-Längsregler SMD zu vernünfitgen Preisen (Bsp: LF33 --&amp;gt; Best.Nr.: LF 33 CV, Preis: 0,76&amp;amp;#8364;)(der LT1086 kostet 4 Euro) ||||| ||||| ||||| ||||| |||||	||||| ||||| ||||| || -&amp;gt; LT1117 CST-3.3V für 1.55 €&lt;br /&gt;
* Spannungsregler in SMD-Version (7805 etc., nicht nur der 78L05) ||||| ||||| ||||| ||||| ||||| ||||| ||| -&amp;gt; LT1117-ADJ für 1.55€&lt;br /&gt;
* TSic Temperatursensoren von ZMD ||| -&amp;gt; TSIC&lt;br /&gt;
* Leiterplattenbuchse Hirschmann 4mm auch in *rot* (gab es schonmal als &amp;quot;PB 4 RT) || -&amp;gt; wieder als PB 4 RT erhältlich, letzte Woche 3 Stück geliefert bekommen; Stückpreis 1,25€&lt;br /&gt;
* MCP25050 CAN-Bus Input/Output Expander ||||| |||| (MCP 25050-I/*)&lt;br /&gt;
* Ethernet-Controller RTL8019AS 337x gewünscht (erhältlich: RTL 8019AS)&lt;br /&gt;
* SPI-Ethernet-Controller ENC28J60 (erhältlich: ENC 28J60-I/*)&lt;br /&gt;
* Microchip PIC 18F4550 (PIC mit USB) ||||| ||||| ||||| ||||| ||||| ||||| |||&lt;br /&gt;
* Microchip PIC 18F2585 ||||&lt;br /&gt;
* gleicher Mindestbestellwert in Österreich und in der Schweiz wie in Deutschland &#039;&#039;&#039; Seit 1.12.10 umgesetzt&#039;&#039;&#039; ||&lt;br /&gt;
* gleicher Mindestbestellwert in den Niederlanden wie in Deutschland | (mittlerweile überall 10€)&lt;br /&gt;
* Versand nach Österreich über GLS oder sonstigen Paketdienst &amp;amp; auf Rechnung, damit die Spesen halbwegs im Rahmen bleiben (bei der letzten Bestellung ca. EUR 40) ||||| ||||| ||||| ||||| ||||| ||||| ||| &#039;&#039;&#039;Anm.: Versand nach AT inzwischen ab 9,90&#039;&#039;&#039;&lt;br /&gt;
* Pakete nach Österreich in EINER Lieferung schicken, und nicht aus &amp;quot;logistischen Gründen&amp;quot; trennen. Würde zumindest die Hälfte der Verandkosten sparen (letztes mal fast 70€ pro Paket (!) ||&lt;br /&gt;
* Digitale Speicherosziloskope für PC ||||| ||||| || (Picoscope, PC-Oszilloskop)&lt;br /&gt;
* Hameg HM2008 Oziloscope || ( ist möglich über Service -&amp;gt; Produktservice -&amp;gt; neue Artikel anfragen)&lt;br /&gt;
* Microchip dsPIC30F ||||| ||||| |||&lt;br /&gt;
* Microchip PIC 16F883 und 16F886 |||&lt;br /&gt;
* Microchip PIC 18F4523 (12/2007: PIC mit 12-Bit A/D-Wandler) ||&lt;br /&gt;
* Microchip PIC 18F6585 |&lt;br /&gt;
* Microchip PIC 18F6720 |&lt;br /&gt;
* Microchip PIC 18F8720 |&lt;br /&gt;
* Microchip PIC 24FJ64GB002-I/SP (USB-OTG im DIP28 Gehäuse) |&lt;br /&gt;
* Atmel XMega-Typen, z.B. ATXMega64A4, ATXMega128A1 ||||| ||&lt;br /&gt;
* 7-Segment-Anzeige, blau, gem. Kathode ||||| ||||| ||||| ||||| ||||| ||||| || (SC 52-11 BL)&lt;br /&gt;
* 7-Segment-Anzeige, blau, gem. Anode ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| ||||| |||| (SA 52-11 BL, SA 56-11 BL)&lt;br /&gt;
* EA DOG-L128 128x64 Grafikdisplay zzgl Touch-Folie und Beleuchtung | --&amp;gt; ist ab Katalog 06/2009 drinn&lt;br /&gt;
* LTC 1661 N8 10 Bit Dual Dac mit SPI Interface | (LT C1661 CMS8)&lt;br /&gt;
* Microchip PIC 10F2xx (+ Programmiergerät) ||||| ||||| ||||| ||| (einige Varianten erhältlich, Programmiergerät nicht sicher)&lt;br /&gt;
* Microchip PIC 24 ||||| ||||| ||||| ||||| ||&lt;br /&gt;
* Microchip PIC32 (MIPS) ||||| ||||| ||||| |||&lt;br /&gt;
* Microchip dsPIC33 ||||| ||||| ||||&lt;br /&gt;
* WAGO 215-4mm-Stecker (Bananenstecker mit Käfigzugklemme) zur schnellen Montage bei Versuchsaufbauten ||||| ||||| ||||| ||||| ||| (dieser Wunsch wurde erhört, Hurraa! Best.-Nr. Wago 215-x11, Vielen Dank an Reichelt.)&lt;br /&gt;
* Philips PCA9555 (I2C IO, 16 Bit par. I/O, c&#039;t Project Soundcheck II) |||||&lt;br /&gt;
* ADuM 1201 o. ADuM1401, bzw. andere ADuMxxxx oder ISOxxxx - Digitale Übertrager mit galvanischer Trennung |||&lt;br /&gt;
* LM2675 SimpleSwitcher Step-Down-Konverter in SO-8 Bauform&lt;br /&gt;
* Sharp Entfernungssensoren (zb den GP2D120 oder den GP2D12) 51x gewünscht---- siehe Reichelt Artikel : GP2-0430 und GP2-1080&lt;br /&gt;
* TSOP31238 (Besserer Ersatz (2,5-5,5V) für den nicht mehr Lieferbaren TSOP1738) || --- Artikel-Nr. &amp;quot;TSOP 31238&amp;quot;&lt;br /&gt;
* ERSA Lötspitzen der Serie 842 (besonders die feinen) Reichelt führt bis jetzt nur 832, die feinen davon sind aber recht unbrauchbar |||| --- sind nach einer freundlichen Mail in den Katalog aufgenommen worden. Artikel-Nr. &amp;quot;SPITZE 842&amp;quot;&lt;br /&gt;
* Atmel ATSTK600 von [http://www.atmel.com/dyn/products/tools_card.asp?tool_id=4254 Atmel] |||| (AVR STK 600)&lt;br /&gt;
* Atmel AVR Dragon von [http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3891 Atmel] ||||| ||||| ||||| ||||| ||| (AT AVR DRAGON)&lt;br /&gt;
* Option zum anklicken beim Versand, &amp;quot;nichtverfügbare Artikel automatisch streichen&amp;quot;, wenn man das ins Kommentarfeld schreibt wirds nicht beachtet, oder bis das jemand liest dauert es wieder mehrere tage. (In der Zwischenzeit realisiert!!) ||||| ||||| ||||| || (oder klare Anzeige wie viel noch vorhanden ist)&lt;br /&gt;
* AVR mit USB: AT90USB1287 (AT 90USB1287 TQ, TQFP64), dazu passendes Demoboard AT 90USB KEY; AT90USB162TQ (AT 90USB162 TQ, TQFP32), AT90USB646 (AT 90USB646 TQ, TQFP64), AT90USB1286QFN (AT 90USB1286 QFN, QFN64), ATmega32u2 (ATMEGA 32-U2 TQ, TQFP44)&lt;br /&gt;
* Buchsenleisten 2.54mm (z.&amp;amp;nbsp;B. BL 1X...G 2,54) TEILBAR, *zum Auseinanderbrechen* (laut Anfrage vom 26.10.2009 nicht im Sortiment) (SPL 64?) {{Reichelt50|FF0000}}||||| ||||| ||||| ||||| ||||| ||||| ||||| |&lt;br /&gt;
*TLE 4905L :: Hallsensor, 3,8-24V ist lieferbar (20.12.11)&lt;br /&gt;
&lt;br /&gt;
= Sonstiges =&lt;br /&gt;
&lt;br /&gt;
== zur Webseite ==&lt;br /&gt;
&lt;br /&gt;
In &amp;quot;Neu in unserem Shop&amp;quot;/Neue Artikel werden unter Bauelemente u.a. Computerkabel und PC-Speicher angezeigt (Anlass Stand 5/2010, ist aber schon früher aufgefallen). Diese Teile würden zumindest etwas besser in PC-Technik passen. (...und die Freude des Elektronikbastlers über eine Anzahl neuer Bauelemente würde auch nach Auswahl der Details anhalten, wenn es nicht &amp;quot;nur&amp;quot; so etwas wie USB-Kabel sind.)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
myReichelt ermöglicht: &lt;br /&gt;
* Warenkorbspeicherung&lt;br /&gt;
* öffentlicher Warenkorb&lt;br /&gt;
* CSV-Import, -Export&lt;br /&gt;
&lt;br /&gt;
zu myReichelt siehe auch http://www.mikrocontroller.net/topic/62628&lt;br /&gt;
&lt;br /&gt;
Eine Webseite ohne Frames ist eigentlich heute Stand der Technik. Oder vielleicht ist es das auch nicht mehr - ich weiss es nicht aber nach meiner Auffassung sollte es Stand der Technik sein. Denn dann hat man für jedes Produkt auch einen eindeutigen Link und kann ggf. auch in Beiträgen, Mails und Anfragen darauf verlinken.&lt;br /&gt;
&lt;br /&gt;
Anmerkung dazu:&lt;br /&gt;
Verlinken auf Artikel geht schon, und zwar in der Form:&lt;br /&gt;
http://www.reichelt.de/?ARTIKEL=ATMEGA%208-16%20DIP&lt;br /&gt;
bzw.&lt;br /&gt;
http://www.reichelt.de/index.html?ARTIKEL=ATMEGA%208-16%20DIP&lt;br /&gt;
&lt;br /&gt;
Neu zu lesen unter &amp;quot;Info zum Shop&amp;quot;:&lt;br /&gt;
Zitat:&lt;br /&gt;
&amp;quot;Frames&lt;br /&gt;
In vielen Votings wurden wir auf die Verwendung von Frames hingewiesen und dass diese Technik nicht mehr -State Of The Art- sei. Dieser Meinung schliessen wir uns in vollem Umfang an. In unserem neuen Shop werden KEINE FRAMES verwendet.&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Reichelt selbst macht das in seinen PDF-Prospekten auch so. Das Problem liegt nur darin, die URL jedesmal von Hand zusammenzubauen (und dabei auf die Ersetzung der Leerzeichen durch %20 zu achten) oder von einer kopierten URL alles überflüssige zu entfernen.&lt;br /&gt;
&lt;br /&gt;
Einfach mal einen &amp;quot;Permalink&amp;quot; button neben &amp;quot;Artikel empfehlen&amp;quot; ? Oder zurück mit der früheren Druckansicht.&lt;br /&gt;
&lt;br /&gt;
Hinweis: Viele Browser ersetzen Leerzeichen im Adressfeld automatisch durch %20. &lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Ferner sollte es möglich sein, Bestellungen, welche noch nicht bearbeitet werden zu verändern, also z.&amp;amp;nbsp;B. was hinzuzufügen oder zu entfernen. Bei einer Wartezeit von ca. 3 Tagen bis zum Versand fällt einem doch noch was ein :-)&lt;br /&gt;
&lt;br /&gt;
Das wird bereits gemacht! Einfach E-Mail an service@reichelt.de mit den Bauteilen, die man noch haben will. I-Net-Nummer nicht vergessen.&lt;br /&gt;
&lt;br /&gt;
Andere Möglichkeit ist anrufen, das mache ich eh immer, um eventuell nicht lieferbare Dinge zu streichen oder zu ersetzen. Geht immer, es sei denn Lieferung wird schon verpackt.&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Shopprogramm: Wäre es nicht komfortabel, ein Programm auf dem heimischen Rechner zu haben, welches das aktuelle Sortiment mit den aktuellen Preisen führt, wo dann auch offline Bestellungen zusammengestellt und hochgeladen werden können? So ließen sich die Merklisten auch besser verwalten.&lt;br /&gt;
&lt;br /&gt;
Ja, das fände ich auch sehr toll, sollte man mal drüber nachdenken.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Passwortschutz: Die derzeitige Lösung der Anmeldung im Shop ist für den heutigen Stand der Dinge recht unsicher. Ein zur Kundennummer gehörendes Passwort sollte schon sein. Was soll schon passieren, die Versandadresse ist ja bekannt, und wenn jemand anderes auf meinen Namen bestellt. lässt er sich über die Versandadresse herrausfinden, außerdem weiß ja auch nicht jeder meine Kundennummer.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Eine Art Lagerbestand im Onlineshop wäre sinnvoll. Es ist mehr als ärgerlich, wenn bei einer Bestellung z.&amp;amp;nbsp;B. Kleinteile wie Kondensatoren oder Schalter fehlen, weil sie nicht auf Lager waren. Dabei gibt es gerade bei solchen Teilen genug Alternativen, sei es Farbe, Bauart oder Wert, auf die man umsteigen könnte, damit die Bestellung vollständig ist. Es würde ja vollkommen ausreichen den Bestand in Form einer Ampel, wie bei anderen Shops, mit grün, gelb und rot zu realisieren.&lt;br /&gt;
&lt;br /&gt;
Im Warenkorb werden Artikel, die nicht auf Lager sind, mittlerweile auch so gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Früher würden neue Artikel mit einem gelben &amp;quot;NEU&amp;quot; gekennzeichnet, jetzt ist das nicht mehr so. Hätte gerne wieder einen Überblick, was neu hinzugekommen ist ohne jede Artikelgruppe aufrufen zu müssen. ||&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Artikelsuche: Bitte standardmäßig in der Liste alle Suchergebnisse anzeigen, nicht nur 16 Stück (oder wenigstens eine vernünftige Anzahl). Die Zeiten der 56k-Modems sind vorbei. ||&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Nummerierung der Bauteile: Warum wird der Warenkorb nicht nummeriert. Ich hasse es wenn ich manuell mit Hand zählen muss! Das ist auch nervig wenn man manuell per Hand vergleichen will!!&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
Virtuelle Bauteilekisten (vbox): Wer bei Reichelt bestellt, ordert oft viele viele Kleinteile. Wenn man nun ein Gerät zum wiederholten mal baut, muss man alle Teile erneut eingeben. Könnte ich nun neben dem Warenkorb auch noch virtuelle Bauteilekisten füllen, würde das neue Bestellungen sehr beschleunigen. Der Kunde als Wiederholungstäter sozusagen.&lt;br /&gt;
&lt;br /&gt;
Konkret:&lt;br /&gt;
Ich habe vier verschiedene Elektronikprojekte entwickelt.Für jedes dieser Projekte lege ich bei Reichelt.de eine virtuelle Bauteilekiste mit eigenem Namen an. Die Zusammenstellung der Artikel funktioniert wie beim normalen Warenkorb. Wenn ich nun ein Projekt erneut bauen möchte, kopiere ich einfach den Inhalt der virtuellen Bauteilekiste per Knopfdruck in meinen Warenkorb. Wenn ich Projekt2 also dreimal nachbauen möchte kopiere ich die virtuelle Bauteilebox &amp;quot;Projekt2&amp;quot; dreifach in den Warenkorb.&lt;br /&gt;
Schön wäre es auch die virtuellen Bauteilekisten mit Schaltplan und ev. Eagle  - Dateien veröffentlichen zu können.&lt;br /&gt;
&lt;br /&gt;
Und wieso ist der Login, den es früher mal gab weg? Da konnte man zumindest den aktuellen Warenkorb speichern soweit ich mich erinnern kann, aber seit der neuen Website gibt&#039;s den Login nicht mehr. Ausserdem muss ich jetzt jedesmal meine Kundennummer rauskramen um meine Bestellung abzusenden - Conrad löst das beispielsweise besser. (dafür haben die aber auch ne besch...eidene Suchfunktion und nen unübersichtlichen Shop)&lt;br /&gt;
&lt;br /&gt;
Nebenanregung:&lt;br /&gt;
Damit die &amp;quot;Bauteilekisten&amp;quot; nicht unmengen Platz beim Anbieter verschwenden könnte man diese auslagern.&lt;br /&gt;
Also Nach erstellen Download als einfaches File und bei Bedarf einfach bei Bestellung übertragen.&lt;br /&gt;
So könnte sie jeder in Ruhe offline vorbereiten und verwalten.&lt;br /&gt;
&lt;br /&gt;
IDEE: Offenlegung der Datenbank: Offenlegung der Datenbank oder zumindest Export für die User. Somit koennten die Datenbank in eine Art Datenbank gespeichert werden. Als Katalogprogramm koennte dann soetwas ähnliches wie das von Segor zum Einsatz kommen. Gibt es einen Standard dann koennten  Reichelt, Conrad, Segor, etc. mit einem Programm genutzt und verglichen werden:&lt;br /&gt;
siehe auch http://www.mikrocontroller.net/forum/read-7-363596.html&lt;br /&gt;
Programmierunterstuetzung findet sich bestimmt. Abgesehen davon haben die Distributoren den Vorteil die Katalogdaten übers Internet upzudaten.&lt;br /&gt;
&lt;br /&gt;
Zum offenlegen der Datenbank: Wie wäre es mit einem Webservice, mit dem man über SOAP auf die Datenbank zugreifen kann? Ähnlich wie bei Amazon oder auch Google.&lt;br /&gt;
&lt;br /&gt;
Lösung in HTML:&amp;lt;br/&amp;gt;&lt;br /&gt;
Ich hatte für das Projekt [http://www.mikrocontroller.net/topic/82127 &amp;quot;Webserver ATmega32/644DIP ENC28J60&amp;quot;] ein Bestellformular ([http://www.mikrocontroller.net/attachment/29451/reichelt.htm reichelt.htm] &amp;lt;span style=&amp;quot;font-size: 0.8em;&amp;quot;&amp;gt;[Version vom 22.12.2007]&amp;lt;/span&amp;gt;) gebastelt um schnell alle nötigen teile in den Reichelt – Warenkorb zulegen. Mit etwas HTML-Kenntnis dürfte eine Anpassung nicht das Problem darstellen.&amp;lt;br/&amp;gt;&lt;br /&gt;
In JavaScript, des &#039;&#039;&#039;reichelt.htm&#039;&#039;&#039; Bestellformulars, die Funktion &amp;lt;code&amp;gt;&#039;&#039;&#039;send()&#039;&#039;&#039; &#039;&#039;Zeile 42:&#039;&#039; var maxElements = 40;&amp;lt;/code&amp;gt; die &#039;&#039;&#039;40&#039;&#039;&#039; durch die Anzahl der unterschiedlichen Bauteile Anpassen.&lt;br /&gt;
&lt;br /&gt;
== zu Artikeln ==&lt;br /&gt;
&lt;br /&gt;
* Spitze fände ich eine verbesserte Suche für Gehäuse. Oft stehe ich vor dem Problem, meine Baugruppe ist so-und-so groß und ich brauche ein Gehäuse, in das diese Baugruppe hineinpasst. Zur Zeit muss ich mich manuell durch alle Gehäusegrößen &amp;quot;durchwühlen&amp;quot;, bis ich ein passendes gefunden habe. Die Suche stelle ich mir so vor: Ich gebe die Maße ein, die das Gehäuse mindestens haben &#039;&#039;muss&#039;&#039;, und bekomme alle Gehäuse angezeigt, die genau so groß oder etwas größer sind als meine Vorgaben.&lt;br /&gt;
&lt;br /&gt;
== Abwicklung ==&lt;br /&gt;
&lt;br /&gt;
* Sammelbestellung: Wenn ich etwas bei Reichelt bestelle, bestelle ich für meine Kollegen auch immer etwas mit. Wenn dann das Päckchen kommt, heisst es sortieren. Wer hatte von was, wie viel? Danach kommt das rechnen dran. Ein besonderes Highlight, sind die Nettopreise. Und auch das Verteilen der Versandkosten ist nicht ohne. Währe es nicht möglich, im Bestellvorgang eine Zuordnung zu Personen oder Projekten zu realisieren, und die Zwischensummen der Personen oder Projekte auf der Rechnung oder per Mail anzugeben. Ein Schmankerl wäre die Angabe der Bruttopreise inklusive der anteiligen Versandkosten.&lt;br /&gt;
** Wahrscheinlich nicht möglich, siehe AGB-Klausel zu Massenbestellungen. &amp;quot;Garantieberechtigt&amp;quot; ist auch immer nur der ursprüngliche Besteller.&lt;br /&gt;
** Welche Klausel? Mir fällt nur 13.3 ins Auge...&lt;br /&gt;
&lt;br /&gt;
* Abpackgrößen bei SMD-Bauteilen auf 5- oder 10er-Schritte beschränken. Die meisten sind eh im Cent-Bereich und es dürfte logistisch einfacher/schneller sein, feste Stückzahlen vorzuhalten, was man preislich sicher an die Kunden weitergeben kann ;)&lt;br /&gt;
&lt;br /&gt;
== zu dieser Wunschliste ==&lt;br /&gt;
&lt;br /&gt;
(gehört eigentlich in Diskussion)&lt;br /&gt;
&lt;br /&gt;
* Wäre es möglich ein Script zu bauen, welches man ab und zu über diesen Artikel jagt und das die Einträge nach Anzahl der Striche ordnet? =&amp;gt; Formatierung als Tabelle (1. Spalte: das Teil, 2. Spalte: die Striche) würde auch schon helfen.&lt;br /&gt;
** Das geht kaum, weil | ein SOnderzeichen in Vorlagen ist.&lt;br /&gt;
&lt;br /&gt;
* Dass hier jeder immer nur einen Strich macht, glaube ich nicht! Ein Script was pro IP nur einen Strich zulässt wäre gut. -&amp;gt; Naja, alle 24h spätestens gibt es eigendlich eine neue IP...   Antwort: Lässt sich sehr leicht überprüfen mit Artikel -&amp;gt; Versionen&lt;br /&gt;
&lt;br /&gt;
* Warum macht der 5te nicht anstelle |||| ein V :-) und anstelle vom nächsten V kommt dann ein X ....Daniel [[Benutzer:84.179.17.164|84.179.17.164]] 20:11, 4. Feb 2006 (CET)&lt;br /&gt;
::Sehr clever. Das würde es Reichelt bestimmt enorm erleichtern, stark nachgefragte Artikel schnell zu erkennen. *facepalm* ;-)&lt;br /&gt;
&lt;br /&gt;
* Wenn Reichelt was aus der Liste neu ins Programm aufnimmt wäre eine Benachrichtigung per Newsletter oder RSS nett. Oder zumindest eine Rubrik &amp;quot;Seit XX.XX.200X neu im Programm&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
== Logbuch ==&lt;br /&gt;
&lt;br /&gt;
20.03.2012: Sensorik Aktorik: Merge und alphabetische Sortierung&lt;br /&gt;
&lt;br /&gt;
19.03.2012: Aufräumarbeiten (&amp;gt;50 eingefärbt, Blöcke &amp;gt;5 getrennt)&lt;br /&gt;
Dachte dafür gibts hier einen Bot, der dann auch am besten gleich nach Wunschhäufigkeit sortieren könnte...derweil habe ich den Bio-Bot gemacht...hoffe das geht OK, oder gibts da FESTE Zuständigkeiten?&lt;br /&gt;
&lt;br /&gt;
07.10.2011: Reichelt über Facebook drauf aufmerksam gemacht - man schaue sich die Liste regelmäßig durch :)&lt;br /&gt;
&lt;br /&gt;
01.10.2011: Umfangreiche Neuordnung der gesamten Wishlist: Neue Unterkategorien, alphabetische Sortierung, Zusammenführung gleicher Wünsche aus verschiedenen Kategorien, Fix diverse Falsch-Einsortierungen, Update inzwischen erhältlicher Teile, Ausbau einzelner Einträge für bessere Sortierung und mehr Info beim Lesen (nicht nur IC-Namen), etc. Vielleicht hat ja noch jemand nen Einfall für die Sichtbarmachung besonders nachgefragter Einträge, Fett- und Kursivdruck der &#039;&#039;&#039;&#039;&#039;|||||&#039;&#039;&#039;&#039;&#039;-Blöcke funktioniert ja leider nicht... &lt;br /&gt;
&lt;br /&gt;
...bei Ausrufezeichen funktionierts aber. Meinungen zur Farbe und der Auslagerung in eine Vorlage?--[[Benutzer:Bzzz|Bzzz]] 14:49, 1. Okt. 2011 (UTC)&lt;br /&gt;
&lt;br /&gt;
03.03.2011: E-Mail wurde an Reichelt-Verwaltung geschrieben.&lt;br /&gt;
&lt;br /&gt;
8.4.2010: Mail an Reichelt geschickt und an die Liste erinnert.&lt;br /&gt;
&lt;br /&gt;
2.10.2009: REVERT auf die Version vor dem 20.Jul.2009 12:47. Da der Artikel von 193.200.150.82 &amp;quot;verdoppelt&amp;quot; wurde. D.h. alles war doppelt vorhanden und die Einleitung gelöscht&lt;br /&gt;
&lt;br /&gt;
19.06.2009: Hab mal den Kram unter der Rubrik &amp;quot;Webseite&amp;quot; entfernt/zusammengefasst der schon realisiert wurde. -- Tobias&lt;br /&gt;
&lt;br /&gt;
12.03.2009: Da haben wir ja alle verpennt, Reichelt in 2008 mal wieder an die Liste zu erinnern. Ich hab das jetzt mal nachgeholt und eine Mail an Reichelt geschickt. -- [http://www.reintechnisch.de Winfried Mueller]&lt;br /&gt;
&lt;br /&gt;
03.08.2007: Das Feld für &amp;quot;neue Artikel&amp;quot; scheint aus dem Reichelt Shop entfernt worden zu sein, schade da man so schnell schauen konnte was neu im Programm ist, nun ist wieder Katalogblättern angesagt. - Nicht nachvollziehbar. siehe Startseite-&amp;gt;Service-&amp;gt;Neu in unserem Shop &lt;br /&gt;
&lt;br /&gt;
18.05.2007: Habe Reichelt an diese Liste erinnert. -- Robin Tönniges&lt;br /&gt;
&lt;br /&gt;
14.11.2006 Ich lese mir gerade euer Wishlist durch. Finde ich gut! Aber wie ihr &lt;br /&gt;
hier (Logbuch) über Reichelt kritisiert finde ich nicht fair! Die haben genug zu arbeiten! Bitte keine Vorurteile! Um das gehts mir hauptsächlich!&lt;br /&gt;
Macht weiter nur nicht so! &lt;br /&gt;
P.S. Schöne inforeiche Site&lt;br /&gt;
Steven&lt;br /&gt;
&lt;br /&gt;
6.8.2006 Habe eine umfassende Kritik zu Reichelts neuem Webshop geschrieben und dabei auf unsere Wünsche bzl. Webseite, insbesondere &amp;quot;Virtuelle Bauteilebox&amp;quot; und &amp;quot;Gehäusesuche&amp;quot; hingewiesen. Verlinkung auf diese Seite ist auch erwähnt worden.&lt;br /&gt;
&lt;br /&gt;
5.8.2006 Hurra, Reichelt bietet endlich den ATtiny13V an! Jetzt können wir  Batteriebetriebene Geräte (2,4-3V) bauen. By the way: Gibt es blaue LED&#039;s, die dazu passen?&lt;br /&gt;
&lt;br /&gt;
14.7.2006 Reichelt antwortete: (Zu lang, deshalb hier nur der Inhalt:) Wir haben                                                                                    ihre mail zur Kenntnis genommen (Forum wird angeblich ab und zu immer wieder kontrolliert). Entscheidender Satz (Original eines Mitarbeiters:)....Ich denke jedoch, dass die meisten und&lt;br /&gt;
wichtigsten Wünsche zum Herbstkatalog eingelistet werden.&lt;br /&gt;
&lt;br /&gt;
14.7.2006 Reichelt erneut auf diesen Beitrag aufmerksam gemacht, erwarte Antwort.&lt;br /&gt;
&lt;br /&gt;
3.7.2006: beitz-online.de eine verlinkung gemailt. Ich hoffe das ist erlaubt.&lt;br /&gt;
&lt;br /&gt;
5.3.2006: Verlinkung gemailt&lt;br /&gt;
&lt;br /&gt;
12.10.2005: Verlinkung gemailt und gebeten sich darum zu kümmern&lt;br /&gt;
&lt;br /&gt;
07.10.2005: Reichelt eine Verlinkung gemailt und speziell auf LOW ESR Elkos und 433 Mhz Funkmodule hingewiesen. Mal sehen was die Antworten.&lt;br /&gt;
&lt;br /&gt;
08.07.2005: Reichelt bescheid gegeben, man möge mal wieder hier rein schauen -- Thomas O.&lt;br /&gt;
&lt;br /&gt;
13.05.2005: Antwort von Reichelt: der Versand ins Ausland bleibt leider bei 150 Eur -- nurmi&lt;br /&gt;
&lt;br /&gt;
09.05.2005: Reichelt bescheid gegeben, man möge mal wieder hier rein schauen -- nurmi&lt;br /&gt;
&lt;br /&gt;
08.05.2005: Pflege der Liste hier: Wenn ihr was in der Liste seht, was bereits schon im Angebot ist, löscht es bitte! Sonst ist das hier bald ein unüberschaubares Chaos. -- [http://www.reintechnisch.de Winfried Mueller]&lt;br /&gt;
&lt;br /&gt;
08.02.2005: Positives Feedback von Reichelt. Freuen sich über diese Form der Anregung. In der 2. Märzhälfte sollen weitere Produkte in den neuen Katalog einfließen. -- [http://www.reintechnisch.de Winfried Mueller]&lt;br /&gt;
&lt;br /&gt;
07.02.2005: Reichelt bescheid gegeben, man möge mal wieder hier rein schauen -- [http://www.reintechnisch.de Winfried Mueller]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Bauteile]]&lt;br /&gt;
[[Kategorie:Lieferanten]]&lt;/div&gt;</summary>
		<author><name>Sebion7125</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_Bootloader_in_C_-_eine_einfache_Anleitung&amp;diff=62605</id>
		<title>AVR Bootloader in C - eine einfache Anleitung</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_Bootloader_in_C_-_eine_einfache_Anleitung&amp;diff=62605"/>
		<updated>2011-12-19T23:16:58Z</updated>

		<summary type="html">&lt;p&gt;Sebion7125: /* Schritt 3 - Programmieren der Anwendung */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Dieser Artikel soll dazu dienen, das Thema [[Bootloader]] im AVR etwas zu demystifizieren.&lt;br /&gt;
&lt;br /&gt;
Es gibt schon einige Artikel und Codebeispiele für verschiedene Bootloader in Assembler oder C (bzw. gemischt), aber kein Artikel beleuchtet das Thema von einer einfachen Seite aus Anwendungssicht. In diese Lücke zielt dieses Tutorial.&lt;br /&gt;
Es soll anhand von Beispielen einen möglichst einfachen, verständlichen und nachvollziehbaren Weg zeigen, sich mit Hilfe der Hochsprache C in das Thema einzuarbeiten (dabei soll weder Assembler noch Inline-Assembler verwendet werden). &lt;br /&gt;
&lt;br /&gt;
Vielleicht werden einige meinen dass es nicht möglich ist das Thema ohne tieferen Einblick in die Hardware und die AVR-Register zu beleuchten, ich möchte es aber trotzdem versuchen.&lt;br /&gt;
&lt;br /&gt;
Der Artikel wird sich auf das notwendige Wissen beschränken, um mit Booloadern arbeiten zu können. Es wird ein genereller Weg gezeigt, der sich leicht auf andere AVR-Devices (mit Bootloader Sektion) übertragen lässt.&lt;br /&gt;
Die Codebeispiele wurden für den ATmega88 kompiliert und getestet.&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Zu Beginn soll das notwendige Wissen über die Bootloaderunterstützung im AVR vermittelt werden, um eine Arbeitsgrundlage zu schaffen.&lt;br /&gt;
&lt;br /&gt;
Im weiteren Verlauf des Artikels werden insgesamt drei Anwendungen programmiert: Zuerst ein einfacher Bootloader, welcher in der Bootloadersektion des Flashs ausgeführt wird, aber noch keine eigentliche Bootloader-Funktion hat, sozusagen ein &amp;quot;Hallo Welt&amp;quot;-Bootloader. Danach soll eine kleine Applikation programmiert werden, welche der spätere &#039;&#039;echte&#039;&#039; Bootloader ins Flash programmieren soll. Als großes Finale soll dann ein Bootloader entstehen, welcher in der Lage ist, Intel-HEX-Dateien über die serielle Schnittstelle zu laden, ins Flash zu programmieren und zu starten.&lt;br /&gt;
&lt;br /&gt;
Der Leser sollte bereits Erfahrungen im Umgang mit dem AVR Studio und der Programmiersprache C gemacht haben und schon Anwendungen geschrieben haben. Für absolute Einsteiger ist der Artikel ungeeignet.&lt;br /&gt;
&lt;br /&gt;
Den Thread zum Artikel gibt es hier: http://www.mikrocontroller.net/topic/195102&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
&lt;br /&gt;
Für den Artikel werden folgende Software-Pakete benötigt:&lt;br /&gt;
&lt;br /&gt;
* aktuelles [http://http://www.atmel.com/dyn/products/tools_card.asp?tool_id=2725 AVR Studio] (hier verwendet: AVR Studio v4.18) &lt;br /&gt;
* aktuelles [http://sourceforge.net/projects/winavr/files/ WinAVR] (hier verwendet: WinAVR20100110)&lt;br /&gt;
* [http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html PuTTY] als serielle Konsole (Version v0.6)&lt;br /&gt;
&lt;br /&gt;
Des weiteren wurde auf der AVR-Seite für die serielle Kommunikation mit dem PC auf die beliebte UART-Library von [http://www.jump.to/fleury Peter Fleury] zurückgegriffen, damit wir uns nicht um die gepufferte UART-Kommunikation kümmern müssen.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
Für den Artikel wurde eine kleine Hardware bestehend aus einem [http://www.atmel.com/dyn/products/product_card.asp?part_id=3302 Atmega88] und einem [http://www.ftdichip.com/Products/ICs/FT232R.htm FT232] als USB-Seriell-Wandler erstellt. Dies soll als Basis für die Experimente dienen. Der USB-Seriell-Wandler ist nicht zwingend notwendig und kann auch durch den üblichen Pegelwandler vom Typ [http://www.maxim-ic.com/datasheet/index.mvp/id/1798/ln/en MAX232] ersetzt werden, wenn der PC noch eine serielle Schnittstelle besitzt. Entscheidend ist nur die Möglichkeit der seriellen Kommunikation mit dem Rechner.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Schaltplan-ATmega88-USB.png|800px|Schaltplan]]&lt;br /&gt;
&lt;br /&gt;
Für die ISP-Programmierung wurde der [http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3808 AVRISPmkII-In-System-Programmer] von Atmel verwendet. Es kann natürlich auch ein anderer Programmer (z.B. [http://www.atmel.com/dyn/products/tools_card.asp?tool_id=2735 STK500]) verwendet werden, welcher mit dem AVR Studio zusammenarbeitet. Prinzipiell kann natürlich auch ein selbstgebastelter Parallel-Programmer verwendet werden, dann kann aber nicht via AVR Studio programmiert werden, sondern mit [http://www.nongnu.org/avrdude/ AVRDude] oder [http://www.lancos.com/prog.html PonyProg] o.ä. Der Artikel beschränkt sich auf die Verwendung vom AVR Studio.&lt;br /&gt;
&lt;br /&gt;
Für das Verständis der Hardware und der seriellen Kommunikation sind folgende Artikel empfehlenswert:&lt;br /&gt;
&lt;br /&gt;
* [[AVR-Tutorial: UART]]&lt;br /&gt;
* [[RS-232]]&lt;br /&gt;
&lt;br /&gt;
= Grundlagen =&lt;br /&gt;
&lt;br /&gt;
[[Bild:AVR-Memory.png|400px|thumb|Flash Speicher Aufteilung]]&lt;br /&gt;
&lt;br /&gt;
Was ist eigentlich ein Bootloader und was macht er? Wofür sollte ich so etwas brauchen? Ist das nicht viel zu kompliziert? Ich bin eingefleischter AVR Studio-Benutzer, muss ich mich jetzt mit makefiles beschäftigen? Kann man im AVR Studio mit C überhaupt einen Bootloader schreiben? Vielleicht hat sich der eine oder andere schon einmal diese oder ähnliche Fragen gestellt. &lt;br /&gt;
&lt;br /&gt;
Der Programmcode des AVR steht in seinem Flashspeicher und wird von dort ausgeführt. Normalerweise kann während der Ausführung des Programms nicht auf den Flashspeicher geschrieben werden. Dies ist auch einleuchtend da sich das Programm ja sonst selbst überschreiben oder löschen könnte. Das Beschreiben des Flashs erfolgt beim AVR üblicherweise über die ISP-Schnittstelle, dabei befindet sich der Controller im Reset und es wird kein Programm ausgeführt. Dies ist für Prototyping und kleine Anwendungen hinnehmbar. Ist der Controller allerdings in einem größeren System oder in größerer räumlicher Entfernung verbaut und die ISP-Schnittstelle nicht mehr zugänglich, ist ein Update der Firmware nicht mehr ohne Weiteres möglich oder sehr teuer und aufwendig. Hier kann ein Bootloader Abhilfe schaffen, in dem er das Anwendungsprogramm auf einer definierten Schnittstelle entgegennimmt (UART, I2C, Wireless) und ins Flash transferiert. Ein Bootloader ist also in erster Linie ein kleines Programm, welches in einem besonderem Teil des Flash steht - der &#039;&#039;&#039;Boot Loader Section&#039;&#039;&#039;.  Durch die Lokalisierung des Bootloader-Programms in dieser besonderen Sektion des AVR ist es dem Programm möglich, auf Teile des Flashs - der sogenannten &#039;&#039;&#039;Application Flash Section&#039;&#039;&#039; - zu schreiben. Die eigentliche Anwendung wird ausschließlich in der &#039;&#039;&#039;Application Flash Section&#039;&#039;&#039; ausgeführt. Wenn man so will, können im Flash des AVR also zwei unabhängige Programme stehen. Der Flash ist in zwei Bereiche mit unterschiedlichen Merkmalen aufgeteilt (siehe Bild). Auf die RWW bzw. NRWW-Sektion möchte ich an dieser Stelle (noch) nicht eingehen.&lt;br /&gt;
&lt;br /&gt;
Wie man unschwer erkennen kann, liegt der Bootloader-Bereich am Ende des Flash-Speichers. Normalerweise startet der Controller die Abarbeitung seiner Programmierung an der Stelle 0x0000. Ein Bootloader soll ja aber &#039;&#039;&#039;vor&#039;&#039;&#039; der Abarbeitung der eigentlichen Applikation ausgeführt werden. Woher weiß also der AVR-Controller nach dem Reset, dass er nicht von Adresse 0x0000 sondern einer anderen Adresse starten soll? Diese Konfiguration ist wie alle wichtigen und grundlegenden Konfigurationen über die Fuses des AVRs geregelt. Wir beginnen mit der folgende Tabelle, welche die Speicheraufteilung des Programmspeichers veranschaulicht.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Boot Size Konfiguration, Tabelle 26-6 im Atmega88-Datenblatt S.280&lt;br /&gt;
|- &lt;br /&gt;
! BOOTSZ1 || BOOTSZ0 || Boot&amp;lt;br&amp;gt;Size || Pages || Application&amp;lt;br&amp;gt;Flash Section || Boot Loader&amp;lt;br&amp;gt;Flash Section || End&amp;lt;br&amp;gt;Application&amp;lt;br&amp;gt;Section || Boot Reset&amp;lt;br&amp;gt;(Start Boot&amp;lt;br&amp;gt;Loader Section)&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 1 || 128 words || 4 || 0x000 - 0xF7F || 0xF80 - 0xFFF || 0xF7F || 0xF80&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 0 || 256 words || 8 || 0x000 - 0xEFF || 0xF00 - 0xFFF || 0xEFF || 0xF00&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 1 || 512 words || 16 || 0x000 - 0xDFF || 0xE00 - 0xFFF || 0xDFF || 0xE00&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 0 || 1024 words || 32 || 0x000 - 0xBFF || 0xC00 - 0xFFF || 0xBFF || 0xC00&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Um die Tabelle zu verstehen muss man wissen, dass der Flash-Speicher intern in sogenannten &#039;&#039;Pages&#039;&#039; (Seiten) organisiert ist. Die Multiplikation der &#039;&#039;Page&#039;&#039;-Größe mit der Anzahl der &#039;&#039;Pages&#039;&#039; ergibt die Speichergröße. Die Größe einer &#039;&#039;Page&#039;&#039; steht im Datenblatt und ist in &#039;&#039;Words&#039;&#039; - also Datenworte - angegeben. Ein Datenwort entspricht zwei Bytes. &#039;&#039;&#039;&#039;&#039;Hier offenbart sich eine Tücke des Datenblatts: Alle Speicherbezüge und Adressen sind in Datenworten  (also immer 2 Bytes) angegeben!&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
Aus der Tabelle erfahren wir auch, dass man mit den beiden Fuses &#039;&#039;&#039;BOOTSZ0&#039;&#039;&#039; und &#039;&#039;&#039;BOOTSZ1&#039;&#039;&#039; die Größe des Bootloaderbereichs einstellen kann. Eine weitere Tabelle aus dem Atmega88-Datenblatt gibt Auskunft über die Aufteilung der Pages und die Anzahl der Datenworte einer Page.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ No.of Words in a Page and No.of Pages in Flash, Tabelle 27-9 im Atmega88-Datenblatt S.288&lt;br /&gt;
|- &lt;br /&gt;
!  Device || Flash Size || Page Size || PCWORD || No. of Pages || PCPAGE || PCMSB&lt;br /&gt;
|-&lt;br /&gt;
| Atmega88 || 4K words (8 Kbytes) || 32 words || PC[4:0] || 128 || PC[11:5] || 11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Aus der Tabelle ergibt sich, dass die Größe einer &#039;&#039;Page&#039;&#039; des verwendeten Atmega88 32 &#039;&#039;Words&#039;&#039; - also 64 Byte sind. Insgesamt gibt es 128 &#039;&#039;Pages&#039;&#039;, damit ergibt sich nach Adam Riese 128 * 64 = 8192 Byte, also 8 Kbytes. In unserem späteren Codebeispiel soll die Größe des Bootloaderbereichs auf 1024 &#039;&#039;words&#039;&#039; - also 2048 Bytes gestellt werden (&#039;&#039;&#039;BOOTSZ0=0&#039;&#039;&#039; und &#039;&#039;&#039;BOOTSZ1=0&#039;&#039;&#039;). Nun können wir ausrechnen, in welcher Flash-&#039;&#039;Page&#039;&#039; bzw. an welcher Flash-Adresse der Bootloaderbereich beginnt: Er beginnt in der 96 &#039;&#039;Page&#039;&#039; (128 - 32) an &#039;&#039;Word&#039;&#039;-Adresse 0xC00, also Byteadresse 0xC00 * 2 = 0x1800. Dies ist die exakte Startadresse unseres Bootloaderbereiches.&lt;br /&gt;
&lt;br /&gt;
Weiter oben wurde die Frage gestellt, woher der AVR weiß, an welcher Stelle (entweder 0x0000 oder in unserem Fall 0x1800) er nach dem Reset starten soll. Um dem AVR dies mitzuteilen, ist eine weitere Fuse nötig - die &#039;&#039;&#039;BOOTRST&#039;&#039;&#039;-Fuse. Eine weitere Tabelle aus dem Atmega88-Datenblatt gibt Auskunft über diese Fuse.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Reset and Interrupt Vectors Placement in Atmega88, Tabelle 11-3 im Atmega88-Datenblatt S.58&lt;br /&gt;
|- &lt;br /&gt;
!  BOOTRST|| IVSEL || Reset Adress || Interrupt Vectors Start Adress&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 0 || 0x000 || 0x001 &lt;br /&gt;
|-&lt;br /&gt;
| 1 || 1 || 0x000 || Boot Reset Address + 0x001 &lt;br /&gt;
|-&lt;br /&gt;
| 0 || 0 || Boot Reset Address || 0x001 &lt;br /&gt;
|-&lt;br /&gt;
| 0 || 1 || Boot Reset Address || Boot Reset Address + 0x001 &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Mit der &#039;&#039;&#039;BOOTRST&#039;&#039;&#039;-Fuse wird festgelegt, dass der AVR nach dem Reset an die Startadresse der Bootloader Sektion im Flash springt. Auf das &#039;&#039;&#039;IVSEL&#039;&#039;&#039;-Bit (keine Fuse) möchte ich erst an späterer Stelle - wenn es um Interrupts geht - zurückkommen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Noch ein wichtiger Hinweis für die Werte der Fuses im Datenblatt:&#039;&#039;&#039; &#039;&#039;&#039;&#039;&#039;Der Wert &amp;quot;0&amp;quot; bedeutet, dass die Fuse programmiert ist, es entspicht dem Häkchen im AVR Studio!&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Der &amp;quot;Hallo Welt&amp;quot; - Bootloader =&lt;br /&gt;
&lt;br /&gt;
Wie oben erwähnt, wird für die Erstellung des Codes die kostenlose IDE von Atmel - das AVRStudio - benutzt. Ergänzt wird es durch C-Compiler und Tools des WinAVR Projektes. Des weiteren wird zur seriellen Kommunikation das Terminalprogramm benötigt. Im Tutorial wird PuTTY verwendet und sollte installiert sein. Die Hardware ist aufgebaut und via AVRISPmkII-Programmer an den PC angeschlossen - nun kann es losgehen!&lt;br /&gt;
&lt;br /&gt;
Zu Beginn wird ein neues AVRStudio-Projekt erstellt. Danach werden folgende Schritte abgearbeitet:&lt;br /&gt;
&lt;br /&gt;
== Schritt 1 - Konfiguration der Projekteinstellungen ==&lt;br /&gt;
[[Bild:Bootloader-Projekt.png|200px|thumb|Erstellen des Projekts]]&lt;br /&gt;
[[Bild:Bootloader-Config-General.PNG|200px|thumb|Generelle Optionen - setzten der Taktfrequenz]]&lt;br /&gt;
[[Bild:Bootloader-Config-Linker.png|200px|thumb|Linker Option eingeben]]&lt;br /&gt;
&lt;br /&gt;
Als erstes öffnen wir die Projekteinstellungen (Menü &#039;&#039;Project/Configuration Options&#039;&#039;) und tragen die richtige Taktfrequenz ein (Im Beispiel nutzen wir den internen Oszillator mit 8 Mhz). Danach gehen wir zum Reiter &#039;&#039;&#039;Custom Options&#039;&#039;&#039;. Dort klicken wir auf &#039;&#039;&#039;Linker Options&#039;&#039;&#039; und geben dann im Textfeld daneben &#039;&#039;&#039;-Ttext=0x1800&#039;&#039;&#039; ein. Danach drücken wir auf &#039;&#039;&#039;Add&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Was bewirkt dieser Linker-Parameter? Dafür muß wieder etwas weiter ausgeholt werden. Nach dem Kompilieren der Programmquellen &#039;&#039;linkt&#039;&#039; der Linker den Programmcode an bestimmte Stellen in den drei verschiedenen Speichern Flash, EEPROM und SRAM des AVR. In der vom Compiler verwendeten [http://www.nongnu.org/avr-libc/user-manual/mem_sections.html AVR Libc] ist der Speicher in verschiedene Sektionen aufgeteilt. Dem Linker muss mitgeteilt werden, in welche Speicher er den Programmcode linken soll. Die Lokalisierung des Speichers sind die Sektionen. Die Sektion &#039;&#039;.text&#039;&#039; ist dem ausführbaren Programmcode - also den Befehlen - vorbehalten und liegt im Flash des AVR, des weiteren gibt es auch noch die Sektionen &#039;&#039;.data&#039;&#039; und &#039;&#039;.bss&#039;&#039; für die statischen und dynamischen Variablen im SRAM und eine Sektion &#039;&#039;.eeprom&#039;&#039; für den EEPROM und noch ein paar spezielle (Flash-)Sektionen.&lt;br /&gt;
&lt;br /&gt;
Nun gibt es verschiedene Methoden, dem Linker mitzuteilen, dass man den Programmcode an die Stelle des Bootloaderbereichs haben möchte. Eine sehr einfache Methode ist &#039;&#039;&#039;die Verschiebung der Sektion &#039;&#039;&#039; &#039;&#039;&#039;&#039;&#039;.text&#039;&#039;&#039;&#039;&#039;, welche normalerweise ab Adresse 0x0000 beginnt. Eben dies geschieht mit dem Linker Parameter &#039;&#039;&#039;-Ttext=0x1800&#039;&#039;&#039;. Die Adresse des Beginns der &#039;&#039;.text&#039;&#039; Sektion wird auf die (Byte-)Adresse 0x1800 gesetzt.&lt;br /&gt;
&lt;br /&gt;
== Schritt 2 - Einbinden der UART Library von Peter Fleury ==&lt;br /&gt;
&lt;br /&gt;
Wie bereits erwähnt, wird für die serielle Kommunikation auf der AVR-Seite die UART-Library von [http://www.jump.to/fleury Peter Fleury] verwendet. Nach dem Download werden die uart.c und uart.h in das Projekt eingebunden (für die uart.c im AVR Studio rechte Maustaste auf &#039;&#039;Source Files&#039;&#039; und dann &#039;&#039;Add Existing Source File(s)...&#039;&#039; und für die uart.h die rechte Maustaste auf &#039;&#039;Header Files&#039;&#039; und dann &#039;&#039;Add Existing Header File(s)...&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
== Schritt 3 - Programmieren des Bootloaders ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Bootloader-Config-Linker-ok.PNG|200px|thumb|Linker Option nach Add]]&lt;br /&gt;
[[Bild:Bootloader-AVRStudio.PNG|200px|thumb|Kompilieren des Bootloaders]]&lt;br /&gt;
&lt;br /&gt;
Nun soll eine kleine Applikation geschrieben werden. Keine Angst, unser erstes Ziel ist es, eine kleine Anwendung in dem Bootloaderbereich zu positionieren, welche serielle Ein-und Ausgaben behandelt. Die eigentliche Bootloaderfunktionalität kommt später dazu. Also schreiben wir die Datei &#039;&#039;main.c&#039;&#039; wie folgt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/boot.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
#define BOOT_UART_BAUD_RATE     9600     /* Baudrate */&lt;br /&gt;
#define XON                     17       /* XON Zeichen */&lt;br /&gt;
#define XOFF                    19       /* XOFF Zeichen */&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
    unsigned int 	c=0;               /* Empfangenes Zeichen + Statuscode */&lt;br /&gt;
    unsigned char	temp,              /* Variable */&lt;br /&gt;
                        flag=1,            /* Flag zum steuern der Endlosschleife */&lt;br /&gt;
			p_mode=0;	   /* Flag zum steuern des Programmiermodus */&lt;br /&gt;
    void (*start)( void ) = 0x0000;        /* Funktionspointer auf 0x0000 */&lt;br /&gt;
 &lt;br /&gt;
    /* Interrupt Vektoren verbiegen */&lt;br /&gt;
&lt;br /&gt;
    char sregtemp = SREG;&lt;br /&gt;
    cli();&lt;br /&gt;
    temp = MCUCR;&lt;br /&gt;
    MCUCR = temp | (1&amp;lt;&amp;lt;IVCE);&lt;br /&gt;
    MCUCR = temp | (1&amp;lt;&amp;lt;IVSEL);&lt;br /&gt;
    SREG = sregtemp;&lt;br /&gt;
 &lt;br /&gt;
    /* Einstellen der Baudrate und aktivieren der Interrupts */&lt;br /&gt;
    uart_init( UART_BAUD_SELECT(BOOT_UART_BAUD_RATE,F_CPU) ); &lt;br /&gt;
    sei();&lt;br /&gt;
 &lt;br /&gt;
    uart_puts(&amp;quot;Hallo hier ist der Bootloader\n\r&amp;quot;);&lt;br /&gt;
    _delay_ms(1000);&lt;br /&gt;
 &lt;br /&gt;
    do&lt;br /&gt;
    {&lt;br /&gt;
        c = uart_getc();&lt;br /&gt;
        if( !(c &amp;amp; UART_NO_DATA) )&lt;br /&gt;
        {&lt;br /&gt;
            switch((unsigned char)c)&lt;br /&gt;
            {&lt;br /&gt;
                 case &#039;q&#039;: &lt;br /&gt;
		     flag=0;&lt;br /&gt;
                     uart_puts(&amp;quot;Verlasse den Bootloader!\n\r&amp;quot;);&lt;br /&gt;
                     break;&lt;br /&gt;
                  default:&lt;br /&gt;
                     uart_puts(&amp;quot;Du hast folgendes Zeichen gesendet: &amp;quot;);&lt;br /&gt;
                     uart_putc((unsigned char)c);&lt;br /&gt;
                     uart_puts(&amp;quot;\n\r&amp;quot;);&lt;br /&gt;
                     break;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    while(flag);&lt;br /&gt;
 &lt;br /&gt;
    uart_puts(&amp;quot;Springe zur Adresse 0x0000!\n\r&amp;quot;);&lt;br /&gt;
    _delay_ms(1000);&lt;br /&gt;
&lt;br /&gt;
    /* vor Rücksprung eventuell benutzte Hardware deaktivieren&lt;br /&gt;
       und Interrupts global deaktivieren, da kein &amp;quot;echter&amp;quot; Reset erfolgt */&lt;br /&gt;
&lt;br /&gt;
    /* Interrupt Vektoren wieder gerade biegen */&lt;br /&gt;
    cli();&lt;br /&gt;
    temp = MCUCR;&lt;br /&gt;
    MCUCR = temp | (1&amp;lt;&amp;lt;IVCE);&lt;br /&gt;
    MCUCR = temp &amp;amp; ~(1&amp;lt;&amp;lt;IVSEL);&lt;br /&gt;
&lt;br /&gt;
    /* Rücksprung zur Adresse 0x0000 */&lt;br /&gt;
    start(); &lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Erklärung des Codes&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Beginnen wir mit den Defines: Die Baudrate erklärt sich von selbst. Die Defines XON und XOFF werden später, wenn die Bootloader-Funktionalität dazukommt, zur Flusssteuerung gebraucht. Wir werden also die XON/XOFF-Flussteuerung nutzen (merken für die Einstellung von PuTTY). &lt;br /&gt;
&lt;br /&gt;
Bei den Variablen ist nur eine interessant: Der Funktionspointer &amp;lt;pre&amp;gt;void (*start)( void ) = 0x0000;&amp;lt;/pre&amp;gt; ist ein einfacher Trick, um mit dem Programmcounter (PC) zur Adresse 0x0000 zu springen. Wir definieren einfach eine (fiktive) Funktion an der Stelle 0x0000. Beim Aufruf der Funktion mit &amp;lt;pre&amp;gt;start();&amp;lt;/pre&amp;gt; springt der Programmcounter und damit das Programm an Adresse 0x0000 und das Anwendungsprogramm - wenn es eins gibt - kann starten. &lt;br /&gt;
&lt;br /&gt;
Nun folgt ein sehr wichtiger Teil, auf den ich noch eingehen muss - die Interrupt-Vektoren. Interrupt-Vektoren sind Einsprungpunkte der Interrupts, welche normalerweise fest ab Adresse 0x0001 im Flash liegen. Wird ein Interrupt ausgelöst, springt der AVR automatisch zu der festen Flash-Adresse. Von dort aus - wenn eine ISR programmiert ist - springt der Controller zur ISR (&#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;S&#039;&#039;&#039;ervice &#039;&#039;&#039;R&#039;&#039;&#039;outine). Nun haben wir folgendes Problem: Wenn wir den Bootloadercode ab der Adresse 0x1800 ausführen, nützt es uns gar nichts, wenn der AVR nach Auslösen eines Interrupts an die Stelle 0x0001 + X springt, da dieser Speicherbereich ja im Zweifelsfalle sogar von uns überschrieben wird. Unser Code soll nur ab Adresse 0x1800 stehen! Wir müssen also die Sprungtabelle &amp;quot;verbiegen&amp;quot;, d.h. den AVR veranlassen, bei Auslösung eines Interrupts an Adresse 0x1801 + X zu springen und dann zur ISR. Das Verbiegen der Sprungtabelle passiert mit dem Setzen des &#039;&#039;&#039;IVSEL&#039;&#039;&#039;-Bits im &#039;&#039;&#039;MCUCR&#039;&#039;&#039; (ACHTUNG: beim Atmega8 &#039;&#039;&#039;GICR&#039;&#039;&#039;), also&lt;br /&gt;
&lt;br /&gt;
beim Atmega88:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
temp = MCUCR;&lt;br /&gt;
MCUCR = temp | (1&amp;lt;&amp;lt;IVCE);&lt;br /&gt;
MCUCR = temp | (1&amp;lt;&amp;lt;IVSEL);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
bzw. beim Atmega8:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
temp = GICR;&lt;br /&gt;
GICR = temp | (1&amp;lt;&amp;lt;IVCE);&lt;br /&gt;
GICR = temp | (1&amp;lt;&amp;lt;IVSEL);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das &#039;&#039;&#039;IVCE&#039;&#039;&#039;-Bit wird nur benötigt, um dem Mikrocontroller zu sagen, dass wir als nächstes den Parameter &#039;&#039;&#039;IVSEL&#039;&#039;&#039; setzen wollen, das Bit wird nachher vom Controller wieder gelöscht. Um versehentliches verstellen der Interrupttabelle zu vermeiden muss das setzen von &#039;&#039;&#039;IVCE&#039;&#039;&#039; und &#039;&#039;&#039;IVSEL&#039;&#039;&#039; innerhalb von 4 Taktzyklen erfolgen. Um dies zu gewährleisten müssen alle interrupts während des Setzens deaktiviert sein. ACHTUNG Stolperfalle: Die Variable temp wird benötigt, da beim Setzen von &#039;&#039;&#039;IVSEL&#039;&#039;&#039; gleichzeitig &#039;&#039;&#039;IVCE&#039;&#039;&#039; gelöscht werden muss:&lt;br /&gt;
&lt;br /&gt;
bei Atmega8/16:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
GICR |= (1&amp;lt;&amp;lt;IVCE);   // noch richtig. IVCE wird gesetzt&lt;br /&gt;
GICR |= (1&amp;lt;&amp;lt;IVSEL);  // falsch! IVSEL wird zwar gesetzt, &lt;br /&gt;
                        IVCE bleibt jedoch in diesem Prozessortakt gesetzt.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In der Hauptschleife wird lediglich gepollt, ob ein neues Zeichen von der Konsole kommt. Nach dem Empfang eines Zeichens wird es ausgewertet (switch). Nach dem Drücken von &#039;&#039;&amp;quot;q&amp;quot;&#039;&#039; verlässt der Bootloader die Hauptschleife, setzt die Interrupt-Vektoren wieder zurück und startet die Hauptanwendung - wenn eine da ist.&lt;br /&gt;
&lt;br /&gt;
Nach dem Kompilieren sagt uns der Linker, dass 754 Byte Programmspeicher und 265 Byte Datenspeicher verbraucht wurde. 754 Byte ist weit unter den 2048 Byte, welche uns ab der Adresse 0x1800 zur Verfügung stehen, wir haben also alles richtig gemacht.&lt;br /&gt;
&lt;br /&gt;
Nun kontrollieren wir noch schnell, ob das Programm an der richtigen Stelle im Flash steht. Mit dem Hex-File (Bootloader.hex) wird auch ein List-File (Bootloader.lss) erzeugt. Im List-File findet sich das disassemblierte Programm und die Speicherzuordnungen. Hier ein Auszug der Datei:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Bootloader.elf:     file format elf32-avr&lt;br /&gt;
&lt;br /&gt;
Sections:&lt;br /&gt;
Idx Name          Size      VMA       LMA       File off  Algn&lt;br /&gt;
  0 .data         00000080  00800100  00001a68  000002fc  2**0&lt;br /&gt;
                  CONTENTS, ALLOC, LOAD, DATA&lt;br /&gt;
  1 .text         00000268  00001800  00001800  00000094  2**1&lt;br /&gt;
                  CONTENTS, ALLOC, LOAD, READONLY, CODE&lt;br /&gt;
  2 .bss          00000085  00800180  00800180  0000037c  2**0&lt;br /&gt;
                  ALLOC&lt;br /&gt;
  3 .debug_aranges 00000040  00000000  00000000  0000037c  2**0&lt;br /&gt;
                  CONTENTS, READONLY, DEBUGGING&lt;br /&gt;
  4 .debug_pubnames 00000095  00000000  00000000  000003bc  2**0&lt;br /&gt;
                  CONTENTS, READONLY, DEBUGGING&lt;br /&gt;
  5 .debug_info   00000459  00000000  00000000  00000451  2**0&lt;br /&gt;
                  CONTENTS, READONLY, DEBUGGING&lt;br /&gt;
  6 .debug_abbrev 00000238  00000000  00000000  000008aa  2**0&lt;br /&gt;
                  CONTENTS, READONLY, DEBUGGING&lt;br /&gt;
  7 .debug_line   000003eb  00000000  00000000  00000ae2  2**0&lt;br /&gt;
                  CONTENTS, READONLY, DEBUGGING&lt;br /&gt;
  8 .debug_frame  000000a0  00000000  00000000  00000ed0  2**2&lt;br /&gt;
                  CONTENTS, READONLY, DEBUGGING&lt;br /&gt;
  9 .debug_str    000001cf  00000000  00000000  00000f70  2**0&lt;br /&gt;
                  CONTENTS, READONLY, DEBUGGING&lt;br /&gt;
 10 .debug_loc    0000024a  00000000  00000000  0000113f  2**0&lt;br /&gt;
                  CONTENTS, READONLY, DEBUGGING&lt;br /&gt;
 11 .debug_ranges 00000048  00000000  00000000  00001389  2**0&lt;br /&gt;
                  CONTENTS, READONLY, DEBUGGING&lt;br /&gt;
&lt;br /&gt;
Disassembly of section .text:&lt;br /&gt;
&lt;br /&gt;
00001800 &amp;lt;__vectors&amp;gt;:&lt;br /&gt;
    1800:	19 c0       	rjmp	.+50     	; 0x1834 &amp;lt;__ctors_end&amp;gt;&lt;br /&gt;
    1802:	33 c0       	rjmp	.+102    	; 0x186a &amp;lt;__bad_interrupt&amp;gt;&lt;br /&gt;
    1804:	32 c0       	rjmp	.+100    	; 0x186a &amp;lt;__bad_interrupt&amp;gt;&lt;br /&gt;
    1806:	31 c0       	rjmp	.+98     	; 0x186a &amp;lt;__bad_interrupt&amp;gt;&lt;br /&gt;
    1808:	30 c0       	rjmp	.+96     	; 0x186a &amp;lt;__bad_interrupt&amp;gt;&lt;br /&gt;
    180a:	2f c0       	rjmp	.+94     	; 0x186a &amp;lt;__bad_interrupt&amp;gt;&lt;br /&gt;
    180c:	2e c0       	rjmp	.+92     	; 0x186a &lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
(viele Zeilen)&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
0000186c &amp;lt;main&amp;gt;:&lt;br /&gt;
#define BOOT_UART_BAUD_RATE     9600     /* Baudrate */&lt;br /&gt;
#define XON                     17       /* XON Zeichen */&lt;br /&gt;
#define XOFF                    19       /* XOFF Zeichen */&lt;br /&gt;
 &lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
    186c:	cf 93       	push	r28&lt;br /&gt;
    186e:	df 93       	push	r29&lt;br /&gt;
    unsigned char	temp,            /* Variable */&lt;br /&gt;
                        flag=1;          /* Flag zum steuern der Endlosschleife */&lt;br /&gt;
    void (*start)( void ) = 0x0000;    /* Funktionspointer auf 0x0000 */&lt;br /&gt;
 &lt;br /&gt;
    /* Interrupt Vektoren verbiegen */&lt;br /&gt;
    temp = MCUCR;&lt;br /&gt;
    1870:	85 b7       	in	r24, 0x35	; 53&lt;br /&gt;
    MCUCR = temp | (1&amp;lt;&amp;lt;IVCE);&lt;br /&gt;
    1872:	98 2f       	mov	r25, r24&lt;br /&gt;
    1874:	91 60       	ori	r25, 0x01	; 1&lt;br /&gt;
    1876:	95 bf       	out	0x35, r25	; 53&lt;br /&gt;
    MCUCR = temp | (1&amp;lt;&amp;lt;IVSEL);&lt;br /&gt;
    1878:	82 60       	ori	r24, 0x02	; 2&lt;br /&gt;
    187a:	85 bf       	out	0x35, r24	; 53&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
(noch mehr Zeilen)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir erkennen, dass die Sektion &#039;&#039;.text&#039;&#039; ab der Adresse (VMA) 0x1800 beginnt. Weiter sehen wir im Disassembly der Sektion &#039;&#039;.text&#039;&#039;, dass unser Programm mit der Interrupt-Einsprungstabelle ab Adresse 0x1800 beginnt. Unsere &#039;&#039;main()&#039;&#039; beginnt ab Adresse 0x186C. Super. Das hat geklappt. Aber nun schnell zu Schritt 4 - dem Flashen und Ausprobieren des Programms...&lt;br /&gt;
&lt;br /&gt;
== Schritt 4 - Flashen und Ausprobieren des Bootloaders ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Bootloader-AVRStudio-Fuses.png|200px|thumb|Setzen der Fuses]]&lt;br /&gt;
[[Bild:PuTTY-Serconfig.png|200px|thumb|Serielle Konfiguration von PuTTY]]&lt;br /&gt;
[[Bild:PuTTY-Serconfig-xon.png|200px|thumb|Serielle Konfiguration von PuTTY]]&lt;br /&gt;
&lt;br /&gt;
Nach dem Start des AVRISPmkII-In-System-Programmers aus dem AVRStudio werden zunächst die Einstellungen geprüft. Die Signatur des AVRs muss stimmen und die ISP-Frequenz. Im Reiter Program muss unter &#039;&#039;Flash&#039;&#039; die richtige Datei angegeben sein (&#039;&#039;Bootloader.hex&#039;&#039;). Danach können wir uns an das setzen der Fuses machen. &#039;&#039;&#039;CKDIV8&#039;&#039;&#039; sollte ausgeschalten werden, der interne Takt von 8 Mhz sollte genutzt werden (&#039;&#039;&#039;SUT_CKSEL&#039;&#039;&#039;) und &#039;&#039;BOOTSZ&#039;&#039; auf 1024 words gestellt werden. Zusätzlich muß die &#039;&#039;&#039;BOOTRST&#039;&#039;&#039;-Fuse gesetzt werden, damit der Bootloader an der richtigen Adresse anfängt. Für alle, die einen anderen Programmer benutzen (z.B. avrdude), hier die exakten Werte der Fuses:&lt;br /&gt;
* Low Fuse: &#039;&#039;&#039;0xE2&#039;&#039;&#039;&lt;br /&gt;
* High Fuse: &#039;&#039;&#039;0xD2&#039;&#039;&#039;&lt;br /&gt;
* Extended Fuse: &#039;&#039;&#039;0xF8&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Jetzt kann PuTTY gestartet und konfiguriert werden. Der &#039;&#039;Connection type&#039;&#039; muss auf &#039;&#039;&#039;Serial&#039;&#039;&#039; gestellt werden. Die Baudrate beträgt 9600 Baud. Unter &#039;&#039;Connection/Serial&#039;&#039; muss der &#039;&#039;Flow control&#039;&#039; auf &#039;&#039;&#039;XON/XOFF&#039;&#039;&#039; gestellt werden. Nach dem Konfigurieren kann die Konsole mit &#039;&#039;Open&#039;&#039; geöffnet werden.&lt;br /&gt;
&lt;br /&gt;
Jetzt kann wieder in das AVR Studio gewechselt werden. Mit einem beherztem Druck auf &#039;&#039;Program&#039;&#039; wird das Flash im ATmega88 programmiert. Nach dem Wechsel auf die Konsole erscheint folgendes Bild:&lt;br /&gt;
&lt;br /&gt;
[[Bild:PuTTY-Bootloader-start.png|600px|Bootloader in PuTTY]]&lt;br /&gt;
&lt;br /&gt;
Nach dem Drücken von ein paar Tasten erscheint folgendes:&lt;br /&gt;
&lt;br /&gt;
[[Bild:PuTTY-Bootloader-taste.png|600px|Bootloader nach Tastendruck in PuTTY]]&lt;br /&gt;
&lt;br /&gt;
Nach dem Drücken von &#039;&#039;&#039;q&#039;&#039;&#039; erscheint folgendes Bild:&lt;br /&gt;
&lt;br /&gt;
[[Bild:PuTTY-Bootloader-restart.png|600px|Bootloader nach Tastendruck in PuTTY]]&lt;br /&gt;
&lt;br /&gt;
Der Bootloader versucht, zur Adresse 0x0000 zu springen, wo er allerdings keinen Programmcode findet. Wie auch? Wir haben ja den ganzen Flash des AVR gerade gelöscht und mit dem Bootloader gefüllt. Nun muss man wissen, dass in einem gelöschten Flash &#039;&#039;0xFF&#039;&#039; in jeder Speicherzelle steht. &#039;&#039;0xFF&#039;&#039; ist für den AVR kein gültiger Opcode. Der Programmzähler zählt nur um eins nach oben. Damit hopst er sozusagen durch den gesamten Flash bis er wieder beim Bootloader landet.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;[http://de.wikipedia.org/wiki/Heureka Heureka]&#039;&#039;&#039;&#039;&#039; wir haben es geschafft! Ein Programm wird im Bootloaderbereich des Flashs ausgeführt! Es &#039;&#039;bootet&#039;&#039; zwar schon schön, aber es &#039;&#039;loadet&#039;&#039; noch nichts in den Flash. Aber die halbe Miete haben wir damit schon. Nun schreiben wir erst einmal eine kleine Anwendung, welche wir nach der Erweiterung unseres Bootloaders in den Flash-Speicher laden.&lt;br /&gt;
&lt;br /&gt;
= Die Test-Anwendung =&lt;br /&gt;
&lt;br /&gt;
[[Bild:Anwendung-AVRStudio.png|200px|thumb|Erstellen des Projektes]]&lt;br /&gt;
[[Bild:Anwendung-AVRStudio-Code.png|200px|thumb|Sourcecode im AVRStudio]]&lt;br /&gt;
&lt;br /&gt;
Die Kategorie Anwendung möchte ich möglichst kurz halten. Ziel ist es, eine kleine Anwendung zu schreiben, welche dann mit dem (echten) Bootloader ins Flash gespeichert wird. &lt;br /&gt;
&lt;br /&gt;
== Schritt 1 - Erstellen des Projektes ==&lt;br /&gt;
&lt;br /&gt;
Nach dem Erstellen eines neuen Projektes muss in den Projekt-Einstellungen des AVR Studios nur die Taktfrequenz eingetragen werden. Die Linker-Optionen werden nicht verändert, also bleibt wie es ist.&lt;br /&gt;
&lt;br /&gt;
== Schritt 2 - Einbinden der UART Library ==&lt;br /&gt;
&lt;br /&gt;
Dieser Schritt kann vom Bootloader übernommen werden. Es wird wieder die UART-Bibliothek von Peter Fleury verwendet.&lt;br /&gt;
&lt;br /&gt;
== Schritt 3 - Programmieren der Anwendung ==&lt;br /&gt;
&lt;br /&gt;
Wir starten also ein neues AVR Studio und legen ein neues Projekt an, konfigurieren die Taktfrequenz (8 MHz) und laden die &#039;&#039;uart.c&#039;&#039; und &#039;&#039;uart.h&#039;&#039; dazu. Nun schreiben wir in die &#039;&#039;main.c&#039;&#039; folgende Zeilen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/pgmspace.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#define UART_BAUD_RATE	9600&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
   unsigned int 	c;&lt;br /&gt;
   void (*bootloader)( void ) = 0x0C00;  // Achtung Falle: Hier Word-Adresse&lt;br /&gt;
&lt;br /&gt;
   uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); &lt;br /&gt;
   sei();&lt;br /&gt;
    &lt;br /&gt;
   uart_puts_P(&amp;quot;\n\rHier ist das Anwendungsprogramm...&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
   for(;;)&lt;br /&gt;
   {&lt;br /&gt;
       c = uart_getc();&lt;br /&gt;
       if(!(c &amp;amp; UART_NO_DATA))&lt;br /&gt;
       {&lt;br /&gt;
	   switch( (unsigned char)c)&lt;br /&gt;
	   {&lt;br /&gt;
	       case &#039;b&#039;:&lt;br /&gt;
		   uart_puts(&amp;quot;\n\rSpringe zum Bootloader...&amp;quot;);&lt;br /&gt;
		   _delay_ms(1000);&lt;br /&gt;
		    bootloader();&lt;br /&gt;
		    break;&lt;br /&gt;
		default:&lt;br /&gt;
                    uart_puts(&amp;quot;\n\rDu hast folgendes Zeichen gesendet: &amp;quot;);&lt;br /&gt;
		    uart_putc((unsigned char)c);&lt;br /&gt;
		    break;&lt;br /&gt;
	    }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Erklärung des Codes&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viel interessantes ist nicht an diesem Code. Es gibt wie immer die berühmte Endlosschleife. Wir definieren wieder einen fiktiven Funktionspointer auf die Word-Adresse(Hier verhält sich der AVR-GCC leider etwas inkonsistent, da sonst bei Flash-Adressen mit Bytes gearbeitet wird. Gibt man hier versehentlich die Byteadresse an, kann es sein, dass der Sprung in den Bootloader klappt, es muss aber nicht funktionieren, da das Sprungziel undefiniert ist. Verwendet man stattdessen einen JMP befehl im Inline-Assembler, so ist die Byte-Adresse für das Sprungziel anzugeben) des Bootloaders&amp;lt;pre&amp;gt;void (*bootloader)( void ) = 0x0C00;&amp;lt;/pre&amp;gt; Nach drücken der Taste &#039;&#039;&#039;b&#039;&#039;&#039; soll das Programm wieder zum Bootloader springen.&lt;br /&gt;
&lt;br /&gt;
Nach dem Kompilieren des Programms sehen wir, dass der Programmspeicher mit 686 Byte belegt ist, der Datenspeicher mit 201 Bytes.&lt;br /&gt;
&lt;br /&gt;
== Schritt 4 - Ausprobieren der Anwendung ==&lt;br /&gt;
&lt;br /&gt;
Wer möchte kann die Anwendung auf den AVR flashen und ausprobieren. Die Funktion sollte sich von selbst erschließen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Achtung:&#039;&#039;&#039; Es muss darauf geachtet werden, dass beim flashen der Anwendung nicht der Bootloader überschrieben wird.&amp;lt;br&amp;gt;Bei Verwendung von avrdude muss dazu die Option &amp;quot;-D&amp;quot; angegeben werden.&lt;br /&gt;
&lt;br /&gt;
Nun wollen wir uns der Erweiterung des Bootloaders widmen.&lt;br /&gt;
&lt;br /&gt;
= Der &amp;quot;echte&amp;quot; Bootloader =&lt;br /&gt;
[[Bild:Real-Bootloader-AVRStudio.png|200px|thumb|Programmieren des Bootloaders]]&lt;br /&gt;
&lt;br /&gt;
Zum Erstellen des Bootloaders wird wieder Schrittweise vorgegangen. Folgende Schritte sind zu befolgen:&lt;br /&gt;
&lt;br /&gt;
== Schritt 1 und 2 - siehe &amp;quot;Hallo Welt&amp;quot; Bootloader ==&lt;br /&gt;
Schritt 1 und 2 können vom &amp;quot;Hallo Welt&amp;quot; Bootloader übernommen werden. Es sind wieder die korrekte Taktfrequenz und die Verschiebung der Sektion &#039;&#039;&#039;.text&#039;&#039;&#039; auf die Bootresetadresse einzustellen.&lt;br /&gt;
&lt;br /&gt;
== Schritt 3 - Programmieren des Bootloaders ==&lt;br /&gt;
&lt;br /&gt;
Nun soll der Bootloader erweitert werden. Nach dem Kompilieren des Anwendungsprogramms erhalten wir eine Datei &#039;&#039;Anwendung.hex&#039;&#039; im [http://de.wikipedia.org/wiki/Intel_HEX Intel-HEX-Format]. Da wir im Bootloader diese Daten auswerten müssen, wollen wir uns kurz mit dem Format beschäftigen. Das Intel-HEX-Format ist geschaffen worden, um Binärdaten als ASCII-Daten zu übertragen. Jedes Byte ist in Form von zwei ASCII-Zeichen gespeichert, d.h. aus der Zahl &#039;&#039;0x4A&#039;&#039; wird die ASCII-Zeichenfolge &#039;&#039;&amp;quot;4A&amp;quot;&#039;&#039;. Das bedeutet aber auch, dass aus den Binärdaten die doppelte Anzahl von Zeichen wird, welche übertragen werden müssen, hinzu kommen noch Steuerzeichen und Zusatzinformationen. Jede Zeile in der Intel-HEX-Datei folgt einem bestimmten Schema, in dem u.a. die Anzahl der Bytes, die Zieladresse und Checksumme stehen.&lt;br /&gt;
&lt;br /&gt;
Für weiterführende Erklärungen zum Thema HEX-Datei-Format empfehle ich folgende Lektüre:&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Intel_HEX Wikipedia Artikel über HEX-Files]&lt;br /&gt;
* [http://www.rn-wissen.de/index.php/HEX-Datei RN-Wissen-Artikel über HEX-Files]&lt;br /&gt;
* [http://www.schulz-koengen.de/biblio/intelhex.htm Artikel von Wolfgang R.Schulz]&lt;br /&gt;
&lt;br /&gt;
Unser Bootloader muss in der Lage sein, dieses Format zu interpretieren. Wir müssen also einen Parser schreiben. &#039;&#039;Oje&#039;&#039; werden manche denken, das ist ja wieder ein Thema für sich. Das stimmt prinzipiell auch. Allerdings kommt uns hier das einfache Format der Intel-Hex-Datei zugute, welches den Aufwand in Grenzen hält.&lt;br /&gt;
&lt;br /&gt;
Also erstes brauchen wir also Funktionen, um die ASCII-Zeichenfolgen wieder in Binärdaten umzuwandeln. Normalerweise könnte man dafür die C-Funktion [http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#gaf8ce3b8dae3d45c34c3b172de503f7b3 strtol] aus der stdlib.h nehmen. Allerdings würde das Benutzen dieses Befehls das Linken der Standardbibliothek nach sich ziehen und damit den Code unnötig aufblähen. Daher werden wir uns eine einfache eigene Funktion schreiben, um die Zeichenfolgen umzuwandeln. In der HEX-Datei kommen 2 Byte und 4 Byte Hex-Zahlen im ASCII-Format vor. Wir brauchen also eine Funktion, welche die ASCII-Zeichenfolgen in Zahlen umwandelt, hier ist sie:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
static uint16_t hex2num(const uint8_t * ascii, uint8_t num)&lt;br /&gt;
{&lt;br /&gt;
    uint8_t  i;&lt;br /&gt;
    uint16_t val = 0;&lt;br /&gt;
 &lt;br /&gt;
    for (i=0; i&amp;lt;num; i++)&lt;br /&gt;
    {&lt;br /&gt;
        uint8_t c = ascii[i];&lt;br /&gt;
        &lt;br /&gt;
        /* Hex-Ziffer auf ihren Wert abbilden */&lt;br /&gt;
        if (c &amp;gt;= &#039;0&#039; &amp;amp;&amp;amp; c &amp;lt;= &#039;9&#039;)            c -= &#039;0&#039;;  &lt;br /&gt;
        else if (c &amp;gt;= &#039;A&#039; &amp;amp;&amp;amp; c &amp;lt;= &#039;F&#039;)       c -= &#039;A&#039; - 10;&lt;br /&gt;
        else if (c &amp;gt;= &#039;a&#039; &amp;amp;&amp;amp; c &amp;lt;= &#039;f&#039;)       c -= &#039;a&#039; - 10;&lt;br /&gt;
            &lt;br /&gt;
        val = 16 * val + c;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return val;  &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Wir benutzen hier einen sehr einfachen Ansatz, um die Zahlen zu generieren. Die Funktionen wandeln die ASCII-Zeichen entsprechend ihrer Wertigkeit in Zahlen um. Soll z.B. das ASCII-Zeichen &#039;1&#039; umgewandelt werden, wird vom ASCII-Code &#039;1&#039;, also dezimal 49, 48=&#039;0&#039; abgezogen: 49 - 48 = 1, somit haben wir ein ASCII-Zeichen in eine Zahl umgewandelt. Wenn das ASCII-Zeichen &#039;C&#039; ist (Dezimal: 67), werden &#039;A&#039; - 10 = 65 -10 = 55 abgezogen, um 12 zu erhalten, den Wert der hex-Ziffer C. Näher möchte an dieser Stelle nicht darauf eingehen, wir wollen schnell weiter zum Beschreiben des Flashs kommen.&lt;br /&gt;
&lt;br /&gt;
Um in den Flash zu schreiben, werden wir Makros aus der &#039;&#039;[http://www.nongnu.org/avr-libc/user-manual/group__avr__boot.html boot.h]&#039;&#039; der avr-libc verwenden. Hier findet man alle Werkzeuge, die wir brauchen. Dabei sollte vor allen das &#039;&#039;API Usage Example&#039;&#039; in der [http://www.nongnu.org/avr-libc/user-manual/group__avr__boot.html Online Doku] näher betrachtet werden. Dieses Beispiel soll weitestgehend übernommen werden, da es die nötige Funktionalität beinhaltet. Hier ist die Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
void boot_program_page (uint32_t page, uint8_t *buf)&lt;br /&gt;
{&lt;br /&gt;
    uint16_t i;&lt;br /&gt;
    uint8_t sreg;&lt;br /&gt;
&lt;br /&gt;
    /* Disable interrupts.*/&lt;br /&gt;
    sreg = SREG;&lt;br /&gt;
    cli();&lt;br /&gt;
&lt;br /&gt;
    eeprom_busy_wait ();&lt;br /&gt;
&lt;br /&gt;
    boot_page_erase (page);&lt;br /&gt;
    boot_spm_busy_wait ();      /* Wait until the memory is erased. */&lt;br /&gt;
&lt;br /&gt;
    for (i=0; i&amp;lt;SPM_PAGESIZE; i+=2)&lt;br /&gt;
    {&lt;br /&gt;
        /* Set up little-endian word. */&lt;br /&gt;
        uint16_t w = *buf++;&lt;br /&gt;
        w += (*buf++) &amp;lt;&amp;lt; 8;&lt;br /&gt;
    &lt;br /&gt;
        boot_page_fill (page + i, w);&lt;br /&gt;
    }&lt;br /&gt;
    boot_page_write (page);     /* Store buffer in flash page.		*/&lt;br /&gt;
    boot_spm_busy_wait();       /* Wait until the memory is written.*/&lt;br /&gt;
&lt;br /&gt;
    /* Reenable RWW-section again. We need this if we want to jump back */&lt;br /&gt;
    /* to the application after bootloading. */&lt;br /&gt;
    boot_rww_enable ();&lt;br /&gt;
&lt;br /&gt;
    /* Re-enable interrupts (if they were ever enabled). */&lt;br /&gt;
    SREG = sreg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Als erstes fällt auf, dass man der Funktion die &#039;&#039;Page&#039;&#039;-Adresse übergibt. Es wird also immer seitenweise geschrieben. Dies ist eine Spezialität des Flash-Speichers. Es &#039;&#039;&#039;muss&#039;&#039;&#039; immer die gesamte Seite geschrieben werden, dafür gibt es einen &#039;&#039;Page&#039;&#039;-Puffer, welcher die Daten enthält, welche mit der nächsten Schreiboperation in die entsprechende Page geschrieben werden. Dabei werden die Daten Wortweise in den &#039;&#039;Page&#039;&#039;-Puffer geschrieben. Die wesentlichen Funktionen der Routine sind &#039;&#039;boot_page_erase(page)&#039;&#039;, &#039;&#039;boot_page_fill(page + i, w)&#039;&#039; und &#039;&#039;boot_page_write(page)&#039;&#039;. Nicht zu vergessen auch &#039;&#039;boot_spm_busy_wait()&#039;&#039;. Die Bedeutung der Funktionen (naja es sind eher Makros) findet man in der Dokumentation der AVR Libc. Im wesentlichen läuft das Schreiben einer &#039;&#039;Page&#039;&#039; so ab:&lt;br /&gt;
* &#039;&#039;Page&#039;&#039; löschen&lt;br /&gt;
* &#039;&#039;Page&#039;&#039;-Puffer befüllen (aus der Variable &#039;&#039;buf&#039;&#039;)&lt;br /&gt;
* &#039;&#039;Page&#039;&#039; schreiben&lt;br /&gt;
So einfach, so gut. Für den Bootloader bedeutet das, dass er die Daten sammeln muß, bis er genügend Daten für eine &#039;&#039;Page&#039;&#039; hat. Dann wird eine &#039;&#039;Page&#039;&#039; geschrieben und der Spaß fängt von vorn an.&lt;br /&gt;
&lt;br /&gt;
Mit diesen beiden Funktionen sind wir nun in der Lage, den Parser zu schreiben. Die &#039;&#039;main.c&#039;&#039; sieht folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/boot.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#define BOOT_UART_BAUD_RATE     9600     /* Baudrate */&lt;br /&gt;
#define XON                     17       /* XON Zeichen */&lt;br /&gt;
#define XOFF                    19       /* XOFF Zeichen */&lt;br /&gt;
#define START_SIGN              &#039;:&#039;      /* Hex-Datei Zeilenstartzeichen */&lt;br /&gt;
&lt;br /&gt;
/* Zustände des Bootloader-Programms */&lt;br /&gt;
#define BOOT_STATE_EXIT	        0        &lt;br /&gt;
#define BOOT_STATE_PARSER       1&lt;br /&gt;
&lt;br /&gt;
/* Zustände des Hex-File-Parsers */&lt;br /&gt;
#define PARSER_STATE_START      0&lt;br /&gt;
#define PARSER_STATE_SIZE       1&lt;br /&gt;
#define PARSER_STATE_ADDRESS    2&lt;br /&gt;
#define PARSER_STATE_TYPE       3&lt;br /&gt;
#define PARSER_STATE_DATA       4&lt;br /&gt;
#define PARSER_STATE_CHECKSUM   5&lt;br /&gt;
#define PARSER_STATE_ERROR      6&lt;br /&gt;
&lt;br /&gt;
void program_page (uint32_t page, uint8_t *buf)&lt;br /&gt;
{&lt;br /&gt;
    uint16_t i;&lt;br /&gt;
    uint8_t sreg;&lt;br /&gt;
&lt;br /&gt;
    /* Disable interrupts */&lt;br /&gt;
    sreg = SREG;&lt;br /&gt;
    cli();&lt;br /&gt;
&lt;br /&gt;
    eeprom_busy_wait ();&lt;br /&gt;
&lt;br /&gt;
    boot_page_erase (page);&lt;br /&gt;
    boot_spm_busy_wait ();      /* Wait until the memory is erased. */&lt;br /&gt;
&lt;br /&gt;
    for (i=0; i&amp;lt;SPM_PAGESIZE; i+=2)&lt;br /&gt;
    {&lt;br /&gt;
        /* Set up little-endian word. */&lt;br /&gt;
        uint16_t w = *buf++;&lt;br /&gt;
        w += (*buf++) &amp;lt;&amp;lt; 8;&lt;br /&gt;
    &lt;br /&gt;
        boot_page_fill (page + i, w);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    boot_page_write (page);     /* Store buffer in flash page.		*/&lt;br /&gt;
    boot_spm_busy_wait();       /* Wait until the memory is written.*/&lt;br /&gt;
&lt;br /&gt;
    /* Reenable RWW-section again. We need this if we want to jump back */&lt;br /&gt;
    /* to the application after bootloading. */&lt;br /&gt;
    boot_rww_enable ();&lt;br /&gt;
&lt;br /&gt;
    /* Re-enable interrupts (if they were ever enabled). */&lt;br /&gt;
    SREG = sreg;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static uint16_t hex2num (const uint8_t * ascii, uint8_t num)&lt;br /&gt;
{&lt;br /&gt;
    uint8_t  i;&lt;br /&gt;
    uint16_t val = 0;&lt;br /&gt;
&lt;br /&gt;
    for (i=0; i&amp;lt;num; i++)&lt;br /&gt;
    {&lt;br /&gt;
        uint8_t c = ascii[i];&lt;br /&gt;
        &lt;br /&gt;
        /* Hex-Ziffer auf ihren Wert abbilden */&lt;br /&gt;
        if (c &amp;gt;= &#039;0&#039; &amp;amp;&amp;amp; c &amp;lt;= &#039;9&#039;)            c -= &#039;0&#039;;  &lt;br /&gt;
        else if (c &amp;gt;= &#039;A&#039; &amp;amp;&amp;amp; c &amp;lt;= &#039;F&#039;)       c -= &#039;A&#039; - 10;&lt;br /&gt;
        else if (c &amp;gt;= &#039;a&#039; &amp;amp;&amp;amp; c &amp;lt;= &#039;f&#039;)       c -= &#039;a&#039; - 10;&lt;br /&gt;
            &lt;br /&gt;
        val = 16 * val + c;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    return val;  &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
                    /* Empfangenes Zeichen + Statuscode */&lt;br /&gt;
    uint16_t        c = 0, &lt;br /&gt;
                    /* Intel-HEX Zieladresse */&lt;br /&gt;
           	    hex_addr = 0,&lt;br /&gt;
                    /* Zu schreibende Flash-Page */&lt;br /&gt;
                    flash_page = 0,                    &lt;br /&gt;
                    /* Intel-HEX Checksumme zum Überprüfen des Daten */&lt;br /&gt;
                    hex_check = 0,&lt;br /&gt;
                    /* Positions zum Schreiben in der Datenpuffer */&lt;br /&gt;
                    flash_cnt = 0;&lt;br /&gt;
                    /* temporäre Variable */&lt;br /&gt;
    uint8_t         temp,&lt;br /&gt;
                    /* Flag zum steuern des Programmiermodus */&lt;br /&gt;
                    boot_state = BOOT_STATE_EXIT,&lt;br /&gt;
                    /* Empfangszustandssteuerung */&lt;br /&gt;
                    parser_state = PARSER_STATE_START,&lt;br /&gt;
                    /* Flag zum ermitteln einer neuen Flash-Page */&lt;br /&gt;
                    flash_page_flag = 1,&lt;br /&gt;
                    /* Datenpuffer für die Hexdaten*/&lt;br /&gt;
                    flash_data[SPM_PAGESIZE], &lt;br /&gt;
                    /* Position zum Schreiben in den HEX-Puffer */&lt;br /&gt;
                    hex_cnt = 0, &lt;br /&gt;
                    /* Puffer für die Umwandlung der ASCII in Binärdaten */&lt;br /&gt;
                    hex_buffer[5], &lt;br /&gt;
                    /* Intel-HEX Datenlänge */&lt;br /&gt;
                    hex_size = 0,&lt;br /&gt;
                    /* Zähler für die empfangenen HEX-Daten einer Zeile */&lt;br /&gt;
                    hex_data_cnt = 0, &lt;br /&gt;
                    /* Intel-HEX Recordtype */&lt;br /&gt;
                    hex_type = 0, &lt;br /&gt;
                    /* empfangene HEX-Checksumme */&lt;br /&gt;
                    hex_checksum=0;&lt;br /&gt;
                    /* Funktionspointer auf 0x0000 */&lt;br /&gt;
    void            (*start)( void ) = 0x0000; &lt;br /&gt;
 &lt;br /&gt;
    /* Füllen der Puffer mit definierten Werten */&lt;br /&gt;
    memset(hex_buffer, 0x00, sizeof(hex_buffer));&lt;br /&gt;
    memset(flash_data, 0xFF, sizeof(flash_data));&lt;br /&gt;
 &lt;br /&gt;
    /* Interrupt Vektoren verbiegen */&lt;br /&gt;
    temp = MCUCR;&lt;br /&gt;
    MCUCR = temp | (1&amp;lt;&amp;lt;IVCE);&lt;br /&gt;
    MCUCR = temp | (1&amp;lt;&amp;lt;IVSEL);&lt;br /&gt;
 &lt;br /&gt;
    /* Einstellen der Baudrate und aktivieren der Interrupts */&lt;br /&gt;
    uart_init( UART_BAUD_SELECT(BOOT_UART_BAUD_RATE,F_CPU) ); &lt;br /&gt;
    sei();&lt;br /&gt;
 &lt;br /&gt;
    uart_puts(&amp;quot;Hallo hier ist der echte Bootloader\n\r&amp;quot;);&lt;br /&gt;
    _delay_ms(2000);&lt;br /&gt;
 &lt;br /&gt;
    do&lt;br /&gt;
    {&lt;br /&gt;
        c = uart_getc();&lt;br /&gt;
        if( !(c &amp;amp; UART_NO_DATA) )&lt;br /&gt;
        {&lt;br /&gt;
             /* Programmzustand: Parser */&lt;br /&gt;
             if(boot_state == BOOT_STATE_PARSER)&lt;br /&gt;
             {&lt;br /&gt;
                  switch(parser_state)&lt;br /&gt;
                  {&lt;br /&gt;
                      /* Warte auf Zeilen-Startzeichen */&lt;br /&gt;
                      case PARSER_STATE_START:			&lt;br /&gt;
                          if((uint8_t)c == START_SIGN) &lt;br /&gt;
                          {&lt;br /&gt;
                              uart_putc(XOFF);&lt;br /&gt;
                              parser_state = PARSER_STATE_SIZE;&lt;br /&gt;
                              hex_cnt = 0;&lt;br /&gt;
                              hex_check = 0;&lt;br /&gt;
                              uart_putc(XON);&lt;br /&gt;
                          }&lt;br /&gt;
                          break;&lt;br /&gt;
                      /* Parse Datengröße */&lt;br /&gt;
                      case PARSER_STATE_SIZE:	&lt;br /&gt;
                          hex_buffer[hex_cnt++] = (uint8_t)c;&lt;br /&gt;
                          if(hex_cnt == 2)&lt;br /&gt;
                          {&lt;br /&gt;
                              uart_putc(XOFF);&lt;br /&gt;
                              parser_state = PARSER_STATE_ADDRESS;&lt;br /&gt;
                              hex_cnt = 0;&lt;br /&gt;
                              hex_size = (uint8_t)hex2num(hex_buffer, 2);&lt;br /&gt;
                              hex_check += hex_size;&lt;br /&gt;
                              uart_putc(XON);&lt;br /&gt;
                           }&lt;br /&gt;
                           break;&lt;br /&gt;
                      /* Parse Zieladresse */&lt;br /&gt;
                      case PARSER_STATE_ADDRESS:&lt;br /&gt;
                          hex_buffer[hex_cnt++] = (uint8_t)c;&lt;br /&gt;
                          if(hex_cnt == 4)&lt;br /&gt;
                          {&lt;br /&gt;
                              uart_putc(XOFF);&lt;br /&gt;
                              parser_state = PARSER_STATE_TYPE;&lt;br /&gt;
                              hex_cnt = 0;&lt;br /&gt;
                              hex_addr = hex2num(hex_buffer, 4);&lt;br /&gt;
                              hex_check += (uint8_t) hex_addr;&lt;br /&gt;
                              hex_check += (uint8_t) (hex_addr &amp;gt;&amp;gt; 8);&lt;br /&gt;
                              if(flash_page_flag) &lt;br /&gt;
                              {&lt;br /&gt;
                                  flash_page = hex_addr - hex_addr % SPM_PAGESIZE;&lt;br /&gt;
                                  flash_page_flag = 0;&lt;br /&gt;
                              }&lt;br /&gt;
                              uart_putc(XON);&lt;br /&gt;
                           }&lt;br /&gt;
                           break;&lt;br /&gt;
                      /* Parse Zeilentyp */&lt;br /&gt;
                      case PARSER_STATE_TYPE:	&lt;br /&gt;
                           hex_buffer[hex_cnt++] = (uint8_t)c;&lt;br /&gt;
                           if(hex_cnt == 2)&lt;br /&gt;
                           {&lt;br /&gt;
                               uart_putc(XOFF);&lt;br /&gt;
                               hex_cnt = 0;&lt;br /&gt;
                               hex_data_cnt = 0;&lt;br /&gt;
                               hex_type = (uint8_t)hex2num(hex_buffer, 2);&lt;br /&gt;
                               hex_check += hex_type;&lt;br /&gt;
                               switch(hex_type)&lt;br /&gt;
                               {&lt;br /&gt;
                                   case 0: parser_state = PARSER_STATE_DATA; break;&lt;br /&gt;
                                   case 1: parser_state = PARSER_STATE_CHECKSUM; break;&lt;br /&gt;
                                   default: parser_state = PARSER_STATE_DATA; break;&lt;br /&gt;
                               }&lt;br /&gt;
                               uart_putc(XON);&lt;br /&gt;
                           }&lt;br /&gt;
                           break;&lt;br /&gt;
                      /* Parse Flash-Daten */&lt;br /&gt;
                      case PARSER_STATE_DATA:&lt;br /&gt;
                          hex_buffer[hex_cnt++] = (uint8_t)c;&lt;br /&gt;
                          if(hex_cnt == 2)&lt;br /&gt;
                          {&lt;br /&gt;
                              uart_putc(XOFF);&lt;br /&gt;
                              uart_putc(&#039;.&#039;);&lt;br /&gt;
                              hex_cnt = 0;&lt;br /&gt;
                              flash_data[flash_cnt] = (uint8_t)hex2num(hex_buffer, 2);&lt;br /&gt;
                              hex_check += flash_data[flash_cnt];&lt;br /&gt;
                              flash_cnt++;&lt;br /&gt;
                              hex_data_cnt++;&lt;br /&gt;
                              if(hex_data_cnt == hex_size)&lt;br /&gt;
                              {&lt;br /&gt;
                                  parser_state = PARSER_STATE_CHECKSUM;&lt;br /&gt;
                                  hex_data_cnt=0;&lt;br /&gt;
                                  hex_cnt = 0;&lt;br /&gt;
                              }&lt;br /&gt;
                              /* Puffer voll -&amp;gt; schreibe Page */&lt;br /&gt;
                              if(flash_cnt == SPM_PAGESIZE)&lt;br /&gt;
                              {&lt;br /&gt;
                                  uart_puts(&amp;quot;P\n\r&amp;quot;);&lt;br /&gt;
                                  _delay_ms(100);&lt;br /&gt;
                                  program_page((uint16_t)flash_page, flash_data);&lt;br /&gt;
                                  memset(flash_data, 0xFF, sizeof(flash_data));&lt;br /&gt;
                                  flash_cnt = 0;&lt;br /&gt;
                                  flash_page_flag = 1;&lt;br /&gt;
                              }&lt;br /&gt;
                              uart_putc(XON);&lt;br /&gt;
                          }&lt;br /&gt;
                          break;&lt;br /&gt;
                      /* Parse Checksumme */                             &lt;br /&gt;
                      case PARSER_STATE_CHECKSUM:&lt;br /&gt;
                          hex_buffer[hex_cnt++] = (uint8_t)c;&lt;br /&gt;
                          if(hex_cnt == 2)&lt;br /&gt;
                          {&lt;br /&gt;
                              uart_putc(XOFF);&lt;br /&gt;
                              hex_checksum = (uint8_t)hex2num(hex_buffer, 2);&lt;br /&gt;
                              hex_check += hex_checksum;&lt;br /&gt;
                              hex_check &amp;amp;= 0x00FF;&lt;br /&gt;
                              /* Dateiende -&amp;gt; schreibe Restdaten */ &lt;br /&gt;
                              if(hex_type == 1)&lt;br /&gt;
                              {&lt;br /&gt;
                                  uart_puts(&amp;quot;P\n\r&amp;quot;);&lt;br /&gt;
                                  _delay_ms(100);&lt;br /&gt;
                                  program_page((uint16_t)flash_page, flash_data);&lt;br /&gt;
                                  boot_state = BOOT_STATE_EXIT;&lt;br /&gt;
                              }&lt;br /&gt;
                              /* Überprüfe Checksumme -&amp;gt; muss &#039;0&#039; sein */&lt;br /&gt;
                              if(hex_check == 0) parser_state = PARSER_STATE_START;&lt;br /&gt;
                              else parser_state = PARSER_STATE_ERROR;&lt;br /&gt;
                              uart_putc(XON);&lt;br /&gt;
                          }&lt;br /&gt;
                          break;			&lt;br /&gt;
                      /* Parserfehler (falsche Checksumme) */&lt;br /&gt;
                      case PARSER_STATE_ERROR:&lt;br /&gt;
                          uart_putc(&#039;#&#039;);&lt;br /&gt;
                          break;			&lt;br /&gt;
                      default:&lt;br /&gt;
                          break;&lt;br /&gt;
                  }&lt;br /&gt;
             }&lt;br /&gt;
             /* Programmzustand: UART Kommunikation */               &lt;br /&gt;
             else if(boot_state != BOOT_STATE_PARSER)&lt;br /&gt;
             {&lt;br /&gt;
                 switch((uint8_t)c)&lt;br /&gt;
                 {&lt;br /&gt;
                     case &#039;p&#039;: &lt;br /&gt;
                         boot_state = BOOT_STATE_PARSER;&lt;br /&gt;
                         uart_puts(&amp;quot;Programmiere den Flash!\n\r&amp;quot;);&lt;br /&gt;
                         uart_puts(&amp;quot;Kopiere die Hex-Datei und füge sie&amp;quot;&lt;br /&gt;
                                   &amp;quot; hier ein (rechte Maustaste)\n\r&amp;quot;);&lt;br /&gt;
                         break;&lt;br /&gt;
                     case &#039;q&#039;: &lt;br /&gt;
                         boot_state = BOOT_STATE_EXIT;&lt;br /&gt;
                         uart_puts(&amp;quot;Verlasse den Bootloader!\n\r&amp;quot;);&lt;br /&gt;
                         break;&lt;br /&gt;
                     default:&lt;br /&gt;
                         uart_puts(&amp;quot;Du hast folgendes Zeichen gesendet: &amp;quot;);&lt;br /&gt;
                         uart_putc((unsigned char)c);&lt;br /&gt;
                         uart_puts(&amp;quot;\n\r&amp;quot;);&lt;br /&gt;
                         break;&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    while(boot_state!=BOOT_STATE_EXIT);&lt;br /&gt;
 &lt;br /&gt;
    uart_puts(&amp;quot;Reset AVR!\n\r&amp;quot;);&lt;br /&gt;
    _delay_ms(1000);&lt;br /&gt;
 &lt;br /&gt;
    /* Interrupt Vektoren wieder gerade biegen */&lt;br /&gt;
    temp = MCUCR;&lt;br /&gt;
    MCUCR = temp | (1&amp;lt;&amp;lt;IVCE);&lt;br /&gt;
    MCUCR = temp &amp;amp; ~(1&amp;lt;&amp;lt;IVSEL);&lt;br /&gt;
 &lt;br /&gt;
    /* Reset */&lt;br /&gt;
    start();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Erklärung des Codes&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Der Bootloader wird als &#039;&#039;Zustandsmaschine&#039;&#039; programmiert. Die Variable &#039;&#039;boot_state&#039;&#039; beinhaltet den aktuelle Programmzustand. Für den Parser gibt es eine eigene Zustandsvariable &#039;&#039;parser_state&#039;&#039;, welche die einzelne Zustände des Parsers hält. Mit jeder HEX-Datei-Zeile läuft der Parser einmal durch alle Zustände. Nach Abarbeiten des aktuellen Zustands und Auswertung der empfangenen Daten wird der nächste Zustand aktiviert usw. Für das Verarbeiten der Datei wird jedes Mal die Kommunikation angehalten und ein &#039;&#039;XOFF&#039;&#039; gesendet. Nach Abarbeitung der Daten gibt der Parser den seriellen Empfang wieder frei (&#039;&#039;XON&#039;&#039;). &#039;&#039;&#039;&#039;&#039;Es ist also wichtig, dass in PuTTY die XON/XOFF-Flußkontrolle aktiviert wird!&#039;&#039;&#039;&#039;&#039; Durch den interruptgesteuerten Empfang mit einem 32 Byte tiefen Empfangspuffer geht kein Byte verloren. Am Ende einer HEX-Datei-Zeile wird die Checksumme ausgewertet. Bei falscher Checksumme springt der Parser in den &#039;&#039;PARSER_STATE_ERROR&#039;&#039;, aus dem er nicht mehr rauskommt. Somit wird kein weiteres Byte in den Flash geschrieben. Zusätzlich könnte man noch implementieren, dass der Flash wieder gelöscht wird, wenn falsche Daten empfangen wurden, damit kein unvollständiges Programm im Flash steht.&lt;br /&gt;
Einschränkend muss noch festgehalten werden, das der Bootloader in dieser Fassung einen Adressraum bis 64K unterstützt (HEX-Zeilentyp 1). Die erweiterten Adressräume (HEX-Zeilentyp 2 bis 5) werden noch nicht unterstützt. Für ATmega-Devices mit &amp;gt; 64K Flash muss der Bootloader noch erweitert werden.&lt;br /&gt;
&lt;br /&gt;
Nach dem Kompilieren beträgt die Größe des Bootloaders 1796 Byte, wir sind also unterhalb der 2048 Byte die wir &amp;quot;verbraten&amp;quot; können. Der Datenspeicher wird mit 283 Byte belastet.&lt;br /&gt;
&lt;br /&gt;
Die Funktion des Bootloaders sieht wie folgt aus: Nach dem Reset wartet der Bootloader 2 Sekunden auf Eingaben (&#039;&#039;_delay_ms(2000);&#039;&#039;). Falls keine Eingaben von der Konsole kommen, springt der Bootloader zur Anwendung. Damit ist gewährleiset, dass die Anwendung später automatisch startet, auch wenn wir keine Taste drücken. Wird ein &#039;&#039;p&#039;&#039; gedrückt, springt der Bootloader in den &#039;&#039;BOOT_STATE_PARSER&#039;&#039; und erwartet eine HEX-Datei auf der Konsole. Dies ist der Zeitpunkt, die HEX-Datei der Anwendung mit Copy &amp;amp; Paste in die Konsole zu schreiben. Zum Einfügen von Daten aus dem Zwischenspeicher in die Konsole wird bei PuTTY die rechte Maustaste verwendet.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;WICHTIGER HINWEIS: &#039;&#039;&#039;&#039;&#039; Es hat sich gezeigt, das die Flußkontrolle durch XON/XOFF nicht immer funktioniert, da es eine Software-Flußsteuerung ist und u.U. der (UART-Sende-)Interrupt zu spät (oder gar nicht) ausgeführt wird. Bei Problemen beim Übertragen des HEX-Files sollte man als erstes versuchen die Baudrate zu senken (oder die Taktrate des Controllers erhöhen) um dem Controller mehr Zeit zum Verarbeiten und schnellerem Reagieren auf Interrupts zu geben.&lt;br /&gt;
&lt;br /&gt;
== Schritt 4 - Flashen und Ausprobieren des Bootloaders ==&lt;br /&gt;
Nach dem Flashen via AVRISPmkII startet der Bootloader in der Konsole. Da noch kein Anwendungsprogramm im Flash liegt, startet der Bootloader nach 2 Sekunden immer wieder neu. Nach Drücken der Taste &#039;&#039;p&#039;&#039; erwartet der Bootlader die HEX-Datei der Anwendung. Nach dem Einfügen der Datei in Konsole erscheint für jedes empfangene Byte ein Punkt (&amp;quot;.&amp;quot;). Das Beschreiben einer Flash-&#039;&#039;Page&#039;&#039; kenzeichnet ein &#039;&#039;P&#039;&#039;. Nach dem erfolgreichen Flashen startet die Anwendung automatisch.&lt;br /&gt;
&lt;br /&gt;
Nach erfolgreichem Flashen des Bootloaders via AVRISPmkII erscheint nach dem Reset folgendes Bild:&lt;br /&gt;
&lt;br /&gt;
[[Bild:PuTTY-Real-Bootloader-start.png|PuTTY: Bootloader nach dem Reset]]&lt;br /&gt;
&lt;br /&gt;
Drückt man die Taste &#039;&#039;&#039;p&#039;&#039;&#039;, springt ist der Bootloader bereit zum Empfang der HEX-Datei:&lt;br /&gt;
&lt;br /&gt;
[[Bild:PuTTY-Real-Bootloader-wait.png|PuTTY: Warten auf die HEX-Datei &amp;quot;Anwendung.hex&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
Nach Kopieren &amp;amp; Einfügen der HEX-Datei der vorher kompilierten Anwendung, hier die Intel-HEX-Datei &amp;quot;Anwendung.hex&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:100000002CC046C045C044C043C042C041C040C0EF&lt;br /&gt;
:100010003FC03EC03DC03CC03BC03AC039C038C004&lt;br /&gt;
:1000200037C036C064C08FC033C032C031C030C0AA&lt;br /&gt;
:100030002FC02EC048696572206973742064617393&lt;br /&gt;
:1000400020416E77656E64756E677370726F67724C&lt;br /&gt;
:10005000616D6D2E2E2E0D0A000011241FBECFEFF4&lt;br /&gt;
:10006000D4E0DEBFCDBF11E0A0E0B1E0EAE6F2E00F&lt;br /&gt;
:1000700002C005900D92A434B107D9F711E0A4E4B1&lt;br /&gt;
:10008000B1E001C01D92A938B107E1F702D0EBC081&lt;br /&gt;
:10009000B7CFEF92FF920F931F93CF93DF9383E33A&lt;br /&gt;
:1000A00090E07BD0789484E390E0D0D088ECE82E88&lt;br /&gt;
:1000B000F12C00E018E18BD0EC0190FDFCCF8236F2&lt;br /&gt;
:1000C00069F480E091E0B6D080E197E2F7013197E2&lt;br /&gt;
:1000D000F1F70197D9F7F8010995EDCF8CE191E09F&lt;br /&gt;
:1000E000A9D08C2F91D081E491E0A4D0E4CF1F92CD&lt;br /&gt;
:1000F0000F920FB60F9211242F938F939F93EF932C&lt;br /&gt;
:10010000FF939091C0002091C600E0918601EF5FBF&lt;br /&gt;
:10011000EF7180918701E81711F482E008C0892F00&lt;br /&gt;
:100120008871E0938601F0E0EC59FE4F20838093C4&lt;br /&gt;
:100130008801FF91EF919F918F912F910F900FBEAA&lt;br /&gt;
:100140000F901F9018951F920F920FB60F921124C7&lt;br /&gt;
:100150008F939F93EF93FF939091840180918501FA&lt;br /&gt;
:10016000981769F0E0918501EF5FEF71E0938501E9&lt;br /&gt;
:10017000F0E0EC5BFE4F80818093C60005C080916B&lt;br /&gt;
:10018000C1008F7D8093C100FF91EF919F918F916E&lt;br /&gt;
:100190000F900FBE0F901F9018959C011092840134&lt;br /&gt;
:1001A00010928501109286011092870197FF04C07A&lt;br /&gt;
:1001B00082E08093C0003F773093C5002093C40055&lt;br /&gt;
:1001C00088E98093C10086E08093C20008959091F1&lt;br /&gt;
:1001D000860180918701981719F420E031E012C060&lt;br /&gt;
:1001E000E0918701EF5FEF71E0938701F0E0EC5958&lt;br /&gt;
:1001F000FE4F308120918801922F80E0AC01430FA7&lt;br /&gt;
:10020000511D9A01C9010895282F909184019F5F83&lt;br /&gt;
:100210009F71809185019817E1F3E92FF0E0EC5B85&lt;br /&gt;
:10022000FE4F2083909384018091C100806280936F&lt;br /&gt;
:10023000C1000895CF93DF93EC0102C02196E4DF63&lt;br /&gt;
:1002400088818823D9F7DF91CF910895CF93DF93E9&lt;br /&gt;
:10025000EC0101C0D9DFFE01219684918823D1F7FA&lt;br /&gt;
:0A026000DF91CF910895F894FFCFCD&lt;br /&gt;
:10026A00537072696E6765207A756D20426F6F747C&lt;br /&gt;
:10027A006C6F616465722E2E2E0D0A00447520681B&lt;br /&gt;
:10028A0061737420666F6C67656E646573205A6566&lt;br /&gt;
:10029A00696368656E20676573656E6465743A2084&lt;br /&gt;
:0402AA00000A0D0039&lt;br /&gt;
:00000001FF&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
erscheinen folgende Ausgaben in PuTTY:&lt;br /&gt;
&lt;br /&gt;
[[Bild:PuTTY-Real-Bootloader-prog.png|PuTTY: Flashen der HEX-Datei &amp;quot;Anwendung.hex&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
Nach erfolgreichem Flashen startet die Anwendung und meldet sich mit der Zeile&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Hier ist das Anwendungsprogramm...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Jetzt können nach belieben Tasten gedrückt werden, was die Anwendung jedesmal quittiert:&lt;br /&gt;
&lt;br /&gt;
[[Bild:PuTTY-Real-Bootloader-anwend.png|PuTTY: Ausprobieren der Anwendung]]&lt;br /&gt;
&lt;br /&gt;
Nach Drücken der Taste &#039;&#039;&#039;b&#039;&#039;&#039; springt die Anwendung wieder zur Startadresse des Bootloaders, also zur Adresse &#039;&#039;0x1800&#039;&#039; im Flash-Speicher. Nun hat man wieder 2 Sekunden Zeit, um die Taste &#039;&#039;&#039;p&#039;&#039;&#039; zu drücken, sonst startet die Anwendung wieder:&lt;br /&gt;
&lt;br /&gt;
[[Bild:PuTTY-Real-Bootloader-reset.png|PuTTY: Rücksprung zum Bootloader auf Adresse 0x1800]]&lt;br /&gt;
&lt;br /&gt;
Damit ist das Tutorial abgeschlossen.&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Viel Spass beim Ausprobieren und Weiterentwickeln!&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Zusammenfassung =&lt;br /&gt;
&lt;br /&gt;
Wer den Artikel bis hier hin nachvollzogen hat, ist jetzt in der Lage einen Bootloader selbst zu schreiben. Dabei kann der Bootloader an jede in Frage kommende ATmega-Plattform angepaßt werden. Dazu muss&lt;br /&gt;
* die Linkereinstellung für das Verschieben der Sektion &#039;&#039;.text&#039;&#039; angepasst werden und (&#039;&#039;&#039;-Ttext = 0xXXXX&#039;&#039;&#039;)&lt;br /&gt;
* evtl. der virtuelle Funktionspointer in der Anwendung geändert werden (falls ein Rücksprung zum Bootloader gewünscht ist &#039;&#039;&#039;void (*bootloader)(void) = 0xXXXX&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Um dies zu erleichtern, habe ich hier die Sprungadressen für ausgewählte AVRs tabellarisch zusammengetragen. Dabei wurde immer die maximale Größe des Bootloader betrachtet, also &#039;&#039;&#039;BOOTSZ0=0&#039;&#039;&#039; und &#039;&#039;&#039;BOOTSZ1=0&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Größe und Startadresse der Bootloader Sektion für ausgewählte AVR-Devices&lt;br /&gt;
|- &lt;br /&gt;
! Device || Flash-Größe&amp;lt;br&amp;gt;für Applikation || Flash-Größe&amp;lt;br&amp;gt;des Bootloaders || Startadresse des Bootloaders&amp;lt;br&amp;gt;(Byteadresse)&lt;br /&gt;
|-&lt;br /&gt;
| ATmega8/88 || 6144 Byte || 2048 Byte || 0x1800&lt;br /&gt;
|-&lt;br /&gt;
| ATmega16/164/168 || 14336 Byte || 2048 Byte || 0x3800&lt;br /&gt;
|-&lt;br /&gt;
| ATmega32/324/328 || 28672 Byte || 4096 Byte || 0x7000&lt;br /&gt;
|-&lt;br /&gt;
| ATmega64/644/640 || 57344 Byte || 8192 Byte || 0xE000&lt;br /&gt;
|-&lt;br /&gt;
| ATmega128/1284/1280/1281 || 122880 Byte || 8192 Byte || 0x1E000&lt;br /&gt;
|-&lt;br /&gt;
| ATmega2560/2561 ||  253952 Byte || 8192 Byte || 0x3E000&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Damit kann jeder den Bootloader nach seinen Wünschen anpassen. Eine gängige Praxis ist auch, ein kleines PC-Programm zu schreiben, welches dem Bootloader die Flash-Daten gleich Binär übergibt. Das geht schneller und spart das aufwendige interpretieren der Daten (Parsen). Eine weitere Idee ist es, den Bootloader so anzupassen, das er sich wie ein STK500 an der seriellen Schnittstelle verhält. Dazu muss man die [http://www.atmel.com/dyn/products/tools_card.asp?tool_id=2735 AP068] von Atmel umsetzen. Auch dies sollte nach dem Studium des Tutorial kein Problem mehr sein :)&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/user/show/mario Nachricht an den Autor]&lt;br /&gt;
&lt;br /&gt;
= FAQ =&lt;br /&gt;
&lt;br /&gt;
== Wie kann man Bootloader und Anwendungsprogramm gemeinsam flashen? ==&lt;br /&gt;
&lt;br /&gt;
Es ist in C ohne weiteres nicht möglich ein gemeinsames Hexfile aus Bootloader und Anwendungsprogramm zu kompilieren. Aber man kann das getrennt erstellte Hexfile des Bootloaders und das getrennt erstellte Hexfile des Anwendungsprogramms zusammenfügen und so gemeinsam mit ISP flashen. Dazu die letzte Zeile des 1. Hexfiles entfernen und dahinter das 2. Hexfile anfügen [http://www.mikrocontroller.net/topic/199241#1955092], [http://www.mikrocontroller.net/topic/198428#1949164]. &lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Programmer und -Bootloader|B]]&lt;/div&gt;</summary>
		<author><name>Sebion7125</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_Bootloader_in_C_-_eine_einfache_Anleitung&amp;diff=57269</id>
		<title>AVR Bootloader in C - eine einfache Anleitung</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_Bootloader_in_C_-_eine_einfache_Anleitung&amp;diff=57269"/>
		<updated>2011-05-20T11:09:12Z</updated>

		<summary type="html">&lt;p&gt;Sebion7125: /* Schritt 3 - Programmieren des Bootloaders */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Dieser Artikel soll dazu dienen, das Thema [[Bootloader]] im AVR etwas zu demystifizieren.&lt;br /&gt;
&lt;br /&gt;
Es gibt schon einige Artikel und Codebeispiele für verschiedene Bootloader in Assembler oder C (bzw. gemischt), aber kein Artikel beleuchtet das Thema von einer einfachen Seite aus Anwendungssicht. In diese Lücke zielt dieses Tutorial.&lt;br /&gt;
Es soll anhand von Beispielen einen möglichst einfachen, verständlichen und nachvollziehbaren Weg zeigen, sich mit Hilfe der Hochsprache C in das Thema einzuarbeiten (dabei soll weder Assembler noch Inline-Assembler verwendet werden). &lt;br /&gt;
&lt;br /&gt;
Vielleicht werden einige meinen dass es nicht möglich ist das Thema ohne tieferen Einblick in die Hardware und die AVR-Register zu beleuchten, ich möchte es aber trotzdem versuchen.&lt;br /&gt;
&lt;br /&gt;
Der Artikel wird sich auf das notwendige Wissen beschränken, um mit Booloadern arbeiten zu können. Es wird ein genereller Weg gezeigt, der sich leicht auf andere AVR-Devices (mit Bootloader Sektion) übertragen lässt.&lt;br /&gt;
Die Codebeispiele wurden für den ATmega88 kompiliert und getestet.&lt;br /&gt;
&lt;br /&gt;
== Einleitung ==&lt;br /&gt;
&lt;br /&gt;
Zu Beginn soll das notwendige Wissen über die Bootloaderunterstützung im AVR vermittelt werden, um eine Arbeitsgrundlage zu schaffen.&lt;br /&gt;
&lt;br /&gt;
Im weiteren Verlauf des Artikels werden insgesamt drei Anwendungen programmiert: Zuerst ein einfacher Bootloader, welcher in der Bootloadersektion des Flashs ausgeführt wird, aber noch keine eigentliche Bootloader-Funktion hat, sozusagen ein &amp;quot;Hallo Welt&amp;quot;-Bootloader. Danach soll eine kleine Applikation programmiert werden, welche der spätere &#039;&#039;echte&#039;&#039; Bootloader ins Flash programmieren soll. Als großes Finale soll dann ein Bootloader entstehen, welcher in der Lage ist, Intel-HEX-Dateien über die serielle Schnittstelle zu laden, ins Flash zu programmieren und zu starten.&lt;br /&gt;
&lt;br /&gt;
Der Leser sollte bereits Erfahrungen im Umgang mit dem AVR Studio und der Programmiersprache C gemacht haben und schon Anwendungen geschrieben haben. Für absolute Einsteiger ist der Artikel ungeeignet.&lt;br /&gt;
&lt;br /&gt;
Den Thread zum Artikel gibt es hier: http://www.mikrocontroller.net/topic/195102&lt;br /&gt;
&lt;br /&gt;
== Software ==&lt;br /&gt;
&lt;br /&gt;
Für den Artikel werden folgende Software-Pakete benötigt:&lt;br /&gt;
&lt;br /&gt;
* aktuelles [http://http://www.atmel.com/dyn/products/tools_card.asp?tool_id=2725 AVR Studio] (hier verwendet: AVR Studio v4.18) &lt;br /&gt;
* aktuelles [http://sourceforge.net/projects/winavr/files/ WinAVR] (hier verwendet: WinAVR20100110)&lt;br /&gt;
* [http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html PuTTY] als serielle Konsole (Version v0.6)&lt;br /&gt;
&lt;br /&gt;
Des weiteren wurde auf der AVR-Seite für die serielle Kommunikation mit dem PC auf die beliebte UART-Library von [http://www.jump.to/fleury Peter Fleury] zurückgegriffen, damit wir uns nicht um die gepufferte UART-Kommunikation kümmern müssen.&lt;br /&gt;
&lt;br /&gt;
== Hardware ==&lt;br /&gt;
&lt;br /&gt;
Für den Artikel wurde eine kleine Hardware bestehend aus einem [http://www.atmel.com/dyn/products/product_card.asp?part_id=3302 Atmega88] und einem [http://www.ftdichip.com/Products/ICs/FT232R.htm FT232] als USB-Seriell-Wandler erstellt. Dies soll als Basis für die Experimente dienen. Der USB-Seriell-Wandler ist nicht zwingend notwendig und kann auch durch den üblichen Pegelwandler vom Typ [http://www.maxim-ic.com/datasheet/index.mvp/id/1798/ln/en MAX232] ersetzt werden, wenn der PC noch eine serielle Schnittstelle besitzt. Entscheidend ist nur die Möglichkeit der seriellen Kommunikation mit dem Rechner.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Schaltplan-ATmega88-USB.png|800px|Schaltplan]]&lt;br /&gt;
&lt;br /&gt;
Für die ISP-Programmierung wurde der [http://www.atmel.com/dyn/products/tools_card.asp?tool_id=3808 AVRISPmkII-In-System-Programmer] von Atmel verwendet. Es kann natürlich auch ein anderer Programmer (z.B. [http://www.atmel.com/dyn/products/tools_card.asp?tool_id=2735 STK500]) verwendet werden, welcher mit dem AVR Studio zusammenarbeitet. Prinzipiell kann natürlich auch ein selbstgebastelter Parallel-Programmer verwendet werden, dann kann aber nicht via AVR Studio programmiert werden, sondern mit [http://www.nongnu.org/avrdude/ AVRDude] oder [http://www.lancos.com/prog.html PonyProg] o.ä. Der Artikel beschränkt sich auf die Verwendung vom AVR Studio.&lt;br /&gt;
&lt;br /&gt;
Für das Verständis der Hardware und der seriellen Kommunikation sind folgende Artikel empfehlenswert:&lt;br /&gt;
&lt;br /&gt;
* [[AVR-Tutorial: UART]]&lt;br /&gt;
* [[RS-232]]&lt;br /&gt;
&lt;br /&gt;
= Grundlagen =&lt;br /&gt;
&lt;br /&gt;
[[Bild:AVR-Memory.png|400px|thumb|Flash Speicher Aufteilung]]&lt;br /&gt;
&lt;br /&gt;
Was ist eigentlich ein Bootloader und was macht er? Wofür sollte ich so etwas brauchen? Ist das nicht viel zu kompliziert? Ich bin eingefleischter AVR Studio-Benutzer, muss ich mich jetzt mit makefiles beschäftigen? Kann man im AVR Studio mit C überhaupt einen Bootloader schreiben? Vielleicht hat sich der eine oder andere schon einmal diese oder ähnliche Fragen gestellt. &lt;br /&gt;
&lt;br /&gt;
Der Programmcode des AVR steht in seinem Flashspeicher und wird von dort ausgeführt. Normalerweise kann während der Ausführung des Programms nicht auf den Flashspreicher geschrieben werden. Dies ist auch einleuchtend da sich das Programm ja sonst selbst überschreiben oder löschen könnte. Das Beschreiben des Flashs erfolgt beim AVR üblicherweise über die ISP-Schnittstelle, dabei befindet sich der Controller im Reset und es wird kein Programm ausgeführt. Dies ist für Prototyping und kleine Anwendungen hinnehmbar. Ist der Controller allerdings in einem größeren System oder in größerer räumlicher Entfernung verbaut und die ISP-Schnittstelle nicht mehr zugänglich, ist ein Update der Firmware nicht mehr ohne Weiteres möglich oder sehr teuer und aufwendig. Hier kann ein Bootloader Abhilfe schaffen, in dem er das Anwendungsprogramm auf einer definierten Schnittstelle entgegennimmt (UART, I2C, Wireless) und ins Flash transferiert. Ein Bootloader ist also in erster Linie ein kleines Programm, welches in einem besonderem Teil des Flash steht - der &#039;&#039;&#039;Boot Loader Section&#039;&#039;&#039;.  Durch die Lokalisierung des Bootloader-Programms in dieser besonderen Sektion des AVR ist es dem Programm möglich, auf Teile des Flashs - der sogenannten &#039;&#039;&#039;Application Flash Section&#039;&#039;&#039; - zu schreiben. Die eigentliche Anwendung wird ausschließlich in der &#039;&#039;&#039;Application Flash Section&#039;&#039;&#039; ausgeführt. Wenn man so will, können im Flash des AVR also zwei unabhängige Programme stehen. Der Flash ist in zwei Bereiche mit unterschiedlichen Merkmalen aufgeteilt (siehe Bild). Auf die RWW bzw. NRWW-Sektion möchte ich an dieser Stelle (noch) nicht eingehen.&lt;br /&gt;
&lt;br /&gt;
Wie man unschwer erkennen kann, liegt der Bootloader-Bereich am Ende des Flash-Speichers. Normalerweise startet der Controller die Abarbeitung seiner Programmierung an der Stelle 0x0000. Ein Bootloader soll ja aber &#039;&#039;&#039;vor&#039;&#039;&#039; der Abarbeitung der eigentlichen Applikation ausgeführt werden. Woher weiß also der AVR-Controller nach dem Reset, dass er nicht von Adresse 0x0000 sondern einer anderen Adresse starten soll? Diese Konfiguration ist wie alle wichtigen und grundlegenden Konfigurationen über die Fuses des AVRs geregelt. Wir beginnen mit der folgende Tabelle, welche die Speicheraufteilung des Programmspeichers veranschaulicht.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Boot Size Konfiguration, Tabelle 26-6 im Atmega88-Datenblatt S.280&lt;br /&gt;
|- &lt;br /&gt;
! BOOTSZ1 || BOOTSZ0 || Boot&amp;lt;br&amp;gt;Size || Pages || Application&amp;lt;br&amp;gt;Flash Section || Boot Loader&amp;lt;br&amp;gt;Flash Section || End&amp;lt;br&amp;gt;Application&amp;lt;br&amp;gt;Section || Boot Reset&amp;lt;br&amp;gt;(Start Boot&amp;lt;br&amp;gt;Loader Section)&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 1 || 128 words || 4 || 0x000 - 0xF7F || 0xF80 - 0xFFF || 0xF7F || 0xF80&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 0 || 256 words || 8 || 0x000 - 0xEFF || 0xF00 - 0xFFF || 0xEFF || 0xF00&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 1 || 512 words || 16 || 0x000 - 0xDFF || 0xE00 - 0xFFF || 0xDFF || 0xE00&lt;br /&gt;
|-&lt;br /&gt;
| 0 || 0 || 1024 words || 32 || 0x000 - 0xBFF || 0xC00 - 0xFFF || 0xBFF || 0xC00&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Um die Tabelle zu verstehen muss man wissen, dass der Flash-Speicher intern in sogenannten &#039;&#039;Pages&#039;&#039; (Seiten) organisiert ist. Die Multiplikation der &#039;&#039;Page&#039;&#039;-Größe mit der Anzahl der &#039;&#039;Pages&#039;&#039; ergibt die Speichergröße. Die Größe einer &#039;&#039;Page&#039;&#039; steht im Datenblatt und ist in &#039;&#039;Words&#039;&#039; - also Datenworte - angegeben. Ein Datenwort entspricht zwei Bytes. &#039;&#039;&#039;&#039;&#039;Hier offenbart sich eine Tücke des Datenblatts: Alle Speicherbezüge und Adressen sind in Datenworten  (also immer 2 Bytes) angegeben!&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
Aus der Tabelle erfahren wir auch, dass man mit den beiden Fuses &#039;&#039;&#039;BOOTSZ0&#039;&#039;&#039; und &#039;&#039;&#039;BOOTSZ1&#039;&#039;&#039; die Größe des Bootloaderbereichs einstellen kann. Eine weitere Tabelle aus dem Atmega88-Datenblatt gibt Auskunft über die Aufteilung der Pages und die Anzahl der Datenworte einer Page.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ No.of Words in a Page and No.of Pages in Flash, Tabelle 27-9 im Atmega88-Datenblatt S.288&lt;br /&gt;
|- &lt;br /&gt;
!  Device || Flash Size || Page Size || PCWORD || No. of Pages || PCPAGE || PCMSB&lt;br /&gt;
|-&lt;br /&gt;
| Atmega88 || 4K words (8 Kbytes) || 32 words || PC[4:0] || 128 || PC[11:5] || 11&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Aus der Tabelle ergibt sich, dass die Größe einer &#039;&#039;Page&#039;&#039; des verwendeten Atmega88 32 &#039;&#039;Words&#039;&#039; - also 64 Byte sind. Insgesamt gibt es 128 &#039;&#039;Pages&#039;&#039;, damit ergibt sich nach Adam Riese 128 * 64 = 8192 Byte, also 8 Kbytes. In unserem späteren Codebeispiel soll die Größe des Bootloaderbereichs auf 1024 &#039;&#039;words&#039;&#039; - also 2048 Bytes gestellt werden (&#039;&#039;&#039;BOOTSZ0=0&#039;&#039;&#039; und &#039;&#039;&#039;BOOTSZ1=0&#039;&#039;&#039;). Nun können wir ausrechnen, in welcher Flash-&#039;&#039;Page&#039;&#039; bzw. an welcher Flash-Adresse der Bootloaderbereich beginnt: Er beginnt in der 96 &#039;&#039;Page&#039;&#039; (128 - 32) an &#039;&#039;Word&#039;&#039;-Adresse 0xC00, also Byteadresse 0xC00 * 2 = 0x1800. Dies ist die exakte Startadresse unseres Bootloaderbereiches.&lt;br /&gt;
&lt;br /&gt;
Weiter oben wurde die Frage gestellt, woher der AVR weiß, an welcher Stelle (entweder 0x0000 oder in unserem Fall 0x1800) er nach dem Reset starten soll. Um dem AVR dies mitzuteilen, ist eine weitere Fuse nötig - die &#039;&#039;&#039;BOOTRST&#039;&#039;&#039;-Fuse. Eine weitere Tabelle aus dem Atmega88-Datenblatt gibt Auskunft über diese Fuse.&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Reset and Interrupt Vectors Placement in Atmega88, Tabelle 11-3 im Atmega88-Datenblatt S.58&lt;br /&gt;
|- &lt;br /&gt;
!  BOOTRST|| IVSEL || Reset Adress || Interrupt Vectors Start Adress&lt;br /&gt;
|-&lt;br /&gt;
| 1 || 0 || 0x000 || 0x001 &lt;br /&gt;
|-&lt;br /&gt;
| 1 || 1 || 0x000 || Boot Reset Address + 0x001 &lt;br /&gt;
|-&lt;br /&gt;
| 0 || 0 || Boot Reset Address || 0x001 &lt;br /&gt;
|-&lt;br /&gt;
| 0 || 1 || Boot Reset Address || Boot Reset Address + 0x001 &lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Mit der &#039;&#039;&#039;BOOTRST&#039;&#039;&#039;-Fuse wird festgelegt, dass der AVR nach dem Reset an die Startadresse der Bootloader Sektion im Flash springt. Auf das &#039;&#039;&#039;IVSEL&#039;&#039;&#039;-Bit (keine Fuse) möchte ich erst an späterer Stelle - wenn es um Interrupts geht - zurückkommen.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Noch ein wichtiger Hinweis für die Werte der Fuses im Datenblatt:&#039;&#039;&#039; &#039;&#039;&#039;&#039;&#039;Der Wert &amp;quot;0&amp;quot; bedeutet, dass die Fuse programmiert ist, es entspicht dem Häkchen im AVR Studio!&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Der &amp;quot;Hallo Welt&amp;quot; - Bootloader =&lt;br /&gt;
&lt;br /&gt;
Wie oben erwähnt, wird für die Erstellung des Codes die kostenlose IDE von Atmel - das AVRStudio - benutzt. Ergänzt wird es durch C-Compiler und Tools des WinAVR Projektes. Des weiteren wird zur seriellen Kommunikation das Terminalprogramm benötigt. Im Tutorial wird PuTTY verwendet und sollte installiert sein. Die Hardware ist aufgebaut und via AVRISPmkII-Programmer an den PC angeschlossen - nun kann es losgehen!&lt;br /&gt;
&lt;br /&gt;
Zu Beginn wird ein neues AVRStudio-Projekt erstellt. Danach werden folgende Schritte abgearbeitet:&lt;br /&gt;
&lt;br /&gt;
== Schritt 1 - Konfiguration der Projekteinstellungen ==&lt;br /&gt;
[[Bild:Bootloader-Projekt.png|200px|thumb|Erstellen des Projekts]]&lt;br /&gt;
[[Bild:Bootloader-Config-General.PNG|200px|thumb|Generelle Optionen - setzten der Taktfrequenz]]&lt;br /&gt;
[[Bild:Bootloader-Config-Linker.png|200px|thumb|Linker Option eingeben]]&lt;br /&gt;
&lt;br /&gt;
Als erstes öffnen wir die Projekteinstellungen (Menü &#039;&#039;Project/Configuration Options&#039;&#039;) und tragen die richtige Taktfrequenz ein (Im Beispiel nutzen wir den internen Oszillator mit 8 Mhz). Danach gehen wir zum Reiter &#039;&#039;&#039;Custom Options&#039;&#039;&#039;. Dort klicken wir auf &#039;&#039;&#039;Linker Options&#039;&#039;&#039; und geben dann im Textfeld daneben &#039;&#039;&#039;-Ttext=0x1800&#039;&#039;&#039; ein. Danach drücken wir auf &#039;&#039;&#039;Add&#039;&#039;&#039;. &lt;br /&gt;
&lt;br /&gt;
Was bewirkt dieser Linker-Parameter? Dafür muß wieder etwas weiter ausgeholt werden. Nach dem Kompilieren der Programmquellen &#039;&#039;linkt&#039;&#039; der Linker den Programmcode an bestimmte Stellen in den drei verschiedenen Speichern Flash, EEPROM und SRAM des AVR. In der vom Compiler verwendeten [http://www.nongnu.org/avr-libc/user-manual/mem__sections.html AVR Libc] ist der Speicher in verschiedene Sektionen aufgeteilt. Dem Linker muss mitgeteilt werden, in welche Speicher er den Programmcode linken soll. Die Lokalisierung des Speichers sind die Sektionen. Die Sektion &#039;&#039;.text&#039;&#039; ist dem ausführbaren Programmcode - also den Befehlen - vorbehalten und liegt im Flash des AVR, des weiteren gibt es auch noch die Sektionen &#039;&#039;.data&#039;&#039; und &#039;&#039;.bss&#039;&#039; für die statischen und dynamischen Variablen im SRAM und eine Sektion &#039;&#039;.eeprom&#039;&#039; für den EEPROM und noch ein paar spezielle (Flash-)Sektionen.&lt;br /&gt;
&lt;br /&gt;
Nun gibt es verschiedene Methoden, dem Linker mitzuteilen, dass man den Programmcode an die Stelle des Bootloaderbereichs haben möchte. Eine sehr einfache Methode ist &#039;&#039;&#039;die Verschiebung der Sektion &#039;&#039;&#039; &#039;&#039;&#039;&#039;&#039;.text&#039;&#039;&#039;&#039;&#039;, welche normalerweise ab Adresse 0x0000 beginnt. Eben dies geschieht mit dem Linker Parameter &#039;&#039;&#039;-Ttext=0x1800&#039;&#039;&#039;. Die Adresse des Beginns der &#039;&#039;.text&#039;&#039; Sektion wird auf die (Byte-)Adresse 0x1800 gesetzt.&lt;br /&gt;
&lt;br /&gt;
== Schritt 2 - Einbinden der UART Library von Peter Fleury ==&lt;br /&gt;
&lt;br /&gt;
Wie bereits erwähnt, wird für die serielle Kommunikation auf der AVR-Seite die UART-Library von [http://www.jump.to/fleury Peter Fleury] verwendet. Nach dem Download werden die uart.c und uart.h in das Projekt eingebunden (für die uart.c im AVR Studio rechte Maustaste auf &#039;&#039;Source Files&#039;&#039; und dann &#039;&#039;Add Existing Source File(s)...&#039;&#039; und für die uart.h die rechte Maustaste auf &#039;&#039;Header Files&#039;&#039; und dann &#039;&#039;Add Existing Header File(s)...&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
== Schritt 3 - Programmieren des Bootloaders ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Bootloader-Config-Linker-ok.PNG|200px|thumb|Linker Option nach Add]]&lt;br /&gt;
[[Bild:Bootloader-AVRStudio.PNG|200px|thumb|Kompilieren des Bootloaders]]&lt;br /&gt;
&lt;br /&gt;
Nun soll eine kleine Applikation geschrieben werden. Keine Angst, unser erstes Ziel ist es, eine kleine Anwendung in dem Bootloaderbereich zu positionieren, welche serielle Ein-und Ausgaben behandelt. Die eigentliche Bootloaderfunktionalität kommt später dazu. Also schreiben wir die Datei &#039;&#039;main.c&#039;&#039; wie folgt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/boot.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
#define BOOT_UART_BAUD_RATE     9600     /* Baudrate */&lt;br /&gt;
#define XON                     17       /* XON Zeichen */&lt;br /&gt;
#define XOFF                    19       /* XOFF Zeichen */&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
    unsigned int 	c=0;               /* Empfangenes Zeichen + Statuscode */&lt;br /&gt;
    unsigned char	temp,              /* Variable */&lt;br /&gt;
                        flag=1,            /* Flag zum steuern der Endlosschleife */&lt;br /&gt;
			p_mode=0;	   /* Flag zum steuern des Programmiermodus */&lt;br /&gt;
    void (*start)( void ) = 0x0000;        /* Funktionspointer auf 0x0000 */&lt;br /&gt;
 &lt;br /&gt;
    /* Interrupt Vektoren verbiegen */&lt;br /&gt;
&lt;br /&gt;
    char sregtemp = SREG;&lt;br /&gt;
    cli();&lt;br /&gt;
    temp = MCUCR;&lt;br /&gt;
    MCUCR = temp | (1&amp;lt;&amp;lt;IVCE);&lt;br /&gt;
    MCUCR = temp | (1&amp;lt;&amp;lt;IVSEL);&lt;br /&gt;
    SREG = sregtemp;&lt;br /&gt;
 &lt;br /&gt;
    /* Einstellen der Baudrate und aktivieren der Interrupts */&lt;br /&gt;
    uart_init( UART_BAUD_SELECT(BOOT_UART_BAUD_RATE,F_CPU) ); &lt;br /&gt;
    sei();&lt;br /&gt;
 &lt;br /&gt;
    uart_puts(&amp;quot;Hallo hier ist der Bootloader\n\r&amp;quot;);&lt;br /&gt;
    _delay_ms(1000);&lt;br /&gt;
 &lt;br /&gt;
    do&lt;br /&gt;
    {&lt;br /&gt;
        c = uart_getc();&lt;br /&gt;
        if( !(c &amp;amp; UART_NO_DATA) )&lt;br /&gt;
        {&lt;br /&gt;
            switch((unsigned char)c)&lt;br /&gt;
            {&lt;br /&gt;
                 case &#039;q&#039;: &lt;br /&gt;
		     flag=0;&lt;br /&gt;
                     uart_puts(&amp;quot;Verlasse den Bootloader!\n\r&amp;quot;);&lt;br /&gt;
                     break;&lt;br /&gt;
                  default:&lt;br /&gt;
                     uart_puts(&amp;quot;Du hast folgendes Zeichen gesendet: &amp;quot;);&lt;br /&gt;
                     uart_putc((unsigned char)c);&lt;br /&gt;
                     uart_puts(&amp;quot;\n\r&amp;quot;);&lt;br /&gt;
                     break;&lt;br /&gt;
            }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    while(flag);&lt;br /&gt;
 &lt;br /&gt;
    uart_puts(&amp;quot;Springe zur Adresse 0x0000!\n\r&amp;quot;);&lt;br /&gt;
    _delay_ms(1000);&lt;br /&gt;
&lt;br /&gt;
    /* vor Rücksprung eventuell benutzte Hardware deaktivieren&lt;br /&gt;
       und Interrupts global deaktivieren, da kein &amp;quot;echter&amp;quot; Reset erfolgt */&lt;br /&gt;
&lt;br /&gt;
    /* Interrupt Vektoren wieder gerade biegen */&lt;br /&gt;
    cli();&lt;br /&gt;
    temp = MCUCR;&lt;br /&gt;
    MCUCR = temp | (1&amp;lt;&amp;lt;IVCE);&lt;br /&gt;
    MCUCR = temp &amp;amp; ~(1&amp;lt;&amp;lt;IVSEL);&lt;br /&gt;
&lt;br /&gt;
    /* Rücksprung zur Adresse 0x0000 */&lt;br /&gt;
    start(); &lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Erklärung des Codes&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Beginnen wir mit den Defines: Die Baudrate erklärt sich von selbst. Die Defines XON und XOFF werden später, wenn die Bootloader-Funktionalität dazukommt, zur Flusssteuerung gebraucht. Wir werden also die XON/XOFF-Flussteuerung nutzen (merken für die Einstellung von PuTTY). &lt;br /&gt;
&lt;br /&gt;
Bei den Variablen ist nur eine interessant: Der Funktionspointer &amp;lt;pre&amp;gt;void (*start)( void ) = 0x0000;&amp;lt;/pre&amp;gt; ist ein einfacher Trick, um mit dem Programmcounter (PC) zur Adresse 0x0000 zu springen. Wir definieren einfach eine (fiktive) Funktion an der Stelle 0x0000. Beim Aufruf der Funktion mit &amp;lt;pre&amp;gt;start();&amp;lt;/pre&amp;gt; springt der Programmcounter und damit das Programm an Adresse 0x0000 und das Anwendungsprogramm - wenn es eins gibt - kann starten. &lt;br /&gt;
&lt;br /&gt;
Nun folgt ein sehr wichtiger Teil, auf den ich noch eingehen muss - die Interrupt-Vektoren. Interrupt-Vektoren sind Einsprungpunkte der Interrupts, welche normalerweise fest ab Adresse 0x0001 im Flash liegen. Wird ein Interrupt ausgelöst, springt der AVR automatisch zu der festen Flash-Adresse. Von dort aus - wenn eine ISR programmiert ist - springt der Controller zur ISR (&#039;&#039;&#039;I&#039;&#039;&#039;nterrupt &#039;&#039;&#039;S&#039;&#039;&#039;ervice &#039;&#039;&#039;R&#039;&#039;&#039;outine). Nun haben wir folgendes Problem: Wenn wir den Bootloadercode ab der Adresse 0x1800 ausführen, nützt es uns gar nichts, wenn der AVR nach Auslösen eines Interrupts an die Stelle 0x0001 + X springt, da dieser Speicherbereich ja im Zweifelsfalle sogar von uns überschrieben wird. Unser Code soll nur ab Adresse 0x1800 stehen! Wir müssen also die Sprungtabelle &amp;quot;verbiegen&amp;quot;, d.h. den AVR veranlassen, bei Auslösung eines Interrupts an Adresse 0x1801 + X zu springen und dann zur ISR. Das Verbiegen der Sprungtabelle passiert mit dem Setzen des &#039;&#039;&#039;IVSEL&#039;&#039;&#039;-Bits im &#039;&#039;&#039;MCUCR&#039;&#039;&#039; (ACHTUNG: beim Atmega8 &#039;&#039;&#039;GICR&#039;&#039;&#039;), also&lt;br /&gt;
&lt;br /&gt;
beim Atmega88:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
temp = MCUCR;&lt;br /&gt;
MCUCR = temp | (1&amp;lt;&amp;lt;IVCE);&lt;br /&gt;
MCUCR = temp | (1&amp;lt;&amp;lt;IVSEL);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
bzw. beim Atmega8:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
temp = GICR;&lt;br /&gt;
GICR = temp | (1&amp;lt;&amp;lt;IVCE);&lt;br /&gt;
GICR = temp | (1&amp;lt;&amp;lt;IVSEL);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Das &#039;&#039;&#039;IVCE&#039;&#039;&#039;-Bit wird nur benötigt, um dem Mikrocontroller zu sagen, dass wir als nächstes den Parameter &#039;&#039;&#039;IVSEL&#039;&#039;&#039; setzen wollen, das Bit wird nachher vom Controller wieder gelöscht. Um versehentliches verstellen der Interrupttabelle zu vermeiden muss das setzen von &#039;&#039;&#039;IVCE&#039;&#039;&#039; und &#039;&#039;&#039;IVSEL&#039;&#039;&#039; innerhalb von 4 Taktzyklen erfolgen. Um dies zu gewährleisten müssen alle interrupts während des Setzens deaktiviert sein. ACHTUNG Stolperfalle: Die Variable temp wird benötigt, da beim Setzen von &#039;&#039;&#039;IVSEL&#039;&#039;&#039; gleichzeitig &#039;&#039;&#039;IVCE&#039;&#039;&#039; gelöscht werden muss:&lt;br /&gt;
&lt;br /&gt;
bei Atmega8/16:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
GICR |= (1&amp;lt;&amp;lt;IVCE);   // noch richtig. IVCE wird gesetzt&lt;br /&gt;
GICR |= (1&amp;lt;&amp;lt;IVSEL);  // falsch! IVSEL wird zwar gesetzt, &lt;br /&gt;
                        IVCE bleibt jedoch in diesem Prozessortakt gesetzt.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In der Hauptschleife wird lediglich gepollt, ob ein neues Zeichen von der Konsole kommt. Nach dem Empfang eines Zeichens wird es ausgewertet (switch). Nach dem Drücken von &#039;&#039;&amp;quot;q&amp;quot;&#039;&#039; verlässt der Bootloader die Hauptschleife, setzt die Interrupt-Vektoren wieder zurück und startet die Hauptanwendung - wenn eine da ist.&lt;br /&gt;
&lt;br /&gt;
Nach dem Kompilieren sagt uns der Linker, dass 754 Byte Programmspeicher und 265 Byte Datenspeicher verbraucht wurde. 754 Byte ist weit unter den 2048 Byte, welche uns ab der Adresse 0x1800 zur Verfügung stehen, wir haben also alles richtig gemacht.&lt;br /&gt;
&lt;br /&gt;
Nun kontrollieren wir noch schnell, ob das Programm an der richtigen Stelle im Flash steht. Mit dem Hex-File (Bootloader.hex) wird auch ein List-File (Bootloader.lss) erzeugt. Im List-File findet sich das disassemblierte Programm und die Speicherzuordnungen. Hier ein Auszug der Datei:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Bootloader.elf:     file format elf32-avr&lt;br /&gt;
&lt;br /&gt;
Sections:&lt;br /&gt;
Idx Name          Size      VMA       LMA       File off  Algn&lt;br /&gt;
  0 .data         00000080  00800100  00001a68  000002fc  2**0&lt;br /&gt;
                  CONTENTS, ALLOC, LOAD, DATA&lt;br /&gt;
  1 .text         00000268  00001800  00001800  00000094  2**1&lt;br /&gt;
                  CONTENTS, ALLOC, LOAD, READONLY, CODE&lt;br /&gt;
  2 .bss          00000085  00800180  00800180  0000037c  2**0&lt;br /&gt;
                  ALLOC&lt;br /&gt;
  3 .debug_aranges 00000040  00000000  00000000  0000037c  2**0&lt;br /&gt;
                  CONTENTS, READONLY, DEBUGGING&lt;br /&gt;
  4 .debug_pubnames 00000095  00000000  00000000  000003bc  2**0&lt;br /&gt;
                  CONTENTS, READONLY, DEBUGGING&lt;br /&gt;
  5 .debug_info   00000459  00000000  00000000  00000451  2**0&lt;br /&gt;
                  CONTENTS, READONLY, DEBUGGING&lt;br /&gt;
  6 .debug_abbrev 00000238  00000000  00000000  000008aa  2**0&lt;br /&gt;
                  CONTENTS, READONLY, DEBUGGING&lt;br /&gt;
  7 .debug_line   000003eb  00000000  00000000  00000ae2  2**0&lt;br /&gt;
                  CONTENTS, READONLY, DEBUGGING&lt;br /&gt;
  8 .debug_frame  000000a0  00000000  00000000  00000ed0  2**2&lt;br /&gt;
                  CONTENTS, READONLY, DEBUGGING&lt;br /&gt;
  9 .debug_str    000001cf  00000000  00000000  00000f70  2**0&lt;br /&gt;
                  CONTENTS, READONLY, DEBUGGING&lt;br /&gt;
 10 .debug_loc    0000024a  00000000  00000000  0000113f  2**0&lt;br /&gt;
                  CONTENTS, READONLY, DEBUGGING&lt;br /&gt;
 11 .debug_ranges 00000048  00000000  00000000  00001389  2**0&lt;br /&gt;
                  CONTENTS, READONLY, DEBUGGING&lt;br /&gt;
&lt;br /&gt;
Disassembly of section .text:&lt;br /&gt;
&lt;br /&gt;
00001800 &amp;lt;__vectors&amp;gt;:&lt;br /&gt;
    1800:	19 c0       	rjmp	.+50     	; 0x1834 &amp;lt;__ctors_end&amp;gt;&lt;br /&gt;
    1802:	33 c0       	rjmp	.+102    	; 0x186a &amp;lt;__bad_interrupt&amp;gt;&lt;br /&gt;
    1804:	32 c0       	rjmp	.+100    	; 0x186a &amp;lt;__bad_interrupt&amp;gt;&lt;br /&gt;
    1806:	31 c0       	rjmp	.+98     	; 0x186a &amp;lt;__bad_interrupt&amp;gt;&lt;br /&gt;
    1808:	30 c0       	rjmp	.+96     	; 0x186a &amp;lt;__bad_interrupt&amp;gt;&lt;br /&gt;
    180a:	2f c0       	rjmp	.+94     	; 0x186a &amp;lt;__bad_interrupt&amp;gt;&lt;br /&gt;
    180c:	2e c0       	rjmp	.+92     	; 0x186a &lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
(viele Zeilen)&lt;br /&gt;
...&lt;br /&gt;
&lt;br /&gt;
0000186c &amp;lt;main&amp;gt;:&lt;br /&gt;
#define BOOT_UART_BAUD_RATE     9600     /* Baudrate */&lt;br /&gt;
#define XON                     17       /* XON Zeichen */&lt;br /&gt;
#define XOFF                    19       /* XOFF Zeichen */&lt;br /&gt;
 &lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
    186c:	cf 93       	push	r28&lt;br /&gt;
    186e:	df 93       	push	r29&lt;br /&gt;
    unsigned char	temp,            /* Variable */&lt;br /&gt;
                        flag=1;          /* Flag zum steuern der Endlosschleife */&lt;br /&gt;
    void (*start)( void ) = 0x0000;    /* Funktionspointer auf 0x0000 */&lt;br /&gt;
 &lt;br /&gt;
    /* Interrupt Vektoren verbiegen */&lt;br /&gt;
    temp = MCUCR;&lt;br /&gt;
    1870:	85 b7       	in	r24, 0x35	; 53&lt;br /&gt;
    MCUCR = temp | (1&amp;lt;&amp;lt;IVCE);&lt;br /&gt;
    1872:	98 2f       	mov	r25, r24&lt;br /&gt;
    1874:	91 60       	ori	r25, 0x01	; 1&lt;br /&gt;
    1876:	95 bf       	out	0x35, r25	; 53&lt;br /&gt;
    MCUCR = temp | (1&amp;lt;&amp;lt;IVSEL);&lt;br /&gt;
    1878:	82 60       	ori	r24, 0x02	; 2&lt;br /&gt;
    187a:	85 bf       	out	0x35, r24	; 53&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
(noch mehr Zeilen)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wir erkennen, dass die Sektion &#039;&#039;.text&#039;&#039; ab der Adresse (VMA) 0x1800 beginnt. Weiter sehen wir im Disassembly der Sektion &#039;&#039;.text&#039;&#039;, dass unser Programm mit der Interrupt-Einsprungstabelle ab Adresse 0x1800 beginnt. Unsere &#039;&#039;main()&#039;&#039; beginnt ab Adresse 0x186C. Super. Das hat geklappt. Aber nun schnell zu Schritt 4 - dem Flashen und Ausprobieren des Programms...&lt;br /&gt;
&lt;br /&gt;
== Schritt 4 - Flashen und Ausprobieren des Bootloaders ==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Bootloader-AVRStudio-Fuses.png|200px|thumb|Setzen der Fuses]]&lt;br /&gt;
[[Bild:PuTTY-Serconfig.png|200px|thumb|Serielle Konfiguration von PuTTY]]&lt;br /&gt;
[[Bild:PuTTY-Serconfig-xon.png|200px|thumb|Serielle Konfiguration von PuTTY]]&lt;br /&gt;
&lt;br /&gt;
Nach dem Start des AVRISPmkII-In-System-Programmers aus dem AVRStudio werden zunächst die Einstellungen geprüft. Die Signatur des AVRs muss stimmen und die ISP-Frequenz. Im Reiter Program muss unter &#039;&#039;Flash&#039;&#039; die richtige Datei angegeben sein (&#039;&#039;Bootloader.hex&#039;&#039;). Danach können wir uns an das setzen der Fuses machen. &#039;&#039;&#039;CKDIV8&#039;&#039;&#039; sollte ausgeschalten werden, der interne Takt von 8 Mhz sollte genutzt werden (&#039;&#039;&#039;SUT_CKSEL&#039;&#039;&#039;) und &#039;&#039;BOOTSZ&#039;&#039; auf 1024 words gestellt werden. Zusätzlich muß die &#039;&#039;&#039;BOOTRST&#039;&#039;&#039;-Fuse gesetzt werden, damit der Bootloader an der richtigen Adresse anfängt. Für alle, die einen anderen Programmer benutzen (z.B. avrdude), hier die exakten Werte der Fuses:&lt;br /&gt;
* Low Fuse: &#039;&#039;&#039;0xE2&#039;&#039;&#039;&lt;br /&gt;
* High Fuse: &#039;&#039;&#039;0xD2&#039;&#039;&#039;&lt;br /&gt;
* Extended Fuse: &#039;&#039;&#039;0xF8&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Jetzt kann PuTTY gestartet und konfiguriert werden. Der &#039;&#039;Connection type&#039;&#039; muss auf &#039;&#039;&#039;Serial&#039;&#039;&#039; gestellt werden. Die Baudrate beträgt 9600 Baud. Unter &#039;&#039;Connection/Serial&#039;&#039; muss der &#039;&#039;Flow control&#039;&#039; auf &#039;&#039;&#039;XON/XOFF&#039;&#039;&#039; gestellt werden. Nach dem Konfigurieren kann die Konsole mit &#039;&#039;Open&#039;&#039; geöffnet werden.&lt;br /&gt;
&lt;br /&gt;
Jetzt kann wieder in das AVR Studio gewechselt werden. Mit einem beherztem Druck auf &#039;&#039;Program&#039;&#039; wird das Flash im ATmega88 programmiert. Nach dem Wechsel auf die Konsole erscheint folgendes Bild:&lt;br /&gt;
&lt;br /&gt;
[[Bild:PuTTY-Bootloader-start.png|600px|Bootloader in PuTTY]]&lt;br /&gt;
&lt;br /&gt;
Nach dem Drücken von ein paar Tasten erscheint folgendes:&lt;br /&gt;
&lt;br /&gt;
[[Bild:PuTTY-Bootloader-taste.png|600px|Bootloader nach Tastendruck in PuTTY]]&lt;br /&gt;
&lt;br /&gt;
Nach dem Drücken von &#039;&#039;&#039;q&#039;&#039;&#039; erscheint folgendes Bild:&lt;br /&gt;
&lt;br /&gt;
[[Bild:PuTTY-Bootloader-restart.png|600px|Bootloader nach Tastendruck in PuTTY]]&lt;br /&gt;
&lt;br /&gt;
Der Bootloader versucht, zur Adresse 0x0000 zu springen, wo er allerdings keinen Programmcode findet. Wie auch? Wir haben ja den ganzen Flash des AVR gerade gelöscht und mit dem Bootloader gefüllt. Nun muss man wissen, dass in einem gelöschten Flash &#039;&#039;0xFF&#039;&#039; in jeder Speicherzelle steht. &#039;&#039;0xFF&#039;&#039; ist für den AVR kein gültiger Opcode. Der Programmzähler zählt nur um eins nach oben. Damit hopst er sozusagen durch den gesamten Flash bis er wieder beim Bootloader landet.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;[http://de.wikipedia.org/wiki/Heureka Heureka]&#039;&#039;&#039;&#039;&#039; wir haben es geschafft! Ein Programm wird im Bootloaderbereich des Flashs ausgeführt! Es &#039;&#039;bootet&#039;&#039; zwar schon schön, aber es &#039;&#039;loadet&#039;&#039; noch nichts in den Flash. Aber die halbe Miete haben wir damit schon. Nun schreiben wir erst einmal eine kleine Anwendung, welche wir nach der Erweiterung unseres Bootloaders in den Flash-Speicher laden.&lt;br /&gt;
&lt;br /&gt;
= Die Test-Anwendung =&lt;br /&gt;
&lt;br /&gt;
[[Bild:Anwendung-AVRStudio.png|200px|thumb|Erstellen des Projektes]]&lt;br /&gt;
[[Bild:Anwendung-AVRStudio-Code.png|200px|thumb|Sourcecode im AVRStudio]]&lt;br /&gt;
&lt;br /&gt;
Die Kategorie Anwendung möchte ich möglichst kurz halten. Ziel ist es, eine kleine Anwendung zu schreiben, welche dann mit dem (echten) Bootloader ins Flash gespeichert wird. &lt;br /&gt;
&lt;br /&gt;
== Schritt 1 - Erstellen des Projektes ==&lt;br /&gt;
&lt;br /&gt;
Nach dem Erstellen eines neuen Projektes muss in den Projekt-Einstellungen des AVR Studios nur die Taktfrequenz eingetragen werden. Die Linker-Optionen werden nicht verändert, also bleibt wie es ist.&lt;br /&gt;
&lt;br /&gt;
== Schritt 2 - Einbinden der UART Library ==&lt;br /&gt;
&lt;br /&gt;
Dieser Schritt kann vom Bootloader übernommen werden. Es wird wieder die UART-Bibliothek von Peter Fleury verwendet.&lt;br /&gt;
&lt;br /&gt;
== Schritt 3 - Programmieren der Anwendung ==&lt;br /&gt;
&lt;br /&gt;
Wir starten also ein neues AVR Studio und legen ein neues Projekt an, konfigurieren die Taktfrequenz (8 MHz) und laden die &#039;&#039;uart.c&#039;&#039; und &#039;&#039;uart.h&#039;&#039; dazu. Nun schreiben wir in die &#039;&#039;main.c&#039;&#039; folgende Zeilen:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/pgmspace.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#define UART_BAUD_RATE	9600&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
   unsigned int 	c;&lt;br /&gt;
   void (*bootloader)( void ) = 0x1800;&lt;br /&gt;
&lt;br /&gt;
   uart_init( UART_BAUD_SELECT(UART_BAUD_RATE,F_CPU) ); &lt;br /&gt;
   sei();&lt;br /&gt;
    &lt;br /&gt;
   uart_puts_P(&amp;quot;\n\rHier ist das Anwendungsprogramm...&amp;quot;);&lt;br /&gt;
 &lt;br /&gt;
   for(;;)&lt;br /&gt;
   {&lt;br /&gt;
       c = uart_getc();&lt;br /&gt;
       if(!(c &amp;amp; UART_NO_DATA))&lt;br /&gt;
       {&lt;br /&gt;
	   switch( (unsigned char)c)&lt;br /&gt;
	   {&lt;br /&gt;
	       case &#039;b&#039;:&lt;br /&gt;
		   uart_puts(&amp;quot;\n\rSpringe zum Bootloader...&amp;quot;);&lt;br /&gt;
		   _delay_ms(1000);&lt;br /&gt;
		    bootloader();&lt;br /&gt;
		    break;&lt;br /&gt;
		default:&lt;br /&gt;
                    uart_puts(&amp;quot;\n\rDu hast folgendes Zeichen gesendet: &amp;quot;);&lt;br /&gt;
		    uart_putc((unsigned char)c);&lt;br /&gt;
		    break;&lt;br /&gt;
	    }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Erklärung des Codes&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Viel interessantes ist nicht an diesem Code. Es gibt wie immer die berühmte Endlosschleife. Wir definieren wieder einen fiktiven Funktionspointer&amp;lt;pre&amp;gt;void (*bootloader)( void ) = 0x1800;&amp;lt;/pre&amp;gt; Nach drücken der Taste &#039;&#039;&#039;b&#039;&#039;&#039; soll das Programm wieder zum Bootloader springen.&lt;br /&gt;
&lt;br /&gt;
Nach dem Kompilieren des Programms sehen wir, dass der Programmspeicher mit 686 Byte belegt ist, der Datenspeicher mit 201 Bytes.&lt;br /&gt;
&lt;br /&gt;
== Schritt 4 - Ausprobieren der Anwendung ==&lt;br /&gt;
&lt;br /&gt;
Wer möchte kann die Anwendung auf den AVR flashen und ausprobieren. Die Funktion sollte sich von selbst erschließen. Nun wollen wir uns der &lt;br /&gt;
Erweiterung des Bootloaders widmen.&lt;br /&gt;
&lt;br /&gt;
= Der &amp;quot;echte&amp;quot; Bootloader =&lt;br /&gt;
[[Bild:Real-Bootloader-AVRStudio.png|200px|thumb|Programmieren des Bootloaders]]&lt;br /&gt;
&lt;br /&gt;
Zum Erstellen des Bootloaders wird wieder Schrittweise vorgegangen. Folgende Schritte sind zu befolgen:&lt;br /&gt;
&lt;br /&gt;
== Schritt 1 und 2 - siehe &amp;quot;Hallo Welt&amp;quot; Bootloader ==&lt;br /&gt;
Schritt 1 und 2 können vom &amp;quot;Hallo Welt&amp;quot; Bootloader übernommen werden. Es sind wieder die korrekte Taktfrequenz und die Verschiebung der Sektion &#039;&#039;&#039;.text&#039;&#039;&#039; auf die Bootresetadresse einzustellen.&lt;br /&gt;
&lt;br /&gt;
== Schritt 3 - Programmieren des Bootloaders ==&lt;br /&gt;
&lt;br /&gt;
Nun soll der Bootloader erweitert werden. Nach dem Kompilieren des Anwendungsprogramms erhalten wir eine Datei &#039;&#039;Anwendung.hex&#039;&#039; im [http://de.wikipedia.org/wiki/Intel_HEX Intel-HEX-Format]. Da wir im Bootloader diese Daten auswerten müssen, wollen wir uns kurz mit dem Format beschäftigen. Das Intel-HEX-Format ist geschaffen worden, um Binärdaten als ASCII-Daten zu übertragen. Jedes Byte ist in Form von zwei ASCII-Zeichen gespeichert, d.h. aus der Zahl &#039;&#039;0x4A&#039;&#039; wird die ASCII-Zeichenfolge &#039;&#039;&amp;quot;4A&amp;quot;&#039;&#039;. Das bedeutet aber auch, dass aus den Binärdaten die doppelte Anzahl von Zeichen wird, welche übertragen werden müssen, hinzu kommen noch Steuerzeichen und Zusatzinformationen. Jede Zeile in der Intel-HEX-Datei folgt einem bestimmten Schema, in dem u.a. die Anzahl der Bytes, die Zieladresse und Checksumme stehen.&lt;br /&gt;
&lt;br /&gt;
Für weiterführende Erklärungen zum Thema HEX-Datei-Format empfehle ich folgende Lektüre:&lt;br /&gt;
* [http://en.wikipedia.org/wiki/Intel_HEX Wikipedia Artikel über HEX-Files]&lt;br /&gt;
* [http://www.rn-wissen.de/index.php/HEX-Datei RN-Wissen-Artikel über HEX-Files]&lt;br /&gt;
* [http://www.schulz-koengen.de/biblio/intelhex.htm Artikel von Wolfgang R.Schulz]&lt;br /&gt;
&lt;br /&gt;
Unser Bootloader muss in der Lage sein, dieses Format zu interpretieren. Wir müssen also einen Parser schreiben. &#039;&#039;Oje&#039;&#039; werden manche denken, das ist ja wieder ein Thema für sich. Das stimmt prinzipiell auch. Allerdings kommt uns hier das einfache Format der Intel-Hex-Datei zugute, welches den Aufwand in Grenzen hält.&lt;br /&gt;
&lt;br /&gt;
Also erstes brauchen wir also Funktionen, um die ASCII-Zeichenfolgen wieder in Binärdaten umzuwandeln. Normalerweise könnte man dafür die C-Funktion [http://www.nongnu.org/avr-libc/user-manual/group__avr__stdlib.html#gaf8ce3b8dae3d45c34c3b172de503f7b3 strtol] aus der stdlib.h nehmen. Allerdings würde das Benutzen dieses Befehls das Linken der Standardbibliothek nach sich ziehen und damit den Code unnötig aufblähen. Daher werden wir uns eine einfache eigene Funktion schreiben, um die Zeichenfolgen umzuwandeln. In der HEX-Datei kommen 2 Byte und 4 Byte Hex-Zahlen im ASCII-Format vor. Wir brauchen also eine Funktion, welche die ASCII-Zeichenfolgen in Zahlen umwandelt, hier ist sie:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
static uint16_t hex2num(const uint8_t * ascii, uint8_t num)&lt;br /&gt;
{&lt;br /&gt;
    uint8_t  i;&lt;br /&gt;
    uint16_t val = 0;&lt;br /&gt;
 &lt;br /&gt;
    for (i=0; i&amp;lt;num; i++)&lt;br /&gt;
    {&lt;br /&gt;
        uint8_t c = ascii[i];&lt;br /&gt;
        &lt;br /&gt;
        /* Hex-Ziffer auf ihren Wert abbilden */&lt;br /&gt;
        if (c &amp;gt;= &#039;0&#039; &amp;amp;&amp;amp; c &amp;lt;= &#039;9&#039;)            c -= &#039;0&#039;;  &lt;br /&gt;
        else if (c &amp;gt;= &#039;A&#039; &amp;amp;&amp;amp; c &amp;lt;= &#039;F&#039;)       c -= &#039;A&#039; - 10;&lt;br /&gt;
        else if (c &amp;gt;= &#039;a&#039; &amp;amp;&amp;amp; c &amp;lt;= &#039;f&#039;)       c -= &#039;a&#039; - 10;&lt;br /&gt;
            &lt;br /&gt;
        val = 16 * val + c;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    return val;  &lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Wir benutzen hier einen sehr einfachen Ansatz, um die Zahlen zu generieren. Die Funktionen wandeln die ASCII-Zeichen entsprechend ihrer Wertigkeit in Zahlen um. Soll z.B. das ASCII-Zeichen &#039;1&#039; umgewandelt werden, wird vom ASCII-Code &#039;1&#039;, also dezimal 49, 48=&#039;0&#039; abgezogen: 49 - 48 = 1, somit haben wir ein ASCII-Zeichen in eine Zahl umgewandelt. Wen das ASCII-Zeichen &#039;C&#039; ist (Dezimal: 67), werden &#039;A&#039; - 10 = 65 -10 = 55 abgezogen, um 12 zu erhalten, den Wert der hex-Ziffer C. Näher möchte an dieser Stelle nicht darauf eingehen, wir wollen schnell weiter zum Beschreiben des Flashs kommen.&lt;br /&gt;
&lt;br /&gt;
Um in den Flash zu schreiben, werden wir Makros aus der &#039;&#039;[http://www.nongnu.org/avr-libc/user-manual/group__avr__boot.html boot.h]&#039;&#039; der avr-libc verwenden. Hier findet man alle Werkzeuge, die wir brauchen. Dabei sollte vor allen das &#039;&#039;API Usage Example&#039;&#039; in der [http://www.nongnu.org/avr-libc/user-manual/group__avr__boot.html Online Doku] näher betrachtet werden. Dieses Beispiel soll weitestgehend übernommen werden, da es die nötige Funktionalität beinhaltet. Hier ist die Funktion:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
void boot_program_page (uint32_t page, uint8_t *buf)&lt;br /&gt;
{&lt;br /&gt;
    uint16_t i;&lt;br /&gt;
    uint8_t sreg;&lt;br /&gt;
&lt;br /&gt;
    /* Disable interrupts.*/&lt;br /&gt;
    sreg = SREG;&lt;br /&gt;
    cli();&lt;br /&gt;
&lt;br /&gt;
    eeprom_busy_wait ();&lt;br /&gt;
&lt;br /&gt;
    boot_page_erase (page);&lt;br /&gt;
    boot_spm_busy_wait ();      /* Wait until the memory is erased. */&lt;br /&gt;
&lt;br /&gt;
    for (i=0; i&amp;lt;SPM_PAGESIZE; i+=2)&lt;br /&gt;
    {&lt;br /&gt;
        /* Set up little-endian word. */&lt;br /&gt;
        uint16_t w = *buf++;&lt;br /&gt;
        w += (*buf++) &amp;lt;&amp;lt; 8;&lt;br /&gt;
    &lt;br /&gt;
        boot_page_fill (page + i, w);&lt;br /&gt;
    }&lt;br /&gt;
    boot_page_write (page);     /* Store buffer in flash page.		*/&lt;br /&gt;
    boot_spm_busy_wait();       /* Wait until the memory is written.*/&lt;br /&gt;
&lt;br /&gt;
    /* Reenable RWW-section again. We need this if we want to jump back */&lt;br /&gt;
    /* to the application after bootloading. */&lt;br /&gt;
    boot_rww_enable ();&lt;br /&gt;
&lt;br /&gt;
    /* Re-enable interrupts (if they were ever enabled). */&lt;br /&gt;
    SREG = sreg;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
Als erstes fällt auf, dass man der Funktion die &#039;&#039;Page&#039;&#039;-Adresse übergibt. Es wird also immer seitenweise geschrieben. Dies ist eine Spezialität des Flash-Speichers. Es &#039;&#039;&#039;muss&#039;&#039;&#039; immer die gesamte Seite geschrieben werden, dafür gibt es einen &#039;&#039;Page&#039;&#039;-Puffer, welcher die Daten enthält, welche mit der nächsten Schreiboperation in die entsprechende Page geschrieben werden. Dabei werden die Daten Wortweise in den &#039;&#039;Page&#039;&#039;-Puffer geschrieben. Die wesentlichen Funktionen der Routine sind &#039;&#039;boot_page_erase(page)&#039;&#039;, &#039;&#039;boot_page_fill(page + i, w)&#039;&#039; und &#039;&#039;boot_page_write(page)&#039;&#039;. Nicht zu vergessen auch &#039;&#039;boot_spm_busy_wait()&#039;&#039;. Die Bedeutung der Funktionen (naja es sind eher Makros) findet man in der Dokumentation der AVR Libc. Im wesentlichen läuft das Schreiben einer &#039;&#039;Page&#039;&#039; so ab:&lt;br /&gt;
* &#039;&#039;Page&#039;&#039; löschen&lt;br /&gt;
* &#039;&#039;Page&#039;&#039;-Puffer befüllen (aus der Variable &#039;&#039;buf&#039;&#039;)&lt;br /&gt;
* &#039;&#039;Page&#039;&#039; schreiben&lt;br /&gt;
So einfach, so gut. Für den Bootloader bedeutet das, dass er die Daten sammeln muß, bis er genügend Daten für eine &#039;&#039;Page&#039;&#039; hat. Dann wird eine &#039;&#039;Page&#039;&#039; geschrieben und der Spaß fängt von vorn an.&lt;br /&gt;
&lt;br /&gt;
Mit diesen beiden Funktionen sind wir nun in der Lage, den Parser zu schreiben. Die &#039;&#039;main.c&#039;&#039; sieht folgt aus:&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;string.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/boot.h&amp;gt;&lt;br /&gt;
#include &amp;lt;util/delay.h&amp;gt;&lt;br /&gt;
#include &amp;quot;uart.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
#define BOOT_UART_BAUD_RATE     9600     /* Baudrate */&lt;br /&gt;
#define XON                     17       /* XON Zeichen */&lt;br /&gt;
#define XOFF                    19       /* XOFF Zeichen */&lt;br /&gt;
#define START_SIGN              &#039;:&#039;      /* Hex-Datei Zeilenstartzeichen */&lt;br /&gt;
&lt;br /&gt;
/* Zustände des Bootloader-Programms */&lt;br /&gt;
#define BOOT_STATE_EXIT	        0        &lt;br /&gt;
#define BOOT_STATE_PARSER       1&lt;br /&gt;
&lt;br /&gt;
/* Zustände des Hex-File-Parsers */&lt;br /&gt;
#define PARSER_STATE_START      0&lt;br /&gt;
#define PARSER_STATE_SIZE       1&lt;br /&gt;
#define PARSER_STATE_ADDRESS    2&lt;br /&gt;
#define PARSER_STATE_TYPE       3&lt;br /&gt;
#define PARSER_STATE_DATA       4&lt;br /&gt;
#define PARSER_STATE_CHECKSUM   5&lt;br /&gt;
#define PARSER_STATE_ERROR      6&lt;br /&gt;
&lt;br /&gt;
void program_page (uint32_t page, uint8_t *buf)&lt;br /&gt;
{&lt;br /&gt;
    uint16_t i;&lt;br /&gt;
    uint8_t sreg;&lt;br /&gt;
&lt;br /&gt;
    /* Disable interrupts */&lt;br /&gt;
    sreg = SREG;&lt;br /&gt;
    cli();&lt;br /&gt;
&lt;br /&gt;
    eeprom_busy_wait ();&lt;br /&gt;
&lt;br /&gt;
    boot_page_erase (page);&lt;br /&gt;
    boot_spm_busy_wait ();      /* Wait until the memory is erased. */&lt;br /&gt;
&lt;br /&gt;
    for (i=0; i&amp;lt;SPM_PAGESIZE; i+=2)&lt;br /&gt;
    {&lt;br /&gt;
        /* Set up little-endian word. */&lt;br /&gt;
        uint16_t w = *buf++;&lt;br /&gt;
        w += (*buf++) &amp;lt;&amp;lt; 8;&lt;br /&gt;
    &lt;br /&gt;
        boot_page_fill (page + i, w);&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    boot_page_write (page);     /* Store buffer in flash page.		*/&lt;br /&gt;
    boot_spm_busy_wait();       /* Wait until the memory is written.*/&lt;br /&gt;
&lt;br /&gt;
    /* Reenable RWW-section again. We need this if we want to jump back */&lt;br /&gt;
    /* to the application after bootloading. */&lt;br /&gt;
    boot_rww_enable ();&lt;br /&gt;
&lt;br /&gt;
    /* Re-enable interrupts (if they were ever enabled). */&lt;br /&gt;
    SREG = sreg;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
static uint16_t hex2num (const uint8_t * ascii, uint8_t num)&lt;br /&gt;
{&lt;br /&gt;
    uint8_t  i;&lt;br /&gt;
    uint16_t val = 0;&lt;br /&gt;
&lt;br /&gt;
    for (i=0; i&amp;lt;num; i++)&lt;br /&gt;
    {&lt;br /&gt;
        uint8_t c = ascii[i];&lt;br /&gt;
        &lt;br /&gt;
        /* Hex-Ziffer auf ihren Wert abbilden */&lt;br /&gt;
        if (c &amp;gt;= &#039;0&#039; &amp;amp;&amp;amp; c &amp;lt;= &#039;9&#039;)            c -= &#039;0&#039;;  &lt;br /&gt;
        else if (c &amp;gt;= &#039;A&#039; &amp;amp;&amp;amp; c &amp;lt;= &#039;F&#039;)       c -= &#039;A&#039; - 10;&lt;br /&gt;
        else if (c &amp;gt;= &#039;a&#039; &amp;amp;&amp;amp; c &amp;lt;= &#039;f&#039;)       c -= &#039;a&#039; - 10;&lt;br /&gt;
            &lt;br /&gt;
        val = 16 * val + c;&lt;br /&gt;
    }&lt;br /&gt;
    &lt;br /&gt;
    return val;  &lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
                    /* Empfangenes Zeichen + Statuscode */&lt;br /&gt;
    uint16_t        c = 0, &lt;br /&gt;
                    /* Intel-HEX Zieladresse */&lt;br /&gt;
           	    hex_addr = 0,&lt;br /&gt;
                    /* Zu schreibende Flash-Page */&lt;br /&gt;
                    flash_page = 0,                    &lt;br /&gt;
                    /* Intel-HEX Checksumme zum Überprüfen des Daten */&lt;br /&gt;
                    hex_check = 0,&lt;br /&gt;
                    /* Positions zum Schreiben in der Datenpuffer */&lt;br /&gt;
                    flash_cnt = 0;&lt;br /&gt;
                    /* temporäre Variable */&lt;br /&gt;
    uint8_t         temp,&lt;br /&gt;
                    /* Flag zum steuern des Programmiermodus */&lt;br /&gt;
                    boot_state = BOOT_STATE_EXIT,&lt;br /&gt;
                    /* Empfangszustandssteuerung */&lt;br /&gt;
                    parser_state = PARSER_STATE_START,&lt;br /&gt;
                    /* Flag zum ermitteln einer neuen Flash-Page */&lt;br /&gt;
                    flash_page_flag = 1,&lt;br /&gt;
                    /* Datenpuffer für die Hexdaten*/&lt;br /&gt;
                    flash_data[SPM_PAGESIZE], &lt;br /&gt;
                    /* Position zum Schreiben in den HEX-Puffer */&lt;br /&gt;
                    hex_cnt = 0, &lt;br /&gt;
                    /* Puffer für die Umwandlung der ASCII in Binärdaten */&lt;br /&gt;
                    hex_buffer[5], &lt;br /&gt;
                    /* Intel-HEX Datenlänge */&lt;br /&gt;
                    hex_size = 0,&lt;br /&gt;
                    /* Zähler für die empfangenen HEX-Daten einer Zeile */&lt;br /&gt;
                    hex_data_cnt = 0, &lt;br /&gt;
                    /* Intel-HEX Recordtype */&lt;br /&gt;
                    hex_type = 0, &lt;br /&gt;
                    /* empfangene HEX-Checksumme */&lt;br /&gt;
                    hex_checksum=0;&lt;br /&gt;
                    /* Funktionspointer auf 0x0000 */&lt;br /&gt;
    void            (*start)( void ) = 0x0000; &lt;br /&gt;
 &lt;br /&gt;
    /* Füllen der Puffer mit definierten Werten */&lt;br /&gt;
    memset(hex_buffer, 0x00, sizeof(hex_buffer));&lt;br /&gt;
    memset(flash_data, 0xFF, sizeof(flash_data));&lt;br /&gt;
 &lt;br /&gt;
    /* Interrupt Vektoren verbiegen */&lt;br /&gt;
    temp = MCUCR;&lt;br /&gt;
    MCUCR = temp | (1&amp;lt;&amp;lt;IVCE);&lt;br /&gt;
    MCUCR = temp | (1&amp;lt;&amp;lt;IVSEL);&lt;br /&gt;
 &lt;br /&gt;
    /* Einstellen der Baudrate und aktivieren der Interrupts */&lt;br /&gt;
    uart_init( UART_BAUD_SELECT(BOOT_UART_BAUD_RATE,F_CPU) ); &lt;br /&gt;
    sei();&lt;br /&gt;
 &lt;br /&gt;
    uart_puts(&amp;quot;Hallo hier ist der echte Bootloader\n\r&amp;quot;);&lt;br /&gt;
    _delay_ms(2000);&lt;br /&gt;
 &lt;br /&gt;
    do&lt;br /&gt;
    {&lt;br /&gt;
        c = uart_getc();&lt;br /&gt;
        if( !(c &amp;amp; UART_NO_DATA) )&lt;br /&gt;
        {&lt;br /&gt;
             /* Programmzustand: Parser */&lt;br /&gt;
             if(boot_state == BOOT_STATE_PARSER)&lt;br /&gt;
             {&lt;br /&gt;
                  switch(parser_state)&lt;br /&gt;
                  {&lt;br /&gt;
                      /* Warte auf Zeilen-Startzeichen */&lt;br /&gt;
                      case PARSER_STATE_START:			&lt;br /&gt;
                          if((uint8_t)c == START_SIGN) &lt;br /&gt;
                          {&lt;br /&gt;
                              uart_putc(XOFF);&lt;br /&gt;
                              parser_state = PARSER_STATE_SIZE;&lt;br /&gt;
                              hex_cnt = 0;&lt;br /&gt;
                              hex_check = 0;&lt;br /&gt;
                              uart_putc(XON);&lt;br /&gt;
                          }&lt;br /&gt;
                          break;&lt;br /&gt;
                      /* Parse Datengröße */&lt;br /&gt;
                      case PARSER_STATE_SIZE:	&lt;br /&gt;
                          hex_buffer[hex_cnt++] = (uint8_t)c;&lt;br /&gt;
                          if(hex_cnt == 2)&lt;br /&gt;
                          {&lt;br /&gt;
                              uart_putc(XOFF);&lt;br /&gt;
                              parser_state = PARSER_STATE_ADDRESS;&lt;br /&gt;
                              hex_cnt = 0;&lt;br /&gt;
                              hex_size = (uint8_t)hex2num(hex_buffer, 2);&lt;br /&gt;
                              hex_check += hex_size;&lt;br /&gt;
                              uart_putc(XON);&lt;br /&gt;
                           }&lt;br /&gt;
                           break;&lt;br /&gt;
                      /* Parse Zieladresse */&lt;br /&gt;
                      case PARSER_STATE_ADDRESS:&lt;br /&gt;
                          hex_buffer[hex_cnt++] = (uint8_t)c;&lt;br /&gt;
                          if(hex_cnt == 4)&lt;br /&gt;
                          {&lt;br /&gt;
                              uart_putc(XOFF);&lt;br /&gt;
                              parser_state = PARSER_STATE_TYPE;&lt;br /&gt;
                              hex_cnt = 0;&lt;br /&gt;
                              hex_addr = hex2num(hex_buffer, 4);&lt;br /&gt;
                              hex_check += (uint8_t) hex_addr;&lt;br /&gt;
                              hex_check += (uint8_t) (hex_addr &amp;gt;&amp;gt; 8);&lt;br /&gt;
                              if(flash_page_flag) &lt;br /&gt;
                              {&lt;br /&gt;
                                  flash_page = hex_addr - hex_addr % SPM_PAGESIZE;&lt;br /&gt;
                                  flash_page_flag = 0;&lt;br /&gt;
                              }&lt;br /&gt;
                              uart_putc(XON);&lt;br /&gt;
                           }&lt;br /&gt;
                           break;&lt;br /&gt;
                      /* Parse Zeilentyp */&lt;br /&gt;
                      case PARSER_STATE_TYPE:	&lt;br /&gt;
                           hex_buffer[hex_cnt++] = (uint8_t)c;&lt;br /&gt;
                           if(hex_cnt == 2)&lt;br /&gt;
                           {&lt;br /&gt;
                               uart_putc(XOFF);&lt;br /&gt;
                               hex_cnt = 0;&lt;br /&gt;
                               hex_data_cnt = 0;&lt;br /&gt;
                               hex_type = (uint8_t)hex2num(hex_buffer, 2);&lt;br /&gt;
                               hex_check += hex_type;&lt;br /&gt;
                               switch(hex_type)&lt;br /&gt;
                               {&lt;br /&gt;
                                   case 0: parser_state = PARSER_STATE_DATA; break;&lt;br /&gt;
                                   case 1: parser_state = PARSER_STATE_CHECKSUM; break;&lt;br /&gt;
                                   default: parser_state = PARSER_STATE_DATA; break;&lt;br /&gt;
                               }&lt;br /&gt;
                               uart_putc(XON);&lt;br /&gt;
                           }&lt;br /&gt;
                           break;&lt;br /&gt;
                      /* Parse Flash-Daten */&lt;br /&gt;
                      case PARSER_STATE_DATA:&lt;br /&gt;
                          hex_buffer[hex_cnt++] = (uint8_t)c;&lt;br /&gt;
                          if(hex_cnt == 2)&lt;br /&gt;
                          {&lt;br /&gt;
                              uart_putc(XOFF);&lt;br /&gt;
                              uart_putc(&#039;.&#039;);&lt;br /&gt;
                              hex_cnt = 0;&lt;br /&gt;
                              flash_data[flash_cnt] = (uint8_t)hex2num(hex_buffer, 2);&lt;br /&gt;
                              hex_check += flash_data[flash_cnt];&lt;br /&gt;
                              flash_cnt++;&lt;br /&gt;
                              hex_data_cnt++;&lt;br /&gt;
                              if(hex_data_cnt == hex_size)&lt;br /&gt;
                              {&lt;br /&gt;
                                  parser_state = PARSER_STATE_CHECKSUM;&lt;br /&gt;
                                  hex_data_cnt=0;&lt;br /&gt;
                                  hex_cnt = 0;&lt;br /&gt;
                              }&lt;br /&gt;
                              /* Puffer voll -&amp;gt; schreibe Page */&lt;br /&gt;
                              if(flash_cnt == SPM_PAGESIZE)&lt;br /&gt;
                              {&lt;br /&gt;
                                  uart_puts(&amp;quot;P\n\r&amp;quot;);&lt;br /&gt;
                                  _delay_ms(100);&lt;br /&gt;
                                  program_page((uint16_t)flash_page, flash_data);&lt;br /&gt;
                                  memset(flash_data, 0xFF, sizeof(flash_data));&lt;br /&gt;
                                  flash_cnt = 0;&lt;br /&gt;
                                  flash_page_flag = 1;&lt;br /&gt;
                              }&lt;br /&gt;
                              uart_putc(XON);&lt;br /&gt;
                          }&lt;br /&gt;
                          break;&lt;br /&gt;
                      /* Parse Checksumme */                             &lt;br /&gt;
                      case PARSER_STATE_CHECKSUM:&lt;br /&gt;
                          hex_buffer[hex_cnt++] = (uint8_t)c;&lt;br /&gt;
                          if(hex_cnt == 2)&lt;br /&gt;
                          {&lt;br /&gt;
                              uart_putc(XOFF);&lt;br /&gt;
                              hex_checksum = (uint8_t)hex2num(hex_buffer, 2);&lt;br /&gt;
                              hex_check += hex_checksum;&lt;br /&gt;
                              hex_check &amp;amp;= 0x00FF;&lt;br /&gt;
                              /* Dateiende -&amp;gt; schreibe Restdaten */ &lt;br /&gt;
                              if(hex_type == 1)&lt;br /&gt;
                              {&lt;br /&gt;
                                  uart_puts(&amp;quot;P\n\r&amp;quot;);&lt;br /&gt;
                                  _delay_ms(100);&lt;br /&gt;
                                  program_page((uint16_t)flash_page, flash_data);&lt;br /&gt;
                                  boot_state = BOOT_STATE_EXIT;&lt;br /&gt;
                              }&lt;br /&gt;
                              /* Überprüfe Checksumme -&amp;gt; muss &#039;0&#039; sein */&lt;br /&gt;
                              if(hex_check == 0) parser_state = PARSER_STATE_START;&lt;br /&gt;
                              else parser_state = PARSER_STATE_ERROR;&lt;br /&gt;
                              uart_putc(XON);&lt;br /&gt;
                          }&lt;br /&gt;
                          break;			&lt;br /&gt;
                      /* Parserfehler (falsche Checksumme) */&lt;br /&gt;
                      case PARSER_STATE_ERROR:&lt;br /&gt;
                          uart_putc(&#039;#&#039;);&lt;br /&gt;
                          break;			&lt;br /&gt;
                      default:&lt;br /&gt;
                          break;&lt;br /&gt;
                  }&lt;br /&gt;
             }&lt;br /&gt;
             /* Programmzustand: UART Kommunikation */               &lt;br /&gt;
             else if(boot_state != BOOT_STATE_PARSER)&lt;br /&gt;
             {&lt;br /&gt;
                 switch((uint8_t)c)&lt;br /&gt;
                 {&lt;br /&gt;
                     case &#039;p&#039;: &lt;br /&gt;
                         boot_state = BOOT_STATE_PARSER;&lt;br /&gt;
                         uart_puts(&amp;quot;Programmiere den Flash!\n\r&amp;quot;);&lt;br /&gt;
                         uart_puts(&amp;quot;Kopiere die Hex-Datei und füge sie&amp;quot;&lt;br /&gt;
                                   &amp;quot; hier ein (rechte Maustaste)\n\r&amp;quot;);&lt;br /&gt;
                         break;&lt;br /&gt;
                     case &#039;q&#039;: &lt;br /&gt;
                         boot_state = BOOT_STATE_EXIT;&lt;br /&gt;
                         uart_puts(&amp;quot;Verlasse den Bootloader!\n\r&amp;quot;);&lt;br /&gt;
                         break;&lt;br /&gt;
                     default:&lt;br /&gt;
                         uart_puts(&amp;quot;Du hast folgendes Zeichen gesendet: &amp;quot;);&lt;br /&gt;
                         uart_putc((unsigned char)c);&lt;br /&gt;
                         uart_puts(&amp;quot;\n\r&amp;quot;);&lt;br /&gt;
                         break;&lt;br /&gt;
                 }&lt;br /&gt;
             }&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
    while(boot_state!=BOOT_STATE_EXIT);&lt;br /&gt;
 &lt;br /&gt;
    uart_puts(&amp;quot;Reset AVR!\n\r&amp;quot;);&lt;br /&gt;
    _delay_ms(1000);&lt;br /&gt;
 &lt;br /&gt;
    /* Interrupt Vektoren wieder gerade biegen */&lt;br /&gt;
    temp = MCUCR;&lt;br /&gt;
    MCUCR = temp | (1&amp;lt;&amp;lt;IVCE);&lt;br /&gt;
    MCUCR = temp &amp;amp; ~(1&amp;lt;&amp;lt;IVSEL);&lt;br /&gt;
 &lt;br /&gt;
    /* Reset */&lt;br /&gt;
    start();&lt;br /&gt;
&lt;br /&gt;
    return 0;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Erklärung des Codes&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Der Bootloader wird als &#039;&#039;Zustandsmaschine&#039;&#039; programmiert. Die Variable &#039;&#039;boot_state&#039;&#039; beinhaltet den aktuelle Programmzustand. Für den Parser gibt es eine eigene Zustandsvariable &#039;&#039;parser_state&#039;&#039;, welche die einzelne Zustände des Parsers hält. Mit jeder HEX-Datei-Zeile läuft der Parser einmal durch alle Zustände. Nach Abarbeiten des aktuellen Zustands und Auswertung der empfangenen Daten wird der nächste Zustand aktiviert usw. Für das Verarbeiten der Datei wird jedes Mal die Kommunikation angehalten und ein &#039;&#039;XOFF&#039;&#039; gesendet. Nach Abarbeitung der Daten gibt der Parser den seriellen Empfang wieder frei (&#039;&#039;XON&#039;&#039;). &#039;&#039;&#039;&#039;&#039;Es ist also wichtig, dass in PuTTY die XON/XOFF-Flußkontrolle aktiviert wird!&#039;&#039;&#039;&#039;&#039; Durch den interruptgesteuerten Empfang mit einem 32 Byte tiefen Empfangspuffer geht kein Byte verloren. Am Ende einer HEX-Datei-Zeile wird die Checksumme ausgewertet. Bei falscher Checksumme springt der Parser in den &#039;&#039;PARSER_STATE_ERROR&#039;&#039;, aus dem er nicht mehr rauskommt. Somit wird kein weiteres Byte in den Flash geschrieben. Zusätzlich könnte man noch implementieren, dass der Flash wieder gelöscht wird, wenn falsche Daten empfangen wurden, damit kein unvollständiges Programm im Flash steht.&lt;br /&gt;
Einschränkend muss noch festgehalten werden, das der Bootloader in dieser Fassung einen Adressraum bis 64K unterstützt (HEX-Zeilentyp 1). Die erweiterten Adressräume (HEX-Zeilentyp 2 bis 5) werden noch nicht unterstützt. Für ATmega-Devices mit &amp;gt; 64K Flash muss der Bootloader noch erweitert werden.&lt;br /&gt;
&lt;br /&gt;
Nach dem Kompilieren beträgt die Größe des Bootloaders 1796 Byte, wir sind also unterhalb der 2048 Byte die wird &amp;quot;verbraten&amp;quot; können. Der Datenspeicher wird mit 283 Byte belastet.&lt;br /&gt;
&lt;br /&gt;
Die Funktion des Bootloaders sieht wie folgt aus: Nach dem Reset wartet der Bootloader 2 Sekunden auf Eingaben (&#039;&#039;_delay_ms(2000);&#039;&#039;). Falls keine Eingaben von der Konsole kommen, springt der Bootloader zur Anwendung. Damit ist gewährleiset, dass die Anwendung später automatisch startet, auch wenn wir keine Taste drücken. Wird ein &#039;&#039;p&#039;&#039; gedrückt, springt der Bootloader in den &#039;&#039;BOOT_STATE_PARSER&#039;&#039; und erwartet eine HEX-Datei auf der Konsole. Dies ist der Zeitpunkt, die HEX-Datei der Anwendung mit Copy &amp;amp; Paste in die Konsole zu schreiben. Zum Einfügen von Daten aus dem Zwischenspeicher in die Konsole wird bei PuTTY die rechte Maustaste verwendet.&lt;br /&gt;
&lt;br /&gt;
== Schritt 4 - Flashen und Ausprobieren des Bootloaders ==&lt;br /&gt;
Nach dem Flashen via AVRISPmkII startet der Bootloader in der Konsole. Da noch kein Anwendungsprogramm im Flash liegt, startet der Bootloader nach 2 Sekunden immer wieder neu. Nach Drücken der Taste &#039;&#039;p&#039;&#039; erwartet der Bootlader die HEX-Datei der Anwendung. Nach dem Einfügen der Datei in Konsole erscheint für jedes empfangene Byte ein Punkt (&amp;quot;.&amp;quot;). Das Beschreiben einer Flash-&#039;&#039;Page&#039;&#039; kenzeichnet ein &#039;&#039;P&#039;&#039;. Nach dem erfolgreichen Flashen startet die Anwendung automatisch.&lt;br /&gt;
&lt;br /&gt;
Nach erfolgreichem Flashen des Bootloaders via AVRISPmkII erscheint nach dem Reset folgendes Bild:&lt;br /&gt;
&lt;br /&gt;
[[Bild:PuTTY-Real-Bootloader-start.png|PuTTY: Bootloader nach dem Reset]]&lt;br /&gt;
&lt;br /&gt;
Drückt man die Taste &#039;&#039;&#039;p&#039;&#039;&#039;, springt ist der Bootloader bereit zum Empfang der HEX-Datei:&lt;br /&gt;
&lt;br /&gt;
[[Bild:PuTTY-Real-Bootloader-wait.png|PuTTY: Warten auf die HEX-Datei &amp;quot;Anwendung.hex&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
Nach Kopieren &amp;amp; Einfügen der HEX-Datei der vorher kompilierten Anwendung, hier die Intel-HEX-Datei &amp;quot;Anwendung.hex&amp;quot;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
:100000002CC046C045C044C043C042C041C040C0EF&lt;br /&gt;
:100010003FC03EC03DC03CC03BC03AC039C038C004&lt;br /&gt;
:1000200037C036C064C08FC033C032C031C030C0AA&lt;br /&gt;
:100030002FC02EC048696572206973742064617393&lt;br /&gt;
:1000400020416E77656E64756E677370726F67724C&lt;br /&gt;
:10005000616D6D2E2E2E0D0A000011241FBECFEFF4&lt;br /&gt;
:10006000D4E0DEBFCDBF11E0A0E0B1E0EAE6F2E00F&lt;br /&gt;
:1000700002C005900D92A434B107D9F711E0A4E4B1&lt;br /&gt;
:10008000B1E001C01D92A938B107E1F702D0EBC081&lt;br /&gt;
:10009000B7CFEF92FF920F931F93CF93DF9383E33A&lt;br /&gt;
:1000A00090E07BD0789484E390E0D0D088ECE82E88&lt;br /&gt;
:1000B000F12C00E018E18BD0EC0190FDFCCF8236F2&lt;br /&gt;
:1000C00069F480E091E0B6D080E197E2F7013197E2&lt;br /&gt;
:1000D000F1F70197D9F7F8010995EDCF8CE191E09F&lt;br /&gt;
:1000E000A9D08C2F91D081E491E0A4D0E4CF1F92CD&lt;br /&gt;
:1000F0000F920FB60F9211242F938F939F93EF932C&lt;br /&gt;
:10010000FF939091C0002091C600E0918601EF5FBF&lt;br /&gt;
:10011000EF7180918701E81711F482E008C0892F00&lt;br /&gt;
:100120008871E0938601F0E0EC59FE4F20838093C4&lt;br /&gt;
:100130008801FF91EF919F918F912F910F900FBEAA&lt;br /&gt;
:100140000F901F9018951F920F920FB60F921124C7&lt;br /&gt;
:100150008F939F93EF93FF939091840180918501FA&lt;br /&gt;
:10016000981769F0E0918501EF5FEF71E0938501E9&lt;br /&gt;
:10017000F0E0EC5BFE4F80818093C60005C080916B&lt;br /&gt;
:10018000C1008F7D8093C100FF91EF919F918F916E&lt;br /&gt;
:100190000F900FBE0F901F9018959C011092840134&lt;br /&gt;
:1001A00010928501109286011092870197FF04C07A&lt;br /&gt;
:1001B00082E08093C0003F773093C5002093C40055&lt;br /&gt;
:1001C00088E98093C10086E08093C20008959091F1&lt;br /&gt;
:1001D000860180918701981719F420E031E012C060&lt;br /&gt;
:1001E000E0918701EF5FEF71E0938701F0E0EC5958&lt;br /&gt;
:1001F000FE4F308120918801922F80E0AC01430FA7&lt;br /&gt;
:10020000511D9A01C9010895282F909184019F5F83&lt;br /&gt;
:100210009F71809185019817E1F3E92FF0E0EC5B85&lt;br /&gt;
:10022000FE4F2083909384018091C100806280936F&lt;br /&gt;
:10023000C1000895CF93DF93EC0102C02196E4DF63&lt;br /&gt;
:1002400088818823D9F7DF91CF910895CF93DF93E9&lt;br /&gt;
:10025000EC0101C0D9DFFE01219684918823D1F7FA&lt;br /&gt;
:0A026000DF91CF910895F894FFCFCD&lt;br /&gt;
:10026A00537072696E6765207A756D20426F6F747C&lt;br /&gt;
:10027A006C6F616465722E2E2E0D0A00447520681B&lt;br /&gt;
:10028A0061737420666F6C67656E646573205A6566&lt;br /&gt;
:10029A00696368656E20676573656E6465743A2084&lt;br /&gt;
:0402AA00000A0D0039&lt;br /&gt;
:00000001FF&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
erscheinen folgende Ausgaben in PuTTY:&lt;br /&gt;
&lt;br /&gt;
[[Bild:PuTTY-Real-Bootloader-prog.png|PuTTY: Flashen der HEX-Datei &amp;quot;Anwendung.hex&amp;quot;]]&lt;br /&gt;
&lt;br /&gt;
Nach erfolgreichem Flashen startet die Anwendung und meldet sich mit der Zeile&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Hier ist das Anwendungsprogramm...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Jetzt können nach belieben Tasten gedrückt werden, was die Anwendung jedesmal quittiert:&lt;br /&gt;
&lt;br /&gt;
[[Bild:PuTTY-Real-Bootloader-anwend.png|PuTTY: Ausprobieren der Anwendung]]&lt;br /&gt;
&lt;br /&gt;
Nach Drücken der Taste &#039;&#039;&#039;b&#039;&#039;&#039; springt die Anwendung wieder zur Startadresse des Bootloaders, also zur Adresse &#039;&#039;0x1800&#039;&#039; im Flash-Speicher. Nun hat man wieder 2 Sekunden Zeit, um die Taste &#039;&#039;&#039;p&#039;&#039;&#039; zu drücken, sonst startet die Anwendung wieder:&lt;br /&gt;
&lt;br /&gt;
[[Bild:PuTTY-Real-Bootloader-reset.png|PuTTY: Rücksprung zum Bootloader auf Adresse 0x1800]]&lt;br /&gt;
&lt;br /&gt;
Damit ist das Tutorial abgeschlossen.&lt;br /&gt;
 &lt;br /&gt;
&#039;&#039;&#039;&#039;&#039;Viel Spass beim Ausprobieren und Weiterentwickeln!&#039;&#039;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Zusammenfassung =&lt;br /&gt;
&lt;br /&gt;
Wer den Artikel bis hier hin nachvollzogen hat, ist jetzt in der Lage einen Bootloader selbst zu schreiben. Dabei kann der Bootloader an jede in Frage kommenden ATmega-Plattform angepaßt werden. Dazu muss&lt;br /&gt;
* die Linkereinstellung für das Verschieben der Sektion &#039;&#039;.text&#039;&#039; angepasst werden und (&#039;&#039;&#039;-Ttext = 0xXXXX&#039;&#039;&#039;)&lt;br /&gt;
* evtl. der virtuelle Funktionspointer in der Anwendung geändert werden (falls ein Rücksprung zum Bootloader gewünscht ist &#039;&#039;&#039;void (*bootloader)(void) = 0xXXXX&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Um dies zu erleichtern, habe ich hier die Sprungadressen für ausgewählte AVRs tabellarisch zusammengetragen. Dabei wurde immer die maximale Größe des Bootloader betrachtet, also &#039;&#039;&#039;BOOTSZ0=0&#039;&#039;&#039; und &#039;&#039;&#039;BOOTSZ1=0&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
{| border=&amp;quot;1&amp;quot; class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Größe und Startadresse der Bootloader Sektion für ausgewählte AVR-Devices&lt;br /&gt;
|- &lt;br /&gt;
! Device || Flash-Größe&amp;lt;br&amp;gt;für Applikation || Flash-Größe&amp;lt;br&amp;gt;des Bootloaders || Startadresse des Bootloaders&amp;lt;br&amp;gt;(Byteadresse)&lt;br /&gt;
|-&lt;br /&gt;
| ATmega8/88 || 6144 Byte || 2048 Byte || 0x1800&lt;br /&gt;
|-&lt;br /&gt;
| ATmega16/164/168 || 14336 Byte || 2048 Byte || 0x3800&lt;br /&gt;
|-&lt;br /&gt;
| ATmega32/324/328 || 28672 Byte || 4096 Byte || 0x7000&lt;br /&gt;
|-&lt;br /&gt;
| ATmega64/644/640 || 57344 Byte || 8192 Byte || 0xE000&lt;br /&gt;
|-&lt;br /&gt;
| ATmega128/1284/1280/1281 || 122880 Byte || 8192 Byte || 0x1E000&lt;br /&gt;
|-&lt;br /&gt;
| ATmega2560/2561 ||  253952 Byte || 8192 Byte || 0x3E000&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Damit kann jeder den Bootloader nach seinen Wünschen anpassen. Eine gängige Praxis ist auch, ein kleines PC-Programm zu schreiben, welches dem Bootloader die Flash-Daten gleich Binär übergibt. Das geht schneller und spart das aufwendige Parsen. Eine weitere Idee ist es, den Bootloader so anzupassen, das er sich wie ein STK500 an der seriellen Schnittstelle verhält. Dazu muss man die [http://www.atmel.com/dyn/products/tools_card.asp?tool_id=2735 AP068] von Atmel umsetzen. Auch dies sollte nach dem Studium des Tutorial kein Problem mehr sein :)&lt;br /&gt;
&lt;br /&gt;
[http://www.mikrocontroller.net/user/show/mario Nachricht an den Autor]&lt;br /&gt;
&lt;br /&gt;
= FAQ =&lt;br /&gt;
&lt;br /&gt;
== Wie kann man Bootloader und Anwendungsprogramm gemeinsam flashen? ==&lt;br /&gt;
&lt;br /&gt;
Es ist in C ohne weiteres nicht möglich ein gemeinsames Hexfile aus Bootloader und Anwendungsprogramm zu kompilieren. Aber man kann das getrennt erstellte Hexfile des Bootloaders und das getrennt erstellte Hexfile des Anwendungsprogramms zusammenfügen und so gemeinsam mit ISP flashen. Dazu die letzte Zeile des 1. Hexfiles entfernen und dahinter das 2. Hexfile anfügen [http://www.mikrocontroller.net/topic/199241#1955092], [http://www.mikrocontroller.net/topic/198428#1949164]. &lt;br /&gt;
&lt;br /&gt;
[[Kategorie:AVR-Programmer und -Bootloader|B]]&lt;/div&gt;</summary>
		<author><name>Sebion7125</name></author>
	</entry>
	<entry>
		<id>https://www.mikrocontroller.net/index.php?title=AVR_TWI&amp;diff=52546</id>
		<title>AVR TWI</title>
		<link rel="alternate" type="text/html" href="https://www.mikrocontroller.net/index.php?title=AVR_TWI&amp;diff=52546"/>
		<updated>2010-11-05T18:58:36Z</updated>

		<summary type="html">&lt;p&gt;Sebion7125: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;von Alexander Starke&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Grundlagen ==&lt;br /&gt;
&lt;br /&gt;
Das TWI (Two Wire Interface) ist begründet durch seinen Aufbau ideal auf typische Mikrocontroller Applikationen zugeschnitten. Durch seinen 7 Bit breiten Adressraum können bis zu 128 (2&amp;lt;sup&amp;gt;7&amp;lt;/sup&amp;gt; = 128) Geräte miteinander verschaltet werden. Im Gegensatz zum SPI ([[Serial Peripheral Interface]]) werden nur zwei Busleitungen benötigt. Eine dient der Bereitstellung des Taktes (SCL) und die andere dem Datentransport (SDA). Die einzige zusätzlich benötigt Hardware besteht aus zwei Pull-Up Widerständen, welche von jeweils einer Busleitung gegen Vcc (5V) geschalten werden. Da alle Bustreiber mit offenem Kollektor bzw. Drain am Bus anliegen, ergibt sich eine logische UND-Verknüpfung. D.h., sobald irgendein Gerät auf einer der Busleitungen Low-Pegel anlegt, liegt automatisch die gesamte Busleitung auf Low. Der BUS hat nur High-Pegel, wenn alle angeschlossenen Geräte auch High-Pegel an ihrer entsprechenden Schnittstelle haben.&lt;br /&gt;
&lt;br /&gt;
Genau wie beim SPI initiiert auch beim TWI der Master den Datentransfer und beendet selbigen auch wieder. Gestartet wird eine Transmission durch eine Start-Bedingung und entsprechend beendet durch eine Stop-Bedingung. Während einer Transmission gilt der Bus als &amp;quot;busy&amp;quot; (beschäftigt) und kein anderer Master darf versuchen, Kontrolle über ihn zu erlangen. Einzige Ausnahme bildet hier der Fall, dass vor einer Stop-Bedingung durch den gerade aktiven Master noch eine zusätzliche Start-Bedingung auf den Bus gegeben wird. Dieser Fall tritt normalerweise dann ein, wenn der Master noch weitere Daten zu versenden hat und nicht die Kontrolle über den Bus verlieren möchte. Nach solch einem wiederholten Start (Repeated Start) ist der Bus wieder beschäftigt, bis zum nächsten Stop.&lt;br /&gt;
Start- und Stop-Bedingungen werden signalisiert, indem der Pegel der SDA-Leitung wechselt, während SCL High-Pegel hat.&lt;br /&gt;
&lt;br /&gt;
Alle Adresspakete auf dem TWI Bus haben eine Länge von 9 Bit. Davon beinhalten 7 Bit wie bereits eingangs erwähnt die Adresse der angesprochenen Komponente. Zusätzlich gibt es noch ein Bit, dass darüber bestimmt, ob ein Lese- oder ein Schreibzugriff durchgeführt werden soll (R/W=1 -&amp;gt; Lesen; RW=0 -&amp;gt; Schreiben). Das 9 Bit dient der Bestätigung. Wenn ein Slave bemerkt, dass er angesprochen wird, so bestätigt er dies, indem er mit dem 9. Taktzyklus (ACK) von SCL SDA auf Low-Pegel legt. Sollte der angesprochene Slave aus irgendwelchen Gründen nicht antworten können, so sollte SDA auf H-Pegel bleiben. Der Master hat dann die Wahl, ob er ein Stop sendet oder einen wiederholten Start durchführt.&lt;br /&gt;
&lt;br /&gt;
* SLA +R   --&amp;gt;    Adresspaket mit einer Slave-Adresse und einem Lese-Bit&lt;br /&gt;
* SLA +W  --&amp;gt;    Adresspaket mit einer Slave-Adresse und einem Schreib-Bit&lt;br /&gt;
&lt;br /&gt;
Das höchstwertige Bit wird prinzipiell zuerst übertragen (MSB Most Significant Bit). Die Slave-Adressen können durch den Anwender frei gewählt werden, nur 0000 000 ist reserviert, hiermit werden alle Slaves angesprochen. Wird ein solcher Zugriff durchgeführt, so sollten alle Slaves im ACK-Zyklus SDA auf L-Pegel legen.&lt;br /&gt;
Benutzt wird diese Aktion, wenn der Master die selben Daten an mehrere Slaves senden möchte. Sinn macht die Verwendung nur in Verbindung mit dem Schreib-Bit. Ein Setzen des Lese-Bits hätte zur Folge, dass verschiedene Slaves ja verschiedene Daten auf den Bus stellen könnten, was zu einem Durcheinander führen würde. Wird das Schreib-Bit gesetzt, so setzen im ACK-Zyklus alle Slaves SDA auf L-Pegel, welche den allgemeinen Adressaufruf erhalten und ausgewertet haben (also die nicht beschäftigt waren). Die folgenden Datenpakete werden dann von allen Slaves empfangen, welche SDA auf L-Pegel gelegt hatten.&lt;br /&gt;
&lt;br /&gt;
Alle Datenpakete auf dem TWI-Bus haben analog zu den Adresspaketen 9 Bit. Hiervon sind 8 Datenbits. Das 9. dient der Bestätigung. Während einer Datenübertragung ist es Aufgabe des Masters, den Takt, das Start- und das Stopzeichen bereitzustellen. Aufgabe des Empfängers ist die Bestätigung der erhaltenen Daten, indem er die SDA-Leitung während des 9. SCL-Zyklus auf L-Pegel legt. Dieses wird als ACK bezeichnet (Acknowledge). Bleibt SDA auf H-Pegel, so wird dem Sender signalisiert, dass die gesendeten Daten nicht empfangen wurden (NACK). Das MSB wird zuerst übertragen.&lt;br /&gt;
&lt;br /&gt;
Wenn man nun Adress- und Datenpakete kombiniert, hat man schon eine fertige Transmission. Diese besteht aus:&lt;br /&gt;
&lt;br /&gt;
* START    --&amp;gt;    SLA R/W    --&amp;gt;    ein oder mehr Datenpakete    --&amp;gt;    STOP&lt;br /&gt;
&lt;br /&gt;
Ein START gefolgt von einem STOP ist nicht zulässig. Wenn der Takt des Masters für den Slave zu schnell ist oder er noch mehr Zeit zur Bearbeitung braucht, so kann er SCL einfach länger auf L-Pegel halten. Die Verlängerung der L-Phase von SCL hat allerdings keinen Einfluss auf die Länge der H-Phase, da diese vom Master zur Verfügung gestellt wird. Dadurch kann es allerdings zu einer Reduzierung des Datentransfers kommen.&lt;br /&gt;
&lt;br /&gt;
== Multi-Master-Bussysteme ==&lt;br /&gt;
&lt;br /&gt;
Das TWI-Bussystem erlaubt den Multi-Master Betrieb. Es wurden spezielle Vorkehrungen getroffen, so dass auch wenn mehrere Master zur selben Zeit eine Transmission beginnen wollen keine Probleme auftreten und der Bus normal funktioniert. Nur die zwei folgenden Probleme sollten beachtet werden:&lt;br /&gt;
&lt;br /&gt;
# Es ist Sache des Anwenders, seine Algorithmen so auszulegen, dass in diesem Fall nur ein Master seine Transmission fortsetzt. Alle anderen Master sollten ihre Transmission sofort abbrechen. Diesen Auswahlprozess zwischen den Mastern nennt man Arbitrierung (Entscheidung). Wenn ein Master bemerkt, dass er den Entscheidungsprozess (die Arbitrierung) verloren hat, sollte er sofort in den Slave-Modus gehen, da es sein kann, dass der Master welcher den Prozess gewonnen hat ihn adressieren will. Die Tatsache, dass mehrere Master versucht hatten, eine Übertragung zu starten, sollte für die Slaves nicht feststellbar sein, die Daten auf dem Bus dürfen nicht beschädigt sein.&lt;br /&gt;
# Da verschiedene Master mit verschiedenen Taktfrequenzen auf dem Bus arbeiten könnten, ist eine Festlegung zu treffen, wie man diese synchronisiert. Dieses erleichtert auch den Arbitrierungsprozess.&lt;br /&gt;
&lt;br /&gt;
Diese Lösung dieses Problems stellt die schon oben angesprochene UND-Verknüpfung aller Komponenten auf dem Bus dar. So werden alle seriellen Taktraten der einzelnen Master UND verknüpft. Somit ergibt sich ein High-Pegel entsprechend dem des Masters mit dem kürzesten H-Pegel, der Low-Pegel ist durch den Master mit der geringsten Taktrate gegeben.&lt;br /&gt;
&lt;br /&gt;
Da der Multi-Master Betrieb für meine Anwendung keinen Belang hat, werde ich hier nicht näher darauf eingehen.&lt;br /&gt;
&lt;br /&gt;
==Aufbau des TWI==&lt;br /&gt;
&lt;br /&gt;
Der SCL- und der SDA-Pin stellen die Schnittstelle des einzelnen MC mit dem Bus dar. Zusätzlich ist intern vorgesehen, dass Spannungsspitzen, welche kürzer als 50ns sind, herausgefiltert werden. Es besteht bei manchen Konfigurationen die Möglichkeit, die internen Pull-Up Widerstände zu verwenden, dies kann die Verwendung der externen überflüssig machen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich verfügt der ATmega über einen Bitraten-Generator, welcher im Masterbetrieb das entsprechende Signal auf SCL gibt. Die Taktrate wird durch das TWBR (TWI Bit Rate Register) und TWSR (TWI Status Register) festgelegt. Zu beachten ist, dass die interne Taktfrequenz der einzelnen Slaves mindestens 16 mal höher als die Taktrate des Bus ist. Diese ergibt sich nach folgender Formel:&lt;br /&gt;
&lt;br /&gt;
http://www.mikrocontroller.net/mc-project/Pages/AVR/TWI/twi_formel.gif&lt;br /&gt;
&lt;br /&gt;
* TWBR - TWI Bit Rate Register&lt;br /&gt;
* TWPS - TWI Prescaler Bits im TWI Status Register&lt;br /&gt;
&lt;br /&gt;
Des weiteren verfügt der MC über je ein Daten- und Adressschieberegister, einen START/STOP Controller und die Arbitrierungslogik. Das TWDR (TWI Data Register) beinhaltet entweder die Adresse und Daten welche gesendet werden sollen oder die empfangene Adresse samt Daten. Zusätzlich existiert noch ein Register, welches das (N)ACK-Bit enthält, das aber nicht direkt zugänglich ist. Jedoch kann es im Empfangsmodus durch verändern von TWCR (TWI Control Register) bzw. im Empfangsmodus durch verändern von TWSR manipuliert werden.&lt;br /&gt;
&lt;br /&gt;
Der START/STOP Controller ist wie sein Name bereits sagt, dafür verantwortlich, den anderen Teilnehmern am Bus mitzuteilen, dass der entsprechende Master eine Übertragung plant bzw. beendet. Zusätzlich führt er auch den bereits erwähnten REPEATED START durch. Eine Besonderheit ist, dass er solche START/STOP-Zeichen auf dem Bus sogar detektieren kann, wenn sich der Controller in einem der Sleep-Modi befindet. Er kann somit &amp;quot;aufgeweckt&amp;quot; werden, wenn er von einem Master adressiert wird.&lt;br /&gt;
&lt;br /&gt;
Ein weiterer Bestandteil des TWI ist die &amp;quot;Adress Match Unit&amp;quot;. Diese überwacht, ob die empfangenen Adress-Bytes mit denen im TWAR (TWI Adress Register) übereinstimmen. Wenn TWGCE (TWI General Call Recognition Enable) in TWAR gesetzt ist, werden alle eingehenden Adress-Bytes zusätzlich noch daraufhin überprüft, ob eine allgemeine Ruf (0000 000) vorliegt. Sollte eine Übereinstimmung vorliegen, wird die Kontrolleinheit informiert, eventuelle Korrekturmaßnahmen können durchgeführt werden. Die TWI-Logik kann nun die Anforderung bestätigen, je nach dem welche Einstellungen in TWCR getroffen wurden. Wie bereits oben angesprochen wurde, arbeitet die Adress-Vergleichs-Logik sogar, wenn sich der MC in einem der Sleep-Modi befindet. Man kann den MC somit per TWI reaktivieren. Einzige Ausnahme bildet der Fall, dass der Controller zuvor durch einen anderen Interrupt reaktiviert wurde. Danach geht die TWI-Logik sofort in den Leerlauf. Sollte das bei der vorgesehenen Problemstellung zu Problemen führen, bleibt nur der Ausweg sämtliche anderen Interrupts in der Hinsicht zu sperren, dass sie den Controller nicht mehr reaktivieren können.&lt;br /&gt;
&lt;br /&gt;
Die Kontrolleinheit des TWI beobachtet ständig den Bus und antwortet auf Anfragen entsprechend den Einstellungen in TWCR. Tritt ein Ereignis ein, auf welches die angesprochene Einheit reagieren soll, so wird automatisch TWINT (TWI Interrupt Flag) gesetzt. Im nächsten Taktzyklus wird dann TWSR aktualisiert, in ihm steht jetzt ein Code mit welchem das Ereignis spezifiziert werden kann. TWSR beinhaltet nur relevante Informationen, wenn TWINT gesetzt wird, andernfalls beinhaltet es bloß einen Statuscode, welcher aussagt, dass keine relevanten Informationen vorliegen. Solange TWINT gesetzt ist, wird SCL auf Low Pegel belassen. Dies gibt dem angesprochenen MC die Chance, alle Anwendungen erst zu beenden, bevor er sich der Transmission widmet. TWINT wird gesetzt wenn:&lt;br /&gt;
&lt;br /&gt;
* wenn das TWI START/REPEATED START gesendet hat&lt;br /&gt;
* wenn das TWI SLA +R/W gesendet hat&lt;br /&gt;
* wenn das TWI ein Adress-Byte gesendet hat&lt;br /&gt;
* wenn das TWI seine &amp;quot;Vormacht&amp;quot; auf dem Bus verloren hat&lt;br /&gt;
* wenn das TWI durch seine eigene Slave-Adresse bzw. einen allgemeinen Ruf (general call) adressiert wurde&lt;br /&gt;
* wenn das TWI ein Datenbyte empfangen hat&lt;br /&gt;
* wenn ein STOP oder REPEATED START empfangen wurde, während es immer noch als Slave angesprochen ist&lt;br /&gt;
* wenn ein Busfehler durch einen illegalen START bzw. STOP aufgetreten ist&lt;br /&gt;
&lt;br /&gt;
== Benutzung des TWI ==&lt;br /&gt;
&lt;br /&gt;
Das TWI ist wie bereits ausführlich dargestellt wurde, byte- bzw. interruptbasiert. Dadurch ist es der Anwendersoftware möglich, parallel zum Datenversand bzw. -empfang auf dem TWI Bus noch weitere Anwendungen (Operationen) auszuführen. Die Ausführung einer ISR ist allein durch das Setzen von TWIE (TWI Interrupt Enable) in TWCR bedingt (die Interrupts müssen natürlich auch global freigegeben sein). Es ist Sache des Anwenders, ob das Setzen von TWINT einen Interrupt verursachen soll. Ist TWIE nicht gesetzt, so ist es dem Programm selbst überlassen, ständig TWINT zu prüfen, um sämtliche Ereignisse auf dem Bus mit zu bekommen. &lt;br /&gt;
&lt;br /&gt;
Bei jedem Setzen von TWINT ist eine Operation auf dem Bus abgeschlossen worden und es wird eine Antwort erwartet. In diesem Fall beinhaltet TWSR einen Wert, welcher ein direktes Maß für den aktuellen Status des Bus ist. Die Software legt nun fest, welche Aktion mit dem nächsten Buszyklus durchgeführt werden soll, indem sie TWCR und TWDR entsprechend verändert. Im folgenden wird schrittweise ein Beispiel für den Ablauf einer Übertragung gegeben.&lt;br /&gt;
&lt;br /&gt;
Um die entsprechenden Statusmakros (&#039;&#039;TW_*&#039;&#039;) verwenden zu können wird die entsprechende Headerdatei eingebunden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
#include &amp;lt;util/twi.h&amp;gt;&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zuerst muss vom Master ein START-Signal auf den Bus gegeben werden. Dies erfolgt durch Schreiben eines speziellen Wertes in TWCR. Nach Abschluss der Operation wird TWINT gesetzt. Die Logik wartet nun so lange, bis durch den Anwender das Flag wieder gelöscht wurde (durch Schreiben einer &#039;1&#039;). Unmittelbar nach dem Löschen von TWINT beginnt die Logik damit das START-Signal zu senden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
TWCR = _BV(TWINT) | _BV(TWSTA) | _BV(TWEN);                        //TWSTA = TWI START Condition Bit&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nach dem Senden des START wird sofort wieder TWINT in TWCR gesetzt. Zusätzlich beinhaltet TWSR jetzt den entsprechenden Status Code, welcher mitteilt, dass START erfolgreich gesendet wurde.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
while  (!(TWCR &amp;amp; (1&amp;lt;&amp;lt;TWINT)));&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Nachdem durch die Applikation TWSR daraufhin überprüft wurde, dass START erfolgreich gesendet wurde, kann es nun weitergehen. Im Fehlerfall könnte beispielsweise eine vom Anwender definierte Fehlerroutine greifen. &lt;br /&gt;
&lt;br /&gt;
Nun muss SLA_W in TWDR geladen werden. Ist dies abgeschlossen, muss wiederum ein spezieller Wert in TWCR geschrieben werden, um der TWI-Logik mitzuteilen, dass die Adresse und der Schreibbefehl aus TWDR gesendet werden können. Unmittelbar nachdem durch den Anwender dann TWINT in TWCR gelöscht wurde (Schreiben einer &#039;1&#039;) sendet das TWI das Adresspaket.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
if ((TWSR &amp;amp; 0xF8) != TW_START)&lt;br /&gt;
  ERROR();                                                                //Fehlerbehandlung&lt;br /&gt;
TWDR = SLA_W;&lt;br /&gt;
TWCR = (1&amp;lt;&amp;lt;TWINT) | (1&amp;lt;&amp;lt;TWEN);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nach Abschluss der Sendung wird wiederum TWINT gesetzt in TWSR steht der entsprechende Statuscode, welcher über Erfolg bzw. Misserfolg der Sendung urteilt. In ihm ist auch das ACK-Bit des angesprochenen Slaves enthalten (oder auch nicht, was dann einen Fehler bedeuten würde).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
while (!(TWCR &amp;amp; (1&amp;lt;&amp;lt;TWINT)));&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Nach der Prüfung von TWSR ob bei der Sendung keine Fehler aufgetreten sind, kann das Datenpaket in TWDR geladen werden. Erneut muss ein spezieller Wert in TWCR geschrieben werden, welcher der Logik sagt, dass ein Datenpaket aus TWDR versendet werden soll. Nach dem Löschen von TWINT wird dieses automatisch versendet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
if ((TWSR &amp;amp; 0xF8) != TW_MT_SLA_ACK)&lt;br /&gt;
  ERROR();&lt;br /&gt;
TWDR = DATA;&lt;br /&gt;
TWCR = (1&amp;lt;&amp;lt;TWINT) | (1&amp;lt;&amp;lt;TWEN);&lt;br /&gt;
&amp;lt;/c&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Nachdem TWINT gesetzt wurde kann mit Hilfe von TWSR überprüft werden, ob das Datenpaket erfolgreich gesendet und vom angesprochenen Slave angenommen wurde (ACK-Bit).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
while (!(TWCR &amp;amp; (1&amp;lt;&amp;lt;TWINT)));&lt;br /&gt;
 &amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Nachdem bis hierhin alles funktioniert hat (angenommen), muss nun nur noch ein STOP gesendet werden. Dies erfolgt analog zu den obigen Ausführungen durch Schreiben eines speziellen Wertes in TWCR. Nach dem Löschen von TWINT wird dieses gesendet. Allerdings wird danach TWINT nicht automatisch wieder gesetzt, wie es zuvor immer der Fall war.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;c&amp;gt;&lt;br /&gt;
if ((TWSR &amp;amp; 0xF8) != TW_MT_DATA_ACK)&lt;br /&gt;
  ERROR();&lt;br /&gt;
TWCR = (1&amp;lt;&amp;lt;TWINT)|(1&amp;lt;&amp;lt;TWEN)|&lt;br /&gt;
(1&amp;lt;&amp;lt;TWSTO);&lt;br /&gt;
&amp;lt;/c&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Anmerkung: Selbstverständlich muss zuvor beim anzusprechenden Slave in TWAR (TWI Adress Register) eine Adresse festgelegt werden, damit er auch gezielt angesprochen werden kann.&lt;br /&gt;
&lt;br /&gt;
== Übertragungsmodi ==&lt;br /&gt;
&lt;br /&gt;
Das TWI kann prinzipiell in vier verschiedenen Modi arbeiten: Master Transmitter (MT), Master Receiver (MR), Slave Transmitter (ST), Slave Receiver (SR). Diese können natürlich alle in einer Anwendung verwendet werden, je nachdem, wie sie es erfordert.&lt;br /&gt;
&lt;br /&gt;
=== Master Transmitter Mode ===&lt;br /&gt;
&lt;br /&gt;
Im MTM wird eine Abfolge von Bytes (Daten) an einen SR gesendet. Um ihn zu benutzen, muss das Adresspaket nach dem gesendeten START eine bestimmte Form aufweisen. Wird SLA+W gesendet, liegt der MTM vor, für SLA+R wäre es der MRM.&lt;br /&gt;
Das Senden eines START gestaltet sich wie folgt (TWCR):&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |1    |0    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
* TWEN:    Aktivierung des TWI&lt;br /&gt;
* TWSTA:    Senden des START&lt;br /&gt;
* TWINT:    um TWINT zu löschen&lt;br /&gt;
&lt;br /&gt;
Das TWI wartet nun solange, bis der Bus frei ist und sendet dann START. Danach wird TWINT wieder gesetzt und TWSR aktualisiert. Es sollte jetzt 0x08 enthalten. Beim Auslesen des Status-Code müssen die Prescaler-Bits mit Null maskiert werden. Um den MTM zu benutzen, muss SLA+W in TWDR geschrieben werden. Nachdem TWINT gelöscht wurde, wird dies gesendet. TWCR muss dazu die folgende Form haben:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |0    |0    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Nachdem SLA+W gesendet und das ACK-Bit empfangen wurde, wird TWINT erneut gesetzt. Der Statuscode in TWSR kann nun unter anderem folgende Formen haben: 0x18, 0x20, 0x38. &lt;br /&gt;
&lt;br /&gt;
Nachdem bis hierhin alles erfolgreich funktioniert hat, kann jetzt ein Datenpaket versendet werden. Dies erfolgt durch Schreiben der Daten in TWDR. TWDR kann nur aktualisiert werden, wenn TWINT gesetzt ist, andernfalls kommt es zu einem Fehler, TWWC (TWI Write Collision Bit) wird gesetzt. Um die Daten zu senden, muss TWINT erneut gelöscht werden. TWCR sollte so aussehen:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |1    |0    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Dieses Schema wiederholt sich nun solange, bis alle Daten versendet wurden und ein STOP gesendet werden kann. Dies erfolgt folgendermaßen:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |0    |1    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Ein erneuter Start (REPEATED START) erfolgt durch Schreiben der folgenden Werte in TWCR:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |1    |0    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Nach einem REPEATED START kann der Master denselben Slave erneut kontaktieren oder auch einen anderen, ohne ein STOP zu senden. Der REPEATED START erlaubt dem Master das Wechseln zwischen Slaves, MTM und MRM ohne die Kontrolle über den Bus zu verlieren.&lt;br /&gt;
&lt;br /&gt;
Eine Tabelle mit sämtlichen Status-Codes und den zugehörigen Ereignissen ist dem Datenblatt S.176 zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
=== Master Receiver Mode ===&lt;br /&gt;
&lt;br /&gt;
Im MRM empfängt der Master Daten von einem ST. Zunächst muss wieder START gesendet werden. Das folgende Adresspaket sollte dann SLA+R enthalten.&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |1    |0    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
* TWEN:    Aktivierung des TWI&lt;br /&gt;
* TWSTA:    Senden des START&lt;br /&gt;
* TWINT:    um TWINT zu löschen&lt;br /&gt;
&lt;br /&gt;
Das TWI wartet nun solange, bis der Bus frei ist und sendet dann START. Danach wird TWINT wieder gesetzt und TWSR aktualisiert. Es sollte jetzt 0x08 enthalten. Beim Auslesen des Status-Code müssen die Prescaler-Bits mit Null maskiert werden. Um den MTM zu benutzen, muss SLA+R in TWDR geschrieben werden. Nachdem TWINT gelöscht wurde, wird dies gesendet. TWCR muss dazu die folgende Form haben:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |0    |0    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Nachdem SLA+R gesendet und das ACK-Bit empfangen wurde, wird TWINT erneut gesetzt. Der Statuscode in TWSR kann nun unter anderem folgende Formen haben: 0x38, 0x40, 0x48. &lt;br /&gt;
Die empfangenen Daten können aus TWDR gelesen werden, so denn TWINT gesetzt ist. Dieses Schema kann sich bis zum Empfang des letzten Bytes immer wieder wiederholen. Nachdem das letzte Byte empfangen wurde, kann der Master dem Slave durch senden von NACK klar machen, dass keine Daten mehr erwartet werden. Beendet wird der Transfer durch senden von STOP oder REPEATED START.&lt;br /&gt;
Für STOP muss folgendes in TWCR geschrieben werden:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |0    |1    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Für einen REPEATED START muss folgendes in TWCR geschrieben werden:&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |1    |X   |1    |0    |X   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Nach einem REPEATED START kann der Master denselben Slave erneut kontaktieren oder auch einen anderen, ohne ein STOP zu senden. Der REPEATED START erlaubt dem Master das Wechseln zwischen Slaves, MTM und MRM ohne die Kontrolle über den Bus zu verlieren.&lt;br /&gt;
&lt;br /&gt;
Eine Tabelle mit sämtlichen Status-Codes und den zugehörigen Ereignissen ist dem Datenblatt S.179 zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
=== Slave Receiver Mode ===&lt;br /&gt;
&lt;br /&gt;
Im SRM werden Daten vom MT empfangen. Um einen Atmega8 im SRM zu betreiben, müssen TWAR und TWCR die folgende Form haben:&lt;br /&gt;
&lt;br /&gt;
TWAR:&lt;br /&gt;
Die oberen 7 Bit stellen die Adress dar, an die das TWI antwortet, wenn es von einem Master angesprochen wird. Wenn das LSB (Least Significant Bit) in Form von TWGCE gesetzt ist, antwortet der Slave auch auf allgemeine Rufe (general calls), andernfalls natürlich nicht.&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWA6|TWA5|TWA4|TWA3|TWA2|TWA1|TWA0|TWGCE&lt;br /&gt;
 |Hier|steht|dann|die|Adresse|des|Slave!|X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
TWCR:&lt;br /&gt;
TWEN muss zum aktivieren des TWI gesetzt werden. TWEA muss gesetzt werden, damit der Slave antwortet, falls er von einem Master oder gegeben falls durch einen general call angesprochen wird. TWSTA und TWSTO müssen auf Null gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |0    |1   |0    |0    |0   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Wenn TWAR und TWCR initialisiert wurden, wartet der Slave ab, bis er mit seiner Adresse bzw. gegebenen falls durch einen generall call angesprochen wird gefolgt von einem Datenrichtungs-Bit. Hierbei steht eine &#039;0&#039; für Schreiben (SR) und eine &#039;1&#039; für Lesen (ST).&lt;br /&gt;
Nachdem die Logik ihre eigene Adresse und ein Schreib-Bit erhalten hat, wird TWINT gesetzt und TWSR beinhaltet den entsprechenden Statuscode. Mit seiner Hilfe kann die Software dann eine sinnvolle Reaktion einleiten. Der Eintritt in den SRM kann auch erfolgen, wenn ein Master sein Vorrecht auf dem Bus verloren hat (0x68, 0x78).&lt;br /&gt;
&lt;br /&gt;
Wenn TWEA während eines Transfers zurückgesetzt wird, wird das TWI ein NACK (Not Acknowledge) auf den Bus nach Empfang des nächsten Bytes geben. Dies kann verwendet werden, wenn der Slave nicht mehr in der Lage ist, mehr Bytes zu empfangen. Solange TWEA &#039;0&#039; ist, reagiert das TWI nicht mehr auf seine eigene Slave-Adresse. Jedoch wird der Bus weiterhin beobachtet und das TWI ist nach dem Setzen von TWEA sofort wieder einsatzbereit. Somit kann dieses Feature verwendet werden, um einen Baustein für eine bestimmte Zeitspanne vom Bus zu nehmen.&lt;br /&gt;
&lt;br /&gt;
In sämtlichen Sleep-Modi (außer Idle Mode) ist der Systemtakt des TWI inaktiv. Dessen zu trotz kann das TWI durch setzen von TWEA allein mit Hilfe des Bustaktes erfassen, wenn es mit seiner Adresse bzw. durch einen general call angesprochen wird. Somit kann das TWI den Controller aufwecken. Während der Aufweck-Phase kann SCL auf L-Pegel gehalten werden wenn TWINT gelöscht ist (Schreiben einer &#039;1&#039;). Der Datenempfang kann wieder im Normalbetrieb stattfinden. Zu beachten ist, dass solange SCL auf L-Pegel ist keine anderen Transmissionen stattfinden können. Wichtig ist, dass TWDR nach dem Aufwecken nicht mehr das letzte Byte, welches auf dem Bus war, enthält.&lt;br /&gt;
&lt;br /&gt;
Eine Tabelle mit sämtlichen Status-Codes und den zugehörigen Ereignissen ist dem Datenblatt S.182 zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
=== Slave Transmitter Mode ===&lt;br /&gt;
&lt;br /&gt;
Im STM werden Daten an einen MR gesendet. Um den Controller im STM zu betreiben, müssen TWAR und TWCR wie folgt initialisiert werden.&lt;br /&gt;
&lt;br /&gt;
TWAR:&lt;br /&gt;
Die oberen 7 Bit stellen die Adress dar, an die das TWI antwortet, wenn es von einem Master angesprochen wird. Wenn das LSB (Least Significant Bit) in Form von TWGCE gesetzt ist, antwortet der Slave auch auf allgemeine Rufe (general calls), andernfalls natürlich nicht.&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWA6|TWA5|TWA4|TWA3|TWA2|TWA1|TWA0|TWGCE&lt;br /&gt;
 |Hier|steht|dann|die|Adresse|des|Slave!|X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
TWCR:&lt;br /&gt;
TWEN muss zum aktivieren des TWI gesetzt werden. TWEA muss gesetzt werden, damit der Slave antwortet, falls er von einem Master oder gegeben falls durch einen general call angesprochen wird. TWSTA und TWSTO müssen auf Null gesetzt werden.&lt;br /&gt;
&lt;br /&gt;
{{ByteWithValues|&lt;br /&gt;
 |TWINT|TWEA|TWSTA|TWSTO|TWWC|TWEN|&amp;amp;ndash;|TWIE&lt;br /&gt;
 |0    |1   |0    |0    |0   |1   |0      |X&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Nach der Initialisierung wartet das TWI auf eine Anfrage gefolgt von einem Datenrichtungsbit. Wird das TWI angesprochen wird TWINT gesetzt und TWSR beinhaltet den Statuscode. Mit seiner Hilfe kann das weitere Vorgehen festgelegt werden. Ein Controller kann auch in den STM gelangen, wenn er die Hoheit auf dem Bus an einen anderen Master verliert (0xB0). &lt;br /&gt;
&lt;br /&gt;
Wird TWEA während eines Transfers gesetzt, wird das aktuelle Byte noch fertig gesendet und Status 0xC0 oder 0xC8 tritt ein, je nachdem ob der Master ACK oder NACK nach dem letzten Byte gesendet hatte. Das TWI wird in einen Blockierzustand gehen, unabhängig davon, ob der Master den Transfer fortsetzt. So erhält der Master nur noch &#039;1&#039; auf dem seriellen Bus. Status 0xC8 tritt ein, wenn der Master weitere Daten fordert (durch Senden von ACK), obwohl der Slave bereits das letzte Byte gesendet hat (TWEA &#039;0&#039; und erwartet NACK).&lt;br /&gt;
&lt;br /&gt;
Trotz des Blockierzustandes wird der Bus weiter beobachtet und das TWI kann durch setzen von TWEA jederzeit wieder daran teilnehmen. Somit kann der Slave mit Hilfe von TWEA kurzzeitig vom Bus isoliert werden.&lt;br /&gt;
&lt;br /&gt;
In sämtlichen Sleep-Modi (außer Idle Mode) ist der Systemtakt des TWI inaktiv. Dessen zu trotz kann das TWI durch setzen von TWEA allein mit Hilfe des Bustaktes erfassen, wenn es mit seiner Adresse bzw. durch einen general call angesprochen wird. Somit kann das TWI den Controller aufwecken. Während der Aufweck-Phase kann SCL auf L-Pegel gehalten werden wenn TWINT gelöscht ist (Schreiben einer &#039;1&#039;). Der Datenversand kann wieder im Normalbetrieb stattfinden. Zu beachten ist, dass solange SCL auf L-Pegel ist keine anderen Transmissionen stattfinden können. Wichtig ist, dass TWDR nach dem Aufwecken nicht mehr das letzte Byte, welches auf dem Bus war, enthält.&lt;br /&gt;
&lt;br /&gt;
Eine Tabelle mit sämtlichen Status-Codes und den zugehörigen Ereignissen ist dem Datenblatt S.185 zu entnehmen.&lt;br /&gt;
&lt;br /&gt;
Zusätzlich zu den Betriebsart bezogenen Statuscodes gibt es noch zwei, welche davon unabhängig sind.&lt;br /&gt;
Status 0xF8 bedeutet, dass keine relevanten Informationen vorhanden sind, da TWINT nicht gesetzt ist. Dieser Fall tritt bei einem Statuswechsel ein oder wenn TWI im Moment nicht am Bus beteiligt ist.&lt;br /&gt;
&lt;br /&gt;
Status 0x00 steht für einen Busfehler während einer Übertragung. Ursache kann das Senden von START oder STOP zu einem nicht zulässigem Zeitpunkt sein. Bei solch einem Fehler wird TWINT automatisch gesetzt. Um die Fehlerroutine zu verlassen, muss TWSTO gesetzt und TWINT gelöscht werden. Dieses führt dazu, dass das TWI in den nicht adressierten Slave-Modus geht und SDA und SCL wieder freigegeben werden. Es wird kein STOP gesendet.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Wem das alles zuviel Theorie war und wer das I2C-Interface einmal im Einsatz erleben möchte, dem lege ich die Rubrik ICs &amp;amp; Co ans Herz. Dort wird die Verwendung eines I2C-EEPROMS demonstriert.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Weblinks ==&lt;br /&gt;
&lt;br /&gt;
=== Application notes ===&lt;br /&gt;
&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc2565.pdf AVR311: Using the TWI module as I2C slave]&lt;br /&gt;
&lt;br /&gt;
* [http://www.atmel.com/dyn/resources/prod_documents/doc2564.pdf AVR315: Using the TWI module as I2C master]&lt;br /&gt;
&lt;br /&gt;
=== Bibliotheken ===&lt;br /&gt;
&lt;br /&gt;
* [http://jump.to/fleury Peter Fleury&#039;s AVR I2C Library]&lt;br /&gt;
&lt;br /&gt;
* http://www.mikrocontroller.net/topic/87597&lt;br /&gt;
&lt;br /&gt;
* [http://www.jtronics.de/elektronik-avr/lib-i2ctwi-avr.html AVR TWI Slave]&lt;br /&gt;
&lt;br /&gt;
[[Category:AVR]] &lt;br /&gt;
[[Category:Mc-project.de]]&lt;br /&gt;
[[Category:I2C]]&lt;/div&gt;</summary>
		<author><name>Sebion7125</name></author>
	</entry>
</feed>