Hallo zusammen.
Ich benötige eure vielseitige Hilfe, nachdem ich das Forum durchsucht
habe (suchbegriff: Programm läuft nicht auf ATmega32) und die gefundenen
Beiträge mir leider keine Hilfe gebracht haben.
Das Programm sieht so aus:
#include <avr/io.h>
int main(void)
{
DDRD=0xf0;
while(1){
if((PIND&(1<<PIND2))==1)
PORTD|=(1<<PD5);
else PORTD&=~(1<<PD5);
}
return1;
}
Wie die Kenner wissen, soll das Programm, wenn an PIND2 eine 1 anliegt,
am ausgang PD5 eine eins ausgeben, wenn nicht, an PD5 eine Null
ausgeben.
Ich habe extern einen Taster, welcher über einen Pull down Widerstand an
Masse geschlossen ist. Am ausgang ist eine LED.
Parallel zum Wiederstand ist ein Kondensator.
Ach ja, ich benutze das Pollin Evaluationsboard, vorerst ohne
Addonboard.
Das makefile sollte stimmen. Es ist auf den ATmega32 angepasst.
Fusebits werde ich falls diese jemand verlangt auch noch Preisgeben.
Ich würde mich über eure Hilfe sehr Freuen. Ausserdem sind Kritik im
Positiven und oder negativen sinne zum Programm sehr erwünscht
Mfg Jens
Ich bin noch nicht lange in C, aber ich Probiere es mal aus:
Entweder weil ich hier sage das eine 1 an PIND2 geschrieben werden soll,
was fölliger blödsinn wäre weil das ein Eingang ist.
Oder wegen dem ==1.
Tut mir leid, ein größeres geschütz an Wissen kann ich leider noch nicht
aufbringen. Verstehen möchte ich das aber trotzdem.
Aber danke schonmal für das durchlesen und den Gedankenanstoss
Gruß Jens
Hier mal genau aufgeschlüsselt was du erhälst, danach kommt der "aha"
Effekt.
Annahme: An PIND2 liegt eine 1 an:
1
PIND&(1<<PIND2)
Ergebniss (binärdarstellung): 0b0000 0100
Du hast also ein gesetztes bit, aber die Dezimalzahl davon ist nich 1.
Denn die binäre Darstellung von 1 sieht wie folgt aus:
0b0000 0001
Das "0b0000 0100" ungleich ist zu "0b0000 0001" sieht man ja sofort.
Richtig würde die if Abfrage wie folgt aussehen
1
if(PIND&(1<<PIND2))
Die Abfrage wird zutreffen wenn das Ergebnis ungleich Null ist. Was mit
0b0000 0100 ja der Fall ist.
Du könntest auch einen Vergleich auf 4 durchführen (0b0000 0100 = 4 in
Dezimal), aber das kannste dir bei nur einem Pin sparen.
AHA.
Nun verstehe ich. ==1 bedeutet, das ich nach einer Dezimalen 1 abfrage.
Also wenn ich tatsächlich nach einer Dezimalen 1 abfragen würde, müsste
ich PIND0 abfragen (nur zum verständniss).
Denn die if Bedingung wäre Wahr wenn ich PIND0 abfragen würde.
&& ist das Logische und, also wenn bedingung1 UND(&&) bedingung2 wahr,
dann mache irgendwas (sollte natürlich definiert sein).
Über & habe ich im C buch gelesen, das es ein Adressoperator ist, den
zusammenhang mit if(PIND&(1<<PIND2)) verstehe ich nicht.
Aber trotzdem vielen dank für eure Hilfe stellung.
Gruß JEns
>Über & habe ich im C buch gelesen, das es ein Adressoperator ist, den>zusammenhang mit if(PIND&(1<<PIND2)) verstehe ich nicht.
Jain. Wenn & vor einer Variable steht ist es der Adressoperator, in
einem Vergleich steht es für BINÄRES UND. Das ganze sollte man nicht mit
&& verwechseln, das ist das LOGISCHE UND.
also
1
inti;//Variable vom Typ Int
2
int*j;//POINTER auf Variable vom Typ Int
3
j=&i;//j bekommt die Adresse von i zugewiesen
aber
1
if(j&1)//Wenn j und 1 wahr ist, also das Bit 0 in j gesetzt ist dann...
@ Jens (Gast)
>Nun verstehe ich. ==1 bedeutet, das ich nach einer Dezimalen 1 abfrage.
Ja.
>Also wenn ich tatsächlich nach einer Dezimalen 1 abfragen würde, müsste>ich PIND0 abfragen (nur zum verständniss).>Denn die if Bedingung wäre Wahr wenn ich PIND0 abfragen würde.
Ja.
>&& ist das Logische und, also wenn bedingung1 UND(&&) bedingung2 wahr,>dann mache irgendwas (sollte natürlich definiert sein).
Ja.
>Über & habe ich im C buch gelesen, das es ein Adressoperator ist, den>zusammenhang mit if(PIND&(1<<PIND2)) verstehe ich nicht.
Hehe, stimmt, das ist AUCH der Adressoperator, aber nur, wenn er direkt
vor einer Variablen steht. EIn einfach & ist ein binäres UND, dabei wird
Bit für Bit verglichen, siehe Logische Verknüpfungen. Das ERGEBNIS
kann man dann wieder LOGISCH bewerten. Ist es kann NULL oder ungleich
NULL sein, was logisch NEIN(false) oder JA(true) bedeutet.
1
if((PIND&(1<<PD2))!=0){};// erst binär UND, dann logisch vergleichen, explizite Schreibweise
2
3
if(PIND&(1<<PD2))){};// erst binär UND, dann logisch vergleichen, verkürzte C-Schreibweise
Vielen, Vielen dank.
Ich werde mir den ADressoperator und Binäres Und genau anschauen, um
auch dahinter zusteigen. Kann bestimmt nicht schaden.
Aber das erfolgsgefühl, das die LED leuchtet ist da und motiviert weiter
zu machen.
Vielen dank. Meine Persönliche erste kleine Hürde ist geschafft dank
euch.
Das sind die kleinen fehler, aus denen man sehr viel lernt.
Danke nochmals.
Mfg Jens
Jens schrieb:> Vielen, Vielen dank.> Ich werde mir den ADressoperator und Binäres Und genau anschauen, um> auch dahinter zusteigen.
Adressoperator kannst du noch eine Weile ignorieren
> Das sind die kleinen fehler, aus denen man sehr viel lernt.
Mitnehmen solltest du, dass bei Abfragen weniger oft mehr ist.
Wenn es aber sein muss, dann frag auf 0 oder nicht 0 ab und nicht auf
explizit 1. Denn wenn etwas 1 sein muss, dann muss es auch wirklich 1
sein, während logisch alles, was nicht 0 ist, automatisch als TRUE gilt.
Also entweder so
1
if((PIND&(1<<PD2))!=0)
oder überhaupt gleich in der Kurzform
1
if(!(PIND&(1<<PD2)))
bzw in der Umkehrung
1
if(PIND&(1<<PD2))
Ein if verlangt kein explizites TRUE oder FALSE. Alles was es will ist
ein Ausdruck der entweder 0 oder nicht 0 ist. Das reicht dann schon.
>während logisch alles, was nicht 0 ist, automatisch als TRUE gilt.
Das greife ich mal kurz auf: Müsste man dann nicht TRUE als (!FALSE)
statt als 1 definieren wie man es öfters sieht?
Mit !FALSE bekommst du auch genau 1, und nicht "alles außer 0".
#define TRUE (1) und #define TRUE (!FALSE) sind vollkommen gleichwertig,
gleich gut wie schlecht.
Das klingt logisch, aber... Wenn jetzt jede Zahl ungleich Null TRUE ist,
dann heisst das ja dass z.B. 2 auch TRUE ist. Was ist wenn ich eine
Funktion habe die anstatt einer 1 eine 2 für TRUE zurückgibt? Soweit ich
durchblicke ist das erlaubt, aber der Vergleich if(foo()==TRUE) würde
fehlschlagen. Jetzt bin ich verwirrt.
abc schrieb:> Das klingt logisch, aber... Wenn jetzt jede Zahl ungleich Null TRUE ist,> dann heisst das ja dass z.B. 2 auch TRUE ist.
Genau
> Was ist wenn ich eine> Funktion habe die anstatt einer 1 eine 2 für TRUE zurückgibt?
Nichts, Was soll sein?
> Soweit ich> durchblicke ist das erlaubt, aber der Vergleich if(foo()==TRUE) würde> fehlschlagen.
Würde er
> Jetzt bin ich verwirrt.
Daher: Weniger ist oft mehr
if( foo() )
und alles ist in Butter.
Vergleiche auf == TRUE sind NIE besonders schlau! Wenn schon dann !=
FALSE, aber üblicher ist die Kurzform
if( foo() )
bzw
if( !foo() )
du musst dir nochmal auf der Zunge zergehen lassen:
1. Das Ergebnis eines Tests (i<j oder x==5) ist immer 0 oder 1.
1 kommt raus, wenn der Test wahr feststellt, 0 bei false.
2. Wenn irgendwo ein Wert für eine logische Entscheidung
benutzt wird (if(...) oder while(...) etc.) dann wird
der entsprechende Ausdruck immer als false gewertet,
wenn er 0 ist, in jedem anderen Fall als true.
1.+2. sind einfachnur unterschiedliche Richtungen der Auswertung.
Bei 1. wird aus etwas logischen eine Zahl, bei 2. wird umgekehrt
irgendeine Zahl für eine logische verwendet.
Bei 1. kann leicht festgelegt werden, daß es nur 2 Werte geben
soll.
Es kann ja nur true oder false sein, und die beiden entsprechen
per Definition 1 bzw. 0.
Ein i<j wird nie etwas anderes als 0 oder 1 liefern; wieso
sollte der Code da -14 oder 48 erzeugen?
Bei 2. dagegen ist es nicht so einfach: es geht eine Zahl rein
(woher auch immer die kommen mag) und es soll darauf eine
Entscheidung gefällt werden ja oder nein, bzw. wahr oder
falsch:
int i = ...;
if( i ) ...
i könnte 0 sein, oder 1, oder jeder andere Wert.
Deshalb ist für diese Richtung festgelegt, daß 0
dem false entspricht, 1 dem true und zusätzlich (damit keine
Lücken entstehen): alles andere auch gleich true.
Genau deshalb ist es gefährlich, irgendwas mit ==TRUE
zu testen.
54648648 wäre nach C-Logik auch wahr, aber 54648648==TRUE
liefert dagegen das Gegenteil.
Daher meine Empfehlung: nie irgendwas==TRUE testen, sondern
entweder nur (irgendwas) nehmen oder notfalls irgendwas!=FALSE,
aber letzteres ist nur sinnloses Aufblähen und stiftet auch+
nur Verwirrung.
Karl heinz Buchegger schrieb:>> Das klingt logisch, aber... Wenn jetzt jede Zahl ungleich Null TRUE ist,>> dann heisst das ja dass z.B. 2 auch TRUE ist.>> Genau
nein, eigentlich nicht - hier tritt die Verwirrung ein.
Nach einem #define TRUE 1 ist 2 eben nicht TRUE, aber auch nicht FALSE.
Ein if(2==TRUE)... ist kontraproduktiv und geht schief.
Ansonsten natürlich völlige Übereinstimmung.
Karl heinz Buchegger schrieb:> Daher: Weniger ist oft mehr>> if( foo() )>> und alles ist in Butter.>> Vergleiche auf == TRUE sind NIE besonders schlau! Wenn schon dann !=> FALSE, aber üblicher ist die Kurzform>> if( foo() )> bzw> if( !foo() )
Natürlich, da hätte ich jetzt selbst drauf kommen können!
Halten wir fest: TRUE und FALSE nicht in Tests verwenden, sondern nur
als Rückgabewerte von Funktionen. Kann man das so stehen lassen?
Ist aber manchmal auch ne haarige Sache diese Programmiersprache...
Danke euch beiden!
Klaus Wachtler schrieb:> Karl heinz Buchegger schrieb:>>> Das klingt logisch, aber... Wenn jetzt jede Zahl ungleich Null TRUE ist,>>> dann heisst das ja dass z.B. 2 auch TRUE ist.>>>> Genau>> nein, eigentlich nicht - hier tritt die Verwirrung ein.> Nach einem #define TRUE 1 ist 2 eben nicht TRUE, aber auch nicht FALSE.
Hast recht, da hab ich mich schlecht ausgedrückt.
Ich hab das aufgefasst als: 2 wird doch ebenfalls als TRUE gewertet.
Wobei mit TRUE der logische Zustand 'wahr' gemeint ist und nicht so sehr
das Definement für TRUE
> Ein if(2==TRUE)... ist kontraproduktiv und geht schief.
selbstredend.
> Ansonsten natürlich völlige Übereinstimmung.
Ich denke, das ist etwas was man lernen muss: Dieses explizit sein zu
wollen abzulegen. Gerade bei diesen Vergleichen fällt man damit mehr als
des öfteren auf die Nase, bis man einsieht, dass
if( irgendwas == TRUE )
eine extrem schlechte Idee ist.
Wozu auch so explizit sein. Wenn irgendwas offensichtlich als logischer
Wert aufzufassen ist, dann ist das bereits (gedanklich gesehen) ein
logischer Wert. Wozu dann noch einmal mit TRUE/FALSE abtesten?
Genausogut könnte man ja auch fragen, ob der Vergleich von a mit b TRUE
ergibt oder nicht und das so schreiben
if( ( a == b ) == TRUE )
und spätestens jetzt sieht man schon, dass einen hier der Vergleich im
Grunde nicht weiterbringt. Denn da ist ja schon wieder ein Vergleich,
den man abtesten müsste
if( ( ( a == b ) == TRUE ) == TRUE )
Viel besser ist die Sichtweise, das if (und while und for etc.) den
Vergleich mit !FALSE quasi schon eingebaut haben. In
if( irgendwas )
ist es im if schon enthalten, dass iregendwas auf true/false abgetestet
wird. Das braucht man nicht explizit hinschreiben. Und das sollte man
sogar auch nicht tun. Gibt nur Ärger.
Hallo,
die 'einfache' Schreibweise trifft vlt. auf den Heimbereich zu.
Wenn allerdings für sicherheitsrelevante Elektronik entwickelt werden
muss, so gibt es diverse Standards an die man sich halten sollte.
Für Ansi C im automotive Bereich bietet sich hier z.B. ein Blick in die
MISRA C Guidline an.
Dort wird (zwar nur vorgeschlagen und nicht verlangt) in Regel 49 eine
explizite Schreibweise der Abfrage befürwortet, solange es sich nicht um
einen effektiven Boolean-Typ handelt (z.B. ein Flag, Bitfield etc.).
Wenn man über diversen Code mal einen LINT check laufen lässt, dann
sieht man erst mal was man alles tun können sollte um Sourcecode 'schön'
aussehen zu lassen.