Forum: Mikrocontroller und Digitale Elektronik Taster Problem


von Vitalij K. (kingvita1989)


Lesenswert?

Hallo Leute!!

Habe folgendes Problem: möchte mit einem Taster ein lauflicht starten 
und dann wieder unterbrechen bzw. die drei leds die als Lauflicht (beim 
ersten betätigen des Tasters)an sind mit dem zweite betätigen des 
Tasters ausmachen.  Bist zum an machen des Lauflichtes mit LED 
funktioniert mein code, jedoch das ausmachen nicht. Wo ist der fehler ? 
Bzw. wie sag ich dem Controller das der taster zum zweiten mal gedrückt 
wurde?



#include <mega8.h>
#include <delay.h>
#include <stdint.h>

void main (void)


{
uint8_t pPortB,test;
pPortB = PINB.0;
pPortB+=2;

test=pPortB;





DDRD = 0xFF; // PORTD als Ausgang
PORTD = 0xFF; //PORTD auf high (5V)
DDRB = 0x00; // PORTB als Eingang
PORTB = 0x01; // Pull up Widerstand aktiv an PORTB.0








while (1)
{

if (PINB.0 == 0)




{

     while (1){
       PORTD.0=0;
       delay_ms (10);
       PORTD.0=1;
       delay_ms (50);
       PORTD.1=0;
       delay_ms (10);
       PORTD.1=1;
       delay_ms (50);
       PORTD.2=0;
       delay_ms (10);
       PORTD.2=1;
       delay_ms (50);
}
}

else
{
PORTD.0 = 1; //LED1 aus
PORTD.1 = 1; //LED2 aus
PORTD.2 = 1; //LED3 aus

}
if (test == 2);
{
PORTD.0 = 1; //LED1
PORTD.1 = 1; //LED2 aus
PORTD.2 = 1; //LED3 aus
break;
}
}
}

von Karl H. (kbuchegg)


Lesenswert?

Du musst anfangen mal einen vernünftigen Programmierstil zu entwickeln!
Dazu gehören vernünftige und konsistente Einrückungen. Auch das
Einfügen von exzessiven Leerzeilen-Blöcken trägt nicht wirklich
zur Übersicht bei. Im Gegenteil, dadurch daß der Code nur unnötig
in die Länge gezogen wird, leidet die Übersicht.

Dein Code mal etwas umformatiert
1
#include <mega8.h>
2
#include <delay.h>
3
#include <stdint.h>
4
5
void main (void)
6
{
7
  uint8_t pPortB,test;
8
9
  pPortB = PINB.0;
10
  pPortB += 2;
11
12
  test = pPortB;
13
14
  DDRD  = 0xFF; // PORTD als Ausgang
15
  PORTD = 0xFF; //PORTD auf high (5V)
16
  DDRB  = 0x00; // PORTB als Eingang
17
  PORTB = 0x01; // Pull up Widerstand aktiv an PORTB.0
18
19
  while (1)
20
  {
21
    if (PINB.0 == 0)
22
    {
23
      while (1)
24
      {
25
        PORTD.0=0;
26
        delay_ms (10);
27
        PORTD.0=1;
28
        delay_ms (50);
29
        PORTD.1=0;
30
        delay_ms (10);
31
        PORTD.1=1;
32
        delay_ms (50);
33
        PORTD.2=0;
34
        delay_ms (10);
35
        PORTD.2=1;
36
        delay_ms (50);
37
      }
38
    }
39
    else
40
    {
41
      PORTD.0 = 1; //LED1 aus
42
      PORTD.1 = 1; //LED2 aus
43
      PORTD.2 = 1; //LED3 aus
44
    }
45
46
    if (test == 2)
47
      ;
48
    {
49
      PORTD.0 = 1; //LED1
50
      PORTD.1 = 1; //LED2 aus
51
      PORTD.2 = 1; //LED3 aus
52
      break;
53
    }
54
  }
55
}

Und jetzt gehst du mal zu deinem Lauflichtcode und siehst dir
die umgebende Kontrollstruktur darin an. Wenn du das tust, dann
findest du, dass dieser LED-Blink Code in einer while(1) Schleife
eingebettet ist, also einer Endlosschleife. Sobald die Programm-
ausführung da drin angelangt ist, kommt sie nie wieder raus.

PS: Der Strichpunkt beim Test von test auf 2 war wahrscheinlich
so nicht gewollt. Trotzdem ist er drinnen und sorgt so dafür,
daß der nachfolgende Programmblock nicht unter Kontrolle des
if steht.

von Vitalij K. (kingvita1989)


Lesenswert?

hmm leider hab ich immer noch keine ahnung wie ich dem controller 
mitteilen soll das der taster zum zweiten mal gedrpckt wurde hat einer 
ein beispiel code oder ne idee?

von Karl H. (kbuchegg)


Lesenswert?

Vitalij K. wrote:
> hmm leider hab ich immer noch keine ahnung wie ich dem controller
> mitteilen soll das der taster zum zweiten mal gedrpckt wurde hat einer
> ein beispiel code oder ne idee?

Das Problem ist das Erkennen eines Tastendrucks. Das ist zunächst
mal ziemlich schwierig, weil dir da die Hardware unter Umständen
einen Strich durch die Rechnung macht: Taster prellen. D.h. was
du als einmaligen Tastendruck empfindest, sieht für den µC so
aus als ob der Taster in kurzer Zeit ein paar mal gedrückt und
wieder losgelassen wird. Und Entprellen eines Tasters ist,
wenn man es gut machen will, gar nicht so einfach.

Aber seis drum.
Einen Tastendruck erkennt man daran, dass man einen Flankenwechsel
erkennen muss. D.h. Der Taster wechselt den Eingansgpegel von
1 auf 0. Und es ist nur diese Änderung die dich interessiert,
nicht das der Pegel jetzt dauernd auf 0 ist. Du musst also in
einer Variablen den Zustand des Einganspins speichern um im
nächsten Schleifendurchlauf erkennen zu können, ob sich der
Pegel verändert hat.

Probier mal das hier aus
1
#include <mega8.h>
2
#include <delay.h>
3
#include <stdint.h>
4
5
int main (void)
6
{
7
  uint8_t TasterJetzt, TasterVorher;
8
  uint8_t Count;
9
10
  DDRD  = 0xFF; // PORTD als Ausgang
11
  PORTD = 0xFF; // PORTD auf high (5V)
12
  DDRB  = 0x00; // PORTB als Eingang
13
  PORTB = 0x01; // Pull up Widerstand aktiv an PORTB.0
14
15
  TasterVorher = 1;
16
  Count = 0;
17
18
  while (1)
19
  {
20
    TasterJetzt = PINB.0;    // den jetzigen Zustand des Tasters feststellen
21
22
    if( TasterJetzt != TasterVorher )   // gibt es einen Unterschied?
23
    {
24
      // Der Unterschied kann jetzt beides bedeuten:
25
      // Taster wurde gedrückt   oder
26
      // Taster wurde losgelassen
27
      // Wir sind nur am Fall 'Taster gedrückt' interessiert
28
      // Wenn der Taster aber gedrückt wurde, dann muss TasterJetzt
29
      // aber den Wert 0 haben
30
31
      if( TasterJetzt == 0 )
32
      {
33
        // mitzählen wie oft die Taste gedrückt wurde
34
        Count++;
35
36
        // Der wievielte Tastendruck war das jetzt?
37
        // Der erste?  -> Led einschalten
38
        // Der zweite? -> Led ausschalten und die Tasterzählung
39
        //                wieder von vorne beginnen
40
        if( Count == 1 )
41
          PORTD.0 = 0;
42
 
43
        if( Count == 2 )
44
        {
45
          PORTD.0 = 1;
46
          Count = 0;
47
        }
48
      }
49
    }
50
51
    // den jetzigen Zustand des Tasters als den vorhergehenden
52
    // merken, damit beim nächsten Abfragen des Tasters damit
53
    // verglichen werden kann und ein Wechsel detektiert werden kann
54
    TasterVorher = TasterJetzt;
55
56
    // etwas warten um das Tastenprellproblem etwas zu entschärfen
57
    delay_ms (10);
58
  }
59
}

von Vitalij K. (kingvita1989)


Lesenswert?

viele dank geht jetzt versuche jetz den code nachzu vollziehen...sonst 
meld ich mich noch mal bei dir Karl heinz Buchegger

von Karl H. (kbuchegg)


Lesenswert?

Gut.
bedenke immer, ich muss blind programmieren, da ich nicht deinen
Compiler habe.

Zu deinem Lauflicht:
Du musst von der Vorstellung weg, dass du einen Codeblock
hast, in dem ständig eine LED nach der anderen ein/aus
geschaltet wird.

Stattdessen musst du das in der Hauptschleife machen.
Dazu benutzt du eine weitere Variable, die dir anzeigt
welche LED als nächstes einzuschalten ist. Diese Variable
wird dann laufend erhöht.

Ungefähr so
1
....
2
3
int main( void )
4
{
5
  ....
6
  uint8_t NextLed;
7
  ....
8
9
  NextLed = 0;
10
11
  while( 1 )
12
  {
13
     ....
14
15
     // alle LED mal aus
16
     PORTD.0 = 1;
17
     PORTD.1 = 1;
18
     PORTD.2 = 1;
19
20
     // welche LED ist als nächstes drann mit einschalten
21
     if( NextLed == 0 )
22
       PORTD.0 = 0;
23
24
     else if( NextLed == 1 )
25
       PORTD.1 = 0;
26
 
27
     else if( NextLed == 2 )
28
       PORTD.2 = 0;
29
30
     // und merken, dass im nächsten Schleifendurchlauf die
31
     // nächste Led drannkommt. Aber aufpassen: Nach der
32
     // letzten LED muss wieder die erste drann kommen
33
     NextLed++;
34
     if( NextLed == 3 )
35
       NextLed = 0;
36
37
     // etwas warten
38
     delay_ms( 10 );
39
   }
40
}

Und jetzt liegt es an dir, die beiden Teile: Tastendrücke
und Lauflicht, miteinander zu verbinden. Ich würde dazu eine
weitere Variable benutzen, die mir anzeigt, ob das Lauflicht
ein oder ausgeschaltet ist. Der Tastencode setzt diese Variable
entsprechend und der Lauflichtcode wird vom Inhalt dieser
Variablen abhängig gemacht.

von Vitalij K. (kingvita1989)


Lesenswert?

Habe entlich wieder Zeit gefunden meine C-Kenntnisse zu erweitern und an 
dem Lauflicht zu programmieren. Leider nicht vom Erfolg gekrönt was mach 
ich falsch hier der code:

#include <mega8.h>
#include <delay.h>
#include <stdint.h>

void main (void)
{
  uint8_t TasterJetzt, TasterVorher;
  uint8_t ZaehlerTaster;
  uint8_t ZaehlerLED;
  uint8_t LED1,LED2,LED3;

  DDRD  = 0xFF; // PORTD als Ausgang
  PORTD = 0xFF; //PORTD auf high (5V)
  DDRB  = 0x00; // PORTB als Eingang
  PORTB = 0x01; // Pull up Widerstand aktiv an PORTB.0

  TasterVorher = 1;
  ZaehlerTaster = 0;
  ZaehlerLED = 0;
  LED1 = PORTD.0;
  LED2 = PORTD.1;
  LED3 = PORTD.2;

  while (1)
  {
     LED1 = 1;  // LED1 (grün) aus
     LED2 = 1;  // LED2 (gelb) aus
     LED3 = 1;  // LED3 (rot) aus

    TasterJetzt = PINB.0;    // den jetzigen Zustand des Tasters 
feststellen
    if( TasterJetzt != TasterVorher )   // gibt es einen Unterschied?
    {
      // Der Unterschied kann jetzt beides bedeuten:
      // Taster wurde gedrückt   oder
      // Taster wurde losgelassen
      // Wir sind nur am Fall 'Taster gedrückt' interessiert
      // Wenn der Taster aber gedrückt wurde, dann muss TasterJetzt
      // aber den Wert 0 haben

      if( TasterJetzt == 0 )
      {
        // mitzählen wie oft die Taste gedrückt wurde
        ZaehlerTaster++;

        // Der wievielte Tastendruck war das jetzt?
        // Der erste?  -> Led einschalten
        // Der zweite? -> Led ausschalten und die Tasterzählung
        //                wieder von vorne beginnen
        if( ZaehlerTaster == 1 )

          if( ZaehlerLED == 0)
          {
          LED1 = 0;
          delay_ms (100);
          LED1 = 1;
          }
          if( ZaehlerLED == 1)
          {
          LED2 = 0;
          delay_ms (100);
          LED2=1;
          }
          if( ZaehlerLED == 2)
          {
          LED3 = 0;
          delay_ms(100);
          LED3 = 1;
          ZaehlerLED++;
          if( ZaehlerLED == 3)
          {
          ZaehlerLED = 0;
          }
          }

         if( ZaehlerTaster == 2 )
        {
          PORTD.0 = 1;
          PORTD.1 = 1;
          PORTD.2 = 1;
          ZaehlerTaster = 0;
        }
      }
    }

    // den jetzigen Zustand des Tasters als den vorhergehenden
    // merken, damit beim nächsten Abfragen des Tasters damit
    // verglichen werden kann und ein Wechsel detektiert werden kann
    TasterVorher = TasterJetzt;

    // etwas warten um das Tastenprellproblem etwas zu entschärfen
    delay_ms (10);
  }
}

von Karl H. (kbuchegg)


Lesenswert?

ABgesehen von so manch anderem Problem,
seit wann wird eine LED eingeschaltet, indem man einer
unbeteiligten Variablen etwas zuweist
1
void main (void)
2
{
3
  ...
4
  uint8_t LED1,LED2,LED3;
5
6
  ....
7
8
  LED1 = PORTD.0;
9
  LED2 = PORTD.1;
10
  LED3 = PORTD.2;
11
12
  while (1)
13
  {
14
     LED1 = 1;  // LED1 (grün) aus
15
     LED2 = 1;  // LED2 (gelb) aus
16
     LED3 = 1;  // LED3 (rot) aus
17
     ....

Nach der Zuweisung

   LED1 = PORTD.0;

ist LED1 nicht gleichbedeutend mit PORTD.0
LED1 bekommt den Wert von PORTD.0, aber LED1 und PORTD.0
sind auch danach 2 völlig voneinander verschiedene Dinge!

Wenn du eine LED ein oder ausschalten willst, dann musst du
schon etwas an PORTD.0 zuweisen!

von Karl H. (kbuchegg)


Lesenswert?

1
#include <mega8.h>
2
#include <delay.h>
3
#include <stdint.h>
4
5
void main (void)
6
{
7
  uint8_t TasterJetzt, TasterVorher;
8
  uint8_t ZaehlerTaster;
9
  uint8_t Lauflicht;
10
  uint8_t ZaehlerLED;
11
12
  DDRD  = 0xFF; // PORTD als Ausgang
13
  PORTD = 0xFF; // PORTD auf high (5V)
14
  DDRB  = 0x00; // PORTB als Eingang
15
  PORTB = 0x01; // Pull up Widerstand aktiv an PORTB.0
16
17
  TasterVorher = 1;
18
  ZaehlerTaster = 0;
19
  ZaehlerLED = 0;
20
  Lauflicht = 0;   // Lauflicht ist aus
21
22
  PORTD.0 = 1;
23
  PORTD.1 = 1;
24
  PORTD.2 = 1;
25
26
  while (1)
27
  {
28
    TasterJetzt = PINB.0;    // den jetzigen Zustand des Tasters feststellen
29
    if( TasterJetzt != TasterVorher )   // gibt es einen Unterschied?
30
    {
31
      // Der Unterschied kann jetzt beides bedeuten:
32
      // Taster wurde gedrückt   oder
33
      // Taster wurde losgelassen
34
      // Wir sind nur am Fall 'Taster gedrückt' interessiert
35
      // Wenn der Taster aber gedrückt wurde, dann muss TasterJetzt
36
      // aber den Wert 0 haben
37
38
      if( TasterJetzt == 0 )
39
      {
40
        // mitzählen wie oft die Taste gedrückt wurde
41
        ZaehlerTaster++;
42
43
        if( ZaehlerTaster == 1 )
44
          Lauflicht = 1;   // erster Tastendruck: Lauflicht ein
45
46
        if( ZaehlerTaster == 2 )
47
        {
48
          Lauflicht = 0;   // zweiter Tastendruck: Lauflicht aus
49
          ZaehlerTaster = 0;
50
        }
51
      }
52
    }
53
54
    TasterVorher = TasterJetzt;
55
    delay_ms (10);
56
57
    // was ist mit dem Lauflicht?
58
    // gibt es in diesem Durchgang etwas zu tun?
59
    if( Lauflicht == 1 )
60
    {
61
      // mal alle LEDs ausschalten. Die nächste LED wird erst
62
      // danach abhängig vom Zähler eingeschaltet
63
      PORTD.0 = 1;
64
      PORTD.1 = 1;
65
      PORTD.2 = 1;
66
67
      if( ZaehlerLED == 0)
68
        PORTD.0 = 0;
69
70
      else if( ZaehlerLED == 1)
71
        PORTD.1 = 0;
72
73
      else if( ZaehlerLED == 2)
74
        PORTD.2 = 0;
75
76
      delay_ms(100);
77
78
      ZaehlerLED++;
79
      if( ZaehlerLED == 3)
80
        ZaehlerLED = 0;
81
    }
82
  }
83
}

von David (Gast)


Lesenswert?

davon ausgehend das der undleserliche code am anfang frei von 
syntaxfehlern ist versuch folgendes (ist absolut unsauber 
programmiert!!!)


#include <mega8.h>
#include <delay.h>
#include <stdint.h>

void main (void)


{
uint8_t pPortB,test, hilfsvariable;
pPortB = PINB.0;
pPortB+=2;

test=pPortB;


DDRD = 0xFF; // PORTD als Ausgang
PORTD = 0xFF; //PORTD auf high (5V)
DDRB = 0x00; // PORTB als Eingang
PORTB = 0x01; // Pull up Widerstand aktiv an PORTB.0

hilfsvariable = 1;

while (1)
{
if (PINB.0 == 0)
hilfsvariable = 1;
{

     while (hilfsvariable == 1){
       PORTD.0=0;
       delay_ms (10);
       PORTD.0=1;
       delay_ms (50);
       PORTD.1=0;
       delay_ms (10);
       PORTD.1=1;
       delay_ms (50);
       PORTD.2=0;
       delay_ms (10);
       PORTD.2=1;
       delay_ms (50);

       if (PINB.0 == 1)
       (
            hilfsvariable = 0;
       )

}
}

else
{
PORTD.0 = 1; //LED1 aus
PORTD.1 = 1; //LED2 aus
PORTD.2 = 1; //LED3 aus

}
if (test == 2);
{
PORTD.0 = 1; //LED1
PORTD.1 = 1; //LED2 aus
PORTD.2 = 1; //LED3 aus
break;
}
}
}

wird funktionieren, aber wie gesagt, pfuschig programmiert (war zu faul 
dir das sauber zu machen...
versuchs, und als nächerster schritt würde ich empfehlen dies mit einer 
schrittkette zu lösen (switch, case)

von Martin (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Karl heinz,

vielleichts kannst du mir auch helfen!
bin Afänger und soll zu sagen habe einiege Kapitel von Tutorial 
"bestanden".

mein Problem:

mein Testboard hat 2 Taster die ich beliebig benutzen kann, wenn ich die 
Taster benutzen will Aktiviere ich die "Pull ups" und und funktioniert 
ganz gut.
Nun habe ich ein "Externe Taster Modul" (??) wie im Anhang gelötet also 
mit 10K als vorwiderstand oder als Pull up es bedeutet jetzt brauche ich 
die interne Pull up von controller NICHT mehr oder????

Frage 1:
Wenn ich im Code "kein Pull up" aktiviere funktioniert mein Modul nicht, 
aktiviere ich die Pull up dann funktioniert! warum?

Frage 2: brauche ich überhaupt die "externe" widerstand, ist sowas 
Sinnvoll?

vielen Dank für die Hilfe
Gruß
Martin

von Martin (Gast)


Angehängte Dateien:

Lesenswert?

mein Modul sieht eigentlich so aus

Gruß

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.