mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Taster Problem


Autor: Vitalij K. (kingvita1989)
Datum:

Bewertung
0 lesenswert
nicht 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;
}
}
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
#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;
    }
  }
}

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.

Autor: Vitalij K. (kingvita1989)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
#include <mega8.h>
#include <delay.h>
#include <stdint.h>

int main (void)
{
  uint8_t TasterJetzt, TasterVorher;
  uint8_t Count;

  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;
  Count = 0;

  while (1)
  {
    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
        Count++;

        // Der wievielte Tastendruck war das jetzt?
        // Der erste?  -> Led einschalten
        // Der zweite? -> Led ausschalten und die Tasterzählung
        //                wieder von vorne beginnen
        if( Count == 1 )
          PORTD.0 = 0;
 
        if( Count == 2 )
        {
          PORTD.0 = 1;
          Count = 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);
  }
}

Autor: Vitalij K. (kingvita1989)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
....

int main( void )
{
  ....
  uint8_t NextLed;
  ....

  NextLed = 0;

  while( 1 )
  {
     ....

     // alle LED mal aus
     PORTD.0 = 1;
     PORTD.1 = 1;
     PORTD.2 = 1;

     // welche LED ist als nächstes drann mit einschalten
     if( NextLed == 0 )
       PORTD.0 = 0;

     else if( NextLed == 1 )
       PORTD.1 = 0;
 
     else if( NextLed == 2 )
       PORTD.2 = 0;

     // und merken, dass im nächsten Schleifendurchlauf die
     // nächste Led drannkommt. Aber aufpassen: Nach der
     // letzten LED muss wieder die erste drann kommen
     NextLed++;
     if( NextLed == 3 )
       NextLed = 0;

     // etwas warten
     delay_ms( 10 );
   }
}

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.

Autor: Vitalij K. (kingvita1989)
Datum:

Bewertung
0 lesenswert
nicht 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);
  }
}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ABgesehen von so manch anderem Problem,
seit wann wird eine LED eingeschaltet, indem man einer
unbeteiligten Variablen etwas zuweist
void main (void)
{
  ...
  uint8_t LED1,LED2,LED3;

  ....

  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
     ....

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!

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#include <mega8.h>
#include <delay.h>
#include <stdint.h>

void main (void)
{
  uint8_t TasterJetzt, TasterVorher;
  uint8_t ZaehlerTaster;
  uint8_t Lauflicht;
  uint8_t ZaehlerLED;

  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;
  Lauflicht = 0;   // Lauflicht ist aus

  PORTD.0 = 1;
  PORTD.1 = 1;
  PORTD.2 = 1;

  while (1)
  {
    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++;

        if( ZaehlerTaster == 1 )
          Lauflicht = 1;   // erster Tastendruck: Lauflicht ein

        if( ZaehlerTaster == 2 )
        {
          Lauflicht = 0;   // zweiter Tastendruck: Lauflicht aus
          ZaehlerTaster = 0;
        }
      }
    }

    TasterVorher = TasterJetzt;
    delay_ms (10);

    // was ist mit dem Lauflicht?
    // gibt es in diesem Durchgang etwas zu tun?
    if( Lauflicht == 1 )
    {
      // mal alle LEDs ausschalten. Die nächste LED wird erst
      // danach abhängig vom Zähler eingeschaltet
      PORTD.0 = 1;
      PORTD.1 = 1;
      PORTD.2 = 1;

      if( ZaehlerLED == 0)
        PORTD.0 = 0;

      else if( ZaehlerLED == 1)
        PORTD.1 = 0;

      else if( ZaehlerLED == 2)
        PORTD.2 = 0;

      delay_ms(100);

      ZaehlerLED++;
      if( ZaehlerLED == 3)
        ZaehlerLED = 0;
    }
  }
}

Autor: David (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: Martin (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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

Autor: Martin (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
mein Modul sieht eigentlich so aus

Gruß

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.