- 3D-Druck Einstieg und Tipps         
Ergebnis 1 bis 10 von 59

Thema: Interrupt-Abfrage >>> Routine vereinfachen

Hybrid-Darstellung

Vorheriger Beitrag Vorheriger Beitrag   Nächster Beitrag Nächster Beitrag
  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.06.2019
    Beiträge
    148
    Moin.
    Bin gerade auf dem Sprung - konzentriert komme ich esrt zu Mittag dazu.

    Zitat Zitat von Holomino Beitrag anzeigen
    Ein schönes Beispiel, klingt sehr einfach, hat es aber in sich. Mal so grob geplant mit 2 LEDs und 2 Tastern.
    Mein Testaufbau sieht erst mal genau so aus. Das Spiel wird wesentlich komplexer. Mit Analog-Eingangs-Auswertungen, etc.
    Die Struktur steht auch soweit. Nur wollte ich endlich mal mit Interrupts arbeiten - NEULAND für mich - DAS macht es jetzt gerade etwas komplizierter, wird, wenn ich´s begreife und kontrolliere wesentlich schneller, flexibler und modularer!

    Zitat Zitat von Holomino Beitrag anzeigen
    (das 3. Blinken kann man fieserweise noch mit einem leichten Random verzögern)
    ...ohhhhh, welch B Ö S E R Gedanke ...
    __________________________________________________ _
    | Sprache: C | Teensy 3.2 | Arduino 2.x | Status: EwigerAnfaenger |

  2. #2
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.06.2019
    Beiträge
    148
    Zitat Zitat von Holomino Beitrag anzeigen
    se
    Aber bevor ich jetzt codemäßig anfange loszuwirbeln, erst einmal Dein Kommentar. Weiter geht es also nach der nächsten Maus.
    Danke für deine Gedanken und Mühe!

    Bis auf deine "spinnerte Erweiterungsmöglichkeiten:" ähneld deine Auflistung meinem Projekt.
    ABER, ich brauche keinen fertigen Code als Kopiervorlage. Viel mehr geht es mir ums Verstehen, Funktionen in universelle/autonome Module packen, um diese später in weitere Projekte mit gutem Gewissen einsetzen zu können.

    JETZT geht es mir um eine Interrupt-Eingangsabfrage, die ich nach Bedarf ein/ausschalten kann.
    Aber nicht generell, sondern jeder Eingang autonom.

    Bsp:
    Interrupt-Überwachung/Auslösung, inkl. (einfacher) Tastenentprellung
    # PA4, PA5 ein
    # PA4 aus
    # PB2 ein
    # PB2 aus
    # PA4 ein
    # PA4, PA5 aus
    __________________________________________________ _
    | Sprache: C | Teensy 3.2 | Arduino 2.x | Status: EwigerAnfaenger |

  3. #3
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    07.04.2015
    Beiträge
    903
    Hmmm,

    wenn ich Dir die Zustandcodierung für "Idle" gebe:
    Code:
    #include <avr/io.h>
    #include "Statemanager.h"
    #include "LED.h"
    #include "Started.h"
    
    uint16_t IdleCounter;
    
    void Idle_KeyDown(uint8_t index)
    {
    	// NOT USED
    }
    
    void Idle_KeyUp(uint8_t index)
    {
    	if (index == 1)
    		Started_Init();
    }
    
    
    
    void Idle_TimerTick()
    {
    	IdleCounter++;
    	if (IdleCounter	> 2000)
    	{
    		IdleCounter	= 0;
    		ToggleLED1();
    		
    	}
    }
    
    void Idle_Init()
    {
    	IdleCounter = 0;
    	ClearLED1();
    	ClearLED2();
    	AttachState(Idle_KeyDown, Idle_KeyUp, Idle_TimerTick);
    }
    ...dazu noch die Beschreibung von "Started"...

    Code:
    #include <avr/io.h>
    #include <stdlib.h> //required for rand()
    #include "Statemanager.h"
    #include "LED.h"
    #include "Idle.h"
    
    
    uint16_t StartedCounter;
    uint8_t RandomDelay;
    void Started_KeyDown(uint8_t index)
    {
    	//Mogelvorbeugung: Abbruch, wenn in diesem Zustand die Reaktionstaste gedrückt wird
    	if (index == 2)
    		Idle_Init(); 
    }
    
    void Started_KeyUp(uint8_t index)
    {
    	//Mogelvorbeugung: Abbruch, wenn in diesem Zustand die Reaktionstaste gedrückt wird
    	if (index == 2)
    		Idle_Init();
    }
    
    void Started_TimerTick()
    {
    	//LED Startsequenz
    	switch(StartedCounter)
    	{
    		case 0:
    		case 1000:
    		case 2000:
    			SetLED2();
    			break;
    
    		case 300:
    		case 1300:
    			ClearLED2();	
    			break;
    	}
    	
    	if (StartedCounter	>= (2000 + RandomDelay))
    	{
    		//MeasureInit();
    	}
    	StartedCounter++;
    }
    
    void Started_Init()
    {
    	StartedCounter = 0;
    	ClearLED1();
    	ClearLED2();
    	RandomDelay = rand() % 500; //0..500 ticks delay
    	AttachState(Started_KeyDown, Started_KeyUp, Started_TimerTick);
    }
    ...mit folgenden Infos...
    - die Beiden ähneln sich doch sehr im Aufbau, wie man unschwer erkennt.
    - Jeder Status captured für sich die Eingangsdaten KeyDown/KeyUp/TimerTick durch die Anmeldung über AttachState.
    - Dieses "Capture" läuft über Funktionszeiger in einem Statemanager, den Du von weiter oben auch schon teilweise kennst

    (.h)
    Code:
    #ifndef STATEMANAGER_H_
    #define STATEMANAGER_H_
    
    
    // function prototypes
    typedef void ( *KeyDownCallback ) ( uint8_t );
    typedef void ( *KeyUpCallback ) ( uint8_t );
    typedef void ( *TimerTickCallback ) ( );
    
    void AttachState(KeyDownCallback keyDown, KeyUpCallback keyUp, TimerTickCallback timerTick);
    void Statemanager_Init();
    
    #endif /* STATEMANAGER_H_ */
    (.c)
    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include "Statemanager.h"
    
    KeyDownCallback keyDownHandler;
    KeyUpCallback keyUpHandler;
    TimerTickCallback timerTickHandler;
    
    uint8_t prevPINA;
    
    void Statemanager_Init()
    {
    	//TODO: Init Timer to 1ms tick
    		
    	prevPINA = PINA;
    }
    
    
    
    
    ISR (TIM0_OVF_vect)
    {
    	//Emit Tick
    	if (timerTickHandler != 0)
    		timerTickHandler();
    		
    
    	uint8_t actPINA = PINA; //buffer actual state
    	uint8_t chPINA = prevPINA ^ actPINA;   //get changes with XOR
    	uint8_t setPINA = chPINA & actPINA;    // get new set pins
    	uint8_t clPINA = chPINA & ~actPINA;    // get new cleared pins
    
    	prevPINA = actPINA; //save actual PINA in prevPINA for next ISR call
    	
    	for (uint8_t i = 0; i<8; i++)
    	{
    		if ((setPINA >>i) & 0x01)
    			if (keyDownHandler != 0)
    				keyDownHandler(i); //Emit KeyDown
    		
    		if ((clPINA >>i) & 0x01)
    			if (keyUpHandler != 0)
    				keyUpHandler(i);  //Emit KeyUp
    	}
    }
    
    
    void AttachState(KeyDownCallback keyDown, KeyUpCallback keyUp, TimerTickCallback timerTick)
    {
    	keyDownHandler = keyDown;
    	keyUpHandler = keyUp;
    	timerTickHandler = timerTick;
    }
    ...erkennst Du vielleicht, worauf ich hinaus will:

    Man braucht die main nur zur Initialisierung,...
    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include "Idle.h"
    #include "StateManager.h"
    
    int main(void)
    {
            //TODO: PORT INIT
    	Statemanager_Init();
    	Idle_Init();
    	sei(); //Enable interrupts
    	
        /* Replace with your application code */
        while (1) 
        {
        }
    }
    …, neue States lassen sich über eine Codevorlage als Modul per C&P und anschließendem Ersetzen von "State_" durch den Statusnamen sehr schnell hinzufügen,...
    Code:
    #include <avr/io.h>
    #include "Statemanager.h"
    #include "LED.h"
    void State_KeyDown(uint8_t index)
    {
    }
    
    void State_KeyUp(uint8_t index)
    {
    }
    
    void State_TimerTick()
    {
    
    }
    
    void State_Init()
    {
    	AttachState(State_KeyDown, State_KeyUp, State_TimerTick);
    }
    …, danach kümmert man sich nur noch um das Wesentliche (das Verhalten des States in den vorgegebenen Funktionsrahmen zu codieren).

    Damit man von einem State zum Nächsten springen kann, braucht man noch jeweils einen Minimalheader:
    Beispiel Started.h
    Code:
    #ifndef STARTED_H_
    #define STARTED_H_
    void Started_Init();
    #endif /* STARTED_H_ */
    ...mickrig!


    Ob das der Königsweg ist, vermag ich nicht zu sagen (Gib 100 Programmierern ein Problem und Du bekommst 100 Lösungen). Aber selbst wenn Du den Timer im 1ms-Takt laufen lässt, sind das bei 8MHz 8000 Takte. Der gesamte oben geschriebene Code nimmt als Kompilat aber nur 1kB Flash in Anspruch. Da ist also bei den berühmten 1..4 cycles per instruction der AVRs noch eine ganze Menge Luft nach oben.

    Bist Du immer noch der Meinung, Du brauchst eine Übergabe der Keys in die main()?
    Geändert von Holomino (08.08.2019 um 13:50 Uhr)

  4. #4
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.06.2019
    Beiträge
    148
    ...bin gerade etwas überfordert - brauche etwas mehr Zeit...
    __________________________________________________ _
    | Sprache: C | Teensy 3.2 | Arduino 2.x | Status: EwigerAnfaenger |

  5. #5
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    18.03.2018
    Beiträge
    2.650
    @frabe

    Ich habe mal ein wenig quer gelesen, die letzten Einträge hier.

    Wenn Du mit Interrupt noch nichts gemacht hast, gehe erst mal in eine Doku zum Tiny und schau mal, wie man einen Interrupt programmiert. Also ein- und ausschaltet und wie man eine Interrupt Service Routine dafür erstellt. Dann machst Du ein kleines Testprogramm, zum probieren. Auf diese Weise lernst Du es verstehen und siehst, welche zeitlichen Reserven in einer Interrupt-Unterbrechung vorhanden sind und wie Du damit arbeiten kannst. Ich denke, das ist für Deine Fragestellung zuträglich. Zuerst verstehen, dann das "Pflichtenheft". Die Anforderungen müssen mit dem zusammenpassen, was umsetzbar ist. Also einfach klein anfangen, normal ergibt sich dann der Rest ziemlich von allein.

    MfG

  6. #6
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.06.2019
    Beiträge
    148
    Zitat Zitat von Moppi Beitrag anzeigen
    Wenn Du mit Interrupt noch nichts gemacht hast, gehe erst mal in eine Doku zum Tiny und schau mal, wie man einen Interrupt programmiert.
    MfG
    Timer-Interrupt und PortChange-Interrupt habe ich in Testprog sicher zu Laufen gebracht - dank Datenbätter und Tuts.
    Aktiviert werde die ISR via sei(); - aber Alle zeitgleich - DAS ist derzeit mein Problem...
    Ich Suche nach einer einfachen(!) sequenziellen Ein-/Ausschaltung bestimmter Pins, die dann durch ISR überwacht werden. Siehe hierzu meinen vorletzten Eintrag.
    __________________________________________________ _
    | Sprache: C | Teensy 3.2 | Arduino 2.x | Status: EwigerAnfaenger |

  7. #7
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    07.04.2015
    Beiträge
    903
    Zitat Zitat von frabe Beitrag anzeigen
    ...bin gerade etwas überfordert - brauche etwas mehr Zeit...
    Nimm sie Dir!

    Der Unterschied zwischen Genie und Normalo ist: Das Genie versteht die Relativitätstheorie sofort, der Normalo braucht dafür etwas Zeit.
    ...manchmal auch etwas mehr als das Leben hergibt.
    Geändert von Holomino (08.08.2019 um 15:51 Uhr)

  8. #8
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    18.03.2018
    Beiträge
    2.650
    Hmmm. Ich hoffe, dass ich Dich richtig verstanden habe.

    Das gemeinsame Ein- und Ausschalten aller Interrupts ist normalerweise kein Problem, sondern so vorgesehen.
    Um einzelne Interruptquellen zu maskieren, gibt es (normalerweise) ein Interrupt-Maskierungs-Register.
    Das scheint sogar bei den ATtiny und dem ATmega für einzelne Pins zu funktionieren.

    PCMSK – Pin Change Mask Register

    Datenblatt ATtiny24/44/84 (7701G–AVR–02/15)

    Seite 47 und 48

    Vielleicht ist es das, was Du suchst.
    Geändert von Moppi (09.08.2019 um 01:11 Uhr)

  9. #9
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.06.2019
    Beiträge
    148
    Verstehe!
    Sowohl beim Timer-Interrupt als auch bei PortChange-Interrupt habe ich immer alles Eingeschaltet.
    Über Funktionen könnte ich auch Pin-genaue Konfiguration gewährleisten. Hier könnte ich über ausgelagerte Funktionen immer nur einen Bit im Register PCMSK0 ein/ausschalten.

    So sah bis lang mein PortChange-Interrupt-Konfig aus;
    Code:
    int main(void)
    {
    	DDRB |= (1<<PB0);	
    	DDRA |= (1<<PA6);	
    	DDRA &= ~((1<<PA4)|(1<<PA5));	
    
    	//Interrupt-Routine wird defeniert
    	GIMSK = (1<<PCIE0);					// Bank0 wird eingeschaltet (PA0-PA7) // BANK1 beinhaltet PB0-PB3
    	PCMSK0 = (1<<PCINT4)|(1<<PCINT5);		// PCINT4(PA4) und PCINT5(PA5) könnte Interrupt auslösen
    	sei();								// Interrupt´s werden gestartet 
    
    	LEDaus();
    	SUMaus();
    	StartBlock();
    	
    	while(1)
      {
    
    								
    	}
    }
    __________________________________________________ _
    | Sprache: C | Teensy 3.2 | Arduino 2.x | Status: EwigerAnfaenger |

Ähnliche Themen

  1. [ERLEDIGT] Interrupt Routine
    Von Saturas077 im Forum Assembler-Programmierung
    Antworten: 8
    Letzter Beitrag: 23.04.2014, 12:46
  2. Codebeispiel für Lesen von RC5 Code mit Interrupt-Routine
    Von -tomas- im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 19
    Letzter Beitrag: 25.05.2011, 12:54
  3. Interrupt Routine
    Von luvat im Forum Schaltungen und Boards der Projektseite Mikrocontroller-Elektronik.de
    Antworten: 4
    Letzter Beitrag: 16.03.2008, 20:54
  4. Interrupt in ISR-Routine freigeben
    Von dj5am im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 5
    Letzter Beitrag: 10.08.2007, 08:44
  5. uart interrupt routine
    Von Computerkora im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 4
    Letzter Beitrag: 25.11.2006, 13:45

Berechtigungen

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

fchao-Sinus-Wechselrichter AliExpress