-         

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

Thema: 2 ISR gleichzeitig?

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    24.08.2009
    Beiträge
    30

    2 ISR gleichzeitig?

    Anzeige

    Kann man 2 ISR gleichzeitig laufen lassen? Macht das Sinn?

    Ich verwende bereits einen Zeitgeber in meinem Programm der auf 10ms definiert ist, mit dem ich die Tasten abfrage (kurz oder lang gedrückt):

    Code:
    ISR(TIMER0_OVF_vect)
    {
    	static uint8_t ct0, ct1, rpt;
    	uint8_t i;
    
    	TCNT0 = (uint8_t)(int16_t)-(F_CPU / 1024 * 10e-3 + 0.5);
    
    	i = key_state ^ ~KEY_PIN;								// Taste geändert?
    	ct0 = ~(ct0 & i);										// resete oder zähle CT0
    	ct1 = ct0 ^ (ct1 & i);									// resete oder zähle CT1
    	i &= ct0 & ct1;											// Überlauf gezählt?
    	key_state ^= i;											// dann Entprellstatus ändern
    	key_press |= key_state & i;								// 0->1: Tastendruck erkannt
    
    	if((key_state & REPEAT_MASK) == 0)						// Überprüfe Tastenwiederholfunktion
    		rpt = REPEAT_START;									// Starte Verzögerung
    	if(--rpt == 0)
    	{
    		rpt = REPEAT_NEXT;									// Wiederhole Verzögerung
    		key_rpt |= key_state & REPEAT_MASK;
    	}
    }
    Jetzt bräuchte ich jedoch noch einen der mir eine Variable in einer frei definierten Zeit (mittels Variable) zwischen HI/LOW toggelt.[/code]

  2. #2
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    07.07.2005
    Beiträge
    232
    zwei ISRs können meines Erachtens nicht gleichzeitig laufen.
    Schau mal ins Datenblatt. Da ist eine Liste der Interruptprioritäten.
    Heißt soviel wie:
    wenn gerade eine ISR mit niedrigerer Priorität läuft und ein höherpriorisierter Interrupt eintrifft, wird die aktuelle ISR unterbrochen und die höherwertige abgearbeitet. Dann gehts in der anderen weiter.
    Für mein Verstädnis sollte deine Lösung gut funktionieren. Hätte ich genauso gemacht und ist glaube ich Goldstandard

    Gruß Tim

  3. #3
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    7.551

    Re: 2 ISR gleichzeitig?

    Hi,

    Zitat Zitat von DerSchatten
    Kann man 2 ISR gleichzeitig laufen lassen? Macht das Sinn? ...
    Gleichzeitig geht bei Rechnern (fast) garnix.

    Tim/Ls4 hat schon auf die unterschiedlichen Priorisierungen hingewiesen. Wenn zwei ISR "gleichzeitig" anfallen, dann wird die höher priorisierte zuerst gestartet. Ansonsten startet die, die zuerst aufgerufen wird und verbietet damit allen nachfolgenden einen neuerlichen Interrupt durchzuführen - der kommt auf ne Warteliste. Dieses Verfahren läuft in einigen meiner Projektchen völlig störungsfrei: Timer0, Timer1, LED-blinken, ADC auslesen, extINT0 und extINT1 - also sozusagen "viele" Interrupts, die in mehr oder weniger zufälliger Reihenfolge daherkommen.

    Deine Frage berührt noch etwas. WENN Du nun eine ISR hast, die beispielsweise (leider) nicht so hoch priorisiert ist, wie Du möchtest, dann kannst Du die trotzdem bevorzugen. Das Stichwort heißt "nested interrupts" - und braucht eine sehr saubere Organisation vor allem der in den jeweiligen ISRn behandelten Daten. Dabei wird beim Aufruf der ISR durch Deine Software das Interrupt enable bit gesetzt "sei();" - das ansonsten erst beim RETI von der controllerinternen Organisation gesetzt wird. JETZT kann ein beliebiger anderer Interrupt SEINE ISR aufrufen - die laufende ISR wird dann genauso unterbrochen, wie das "normale" Programm. Steht in den docs z.B. im Kapitel Reset and Interrupt Handling und liest sich so:

    Zitat Zitat von At[size=1
    [/size]mel-doc 8161D–AVR–10/09]... When an interrupt occurs, the Global Interrupt Enable I-bit is cleared and all interrupts are disabled. The user software can write logic one to the I-bit to enable nested interrupts. All enabled interrupts can then interrupt the current interrupt routine. The I-bit is automatically set when a Return from Interrupt instruction – RETI – is executed ...
    Ciao sagt der JoeamBerg

  4. #4
    Benutzer Stammmitglied
    Registriert seit
    24.08.2009
    Beiträge
    30
    Ok, ich habe gerade noch den Tip bekommen mehrere Aufgaben dem selben Timer zukommen zu lassen. D.h. man nimmt einfach die bereits definierte Timerzeit her und rechnet für seine zwecke die benötigte dann dazu.

  5. #5
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    7.551
    Zitat Zitat von DerSchatten
    Puh, das klingt alles sehr komplex ...
    klingt nur so.

    Zitat Zitat von DerSchatten
    ... Also wenn ich mit sei() den Interrupt starte wird zuerst der höher abgearbeitet. Wenn aber jetzt das Verhalten des ersten Interrupts nie eintritt wird der niedere nie abgearbeitet?
    Wieso das denn? Wenn Du am ersten Platz der Warteliste stehst - und beim Aufruf nicht erscheint - dann darf doch der nächste mitfliegen/fahren/etc - oder nicht? GENAUSO ist es bei den Interrupts.

    Der Interrupt wird abgearbeitet:
    a) wenn er erlaubt ist : sei();
    b) wenn ein Auslöser kommt
    b1) der kann z.B. in einer Initialisierungsroutine - z.B. init_TC0 - Initialisiere Timer Counter 0 vorbereitet werden
    c) wenn keine andere ISR läuft
    d) wenn nicht gleichzeitig ein anderer, höher priorisierter IR kommt
    e) wenn eine ISR da ist. Kommt schon mal vor dass ein IR kommt - und keine ISR da ist - dann gibts ein bisschen Konfusion (aber das behandeln wir später)
    f) wenn der Rechner/Controller (noch) läuft *ggg*

    Zitat Zitat von DerSchatten
    ... Also wenn ich mit sei() den Interrupt starte ...
    Du weißt sicher, dass dies nicht die einzige Startbedingung ist - das kann variieren. DENN sei(); ist eine notwendige, aber nicht immer eine hinreichende Bedingung. Manchmal sind weitere Initialisierungen und Interrupt enable Flags notwendig oder sonstwiewasauchimmer.
    Ciao sagt der JoeamBerg

  6. #6
    Erfahrener Benutzer Begeisterter Techniker
    Registriert seit
    07.07.2005
    Beiträge
    232
    Hi Schatten,

    du kannst auch z.b. wenn du einen Timer im CTC Modus laufen hast 2 verschiedene compare Matches auslösen.
    einmal für OCRxA und einmal für OCRxB. Das geht natürlich nicht für jede Anwendung, sondern nur wenn die Zeiten passen (da der Timer ja nur einmal resettet wird)

    Gruß Tim

  7. #7
    Benutzer Stammmitglied
    Registriert seit
    24.08.2009
    Beiträge
    30
    Sagt, wie toggle ich zwischen 0x00 und 0x01?

    So gehts ja nicht:

    Code:
      if( cntTicks == Fire )      // zb nach <Fire> mal 10ms
      {
        repeatMask ^= 0x01;   // von 0x00 nach 0x01
                        // und umgekehrt: von 0x01 nach 0x00
        cntTicks = 0;
      }

  8. #8
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    7.551
    Zitat Zitat von DerSchatten
    ... Sagt, wie toggle ich zwischen 0x00 und 0x01 ...
    Ich mach das meistens "zweiteilig":
    Code:
     #define rLED    3              // Rote LED       auf PB3
     #define ToggleBit(ADDR,BIT)    ((ADDR) ^= (1<<(BIT)))  // Toogelt Bit
    Dann kann man irgendwo dies machen - und das liest sich recht gut:
    Code:
      ToggleBit (PB, rLED);        //
      ToggleBit ( repeatMask, 0 )    // Toggelt Bit 0
    Ansonsten gehts eben so (WENN repeatMask ein Byte ist) :
    Code:
      PORTC ^=  (1<<PC4);    // Port PC4 toggeln
      repeatMask  ^=  (1<<0);
    Ciao sagt der JoeamBerg

  9. #9
    Benutzer Stammmitglied
    Registriert seit
    24.08.2009
    Beiträge
    30
    Danke, das mit dem Tooglen ist nun klar.

    Ich hab noch ein kelines Problem wo ich nicht weiß wie ich das lösen soll:

    Mittels Tabelle weise ich bestimmten Eingänge, bestimmte Ausgänge zu:

    Code:
    #define LED0			(1<<PC0)
    #define LED1			(1<<PC1)
    #define LED2			(1<<PC2)
    #define LED3			(1<<PC3)
    #define LED4			(1<<PC4)
    #define LED5			(1<<PC5)
    
    #define NR_KONFIGS		9
    #define NR_KEYS			6
    
    uint8_t Pattern[NR_KONFIGS][NR_KEYS] PROGMEM =
    	{
    		{LED0,LED1,LED2,LED3,LED4,LED5},					// Konfiguration 0
    		{LED0,LED2,LED4,LED1,LED3,LED5},					// Konfiguration 1
    		{LED2,LED0,LED4,LED1,LED3,LED5},					// Konfiguration 2
    		{LED0,LED2,LED4,LED1,LED3,LED5},					// Konfiguration 3
    		{LED0,LED2,LED4,LED1,LED3,LED5},					// Konfiguration 4
    		{LED0,LED2,LED4,LED1,LED3,LED5},					// Konfiguration 5
    		{LED0,LED2,LED4,LED1,LED3,LED5},					// Konfiguration 6
    		{LED0,LED2,LED4,LED1,LED3,LED5},					// Konfiguration 7
    		{LED0,LED2,LED4,LED1,LED3,LED5},					// Konfiguration 8
       };
    Die dann im main abgerufen wird:

    Code:
    	while(1)
    	{
    		Summe = 0;
    
    		if(!(KEY_PIN & 0x01))								// Wenn Taste PortB.0 auf HIGH
    			Summe |= pgm_read_byte(&Pattern[nKeyPress][0]);
    		if(!(KEY_PIN & 0x02))								// Wenn Taste PortB.1 auf HIGH
    			Summe |= pgm_read_byte(&Pattern[nKeyPress][1]);
    		if(!(KEY_PIN & 0x04))								// Wenn Taste PortB.2 auf HIGH
    			Summe |= pgm_read_byte(&Pattern[nKeyPress][2]);
    		if(!(KEY_PIN & 0x08))								// Wenn Taste PortB.3 auf HIGH
    			Summe |= pgm_read_byte(&Pattern[nKeyPress][3]);
    		if(!(KEY_PIN & 0x10))								// Wenn Taste PortB.4 auf HIGH
    			Summe |= pgm_read_byte(&Pattern[nKeyPress][4]);
    		if(!(KEY_PIN & 0x20))								// Wenn Taste PortB.5 auf HIGH
    			Summe |= pgm_read_byte(&Pattern[nKeyPress][5]);
    
    		OUT_PORT = Summe;									// sonst nur definierte Konfiguration ausgeben
    Jetzt soll das Togglen des PortC.0 da inkludiert werden falls eine Taste gedrückt wird. Jedoch nur wenn eine Variable auf 1 gesetzt ist.

    Ich dachte mir das zuerst so:

    Code:
    if(Dauerfeuer= 1) // Wenn Dauerfeuer aktiv
    {
    OUT_PORT = Summe | repeatMask;                  // Definierte Konfiguration mit Dauerfeuer an Ausgang PortC.0 ausgeben
    }
    else
    {
    OUT_PORT = Summe // sonst nur definierte Konfiguration ausgeben
    }
    Der Toggleeffekt funktioniert zwar, geht jedoch natürlich sofort los, auch wenn keine Taste gedrückt ist.

    Wie kann ich das am ellegantesten lösen?

  10. #10
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    02.11.2005
    Alter
    42
    Beiträge
    1.140
    Ist fast ok, da ist nur der Vergleichsoperator falsch.
    Ersetze einfach
    Code:
    if (Dauerfeuer=1)
    durch
    Code:
    if (Dauerfeuer==1)
    //oder noch einfacher
    if (Dauerfeuer)
    Gruß,
    askazo

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

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