- LiTime Speicher und Akkus         
Seite 1 von 4 123 ... LetzteLetzte
Ergebnis 1 bis 10 von 32

Thema: CTC + timer0 auf mega16 - geben keinen Interrupt (auch m168)

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

    CTC + timer0 auf mega16 - geben keinen Interrupt (auch m168)

    Anzeige

    Praxistest und DIY Projekte
    Nach etlichen Mühen sollte es laufen. Sollte. Tuts nicht. Was sollte laufen und was läuft nicht?

    Am mega16 auf der RNControl soll ein CTC-Interrupt eine Variable im 10 kHz Takt hochzählen (bis 50 000, danach 0...). Diese Zeitmarke wird in zwei externen ISR für EXT0 + EXT1 (von asynchronen Taktgebern - Drehgeber) ausgewertet.

    Das komplette Programm wurde für Testzwecke auf die Timerroutinen zurückgestutzt und getestet. Testziel: LED auf PC4 toggeln.

    Es geschieht - nein, nicht nix - noch schlimmer.

    1) PC4 auf high (LED ist aus), auch PC2, 3 und 5.
    2) PC0,1 und PC6,7 sind low (LED leuchtet) - das hatte ich nirgendwo gesagt.
    3) Timer läuft wohl nicht - weil LED statisch aus ist.
    4) andere PC-Ports sind auch statisch (sagt Oskar).

    Will bitte jemand helfen?
    A) Was habe ich bei der Timerinitialisierung falsch gemacht? bzw. besser
    B) Wie mache ich die Timerinitialisierung richtig?
    C) Ist die ISR ok?
    D) na ja, wenn sonst was Übles auffällt

    Die vollständige Quelle der Testvariante (ohne "andere" Routinen) mit der die hier beschriebene Fehlfunktion entsteht.

    Code:
    /* >> Diese ersten 2 Zeilen können zum Compilieren entfernt werden (muss nicht)
      Sicherung 17dez07 hhmm nach Datei ..C1..\2_drehzahlen\2_drehzahlen-xxx.c
     ===================================================================================
     ========== Beachte: printout aus AVRStudio geht (nur) bis col 85 ==================
      Target MCU        : ATmega16
      Target Hardware   : RNControl
      Target cpu-frequ. : 16 MHz, externer Quarzoszillator
     ===================================================================================
      Enthaltene Routinen:
    	static inline void setportdon/~off
    	void XTI_01_init( void )	// ISR ext0+1 initialisieren
    	void TMR_0_init( void )		// Timer initialisieren 10 ms
    	... (testweise gestrichen)
    	SIGNAL (SIG_INTERRUPT0)		// ISR Motor/Speed1
    	SIGNAL (SIG_INTERRUPT1)		// ISR Motor/Speed2
    	SIGNAL(SIG_OVERFLOW0)
    	int main(void)
     ===================================================================================
      *** Versionsgeschichte:
     ====================
     x11 17dez07 17:mmff Test - seltsame Ergebnisse - Timer timt nicht 
     x10 17dez07 15:43 Erster Codeausbau fertig zum Test (sichern und LED-Test mit 
     				dem Timer0
     x01 16dez07 23:42 Sichern des ersten Standes - ohne Timer-Interrupt-Routine
     x00 16dez07 14:30ff erster Aufbau
     ===================================================================================
      *** Aufgabenstellung : Messen von 2 Motordrehzahlen
      Es werden Impulse von zwei Gabellichtschranken am µC erfasst. Daraus werden
        zwei Drehzahlen errechnet.
        Drehzahlbereich von 0 (Stillstand) bis 1kHz (60 000 Upm)
    
        Grundlage wird ein Timerinterrupt mit ...
    
      Original: ...C1..\C-motst_x10\C_motst_x21_OK.c
     ===================================================================================
                                                                                      */
    /* ============================================================================== */
    
    #include <stdlib.h> 
    #include <avr/io.h> 
    #include <avr/interrupt.h>
    /* Beachte C:\Programme\WinAVR-20070525\avr\include\avr\iom16.h */
    
    #define MCU = ATMega16 
    
    //   Mit Quarz 16 Mhz-CPU 
    #define F_CPU  16000000 
    
    /* ============================================================================== */
    /*   Interrupt-Handler und -Adressen
    Address Labels Code Comments
    siehe C:\Programme\WinAVR-20070525\avr\include\avr\iom16.h sowie
    Interruptvektoren/-vektortabelle in *doc2466, S 45+46 von AVR                    */
    
    /* beachte: volatile!  und   Vorzeichenlos reicht für alle                   */
    volatile uint16_t Iencdr1, Iencdr2;	/* Counter für Encoder-ticks
      Werden in der ISR hochgezählt und im main bei Gelegenheit
        (welcher? - nach 5 sec?) - spätestens aber beim Fahrtrichtungswechsel
        auf Null gesetzt. DAnn aber die Werte musv+musi entsprechend anpassen    */
    volatile uint16_t Iz_ysecv1, Iz_ysecv2;	/* Zeitmarke "µsec"
      des vorletzten Interrupts in der Einheit 100 Mikrosekunden. Ist der Wert des
      hochlaufenden Timers zum Interruptzeitpunkt i-1                            */
    volatile uint16_t Iz_yseci1, Iz_yseci2;	/* Zeitmarke "µsec"
        des letzten Interrupts in der Einheit 100 Mikrosekunden. Ist der Wert des
        hochlaufenden Timers zum Interruptzeitpunkt i (letzter Interrupt)        */
    volatile uint16_t Iz_diff1, Iz_diff2;	/* Zeitdifferenz
      Beim Abarbeiten des Interrupts wird yseci mit time1 belegt und diff aus der
        Differenz yseci-ysecv errechnet. Danach wird yseci nach ysecv kopiert.
        Im main wird aus diff die Drehzahl berechnet.                            */
    volatile uint16_t Izeit_1;			/* Timer läuft hoch
      Die Interruptroutine läuft mit 10 kHz (Möglicherweise sind 100 kHz besser)
        Beim Start des Timers läuft der Zähler time1 hoch und wird nach 5 sec -
        also beim Wert 50 000 - wieder auf Null gesetzt. Dabei werden die Werte
        ysecv und yseci angepasst                                                  */
    /* ============================================================================== */
    
    /* ============================================================================== */
    
    /* =================================================================================
       ##### Hier ISR und ISR - Initialisierung(en)
    ================================================================================= */
    /* ===  Initialisierung fuer EXT_INT0/1 auf Pin 16+17/mega16(32)  ==================
    $002 jmp SIG_INTERRUPT0 ; IRQ0 Handler und
    $004 jmp SIG_INTERRUPT1 ; IRQ1 Handler                  */
    void XTI_01_init( void )	
    {				//Initialisiere beide Interrupts auf rising edge
    				//  d.h. MCUCR ISC00,01,10+11 auf 1 (doc,S68)
        MCUCR |= (1<<ISC11)|(1<<ISC10)|(1<<ISC01)|(1<<ISC00);
        GICR  |= (1<<INT1)|(1<<INT0);	//  und erlaube diese I´s in GICR
    }
    /* ============================================================================== */
    
    
    /* ===  Initialisierung fuer Timer0 8-bit mega16(32)  ==============================
    Aufruf als  SIGNAL (SIG_OVERFLOW0)                  */
    void TMR_0_init( void )	
    {				//Initialisiere 8-Bit-Timer auf 10 kHz
        TCCR0 |= (1<<CS02 | 0<<CS01 | 1<<CS00); // Prescaler 1024 / Clock <- CPU
        TCCR0 |= (1<<WGM01 | 0<<WGM00);	// Timer im CTC-Mode
        TCNT0 = 0x64;   			// Timer0 Counter 0x64 für 10ms bei 16Mhz 
    
        TIMSK |= (1<<OCIE0); 		// Compare Match IRQ 
    
    }
    /* ============================================================================== */
    
    
    /* ===  Nicht unterbrechbare ISR für EXT_INT0 auf Pin 16/PD2/mega16(32)  ======== */
    /* Routine setzt einfach einen Zähler hoch. Der Zähler wird im main
         ausgelesen ##>> cli/sei setzen <<## und nach 2 (od. 5) hunderstel Sekunden
         auf den Speicher WEG_L/_R vorzeichenrichtig aufaddiert und dann zurückgesetzt.
         ##>> Beim Richtungswechsel (cli/sei) wird der Zähler ausgelesen und genullt,
         damit ist eine saubere Wegmessung möglich.
         Der zugehörige Motor auf RNControl auf PB0/PB1 = li,re und PD5 Geschwind.
         Der alternat.  Motor auf RNControl auf PC7/PC6 = li,re und PB4 PWM/Geschw.
    $002 jmp EXT_INT0 ; IRQ0 Handler                  */
    SIGNAL(SIG_INTERRUPT0)
    {
        Iencdr1 ++;			//zähle Counter/encoder 1 hoch
        Iz_yseci1 = Izeit_1;		//Weise musi den akt. Timerwert zu
        Iz_diff1 = Iz_yseci1-Iz_ysecv1;	    //Neue Zeit-Differenz1 ausrechnen
        Iz_ysecv1 = Iz_yseci1;		//der aktuelle Zeitwert wird "Alter"
    }
    /* ============================================================================== */
    
    
    /* ============================================================================== */
    /* ===  Nicht unterbrechbare ISR für EXT_INT1 auf Pin 17/PD3/mega16(32)  ======== */
    /* Routine setzt einfach einen Zähler hoch.
          Sonst wie ISR für EXT_INT0 für Motor auf PC7/PC6 = li,re und PB4 PWM/Geschw.
    $004 jmp EXT_INT1 ; IRQ1 Handler                  */
    SIGNAL(SIG_INTERRUPT1)
    {
        Iencdr2 ++;			//zähle Counter/encoder 2 hoch
        Iz_yseci2 = Izeit_1;		//Weise Iz_yseci den akt. Timerwert zu
        Iz_diff2 = Iz_yseci2-Iz_ysecv2;	//Neue Zeit-Differenz2 ausrechnen
        Iz_ysecv2 = Iz_yseci2;		//der aktuelle Zeitwert wird "Alter"
    }
    /* ============================================================================== */
    
    
    /* ============================================================================== */
    /* ===  Nicht unterbrechbare ISR für timer ====================================== */
    /* Diese Routine zählt hoch im Takt 10 kHz.setzen.
          Dieser Wert wird von den beiden anderen ISR ausgelesen und den Werten
    
    */
    // SIGNAL(SIG_OVERFLOW0)
    // #define SIG_OUTPUT_COMPARE0	//Interuptvektor, siehe Tabelle
    SIGNAL(SIG_OUTPUT_COMPARE0)
    {
        Izeit_1 ++;              //Zeitstand des Interupt-Timers
    
    
    
        PORTC ^= (1 << PC4);	//LED toggeln
    
    
    
    }
    /* ============================================================================== */
    
    
    
    
    // ------------------------------------------------------------------ 
    /*### Hauptschleife ###*/ 
    int main(void) 
    {
    	DDRC |= 0xFF;	//11111111 -> PC6 und PC7 linker Mot, Rest LEDs/Lauflicht
    
        TMR_0_init();
        sei();
    
    for(;;)	{ 
    	}
    }
    oder in einer gekürzten Fassung, mit den "kritischen" Routinen:

    Code:
    #include <stdlib.h> 
    #include <avr/io.h> 
    #include <avr/interrupt.h>
    /* Beachte C:\Programme\WinAVR-20070525\avr\include\avr\iom16.h */
    
    #define MCU = ATMega16 
    
    //   Mit Quarz 16 Mhz-CPU 
    #define F_CPU  16000000 
    
    /* ============================================================================== */
    /*   Interrupt-Handler und -Adressen
    Address Labels Code Comments
    siehe C:\Programme\WinAVR-20070525\avr\include\avr\iom16.h sowie
    Interruptvektoren/-vektortabelle in *doc2466, S 45+46 von AVR                    */
    
    /* beachte: volatile!  und   Vorzeichenlos reicht für alle                   */
    
    volatile uint16_t Izeit_1;			/* Timer läuft hoch
      Die Interruptroutine läuft mit 10 kHz (Möglicherweise sind 100 kHz besser)
        Beim Start des Timers läuft der Zähler time1 hoch und wird nach 5 sec -
        also beim Wert 50 000 - wieder auf Null gesetzt. Dabei werden die Werte
        ysecv und yseci angepasst                                                  */
    /* ============================================================================== */
    
    
    
    /* =================================================================================
       ##### Hier ISR und ISR - Initialisierung(en)
    ================================================================================= */
    
    
    
    /* ===  Initialisierung fuer Timer0 8-bit mega16(32)  ==============================
    Aufruf als  SIGNAL (SIG_OVERFLOW0)                  */
    void TMR_0_init( void )	
    {				//Initialisiere 8-Bit-Timer auf 10 kHz
        TCCR0 |= (1<<CS02 | 0<<CS01 | 1<<CS00); // Prescaler 1024 / Clock <- CPU
        TCCR0 |= (1<<WGM01 | 0<<WGM00);	// Timer im CTC-Mode
        TCNT0 = 0x64;   			// Timer0 Counter 0x64 für 10ms bei 16Mhz 
    
        TIMSK |= (1<<OCIE0); 		// Compare Match IRQ 
    
    }
    /* ============================================================================== */
    
    
    
    
    /* ============================================================================== */
    /* ===  Nicht unterbrechbare ISR für timer ====================================== */
    /* Diese Routine zählt hoch im Takt 10 kHz.setzen.
          Dieser Wert wird von den beiden anderen ISR ausgelesen und den Werten
    
    */
    // SIGNAL(SIG_OVERFLOW0)
    // #define SIG_OUTPUT_COMPARE0	//Interuptvektor, siehe Tabelle
    SIGNAL(SIG_OUTPUT_COMPARE0)
    {
        Izeit_1 ++;              //Zeitstand des Interupt-Timers
    
    
    
        PORTC ^= (1 << PC4);	//LED toggeln
    
    
    
    }
    /* ============================================================================== */
    Danke im Voraus
    Ciao sagt der JoeamBerg

  2. #2
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    20.05.2006
    Ort
    Lippe
    Alter
    54
    Beiträge
    524
    Hallo,

    in der AVR-Studio Simulation läuft es. Hast du irgend eine Optimierung eingestellt? Nimm die mal raus.

    Gruß

    Jens

  3. #3
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.651
    Ohhh - danke - ich werd es abends testen
    Ciao sagt der JoeamBerg

  4. #4
    Erfahrener Benutzer Robotik Visionär Avatar von Hubert.G
    Registriert seit
    14.10.2006
    Ort
    Pasching OÖ
    Beiträge
    6.220
    Irgendwie ist mir deine Taktrechnung nicht klar. Du teilst die 16Mhz durch 1024 mit dem Prescaler, ergibt 15625Hz, stellst den CompareMatch auf 0x64 das ist dez. 100 und sehe gerade du hast auf ext.Clock-Source gestellt und nicht auf Prescaler 1024
    Den TCNT0 musst du auf 156 stellen für 100Hz

    PS: Zu PortC sehe ich nur das du das Port auf Ausgang stellst aber nur mit PC4 was machst, damit sind die restlichen Pin auf L
    Grüsse Hubert
    ____________

    Meine Projekte findet ihr auf schorsch.at

  5. #5
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.651
    Hallo Hubert.G, hallo McJenso,

    @McJenso - ich habe die Optimierung von -Os gestellt auf -O0. Der Maschinenfile wurde auch wirklich um über 40% länger - aber leider nicht lauffähiger.

    @Hubert.G - Hoffentlich kringelst Du Dich nicht über die dämlichen Fehler von dem alten "Bergler". Ja, das mit dem Prescaler steht noch auf der Änderungsliste - das ist noch nicht erledigt (Berechnungs-Excel gesucht - nicht gefunden - IRGENDEINENWERT reingeschrieben ).

    Aber der Klops ist natürlich die ext.Clock. Da hatte ich mich gleich um ZWEI Zeilen verguckt .

    Ich lese das doc2466, Stand 2466P–AVR–08/07 (03.12.2007-runtergeladen bei Atmel), Seite 85, da steht:

    Code:
    CS02 CS01 CS00    Description
    ...
      1    0    1      clkI/O/1024 (From prescaler)
    Die ext. Clock ist 110 oder 111. Und das ist ja mein code:
    Code:
        TCCR0 |= (1<<CS02 | 0<<CS01 | 1<<CS00); // Prescaler 1024 / Clock <- CPU
        TCCR0 |= (1<<WGM01 | 0<<WGM00);	// Timer im CTC-Mode
        TCNT0 = 0x64;   			// Timer0 Counter 0x64 für 10ms bei 16Mhz 
        TIMSK |= (1<<OCIE0); 		// Compare Match IRQ
    Hmmmm

    Trotzdem danke für Eure Hilfe. Doof ist ja, dass es wie Assembler aussieht - und in Assembler bekam ich sowas immer zum Laufen (obwohl meine Assembler-Ziele bedeutend weniger Beine hatten ). Ich werde mich weiter bemühen.
    Ciao sagt der JoeamBerg

  6. #6
    Erfahrener Benutzer Robotik Visionär Avatar von Hubert.G
    Registriert seit
    14.10.2006
    Ort
    Pasching OÖ
    Beiträge
    6.220
    Ein 0<<CS01 schreibt man nicht, ist nämlich sinnlos und irritiert nur, wenn dann so ~(1<<CS01)
    Grüsse Hubert
    ____________

    Meine Projekte findet ihr auf schorsch.at

  7. #7
    Erfahrener Benutzer Robotik Visionär Avatar von Hubert.G
    Registriert seit
    14.10.2006
    Ort
    Pasching OÖ
    Beiträge
    6.220
    Und wenn du den Compare-Wert nicht ins TCNT0 sondern ins OCR0 schreibst könnte sich die Funktion auch verbessern.
    Grüsse Hubert
    ____________

    Meine Projekte findet ihr auf schorsch.at

  8. #8
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.651
    Grüß Dich Hubert.G,

    danke für Deinen Hinweis zum 0<<CS01 . Es ist mein doofer Hang zur Perfektion (na ja - nach dem Motto - ich weiss nicht ob es richtig ist, aber lieber einmal zuviel... und dann wars doch falsch). Es ist beruhigend, wenn man immer wieder geduldig auf Fehler hingewiesen wird - und die Hilfe immer kommt. Danke.

    doof ist es, wenn bei der RNControl läuft:
    1) Das "Lauflicht" - alle 8 LED´s werden nacheinander geschaltet - auf einem mega32 läuft. Hab ich gerade ausprobiert.
    2) die mittlere 4-er Gruppe von PortC beim mega16 "halbhoch" hängen bleibt. Es sind jene Kontakte, an denen kein L293 oder Widerstände hängen.
    3) Deshalb hatte ich auch die getoggelte LED in der Mitte von PortC leider nicht leuchten sehen.
    4) Beim toggeln der LED auf PortC6 in der ISR läufts.

    Manchmal will man das Zeugs wirklich wegwerfen - nicht nur smileyhaft . Na ja - wollen - aber dann doch nicht tun. Nun kann ich in Ruhe weiter C-code generieren .

    Danke - und schönen Abend.
    Ciao sagt der JoeamBerg

  9. #9
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.651
    Zitat Zitat von Hubert.G
    ... Compare-Wert nicht ... sondern ...
    Ach herrje.

    Na ja, nicht wegen der Arbeit - aber dann muss ich diese ganze Litanei im doc nochmal durchlesen *brrrrrrrr*

    Danke und schönen Abend
    Ciao sagt der JoeamBerg

  10. #10
    Erfahrener Benutzer Robotik Visionär Avatar von Hubert.G
    Registriert seit
    14.10.2006
    Ort
    Pasching OÖ
    Beiträge
    6.220
    Hast du den JTAG in den Fuses abgeschaltet.
    Grüsse Hubert
    ____________

    Meine Projekte findet ihr auf schorsch.at

Seite 1 von 4 123 ... LetzteLetzte

Berechtigungen

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

LiTime Speicher und Akkus