-         

Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 16

Thema: Attiny13 mit Pinchange Interrupt boolvariable setzen

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    12.01.2010
    Beiträge
    64

    Attiny13 mit Pinchange Interrupt boolvariable setzen

    Anzeige

    hallo forenuser,
    folgendes problem dürfte für viele hier schnell durchschaut sein, ich finde den fehler nicht:

    ich möchte durch einen pinchange interrupt eine boolvariable verändern, damit in meiner main-schleife je nach zustand der variablen in eine andere schleife gegangen wird.
    Im Beispiel:
    einmaliger Tastendruck -> variable = true -> in der mainschleife der if-zweig, der die led schneller blinken lässt.
    erneuter tastedruck -> variable = false -> anderer (langsamer blinkender) zweig in der mainschleife.
    bei erneutem druck wieder von vorne, usw usf.

    Code:
    #include <stdbool.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <avr/io.h>
    #include <avr/interrupt.h>  
    
    #define F_CPU 9.6E6        
    #include <util/delay.h>    
    
    
    volatile bool onoff;
    
    ISR(PCINT0_vect)
    {
    	if (onoff)
    	{
    		onoff = false;
    
    		PORTB = 0b00000000; // LED OFF
    		_delay_ms(200);
    	}
    
    	if (!onoff)
    	{
    		onoff = true;
    
    		PORTB = 0b00000010; // LED ON
    		_delay_ms(200);
    	}
    }
    
    int main(void) 
    {        
    
      	DDRB  = 0b00000010;   
      	PORTB = 0b00000000;
    
      	GIMSK   |=  (1<<PCIE);         
     	PCMSK   |=  (1<<PCINT0);  // TASTER auf PB0   
     	sei();        
    	                          
     	while (1)
    	{
    		if (onoff)
    		{
    			for (int i=0; i<5; i++)
     			{
    				PORTB = 0b00000000; // LED OFF
    				_delay_ms(50);
    				PORTB = 0b00000010; // LED ON
    				_delay_ms(50);
    			}
    		}
    		else if (!onoff)
    		{	
    			for (int i=0; i<5; i++)	
    			{
    				PORTB = 0b00000000; // LED OFF
    				_delay_ms(200);
    				PORTB = 0b00000010; // LED ON
    				_delay_ms(200);
    			}
    		}
    		else
    		PORTB = 0b00000000; // LED OFF
    	}
                                                  
      return 0;                        
    }
    nun verhält sich mein controller mit dem folgenden code aber so, als würde der wert der variablen ständig derselbe bleiben. Kann mir da jemand helfen?

  2. #2
    Benutzer Stammmitglied
    Registriert seit
    26.08.2006
    Beiträge
    84
    Mahlzeit!

    Die Variable sollte sich schon ändern mit deinem code (wenn ich nichts übersehen hab...).
    Probier doch mal so: halt den Taster mal unten und beobachte.

    Pin *change* interrupt meint genau das was der Name sagt. Ein Int beim Übergang von high auf low und ein Int beim Übergang von low auf high. Wenn du jetzt auf den Taster drückst und loslässt hattest du 2 Ints und damit ist dein Bool wieder da wo es vorher war.

    Dein Taster ist richtig angeschlossen?

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    12.01.2010
    Beiträge
    64
    Zitat Zitat von Slein
    ...Wenn du jetzt auf den Taster drückst und loslässt hattest du 2 Ints und damit ist dein Bool wieder da wo es vorher war.

    Dein Taster ist richtig angeschlossen?
    hi! klingt logisch... ja der taster sollte richtig angeschlossen sein (druck gibt mir ein high am eingang) und ist mit einem 33k wiederstand und 0,33µF entprellt.

    da ich auf dem gebiet sehr neu bin: wie könnte ich das verhindern? ich erinnere mich gelesen zu haben, dass man die flanke auswählen kann, die das interrupt auslöst (?)...
    oder anders: wie könnte man mein problem anders lösen? externer (tastergesteuerter) interrupt, der eine boolvariable bei einmaligem drücken setzt um damit (was mein ziel ist) den µC in den sleep mode zu schicken bzw beim nächsten mal wieder aufzuwecken...

    grüße

  4. #4
    Benutzer Stammmitglied
    Registriert seit
    26.08.2006
    Beiträge
    84
    Du könntest z.B sowas in die int routine mit einbauen:

    if (PINB & 0x01) {
    ....
    }

    Dann würdest du die .... nur ausführen, wenn sich am ausgesuchten (PCMSK) Pin was ändert und der Pin auf high ist. 0x01 für PB0, im Zweifel bei Wikipedia mal nach 'und' suchen.

    Aber aufpassen, wenn du mehrere Pins an portb für Taster benutzt wirds Probleme geben wenn du mehrere Taster gleichzeitig drückst. Da müsste man sich dann die letzten Zustände merken.

    Die Flanke/Level kann man afaik nicht bei pin change interrupts einstellen, dafür gibts dann Int0, Int1 usw. Ob der Tiny13 sowas hat musst du im Datenblatt nachsehen.

  5. #5
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    20.08.2008
    Ort
    Kandel
    Alter
    29
    Beiträge
    1.220
    Die direkte Tasterauswertung in einer ISR ist eine eher schlechte Idee, lies dir Mal etwas Wissen zum Thema Entprellung an.

    Linktipps: RN-Wissen und µC.net Wiki

    mfG
    Markus

  6. #6
    Benutzer Stammmitglied
    Registriert seit
    12.01.2010
    Beiträge
    64
    hallo markus,
    du meinst die hardwareentprellung, die ich oben erwähnt habe, ist ungeeignet?

  7. #7
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    7.551
    Zitat Zitat von Slein
    ... Pin *change* interrupt meint genau das was der Name sagt. Ein Int beim Übergang von high auf low und ein Int beim Übergang von low auf high. Wenn du jetzt auf den Taster drückst und loslässt hattest du 2 Ints und damit ist dein Bool wieder da wo es vorher war ...
    Klar - die hübsche PCI-Funktion hat diesen Effekt. Leider bin ich im Programmieren nicht so erfahren, kann keine guten Ratschläge geben. Aber mein PCI-Code läuft prächtig.

    Dabei gehts um eine ähnliche Sache wie bei ExXeQtor. Der µC wird in den sleep geschickt, und soll bei Tastendruck aufwachen. Deshalb habe ich eine ziemlich kurze PCI-ISR: der vollständige Code in der Routine ist ein return. Damit kann ich z.B. den Aufruf im main :
    schlaf_PI4 ();
    in eine while-Schleife legen, die mir in Art eines Menues - je nach gedrücktem Pin - nach der Rückkehr aus dem SparSchlaf oder auch ohne diesen durch einen oder beliebig viele Tastendrücke auch auf verschiedene Tasten das erledigt, was ich will. Wieso "... nach beliebig vielen Tastendrücken ..."? Weil die ISR nur ein popeliges "return" ist - also im Programm selbst garnicht stört. Der einzige Zweck, der dabei erreicht wird, ist es, den µC mit einem Tastendruck aus dem Sleep zu holen >>wenn er da drin ist<<. Und ich kann >>irgendwann<< - wenn es mir beliebt - den µC wieder in den Sleep schicken. Sogar durch einen Druck auf die gleiche Taste (Anregung: if Taste gedrückt? dann prüfen Taste lose? wenn ja schlaf_PI4 (); - else zum ersten if: etwas ohne Tastendruck).

    @ExXeQtor - vielleicht überlegst Du Dir diese Vorgehensweise? Obwohl ich nicht weiß, ob das ein gutes Verfahren ist. Aber es läuft in meinem pacer seit "Ewigkeiten" problemlos.
    Ciao sagt der JoeamBerg

  8. #8
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    20.08.2008
    Ort
    Kandel
    Alter
    29
    Beiträge
    1.220
    Zitat Zitat von ExXeQtor
    hallo markus,
    du meinst die hardwareentprellung, die ich oben erwähnt habe, ist ungeeignet?
    Das ist keine Hardwareentprellung, es ist überhaupt keine Entprellung.
    Noch während du in der ISR bist kann durch das Prellen der PCINT-Flag erneut gesetzt werden -> Nach verlassen der ISR wird diese gleich wieder ausgelöst.

    Und sleep() in einer ISR ist eine sehr schlechte Idee ...

    mfG
    Markus

  9. #9
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    7.551
    Zitat Zitat von markusj
    ... Und sleep() in einer ISR ...
    Wo taucht die denn auf? Hab ich da etwas übersehen?
    Ciao sagt der JoeamBerg

  10. #10
    Benutzer Stammmitglied
    Registriert seit
    12.01.2010
    Beiträge
    64
    Zitat Zitat von markusj
    Das ist keine Hardwareentprellung, es ist überhaupt keine Entprellung.
    Noch während du in der ISR bist kann durch das Prellen [...]
    prellen tut der aufbau soweit nicht (merkbar)... insofern würde ich die hardwareentprellung schon eine nennen...

    Zitat Zitat von markusj
    Und sleep() in einer ISR ist eine sehr schlechte Idee ...
    die sleep sollte nicht in die ISR, ich wollte in der ISR ja nur ein(ige) bool(s) setzen, die in meiner mainschleife dann bestimmen, ob sleep oder nicht...

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •