Forum: Mikrocontroller und Digitale Elektronik Problem bei Programmierung


von Daniel H. (daniel_fh)


Lesenswert?

Hallo Leute,
ich habe ein kleines Problem. Bin Anfänger in Sachen AVR µC. 
Programmiere in C, hab selbst schon ein paar kleine "Progrämmchen" 
geschrieben. Nur komm ich momentan nicht weiter, obwohl die Funktion 
einfach sein sollte. Also, ich moöchte mit nur einem Taster jeweils 1 
LED an zwei Ausgäng schalten und zwar immer in dieser Reihenfolge:
(Tb = Taster betätigen, Taster z.B an PD0)

Tb --> PB0 = 1 , Tb --> PB0 = 0 , Tb --> PB1 = 1 , Tb --> PB1 = 0 ,
und wieder von vorne beginnen...

Hoffe mal von euch weis jemand Rat, ich komme einfach nicht drauf.
Danke schon einmal Voraus für eure Bemühungen.

von Tony R. (tony)


Lesenswert?

So ganz ohne Code kann ich dein Problem nicht erkennen... Oder hakt es 
schon bei der Umsetzungsidee?

von Karl H. (kbuchegg)


Lesenswert?

Ich denke es handelt sich wieder mal um das übliche 'Wie erkenne ich 
einen Tastendruck' anstelle des 'die Taste ist momentan gerade gedrückt' 
Problems.

Und die Antwort darauf führt über die Entprellung:
http://www.mikrocontroller.net/articles/Entprellung#Komfortroutine_.28C_f.C3.BCr_AVR.29

von Daniel H. (daniel_fh)


Lesenswert?

Naja...
Mehr oder weniger, hab schon ein paar Sachen ausprobiert...

#include <avr/io.h>

#ifndef F_CPU
#define F_CPU 8e6
#endif
#include <util/delay.h>

/****************************************************/
/*                                                  */
/*  Not so powerful Debouncing Macro                */
/*  No Interrupt needed                             */
/*                                                  */
/*  Author: Peter Dannegger                         */
/*                                                  */
/****************************************************/

// Modification for active high push button

#define debounce( port, pin )                                        \
({                                                                   \
  static uint8_t flag = 0; /* new variable on every macro usage */   \
  uint8_t i = 0;                                                     \
                                                                     \
  if( flag ){                  /* check for key release: */          \
    for(;;){                   /* loop... */                         \
      if( (port & 1<<pin) ){   /* ... until key pressed or ... */    \
        i = 0;                 /* 0 = bounce */                      \
        break;                                                       \
      }                                                              \
      _delay_us( 98 );         /* * 256 = 25ms */                    \
      if( --i == 0 ){          /* ... until key >25ms released */    \
        flag = 0;              /* clear press flag */                \
        i = 0;                 /* 0 = key release debounced */       \
        break;                                                       \
      }                                                              \
    }                                                                \
  }else{                       /* else check for key press: */       \
    for(;;){                   /* loop ... */                        \
      if( !(port & 1<<pin) ){  /* ... until key released or ... */   \
        i = 0;                 /* 0 = bounce */                      \
        break;                                                       \
      }                                                              \
      _delay_us( 98 );         /* * 256 = 25ms */                    \
      if( --i == 0 ){          /* ... until key >25ms pressed */     \
        flag = 1;              /* set press flag */                  \
        i = 1;                 /* 1 = key press debounced */         \
        break;                                                       \
      }                                                              \
    }                                                                \
  }                                                                  \
  i;                           /* return value of Macro */           \
})

/*
  Debouncing Example
*/



void ausgang1(void)
{
  if( debounce( PIND, PD0 ) )
    {
     PORTB ^= 1<<PB0; // Toggle @PB0
    }


int main(void)
{
  // PD0 als Eingang
  DDRD &= ~(1<<PD0);
  PORTD |= (1<<PD0); // not needed because active high

  // Jeder Pin ist Ausgang
  DDRB = 0xFF;

  ausgang1();
}

Das Programm zum entprellen is hier vom Forum.
Im Moment Toggelt der Ausgang nur. Weis nicht wie ich weiter schreiben 
soll um den Ausgang zwei anzusprechen...
Wollte die beiden Ausgänge jeweils in 2 Funktionen packen, oder ist das 
schon zu aufwendig?

von dsgbn (Gast)


Lesenswert?

Du brauchst eine Variable, die enthaelt:
entweder was zuletzt ausgeschaltet wurde
oder was als naechstes eingeschaltet werden soll.

Gast

von Klaus W. (mfgkw)


Lesenswert?

unabhängig von einem MC könnte es etwa so aussehen:
1
#include <stdio.h>
2
#include <stdint.h>
3
#include <stdlib.h>
4
5
6
// Dummyfunktion:
7
void holeTastendruck()
8
{
9
  sleep( 1 );
10
}
11
12
int main( )
13
{
14
  // zustand wird jeweils um 1 weiter gezählt, nach 4 Zuständen geht
15
  // es wieder vorne los:
16
  uint8_t   zustand = 0;
17
18
  while( 1 )
19
  {
20
    switch( zustand )
21
    {
22
      case 0:
23
        printf( "PB0 = 0 PB1 = 0\n" );
24
        break;
25
26
      case 1:
27
        printf( "PB0 = 1 PB1 = 0\n" );
28
        break;
29
30
      case 2:
31
        printf( "PB0 = 0 PB1 = 0\n" );
32
        break;
33
34
      case 3:
35
        printf( "PB0 = 0 PB1 = 1\n" );
36
        break;
37
38
      default :
39
        // kommt nie vor
40
        break;
41
    }
42
43
    // Tastendruck holen:
44
    holeTastendruck();
45
46
    zustand++;
47
    zustand %= 4;
48
49
  }
50
51
  return 0;
52
}

Statt holeTastendruck() musst du halt deine Variante einbauen
um die Taste zu erkennen, und statt der printf-Ausgaben deine
Ausgänge passend setzen.

von Peter D. (peda)


Lesenswert?

Sowas nennt sich Statemaschine:
1
uint8_t state = 0;
2
for(;;){
3
  if( debounce( PIND, 0 ))
4
    state++;
5
  switch( state ){
6
    case 1:  PORTB |= 1<<PB0; break;
7
    case 2:  PORTB &= ~(1<<PB0); break;
8
    case 3:  PORTB |= 1<<PB1; break;
9
    default: state = 0;
10
             PORTB &= ~(1<<PB1); break;
11
  }
12
}


Peter

von Klaus W. (mfgkw)


Lesenswert?

Man könnte auch Zustandsautomat sagen:
1
...
2
  uint8_t   zustand = 0;
3
...

:-)

von Daniel H. (daniel_fh)


Lesenswert?

Okay...
Vielen Dank für eure schnelle Hilfe!!!

Probier das gleich mal aus, bin mal gespannt ob ichs hingrieg...
Also, nochmal Danke!

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.