<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
		<id>https://rn-wissen.de/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Plaicy</id>
		<title>RN-Wissen.de - Benutzerbeiträge [de]</title>
		<link rel="self" type="application/atom+xml" href="https://rn-wissen.de/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Plaicy"/>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Spezial:Beitr%C3%A4ge/Plaicy"/>
		<updated>2026-04-11T22:57:57Z</updated>
		<subtitle>Benutzerbeiträge</subtitle>
		<generator>MediaWiki 1.25.1</generator>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Diskussion:Fallstricke_bei_der_C-Programmierung&amp;diff=12256</id>
		<title>Diskussion:Fallstricke bei der C-Programmierung</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Diskussion:Fallstricke_bei_der_C-Programmierung&amp;diff=12256"/>
				<updated>2007-06-12T15:08:25Z</updated>
		
		<summary type="html">&lt;p&gt;Plaicy: C89 immer noch nicht überall unterstüzt?&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===&amp;quot;TRUE ist nicht 1&amp;quot;===&lt;br /&gt;
In dem Abschnitt steht, dass man lieber folgendes schreiben soll.&lt;br /&gt;
 #define FALSE (0!=0)&lt;br /&gt;
 #define TRUE  (0==0)&lt;br /&gt;
&lt;br /&gt;
Was soll das bringen?  Danach ist FALSE 0 und und TRUE als 1 definiert, da laut ANSI-C (ANSI99 6.5.9) ''Each of the operators [&amp;quot;==&amp;quot; und &amp;quot;!=&amp;quot;] yields 1 if the specified relation is true and 0 if it is false.'''.  Siehe auch &lt;br /&gt;
http://www.dclc-faq.de/kap8.htm#8.2 .  Meine Meinung verwirrt die Aussage ''TRUE ist nicht 1'' nur.--[[Benutzer:Plaicy|Plaicy]] 22:43, 3. Jun 2007 (CEST)&lt;br /&gt;
&lt;br /&gt;
: Es gibt mehr als einen C-Standard. Manchmal ist es günstiger, TRUE als -1 zu definieren. Die Makros oben sind jedoch unabhängig davon, welcher Wert ein Compiler implementiert --[[Benutzer:SprinterSB|SprinterSB]] 23:36, 5. Jun 2007 (CEST)&lt;br /&gt;
::Nur aus Interesse: Welcher Compiler unterstüzt nicht C89, wo dies auch schon galt?  Außerdem schließe ich mich der Meinung von http://www.dclc-faq.de/kap8.htm#8.2 an, dass Vergleiche auf auf ''TRUE'' grundsätzlich ungünstig sind.  Wenn man unbedingt auf eine Konstante abfragen will, was eigentlich auch mit dem &amp;quot;!&amp;quot;-Operator übersichtlicher ist, kann man noch ''!= FALSE'' verwenden.--[[Benutzer:Plaicy|Plaicy]] 17:08, 12. Jun 2007 (CEST)&lt;/div&gt;</summary>
		<author><name>Plaicy</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Fallstricke_bei_der_C-Programmierung&amp;diff=12255</id>
		<title>Fallstricke bei der C-Programmierung</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Fallstricke_bei_der_C-Programmierung&amp;diff=12255"/>
				<updated>2007-06-12T15:01:45Z</updated>
		
		<summary type="html">&lt;p&gt;Plaicy: /* Zuweisung statt Vergleich */ Beschreibung mehr am Beispiel orientiert&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Tippfehler=&lt;br /&gt;
&lt;br /&gt;
Tippfehler können immer passieren. Besonders fies ist es, wenn der Tippfehler nicht zu einer Warnung oder zu einer Fehlermeldung führt, weil der entstandene Code korrekter C-Code ist.&lt;br /&gt;
&lt;br /&gt;
==Ein &amp;lt;tt&amp;gt;;&amp;lt;/tt&amp;gt; zu viel==&lt;br /&gt;
Ein reflexartig eingetippter oder nach Änderungen stehen gebliebener &amp;lt;tt&amp;gt;;&amp;lt;/tt&amp;gt; hat schon so manches &lt;br /&gt;
Programm ausgeknockt:&lt;br /&gt;
 if (a == 0);&lt;br /&gt;
 {&lt;br /&gt;
    /* mach was */&lt;br /&gt;
 }&lt;br /&gt;
Wenn &amp;lt;tt&amp;gt;a == 0&amp;lt;/tt&amp;gt; ist, dann wird &amp;lt;tt&amp;gt;;&amp;lt;/tt&amp;gt; ausgeführt (also im Endeffekt garnichts). Danach kommt der Block, der im &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; stehen sollte. Der wird immer ausgeführt, denn er gehört nicht mehr zum &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Zuweisung statt Vergleich==&lt;br /&gt;
 if (a = 0)&lt;br /&gt;
 {&lt;br /&gt;
    /* mach was */&lt;br /&gt;
 }&lt;br /&gt;
Bei einer if-Bedingung wird ob der Ausdruck innerhalb der Klammern ungleich &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;true&amp;lt;/true&amp;gt;) ist, dann wird die darauf folgende Anweisung bzw. Block ausgeführt.  In diesem Codebeispiel ist der Ausdruck eine Zuweisung.  Eine Zuweisung hat den Wert der zugewiesen wird, also hier &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;.  Damit wird bei diesem Code der Block zu der Bedingung nie ausgeführt.&lt;br /&gt;
&lt;br /&gt;
Abhilfe schafft, indem man sich angewöhnt zu schreiben&lt;br /&gt;
 if (0 == a)&lt;br /&gt;
Wenn man dann eine Zuweisung eintippt, gibt's einen Compiler-Fehler.&lt;br /&gt;
&lt;br /&gt;
==Signal/Interrupt-Name vertippt (avr-gcc)==&lt;br /&gt;
&lt;br /&gt;
 SIGNAL (SIG_OVEFRLOW0)&lt;br /&gt;
 {&lt;br /&gt;
    /* mach was */&lt;br /&gt;
 }&lt;br /&gt;
Nicht alle Compiler-Versionen meckern da. Der [[ISR]]-Code wird nicht in die Interrupt-Tabelle eingetragen. Kommt es zum [[Interrupt]], dann landet man in RESET.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Mangelnde C-Kenntnis=&lt;br /&gt;
&lt;br /&gt;
==Warnung ignoriert==&lt;br /&gt;
&lt;br /&gt;
::&amp;quot;''Wieso soll das Probleme machen? Das ist doch nur eine Warnung!''&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Warnungen zur Compile-Zeit werden gerne zu Fehlern zur Laufzeit. Letztere sind deutlich schwerer zu finden, als angewarnten Code zu korrigieren.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void foo (long*);&lt;br /&gt;
&lt;br /&gt;
void bar (int *p)&lt;br /&gt;
{&lt;br /&gt;
    foo (p+1); &lt;br /&gt;
    // Was soll das sein?!&lt;br /&gt;
    // ((long*) p) + 1       oder  &lt;br /&gt;
    // (long*) (p + 1)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; gcc -c -o prog.o prog.c&lt;br /&gt;
&lt;br /&gt;
prog.c: In function `bar':&lt;br /&gt;
prog.c:5: warning: passing arg 1 of `foo' from incompatible pointer type&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Array-Index==&lt;br /&gt;
&lt;br /&gt;
Informatiker am Bahnhof:&lt;br /&gt;
:''&amp;quot;0, 1, 2, ... Wo ist mein dritter Koffer?!&amp;quot;''&lt;br /&gt;
Gleiches gilt für Arrays:&lt;br /&gt;
 #define NUM 10;&lt;br /&gt;
 int a[NUM]; // für die N Werte a[0] ... a[N-1]&lt;br /&gt;
Ein Zugriff auf &amp;lt;tt&amp;gt;a[N]&amp;lt;/tt&amp;gt; greift irgendwo hin. &lt;br /&gt;
Wahlweise liest man Schrott oder überschreibt andere Daten, die in der Nähe liegen, und&lt;br /&gt;
plötzlich seltsame Werte enthalten.&lt;br /&gt;
&lt;br /&gt;
==Bitweise vs. Logische Operatoren==&lt;br /&gt;
&lt;br /&gt;
Die Operatoren AND, OR und NOT gibt es in C in zwei Ausprägungen&lt;br /&gt;
;bitweise: Die Operatoren &amp;lt;tt&amp;gt;^&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;|&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;&amp;amp;&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;~&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;|=&amp;lt;/tt&amp;gt;,  &amp;lt;tt&amp;gt;^=&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;&amp;amp;=&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;|=&amp;lt;/tt&amp;gt; operieren bitweise. Der entsprechende Operator wird also auf alle Bits des Wertes parallel angewandt und das Ergebnis für ein Bit ist unabhängig vom Inhalt der anderen Bits.&lt;br /&gt;
;logisch:  Die Operatoren &amp;lt;tt&amp;gt;||&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;&amp;amp;&amp;amp;&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;!&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;&amp;amp;&amp;amp;=&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;||=&amp;lt;/tt&amp;gt; operieren auf dem ganzen (int) Wert und berücksichtigen nur, ob der Wert 0 (false) oder ungleich 0 (true) ist.&lt;br /&gt;
Dementsprechend liefert &amp;lt;tt&amp;gt;&amp;amp;&amp;amp;&amp;lt;/tt&amp;gt; i.d.R. ein anderes Ergebnis als &amp;lt;tt&amp;gt;&amp;amp;&amp;lt;/tt&amp;gt;:&lt;br /&gt;
 if (a &amp;amp;&amp;amp; b) // erfüllt, wenn a!=0 und b!=0 &lt;br /&gt;
 if (a &amp;amp; b)  // erfüllt, wenn in a und b an der gleichen Stelle ein Bit gesetzt ist&lt;br /&gt;
Ein Verwechseln bzw. unkorrektes Einsetzen der Operatoren gibt also ein falsches Programm.&lt;br /&gt;
&lt;br /&gt;
==TRUE ist nicht 1==&lt;br /&gt;
&lt;br /&gt;
Da C die Begriffe TRUE und FALSE eigentlich nicht kennt, wurde schon öfter beobachtet, daß folgendes definiert wurde: &lt;br /&gt;
 #define TRUE 1&lt;br /&gt;
 #define FALSE 0&lt;br /&gt;
solange man damit nur Schalter setzt und abfragt, ist dagegen nichts zu sagen. &lt;br /&gt;
 a = TRUE; b = FALSE;&lt;br /&gt;
 if ( (a == TRUE) &amp;amp;&amp;amp; (b == FALSE)) {..&amp;quot;this is true&amp;quot;..} &lt;br /&gt;
wenn man aber dann schreibt&lt;br /&gt;
 if ( (a &amp;amp; b) == TRUE)  {..&amp;quot;this is true&amp;quot;..}&lt;br /&gt;
kann man einen herbe Enttäuschung erleben. Man müßte für ein richtiges Ergebnis schreiben&lt;br /&gt;
 if ( (a &amp;amp; b) != FALSE)  {..&amp;quot;this is true&amp;quot;..}&lt;br /&gt;
Damit ist aber eine gute Lesbarkeit endgültig dahin.&lt;br /&gt;
&lt;br /&gt;
Besser sind Definition wie&lt;br /&gt;
 #define FALSE (0!=0)&lt;br /&gt;
 #define TRUE  (0==0)&lt;br /&gt;
denn damit gilt einerseits, daß für alle boolschen Werte einschliesslich dieser Konstanten der&lt;br /&gt;
Zusammenhang &amp;lt;tt&amp;gt;x = !!x&amp;lt;/tt&amp;gt; besteht. &lt;br /&gt;
Mit der allerersten Definition hat man das unerwünschte Ergebnis &amp;lt;tt&amp;gt;TRUE != !FALSE&amp;lt;/tt&amp;gt;.&lt;br /&gt;
Andererseits kann man direkt gegen diese Konstanten vergleichen:&lt;br /&gt;
 a = (x &amp;lt; y);&lt;br /&gt;
 ...&lt;br /&gt;
 if (a == TRUE) // oder die 'klassische' Variante: if (a)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Siehe auch: http://www.dclc-faq.de/kap8.htm#8.2&lt;br /&gt;
&lt;br /&gt;
==Ein , anstatt . in Konstante==&lt;br /&gt;
&lt;br /&gt;
In C sowie im angloamerikanischen Sprachraum werden Dezimalbrüche mit einem &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; (Punkt) geschrieben und nicht wie im Deutschen mit einem &amp;lt;tt&amp;gt;,&amp;lt;/tt&amp;gt; (Komma): &lt;br /&gt;
 float pi;&lt;br /&gt;
 pi = 3,14;         // *AUTSCH* soll wohl heissen 3.14&lt;br /&gt;
Die zweite Zeile besteht aus zwei durch ein Komma getrennten Anweisungen, so daß das ganze&lt;br /&gt;
etwa gleichbedeutend ist mit&lt;br /&gt;
 float pi;&lt;br /&gt;
 pi = 3;&lt;br /&gt;
 14;&lt;br /&gt;
Jedenfalls ist es korrekter C-Code!&lt;br /&gt;
Die &amp;lt;tt&amp;gt;14;&amp;lt;/tt&amp;gt; ist ein Ausdruck, der nicht weiter gebraucht wird und daher wegfällt, da&lt;br /&gt;
er im Gegensatz zu einer void-Funktion keine Wirkung hat.&lt;br /&gt;
Man rechnet also mit dem Wert&amp;amp;nbsp;3 für &amp;lt;math&amp;gt;\pi&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Das falsche Komma hat auch schon so manchen ebay-Freak aufs Kreuz gelegt...&lt;br /&gt;
&lt;br /&gt;
==Führende 0 in Konstanten==&lt;br /&gt;
&lt;br /&gt;
In C kennzeichnet eine führende 0 bei einer Zahlenkonstante, &lt;br /&gt;
daß die Zahl oktal dargestellt ist. Somit ist 010 nicht gleich 10.&lt;br /&gt;
 if (a == 030) // ist a gleich 24?&lt;br /&gt;
&lt;br /&gt;
=Nicht-atomarer Code=&lt;br /&gt;
Verwendet man in einem Programm [[IRQ|IRQs]] ([[Interrupt|Interrupts]]) und ändert in der [[ISR]] (Service Routine) ein Datum (Variable, SFR, ...), dann wird diese Änderung möglicherweise überschrieben, wenn die IRQ zu einem ungünstigen Zeitpunkt auftritt. &lt;br /&gt;
&lt;br /&gt;
Ein ausführlicheres Beispiel, das zeigt, was passieren kann, findet sich im Artikel [[avr-gcc]] im Abschnitt &amp;quot;[[avr-gcc#Zugriff auf einzelne Bits|Zugriff auf einzelne Bits]]&amp;quot;. Ein weiteres Beispiel ist das Lesen, Schreiben oder Testen einer mehrbytigen Variable:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int volatile i;&lt;br /&gt;
   ...&lt;br /&gt;
   if (0 == i)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Weil &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; länger als 1 Byte ist, kann es je nach Architektur nicht in einem Befehl gelesen werden;&lt;br /&gt;
daher kann während des Lesens eine IRQ auftreten, in deren ISR der Wert von &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; möglicherweise &lt;br /&gt;
verändert wird. Der obige Code könnte etwa so assembliert werden (hier mit [[avr-gcc]]):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   ; i wird vom SRAM in das Registerpaar r24:r25 geladen&lt;br /&gt;
   ; low-Teil laden&lt;br /&gt;
   lds r24,i&lt;br /&gt;
   ; high-Teil laden&lt;br /&gt;
   ; wenn hier eine IRQ zuschlägt, in der i verändert wird, ist der Registerinhalt korrupt&lt;br /&gt;
   lds r25,(i)+1&lt;br /&gt;
   or r24,r25&lt;br /&gt;
   brne ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Natürlich können auch komplexere Datenstrukturen von diesem Phänomen betroffen sein.&lt;br /&gt;
Besonders unangenehm an dieser Klasse von Fehlern ist, daß sie nur sporadisch auftauchen&lt;br /&gt;
und man sie daher selbst mit einem guten Debugger sehr schlecht orten kann, da die zugehörige&lt;br /&gt;
Codestelle fast immer korrekt abgearbeitet wird.&lt;br /&gt;
&lt;br /&gt;
Eine Möglichkeit dem zu begegnen ist, den ganzen betroffenen Block ununterbrechbar (atomar) zu machen.&lt;br /&gt;
Wieder ein Beispiel für avr-gcc:&lt;br /&gt;
 #include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
 ...&lt;br /&gt;
    {{ccomment|ein lokale(!) Variable, die das Status-Register und }}&lt;br /&gt;
    {{ccomment|insbesondere das im folgenden geänderte I-Flag merkt }}&lt;br /&gt;
    {{ccomment|Falls man an der Codestelle immer weiß, daß IRQs }}&lt;br /&gt;
    {{ccomment|aktiviert sind, kann man die zu atomisierende Sequenz }}&lt;br /&gt;
    {{ccomment|auch in cli()...sei() einschachteln }}&lt;br /&gt;
    {{ccomment|Falls IRQs global deaktiviert sind brauch man natürlich }}&lt;br /&gt;
    {{ccomment|keine besonderen Vorkehrungen zu treffen, da dann aller Code }}&lt;br /&gt;
    {{ccomment|atomar ist. }}&lt;br /&gt;
    unsigned char sreg = SREG;&lt;br /&gt;
 &lt;br /&gt;
    {{ccomment|Interrupts global deaktivieren (I-Flag &amp;amp;#61; 0) }}&lt;br /&gt;
    cli();&lt;br /&gt;
 &lt;br /&gt;
    if (0 == i)&lt;br /&gt;
    {&lt;br /&gt;
        i = 1;&lt;br /&gt;
        {{ccomment|IRQs sobald als möglich wieder zulassen }}&lt;br /&gt;
        {{ccomment|(I-Flag wieder herstellen) }}&lt;br /&gt;
        SREG = sreg;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        {{ccomment|IRQs so bald als möglich wieder zulassen }}&lt;br /&gt;
        {{ccomment|(I-Flag wieder herstellen) }}&lt;br /&gt;
        SREG = sreg;&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
Oder je nach Programmstruktur sichert man den Wert, z.B. in eine lokale Variable oder deaktiviert nur selektiv die kritischen Interrupts, also solche, die Einfluss auf die kritischen Daten nehmen.&lt;br /&gt;
&lt;br /&gt;
= Weitere Fallstricke =&lt;br /&gt;
* [[Warteschleife]]&lt;br /&gt;
&lt;br /&gt;
= Siehe auch =&lt;br /&gt;
* [[C-Tutorial]]&lt;br /&gt;
* [[avr-gcc]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Grundlagen]]&lt;br /&gt;
[[Kategorie:Quellcode C|!]]&lt;br /&gt;
[[Kategorie:Software]]&lt;/div&gt;</summary>
		<author><name>Plaicy</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Kategorie_Diskussion:Projekte&amp;diff=12235</id>
		<title>Kategorie Diskussion:Projekte</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Kategorie_Diskussion:Projekte&amp;diff=12235"/>
				<updated>2007-06-04T13:05:17Z</updated>
		
		<summary type="html">&lt;p&gt;Plaicy: typos&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;wie krieg ich meinen Artikel &amp;quot;Lötstation&amp;quot; hier rein?&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
Es gibt eine eigene Kategorie, die du ganz ans Ende deines Artikels schreibst:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 [[Kategorie:Projekte]]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hilfe findest du auch im für Autoren lesenswerten Artikel [[RN-Wissen:Editierhilfe]] im vorletzten Abschnitt.&lt;br /&gt;
&lt;br /&gt;
--[[Benutzer:SprinterSB|SprinterSB]] 16:33, 2. Mär 2007 (CET)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:''SO macht die Veröfftlichung von Schaltungen mehr Nutzen, denn alles ist leicht kombinierbar erweiterbar.''&lt;br /&gt;
Da sind zwei typos drin: &amp;quot;SO&amp;quot; und &amp;quot;Veröfftlichung&amp;quot;--[[Benutzer:Plaicy|Plaicy]] 15:05, 4. Jun 2007 (CEST)&lt;/div&gt;</summary>
		<author><name>Plaicy</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Bootloader&amp;diff=12234</id>
		<title>Bootloader</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Bootloader&amp;diff=12234"/>
				<updated>2007-06-04T12:25:23Z</updated>
		
		<summary type="html">&lt;p&gt;Plaicy: typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Ein Boot-Loader ist eine spezielle Software, die gewöhnlich im Rom bzw. Flash sitzt oder vom Betriebsystem geladen und anschließend ausgeführt wird. Der Boot-Loader lädt dann weitere Teile des Betriebssystems (gewöhnlich einen Kernel) oder ein Hauptprogramm. &lt;br /&gt;
{|&lt;br /&gt;
 |valign=&amp;quot;top&amp;quot;|Die [[Atmel]] Controller ([[Avr|AVR]] [[ATMega8|Mega8]], [[Atmel Controller Mega16 und Mega32|Mega32]] usw.) besitzen einen reservierten Speicherbereich in welchen ein eigener Bootloader geladen werden kann. Dieser Bootloader kann automatisch bei einem RESET des Controllers ausgeführt werden, dies kann über die [[Fusebits]] eingestellt werden.&lt;br /&gt;
Mit den zwei Fusebits ''BOOTSZ'' (für Bootsize) kann die Grösse des Bootsektors eingestellt werden, gemessen wird immer vom oberen Speicherende nach unten. Je nach Grösse ändert sich auch der Startpunkt nach einem RESET falls das Fusebit ''BOOTRST'' ausgewählt wurde.&lt;br /&gt;
Um den Bootsektor sowie auch den Programmspeicher vor ungewolltem überschreiben zu schützen, sind vier ''Boot Loader Lock Bits'' (BLB) vorgesehen, diese können die jeweiligen Bereiche mit einem Schreib-/Leseschutz versehen. Diese Lock Bits verhindern aber nicht das auslesen oder neu beschreiben über [[ISP]].&lt;br /&gt;
&lt;br /&gt;
Die LockBits können entweder über ISP oder aber auch per Software direkt vom Programm aus gesetzt werden, zurücksetzen kann man sie aber nur durch einen sogenannten ''Chip Erase'', bei dem auch der ganze Speicher des AVR gelöscht wird.&lt;br /&gt;
 ||[[Bild:FlashBootsektor.png|thumb|Programmspeicher im AVR]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Oft wird dies genutzt, um einen Controller auch per [[RS232]], Infrarot oder Funk programmieren zu können. &lt;br /&gt;
&lt;br /&gt;
Für das AVR Board [[RN-Control]] findet man im Roboternetz-Downloadbereich einen geeigneten Bootloader.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
http://www.microsyl.com/megaload/megalo1.jpg&lt;br /&gt;
&lt;br /&gt;
Leider funktionierte oben genannter Bootloader im Test nicht mit den üblichen Funkmodulen. &lt;br /&gt;
Es gibt nun aber einen neuen Bootloader der offenbar recht gut auch die Programmierung per Funk erlaubt, siehe [[#Weblinks|Weblinks]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Weblinks==&lt;br /&gt;
* [http://www.microsyl.com AVR Bootloader]&lt;br /&gt;
* [http://www.roboternetz.de/phpBB2/dload.php?action=file&amp;amp;file_id=269 Funktioniert auch über Funk]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;br /&gt;
[[Kategorie:Software]]&lt;/div&gt;</summary>
		<author><name>Plaicy</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Diskussion:Avr-gcc_und_avrdude_installieren&amp;diff=12230</id>
		<title>Diskussion:Avr-gcc und avrdude installieren</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Diskussion:Avr-gcc_und_avrdude_installieren&amp;diff=12230"/>
				<updated>2007-06-03T23:39:21Z</updated>
		
		<summary type="html">&lt;p&gt;Plaicy: weitere Korrektur&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;super Tutorial!&lt;br /&gt;
ein paar kleinigkeiten im Makefile warn falsch, habs ausgebessert.&lt;br /&gt;
{{unsigned|Superdude|23:04, 3. Jun 2007 (CEST)}}&lt;br /&gt;
:Du meinst sicher bei der Abhängigkeit ''elf'' statt ''o'' bei dem ''hex''.   Andernfalls würden keine Module unterstützt werden und das ''elf''-Target wäre überflüssig.  Außerdem wüsste ich nicht, ob sichergestellt wird, dass der Linker aufgerufen wird, wenn man direkt aus einer ''o''-Datei eine ''hex''-Datei erstellt.---[[Benutzer:Plaicy|Plaicy]] 01:39, 4. Jun 2007 (CEST)&lt;/div&gt;</summary>
		<author><name>Plaicy</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Vorlage:Unsigned&amp;diff=12229</id>
		<title>Vorlage:Unsigned</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Vorlage:Unsigned&amp;diff=12229"/>
				<updated>2007-06-03T23:34:36Z</updated>
		
		<summary type="html">&lt;p&gt;Plaicy: erstellt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;includeonly&amp;gt;&amp;lt;small&amp;gt;(''Der vorstehende, nicht [[Hilfe:Signatur|signierte]] Beitrag stammt von'' [[Benutzer:{{{1}}}|{{{1}}}]] ([[Benutzer Diskussion:{{{1}}}|Diskussion]] • [[Spezial:Beiträge/{{{1}}}|Beiträge]]) {{{2|}}}) {{{3|}}}&amp;lt;/small&amp;gt;&amp;lt;/includeonly&amp;gt;&amp;lt;noinclude&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Siehe http://de.wikipedia.org/wiki/Vorlage_Diskussion:Unsigned#Vorlagendokumentation&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/noinclude&amp;gt;&lt;/div&gt;</summary>
		<author><name>Plaicy</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Avr-gcc_und_avrdude_installieren&amp;diff=12228</id>
		<title>Avr-gcc und avrdude installieren</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Avr-gcc_und_avrdude_installieren&amp;diff=12228"/>
				<updated>2007-06-03T23:28:35Z</updated>
		
		<summary type="html">&lt;p&gt;Plaicy: /* Beispiel-Projekt */ typo und $^ nach $&amp;lt; geändert: falls man mal mehr Abhängigkeiten einfach hinzufügt, klappt es sonst nicht mehr&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Es gibt bereits eine sehr gute Anleitung für das Installieren vom [[avr-gcc]], aber sie ist etwas veraltet. Für den original Text siehe [http://www.tldp.org/linuxfocus/English/November2004/article352.shtml].&lt;br /&gt;
Ich werde im folgenden nur das nötigste von diesem Artikel kopieren.&lt;br /&gt;
&lt;br /&gt;
Es gibt drei Teile. Im ersten Teil wird die Installation erklärt, im zweiten wird gezeigt, wie man damit denn nun seine Programme für den [[Microcontroller|MCU]] erstellt. Im dritten Teil stehen noch ein paar typische Fehlermeldungen und die Lösungen.&lt;br /&gt;
&lt;br /&gt;
=Installation=&lt;br /&gt;
&lt;br /&gt;
Also los. Wir brauchen folgende Software:&lt;br /&gt;
&lt;br /&gt;
* [ftp://ftp.gnu.org/gnu/binutils/ binutils-2.17.tar.bz2]&lt;br /&gt;
* [ftp://ftp.gnu.org/gnu/gcc/gcc-4.1.2/ gcc-core-4.1.2.tar.bz2] &lt;br /&gt;
* [http://savannah.nongnu.org/download/avr-libc/ avr-libc-1.4.5.tar.bz2]    Dort findet ihr auch das Manual der avr-libc&lt;br /&gt;
* [http://savannah.nongnu.org/download/avrdude/ avrdude-5.3.1.tar.gz]       &lt;br /&gt;
&lt;br /&gt;
Als erstes erstellen wir das Verzeichnis, in das der avr-gcc installiert wird:&lt;br /&gt;
&lt;br /&gt;
* Als root:&lt;br /&gt;
 mkdir /usr/local/avr&lt;br /&gt;
&lt;br /&gt;
Und das Verzeichnis in dem die Programme liegen werden:&lt;br /&gt;
&lt;br /&gt;
* Als root:&lt;br /&gt;
 mkdir /usr/local/avr/bin&lt;br /&gt;
&lt;br /&gt;
Dieses Verzeichnis wird auch gleich in die &amp;lt;tt&amp;gt;PATH&amp;lt;/tt&amp;gt;-Variable geschrieben:&lt;br /&gt;
 export PATH=$PATH:/usr/local/avr/bin&lt;br /&gt;
&lt;br /&gt;
Achtung, dieser Befehl ist nur in dieser eine Konsole in der ihr seid gültig und auch nur solange wie diese offen ist. Um die Änderung systemweit wirksam zu machen, müsst ihr in die Datei &amp;lt;tt&amp;gt;/etc/profile&amp;lt;/tt&amp;gt; den &amp;lt;tt&amp;gt;PATH&amp;lt;/tt&amp;gt; nachtragen. Bei mir sieht das z.B. so aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
# Set the default system $PATH:&lt;br /&gt;
PATH=&amp;quot;/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:/usr/games[b]:/usr/local/avr/bin[/b]&amp;quot;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==[[binutils]]==&lt;br /&gt;
&lt;br /&gt;
Mit den binutils bekommt ihr Programme wie z.b. &amp;lt;tt&amp;gt;avr-as&amp;lt;/tt&amp;gt; (Assembler), &amp;lt;tt&amp;gt;avr-ld&amp;lt;/tt&amp;gt; (Linker), &amp;lt;tt&amp;gt;avr-objcopy&amp;lt;/tt&amp;gt; (Um die Intel-Hex-Files zu erstellen).&lt;br /&gt;
&lt;br /&gt;
Und so wird's gemacht (Das entpacken kann eine Weile dauern):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tar jxf binutils-2.17.tar.bz2&lt;br /&gt;
cd binutils-2.17/&lt;br /&gt;
mkdir obj-avr&lt;br /&gt;
cd obj-avr&lt;br /&gt;
../configure --target=avr --prefix=/usr/local/avr --disable-nls&lt;br /&gt;
make&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Als root:&lt;br /&gt;
 make install&lt;br /&gt;
&lt;br /&gt;
==[[avr-gcc]]==&lt;br /&gt;
&lt;br /&gt;
avr-gcc ist unser eigentlicher Compiler. Er installiert sich wie folgt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tar jxf gcc-core-4.1.2.tar.bz2&lt;br /&gt;
cd gcc-4.1.2&lt;br /&gt;
&lt;br /&gt;
mkdir obj-avr&lt;br /&gt;
cd obj-avr&lt;br /&gt;
../configure --target=avr --prefix=/usr/local/avr --disable-nls --enable-languages=c --disable-libssp&lt;br /&gt;
&lt;br /&gt;
make&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hinweis: Falls ihr jetzt beim Installieren Fehler bekommt die sich z.B so äussern:&lt;br /&gt;
 make[2]: avr-ranlib: Command not found&lt;br /&gt;
Dann liegt &amp;lt;tt&amp;gt;/usr/local/avr/bin&amp;lt;/tt&amp;gt; wider erwarten nicht in &amp;lt;tt&amp;gt;PATH&amp;lt;/tt&amp;gt;. Führt diesen Befehl als root nochmal aus, dann sollte es gehen:&lt;br /&gt;
 export PATH=$PATH:/usr/local/avr/bin&lt;br /&gt;
&lt;br /&gt;
* Als root:&lt;br /&gt;
 make install&lt;br /&gt;
&lt;br /&gt;
==avr C-library ([[avr-libc]])==&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tar jxf avr-libc-1.4.5.tar.bz2&lt;br /&gt;
cd avr-libc-1.4.5&lt;br /&gt;
&lt;br /&gt;
./configure --prefix=/usr/local/avr --build=`./config.guess` --host=avr&lt;br /&gt;
&lt;br /&gt;
make &lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Als root:&lt;br /&gt;
 make install&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==[[avrdude]]==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
tar xzf avrdude-5.3.1.tar.gz&lt;br /&gt;
cd avrdude-5.3.1&lt;br /&gt;
./configure --prefix=/usr/local/avr&lt;br /&gt;
make&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Als root:&lt;br /&gt;
 make install&lt;br /&gt;
&lt;br /&gt;
Wer den avr910 Programmer benutzt, muss avrdude erst fit für einige neuere Controller machen.&lt;br /&gt;
([[ATtiny2313]], [[ATmega162]], ...). Dazu müsst ihr die Configdatei von avrdude anpassen. Ihr findet sie unter &amp;lt;tt&amp;gt;/usr/local/avr/etc/avrdude.conf&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Folgende Zeilen müssen ergänzt werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#------------------------------------------------------------&lt;br /&gt;
# ATtiny2313&lt;br /&gt;
#------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
part&lt;br /&gt;
     id            = &amp;quot;t2313&amp;quot;;&lt;br /&gt;
     desc          = &amp;quot;ATtiny2313&amp;quot;;&lt;br /&gt;
     stk500_devcode   = 0x23;&lt;br /&gt;
##  Try the STK500 devcode:&lt;br /&gt;
   [b]avr910_devcode   = 0x23;[/b]&lt;br /&gt;
.....&lt;br /&gt;
&lt;br /&gt;
#------------------------------------------------------------&lt;br /&gt;
# ATmega8535&lt;br /&gt;
#------------------------------------------------------------&lt;br /&gt;
&lt;br /&gt;
part&lt;br /&gt;
    id               = &amp;quot;m8535&amp;quot;;&lt;br /&gt;
    desc             = &amp;quot;ATMEGA8535&amp;quot;;&lt;br /&gt;
    stk500_devcode   = 0x64;&lt;br /&gt;
   [b] avr910_devcode   = 0x69;[/b]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Analog verfahren für [[ATmega64]], [[ATmega162]] und [[ATmega169]]. Die devicecodes hiefür sind:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
m64:     avr910_devcode   = 0x45;&lt;br /&gt;
m162:    avr910_devcode   = 0x62;&lt;br /&gt;
m169:    avr910_devcode   = 0x78;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wer sich einen eigenen avr910 Programmer bauen will, dem sei diese Seite ans Herz gelegt:&lt;br /&gt;
[http://www.klaus-leidinger.de/mp/Mikrocontroller/AVR-Prog/AVR-Programmer.html].&lt;br /&gt;
Ich habe die Version genommen und um ein Buffer erweitert. Die Bauanleitung dafür gibt es bald auf [http://www.amee-bot.de unserer Roboterseite]. &lt;br /&gt;
&lt;br /&gt;
Somit hätten wir nun alles was wir brauchen installiert.&lt;br /&gt;
&lt;br /&gt;
=Beispiel-Projekt=&lt;br /&gt;
&lt;br /&gt;
Hier erstmal ein winziges Beispielprogramm für den [[ATtiny2313]].&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/*&lt;br /&gt;
 *  blink.c&lt;br /&gt;
 *  ATtiny2313 mit 1 MHz&lt;br /&gt;
 *  PORTB wird ueber ein Timer alle 0.263s ein- und ausgeschaltet. Das entspricht 3.81Hz&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/signal.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
SIGNAL (SIG_TIMER0_OVF)&lt;br /&gt;
{&lt;br /&gt;
  PORTB =~ PORTB; // PORTB inventieren&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
int main()&lt;br /&gt;
{&lt;br /&gt;
  DDRB  = 0xFF; // PORTB als Ausgang schalten&lt;br /&gt;
  PORTB = 0x00; // Alle Ausgaenge auf 0 schalten&lt;br /&gt;
&lt;br /&gt;
  TCCR0B |= (1 &amp;lt;&amp;lt; CS02) | (1 &amp;lt;&amp;lt; CS00); //Prescaler auf 1024 stellen&lt;br /&gt;
  TIMSK  |= (1 &amp;lt;&amp;lt; TOIE0);              // Timer 0 Overflow Interrupt enable&lt;br /&gt;
&lt;br /&gt;
  sei(); // Interrupts einschalten&lt;br /&gt;
&lt;br /&gt;
  for(;;); //ever&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Den Quelltext nehmt ihr und speichert ihn in die Datei &amp;lt;tt&amp;gt;blink.c&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Jetzt kommt das [[make|Makefile]]. Ich habe schonmal ein einfaches vorbereitet:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
TARGET = blink&lt;br /&gt;
MCU    = attiny2313&lt;br /&gt;
CC     = avr-gcc&lt;br /&gt;
OBJCOPY=avr-objcopy&lt;br /&gt;
CFLAGS =-g -mmcu=$(MCU) -Wall -Wstrict-prototypes -Os -mcall-prologues -save-temps -fno-common&lt;br /&gt;
&lt;br /&gt;
all: $(TARGET).hex&lt;br /&gt;
&lt;br /&gt;
$(TARGET).hex : $(TARGET).elf&lt;br /&gt;
	$(OBJCOPY) -j .data -j .text -O ihex $&amp;lt; $@&lt;br /&gt;
&lt;br /&gt;
$(TARGET).elf: $(TARGET).o&lt;br /&gt;
	$(CC) $(CFLAGS) -o $@ -Wl,-Map,$(TARGET).map $&amp;lt;&lt;br /&gt;
&lt;br /&gt;
$(TARGET).o : $(TARGET).c&lt;br /&gt;
	$(CC) $(CFLAGS) -c $&amp;lt;&lt;br /&gt;
&lt;br /&gt;
load: $(TARGET).hex&lt;br /&gt;
	avrdude -p t2313 -c avr910 -U flash:w:$(TARGET).hex -v&lt;br /&gt;
&lt;br /&gt;
clean:&lt;br /&gt;
	rm -f *.o *.map *.elf *.hex *.s *.i&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Das speichert ihr in der Datei &amp;lt;tt&amp;gt;Makefile&amp;lt;/tt&amp;gt; im selben Ordner, in der auch die Datei &amp;lt;tt&amp;gt;blink.c liegt&amp;lt;/tt&amp;gt;. '''Unbedingt darauf achten, daß die Einrückungen durch TABs erfolgen und nicht durch Leerzeichen!'''&lt;br /&gt;
&lt;br /&gt;
Dann in der Konsole &amp;quot;&amp;lt;tt&amp;gt;[[make]]&amp;lt;/tt&amp;gt;&amp;quot; tippen und es sollte compiliert werden. Mit &amp;quot;&amp;lt;tt&amp;gt;make load&amp;lt;/tt&amp;gt;&amp;quot; wird das Hexfile dann in den MCU übertragen.&lt;br /&gt;
&lt;br /&gt;
'''Erklärung:'''&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;tt&amp;gt;MCU=attiny2313&amp;lt;/tt&amp;gt;: &amp;lt;tt&amp;gt;MCU&amp;lt;/tt&amp;gt; ist eine Variable mit dem Inhalt &amp;lt;tt&amp;gt;attiny2313&amp;lt;/tt&amp;gt;. Überall, wo jetzte &amp;lt;tt&amp;gt;$(MCU)&amp;lt;/tt&amp;gt; steht, wird der Variabelninhalt benutzt. Genauso funktioniert das auch mit &amp;lt;tt&amp;gt;TARGET&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;CC&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;OBJCOPY&amp;lt;/tt&amp;gt; und &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
Nachdem ihr &amp;lt;tt&amp;gt;make&amp;lt;/tt&amp;gt; erfolgreich ausgeführt habt, liegen in dem Ordner die Hexfile und eine Datei mit der Endung&amp;lt;tt&amp;gt;&amp;amp;nbsp;.s&amp;lt;/tt&amp;gt;. Darin sind die Assemblerbefehle und -direktiven, die der Compiler aus dem C-Code gemacht hat. Wer so etwas nicht braucht, der kann den Parameter &amp;lt;tt&amp;gt;-save-temps&amp;lt;/tt&amp;gt; in der Variable &amp;lt;tt&amp;gt;CFLAGS&amp;lt;/tt&amp;gt; getrost entfernen.&lt;br /&gt;
&lt;br /&gt;
Wenn ihr &amp;quot;&amp;lt;tt&amp;gt;make load&amp;lt;/tt&amp;gt;&amp;quot; ausfürt, wird avrdude gestarte.&lt;br /&gt;
;&amp;lt;tt&amp;gt;-p&amp;lt;/tt&amp;gt;: gibt an, um welchen MCU es sich handelt&lt;br /&gt;
;&amp;lt;tt&amp;gt;-c&amp;lt;/tt&amp;gt;: gibt an, um welchen Programmer es sich handelt. Hier könnte z.B &amp;lt;tt&amp;gt;stk500&amp;lt;/tt&amp;gt; stehen.&lt;br /&gt;
;&amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;-U flash:w:$(TARGET).hex&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt;: bedeutet einfach, dass das Programm in den Flash geschrieben werden soll. &amp;lt;tt&amp;gt;w&amp;lt;/tt&amp;gt; steht für Schreiben, &amp;lt;tt&amp;gt;r&amp;lt;/tt&amp;gt; für Lesen und &amp;lt;tt&amp;gt;v&amp;lt;/tt&amp;gt; für verify. Dann kommt die Variable &amp;lt;tt&amp;gt;$(TARGET)&amp;lt;/tt&amp;gt;, die besagt, welche Datei genau übertragen werden soll. &lt;br /&gt;
;&amp;lt;tt&amp;gt;-v&amp;lt;/tt&amp;gt;: bedeutet ''&amp;quot;Verbose Output&amp;quot;'' und gibt euch mehr Informationen auf der Konsole aus.&lt;br /&gt;
&lt;br /&gt;
Mit &amp;lt;tt&amp;gt;make clean&amp;lt;/tt&amp;gt; werden alle Object-Dateien etc. gelöscht.&lt;br /&gt;
&lt;br /&gt;
=Fehlermeldungen=&lt;br /&gt;
&lt;br /&gt;
sollten eigentlich keine vorkommen. Wenn doch, vergewissert euch, dass ihr euch genau an die&lt;br /&gt;
Anleitung gehalten und nichts falsch abgeschrieben habt!&lt;br /&gt;
&lt;br /&gt;
Hier ein paar typische Fehlermeldungen und ihr Lösungen:&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;tt&amp;gt;Permission denied&amp;lt;/tt&amp;gt;: Ihr habt nicht die Rechte, um diesen Befehl auszuführen. Höchswahrscheinlich müsst ihr den Befehl als root ausführen.&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;make[2]: avr-ranlib: Command not found&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt;:&amp;lt;tt&amp;gt;/usr/local/avr/bin&amp;lt;/tt&amp;gt; liegt nicht in &amp;lt;tt&amp;gt;$PATH&amp;lt;/tt&amp;gt;. Folgendes Command ausführen:&lt;br /&gt;
:&amp;lt;pre&amp;gt;export PATH=$PATH:/usr/local/avr/bin&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;tt&amp;gt;programmer is not responding&amp;lt;/tt&amp;gt;: Es kann keine Verbindung zum Programmer aufgenommen werden: Defektes Kabel, Programmer an der falschen Schnittstelle angeschlossen (default: &amp;lt;tt&amp;gt;/dev/ttyS0&amp;lt;/tt&amp;gt;), kein Strom am Programmer etc.&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;tt&amp;gt;&amp;lt;nowiki&amp;gt;can't open device &amp;quot;/dev/ttyS0&amp;quot;: Permission denied&amp;lt;/nowiki&amp;gt;&amp;lt;/tt&amp;gt;: Als normaler User darf man auf die serielle Schnittstelle nicht lesen oder schreiben. Folgenden Befehl als root ausführen:&lt;br /&gt;
:&amp;lt;pre&amp;gt;chmod 666 /dev/ttyS0&amp;lt;/pre&amp;gt;&lt;br /&gt;
:{|&lt;br /&gt;
Zweite und bessere Möglichkeit, die Rechte zu ändern ist es, den Benutzer in die tty-Gruppe auzunehmen.&lt;br /&gt;
Hier ein Beispiel für Gentoo.&lt;br /&gt;
Die Gruppe kann bei anderen Distributionen auch anders heißen!&lt;br /&gt;
&lt;br /&gt;
Als root in die Konsole schreiben:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; ls -all /dev/ttyS0&lt;br /&gt;
crw-rw---- 1 root tty 4, 64 25. Jun 02:12 /dev/ttyS0&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Hier kann man schön erkennen, daß die serielle Schnittstelle dem Benutzer root gehört und die Gruppe &amp;lt;tt&amp;gt;tty&amp;lt;/tt&amp;gt; darauf zugreifen darf. Mit einem einfachen&lt;br /&gt;
 &amp;gt; usermod -a -G tty sebastian&lt;br /&gt;
wird der User &amp;lt;tt&amp;gt;sebastian&amp;lt;/tt&amp;gt; in die tty-Gruppe aufgenommen.&lt;br /&gt;
&lt;br /&gt;
Noch ein Test, ob alles geklappt hat:&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;gt; groups sebastian&lt;br /&gt;
tty wheel audio cdrom dialout video games usb users portage scanner&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Danach muss sich Benutzer &amp;lt;tt&amp;gt;sebastian&amp;lt;/tt&amp;gt; neu einlogen und wir sind fertig.&lt;br /&gt;
&lt;br /&gt;
Der Vorteil hierbei ist, daß man Rechte für alle Geräte der Gruppe &amp;lt;tt&amp;gt;tty&amp;lt;/tt&amp;gt; erlangt, also alle seriellen Schnittstellen sowie [[USB]]&amp;amp;nbsp;&amp;amp;harr;&amp;amp;nbsp;[[RS232]]-Adapter, und man braucht an den eigentlichen Rechten nichts zu verändern.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Web-Links=&lt;br /&gt;
*[http://www.nongnu.org/avr-libc/user-manual/install_tools.html ''&amp;quot;Installing the GNU Tool Chain&amp;quot;''] Hilfe zum Build und Installation von GCC, binutils, etc unter Linux&lt;br /&gt;
* [http://www.linuxfocus.org/Deutsch/November2004/article352.shtml www.linuxfocus.org (Artikel)] - Tipps zu Build und Installation von avr-gcc, binutils und avr-libc unter Linux&lt;br /&gt;
* [http://users.rcn.com/rneswold/avr/ Rich Neswold: ''A GNU Development Environment for the AVR Microcontroller'']&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/24166 www.mikrocontroller.net (Foren-Beitrag)] - Installation von GCC und Toolchain unter Mac OS X&lt;br /&gt;
&lt;br /&gt;
=Siehe auch=&lt;br /&gt;
* [[avr-gcc]]&lt;br /&gt;
* [[WinAVR]]&lt;br /&gt;
&lt;br /&gt;
=Quelle=&lt;br /&gt;
* [http://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=125603#125603 www.roboternetz.de (Foren-Beitrag)] ''avrgcc + avrdude installieren''&lt;br /&gt;
&lt;br /&gt;
=Autoren=&lt;br /&gt;
*[[Benutzer:Kater|Kater]] (Manuscript)&lt;br /&gt;
*[[Benutzer:SprinterSB|SprinterSB]] (Transcript und Typo)&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Grundlagen]]&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;br /&gt;
[[Kategorie:Quellcode C]]&lt;/div&gt;</summary>
		<author><name>Plaicy</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Benutzer:Plaicy&amp;diff=12225</id>
		<title>Benutzer:Plaicy</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Benutzer:Plaicy&amp;diff=12225"/>
				<updated>2007-06-03T21:28:17Z</updated>
		
		<summary type="html">&lt;p&gt;Plaicy: erstellt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Siehe [http://de.wikipedia.org/wiki/Benutzer:Plaicy Meine Seite bei der Wikipedia]&lt;/div&gt;</summary>
		<author><name>Plaicy</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Hallo_Welt_f%C3%BCr_AVR_(LED_blinken)&amp;diff=12224</id>
		<title>Hallo Welt für AVR (LED blinken)</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Hallo_Welt_f%C3%BCr_AVR_(LED_blinken)&amp;diff=12224"/>
				<updated>2007-06-03T21:23:03Z</updated>
		
		<summary type="html">&lt;p&gt;Plaicy: /* Von der C-Quelle zum hex-File */ typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Das erste C-Programm, das man zu sehen bekommt, ist für die meisten das &amp;quot;Hallo Welt&amp;quot;.&lt;br /&gt;
Bei &amp;quot;Hallo Welt&amp;quot; geht es weniger um die Funktionalität an sich, sondern darum zu lernen,&lt;br /&gt;
wie man überhaupt ein Programm übersetzt und einen Compiler verwendet.&lt;br /&gt;
&lt;br /&gt;
Was für den PC das &amp;quot;Hallo Welt&amp;quot;, ist für einen kleinen Microcontroller der &amp;quot;Hallo Blinky&amp;quot;,&lt;br /&gt;
der einfach nur eine [[Diode|Leuchtdiode]] (LED) blinken lässt.&lt;br /&gt;
&lt;br /&gt;
Im Vergleich zu &amp;quot;Hallo Welt&amp;quot; sieht der Blinky viel komplizierter aus, &lt;br /&gt;
aber eigentlich ist er einfacher, dann es werden keine umfangreichen Funktionen oder&lt;br /&gt;
Black-Boxen benutzt wie etwa &amp;lt;tt&amp;gt;printf()&amp;lt;/tt&amp;gt;. &lt;br /&gt;
Ausser dem eingegebenen Quellcode kommt also kein anderer Code zur Ausführung!&lt;br /&gt;
&lt;br /&gt;
{{FarbigerRahmen|&lt;br /&gt;
Bitte beachte auch die Hinweise zu [[avr-gcc#Inkompatibilität|Inkompatibilitäten von avr-gcc]]!&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=Beschreibung=&lt;br /&gt;
&lt;br /&gt;
Eine [[LED]] an Port B1 wird einmal pro Sekunde an bzw. ausgeschaltet. Die LED blinkt also mit einer Frequenz von 1/2 Hz.&lt;br /&gt;
&lt;br /&gt;
Im Programm wird der Wert für das OCR1A-Register aus der Taktfrequenz des&lt;br /&gt;
Controllers (&amp;lt;tt&amp;gt;F_CPU&amp;lt;/tt&amp;gt;) und der Anzahl an Interrupts, die pro Sekunde&lt;br /&gt;
ausgelöst werden sollen (&amp;lt;tt&amp;gt;IRQS_PER_SECOND&amp;lt;/tt&amp;gt;), berechnet.&lt;br /&gt;
&lt;br /&gt;
Standardmässig sind [[AVR|AVRs]] mit dem internen RC-Oszillator mit ca. 1&amp;amp;nbsp;MHz getaktet.&lt;br /&gt;
Daher wird &amp;lt;tt&amp;gt;F_CPU&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;blinky.c&amp;lt;/tt&amp;gt; zu 1000000 definiert:&lt;br /&gt;
 #define F_CPU 1000000&lt;br /&gt;
{{FarbigerRahmen|&lt;br /&gt;
Dieser Wert hat rein informativen Charakter und bewirkt ''nicht'', daß der Controller mit einer anderen Frequenz läuft! Das geht über einen anderen Quarz/Oszillator oder andere Fuse-Einstellungen.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Das Programm ist ausgelegt für eine Taktrate von 1&amp;amp;nbsp;MHz. Wenn dein [[Controller]] mit einem anderen Takt läuft, dann hast du zwei Möglichkeiten:&lt;br /&gt;
* Du lässt das Programm so, wie es ist. Dann blinkt die LED entsprechend schneller bzw. langsamer. Hast du deinen AVR zB mit 16&amp;amp;nbsp;MHz getaktet, dann blinkt die LED mit 8&amp;amp;nbsp;Hz.&lt;br /&gt;
* Du passt die Taktfrequenz in der Quelle oder per Kommandozeile an. Für 8 MHz:&lt;br /&gt;
:&amp;lt;pre&amp;gt; &amp;gt; avr-gcc ... -DF_CPU=8000000&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Quellcode=&lt;br /&gt;
Der Quellcode ist für die Version 3.x von [[avr-gcc]]. In der 4er-Version gab es tiefgreifende interne Änderungen im Compiler; er ist noch instabil und kann momentan noch nicht für den Produktiv-Einsatz empfohlen werden (Stand 02/2005).&lt;br /&gt;
 #include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment|Für alte avr-gcc Versionen}}&lt;br /&gt;
 #ifndef SIGNAL&lt;br /&gt;
 #include &amp;lt;avr/signal.h&amp;gt;&lt;br /&gt;
 #endif {{ccomment|SIGNAL}}&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment|Geblinkt wird PortB.1 (push-pull)}}&lt;br /&gt;
 {{ccomment|Eine LED in Reihe mit einem Vorwiderstand zwischen}}&lt;br /&gt;
 {{ccomment|PortB.1 und GND anschliessen.}}&lt;br /&gt;
 #define PAD_LED  1&lt;br /&gt;
 #define PORT_LED PORTB&lt;br /&gt;
 #define DDR_LED  DDRB&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment|Der MCU-Takt. Wird gebraucht, um Timer1 mit den richtigen}}&lt;br /&gt;
 {{ccomment|Werten zu initialisieren. Voreinstellung ist 1MHz.}}&lt;br /&gt;
 {{ccomment|(Werkseinstellung für AVRs mit internem Oszillator).}}&lt;br /&gt;
 {{ccomment|Das Define wird nur gemacht, wenn F_CPU noch nicht definiert wurde.}}&lt;br /&gt;
 {{ccomment|F_CPU kann man so auch per Kommandozeile definieren, z.B. für 8MHz:}}&lt;br /&gt;
 {{ccomment|avr-gcc ... -DF_CPU&amp;amp;#61;8000000}}&lt;br /&gt;
 {{ccomment| &amp;amp;nbsp;}}&lt;br /&gt;
 {{ccomment|! Der Wert von F_CPU hat rein informativen Character für}}&lt;br /&gt;
 {{ccomment|! die korrekte Codeerzeugung im Programm!}}&lt;br /&gt;
 {{ccomment|! Um die Taktrate zu ändern müssen die Fuses des Controllers}}&lt;br /&gt;
 {{ccomment|! und/oder Quarz/Resonator/RC-Glied/Oszillator}}&lt;br /&gt;
 {{ccomment|! angepasst werden!}}&lt;br /&gt;
 #ifndef F_CPU&lt;br /&gt;
 #define F_CPU    1000000&lt;br /&gt;
 #endif&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment|So viele IRQs werden jede Sekunde ausgelöst.}}&lt;br /&gt;
 {{ccomment|Für optimale Genauigkeit muss}}&lt;br /&gt;
 {{ccomment|IRQS_PER_SECOND ein Teiler von F_CPU sein}}&lt;br /&gt;
 {{ccomment|und IRQS_PER_SECOND ein Vielfaches von 100.}}&lt;br /&gt;
 {{ccomment|Ausserdem muss gelten F_CPU / IRQS_PER_SECOND &amp;lt;&amp;amp;#61; 65536}}&lt;br /&gt;
 #define IRQS_PER_SECOND   2000 {{comment|500 µs}}&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment|Anzahl IRQs pro 10 Millisekunden}}&lt;br /&gt;
 #define IRQS_PER_10MS     (IRQS_PER_SECOND / 100)&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment|Gültigkeitsprüfung.}}&lt;br /&gt;
 {{ccomment|Bei ungeeigneten Werten gibt es einen Compilerfehler}}&lt;br /&gt;
 #if (F_CPU/IRQS_PER_SECOND &amp;gt; 65536) || (IRQS_PER_10MS &amp;lt; 1) || (IRQS_PER_10MS &amp;gt; 255)&lt;br /&gt;
 #   error Diese Werte fuer F_CPU und IRQS_PER_SECOND&lt;br /&gt;
 #   error sind ausserhalb des gueltigen Bereichs!&lt;br /&gt;
 #endif&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment|Compiler-Warnung falls die Genauigkeit nicht optimal ist.}}&lt;br /&gt;
 {{ccomment|Wenn das nervt für deine Werte, einfach löschen :-)}}&lt;br /&gt;
 #if (F_CPU % IRQS_PER_SECOND != 0) || (IRQS_PER_SECOND % 100 != 0)&lt;br /&gt;
 #   warning Das Programm arbeitet nicht mit optimaler Genauigkeit.&lt;br /&gt;
 #endif&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment|Prototypen}}&lt;br /&gt;
 void wait_10ms (const uint8_t);&lt;br /&gt;
 void timer1_init();&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment|Zähler-Variable. Wird in der ISR erniedrigt und in wait_10ms benutzt.}}&lt;br /&gt;
 static volatile uint8_t timer_10ms;&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment|//////////////////////////////////////////////////////////////////////}}&lt;br /&gt;
 {{ccomment|Implementierungen der Funktionen}}&lt;br /&gt;
 {{ccomment|//////////////////////////////////////////////////////////////////////}}&lt;br /&gt;
 &lt;br /&gt;
 #if !defined (TCNT1H)&lt;br /&gt;
 #error Dieser Controller hat keinen 16-Bit Timer1!&lt;br /&gt;
 #endif {{ccomment|TCNT1H}}&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment|//////////////////////////////////////////////////////////////////////}}&lt;br /&gt;
 {{ccomment|Timer1 so initialisieren, daß er IRQS_PER_SECOND }}&lt;br /&gt;
 {{ccomment|IRQs pro Sekunde erzeugt.}}&lt;br /&gt;
 void timer1_init()&lt;br /&gt;
 {&lt;br /&gt;
     {{ccomment|Timer1: keine PWM}}&lt;br /&gt;
     TCCR1A = 0;&lt;br /&gt;
 &lt;br /&gt;
     {{ccomment|Timer1 ist Zähler: Clear Timer on Compare Match (CTC, Mode #4)}}&lt;br /&gt;
     {{ccomment|Timer1 läuft mit vollem MCU-Takt: Prescale &amp;amp;#61; 1}}&lt;br /&gt;
 #if defined (CTC1) &amp;amp;&amp;amp; !defined (WGM12)&lt;br /&gt;
    TCCR1B = (1 &amp;lt;&amp;lt; CTC1)  | (1 &amp;lt;&amp;lt; CS10);&lt;br /&gt;
 #elif !defined (CTC1) &amp;amp;&amp;amp; defined (WGM12)&lt;br /&gt;
    TCCR1B = (1 &amp;lt;&amp;lt; WGM12) | (1 &amp;lt;&amp;lt; CS10);&lt;br /&gt;
 #else&lt;br /&gt;
 #error Keine Ahnung, wie Timer1 fuer diesen AVR zu initialisieren ist!&lt;br /&gt;
 #endif&lt;br /&gt;
 &lt;br /&gt;
     {{ccomment|OutputCompare für gewünschte Timer1 Frequenz}}&lt;br /&gt;
     {{ccomment|TCNT1 zählt immer 0...OCR1A, 0...OCR1A, ... }}&lt;br /&gt;
     {{ccomment|Beim überlauf OCR1A -&amp;gt; OCR1A+1 wird TCNT1&amp;amp;#61;0 gesetzt und im nächsten}}&lt;br /&gt;
     {{ccomment|MCU-Takt eine IRQ erzeugt.}}&lt;br /&gt;
     OCR1A = (unsigned short) ((unsigned long) F_CPU / IRQS_PER_SECOND-1);&lt;br /&gt;
 &lt;br /&gt;
     {{ccomment|OutputCompareA-Interrupt für Timer1 aktivieren}}&lt;br /&gt;
 #if defined (TIMSK1)&lt;br /&gt;
     TIMSK1 |= (1 &amp;lt;&amp;lt; OCIE1A);&lt;br /&gt;
 #elif defined (TIMSK)&lt;br /&gt;
     TIMSK  |= (1 &amp;lt;&amp;lt; OCIE1A);&lt;br /&gt;
 #else	 &lt;br /&gt;
 #error Keine Ahnung, wie IRQs fuer diesen AVR zu initialisieren sind!&lt;br /&gt;
 #endif&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment|//////////////////////////////////////////////////////////////////////}}&lt;br /&gt;
 {{ccomment|Wartet etwa t*10 ms. }}&lt;br /&gt;
 {{ccomment|timer_10ms wird alle 10ms in der Timer1-ISR erniedrigt. }}&lt;br /&gt;
 {{ccomment|Weil es bis zum nächsten IRQ nicht länger als 10ms dauert,}}&lt;br /&gt;
 {{ccomment|wartet diese Funktion zwischen (t-1)*10 ms und t*10 ms.}}&lt;br /&gt;
 void wait_10ms (const uint8_t t)&lt;br /&gt;
 {&lt;br /&gt;
     timer_10ms = t;&lt;br /&gt;
     while (timer_10ms);&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment|//////////////////////////////////////////////////////////////////////}}&lt;br /&gt;
 {{ccomment|Die Interrupt Service Routine (ISR).}}&lt;br /&gt;
 {{ccomment|In interrupt_num_10ms werden die IRQs gezählt.}}&lt;br /&gt;
 {{ccomment|Sind IRQS_PER_10MS Interrups geschehen, }}&lt;br /&gt;
 {{ccomment|dann sind 10 ms vergangen.}}&lt;br /&gt;
 {{ccomment|timer_10ms wird alle 10 ms um 1 vermindert und bleibt bei 0 stehen.}}&lt;br /&gt;
 SIGNAL (SIG_OUTPUT_COMPARE1A)&lt;br /&gt;
 {&lt;br /&gt;
     static uint8_t interrupt_num_10ms;&lt;br /&gt;
 &lt;br /&gt;
     {{ccomment|interrupt_num_10ms erhöhen und mit Maximalwert vergleichen}}&lt;br /&gt;
     if (++interrupt_num_10ms == IRQS_PER_10MS)&lt;br /&gt;
     {&lt;br /&gt;
         {{ccomment|10 Millisekunden sind vorbei}}&lt;br /&gt;
         {{ccomment|interrupt_num_10ms zurücksetzen}}&lt;br /&gt;
         interrupt_num_10ms = 0;&lt;br /&gt;
 &lt;br /&gt;
         {{ccomment|Alle 10ms wird timer_10ms erniedrigt, falls es nicht schon 0 ist.}}&lt;br /&gt;
         {{ccomment|Wird verwendet in wait_10ms}}&lt;br /&gt;
         if (timer_10ms != 0)&lt;br /&gt;
             timer_10ms--;&lt;br /&gt;
     }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment|//////////////////////////////////////////////////////////////////////}}&lt;br /&gt;
 {{ccomment|Das Hauptprogramm: Startpunkt }}&lt;br /&gt;
 int main()&lt;br /&gt;
 {&lt;br /&gt;
     {{ccomment|LED-Port auf OUT}}&lt;br /&gt;
     DDR_LED  |= (1 &amp;lt;&amp;lt; PAD_LED);&lt;br /&gt;
 &lt;br /&gt;
     {{ccomment|Timer1 initialisieren}}&lt;br /&gt;
     timer1_init();&lt;br /&gt;
 &lt;br /&gt;
     {{ccomment|Interrupts aktivieren}}&lt;br /&gt;
     sei();&lt;br /&gt;
 &lt;br /&gt;
     {{ccomment|Endlosschleife}}&lt;br /&gt;
     {{ccomment|Die LED ist jeweils 1 Sekunde an und 1 Sekunde aus,}}&lt;br /&gt;
     {{ccomment|blinkt also mit einer Frequenz von 0.5 Hz}}&lt;br /&gt;
     while (1)&lt;br /&gt;
     {&lt;br /&gt;
         {{ccomment|LED an}}&lt;br /&gt;
         PORT_LED |= (1 &amp;lt;&amp;lt; PAD_LED);&lt;br /&gt;
 &lt;br /&gt;
         {{ccomment|1 Sekunde warten}}&lt;br /&gt;
         wait_10ms (100);&lt;br /&gt;
 &lt;br /&gt;
         {{ccomment|LED aus}}&lt;br /&gt;
         PORT_LED &amp;amp;= ~(1 &amp;lt;&amp;lt; PAD_LED);&lt;br /&gt;
 &lt;br /&gt;
         {{ccomment|1 Sekunde warten}}&lt;br /&gt;
         wait_10ms (100);&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     {{ccomment|main braucht keine return-Anweisung, weil wir nie hier hin kommen}}&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
=Von der C-Quelle zum hex-File=&lt;br /&gt;
&lt;br /&gt;
Das Übersetzen über Kommandozeilen-Eingaben erledigen und ''nicht''&lt;br /&gt;
über Werkzeuge wie [[make]], &lt;br /&gt;
das die Zusammenhänge eher verschleiert als erhellt,&lt;br /&gt;
und dessen inkorrekte Anwendung eine häufige Fehlerquelle ist.&lt;br /&gt;
&lt;br /&gt;
Nach Speichern der Quelldatein in ein eigenes Verzeichnis enthält dieses die Datei&lt;br /&gt;
 blinky.c&lt;br /&gt;
&lt;br /&gt;
==Compilieren==&lt;br /&gt;
&lt;br /&gt;
Zunächst wird die C-Dateie übersetzt. &lt;br /&gt;
Der Übersetzungsvorgang wird gesteuert durch Kommandozeilen-Parameter (siehe [[avr-gcc]]).&lt;br /&gt;
Die Option &lt;br /&gt;
;&amp;lt;tt&amp;gt;-c&amp;lt;/tt&amp;gt;: legt fest, daß nur compiliert wird (und nicht gelinkt), &lt;br /&gt;
;&amp;lt;tt&amp;gt;-o name&amp;lt;/tt&amp;gt;: gibt den Name der Ausgabedatei an. Ohne diese Option heisst die Ausgabedatei immer &amp;lt;tt&amp;gt;a.out&amp;lt;/tt&amp;gt;&lt;br /&gt;
;&amp;lt;tt&amp;gt;-mmcu=atmega8&amp;lt;/tt&amp;gt;: legt den Controllertyp fest, in dem Beispiel den [[ATmega8]]&lt;br /&gt;
;&amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt;: erzeugt Debug-Infos und&lt;br /&gt;
;&amp;lt;tt&amp;gt;-Os&amp;lt;/tt&amp;gt;: optimiert auf Codegröße.&lt;br /&gt;
;&amp;lt;tt&amp;gt;-DF_CPU=xxx&amp;lt;/tt&amp;gt;: optional, falls der Controller nicht mit 1 MHz läuft. &amp;lt;tt&amp;gt;xxx&amp;lt;/tt&amp;gt; ist die Taktfrequenz in Hertz.&lt;br /&gt;
 &amp;gt; avr-gcc blinky.c -c -o blinky.o -Os -g -mmcu=atmega8&lt;br /&gt;
Danach ist eine neue Datei entstanden (*.o)&lt;br /&gt;
 blinky.c blinky.o&lt;br /&gt;
&lt;br /&gt;
==Linken==&lt;br /&gt;
Die erzeugte Objek-Datei wird nun zur Ausgabedatei (*.elf) gelinkt:&lt;br /&gt;
 &amp;gt; avr-gcc blinky.o -o blinky.elf -mmcu=atmega8&lt;br /&gt;
erzeugt die ausführbare Datei (*.elf), die noch zusätzliche Informationen wie&lt;br /&gt;
Debug-Infos etc. beinhaltet mit dem Namen &amp;lt;tt&amp;gt;blinky.elf&amp;lt;/tt&amp;gt;:&lt;br /&gt;
 blinky.c blinky.elf blinky.o&lt;br /&gt;
&lt;br /&gt;
==Umwandeln nach hex==&lt;br /&gt;
&lt;br /&gt;
===Code und Daten===&lt;br /&gt;
Viele Progger wollen die zu ladende Datei im Intel-hex-Format (*.hex bzw. *.ihex).&lt;br /&gt;
Dazu gibt man an&lt;br /&gt;
 &amp;gt; avr-objcopy -j .text -j .data -O ihex blinky.elf blinky.hex&lt;br /&gt;
Damit enthält die hex-Datei die Sections &amp;lt;tt&amp;gt;.text&amp;lt;/tt&amp;gt; (Programm) und &amp;lt;tt&amp;gt;.data&amp;lt;/tt&amp;gt; (Daten).&lt;br /&gt;
Das Verzeichnis beinhaltet jetzt&lt;br /&gt;
 blinky.c blinky.elf blinky.hex blinky.o&lt;br /&gt;
&lt;br /&gt;
===EEPROM===&lt;br /&gt;
Ein hex-File, das den Inhalt des EEPROMs wiederspiegelt, erhält man mit&lt;br /&gt;
 &amp;gt; avr-objcopy -j .eeprom --change-section-lma .eeprom=0 -O ihex blinky.elf blinky_eeprom.hex&lt;br /&gt;
Für das Beispiel ist das EEPROM-File &amp;lt;tt&amp;gt;blinky_eeprom.hex&amp;lt;/tt&amp;gt; leer, &lt;br /&gt;
da wir keine Daten ins EEPROM gelegt haben.&lt;br /&gt;
&lt;br /&gt;
==Listfile erstellen==&lt;br /&gt;
&lt;br /&gt;
Falls man ein Listfile haben möchte, dann geht das mit&lt;br /&gt;
 &amp;gt; avr-objdump -h -S -j .text -j .data blinky.elf &amp;gt; blinky.lst&lt;br /&gt;
Das Listfile ist eine Textdatei, die alle Assembler-Befehle auflistet,&lt;br /&gt;
wie sie letztendlich auf den Controller geladen werden.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;avr-objdump&amp;lt;/tt&amp;gt; gibt seine Ausgabe auf das Terminal aus. &lt;br /&gt;
Diese Ausgabe wird mit '&amp;lt;tt&amp;gt;&amp;amp;gt;&amp;lt;/tt&amp;gt;' in die Datei &amp;lt;tt&amp;gt;blinky.lst&amp;lt;/tt&amp;gt; umgeleitet.&lt;br /&gt;
Hier ein Ausschnitt aus dem Listfile:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
00000072 &amp;lt;wait_10ms&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
// //////////////////////////////////////////////////////////////////////&lt;br /&gt;
// Wartet etwa t*10 ms.&lt;br /&gt;
// timer_10ms wird alle 10ms in der Timer1-ISR erniedrigt.&lt;br /&gt;
// Weil es bis zum nächsten IRQ nicht länger als 10ms dauert,&lt;br /&gt;
// wartet diese Funktion zwischen (t-1)*10 ms und t*10 ms.&lt;br /&gt;
void wait_10ms (const uint8_t t)&lt;br /&gt;
{&lt;br /&gt;
    timer_10ms = t;&lt;br /&gt;
  72:	80 93 61 00 	sts	0x0061, r24&lt;br /&gt;
    while (timer_10ms);&lt;br /&gt;
  76:	80 91 61 00 	lds	r24, 0x0061&lt;br /&gt;
  7a:	88 23       	and	r24, r24&lt;br /&gt;
  7c:	e1 f7       	brne	.-8      	; 0x76 &amp;lt;wait_10ms+0x4&amp;gt;&lt;br /&gt;
  7e:	08 95       	ret&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Links stehen die Adressen, dann die Maschinencodes der Befehle,&lt;br /&gt;
danach die Maschinencodes in Assembler-Darstellung. &lt;br /&gt;
Ganz rechts nach dem Kommentarzeichen '&amp;lt;tt&amp;gt;;&amp;lt;/tt&amp;gt;' stehen die Dezimalcodes von&lt;br /&gt;
Konstanten oder die Zieladressen von Sprüngen, wie bei dem &amp;lt;tt&amp;gt;brne&amp;lt;/tt&amp;gt;-Befehl an Adresse 7c, der gegebenenfalls &lt;br /&gt;
8 Bytes zurückspringt und dann an Adresse 76 landet.&lt;br /&gt;
&lt;br /&gt;
==Mapfile erstellen==&lt;br /&gt;
Ein Mapfile gibt Auskunft darüber, an welcher Adresse Code und Objekte&lt;br /&gt;
landen. Erstellt wird das Mapfile während des Linkens, indem &amp;lt;tt&amp;gt;avr-gcc&amp;lt;/tt&amp;gt;&lt;br /&gt;
ein Option an den Linker weiterreicht, die diesem zum Erstellen eines solchen Files veranlasst:&lt;br /&gt;
 &amp;gt; avr-gcc blinky.o -o blinky.elf ... -Wl,-Map,blinky.map&lt;br /&gt;
Dadurch entsteht das Mapfile &amp;lt;tt&amp;gt;blinky.map&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Die Größe ermitteln==&lt;br /&gt;
&lt;br /&gt;
Die Größe der erhaltenen Objekte/Files können mit &amp;lt;tt&amp;gt;avr-size&amp;lt;/tt&amp;gt; ausgegeben werden.&lt;br /&gt;
 &amp;gt; avr-size -x blinky.o&lt;br /&gt;
druckt aus:&lt;br /&gt;
   text    data     bss     dec     hex filename&lt;br /&gt;
   0x7c     0x0     0x2     126      7e blinky.o&lt;br /&gt;
Das sind die Größen der einzelnen [[avr-gcc/Interna#Sections|Sections]].&lt;br /&gt;
Für das Flash relevant ist die Größe von &lt;br /&gt;
&amp;lt;tt&amp;gt;.text&amp;lt;/tt&amp;gt; (Code) + &amp;lt;tt&amp;gt;.data&amp;lt;/tt&amp;gt; (initialisierte Daten),&lt;br /&gt;
für das SRAM relevent ist &amp;lt;tt&amp;gt;.data&amp;lt;/tt&amp;gt; (initialisierte Daten) &lt;br /&gt;
+ &amp;lt;tt&amp;gt;.bss&amp;lt;/tt&amp;gt; (null-initialisierte Daten).&lt;br /&gt;
&lt;br /&gt;
Im Flash werden also 126+0=126 Bytes belegt, und im SRAM 0+2=2 Bytes.&lt;br /&gt;
&lt;br /&gt;
Ab binutils 2.16 gibt es für &amp;lt;tt&amp;gt;avr-size&amp;lt;/tt&amp;gt; die Option &amp;lt;tt&amp;gt;-C&amp;lt;/tt&amp;gt;, mit der man eine Zusammenfassung des ganzen Programms ausgeben kann:&lt;br /&gt;
 &amp;gt; avr-size -C --mcu=atmega8 blinky.elf&lt;br /&gt;
druckt aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
AVR Memory Usage&lt;br /&gt;
----------------&lt;br /&gt;
Device: atmega8&lt;br /&gt;
&lt;br /&gt;
Program:     216 bytes (2.6% Full)&lt;br /&gt;
(.text + .data + .bootloader)&lt;br /&gt;
&lt;br /&gt;
Data:          2 bytes (0.2% Full)&lt;br /&gt;
(.data + .bss + .noinit)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Gesamtgrösse ergibt sich erst aus dem elf-File,&lt;br /&gt;
denn auch die Vektortabelle und der Startup-Code belegen Platz. Hier eine Auflistung der beteiligten Sections:&lt;br /&gt;
 &amp;gt; avr-size -x -A blinky.elf&lt;br /&gt;
druckt aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
blinky.elf  :&lt;br /&gt;
section            size       addr&lt;br /&gt;
.text              0xd8        0x0&lt;br /&gt;
.data               0x0   0x800060&lt;br /&gt;
.bss                0x2   0x800060&lt;br /&gt;
.noinit             0x0   0x800062&lt;br /&gt;
.eeprom             0x0   0x810000&lt;br /&gt;
.stab             0x36c        0x0&lt;br /&gt;
.stabstr           0x84        0x0&lt;br /&gt;
.debug_aranges     0x14        0x0&lt;br /&gt;
.debug_pubnames    0x48        0x0&lt;br /&gt;
.debug_info        0xfc        0x0&lt;br /&gt;
.debug_abbrev      0xa2        0x0&lt;br /&gt;
.debug_line       0x101        0x0&lt;br /&gt;
.debug_str         0xa6        0x0&lt;br /&gt;
Total             0x86b&amp;lt;/pre&amp;gt;&lt;br /&gt;
Im Flash werden somit 0xd8+0=216 Bytes belegt, also 90 Bytes mehr als das Object benötigt; davon entfallen z.B. schon 38 Bytes auf die Vektortabelle des [[ATmega8]], &lt;br /&gt;
die 2*19 Bytes groß ist. &lt;br /&gt;
&lt;br /&gt;
Die Größen einzelner Funktionen/Variablen lassen sich anzeigen mit&lt;br /&gt;
 &amp;gt; avr-nm --size-sort -S blinky.elf&lt;br /&gt;
was nach Größe sortiert ausdruckt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
00800060 00000001 b interrupt_num_10ms.0&lt;br /&gt;
00800061 00000001 b timer_10ms&lt;br /&gt;
00000072 0000000e T wait_10ms&lt;br /&gt;
0000005c 00000016 T timer1_init&lt;br /&gt;
000000bc 0000001c T main&lt;br /&gt;
00000080 0000003c T __vector_6&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= HEX-Dateien zu diesem C-Code =&lt;br /&gt;
Zu dieser C-Datei gibt es HEX-Dateien für einige AVRs. Siehe dazu [[HEX Beispiel-Dateien für AVR]].&lt;br /&gt;
=Spin-off=&lt;br /&gt;
&lt;br /&gt;
Eine [[LED]] blinken zu lassen könnte auch wesentlich einfacher implementert werden,&lt;br /&gt;
also z.B. ohne Funktionsaufrufe oder [[Interrupt]]-Programmierung.&lt;br /&gt;
&lt;br /&gt;
Neben der eigentlichen Aufgabe &amp;quot;LED blinken lassen&amp;quot; kann man an dem Code&lt;br /&gt;
aber noch andere Dinge lernen:&lt;br /&gt;
* Programmierung eines Interrupts&lt;br /&gt;
* Initialisierung von Timer1 als Zähler mit &amp;quot;Clear Timer on Compare Match&amp;quot;&lt;br /&gt;
* Bedingte Codeübersetzung/Controllerunterscheidung mit &amp;lt;tt&amp;gt;#ifdef&amp;lt;/tt&amp;gt; (in &amp;lt;tt&amp;gt;timer1_init&amp;lt;/tt&amp;gt;)&lt;br /&gt;
* Abchecken der Gültigkeit von Defines durch den Präprozessor&lt;br /&gt;
&lt;br /&gt;
=Siehe auch=&lt;br /&gt;
* [[HEX Beispiel-Dateien für AVR]] - Aus diesem Quellcode erzeugte Binärdateien zum Download und Proggen.&lt;br /&gt;
* [[AVR]]&lt;br /&gt;
* [[avr-gcc]]&lt;br /&gt;
* [[Interrupt]]&lt;br /&gt;
* [[:Kategorie:Quellcode C|weitere C-Code Beispiele]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Grundlagen]]&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;br /&gt;
[[Kategorie:Quellcode C]]&lt;br /&gt;
[[Kategorie:Software]]&lt;br /&gt;
[[Kategorie:Praxis]]&lt;/div&gt;</summary>
		<author><name>Plaicy</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Fallstricke_bei_der_C-Programmierung&amp;diff=12223</id>
		<title>Fallstricke bei der C-Programmierung</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Fallstricke_bei_der_C-Programmierung&amp;diff=12223"/>
				<updated>2007-06-03T20:44:42Z</updated>
		
		<summary type="html">&lt;p&gt;Plaicy: /* TRUE ist nicht 1 */ siehe auch&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;=Tippfehler=&lt;br /&gt;
&lt;br /&gt;
Tippfehler können immer passieren. Besonders fies ist es, wenn der Tippfehler nicht zu einer Warnung oder zu einer Fehlermeldung führt, weil der entstandene Code korrekter C-Code ist.&lt;br /&gt;
&lt;br /&gt;
==Ein &amp;lt;tt&amp;gt;;&amp;lt;/tt&amp;gt; zu viel==&lt;br /&gt;
Ein reflexartig eingetippter oder nach Änderungen stehen gebliebener &amp;lt;tt&amp;gt;;&amp;lt;/tt&amp;gt; hat schon so manches &lt;br /&gt;
Programm ausgeknockt:&lt;br /&gt;
 if (a == 0);&lt;br /&gt;
 {&lt;br /&gt;
    /* mach was */&lt;br /&gt;
 }&lt;br /&gt;
Wenn &amp;lt;tt&amp;gt;a == 0&amp;lt;/tt&amp;gt; ist, dann wird &amp;lt;tt&amp;gt;;&amp;lt;/tt&amp;gt; ausgeführt (also im Endeffekt garnichts). Danach kommt der Block, der im &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt; stehen sollte. Der wird immer ausgeführt, denn er gehört nicht mehr zum &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==Zuweisung statt Vergleich==&lt;br /&gt;
 if (a = 0)&lt;br /&gt;
 {&lt;br /&gt;
    /* mach was */&lt;br /&gt;
 }&lt;br /&gt;
Zuerst wird &amp;lt;tt&amp;gt;a = 0&amp;lt;/tt&amp;gt; gesetzt und dann überprüft, ob die &amp;lt;tt&amp;gt;if&amp;lt;/tt&amp;gt;-Bedingung erfullt ist. Der Wert ist aber immer &amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;, was ''nicht erfüllt'' bedeutet. Der nachfolgende Block wird nie betreten.&lt;br /&gt;
&lt;br /&gt;
Abhilfe schafft, indem man sich angewöhnt zu schreiben&lt;br /&gt;
 if (0 == a)&lt;br /&gt;
Wenn man dann eine Zuweisung eintippt, gibt's einen Compiler-Fehler.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Signal/Interrupt-Name vertippt (avr-gcc)==&lt;br /&gt;
&lt;br /&gt;
 SIGNAL (SIG_OVEFRLOW0)&lt;br /&gt;
 {&lt;br /&gt;
    /* mach was */&lt;br /&gt;
 }&lt;br /&gt;
Nicht alle Compiler-Versionen meckern da. Der [[ISR]]-Code wird nicht in die Interrupt-Tabelle eingetragen. Kommt es zum [[Interrupt]], dann landet man in RESET.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=Mangelnde C-Kenntnis=&lt;br /&gt;
&lt;br /&gt;
==Warnung ignoriert==&lt;br /&gt;
&lt;br /&gt;
::&amp;quot;''Wieso soll das Probleme machen? Das ist doch nur eine Warnung!''&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Warnungen zur Compile-Zeit werden gerne zu Fehlern zur Laufzeit. Letztere sind deutlich schwerer zu finden, als angewarnten Code zu korrigieren.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void foo (long*);&lt;br /&gt;
&lt;br /&gt;
void bar (int *p)&lt;br /&gt;
{&lt;br /&gt;
    foo (p+1); &lt;br /&gt;
    // Was soll das sein?!&lt;br /&gt;
    // ((long*) p) + 1       oder  &lt;br /&gt;
    // (long*) (p + 1)&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; gcc -c -o prog.o prog.c&lt;br /&gt;
&lt;br /&gt;
prog.c: In function `bar':&lt;br /&gt;
prog.c:5: warning: passing arg 1 of `foo' from incompatible pointer type&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Array-Index==&lt;br /&gt;
&lt;br /&gt;
Informatiker am Bahnhof:&lt;br /&gt;
:''&amp;quot;0, 1, 2, ... Wo ist mein dritter Koffer?!&amp;quot;''&lt;br /&gt;
Gleiches gilt für Arrays:&lt;br /&gt;
 #define NUM 10;&lt;br /&gt;
 int a[NUM]; // für die N Werte a[0] ... a[N-1]&lt;br /&gt;
Ein Zugriff auf &amp;lt;tt&amp;gt;a[N]&amp;lt;/tt&amp;gt; greift irgendwo hin. &lt;br /&gt;
Wahlweise liest man Schrott oder überschreibt andere Daten, die in der Nähe liegen, und&lt;br /&gt;
plötzlich seltsame Werte enthalten.&lt;br /&gt;
&lt;br /&gt;
==Bitweise vs. Logische Operatoren==&lt;br /&gt;
&lt;br /&gt;
Die Operatoren AND, OR und NOT gibt es in C in zwei Ausprägungen&lt;br /&gt;
;bitweise: Die Operatoren &amp;lt;tt&amp;gt;^&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;|&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;&amp;amp;&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;~&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;|=&amp;lt;/tt&amp;gt;,  &amp;lt;tt&amp;gt;^=&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;&amp;amp;=&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;|=&amp;lt;/tt&amp;gt; operieren bitweise. Der entsprechende Operator wird also auf alle Bits des Wertes parallel angewandt und das Ergebnis für ein Bit ist unabhängig vom Inhalt der anderen Bits.&lt;br /&gt;
;logisch:  Die Operatoren &amp;lt;tt&amp;gt;||&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;&amp;amp;&amp;amp;&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;!&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;&amp;amp;&amp;amp;=&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;||=&amp;lt;/tt&amp;gt; operieren auf dem ganzen (int) Wert und berücksichtigen nur, ob der Wert 0 (false) oder ungleich 0 (true) ist.&lt;br /&gt;
Dementsprechend liefert &amp;lt;tt&amp;gt;&amp;amp;&amp;amp;&amp;lt;/tt&amp;gt; i.d.R. ein anderes Ergebnis als &amp;lt;tt&amp;gt;&amp;amp;&amp;lt;/tt&amp;gt;:&lt;br /&gt;
 if (a &amp;amp;&amp;amp; b) // erfüllt, wenn a!=0 und b!=0 &lt;br /&gt;
 if (a &amp;amp; b)  // erfüllt, wenn in a und b an der gleichen Stelle ein Bit gesetzt ist&lt;br /&gt;
Ein Verwechseln bzw. unkorrektes Einsetzen der Operatoren gibt also ein falsches Programm.&lt;br /&gt;
&lt;br /&gt;
==TRUE ist nicht 1==&lt;br /&gt;
&lt;br /&gt;
Da C die Begriffe TRUE und FALSE eigentlich nicht kennt, wurde schon öfter beobachtet, daß folgendes definiert wurde: &lt;br /&gt;
 #define TRUE 1&lt;br /&gt;
 #define FALSE 0&lt;br /&gt;
solange man damit nur Schalter setzt und abfragt, ist dagegen nichts zu sagen. &lt;br /&gt;
 a = TRUE; b = FALSE;&lt;br /&gt;
 if ( (a == TRUE) &amp;amp;&amp;amp; (b == FALSE)) {..&amp;quot;this is true&amp;quot;..} &lt;br /&gt;
wenn man aber dann schreibt&lt;br /&gt;
 if ( (a &amp;amp; b) == TRUE)  {..&amp;quot;this is true&amp;quot;..}&lt;br /&gt;
kann man einen herbe Enttäuschung erleben. Man müßte für ein richtiges Ergebnis schreiben&lt;br /&gt;
 if ( (a &amp;amp; b) != FALSE)  {..&amp;quot;this is true&amp;quot;..}&lt;br /&gt;
Damit ist aber eine gute Lesbarkeit endgültig dahin.&lt;br /&gt;
&lt;br /&gt;
Besser sind Definition wie&lt;br /&gt;
 #define FALSE (0!=0)&lt;br /&gt;
 #define TRUE  (0==0)&lt;br /&gt;
denn damit gilt einerseits, daß für alle boolschen Werte einschliesslich dieser Konstanten der&lt;br /&gt;
Zusammenhang &amp;lt;tt&amp;gt;x = !!x&amp;lt;/tt&amp;gt; besteht. &lt;br /&gt;
Mit der allerersten Definition hat man das unerwünschte Ergebnis &amp;lt;tt&amp;gt;TRUE != !FALSE&amp;lt;/tt&amp;gt;.&lt;br /&gt;
Andererseits kann man direkt gegen diese Konstanten vergleichen:&lt;br /&gt;
 a = (x &amp;lt; y);&lt;br /&gt;
 ...&lt;br /&gt;
 if (a == TRUE) // oder die 'klassische' Variante: if (a)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Siehe auch: http://www.dclc-faq.de/kap8.htm#8.2&lt;br /&gt;
&lt;br /&gt;
==Ein , anstatt . in Konstante==&lt;br /&gt;
&lt;br /&gt;
In C sowie im angloamerikanischen Sprachraum werden Dezimalbrüche mit einem &amp;lt;tt&amp;gt;.&amp;lt;/tt&amp;gt; (Punkt) geschrieben und nicht wie im Deutschen mit einem &amp;lt;tt&amp;gt;,&amp;lt;/tt&amp;gt; (Komma): &lt;br /&gt;
 float pi;&lt;br /&gt;
 pi = 3,14;         // *AUTSCH* soll wohl heissen 3.14&lt;br /&gt;
Die zweite Zeile besteht aus zwei durch ein Komma getrennten Anweisungen, so daß das ganze&lt;br /&gt;
etwa gleichbedeutend ist mit&lt;br /&gt;
 float pi;&lt;br /&gt;
 pi = 3;&lt;br /&gt;
 14;&lt;br /&gt;
Jedenfalls ist es korrekter C-Code!&lt;br /&gt;
Die &amp;lt;tt&amp;gt;14;&amp;lt;/tt&amp;gt; ist ein Ausdruck, der nicht weiter gebraucht wird und daher wegfällt, da&lt;br /&gt;
er im Gegensatz zu einer void-Funktion keine Wirkung hat.&lt;br /&gt;
Man rechnet also mit dem Wert&amp;amp;nbsp;3 für &amp;lt;math&amp;gt;\pi&amp;lt;/math&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Das falsche Komma hat auch schon so manchen ebay-Freak aufs Kreuz gelegt...&lt;br /&gt;
&lt;br /&gt;
==Führende 0 in Konstanten==&lt;br /&gt;
&lt;br /&gt;
In C kennzeichnet eine führende 0 bei einer Zahlenkonstante, &lt;br /&gt;
daß die Zahl oktal dargestellt ist. Somit ist 010 nicht gleich 10.&lt;br /&gt;
 if (a == 030) // ist a gleich 24?&lt;br /&gt;
&lt;br /&gt;
=Nicht-atomarer Code=&lt;br /&gt;
Verwendet man in einem Programm [[IRQ|IRQs]] ([[Interrupt|Interrupts]]) und ändert in der [[ISR]] (Service Routine) ein Datum (Variable, SFR, ...), dann wird diese Änderung möglicherweise überschrieben, wenn die IRQ zu einem ungünstigen Zeitpunkt auftritt. &lt;br /&gt;
&lt;br /&gt;
Ein ausführlicheres Beispiel, das zeigt, was passieren kann, findet sich im Artikel [[avr-gcc]] im Abschnitt &amp;quot;[[avr-gcc#Zugriff auf einzelne Bits|Zugriff auf einzelne Bits]]&amp;quot;. Ein weiteres Beispiel ist das Lesen, Schreiben oder Testen einer mehrbytigen Variable:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
int volatile i;&lt;br /&gt;
   ...&lt;br /&gt;
   if (0 == i)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Weil &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; länger als 1 Byte ist, kann es je nach Architektur nicht in einem Befehl gelesen werden;&lt;br /&gt;
daher kann während des Lesens eine IRQ auftreten, in deren ISR der Wert von &amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt; möglicherweise &lt;br /&gt;
verändert wird. Der obige Code könnte etwa so assembliert werden (hier mit [[avr-gcc]]):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   ; i wird vom SRAM in das Registerpaar r24:r25 geladen&lt;br /&gt;
   ; low-Teil laden&lt;br /&gt;
   lds r24,i&lt;br /&gt;
   ; high-Teil laden&lt;br /&gt;
   ; wenn hier eine IRQ zuschlägt, in der i verändert wird, ist der Registerinhalt korrupt&lt;br /&gt;
   lds r25,(i)+1&lt;br /&gt;
   or r24,r25&lt;br /&gt;
   brne ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Natürlich können auch komplexere Datenstrukturen von diesem Phänomen betroffen sein.&lt;br /&gt;
Besonders unangenehm an dieser Klasse von Fehlern ist, daß sie nur sporadisch auftauchen&lt;br /&gt;
und man sie daher selbst mit einem guten Debugger sehr schlecht orten kann, da die zugehörige&lt;br /&gt;
Codestelle fast immer korrekt abgearbeitet wird.&lt;br /&gt;
&lt;br /&gt;
Eine Möglichkeit dem zu begegnen ist, den ganzen betroffenen Block ununterbrechbar (atomar) zu machen.&lt;br /&gt;
Wieder ein Beispiel für avr-gcc:&lt;br /&gt;
 #include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
 ...&lt;br /&gt;
    {{ccomment|ein lokale(!) Variable, die das Status-Register und }}&lt;br /&gt;
    {{ccomment|insbesondere das im folgenden geänderte I-Flag merkt }}&lt;br /&gt;
    {{ccomment|Falls man an der Codestelle immer weiß, daß IRQs }}&lt;br /&gt;
    {{ccomment|aktiviert sind, kann man die zu atomisierende Sequenz }}&lt;br /&gt;
    {{ccomment|auch in cli()...sei() einschachteln }}&lt;br /&gt;
    {{ccomment|Falls IRQs global deaktiviert sind brauch man natürlich }}&lt;br /&gt;
    {{ccomment|keine besonderen Vorkehrungen zu treffen, da dann aller Code }}&lt;br /&gt;
    {{ccomment|atomar ist. }}&lt;br /&gt;
    unsigned char sreg = SREG;&lt;br /&gt;
 &lt;br /&gt;
    {{ccomment|Interrupts global deaktivieren (I-Flag &amp;amp;#61; 0) }}&lt;br /&gt;
    cli();&lt;br /&gt;
 &lt;br /&gt;
    if (0 == i)&lt;br /&gt;
    {&lt;br /&gt;
        i = 1;&lt;br /&gt;
        {{ccomment|IRQs sobald als möglich wieder zulassen }}&lt;br /&gt;
        {{ccomment|(I-Flag wieder herstellen) }}&lt;br /&gt;
        SREG = sreg;&lt;br /&gt;
    }&lt;br /&gt;
    else&lt;br /&gt;
    {&lt;br /&gt;
        {{ccomment|IRQs so bald als möglich wieder zulassen }}&lt;br /&gt;
        {{ccomment|(I-Flag wieder herstellen) }}&lt;br /&gt;
        SREG = sreg;&lt;br /&gt;
        return;&lt;br /&gt;
    }&lt;br /&gt;
    ...&lt;br /&gt;
Oder je nach Programmstruktur sichert man den Wert, z.B. in eine lokale Variable oder deaktiviert nur selektiv die kritischen Interrupts, also solche, die Einfluss auf die kritischen Daten nehmen.&lt;br /&gt;
&lt;br /&gt;
= Weitere Fallstricke =&lt;br /&gt;
* [[Warteschleife]]&lt;br /&gt;
&lt;br /&gt;
= Siehe auch =&lt;br /&gt;
* [[C-Tutorial]]&lt;br /&gt;
* [[avr-gcc]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Grundlagen]]&lt;br /&gt;
[[Kategorie:Quellcode C|!]]&lt;br /&gt;
[[Kategorie:Software]]&lt;/div&gt;</summary>
		<author><name>Plaicy</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Diskussion:Fallstricke_bei_der_C-Programmierung&amp;diff=12222</id>
		<title>Diskussion:Fallstricke bei der C-Programmierung</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Diskussion:Fallstricke_bei_der_C-Programmierung&amp;diff=12222"/>
				<updated>2007-06-03T20:43:46Z</updated>
		
		<summary type="html">&lt;p&gt;Plaicy: &amp;quot;TRUE ist nicht 1&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;===&amp;quot;TRUE ist nicht 1&amp;quot;===&lt;br /&gt;
In dem Abschnitt steht, dass man lieber folgendes schreiben soll.&lt;br /&gt;
 #define FALSE (0!=0)&lt;br /&gt;
 #define TRUE  (0==0)&lt;br /&gt;
&lt;br /&gt;
Was soll das bringen?  Danach ist FALSE 0 und und TRUE als 1 definiert, da laut ANSI-C (ANSI99 6.5.9) ''Each of the operators [&amp;quot;==&amp;quot; und &amp;quot;!=&amp;quot;] yields 1 if the specified relation is true and 0 if it is false.'''.  Siehe auch &lt;br /&gt;
http://www.dclc-faq.de/kap8.htm#8.2 .  Meine Meinung verwirrt die Aussage ''TRUE ist nicht 1'' nur.--[[Benutzer:Plaicy|Plaicy]] 22:43, 3. Jun 2007 (CEST)&lt;/div&gt;</summary>
		<author><name>Plaicy</name></author>	</entry>

	</feed>