Forum: Mikrocontroller und Digitale Elektronik LED soll an bleiben


von Sven B. (sven98)


Lesenswert?

Hallo liebe Mitglieder des Mikrocontroller-Nets,

ich wollte gerne meine LED zum leuchten bringen und das funktioniert 
auch. Aber wenn ich ich die Taster los lasse, geht die LED nach 10000 ms 
aus. Mein Ziel ist aber, dass die LED nach einmal drücken der Taster 
anbleibt. Hier ist mein Code, könnte mir jemanden sagen was ich falsch 
mache.

Ps: Bin Anfänger, seit bitte nicht so streng mit mir! ;)

1
#define F_CPU 2000000UL
2
3
#include <util/delay.h>
4
#include <avr/io.h>
5
#include <stdint.h>
6
7
//****** Initialsierung ******************
8
9
int main(void)
10
11
{    DDRB=0x01;    // Port B0 für den Taster als   Eingang
12
    PORTB=0x02;    // Pull-Up ein auf Port B1 als Ausgang für den Taster
13
    DDRA=0x01;    // Port A0 für die LED als Ausgang
14
    //PORTA=0x00;    // Alle Pins auf Port A auf Low für die LED
15
16
//******* Hauptschleife ******************
17
18
    while(1) 
19
    {    if(PINB & (1<<1))
20
        {    PORTA&=~(1<<PA0);
21
22
        }    
23
        
24
        else
25
        {
26
            PORTA|=(1<<PA0);
27
            _delay_ms(10000);
28
        }
29
30
    }
31
    return 0;
32
    
33
}

: Bearbeitet durch User
von Paul W (Gast)


Lesenswert?

1
{    if(PINB & (1<<1))
2
        {    PORTA&=~(1<<PA0);
Wenn der Taster gedrückt licht an
1
        }
2
3
        else
4
        {
5
            PORTA|=(1<<PA0);
6
            _delay_ms(10000);
wenn nicht licht aus 10 sekunden warten bis er wieder von vorne anfängt


Da ist also nix drinne was sich den zustand der Led merken könnte.

: Bearbeitet durch User
von ich (Gast)


Lesenswert?

Die Hauptschleife wird doch immer wieder durchlaufen. Und in dieser 
Schleife prüfst du den Taster und setzt dann den Port für die LED. Dann 
wartest du 10s und dann geht das ganze von vorn los. Wenn also die 
Hauptschleife von vorn beginnt und der Taster ist nicht betätigt, wird 
dieser Zustand auch an den LED-Port übertragen. Das Verhalten ist also 
richtig.
Wenn die LED also anbleiben soll, mußt du nur dafür sorgen, daß der 
gesamte Vorgang nur einmal ausgeführt wird.

von Karl H. (kbuchegg)


Lesenswert?

Das Problem ist weniger, dass es da nichts gibt, was sich den Zustand 
der LED merkt.

Das Problem ist mehr, dass es einen Unterschied gibt zwischen
* die Taste IST niedergedrückt
* die Taste hat ihren Zustand von nicht gedrückt auf gedrückt gewechselt


Das erste ist: Ein Motor läuft solange, solange du eine Taste drückst
Das zweite ist: Einmal niederdrücken löst eine Aktion aus.

Beim zweiten kommt es also darauf an, die Veränderung des Tastenzustands 
festzustellen. Ob die Taste gedrückt IST oder nicht gedrückt IST, ist 
zweitrangig. Wichtig ist, dass sie ihren Zustand ändert.
Dieser Zustandswechsel ist es, den das Programm feststellen muss. Von 
nicht gedrückt auf gedrückt. Und in deinem Fall bedeutet dann das 
detektieren davon eben, dass du eine LED umschaltest.

1
int main()
2
{
3
  uint8_t now;
4
  uint8_t previous;
5
6
   ...
7
8
  previous = ( PINB & (1<<1) );
9
10
  while( 1 )
11
  {
12
    now = ( PINB & (1<<1) );
13
14
    if( now != previous )            // gab es eine Änderung?
15
    {
16
      if( now )                      // ja, gab es. Ist die Taste jetzt
17
                                     // gedrückt oder losgelassen?
18
      {
19
        .....
20
      }
21
    }
22
23
    previous = now;
24
    _delay_ms( 10 );
25
  }
26
}

von Magic S. (magic_smoke)


Lesenswert?

Hm... Relais-Selbsthalteschaltung mit µC?

von ich (Gast)


Lesenswert?

magic smoke schrieb:
> Hm... Relais-Selbsthalteschaltung mit µC?

Welches Relais?

von Magic S. (magic_smoke)


Lesenswert?

Na nimmst Du ein Relais, das Du mit dem Taster einschalten kannst und 
ein Schließer davon kommt über den Taster. Die LED parallel zum Relais, 
dann bleibt die auch an. Spart jeden Programmieraufwand.

von ich (Gast)


Lesenswert?

magic smoke schrieb:
> Na nimmst Du ein Relais, das Du mit dem Taster einschalten kannst
> und
> ein Schließer davon kommt über den Taster. Die LED parallel zum Relais,
> dann bleibt die auch an. Spart jeden Programmieraufwand.

Klar, kann man machen. Aber da braucht man wiederum keinen µC. Also 
entweder oder... :-)

von Magic S. (magic_smoke)


Lesenswert?

> Aber da braucht man wiederum keinen µC.
Eben darum. Gilt das als geschummelt??

Und wenn Du keine LED, sondern eine Glühlampe nimmst, funktioniert das 
sogar noch nach dem nächsten Atomkrieg.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

magic smoke schrieb:
>> Aber da braucht man wiederum keinen µC.
> Eben darum. Gilt das als geschummelt??

In einem Mikrocontroller Forum, wo es darum geht wie man µC 
programmiert: ja, doch. Da ist das geschummelt.

von Magic S. (magic_smoke)


Lesenswert?

Ach Mist ... **in die Ecke geh und schmoll**

von Stefan P. (form)


Lesenswert?

Sven Baum schrieb:
> DDRB=0x01;    // Port B0 für den Taster als   Eingang
> PORTB=0x02;    // Pull-Up ein auf Port B1 als Ausgang für den Taster

B0 ist hier ein Ausgang statt Eingang, und der PullUp ist für den 
falschen Pin.

von Sven B. (sven98)


Lesenswert?

Danke für eure zahlreichen Informationen, die haben mir auch schon 
weiter geholfen.

Nun habe ich ein anderes Problem, mein AVR-Studio 4.13 funktioniert 
nicht mehr. Die Fehlermeldung heißt: "Unbehandelte Ausnahme bei 
0x004c34d7 in AVRStudio.exe: 0xC0000005: Zugriffsverletzung beim Lesen 
an Position 0x05e210bc."

Keine Ahnung was das bedeutet...

Kann mir vielleicht jemand HELFEN, ich komm sonst nicht weiter.

Ich hab alles wieder neu installiert, aber die Fehlermeldung bleibt.


Jetzt funktioniert es, keine Ahnung was passiert ist. Aber ich würde es 
trotzdem gerne wissen was das Problem war. Also wenn jemdand weißt was 
die Fehlermeldung bedeutet, dann wäre das echt nett von euch (Dir) über 
eine kleine Information bzw. Einweisung.

SVEN

: Bearbeitet durch User
von Sven B. (sven98)


Lesenswert?

Guten Abend...,

ich hätte da mal wieder eine Frage. Meine LED leuchtet jetzt wenn ich 
den Taster einmal betätige aber ganz verstehe ich das nicht. Hier einmal 
mein Code:
1
#define F_CPU 2000000UL
2
3
#include <util/delay.h>
4
#include <avr/io.h>
5
#include <stdint.h>
6
7
  int main(void)
8
  {
9
    DDRB=0x01;    // Port B0 für den Taster als Ausgang
10
    PORTB=0x02;    // Pull-Up EIN auf Port B1 als Eingang für den Taster
11
    DDRA=0x01;    // Port A0 für die LED als Ausgang
12
13
    while(1)              // Unendlich lang wiederholen
14
    {
15
      if(PINB&(1<<PB1));        // Wenn Taster gedrückt,...(if = wenn)
16
      //{
17
        
18
            //PORTA&=~(1<<PA1);  //...dann LED AN.
19
      //}
20
        else            // (else = sonst)
21
        {
22
           PORTA|=(1<<PA0);    // Wenn Taster nicht gedrückt, dann LED AUS
23
          //_delay_ms(10000);    // Nach 10 sec. von vorne beginnen    
24
        }
25
    }
26
      
27
  }
Eingentlich dürfte sie doch nicht leuchten oder? Bei meiner if Abfrage, 
da setzte ich den Wert 1 an Port B1 wo der Taster dran ist. Also wenn 
Taster gedrückt, dann soll die LED angehen. Dies passiert aber bei der 
else-Schleife. Das bedeutet doch drücke Taster, sonst mach LED an. Ich 
verstehe das nicht so ganz, ich bin der Meinung, dass die LED nicht 
leuchten dürfte. Dank im vorraus für eure Mühe, ihr habt mir schon 
wirklich sehr geholfen DANKE, DANKE, DANKE...

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Sven Baum schrieb:

> da setzte ich den Wert 1 an Port B1 wo der Taster dran ist.

Du setzt überhaupt nichts.
Du fragst den Zustand des Pins ab.

> Also wenn
> Taster gedrückt

Tja. Jetzt kommt es aber darauf an. Was liefert bei dir ein gedrückter 
Taster. Ist der abgefragte Portpin dann 0 oder 1?

> dann soll die LED angehen. Dies passiert aber bei der
> else-Schleife.

Ein else ist keine Schleife. Genausowenig wie ein if.
Das Wesen einer Schleife besteht darin, dass etwas wiederholt wird. Drum 
heisst es Schleife. Wie ein Streifen Papier, der zu einer Schleife 
zusammengeklebt wird.
Weder bei einem if noch bei einem else wird aber etwas wiederholt. Da 
wird einfach nur eine Auswahl aus 2 Möglichkeiten getroffen.

> Das bedeutet doch drücke Taster, sonst mach LED an. Ich
> verstehe das nicht so ganz, ich bin der Meinung, dass die LED nicht
> leuchten dürfte.

Es hängt davon ab, wie deine Taster angeschaltet sind. Ob die den 
Portpin auf 0 oder auf 1 bringen, wenn sie gedrückt werden. Beides ist 
möglich, aber meistens ist es so, dass ein gedrückter Taster zu einem 
0-Bit führt.


PS: Genausowenig wie automatisch feststeht, dass eine LED brennt, wenn 
man den zugehörigen Ausgangspin auf 1 setzt. Auch das ist kein 
Naturgesetz, dass das so sein muss. Es hängt einzig und allein davon ab, 
wie die LED angeschlossen ist.

von Sven B. (sven98)


Lesenswert?

Hallo Karl Heinz,

danke erst mal für deine Hilfe. Mein Taster ist mit dem einem Pin an 
Port B0 als Ausgang und mit dem andern Pin an Port B1 als Eingang 
verbunden. Der Taster hat vier Pins. Am Eingang habe ich in meiner 
Hardware noch ein Pull-Up integriert. Ich hab es später gesehen das es 
nicht notwendig ist, aber jetzt hab ich es in meiner Hardware und würde 
es auch gerne nutzen.

Die LED ist mir der Anode am Port A0 verbunden mit einem Vorwiderstand 
und mit der Kathode an GND.

Ich bin der Meinung, dass mein Code so aus sehen müsste:
#define F_CPU 2000000UL

#include <util/delay.h>
#include <avr/io.h>
#include <stdint.h>

  int main(void)
  {
    DDRB=0x01;    // Port B0 für den Taster als Ausgang
    PORTB=0x02;    // Pull-Up EIN auf Port B1 als Eingang für den Taster
    DDRA=0x01;    // Port A0 für die LED als Ausgang

    while(1)              // Unendlich lang wiederholen
    {
      if(PINB&(1<<PB1));        // Wenn Taster gedrückt,...(if = wenn)
      {

            PORTA|=(1<<PA0);  //...dann LED AN.
      }



    }

  } aber so funktioniert es nicht.

: Bearbeitet durch User
von Sven B. (sven98)


Lesenswert?

Guten Tag,

ich hab es jetzt soweit hinbekommen, dass meine LED nach einem Taster 
druck leuchtet und nach einem weiteren druck geht sie wieder aus, was 
auch mein Ziel ist.

Aber ein kleines Problem habe ich noch. Manchmal muss ich mehrmals auf 
den Taster drücken, damit ich die LED überhaupt anbekommen und das 
gleiche auch beim aus machen der LED.

In meiner Hardware habe ich an dem Taste einen PULL-UP eingebaut, hat 
das dammit was zu tun?

Hier ist einmal mein Code:
1
#define F_CPU 2000000UL
2
3
#define TASTER_1_DRUECKEN (PINB&(1<<PB0))
4
#define LED_AUS PINA&~(1<<PA0)
5
#define LED_AN PORTA |=(1<<PA0)
6
#define LED_AUSM PORTA &=~(1<<PA0)
7
8
#include <util/delay.h>
9
#include <avr/io.h>
10
#include <stdint.h>
11
12
13
    int main(void)
14
    {
15
      DDRB |=(1<<PB0); // Ausgang Taster
16
      DDRA |=(1<<PA0); // Ausgang LED
17
      PORTB = 0x02;   // Eingang Taster
18
19
20
      while(1) {
21
22
      if(TASTER_1_DRUECKEN) {    // Taster gedrückt
23
        
24
25
        if (LED_AUS) {       // Falls PA0 auf 0, heißt LED ist AUS
26
            LED_AN;         // Dann mache die LED AN, also PA0 = 1
27
        } else {        // Falls PA0 nicht auf 0, heißt LED ist AN
28
           LED_AUSM;       // Dann mach die LED AUS, also PA0 = 0
29
        }
30
      }
31
32
33
34
35
    }
36
  }

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Sven Baum schrieb:

> danke erst mal für deine Hilfe. Mein Taster ist mit dem einem Pin an
> Port B0 als Ausgang und mit dem andern Pin an Port B1 als Eingang
> verbunden.


Wozu?
Machst du dir gerne die Dinge möglichst umständlich?

von Karl H. (kbuchegg)


Lesenswert?

> #define LED_AUS PINA&~(1<<PA0)

Echt?
Du schaltest einen Ausgang, indem du das PIN Register manipulierst?


Es ist wirklich ganz einfach:


mittels DDRx wird festgelegt, ob ein Pin Eingang ist, oder ob er Ausgang 
ist.
Ein 1 Bit an der jeweiligen Pinposition schaltet den Pin auf Ausgang.

Das Port Register hat 2 Funktionen
* bei einem auf Ausgang geschalteten Pin, schaltet es diesen je nach 
Bitposition auf 1 oder 0. Je nachdem was programmiert wurde
* bei einem auf Eingang geschalteten Pin, schaltet es am jeweiligen Pin 
den Pullup Widerstand dazu bzw. weg.

Das Pin Register hat 1 Funktion
* es liefert dir den tatsächlichen Zustand (0 oder 1) des Pins.


Wie setzt man ein bestimmtes Bit auf 1 oder 0, bzw. wie fragt man 1 Bit 
ab?
1
Bit auf 1 setzen
2
3
    register |= ( 1 << Bitnummer );
1
Bit auf 0 löschen
2
3
    register &= ~( 1 << Bitnummer );
1
Bit abfragen, ob es 1 ist
2
3
    if( register & ( 1 << Bitnummer ) )
1
Bit abfragen, ob es 0 ist
2
3
   if( !( register & ( 1 << Bitnummer ) ) )

Das sind Building-Blocks. Also Bausteine, die du je nach Bedarf und je 
nach Anforderung einsetzen kannst.

Man beachte: um einen Ausgang zu manipulieren, findet eine Zuweisung 
statt! &= bzw. |= sind Zuweisungen!
Um einen Eingang abzufragen, wird nur mittels eines & maskiert.
Um einen Ausgang zu manipulieren, wird auf das PORTx Register 
zugegriffen.
Um einen Eingang abzufragen, wird vom PINx Register gelesen.


Und es sind die Basics, wie Pin-Manipulation funktioniert. Man benötigt 
sie um an den Ausgängen zb LED zu schalten bzw. an den Eingängen einen 
Taster (der so angeschlossen wird, dass er bei gedrückt nach Masse 
durchschaltet) abzufragen.


Und .... das findet sich in jedem Tutorial

AVR-GCC-Tutorial
AVR-Tutorial

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

Das hier

>       if(TASTER_1_DRUECKEN) {    // Taster gedrückt
>
>
>       if (LED_AUS) {       // Falls PA0 auf 0, heißt LED ist AUS
>           LED_AN;         // Dann mache die LED AN, also PA0 = 1
>       } else {        // Falls PA0 nicht auf 0, heißt LED ist AN
>          LED_AUSM;       // Dann mach die LED AUS, also PA0 = 0
>       }
>     }

ist wieder kein Code, mit dem die Veränderung des Tastenzustands 
festgestellt wird.
Das ist Code, der den aktuellen Tastenzustand feststellt. ABer das wurde 
weiter oben schon mal gesagt, dass du dazu eine Variable brauchst, und 
bei jedem Schleifendurchlauf vergleichen musst, ob sich der Eingangspin 
verändert hat!
Du kannst es drehen wie du willst. Aber um diesen Vergleich und die 
Flankenerkennung (so nennt sich das im Jargon) kommst du nicht herum. 
Das ist genau das, was die Erkennung eines Tastendrucks ausmacht. Im 
Gegensatz zu der Fragestellung: Ist die Taste genau jetzt, zu diesem 
Zeitpunkt, gedrückt oder nicht?
Denn: deine Taste ist gedrückt, wenn du sie niederdrückst. Für dein 
Programm ist sie viele tausend male hintereinander gedrückt. So eine 
popoelige Schleife
1
  while( 1 )
2
  {
3
    if( PINB & ( 1<<PB0 ) )
4
      ...
5
  }

rattert dein µC ein paar 10-tausend mal in der Sekunde durch. Und 
jedesmal stellt er fest: Jawohl, die Taste ist jetzt gerade gedrückt. 
Und demenstprechend macht er dann auch die Aktion, die von diesem if 
abhängt ein paar 10-tausend mal in der Sekunde.

: Bearbeitet durch User
von Sven B. (sven98)


Lesenswert?

> Das sind Building-Blocks. Also Bausteine, die du je nach Bedarf und je
> nach Anforderung einsetzen kannst.


Ok, wo finde ich die Building-Blocks? Das ist mein Problem, dass ich 
diese Befehle nicht kenne und immer danach suchen muss.

Ich hab schon in den Tutorials gesucht, aber so eine Auflistung wie Du 
es mir beschrieben hast habe ich nicht gefunden.

Danke...

von Karl H. (kbuchegg)


Lesenswert?

Karl Heinz schrieb:


> Denn: deine Taste ist gedrückt, wenn du sie niederdrückst. Für dein
> Programm ist sie viele tausend male hintereinander gedrückt. So eine
> popoelige Schleife
>
>
1
>   while( 1 )
2
>   {
3
>     if( PINB & ( 1<<PB0 ) )
4
>       ...
5
>   }
6
>
>
> rattert dein µC ein paar 10-tausend mal in der Sekunde durch. Und
> jedesmal stellt er fest: Jawohl, die Taste ist jetzt gerade gedrückt.
> Und demenstprechend macht er dann auch die Aktion, die von diesem if
> abhängt ein paar 10-tausend mal in der Sekunde.

Und genau das ist dann auch eines deiner Probleme.
Denn was ist deine Aktion?
Die Aktion lautet: wenn die LED ausgeschaltet ist, dann schalte sie ein. 
Andernfalls schalte sie aus.

Und das wird jetzt ein paar tausend mal gemacht, solange du die Taste 
drückst.
D.h. das kannst du nicht kontrollieren, was im Endeffekt die LED beim 
Loslassen der Taste machen wird. Denn so genau (zeitlich gesehen) kannst 
du einen Taste gar nicht drücken, dass sie genau in dem gewünschten 
Zustand stehen bleibt.

von Sven B. (sven98)


Lesenswert?

Das stimmt, dass ist wirklich mein Problem.

Gibt es solche Listen für die Building-Blocks?

von Karl H. (kbuchegg)


Lesenswert?

Sven Baum schrieb:
> Das stimmt, dass ist wirklich mein Problem.
>
> Gibt es solche Listen für die Building-Blocks?

Die für das Setzen/Löschen/Abfragen hab ich dir ja oben schon gegeben. 
Abgesehen davon: nicht wirklich. Genau das ist dann der 
Erfahrungsschatz, der sich mit der Zeit anhäuft. Denn soooo einfach ist 
die Sache dann auch wieder nicht, dass man nur in einer Liste nachsehen 
muss und sich von dort die Einzelteile zusammenkopiert und das wars dann 
schon.

von Sven B. (sven98)


Lesenswert?

Ok, herzlichsten Dank. Ich werde mich dann mal an die Arbeit machen und 
es so versuchen wie Du es mir erklärt hast.

Ich werde mich dann wieder bei dir melden, wenn ich Erfolg habe bzw. 
auch nicht habe. ;)

von Rudolph (Gast)


Lesenswert?

Karl Heinz schrieb:
>> #define LED_AUS PINA&~(1<<PA0)
>
> Echt?
> Du schaltest einen Ausgang, indem du das PIN Register manipulierst?

Passt nicht so ganz zum Thema, fiel mir nur so gerade auf hier. :-)

Zum einem wird die Zeile nur für die Abfrage verwendet, da wird das PINA 
Register überhaupt nicht mit manipuliert.

Zum anderen aber:

DDRA = (1<<PA0);

while(1)
{
 PINA = (1<<PA0);
}

Das wackelt die ganze Zeit mit dem Ausgang indem das PIN Register 
manipuliert wird.
Okay ja, die alten AVRs können das nicht, aber selbst der etwas 
angestaubte 90CAN macht das.

von Karl H. (kbuchegg)


Lesenswert?

Rudolph schrieb:
> Karl Heinz schrieb:
>>> #define LED_AUS PINA&~(1<<PA0)
>>
>> Echt?
>> Du schaltest einen Ausgang, indem du das PIN Register manipulierst?
>
> Passt nicht so ganz zum Thema, fiel mir nur so gerade auf hier. :-)
>
> Zum einem wird die Zeile nur für die Abfrage verwendet, da wird das PINA
> Register überhaupt nicht mit manipuliert.

Ja, das hab ich zu spät gesehen.
Ich hatte mich am Makronamen orientiert und auf 'Verwendung zum 
SChalten' geschlossen. Das war ein Fehlschluss.

> Okay ja, die alten AVRs können das nicht, aber selbst der etwas
> angestaubte 90CAN macht das.

:-)
Du magst mich hellsichtig nennen: Ich denke nicht, dass das die Absicht 
vom TO war.

von Karl H. (kbuchegg)


Lesenswert?

Sven Baum schrieb:
> Ok, herzlichsten Dank. Ich werde mich dann mal an die Arbeit machen und
> es so versuchen wie Du es mir erklärt hast.
>
> Ich werde mich dann wieder bei dir melden, wenn ich Erfolg habe bzw.
> auch nicht habe. ;)

Der Ansatz dazu wurde am 24.10.2013 10:11 schon gepostet. Da ist die 
Technik drinnen, die anzuwenden ist.

Ein paar Programmteile durch Makros zu ersetzen bringt dich nicht 
weiter. Denn im Grunde ist deine Programmversion vom 04.11.2013 16:33 
immer noch dieselbe wie die vom 24.10.2013 09:47. Du hast ein paar 
Bitoperationen hinter Makros versteckt, aber konzeptionell ist es immer 
noch das gleiche Programm mit immer noch dem genau gleichen Problem.

: Bearbeitet durch User
von Rudolph (Gast)


Lesenswert?

Karl Heinz schrieb:
> Du magst mich hellsichtig nennen: Ich denke nicht, dass das die Absicht
> vom TO war.

Daher mein "passt nicht ganz zum Thema", ich bin nur auf das Ausgang 
schalten per PIN Register angesprungen. :-)

Wobei mir gerade was einfällt was ich mal geschnitzt habe.
Das ist für einen Tiny45 der nichts anderes machen sollte:
1
#include <avr/io.h>
2
#include <avr/power.h>
3
4
int main(void)
5
{
6
uint16_t filter = 0;
7
uint8_t status = 0;
8
9
DDRA = 0x00;
10
PORTA = (1<<PA0);
11
12
DDRB = (1<<PB3);
13
PORTB = 0x00;
14
15
  power_all_disable(); // disable all units
16
  clock_prescale_set(clock_div_256); // set clock to 31,25kHz
17
18
  while(1)
19
  {
20
    if((PINA & (1<<PA0)) == 0) // button pressed
21
    {
22
      if(filter <= 400 && status == 0) // app. 0,2s
23
      {
24
        filter++;
25
      }
26
      if(filter > 400 && status == 0)
27
      {
28
        filter = 3000; // app. 2s
29
        status = 1;
30
        PINB = (1 << PB3); // just toggle
31
      }
32
    }
33
    else // button not pressed
34
    {
35
      if(filter > 0)
36
      {
37
        filter--;
38
      }
39
      if(filter == 0)
40
      {
41
        status = 0;
42
      }
43
    }
44
  }
45
}

Das macht sowas, man muss etwa 0,2s drücken damit eingeschaltet wird
und muss dann für etwa 2 Sekunden loslassen bevor man wieder drücken 
kann.

Ja klar, direkt einbauen in ein grösseres Programm sollte man das nicht. 
:-)

Das Programm merkt sich nicht, ob der Ausgang gerade Null oder High hat, 
die "status" Veriable dient nur dazu festzustellen, ob gerade 
umgeschaltet werden darf.

: Bearbeitet durch User
von Sven B. (sven98)


Lesenswert?

Hallo,

herzlichen Dank für eure Hilfe. Mein LEDs bekomme ich jetzt AN bzw. AUS!

- Wenn ich den Taster einmal drücke, dann geht die Blaue LED An.
- Wenn ich den Taster zum zweiten mal drücke, dann geht die Grüne LED 
AN.

Ich wollte es jetzt gerne erweitern. Undzwar wenn ich ein drittes mal 
auf den Taster drücke, dann sollen die beiden LEDs an gehen. Beim 
vierten mal, soll die beiden LESs AUS gehen.

Also ich hätte vier zustände undzwar:

1: Blaue LED AN, Grüne AUS
2: Grüne LES AN, Grüne AUS
3: Beide LEDs AN
4: Beide LEDs AUS

hier ist mein Code:

// 1. Tastendruck blaue LED, soll AN sein
// 2. Tastendruck rote LED, soll AN sein
// 3. Tastendruck, beide LEDs sollen AN sein
// 4. Tastendruck, beide LEDs sollen AUS sein

// Taster ist an Port PB0 als Ausgang deklariert
// Taster ist an Port PB1 als Eingang deklariert
// Grüne LED ist an Port A0
// Blaue LED ist an Port A1

#include <avr/io.h>
#include <util/delay.h>
#include <inttypes.h>
#include <avr/power.h>

//#define LED_AN  (PORTA |= (1<<LED))   // Setzte Bit 0 an Port A auf 1
//#define LED_AUS (PORTA &= ~(1<<LED))   // Lösche Bit 0 an Port A, also 
0
//#define LED_TOGGEL (PORTA ^= (1<<LED))   // Setze Bit 0 an Port A auf 
1 und wende Exklusiv-ODER an

//#define LED PA0
//#define TASTER PB0
//#define TASTER_GEDRUECKT (PINB & (1<<TASTER))

#define F_CPU 2000000UL
#define TASTE_AUF   0
#define TASTE_ZU   1
#define TASTE_NEU   1

int main(void)
{
  uint8_t neuer_tastenzustand = TASTE_NEU;
  uint8_t alter_tastenzustand = TASTE_AUF;


  DDRB &=~ (1<<PB0);        // PB0 wird auf Ausgang und andere im 
ursprüpnglichen Zustand gelassen
  PORTB |= (1<<PB0);        // Interner Pull-Up für Port 1 einschalten
  DDRB |= (1<<PB1);        // PB1 wird auf Eingang gesetzt
  DDRA |= (1<<PA0) | (1<<PA1);   // PA0 und PA1 wird auf Ausgang und 
andere im ursprünglichen Zustand gelassen

  while(1)
  {

//---------- Blaue LED AN und AUS ---------------------------

    if (PINB & (1<<PB0))                   // Ist der Port B an PIN B0 
auf 1 gesetzt?

    if (alter_tastenzustand == TASTE_ZU)          // Entspricht 
alter_tastenzustand == TASTE_ZU? Also ist 0=1?

      {

        PORTA ^= (1<<PA0);                // Mach die LED AN oder AUS!
        alter_tastenzustand = TASTE_AUF;        // alter_tastenzustand = 
TASTE_AUF, also 0 ist = 0!
      }

    if (!(PINB & (1<<PB0)))                  // Ist der Port B an PIN B0 
gelöscht, also 0?
    alter_tastenzustand = TASTE_ZU;              // alter_tastenzustand 
ist = TASTE_ZU, also 0 ist = 1!



//------------ Grüne LED AN und AUS  ------------------------

    if (PINB & (1<<PB0))                  // Ist der Port B an PIN B0 
auf 1 gesetzt?

    if (neuer_tastenzustand == TASTE_ZU)          // Entspricht 
neuer_tastenzustand == TASTE_NEU? Also ist 1=1?

      {
        PORTA ^= (1<<PA1);                // Mach die LED AN oder AUS!
        neuer_tastenzustand = TASTE_AUF;        // neuer_tastenzustand = 
TASTE_AUF, 1 ist = 0!
      }

    if (!(PINB & (1<<PB0)))                  // Ist der Port B an PIN B0 
gelöscht, also 0?
    neuer_tastenzustand = TASTE_ZU;              // alter_tastenzustand 
ist = TASTE_ZU, also 1 ist = 1!



//--------- Grüne und Blaue LED AN und AUS ------------------

     if (PINB & (1<<PB0))

    if ( alter_tastenzustand == TASTE_ZU)

      {
        PORTA |=(1<<PA0);
        PORTA |=(1<<PA1);
        alter_tastenzustand = TASTE_AUF;

      }

    if (!(PINB & (1<<PB0)))
    alter_tastenzustand = TASTE_ZU;


    _delay_ms(20);                      // Warte 20 ms bzw. 0,02 
Sekunden
   }
}

Kann mir jemand sagen, was ich falsch gemacht habe?

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.