IF Statement

OP #2436495
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.
#2436514
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é
OP #2436558
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?
Gast #2436586
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.
OP #2436599
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
Gast #2436619
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!
OP #2437035
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?
#2437066
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
OP #2437192
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
#2437204
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.
#2437218
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren