-
        

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

Thema: Probleme mit ATtiny2313A wärend Interruptroutine

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    04.06.2017
    Beiträge
    15

    Probleme mit ATtiny2313A wärend Interruptroutine

    Anzeige

    SMARTPHONES & TABLETS-bis zu 77% RABATT-Kostenlose Lieferung-Aktuell | Cool | Unentbehrlich
    Hallo zusammen!

    Habe mir heute ein kleines Testprogramm geschrieben, um einfach mal zu sehen ob das so funktioniert was ich mir vorstelle.

    Der Gedanke dabei war in der while-Schleife die Variable c auszuwerten. In der Interruptroutine, welche durch einen Button auf INT0 ausgelöst wird, soll der Wert von 1 auf 2 bzw. von 2 auf 1 geändert werden.

    c bekommt im Programm direkt nach den Interruptinitialiesierungen den Wert 2. Meine LEDs blinken auch so wie es sein soll. Wenn ich den Button nun einmal betätige blinken die LED auch wieder richtig. Wird der Interrupt erneut ausgelöst ändert sich an dem Blinkverhalten allerdings nichts. Was ist da falsch gelaufen?

    Hier mal der Code
    PHP-Code:
    #define F_CPU 1000000UL

    #include <util/delay.h>
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <stdio.h>

    #define LED1 0
    #define LED2 1
    #define LED3 2
    #define LED4 3

    int a 1;
    int b 2;
    int c;
    int d;

    int main(void)
    {
        
        
    DDRB 0b00001111;
        
        
    //Einstellung Interrupt
        
    PORTD 0b00000100;
        
    GIMSK = (1<<INT0);

        
    sei();
        
        
    2;
        
        while (
    1
        {
            
            if (
    == 1)
            
            {
                
                
    PORTB |= ((1<<LED1) | (1<<LED3));
                
    PORTB &= ~((1<<LED2) | (1<<LED4));
                
                
    _delay_ms(500);
                
                
    PORTB |= ((1<<LED2) | (1<<LED4));
                
    PORTB &= ~((1<<LED1) | (1<<LED3));
                
                
    _delay_ms(500);
                
            }
            
            else if (
    == 2)
            
            {
            
                
    PORTB ^= ((1<<LED1) | (1<<LED2) | (1<<LED3) | (1<<LED4));
                
    _delay_ms(500);
            
            }
            
    }

    }

    ISR(INT0_vect)

    {

    if((
    PINB & (1<<PINB1)) == 0)
    {

        if (
    == 1)

        {    

            
    b;

        }

        else if (
    == 2)

        {
            
    a;
        }

    d;
    return;

    _delay_ms(100);
    }

    Über eure Hilfe wäre ich sehr dankbar.

    Gruß
    Lichti01

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von 021aet04
    Registriert seit
    17.01.2005
    Ort
    Niklasdorf
    Alter
    30
    Beiträge
    4.602
    In Interrupts verwendet man volatile Variablen. Anstatt "int a" musst du "volatile int a" schreiben, gleiches gilt auch für char,...
    Was mir auch noch auffällt ist das du auf "c==1" und "c==2" prüfst. Besser ist es wenn du auf "c==1" und auf "c!=1" prüfst. Wenn du z.B. c==3 ist wird nichts ausgeführt. Wenn du mehrere Auswahlmöglichkeiten hast könntest du auch mit "switch case" arbeiten. Also
    Code:
    switch(c)
    {
    case 1: ....
    break;
    
    case 2: ....
    break;
    
    default: ....
    }
    default wird ausgeführt wenn keine Auswahl zustimmt (also wenn z.B. c==3), benötigt auch kein break; mehr. Du musst auch darauf achten das du ansonsten immer ein break; einfügst. Sonst wird das switch weiter ausgeführt. Wenn du z.B. bei "case 1:" das break; vergisst wird "case 1:" und "case 2:" ausgeführt.

    Ich hatte mit einem else if schon Probleme (Programm hat nicht so funktioniert wie es sollte, habe es mehrfach überprüft und auch neu geschrieben). Ich mache seit dem nur mehr if bzw if/else und switch case Abfragen, aber keine else if Abfragen mehr.

    MfG Hannes

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    04.06.2017
    Beiträge
    15
    HI Hannes!

    Danke für deine schnelle Antwort.

    Habe den Variablen in volatile Variablen geändert. Die If/Else rausgeschmissen und in switch case geändert.
    Leider bestand das Problem immer noch. Des Rätzels Lösung war, den Toggelbefehl in "else if (c == 2)" in - LED ein - warten - LED aus - warten - zu ändern. Jetzt läuft es fast so wie ich mir das vorgestellt habe.
    Das einzige Problem das jetzt noch besteht ist, dass ich den Schalter teilweise mehrmals betätigen muss um das Blinkmuster zu verändern.
    Woran kann das denn liegen?

    Hier nochmal der geänderte Code:
    Code:
    #define F_CPU 1000000UL
    
    #include <util/delay.h>
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <stdio.h>
    
    #define LED1 0
    #define LED2 1
    #define LED3 2
    #define LED4 3
    
    //variablen für interrupt
    volatile int a = 1;
    volatile int b = 2;
    volatile int c;
    volatile int d;
    
    int main(void)
    {
    	
    	//I/O-Ports einstellen
    	DDRB = 0b00001111;
    	
    	//Einstellung Interrupt
    	PORTD = 0b00000100;
    	GIMSK = (1<<INT0);
    
    	//Globale interrupts aktivieren
    	sei();
    	
    	//Wert in Variable setzen
    	c = 2;
    	
    	while (1)
    	{
    		
    		switch(c)
    		
    		{
    			case 1:
    				PORTB |= ((1<<LED1) | (1<<LED3));	//LED1 und 3 ein
    				PORTB &= ~((1<<LED2) | (1<<LED4));	//LED2 und 4 aus
    		
    				_delay_ms(500);
    		
    				PORTB |= ((1<<LED2) | (1<<LED4));	//LED2 und 4 ein
    				PORTB &= ~((1<<LED1) | (1<<LED3));	//LED1 und 3 aus
    		
    				_delay_ms(500);
    			break;
    			case 2:
    				PORTB |= ((1<<LED1) | (1<<LED2) | (1<<LED3) | (1<<LED4));	//LED1-4 ein
    				_delay_ms(500);
    				PORTB &= ~((1<<LED1) | (1<<LED2) | (1<<LED3) | (1<<LED4));	//LED1-4 aus
    				_delay_ms(500);
    			break;
    			
    		}		
    		
    	}
    
    }
    
    ISR(INT0_vect)
    
    {
    	
    	{
    		
    		//switch case Abfrage
    		switch(c)
    		{
    			case 1: d = b;
    			break;
    			case 2: d = a;
    			break;
    			default: PORTB &= ~((1<<LED1) | (1<<LED2) | (1<<LED3) | (1<<LED4));
    		}
    	
    	c = d;
    	return;
    	_delay_ms(250);
    
            }
    }
    Gruß Alex

  4. #4
    Erfahrener Benutzer Roboter Genie Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.439
    Blog-Einträge
    112
    Zitat Zitat von Lichti01 Beitrag anzeigen
    Das einzige Problem das jetzt noch besteht ist, dass ich den Schalter teilweise mehrmals betätigen muss um das Blinkmuster zu verändern.
    Hallo Alex,
    Taster prellen. d.h. sie schließen und öffnen bei einer Betätigung mehrmals sehr schnell bis die Kontakte ihre endgültige Lage einnnehmen. Die Prellzeit von der Betätigung bis die Kontakte zu Ruhe kommen ist vom Taster abhängig und dauert im Allgemeinen 5 bis 20ms.

    In Deinem Programm sehe ich keine Maßnahme dagegen, so daß die ISR bei einem Tastendruck öfter ausgeführt wird und dann das Blinkmuster zufällig eingestellt wird, das dann wie das vorhergehende Blinkmuster aussieht oder eben zufällig das andere ist.

    Also Tastenentprellung implementieren.



    Code:
         return;
         _delay_ms(250);
    Wozu ist das _delay_ms in der ISR gut. Es wird nie ausgeführt, da mit dem "return;" der Ablauf der ISR beendet wird und das Normalprogramm wieder aufgenommen wird.

    Gruß
    Searcher
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

  5. #5
    Erfahrener Benutzer Robotik Einstein Avatar von 021aet04
    Registriert seit
    17.01.2005
    Ort
    Niklasdorf
    Alter
    30
    Beiträge
    4.602
    Ich vermute auch das es Tastenprellen ist.
    Das mit dem delay nach dem return stimmt ebenfalls. Bei C benötigst du kein return aus der ISR (außer es ist gewollt).
    Delay sollte man auch in einer ISR vermeiden. Eine ISR sollte auf ein Ereignis so schnell wie möglich reagieren, das Flag wird aber erst bei beenden der ISR zurückgesetzt. Du sperrst somit alle INT (auch Timer,....).
    Außerdem gilt bei ISR: So wenig wie möglich, so viel wie nötig. Die ISR sollte so schnell wie möglich abgearbeitet werden. Langwierige Berechnungen (z.b. Berechnungen mit Float) außerhalb der ISR (wenn nötig einfach ein Flag setzten und das im Hauptprogramm abfragen).

    MfG Hannes

  6. #6
    Erfahrener Benutzer Roboter Genie Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.439
    Blog-Einträge
    112
    Hallo,
    gerade fällt mir noch etwas auf. Die ISC00 und ISC01 Bits im MCUCR Register werden nicht gesetzt. Damit ist der low-Level Interrupt für INT0 eingeschaltet. Da ist also nicht nur das Tastenprellen ein Problem, sondern auch das Festhalten bzw Betätigungsdauer des Tasters. Solange ein low-Level am INT0 Pin anliegt, wird die ISR immer wieder aufgerufen, weil ja nach Abarbeitung ja immer noch der low-Level anliegt.

    Gruß
    Searcher
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

  7. #7
    Neuer Benutzer Öfters hier
    Registriert seit
    04.06.2017
    Beiträge
    15
    HI Searcher!

    Danke für die Antwort.
    Werde mich dann mit dem Thema Tastenentprellung auseinandersetzen und diese dann implementieren.

    Gruß Alex

  8. #8
    Erfahrener Benutzer Roboter Genie Avatar von Searcher
    Registriert seit
    07.06.2009
    Ort
    NRW
    Beiträge
    1.439
    Blog-Einträge
    112
    Auch meine neue Antwort bitte nicht übersehen
    http://www.roboternetz.de/community/...l=1#post641412

    Viel Erfolg
    Searcher
    Hoffentlich liegt das Ziel auch am Weg
    ..................................................................Der Weg zu einigen meiner Konstruktionen

  9. #9
    Neuer Benutzer Öfters hier
    Registriert seit
    04.06.2017
    Beiträge
    15
    Habe eure neuen Antworten eben gelesen.

    Wurden mir erst nach absenden meiner Antwort angezeigt.

    Vielen DANK nochmals!
    und danke für den Link

  10. #10
    Neuer Benutzer Öfters hier
    Registriert seit
    04.06.2017
    Beiträge
    15
    so habe mich nun einmal mit dem Thema Tasterentprellung auseinandergesetzt. Habe einen Code im Netz gefunden und diesen in meinen Code eingebunden. Leider besteht das Problem "ich blink wie ich will" immer noch. Was habe ich falsch gemacht?

    Code:
    #define F_CPU 1000000UL
    
    #include <util/delay.h>
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <stdio.h>
    
    #define LED1 0
    #define LED2 1
    #define LED3 2
    #define LED4 3
    
    //variablen für entprellung
    #define TASTERPORT PIND
    #define TASTERBIT PIND2
    volatile int r = 1;
    
    //variablen für interrupt
    volatile int a = 1;
    volatile int b = 2;
    volatile int c;
    volatile int d;
    
    //Entprellung
    char taster(void)
    {
    	static unsigned char zustand;
    	char rw = 0;
    
    	if(zustand == 0 && !(TASTERPORT & (1<<TASTERBIT)))   //Taster wird gedrueckt (steigende Flanke)
    	{
    		zustand = 1;
    		rw = 1;
    	}
    	else if (zustand == 1 && !(TASTERPORT & (1<<TASTERBIT)))   //Taster wird gehalten
    	{
    		zustand = 2;
    		rw = 0;
    	}
    	else if (zustand == 2 && (TASTERPORT & (1<<TASTERBIT)))   //Taster wird losgelassen (fallende Flanke)
    	{
    		zustand = 3;
    		rw = 0;
    	}
    	else if (zustand == 3 && (TASTERPORT & (1<<TASTERBIT)))   //Taster losgelassen
    	{
    		zustand = 0;
    		rw = 0;
    	}
    
    	return rw;
    }
    int main(void)
    {
    	
    	//I/O-Ports einstellen
    	DDRB = 0b00001111;
    	
    	//Einstellung Interrupt
    	PORTD = 0b00000100;
    	GIMSK = (1<<INT0);
    	MCUCR = (1<<ISC01) | (1<<ISC00);
    
    	//Globale interrupts aktivieren
    	sei();
    	
    	//Wert in Variable setzen
    	c = 2;
    	
    	while (1)
    	{
    		
    		switch(c)
    		
    		{
    			case 1:
    				PORTB |= ((1<<LED1) | (1<<LED3));	//LED1 und 3 ein
    				PORTB &= ~((1<<LED2) | (1<<LED4));	//LED2 und 4 aus
    		
    				_delay_ms(500);
    		
    				PORTB |= ((1<<LED2) | (1<<LED4));	//LED2 und 4 ein
    				PORTB &= ~((1<<LED1) | (1<<LED3));	//LED1 und 3 aus
    		
    				_delay_ms(500);
    			break;
    			case 2:
    				PORTB |= ((1<<LED1) | (1<<LED2) | (1<<LED3) | (1<<LED4));	//LED1-4 ein
    				_delay_ms(500);
    				PORTB &= ~((1<<LED1) | (1<<LED2) | (1<<LED3) | (1<<LED4));	//LED1-4 aus
    				_delay_ms(500);
    			break;
    			
    		}		
    		
    	}
    
    }
    
    ISR(INT0_vect)
    
    {
    	if (taster == r);	//Wenn Taster gedrückt
    	{
    		
    		//switch case Abfrage
    		switch(c)
    		{
    			case 1: d = b;
    			break;
    			case 2: d = a;
    			break;
    			default: PORTB &= ~((1<<LED1) | (1<<LED2) | (1<<LED3) | (1<<LED4));
    		}
    	
    	c = d;
    	
    	}	
    	
    }
    Ist das überhaupt der richtige Code für Tasterentprellung?

    Gruß
    Alex

Seite 1 von 2 12 LetzteLetzte

Ähnliche Themen

  1. ATTINY Spannung wärend Betrieb ändern
    Von .:markus:. im Forum AVR Hardwarethemen
    Antworten: 9
    Letzter Beitrag: 04.08.2010, 22:32
  2. Programmvariablen wärend Programmablauf ändern und speichern
    Von mat-sche im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 8
    Letzter Beitrag: 06.06.2007, 19:30
  3. Variablen aus Interruptroutine an Sub übergeben
    Von MarkusH im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 4
    Letzter Beitrag: 04.03.2007, 12:44
  4. Timer in interruptroutine nutzen?
    Von sebastian.heyn im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 1
    Letzter Beitrag: 12.01.2006, 21:04
  5. interruptroutine umschreiben in ASM
    Von emulein im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 2
    Letzter Beitrag: 15.02.2005, 07:20

Berechtigungen

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