Forum: Mikrocontroller und Digitale Elektronik Problem bei Programm mit Taster und LED


von Tim (Gast)


Lesenswert?

Hallo Gemeinde,

ich bin blutiger Anfänger und habe daher einen für die meisten 
wahrscheinlich einfaches Problem. Ich hoffe aber, dass ihr mit helfen 
könnt/wollt.

Ich möchte nur ein einfaches Programm schreiben mit zwei Tastern und 
zwei LED`s.
Die eine LED soll "selbst" gehalten werden und die andere jeweils beim 
Tastendruck an gehen und anschließend wieder aus gehen.
Allerdings ist einer der LED`s von Beginn an, an und bei der anderen tut 
sich garnichts. Könntet Ihr bitte mal über meine Code rüber schauen und 
mit vllt verraten was ich dort falsch gemacht habe. Ich komme schon seit 
Tagen einfach nicht mehr weiter.

Vielen Dank im Vorfeld.
1
#define F_CPU 8000000
2
#include <avr/io.h>
3
4
#include <avr/delay.h>
5
6
int main(void)
7
{
8
  
9
  DDRB |=(1<<PB6); // PB 6 Ausgang 
10
  DDRB |=(1<<PB7); // PB7 Ausgang
11
  DDRD &=~ (1<<PD2); //PD 2 Eingang (Taster) 
12
  PORTD = (1<<PD2); // Pullup ein 
13
  DDRD &=~ (1<<PD3); //PD 3 Eingang (Taster) 
14
  PORTD = (1<<PD3); // Pullup ein
15
    
16
    while(1)
17
    {
18
  
19
  if((PIND & (1<<PD3))==0)
20
  
21
  {
22
    _delay_ms(50);
23
    
24
    
25
    
26
    if((PIND & (1<<PD3))==0)
27
    {
28
    PORTB |=(1<<PB7);
29
    }
30
    else 
31
    {
32
      PORTB &=~(1<<PB7);
33
    }
34
  }
35
36
  if((PIND & (1<<PD2))==0)
37
  
38
  {
39
    _delay_ms(50);
40
  
41
    if((PIND & (1<<PD2))==0)
42
    {
43
      
44
      PORTB ^=(1<<PB6);
45
    }
46
   while((PIND & (1<<PD2))==0);        
47
  }
48
  
49
  
50
    
51
  }
52
    
53
  }

: Bearbeitet durch User
von Rene H. (ballibou77)


Lesenswert?

Hi,
1
#define F_CPU 8000000
2
#include <avr/io.h>
3
#include <avr/delay.h>
4
5
#define TASTER1_DDR DDRD
6
#define TASTER2_DDR DDRD
7
#define TASTER1_PIN PD2
8
#define TASTER2_PIN PD3
9
#define TASTER1_PORT PORTD
10
#define TASTER2_PORT PORTD
11
#define TASTER1_PIND PIND
12
#define TASTER2_PIND PIND
13
14
#define LED1_DDR DDRB
15
#define LED2_DDR DDRB
16
#define LED1_PIN PB6
17
#define LED2_PIN PB7
18
#define LED1_PORT PORTB
19
#define LED2_PORT PORTB
20
21
int onoff_var = 0;
22
23
LED1_PORT &= ~(1<<LED1_PIN); // schalte LED1 Aus
24
LED2_PORT &= ~(1<<LED2_PIN); // schalte LED2 Aus
25
26
inline uint8_t debounce(volatile uint8_t *port, uint8_t pin)
27
{
28
    if ( !(*port & (1 << pin)) )
29
    {
30
        /* Pin wurde auf Masse gezogen, 100ms warten   */
31
        _delay_ms(50);   // Maximalwert des Parameters an _delay_ms 
32
        _delay_ms(50);   // beachten, vgl. Dokumentation der avr-libc
33
        if ( *port & (1 << pin) )
34
        {
35
            /* Anwender Zeit zum Loslassen des Tasters geben */
36
            _delay_ms(50);
37
            _delay_ms(50); 
38
            return 1;
39
        }
40
    }
41
    return 0;
42
}
43
int main(void)
44
{
45
46
  LED1_DDR |=(1<<LED1_PIN); // PB 6 Ausgang
47
  LED2_DDR |=(1<<LED2_PIN); // PB7 Ausgang
48
  TASTER1_DDR &=~ (1<<TASTER1_PIN); //PD 2 Eingang (Taster)
49
  TASTER1_PORT = (1<<TASTER1_PIN); // Pullup ein
50
  TASTER2_DDR &=~ (1<<TASTER2_PIN); //PD 3 Eingang (Taster)
51
  TASTER2_PORT = (1<<TASTER2_PIN); // Pullup ein
52
53
while(1)
54
 {
55
    if (debounce(&TASTER1_PIND, TASTER1_PIN)) { // Taster 1 entprellen
56
      if (onoff_var == 0) { onoff_var = 1; } // setze LED Zustand auf 1 wenn 0 war
57
      if (onoff_var == 1) { onoff_var = 0; } // setze LED Zustand auf 0 wenn 1 war
58
    }
59
60
    if (debounce(&TASTER2_PIND, TASTER2_PIN)) { // Taster 2 entprellen
61
      LED2_PORT |= (1<<LED2_PIN); // LED 2 einschalten
62
      _delay_ms(1000); // 1 sek warten
63
      LED2_PORT &= ~(1<<LED2_PIN); // LED2 wieder ausschalten
64
    }
65
66
    if (onoff_var == 1)
67
      {
68
        LED1_PORT |= (1<<LED1_PIN); // schalte LED1 ein wenn Zustand 1 ist
69
      }
70
      else
71
      {
72
        LED1_PORT &= ~(1<<LED1_PIN); // schalte LED1 aus wenn Zustand 0 ist
73
      }
74
 }
75
}

Musst nur noch oben die defines richtig einsetzen.

Ich möchte dir nicht das ganze C vorkauen. Guck dir die unterschiede im 
Code an und versuche sie zu verstehen. Ist eigentlich ganz simpel, in 
ein paar minuten geschrieben und funktioniert ;) (gerade mal getestet)

Die Taster werden entprellt. Wenn du nun den Taster an der LED drückst 
die nur kurz eingeschaltet werden soll dann geht die LED an, der µC 
wartet 1 sek (1000ms) und schaltet die LED wieder aus.

Bei der anderen LED setzt er jeweils die Zustand in die onoff_var. Diese 
ist von Start an 0. Wenn du nun den Taster drückst wird diese auf 1 
gesetzt. Steht dort bereits 1 drinne wird, wenn du den Taster wieder 
drückt dort eine 0 rein geschrieben usw. Am ende des Codes wird dann 
geschaut was in der variable steht. Steht dort eine 1 wird die LED 
eingeschaltet / bleibt eingeschaltet. Steht dort eine 0 wird die LED 
ausgeschaltet / bleibt ausgeschaltet.

: Bearbeitet durch User
von Michael B. (laberkopp)


Lesenswert?

Tim schrieb:
> DDRD &=~ (1<<PD2); //PD 2 Eingang (Taster)
>   PORTD = (1<<PD2); // Pullup ein
>   DDRD &=~ (1<<PD3); //PD 3 Eingang (Taster)
>   PORTD = (1<<PD3); // Pullup ein

Der ist ja wohl falsch, macht dir deimem PD2 pull up kaputt.

> if((PIND & (1<<PD3))==0)
>
>   {
>     _delay_ms(50);
>
>     if((PIND & (1<<PD3))==0)
>     {
>     PORTB |=(1<<PB7);
>     }
>     else
>     {
>       PORTB &=~(1<<PB7);
>     }
>   }

Lass die doppelte Abfrage und den Delay-Kram in diesem Fall weg. Du 
prüfst nur wenn der Tasteneingang gedrückt ist, ob er gleich danach 
immer noch gedrückt ist und schaltet nur in dem unwahrscheinlichen Fall 
daß er prellt und nicht mehr gedrückt ist, wieder aus.

>
>   if((PIND & (1<<PD2))==0)
>
>   {
>     _delay_ms(50);
>
>     if((PIND & (1<<PD2))==0)
>     {
>
>       PORTB ^=(1<<PB6);
>     }
>    while((PIND & (1<<PD2))==0);
>   }

Das ist Murks. Die while Schleife wartet bis der Taster losgelassen 
wird, aber er kann dabei genau so prellen wie beim runterdrücken.

Insgesamt ist die Form der Entprellung eher murksig. Du behandelst 
runterdrücken und loslassen unterschiedlich. Das ist physikalischer 
Unsinn. Ausserdem verbrätst du 10 mal mehr Programm als nötig.

von Tim L. (tim1407)


Lesenswert?

Vielen Dank für die schnellen Antworten. Ich werde am We versuchen dort 
durch zu steigen.

Aber kurze Frage: Wieso mache ich mir mit diesem Code den Pull-Up kaputt
?

von Karl H. (kbuchegg)


Lesenswert?

Weil eine einfache Zuweisung an einen Port ALLE Bits neu setzt.
Wenn du also schreibst
1
PORTD = (1<<PD3); // Pullup ein
was passiert dann mit dem Bit PD2?

von Stefan F. (Gast)


Lesenswert?

> PORTD = (1<<PD2);
> PORTD = (1<<PD3);

Das ergibt aufgelöst in Bits:

PORTD = 0b00000100;
PORTD = 0b00001000;

Also ist danach nur ein Pull-Up eingeschaltet, nämlich der von PD3. 
Richtig geht es so:

> PORTD |= (1<<PD2);
> PORTD |= (1<<PD3);

Initial ist PORTD auf 0b00000000.

PORTD = PORTD | 0b00000100;
PORTD = PORTD | 0b00001000;

Danach hat PORTD den Wert 0b00001100.

von Marc V. (Firma: Vescomp) (logarithmus)


Lesenswert?

Stefan U. schrieb:
> Richtig geht es so:
>
>> PORTD |= (1<<PD2);
>> PORTD |= (1<<PD3);

    PORTD |= (1<<PD2) | (1<<PD3);

von Tim L. (tim1407)


Lesenswert?

ahhhh ich verstehe.

super, danke für die schnelle und vor allem nutzbare Hilfe .

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.