Forum: Compiler & IDEs IF Statement


von Alexander F. (alexander_f25)


Lesenswert?

Hallo,

ich bin "Neuling" im Bereich µC Programmierung mit C.
Ich programmiere schon seit längerem im Bereich Objective-C (iOS), aber 
wie mir scheint gibt's in diesem Bereich so einige Sachen, welche anders 
sind...

Zum Beispiel habe ich mit folgendem Code meine Probleme, genauer gesagt 
mit dem IF Statement nach dem 1. IF.
Im Simulator klappts, dann auf dem STK600 mit ATmega2560 nicht mehr - 
entweder habe ich einen Denkfehler oder das Board / MCU ist kaputt...???

Hier der Code:
#include <avr/io.h>
#include "stdint.h"

volatile uint8_t counter;

int main(void)
{
  DDRB = 0b00000010;
  PORTB = (1 << PB1);
    while(1)
    {
        if(PORTB & (1 << PB1))
    {
      if(counter < 5) // dieses if wird vom Board nicht "erkannt"
      {
        PORTB &= ~(1 << PB0);
        counter++;
      }
      else
      {
        PORTB |= (1 << PB0);
      }
    }
    else
    {
      PORTB |= (1 << PB0);
      counter = 0;
    }
    }
}


Gibts bei den IF Statements hier in C mehr zu beachten bzw. 
Besonderheiten?



Vielen Dank schon mal im Vorraus!
Grüße,
Alex

PS: Ich "lerne" mit dem AVR-GCC-Tutorial hier von Mikrocontroller.net.

von André M. (pc-fan)


Lesenswert?

Hallo Alex,

beschreibe doch bitte erst einmal welche Reaktion du von dem Programm 
erwartest. Dass es im Simulator funktioniert könnte vielleicht daran 
liegen, dass du es dort Schritt für Schritt durchgehst, es auf dem Board 
dann aber alles viel schneller abläuft.

Gruß
André

von ... (Gast)


Lesenswert?

Alexander F. schrieb:
> Im Simulator klappts, dann auf dem STK600 mit ATmega2560 nicht mehr -
> entweder habe ich einen Denkfehler oder das Board / MCU ist kaputt...???

Die Klammern sind nicht richtig eingerückt. Kein Wunder, dass das zu 
Unklarheiten führt.

von Alexander F. (alexander_f25)


Lesenswert?

Hallo André,

ein Eingang gibt ein permanentes Signal zum einschalten, ein Motor wird 
aktiviert - dieser liefert Impulse zurück welche der µC zählen und nach 
X Impulsen den Motor wieder deaktivieren soll.


Gruß,
Alex

von Alexander F. (alexander_f25)


Lesenswert?

... schrieb:
> Die Klammern sind nicht richtig eingerückt.

Kann es aufgrund des Einrückens bzw. der Klammern zu fehlern führen???

if(1 == 1) {

}
else {

}

ODER

if(1 == 1) {

} else {

}

ODER

if(1 == 1)
{

}
else
{

}

macht das in dieser Sprache einen unterschied?

von J.-u. G. (juwe)


Lesenswert?


von Alexander F. (alexander_f25)


Lesenswert?

J.-u. G. schrieb:
> Was soll das bezwecken?

sorry, sollte natürlich PINB heissen...
Ich hab diesen Beispielcode vom Original verkürzt...

von J.-u. G. (juwe)


Lesenswert?

Alexander F. schrieb:
> sorry, sollte natürlich PINB heissen...

PB1 wird als Ausgang definiert. Dieser wird vor der while-Schleife auf 
HIGH gesetzt und danach nie mehr angefasst. Demzufolge ist diese 
if-Abfrage sinnlos. Insbesondere wird nie der zugehörige else-Zweig 
erreicht und damit wird auch counter auch nie auf 0 zurückgesetzt.

von Alexander F. (alexander_f25)


Lesenswert?

J.-u. G. schrieb:
> Alexander F. schrieb:
>> sorry, sollte natürlich PINB heissen...
>
> PB1 wird als Ausgang definiert.

ich sollte das was ich kopiere vorher definitiv genauer durchsehen...

int main(void)
{
  DDRB = 0b00000001;
  PORTB = 0b00000010;
    while(1)
    {
        if(PINB & (1 << PB1))
    {
      if(counter < 5)
      {
        PORTB |= (1 << PB0);
        counter++;
      }
      else
      {
        PORTB &= ~(1 << PB0);
      }
    }
    else
    {
      PORTB &= ~(1 << PB0);
      counter = 0;
    }
    }
}

das sollte dann so korrekt sein?

von (prx) A. K. (prx)


Lesenswert?

Alexander F. schrieb:

> Kann es aufgrund des Einrückens bzw. der Klammern zu fehlern führen???

Nein, nicht in C, wohl aber zu fehlendem Durchblick, der dann wiederum 
zu Fehlern führt. Oder die Forenleser so verwirrt, dass sie sich 
weigern, sich dem eigentlichen Thema zu widmen.

Tipp fürs Posten: TABs sind hier sehr unpraktisch.

von Alexander F. (alexander_f25)


Lesenswert?

A. K. schrieb:
> aber zu fehlendem Durchblick

Ah gut, dann bin ich beruhigt. ^^
Ok, werde es beachten!

von DirkB (Gast)


Lesenswert?

Woran erkennst du, dass das if nicht erkannt wird?

Der µC ist so schnell, dass schon beim ersten Impuls bis 5 gezählt wird. 
Und die Zeit ist zu kurz, dass da irgend etwas sinnvolles am Motor 
passiert.

von Alexander F. (alexander_f25)


Lesenswert?

DirkB schrieb:
> Woran erkennst du, dass das if nicht erkannt wird?

Ich hatte vorhin eine LED als Ausgang geschalten und diese sollte, nach 
Betätigung eines Tasters und herunterzählen von ca. 1000 Schritten 
deaktiviert werden...
Es passierte nichts, die LED ging nicht aus. (In der IF Abfrage hatte 
ich PINB verwendet)

Vielleicht hatte ich heute einfach nur "den Wald vor lauter Bäumen nicht 
gesehen" oder das STK600 bzw. die MCU ist defekt... gg

von Peter (Gast)


Lesenswert?

Wie und wo hast Du counter deklariert? Bitte immer den exakten Code (mit 
Copy+Paste) posten, sonst versäumst Du die Zeit allfälliger Foren-Helfer 
mit unnötigen Tippfehlern

>herunterzählen von ca. 1000 Schritten
Wo sind denn diese 1000 Schritte zu sehen / zu finden?
1
if(counter < 5)
2
{
3
  PORTB |= (1 << PB0);
4
  counter++;
5
}
6
else
7
{
8
  PORTB &= ~(1 << PB0);
9
}
Der counter wird schneller auf 5 gezählt, als Dein Auge den LED-Blitz 
mitkriegen kann!

von Alexander F. (alexander_f25)


Lesenswert?

Peter schrieb:
> Wie und wo hast Du counter deklariert?

Der erste Code, den ich gepostet hatte...
1
volatile uint8_t counter;

Naja die LED sollte komplett erlischen da der Counter ja "voll" ist, 
erst nach loslassen des Tasters würde der Counter wieder auf 0 gesetzt 
werden...

von Alexander F. (alexander_f25)


Lesenswert?

Alexander F. schrieb:
> Naja die LED sollte komplett erlischen

Also in meinen eigentlichen Code sollte der Motor stoppen... in dem 
Beispielcode hier wollt ich auf das IF Statement bezug nehmen.
Hier würde es ja tatsächlich nur kurz blitzen.

von J.-u. G. (juwe)


Lesenswert?

Alexander F. schrieb:
> Ich hatte vorhin eine LED als Ausgang geschalten und diese sollte, nach
> Betätigung eines Tasters und herunterzählen von ca. 1000 Schritten
> deaktiviert werden...
> Es passierte nichts, die LED ging nicht aus. (In der IF Abfrage hatte
> ich PINB verwendet)

1000 Schritte? Mit einem uint8_t?

von Alexander F. (alexander_f25)


Lesenswert?

auf ein neues:
1
#include <avr/io.h>
2
#include <stdint.h>
3
 
4
#define MOTORSTEPS 10000
5
6
volatile int16_t stepCounter;
7
8
int main(void)
9
{
10
  DDRA = 0xff;
11
  DDRD = 0x00;
12
  PORTD = 0xff;
13
  while(1)
14
  {
15
    if(PIND & (1 << PIND1)) {
16
      if(stepCounter < MOTORSTEPS) {
17
        PORTA |= (1 << PA0);
18
        stepCounter++;
19
      }
20
      else {
21
        PORTA &= ~(1 << PA0);
22
      }
23
    }
24
    else {
25
      PORTA &= ~(1 << PA0);
26
      stepCounter = 0;
27
    }
28
  }
29
}

Nach dem Upload auf das STK600 sind seltsamerweise alle Pins am PORTA 
(Ausgang) aktiv. Wenn ich dann PD1 betätige und wieder los lasse 
schaltet sich die LED kurz aus (wahrscheinlich die 10000 schritte lang).

Entferne ich nun das IF Statment "if(stepCounter < MOTORSTEPS)" und 
ersetze es mit einem einfachen "PORTA |= (1 << PA0);" dann läuft alles 
normal, d.h. die LED an PA0 ist von Anfang an aus und wird erst bei 
Betätigung PD1 aktiv...

Was ist hier falsch?

von Karl H. (kbuchegg)


Lesenswert?

Was genau hängt bei dir am PD1?

Dir ist bewusst, dass der Eingangspin vom STK600 mit Taster so 
funktioniert, dass er bei NICHT gedrücktem Taster eine 1 liefert (Bit 
ist gesetzt) und bei gedrücktem Taster dieses Bit eine 0 liefert.

Will man also etwas tun, wenn ein Taster gedrückt ist, dann lautet die 
Abfrage

    if( !(PIND & (1 << PIND1) ) {    // Taster PD1 ist gedrückt

von Alexander F. (alexander_f25)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Dir ist bewusst, dass der Eingangspin vom STK600 mit Taster so
> funktioniert, dass er bei NICHT gedrücktem Taster eine 1 liefert (Bit
> ist gesetzt) und bei gedrücktem Taster dieses Bit eine 0 liefert.

Vielen Dank, das hilft mir ungemein weiter.
War mir leider nicht bewusst...

Kann es auch sein, dass die Ausgangsschaltung verkehrt ist???
PORTA &= ~(1 << PA0) = Ein
PORTA |= (1 << PA0) = Aus

von Karl H. (kbuchegg)


Lesenswert?

Alexander F. schrieb:

> Vielen Dank, das hilft mir ungemein weiter.
> War mir leider nicht bewusst...
>
> Kann es auch sein, dass die Ausgangsschaltung verkehrt ist???
> PORTA &= ~(1 << PA0) = Ein
> PORTA |= (1 << PA0) = Aus

Probiers doch einfach aus
1
int main()
2
{
3
  DDRA = 0xFF;
4
  PORTA = 0b11110000;
5
6
  while( 1 )
7
    ;
8
}

welche LED leuchten? Die bei denen du ein 0-Bit gesetzt hast, oder die 
bei denen du ein 1-Bit gesetzt hast?
Und schon hast du das selber rausgefunden.

von Alexander F. (alexander_f25)


Lesenswert?

Ja, Danke.

Ich hatte gedacht ich hab einen Fehler im Code, anstatt zu wissen dass 
eben diverse Bits hierbei anders zu setzen sind...

von Karl H. (kbuchegg)


Lesenswert?

Alexander F. schrieb:
> Ja, Danke.
>
> Ich hatte gedacht ich hab einen Fehler im Code, anstatt zu wissen dass
> eben diverse Bits hierbei anders zu setzen sind...

Genau aus dem Grund beginnen alle Tutorien hier auf der 
Mikrocontroller-Website damit, dass erst mal einzelne Ausgänge auf 0 
oder 1 gesetzt werden um LED zum Leuchten oder Nicht Leuchten zu 
bringen. Sie sind quasi das "Hallo Welt" der µC Szene mit dem 
Nebeneffekt, dass man rauskriegt was eine 0 oder eine 1 am Ausgabepin 
bewirkt. Es ist ja kein Naturgesetz, dass eine 1 etwas einschalten muss.

Für den "nicht gedrückter Taster liefert eine 1" gibt es allerdings 
einen guten Grund. Im AVR gibt es nur Pullup Widerstände. Pullup 
bedeutet, dass ein offener Eingang damit auf 1 gezogen wird. Ein nicht 
gedrückter Taster ist aber so ein offener Eingang. Erst durch das 
Drücken des Tasters wird der Eingang mit irgend einer Spannung 
verbunden. Wenn ich aber nur einen Pullup habe und damit einen offenen 
Eingang nur auf 1 ziehen kann, dann bleibt für den Taster nicht mehr 
viel übrig als nach GND zu schalten. Und damit liefert dann ein 
gedrückter Taster eine 0 (weil der Taster den Eingang nach Masse 
verbindet) und wenn der Taster nicht gedrückt ist, dann zieht der 
Pullup-Widerstand den Eingang auf 1.

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.