Forum: Compiler & IDEs ATMega 8 Pin als Eingang und Ausgang


von Matthias F. (idefix)


Lesenswert?

Hi,

ich habe hier ein kleines Problem. Ich habe ab einem Pin einen Schalter 
und ein LED hängen. Wenn ich jetzt den Schalter drücke soll er das beim 
einlesen registrieren und der setzt dann den Port so, das das LED 
leuchtet.
Bei erneuten drücken soll es wieder aus gehen. Der Status ob das Led an 
ist oder nicht wird in einer Variable gespeichert.

Leider hab ich da meine Probleme und es will einfach nicht klappen, hab 
den folgenden Code:
[c]
     DDRB &= ~(1<<PROGBUTTON);
     PORTB &= ~(1<<PROGBUTTON);
     for(i=0;i<5;i++)
          _NOP();

     // check if programming button is pressed
     if(!(PINB & (1<<PROGBUTTON)))
     {
          // wait until button is released
          while(!(PINB & (1<<PROGBUTTON)));
          if(mode & (1<<SS_PROG))
          {
               DEBUG_PUTS("Prog Mode off ");
               mode &= ~(1<<SS_PROG);
          }else
          {
               DEBUG_PUTS("Prog Mode on ");
               mode |= (1<<SS_PROG);

          }
     }

     // intermediate state, necessary to switch between input/output
     DDRB &= ~(1<<PROGBUTTON);
     PORTB |= (1<<PROGBUTTON);

     // set pin to represent progmode
     if(mode & (1<<SS_PROG))
          PORTB &= ~(1<<PROGBUTTON);
     else
          PORTB |= (1<<PROGBUTTON);

     DDRB |= (1<<PROGBUTTON);
[\c]

Der Code klappt ganz gut, aber auf einmal kommt der total aus dem Trap 
(auf dem Kontroller laufen noch einige Interrupt Routinen, Timer und 
INT0).

Hat einer ne Idee wie man das evtl. besser machen könnte?

Liebe Grüsse
Matthias

von mehrfacher STK500-Besitzer (Gast)


Lesenswert?

>Der Status ob das Led an ist oder nicht wird in einer Variable gespeichert.

Schon mal schlecht.

Wie hängt dein Schalter und deine LED am Port-Pin?
Es handelt sich vermutlich um einen mechanischen Taster. Die haben die 
Angewohnheit zu prellen, also den Kontakt nicht sofort richtig zu 
schliessen, sondern über eine gewisse Zeit zwischen den zwei Zuständen 
hin- und herzuschalten.
Eine Entprellroutine würde helfen (gibt's in der Codesammlung).

Ich mache solche Sachen so, dass die LED an VCC (über einen 
Vorwiderstand) und dem Portpin hängt. Der Taster schaltet GND.
Den Portpin schaltet ich auf GND (logisch 0).
Dann schalte ich nur noch das DDR um.
Das ganze passiert in einem Timer-Interrupt, wo dann auch gleich noch 
der Taster entprellt wird. Dazu ist es aber nötig, den LED-Zustand in 
einer Variablen zwischenzuspeichern.

PORTB &= ~(1<<PROGBUTTON); // Pin auf GND-Pegel sschalten

Ablauf in der ISR:
DDRB &=~(1<<PROGBUTTON); // Pin als Eingang schalten
PINB einlesen und mit vorherigem Zustand vergleichen
Ist der Zustand über eine gewisse Dauer stabil und die Taste gedrückt, 
ändere den Zustand der LED (an/aus...) in ihrer Variablen (ganzer Port 
ist ganz praktisch, wenn man mehrere Taster und LEDs hat).
Merke dir, dass die Taste gedrückt wurde.
Ist der Zustand über eine gewisse Dauer stabil und die Taste nicht 
gedrückt, freue dich...(irgendwie sollte noch erkannt werden, dass die 
Taste losgelassen wurde...)
schreibe den neuen Zustand (kann auch der alte sein) der LED ins DDRB.

Die LED arbeitet in diesem Fall auch als Pullup-Widerstand.

von Matthias F. (idefix)


Lesenswert?

Also die Ansteuerung ist die folgende:

VCC---R---LED-----Schalter---GND
               |
               |
             PIN MC

von mehrfacher STK500-Besitzer (Gast)


Lesenswert?

Dann geht das so (in etwa) wie ich es geschrieben habe.

von Matthias F. (idefix)


Lesenswert?

mehrfacher STK500-Besitzer wrote:
> Dann geht das so (in etwa) wie ich es geschrieben habe.

super danke dir, dann liegt mein problem wohl wo anders begraben :(
Naja mal weitersuchen wieso es auf einmal nicht mehr geht.

von Matthias F. (idefix)


Lesenswert?

so, es klappt wunderbar, hier eine kurze Zusammenfassung wie es geht.
So ist es möglich einen Pin als Eingang und Ausgang gleichzeitig zu 
nutzen, um z.B. den Kontroller in einen bestimmten Zustand zu bringen 
und gleichzeitig diesen Zustand mit einem LED am gleichen Port 
anzuzeigen.

Zuerst den Pin als Ausgang definieren:
PORTB |= _BV(PROGBUTTON);
DDRB |= _BV(PROGBUTTON);

Ein define zum warten:
#define _NOP() do { _asm__ __volatile_ ("nop"); } while (0)

Die Schleife oben scheint den Schalter auch gleich zu entprellen
Dann das abfragen:
     uint8_t i;
     // switch to input mode
     DDRB &= ~(1<<PROGBUTTON);
     for(i=0;i<10;i++)
          _NOP();

     // check if programming button is pressed
     if(!(PINB & (1<<PROGBUTTON)))
     {
          // wait until button is released
          while(!(PINB & (1<<PROGBUTTON)));
          if(progmode == 1)
          {
               DEBUG_PUTS("PM off ");
               progmode = 0;
          }else
          {
               DEBUG_PUTS("PM on ");
               progmode = 1;
          }
     }

     // set pin to represent progmode
     if(progmode == 1)
          PORTB &= ~(1<<PROGBUTTON);
     else
          PORTB |= (1<<PROGBUTTON);

     // define port as output
     DDRB |= (1<<PROGBUTTON);
     return;

Hoffe das hilft dem ein oder anderem.

Gruss
Matthias

von Peter D. (peda)


Lesenswert?

Dein Programm hat aber den Schönheitsfehler, daß die LED nie aus geht, 
wenn die Taste gedrückt ist.
So gehts aber:


Beitrag "Taster + LED am selben Draht (4*)"


Peter

von Matthias F. (idefix)


Lesenswert?

Hallo Peter,

danke für Deinen Tip, hab mir das mal angeschaut und es geht ein bischen 
weiter als ich gerne hätte, aber ich hab mir es auf jeden Fall mal 
gebookmarkt, kann vielleicht später mal brauchen.

Mit ist vollkommen bewusst wie das Programm sich verhält und ich muss 
sagen, ich wollte es auch genauso.
Und wenn einer den Taster drückt und nicht los lässt geht es nicht 
weiter, sehe ich aber als absolut nicht kritisch, da es ein Taster und 
kein Schalter ist und wenn einer den Taster nicht loslassen will, denkt 
er sich bestimmt was dabei :)

Gruss
Matthias

von Peter D. (peda)


Lesenswert?

Matthias Fechner wrote:

> Mit ist vollkommen bewusst wie das Programm sich verhält und ich muss
> sagen, ich wollte es auch genauso.

Sagen wir mal, Du hast Dich dran gewöhnt.

Ein Fremder würde immer die Reaktion beim Betätigen erwarten.
Natürlich läßt er irgendwann los und lernt es dann.

Ein weiterer Vorteil meiner Lösung ist auch, daß für Taste und LED 
zusammen nur 2 Leitungen nötig sind.


Peter

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.