LED mit einem Taster ein- auschalten

OP #640105
Lesenswert?

Hallo,
ich bin noch ein absoluter Anfänger was AVRs angeht und habe schon alle 
Blinkschaltungen durch. Jetzt möchte ich unbedingt eine LED mit nur 
einem Taster ein- und ausschalten. Ich habe aber irgendwie keine 
richtige Idee, alles was ich bis jetzt probiert habe schaltet immer nur 
für die dauer des Tastendrucks ein.
Wäre sehr nett, wenn mir wer helfen könnte.....
Danke !
#640108
Lesenswert?

Hallo!
also ich würd das jetzt erst mal so lösen:
Wenn du den Taster drückst, lasse dein Programm in eine Schleife 
springen in der du die LED anschaltest und warte dann einfach auf den 
nächsten Tastendruck, den du in dieser Schleife gesondert abfängst und 
schalte sie dann wieder aus.

Also ungefähr so:

Schleife 1: Taster gedrückt? wenn ja, zu Schleife 2, wenn nein, zu 1

Schleife 2: LED an, warten ob Taster gedrückt. Wenn nein, schleife 2, 
wenn ja, LED aus und schleife 1.

Ist jetzt nicht die eleganteste Lösung, aber um das erstmal 
hinzubekommen sollte es reichen ;-).
Gast #640150
Lesenswert?

hier mal die oben genannte idee ganz simpel (ohne entprellung), keine 
wirklich gute technik aber damit geht es schonmal (oder sollte ;)).

#define CONTROL  PORTC
#define TASTER  PC0
#define  DISPLAY  PORTB
#define LED  0

volatile int cnt=0;

int main.....
{

while(1) {
  if ((CONTROL & (1 << TASTER)))
    cnt++;

  if(cnt>10) {
    PORTX ^= _BV(PXx);
    cnt=0;
  }
}
OP #640442
Lesenswert?

Tja also irgendwie ist das alles nicht so dolle....
hat jemand eine Idee, wie man das richtig hinbekommt ?
was mache ich falsch ?
Sind die Ports zur ein-/ausgabe richtig definiert ?
Danke !!!


#include <inttypes.h>
#include <avr/io.h>
#include <avr/delay.h>            // definiert _delay_ms()


void main()
{


    DDRB = (1 << DDB0);          // PB0 als Ausgang
    DDRB &= ~(1 << DDB1);        // PB1 als Eingang

{
if (PINB & (1 << PB1))          // wenn PB1 geschlossen (HIGH)

      do
      {
      PORTB = PINB ^ ( 1 << PB0 );  // LED an PB0 umschalten
      PORTB = PORTB | (1 << DDB0);  // LED an PB0 ein
      }
      while (PINB & (1 << PB1))    // wenn PB1 geschlossen (HIGH)

      PORTB = PORTB & ~(1 << DDB0);  // LED aus
}
}
#640495
Lesenswert?

Boriza L. wrote:
> Ich habe das STK500-Board mit einem Tiny45 bestückt und ich habe das
> dumme Gefühl, das ich auf dem absolut falschen Weg bin.
Ja. Beim STK500 ist nämlich genau das der Fall, was ich oben 
angesprochen habe: LEDs sind High-Side und Taster Low-Side 
angeschlossen.

> Ich bin mir auch
> noch nicht sicher ob ich besser in Assembler oder C programmieren soll.
> Ist Bascom wirklich soviel besser als AVR-Studio ???
Bascom ist mit Sicherheit nicht "besser" als "AVRStudio" (wobei ich mal 
vermute, dass Du mit "AVRStudio" C meinst, was aber gar nicht zu 
AVRStudio gehört, sondern nur in Form des AVR-GCC-Plugins in die IDE 
integriert werden kann). Was von beiden Dir eher liegt, musst Du selbst 
entscheiden. Aber die Hardware ist davon unabhängig. Auch in BASCOM 
musst Du einen Pin auf Low schalten, um eine LED am STK500 ans Leuchten 
zu bringen. Für die Taster gilt entsprechendes...
#640518
Lesenswert?

Boriza L. wrote:
> Tja also irgendwie ist das alles nicht so dolle....

definier doch mal 'nicht so dolle....'

> hat jemand eine Idee, wie man das richtig hinbekommt ?
> was mache ich falsch ?

>     DDRB = (1 << DDB0);          // PB0 als Ausgang
>     DDRB &= ~(1 << DDB1);        // PB1 als Eingang

OK

>
> {
> if (PINB & (1 << PB1))          // wenn PB1 geschlossen (HIGH)

Bist du ganz sicher, dass vom Port eine 1 kommt, wenn der
Taster gedrückt wird?
Wie Johannes schon schrieb: Normalerweise ist es umgekehrt.
Der Grundzustand ist 1 und nur wenn ein Taster gedrückt wird,
wechselt der Pin auf 0

>
>       do
>       {
>       PORTB = PINB ^ ( 1 << PB0 );  // LED an PB0 umschalten
>       PORTB = PORTB | (1 << DDB0);  // LED an PB0 ein
>       }
>       while (PINB & (1 << PB1))    // wenn PB1 geschlossen (HIGH)

Du willst wirklich die ganze Zeit, während ein Taster geschlossen
(=gedrückt) ist, den Ausgangsport umschalten? Das wird aber dann
eher ein Zufallsgenerator.
Dir ist schon klar, dass dein AVR je nach Taktfrequenz, die obige
Schleife bei gedrückter Taste ein paar 100-tausendmal in der
Sekunde abarbeitet?

Auch:
  PINx    verwendet man, um den Zustand eines Port-Pins einzulesen,
          wenn dieser Pin als Eingang konfiguriert ist

  PORTx   verwendxet man, um den Zustand eines Port-Pins zu verändern
          oder auch den zuletzt ausgegebenen Zustand wieder einzulesen,
          wenn dieser Pin auf Ausgang konfiguriert ist.

          PORTx wird weiterhin verwendet, um die Pullup Widerstände
          zu konfigurieren, wenn ein Pin auf Eingang konfiguriert
          ist.

Sieh dir nochmal deine Verwendung von PORT und PIN in obiger
Schleife dahingehend durch.
Auch: Für die normalen Port-Operationen Ausgabe und Eingabe werden
  die Pxn (zb. PB0) Makros benutzt um einen bestimmten Pin anzusprechen.
  Nur wenn man auf das entsprechende Konfigurationsregister
  DDRx zugreift, verwendet man die DDxn (zb. DDB0) Makros.
  Macht zwar keinen wirklichen Unterschied, da PB0 denselben
  Zahlenwert wie DDB0 aufweist (nämlich 0), ist aber eine Frage
  der Konsistenz und Sorgfalt.

Was du machen willst ist was anderes:

  mache ewig {
     warte darauf, dass die Taste gedrückt wird
     Schalte den Ausgangsport um
     warte darauf, dass die Taste wieder losgelassen wird.
  }

aber auch das wird 'nicht so dolle' funktionieren, weil Tasten
nun mal prellen. Im allereinfachsten Fall, kann man das Prellen
loswerden, indem nach dem Erkennen des Umschaltens des Tasters
eine kleine Wartezeit eingelegt wird. Für Profi-Anwendungen ist
diese Warterei so meist nicht zu gebrauchen, aber für deine ersten
Schritte ist das schon ok.

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