-         

Ergebnis 1 bis 3 von 3

Thema: externer INT1 Mega8

  1. #1
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    10.03.2005
    Alter
    28
    Beiträge
    967

    externer INT1 Mega8

    Anzeige

    Hallo zusammen,

    ich habe folgenden Code:

    Code:
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    #include <gue.h>
    #include <adc.h>
    
    short currentValue = 0;
    unsigned char condition = 0;
    short threshold = 0;
    
    void init_gue(void)
    {
        // Grenzüberwachung Timer
        TCCR2 |= (1 << WGM21) | (1 << CS01) | (1 << CS00);
        //OCR2 = 250 ergibt 1kHz
        OCR2 = 250; // ergibt 10kHz
        // HW Interrupt Erkennungspin als Eingang definieren
        DDRD &= ~(1 << DDD3);
        // INT1 steigende Flanke
        MCUCR |= (1 << ISC11) | (1 << ISC10);
        // Ausgang für Meldung an die Sollsignalgenerierung
        DDRC |= (1 << DDC5);
        // anschalten, da Perioden Stop low aktiv ist 
        PORTC |= (1 << PC5);
        // SW Notauspin auf Ausgang
        DDRD |= (1 << DDD7);
        // kein Notaus durchführen
        PORTD &= ~(1 << PD7);
    }
    
    void gue_setCondition(unsigned char above)
    {
        condition = above;        
    }
    
    void gue_setValue(unsigned short value)
    {
        threshold = (short)value;
    
        // Threshold Wert ebenfalls transformieren, weil im gleichen Werteraum wie ADC gesendet wird.
        if (threshold >= 2048)
        {
            threshold -= 4096; 
        }
    }
    
    void gue_start(void)
    {
        // "Berichterstattung" für Signal generierung zurücksetzten
        PORTC |= (1 << PC5);
        // condition == 2 soll der SW GÜ ausgeschaltet sein.
        if ((condition == 0) | (condition == 1)){
            // Grenzüberwachung starten
            TIMSK |= (1 << OCIE2);
        }
    
        // INT1    enablen für HW Notaus Erkennung
        GICR |= (1 << INT1);
    }
    
    
    void gue_stop(void)
    {
        // Grenzüberwachung stoppen
        TIMSK &= ~(1 << OCIE2);
        // INT1    disablen
        GICR &= ~(1 << INT1);
    }
    
    void gue_stop_signal(void)
    {
        // fallende Flanke erzeugen
        PORTC &= ~(1 << PC5);
    }
    
    void gue_do_emergency_stop(void)
    {
        // Notaus erzeugen
        PORTD |= (1 << PD7);    
    }
    
    
    ISR(TIMER2_COMP_vect)
    {
        // mit 10kHz Abtastrate schauen, ob man ein Notaus durchführen soll
    
        // aktuellen Wert, der für die zusätzliche Software Grenzüberwachung heran gezogen wird, messen
        //currentValue = (short)adc_read();
    
        // ADC Wert transformieren
        /*if (currentValue >= 2048)
        {
            currentValue -= 4096; 
        }*/
        // Condition = 1 -> wenn istwert GRÖßER als die Schranke
        // Condition = 0 -> wenn istwert KLEINER als die Schranke
        /*if ((condition == 1) & (currentValue > threshold))
        {
            gue_do_emergency_stop();
        }
        if ((condition == 0) & (currentValue < threshold))
        {
            gue_do_emergency_stop();
        }*/
    
        
    }    
    
    ISR(INT1_vect)
    {
        // HW Notaus wurde erkannt --> Sollsignal stoppen!
        gue_stop_signal();
        gue_stop();
        // SW Notaus wieder zurück setzten
        PORTD &= ~(1 << PD7);
    }
    ...und folgendes Problem:

    Während der Initialisierung wird eben auch die Funktion init_gue() aufgerufen. Diese setzt den PC5 auf High Pegel.
    So jetzt kommt von UART ein Trigger, der das Ganze starten lässt bzw. die Funktion gue_start() aufruft.

    Nun mess ich an dem Pin und ich hab nur noch 0V anliegen. Die einzige Möglichkeit, welchen diesen Pin zurücksetzt, führt über die ISR zum INT1. Nach der Initialisierung ist der Pin auf +5V; das hab ich überprüft.

    So jetzt ist mein Verdacht, dass sich der Controller obwohl der INT1 noch nicht eingeschaltet ist, trotzdem die Interrupts registriert und im GIFR Register kenntlich macht. Aber eben keine ISR aufgerufen wird.
    Sobald ich nun den INT1 aktiviere, wird sofort ein Interrupts ausgelöst und in die ISR gesprungen.

    Kann das sein?

    Ich werde morgen mal probieren, vor dem Aktivieren des Interrupts das entsprechende Flag im GIFR zu löschen. Vielleicht hilft das.

    Aber untergekommen ist mir das noch nie. Ich hatte eigentlich damit noch nie Probleme.

    Sollte man somit generell vor dem Aktivieren der Interrupts die entsprechenden Flags löschen?


    Grüße,
    hacker
    Ich würde ja gern die Welt verändern..., doch Gott gibt mir den Quellcode nicht!

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von Jaecko
    Registriert seit
    16.10.2006
    Ort
    Lkr. Rottal/Inn
    Alter
    35
    Beiträge
    1.987
    Das ist so. Wenn eine (konfigurierte) Interruptbedingung vorliegt, wird das entsprechende Flag gesetzt. Erst wenn die Interrupts dann freigegeben werden, wird die jeweilige ISR auch angesprungen. Ist sozusagen ein "Nebeneffekt" der Funktion, dass ankommende Interrupts nicht "vergessen" werden, wenn der Controller selbst gerade eine ISR ausführt.

    Das Löschen der Flags vor dem Aktivieren ist bei mir eigentlich schon gewohnheitsmässig drin. Ob mans braucht oder nicht, hängt davon ab, obs Probleme machen könnte.
    #ifndef MfG
    #define MfG

  3. #3
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    10.03.2005
    Alter
    28
    Beiträge
    967
    Danke. Hat jetzt auch wunderbar funktioniert, so wie es sein sollte.

    Ich werde ab jetzt wohl auch vor jeder Aktivierung eines Interrupts die Flags löschen.
    Ich würde ja gern die Welt verändern..., doch Gott gibt mir den Quellcode nicht!

Berechtigungen

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