Hallo alle
bitte helft mir bei (m)einem Timerproblem.
Aktueller Stand: meinen Pacer (Schrittsignal für Trainingszwecke/Laufen) schreibe ich neu, diesmal in C statt Assembler. Der Assemblerpacer läuft gut. Der C-pacer funktioniert im Prinzip so, wie ich das will.
Aufgabe: Es werden in einer Minute eine bestimmte Anzahl "Blinkies" (BpM) mit einer Leuchtdiode erzeugt als Vorgabe für Doppelschritte. Dazu läuft mein Lieblingstimer im 50µs-Takt - will sagen, die ISR wird alle 50 µs aufgerufen. Zur Messung der ungefähren ISR-Dauer (Pushs und Pops werden ja nicht erfasst) wird zu Beginn der ISR eine separate LED an- und am Ende der ISR ausgeschaltet.
Aktuelle Beschaltung des Controllers:
Timerinitialisierung und ISR Code:Code:// Pins/Ports als Ein- (0) oder Ausgänge (1) konfigurieren, Pull Ups (1) aktivieren // A = Ausgang, E = Eingang ohne , EU = Eingang MIT PullUp DDRB = 0b11111111; // Aus- + Eingänge definieren PORTB = 0b00000000; // und Port/Pull Ups (1) aktivieren //DDRC = 0b--------; // Von Port C existiert nur /RESET //PORTC = 0b--------; // // DDRD = 0b01111110; // PD7 existiert beim t2313 nicht PORTD = 0b00000001; // Pull Ups aktivieren /* Dadurch Initialisierung der Anschlüsse für Pacer60+ : - - - - - - - - - - - - - /RESET, dW, PC6 1 A 20 VCC RxD, PD0 2 EU A 19 PB7, USCK, SCL TxD, PD1___3 A A 18___PB6, MISO XTAL1, PA1 4 A A 17 PB5, MOSI XTAL2, PA0___5 A A 16___PB4 (Test-) gLED1, PD2 6 A A 15 PB3 Test-LED zum Messen der ISR-Dauer PD3___7 A 14___PB2 PD4 8 A A 13 PB1, rLED - das Minuten-Signal PD5 9 A A 12 PB0, gLED - die Blinkie-Leuchte GND__10 A 11___PD6 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
Im main läuft derzeit folgende Dummy-Schleife:Code:/* ============================================================================== */ /* === Initialisierung fuer Timer0 tiny2313 ==================================== */ void TC0TMR_init(void) // Init Tmr/Cntr 2, 8-Bit auf 20 kHz = 50 µs { TCCR0A |= (1<<WGM01); // Timer im CTC-Mode, Top=OCR2A doc S 79 TCCR0B |= (1<<CS01); // Prescaler 1/8 / Clock <- CPU doc S 81 OCR0A = 124; // Preset 124 für 50µs bei 20Mhz TIMSK |= (1<<OCIE0A); // Tmr/Cntr2 CompareA interrupt enabled } /* ============================================================================== */ /* ============================================================================== */ /* === Nicht unterbrechbare ISR für timer0 ===================================== */ /* Routine zählt hoch im Takt 20 kHz = 50 µs. Der Zählerwert wird von den ISR weiter ausgewertet ...... */ ISR(TIMER0_COMPA_vect) // Vektor 7 { PORTB |= (1<<PB3); // Zeitmessung ISR: LED auf Port PB3 einschalten // Messzeit am 02apr09 1036: 1,5 µs // !!! Zyklusdauer 25 µs !!! if (Izeit_1 < 20000) //Interrupt-Timer = 20 000 ... (1 sec blink on/off) { Izeit_1 ++; // war: alle drei Sekunden wird 60000 erreicht } // und Izeit_1 bleibt in der uint16-Grenze else { PORTD ^= (1<<PD2); // LED auf Port PD2 toggeln Izeit_1 = 0; // ansonsten: Rückstellen auf Null icntdwn = icntdwn + 1; // Countdownzähler hoch(!!)zählen if (icntdwn > 32400) // Countdownzähler geht maximal 9 Std. icntdwn = 1; } if (Iblink < Ibzykl) // Blinkzyklus noch nicht zu Ende? { Iblink ++; // Counter für Blinkzyklus hochzählen } else // Blinkzyklus ist abgelaufen { Iblink = 1; // Counter für Blinkzyklus zurücksetzen PORTB |= (1<<PB0); // bLED auf Port PB0 ein } if (Iblink == Iblitz) // Leuchtdauer des Blinkies { PORTB &= ~(1<<PB0); // bLED auf Port PB0 aus } PORTB &= ~(1<<PB3); // Zeitmessung ISR: LED auf Port PB3 ausschalten } /* ============================================================================== */
Ergebnisse:Code:// ###>>> Erste pacerversion in C #####################>>>>>>>> cli(); // Verbiete Interrupts während der folgenden // ##### Dateninitialisierung =================== Ibanz = 82; // Anzahl der blinkies pro Minute Ibzykl = (20000 / Ibanz); // Berechne Blinkiezyklus Ibzykl = Ibzykl * 60; // in 50µs-Zeitscheiben Iblitz = 1000; // Im Blinkiezyklus wird geblinkt // Ibanz Anzahl der Blinkies pro Minute // Ibzykl Blinkie-Abstand in 50µs-Einheiten // Iblink der Counter für Blinkieabstand // Iblitz Dauer des Blinkens in 50µs-Einheiten sei(); // Abschluss der Initialisierung, erlaube Interrupts while (1) { if (Izeit_1 <= 10) PORTB |= (1<<PB1); // bLED auf Port PB1 an if (Izeit_1 >= 10000) PORTB &= ~(1<<PB1); // bLED auf Port PB1 aus } // ########### Ende des pacers #####################<<<<<<<<
1) Die übliche Kontroll-LED auf PD2 toggelt wie bisher immer im 1-sec-Takt: 1 sec an - 1 sec aus.
2) Die Blinkies werden je nach Vorgabe der BpM korrekt erzeugt.
3) Die ungefähre ISR-Dauer wird mit 1,5 µs von der LED (Oszilloskop) bestätigt.
4) Die LED auf PB3 zur Messung der ISR-Dauer wird alle 25 µs eingeschaltet (5 µs/DIV, ziemlich genau 5 DIV).
5) Alle Variablen sind int16_t bis auf Izeit_1, die ist traditionell uint16_t.
Punkt 4 ist mir völlig schleierhaft. Die ISR sollte doch "nur" alle 50 µs laufen - da bekäme ich bei 5 µs/DIV auf meinem 10-DIV-Bildschirm gerade einen vollen Zyklus mit - es sind aber momentan 2.
Danke im Voraus







Zitieren

Lesezeichen