Forum: Compiler & IDEs Anfängerhilfe bei Input


von Martin *. (mistermister606)


Lesenswert?

Hallo zusammen ich habe vor wenigen Tagen mit dem rumpus board zu 
programmieren begonnen. Jetzt komme ich allerdings trotz des 
AVR-GCC-Tutorial nicht weiter.

Ich möchte einen Eingang (schalter) einlesen und dementsprechend eine 
LED leuchten lassen.


DANKE

1
//io.h einbinden damit die ARV Register ueber Namen wie DDRD angesprochen werden koennen
2
#include <avr/io.h>
3
//delay.h einbinden damit die Funktion _delay_loop_2 bekannt ist
4
#include <util/delay.h>
5
6
7
void main(void) {
8
9
DDRD = (1<<PD3) | (1<<PD6);
10
DDRC &= ~(1<<PC0);  // Definition des Eingangs      = 0 = Eingang
11
PORTC |= (1<<PC0);  // Pul Up       = EIN
12
13
14
15
16
if ( PINC & (1<<PINC0) ) {
17
18
PORTD |= (1<<PD3);  //LED2
19
}
20
21
22
23
if ( !(PINC & (1<<PINC0)) ) {
24
25
  PORTD |= (1<<PD6);  //LED3
26
}
27
28
 
29
   while(1) {                // (5)
30
    }                         // (7)
31
   return 0;                 // (8)
32
33
34
35
}

von Karl H. (kbuchegg)


Lesenswert?

Fang erst mal damit an, deinem Programm eine vernünftige äussere Form zu 
geben. Interessanterweise haben nämlich die mit den scheuslichsten 
Programmen immer wieder das Problem, dass
* sie ihre eigenen Programme nicht verstehen
* sie die tollsten und unlogischten Fehler haben


Jedes C-Programm, dass du in den nächsten Wochen schreiben wirst, folgt 
immer diesem grundsätzlichen Aufbau

1
#include ....
2
3
4
int main()
5
{
6
  Initialisierungen. Das beinhaltet
7
  * Variablen auf Startwerte stellen
8
  * Die Hardware-Sachen konfigurieren
9
10
11
  eventuell ein sei(), wenn im Programm mit Interrupts gearbeitet wird
12
13
  while( 1 )
14
  {
15
    hier kommt die eigentliche Programmarbeit rein
16
    also das was das Programm tun soll
17
  }
18
}


Die 'eigentliche Arbeit' die dein Programm machen soll, besteht darin 
die LED je nach Schalterstellung entsprechen ein oder auszuschalten.

Und jetzt formatier erst mal dein Programm richtig und sieh nach, wo und 
wie du die Dinge angeordnet hast.

von Kali (Gast)


Lesenswert?

Wenns VHDL wäre würd's vielleicht gehen. ;-)

von Karl H. (kbuchegg)


Lesenswert?

Zum Thema formatieren
* eine einzige Leerzeile zwischen funktionalen Blöcken ist ok.
  Die Leerzeile sorgt für eine optische Gruppierung und leitet
  dich beim Lesen. Sie sagt dir: hier ist ein Gedankengang zu Ende
  und eine neuer Gedanke beginnt.

  Das macht EINE Leerzeile.

  Viele Leerzeilen hintereinander hingegen bringen nichts. Sie ziehen
  den Code nur in die Länge und bewirken das Gegenteil. Die Übersicht
  steigt nicht, sondern sie nimmt ab. Eben weil der Code unnötigerweise
  in die Länge gezogen wird.

* nach jeder öffnenden Klammer { beginnt ein neuer sog. Code-Block.
  um den Code-Block erkennen zu können ohne jedesmal die
  einschliessenden { } suchen zu müssen, wird der Block eingerückt.
  Nach einer { wird der zum Block gehörende Code um 2 Leerzeichen
  eingerückt. Diese Einrückung wird erst wieder mit der schliessenden }
  wieder aufgehoben. Die schliessende } steht auf der selben
  Einrücktiefe wie entweder die { selber oder wie die Anweisung in der
  die { zu finden ist. Auf die Art braucht man nur immer einfach nur
  in derselben Spalte nach oben oder nach unten im Code zu gehen um
  die jeweils korrespondierende { oder } zu finden und zu sehen, welchen
  Code die { } in einen Codeblock einschliessen.

Die erste Einrückversion sieht so aus
1
int main()
2
{
3
  // einrücken
4
5
  ...
6
7
  while( 1 )
8
  {
9
    // einrücken
10
11
    if( PIND & ( 1 << PD2 ) )
12
    {
13
      // einrücken
14
      PORTB = 5;
15
      // Block ist zu Ende, also für die } ausrücken
16
    }
17
    else
18
    {
19
      // einrücken
20
      PORTB = 8;
21
      // ausrücken
22
    }
23
24
    // Block zu Ende, es fehlt noch eine } für das while
25
    // also ausrücken
26
  }
27
28
  // und es fehlt noch ein } für die { nach dem int main()
29
}

die andere Version sieht so aus (jetzt ohne die blödsinnigen 
einrücken/ausrücken Kommentare. Die schreibt man natürlich nicht 
wirklich)
1
int main()
2
{
3
  ...
4
5
  while( 1 ) {
6
7
    if( PIND & ( 1 << PD2 ) ) {
8
      PORTB = 5;
9
    }
10
    else {
11
      PORTB = 8;
12
    }
13
  }
14
}

Die Variante, in der die öffnende { auf derselben Zeile steht (mit 
Ausnahme nach einem Funktionskopf) ist etwas platzsparender als die 
Variante, in der die { ihre eigene Zeile bekommt. Aber ansonsten sind 
die Dinge gleichwertig: Nach einem { wird eingerückt. Die schliessende } 
wird wieder ausgerückt.

Am Ende einer Funktion muss die schliessende } wieder am linken Rand 
stehen. Sonst stimmt irgendwo mit den { und } etwas nicht.

Aber auf keinen Fall kann es sein, dass eine Anweisung am linken Rand 
anfängt.

von Martin *. (mistermister606)


Lesenswert?

Erstmal vielen vielen DANK.
Ich habe nun alles etwas aufgeräumt und siehe da dann auch den Fehler 
verstanden :)
Ich finde genau diesen letzten Artikel TOP, packe doch den gleich mal 
ins AVR-GCC-Tutorial den dies würde viele Anfänger vor genau solchen 
Fehlern bewahren!
Hab ich noch etwas übersehen oder ist die äußere Form, für meine 
nächsten Schritte ok ? :)

1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
5
int main()
6
{
7
8
  DDRD = (1<<PD3) | (1<<PD6);
9
  DDRC &= ~(1<<PC0);  // Definition des Eingangs    = 0 = Eingang
10
  PORTC |= (1<<PC0);  // Pul Up         = EIN
11
  PINC &= ~(1<<PC0);  // Ausgangszustand      = 0
12
13
14
  while( 1 )
15
  {
16
    
17
    if ( PINC & (1<<PINC0) ) {
18
      PORTD |= (1<<PD3);  //LED2
19
      PORTD &= ~(1<<PD6);  //LED3 reset
20
    }
21
22
    if ( !(PINC & (1<<PINC0)) ) {
23
      PORTD |= (1<<PD6);  //LED3
24
      PORTD &= ~(1<<PD3);  //LED2 reset
25
    }
26
27
  }
28
}

von Karl H. (kbuchegg)


Lesenswert?

Martin *** schrieb:
> Erstmal vielen vielen DANK.
> Ich habe nun alles etwas aufgeräumt und siehe da dann auch den Fehler
> verstanden :)

gut. das war der Sinn der Sache.


> Hab ich noch etwas übersehen oder ist die äußere Form, für meine
> nächsten Schritte ok ? :)

Ist soweit ok.


Hier

>     if ( PINC & (1<<PINC0) ) {
>       PORTD |= (1<<PD3);  //LED2
>       PORTD &= ~(1<<PD6);  //LED3 reset
>     }
>
>     if ( !(PINC & (1<<PINC0)) ) {
>       PORTD |= (1<<PD6);  //LED3
>       PORTD &= ~(1<<PD3);  //LED2 reset
>     }

gibt es noch was.

Die Bedingung vom 2.ten if ist das genau Gegenteil der Bedingung vom 
1.ten if. Ist ja auch logisch warum das so sein soll.

Schreib das besser mit einem else
1
     if ( PINC & (1<<PINC0) ) {
2
       PORTD |= (1<<PD3);  //LED2
3
       PORTD &= ~(1<<PD6);  //LED3 reset
4
     }
5
     else {
6
       PORTD |= (1<<PD6);  //LED3
7
       PORTD &= ~(1<<PD3);  //LED2 reset
8
     }

das hat gleich mehrere Vorteile
* zum einen verhindert es blöde Tippfehler in den Bedingungen. Alles was
  man 2 mal tippen muss, öffnet schon die Gefahr dass man sich einmal
  vertippt.

* zum anderen bindet es die beiden abhängigen Code-Blöcke enger 
aneinander. Ich muss nicht erst lange die beiden if-Bedingungen 
studieren um mich zu vergewissern, dass die eine das Gegenteil vom 
anderen ist und dass diese beiden Code Blöcke voneinander abhängen und 
zwischen ihnen eine Beziehung besteht. Das else erzählt es mir mit einem 
Blick.

* Es entspricht auch (in diesem Fall) etwas besser unserer menschlichen 
Denkweise. Wir sagen: Wenn die Taste gedrückt ist, dann schalte die LED 
ein, anderfalls schalte sie aus.
Wir sagen nicht: Wenn die Taste A gedrückt ist, dann schalte die LED 
ein. Wenn die Taste A nicht gedrückt ist, dann schalte die LED aus.
Auch hier wieder: Die erste Version ist uns vertrauter, weil sie in der 
Formulierung kürzer ist und weil sie einen expliziten Bezug zwischen 
"Wenn .. andernfalls ..." herstellt. Im zweiten Fall musst du beim Lesen 
des zweiten Teilsatzes kurz im Text zurückgehen um festzustellen: 
Hoppla, da ist ja von derselben Taste die Rede.

von Martin *. (mistermister606)


Lesenswert?

nochmals DANKE :) thumbsup

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.