- LiFePO4 Speicher Test         
Seite 1 von 2 12 LetzteLetzte
Ergebnis 1 bis 10 von 14

Thema: 1 interrupt vom avr16 für 2 aufgaben ?

  1. #1
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    20.06.2004
    Beiträge
    1.941

    1 interrupt vom avr16 für 2 aufgaben ?

    Anzeige

    E-Bike
    hallo, unten die beiden befehle werden für 2 verschiedene aktion gebraucht,
    der eine für den rc5-code und er andere für den ultra srf04.
    kann man die beiden gleichzeitig so einsetzen?

    TIMSK = 1<<TOIE0;
    TIMSK|= (1<<TICIE1);

    ich habe 2x die interrupt-routine mit verschiedenen aufgaben,
    kann man ein interrupt so für verschiedene aufgaben nutzen?

    void erster_i(void){
    SIGNAL (SIG_OVERFLOW0)
    {}

    }

    void zweiter_i(void){
    SIGNAL (SIG_OVERFLOW0)
    {}

    }


    void main(void){
    sei;
    zweiter_i;
    erstrer_i;
    ;

    mfg
    pebisoft

  2. #2
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    22.11.2003
    Beiträge
    991
    Ich versteh ehrlich gesagt nicht was du genau machen willst. So wie du es im Moment geschrieben hast kannst du das auf keine Fall machen. Man kann nicht einfach eine Funktion zweimal definieren...

    Du kannst natürlich eine Interruptroutine für verschiedene Sachen nutzten, allerdings musst du da dann in der Routine auswählen welche Aktion gerade durchgeführt wird.

    Code:
    volatile uint8_t aktion;
    
    SIGNAL (SIG_OVERFLOW0)
    {
      if (aktion == 1)
        // mach irgendwas....
      else if (aktion == 2)
       // mach was anderes...
    }
    MfG Kjion

  3. #3
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    05.11.2004
    Ort
    Karlsruhe
    Beiträge
    223
    so wie ich das lese will er einfach nur 2 Dinge in einem IRQ machen. Aber wo liegt das Problem 2 Funktionen zu schreiben und die dann im IRQ aufzurufen?

    void tu_was( void ) { foobar; }
    void tu_wasanderes( void ) { blah; }

    void irq_handler( void )
    SIGNAL( irgendeins )
    {
    tu_was();
    tu_wasanseres();
    }

    Warum er versucht die Funktionen vom main() aus aufzurufen ist mir aber absolut nicht klar.

  4. #4
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    28.04.2004
    Ort
    Nähe Köln
    Alter
    57
    Beiträge
    247
    Hallo

    Schade das die Leute oft nicht genauer sagen, was sie erreichen wollen.

    Mit solchen Code Fetzen kann man nicht richtig helfen.

    @bluebrother

    Den Tip, aus einem INT Funktionen aufzurufen halte ich aber für sehr gefährlich. Lieber in der INT ein Bit setzen in einem eigenen Staus Reg. und dann im Hauptprogramm auswerten, oder so wie Kjörn es gemacht hat.

    Und INT so kurz wie möglich halten

    MFG
    Dieter

  5. #5
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    20.06.2004
    Beiträge
    1.941
    hallo kjion, der rc5 braucht eine genaue zeitmessung von einer bestimmten zeit um die daten auszuwerten. die sendediode braucht zum senden auch eine bestímmte frequenz. ich wollte beim senden die frequenz haben für die diode und beim empfangen die zeit um die bits aus den tsop rausholen und umwandeln. sonst braucht jeder seinen eigenen timer.
    mfg pebisoft

  6. #6
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    20.06.2004
    Beiträge
    1.941
    hallo, kann man innerhalb des interrupt bei der jeweiligen funktion tu_was() den timer auf 0 setzen, damit der zähler hier dann wieder von neuem beginnen kann bis zum überlauf.
    mfg pebisoft

  7. #7
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    22.11.2003
    Beiträge
    991
    Zitat Zitat von pebisoft
    hallo, kann man innerhalb des interrupt bei der jeweiligen funktion tu_was() den timer auf 0 setzen, damit der zähler hier dann wieder von neuem beginnen kann bis zum überlauf.
    Klar kann man das. Warum auch nicht ?? Allerdings halte ich es für keine gute Idee in den Interrupts Funktionen aufzurufen. Dies hat zwei Gründe:
    1.) Man weiß nicht genau/vergisst es wie lange diese Funktion die man aufruft dauert. Das kann insbesondere bei UART oder dem Timer zu sehr seltsamen Effekten führen, da dann quasi ständig die Interrupts aufgerufen werden ( der eine ist zum Beispiel noch nicht fertig während der nächste schon wieder ausgelöst wird. )
    2.) Der Compiler weiß nicht welche Register in der Int Routine benutzt werden und sichert deswegen alle! auf den Stack. Diese dauert einfach ein bißchen, wenn man also eine kurze Interruptroutine haben will so sollte man den ganzen Code dort hineinschreiben!

    Ob sich die RC5 Auswertung und die Frequenzerzeugung für die Sendediode in einem Interrupt verarbeiten lassen musst du selbst wissen. Entweder du wählst den Int so, dass er dem kleinsten gemeinsamen Takt entspricht ( geht nicht immer, ist aber einfacher ), oder du musst dir das ganze so genau zusammenbasteln, dass das Timing wieder stimmt.

    MfG Kjion

    PS: Könntest du nicht ab und zu die Großschreibetaste benutzten ?? Das würde deine Text wesentlich leserlicher machen..

  8. #8
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    23.05.2004
    Ort
    Untersöchering(Bayern,Alpenvorland)
    Alter
    37
    Beiträge
    215
    Pepisoft was du doch willst ist mit einem Timer mehrer Zeiten messen. Also Ultraschall, rc5 und PWM von deinem Kompass. Der Timer1 hat hat nur einen Input Capture Pin (für srf04). Du kannst aber die Externen Interrupt Pins benutzen.
    Ich hab hier mal Code:
    Code:
    // geändert auf 8MHZ
    #include <io.h>
    #include <avr/delay.h>
    
    #define US_PORT            PORTD
    #define US_PORT_RICHTUNG   DDRD
    #define US_PIN             PD7         // Der Pin kommt zum Trigger-Puls Eingang  
    
    volatile unsigned int us_zeit=0;
    volatile unsigned int zeit_int0=0,zeit_int1=0;      // geändert
    
    SIGNAL(SIG_INTERRUPT0)
    {
        zeit_int0=TCNT1;     // geändert
        TCCR1B= ~(1<<CS12) & ~(1<<CS11) & ~(1<<CS10);     // Timer wieder aus
        TCNT1=0;
    }
    
    SIGNAL(SIG_INTERRUPT1)
    {
        zeit_int1=TCNT1;       // geändert
        TCCR1B= ~(1<<CS12) & ~(1<<CS11) & ~(1<<CS10);     // Timer wieder aus
         TCNT1=0;
    }
    
    SIGNAL(SIG_INPUT_CAPTURE1)         // Interrupt für US Zeitmessung
    {
        us_zeit=ICR1; 
        TCCR1B= ~(1<<CS12) & ~(1<<CS11) & ~(1<<CS10);     // Timer wieder aus
        TCNT1=0;
    }               
    
    unsigned char start_us_messung(void)           // Ultraschallmessung
    {
        unsigned char wert,wert_in_cm;
    	        
        // PD6 ist Input Capture Pin beim ATMega8, hier kommt der Echo-Pulse Ausgang hin
        TIMSK|= (1<<TICIE1);          // Input Capture Interrupt enable	
        TCCR1B&=~(1<<ICES1);   // Fallende Flanke für Input Capture
        US_PORT|=(1<<US_PIN);       // Trigger-Puls Eingang high
        _delay_us(15);          // Laut Datenblatt Trigger-Puls min 10us auf high
        _delay_us(15);           // Laut Simulator ist wartet _delay_us() nur die 
                                        // hälfte der Zeit
        US_PORT&=~(1<<US_PIN);   // Trigger-Puls Eingang wieder auf low
        _delay_us(185);                  // Erst wird ein 200us langer 40kHz Burst vom srf04 gesendet
        _delay_us(185);
        TCCR1B|=(1<<CS11); // Prescaler 8,     startet Timer
        while(us_zeit==0);        // Warten bis Ergebnis
        if(us_zeit>19000)       // Dann kein Objekt vor den Sensor
        {
             wert=0;
             us_zeit=0;
             return wert;
        }
        else
        {
           wert=172*us_zeit/10000;   // wert ist nun in cm       
           us_zeit=0;
           return wert;
        }
    }
    
    
    // Zeitmessung mithilfe von Externem Interrupt 0 und Timer1
    unsigned long long star_zeitmessung_int0(unsigned char flag) // flag = 1 fallende Flanke generiert Interrup
    {                                                               // flag = 2 gegenteil
        unsigned long long wert;
        if(flag==1)
           MCUCR|=(1<<ISC01);
        if(flag==2)
           MCUCR=(1<<ISC01|(1<<ISC00);
        GICR |=(1<<INT0);         // Externer Interrupt an
        TCCR1B|= (1<<CS11); // Timer an, Prescaler 8 damit Zeitäuflösung genau 1 micro sekunde !!!   geändert
        while(zeit_int0==0);     // Warten bis Ergebnis
        wert=zeit_int0;         // Wert in micro sekunden
        zeit_int0=0;        // Wieder auf 0 setzen für nächste Messung
        return wert;
    }
    
    // Zeitmessung mit Externem Interrupt1 und Timer1
    unsigned long long start_zeitmessung_int1(unsigned char flag)
    {
        unsigned long long wert;
        if(flag==1)
        MCUCR|=(1<<ISC11);
        if(flag==2)   
           MCUCR=(1<<ISC11) | (1<<ISC10);
        GICR|=(1<<INT1);
        TCCR1B|= (1<<CS11);  // Timer an, Prescaler 8   geändert
        while(zeit_int1==0);
        wert=zeit_int1;
        zeit_int1=0;
        return wert;
    }
    
    void main (void)
    {
        unsigned char wert;
        unsigned long long wert1,wert2;
        US_PORT_RICHTUNG|=(1<<US_PIN);         // US_PIN auf Ausgang
        wert=start_messung();
        wert1=start_zeitmessung_int0();
        wert2=start_zeitmessung_int1();
    }
    Damit kann man mit einem Timer alle deine drei Ereignisse messen. Die Funktionen start_zeitmessung_intX() geben dir nur die Zeit in micro sekunden zurück. Was du damit machst (umrechnen in Grad bei Kompass, rc5 usw.) ist dir überlassen. In deinem Fall muss halt z.B. den Out Pin von deim TSOP auf einen der Externen Interrupt Pins von deinem ATMega. Allerdings weis ich immer noch nicht was passiert wenn der Timer mehr als 1mal durchläuft, also nach 262,144 millisekunden. Um den sozusagen Höchsmesswert zu erhöhen kann man den Prescaler in den Funktionen start_zeitmessung_intX() verändern und in den Interrupts in den Zeilen zeit_intX=TCNT1*4; das *4 dementsprechend ändern. Hoffe man hats verstanden.
    Gruß Muraad

    EDIT: nochmal geändert, das mit TCCRB1 und TICIE1

    EDIT: Code funktioniert nicht richtig. Bitte in den Thread schauen:
    https://www.roboternetz.de/phpBB2/vi...?p=67114#67114
    Alle sind unzufrieden - und alle machen weiter wie bisher.

  9. #9
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    20.06.2004
    Beiträge
    1.941
    hallo, vielen. ich bewundere dich, wie du das mit den timern so machen kannst. alle achtung. bei mir wird es noch länger dauern, bis ich das begriffen habe. ich schlage dauernd in der avr-datei nach für den AVR16, ist in englisch und hat wie du weisst über 300 seiten. eine bitte ,ich habe den AVR16 mit 8mhz. was muss ich jetzt an deinen zeiten noch ändern.
    extern habe ich 16mhz dran, weis aber nicht, wie ich die fusebits für diesen externen einstellen soll???
    danke
    mfg pebisoft

  10. #10
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    23.05.2004
    Ort
    Untersöchering(Bayern,Alpenvorland)
    Alter
    37
    Beiträge
    215
    Also ich hab den Code oben geändert.
    Aber die max. Zeit die du jetzt messen kannst ist bei 65535us also 65,535 millisekunden. Wobei sich das auch irgendwie ändern liese. Und das Warten auf ein neues Ergebniss mit while(zeit_int0==0); ist auch nicht sehr elegant. In einem Roboter würde ich in regelmäßigen abständen (geregelt durch Timer0 oder Timer2) eine neue Messung starten und gleichzeitig das Ergebniss der alten Messung abholen.
    Gruß Muraad

    EDIT: Ich hab hier die start_us_messung() auch nochmal auf 8Mhz geändert da im Datenblatt vom srf04 steht das es eine Pulsweite von max. 40ms zu messen gibt. Womit hier die 65,535ms max. Messzeit ausreichen. Nochmal zur Höchstmesszeit: 8Mhz/8 Prescaler= 1.000.000Hz
    1/1.000.000Hz=1micro sekunde Takt. Timer1 hat 16Bit also 2<hoch>16=65536 Takte bis er überläuft. Da ich nicht weis was in dem Fall passiert wenn er überläuft "Höchstmesszeit".
    Wobei es sich auch ändern lassen würde aber da müsst ich jetzt mehr drüber nachdenken. Mit Fusebits kenn ich mich nicht so gut aus. Ich hab sie bei meinem RN-Control noch nie verändert. Aber auch weil bei mir PonyProg nicht funktioniert und ich sie, wenn überhaupt, damit verändert hätte.

Seite 1 von 2 12 LetzteLetzte

Berechtigungen

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

MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad