PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Timer0-Problem auf t2313 war falsche Oszilloskopeinstellung



oberallgeier
02.04.2009, 10:50
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:


// 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
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
Timerinitialisierung und ISR 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
}
/* ================================================== ============================ */

Im main läuft derzeit folgende Dummy-Schleife:


// ###>>> 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 #####################<<<<<<<<

Ergebnisse:
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

thewulf00
02.04.2009, 11:21
Hallo.

Der Wert ist sogar noch abweichender, als Du denkst.
Denn im Datenblatt auf Seite 72 steht die Formel zur Berechnung der resultierenden Frequenz eines Timers.
Wenn ich Deine Werte dort einsetze, erhalte ich aber nur 10 kHz. (Das liegt an diesem 2er-Fakter in der Gleichung. Also eigentlich solltest Du 100µs erhalten. :-)

Miss die LED bitte mal mit einem anderen Gerät (bspw. mit einem Multimeter auf Frequenzmessung).

oberallgeier
02.04.2009, 12:30
... ist sogar noch abweichender, als Du denkst ... die Formel zur Berechnung der resultierenden Frequenz der "Schwingung" ...Diese Formel hat mich immer wieder verwirrt (und die Angabe von 20kHz ist auch nicht die Frequenz - da hast Du recht). Nichtsdestoweniger wird laut Datenblatt auf S 72 innerhalb einer Periode der Interrupt zweimal ausgelöst - Zitat Datenblatt, siehe Bild unten: ... each time the counter value reaches the TOP value ... - damit bin ich wieder bei 20000 ISR in einer Sekunde. Entsprechend blinkt auch meine LED auf PD2 mit 1 sec langen on-off-Sequenzen.

..........http://oberallgeier.ob.funpic.de/CTCauf2313.gif

Das gibt mir ja auch die Sicherheit, dass die ISR (nur) 20 000 mal in einer Sekunde den Wert Izeit_1 hochzählt. Und das tut sie ja jedes Mal, wenn sie aufgerufen wird. Wieso dann aber die LED auf PB3 im genannten Takt blinzelt ist mir eben nicht klar.

Übrigens: wenn ich bei meinem Dottie oder MiniD0 (ok, ist ein mega168 aber auch 20 MHz und praktisch gleiche Routinen) eine bestimmte Fahrgeschwindigkeit einstelle, ist die auch mit der Stoppuhr zu verifizieren.

oberallgeier
02.04.2009, 13:06
Oh oh oh - - - (oder: die Sonne scheint, das Moped zittert - aber ich hab noch ´nen Fehler gewittert).

WENN es wenigstens nicht die "Hälfte" gewesen wäre (lt Anzeige 5 DIV à 5 µs statt 50 µs), WENN ich genau auf den Oskar gesehen hätte (vor lauter Einstellknöpfen sieht man den einen, fasch stehenden Knopf nicht) - hätte ich früher gemerkt, dass der kleine Timebase-Knopf zur stufenlosen Justage nicht eingerastet war - und beim Drehen des großen Knopfs raste ich ja nur die verschiedenen Stufen. JETZT ist der Kleine in Endstellung eingerastet. JETZT dauert die ISR tatsächlich 3 µs ABER sie wird nur alle 50 µs aufgerufen \:D/ . Laut Bildschirm. Puhhhhh - - aber Sonne und Moped sind noch da. Blos das Moped ist gleich weg.

Fazit: dumm - nein nicht gelaufen - Oskar abgelesen.

thewulf00
02.04.2009, 15:46
Ohje.
Das freut mich, dass das Rätsel entwirrt wurde.

Ich hatte Deinen Code auch komplett angeschaut - da fand ich keinen Fehler, habe mir schon Sorgen gemacht :D