Forum: Mikrocontroller und Digitale Elektronik Folgendes Programm läuft nicht auf dem ATmega32


von Jens (Gast)


Lesenswert?

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

von Antwort (Gast)


Lesenswert?

Dein Fehler liegt in folgender Zeile
1
if((PIND&(1<<PIND2))==1)
Diese Bedingung wird niemals erfüllt sein. Denke einmal nach wieso. Ist 
nicht schwer.

von Jens (Gast)


Lesenswert?

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

von Klaus W. (mfgkw)


Lesenswert?

Dann C-Buch und die Operatoren & und && und == mal anschauen?

von Antwort (Gast)


Lesenswert?

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.

von Jens (Gast)


Lesenswert?

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

von abc (Gast)


Lesenswert?

>Ü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
int i; //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...
2
{
3
   foo();
4
}
5
else //ansonsten
6
{  bar();
7
}

von Falk B. (falk)


Lesenswert?

@  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

MFG
Falk

von Klaus W. (mfgkw)


Lesenswert?

1
  int i = 1;
2
  if( i&i&&i&&&i )
3
  {
4
    puts( "ja" );
5
  }

von Jens (Gast)


Lesenswert?

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

von Karl H. (kbuchegg)


Lesenswert?

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.

von abc (Gast)


Lesenswert?

>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?

von Klaus W. (mfgkw)


Lesenswert?

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.

von abc (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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() )

von Klaus W. (mfgkw)


Lesenswert?

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.

von Klaus W. (mfgkw)


Lesenswert?

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.

von abc (Gast)


Lesenswert?

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!

von Karl H. (kbuchegg)


Lesenswert?

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.

von Robert K. (murdok)


Lesenswert?

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.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.