Hi Zotti,
Zitat von
Zotti
... Zeitmessung für Rundenzeiten ... Atmel soll einen Zeitstempel generieren ...
Mir fehlt der richtige Ansatz mit welchem Atmel ich ein Timestamp oder so was ähnliches generieren kann ...
Die zweite Frage zuerst: Das geht praktisch mit jedem Atmel. Ich habe eine Lösung, die ist noch von meiner Anfangszeit als C-Neuling geprägt - sprich: es geht sicher eleganter. Aber so geht es - mit der Genauigkeit von 50 µs bei meinem 20 MHz-Quarz. Der Timer wird wie folgt initialisiert (für einen anderen Atmel und/oder einen anderen Quarz brauchst Du andere Registernamen, und sicher auch andere Parameter):
Code:
/* ============================================================================== */
/* === Initialisierung fuer Timer2 mega328 ===================================== */
void TC2TMR_init(void) // Init Tmr/Cntr 2, 8-Bit auf 20 kHz = 50 µs
{
TCCR2A |= (1<<WGM21); // Timer im CTC-Mode, Top=OCR2A doc S 157
TCCR2B |= (1<<CS21); // Prescaler 1/8 / Clock <- CPU doc S 158
OCR2A = 124; // Preset 125 für 50µs bei 20Mhz
TIMSK2 |= (1<<OCIE2A); // Tmr/Cntr2 CompareA interrupt enabled
}
/* ============================================================================== */
In einer ISR wird der Interrupt gezählt und bis zu einem Sekundensignal ausgewertet, denn 20000 mal 50 µs sind eine Sekunde:
Code:
/* ============================================================================== */
/* === Nicht unterbrechbare ISR für timer2 ===================================== */
/* Routine zählt hoch im Takt 20 kHz = 50 µs. Der Zählerwert wird von den ISR für
EXT_INT0 und -INT1 ausgelesen und den Werten Iz_yseci zugewiesen ...... */
ISR(TIMER2_COMPA_vect) // Vektor 7
{
if (Izeit_1 < Izthrznt) //Interrupt-Timer (Zeithorizont derzeit = 20 000)
{
Izeit_1 ++; // Jede eine Sekunde wird 20000 erreicht
} // und Izeit_1 bleibt in der uint16-Grenze
else
{
Izeit_1 = 1; // ansonsten: Rückstellen 50µs-Zähler
I_sec_1 ++; // Sekundencounter, geht bis ca. neun Stunden
if (I_sec_1 > 32000) // Sekundenzähler-Maximum 9 Std. abprüfen
I_sec_1 = 1;
}
}
/* ============================================================================== */
Nun kannst Du in beliebigen Routinen die Variablen Izeit_1 - also die Anzahl der 50 µsec innerhalb einer Sekunde - und I_sec_1 - das ist der Sekundenzähler, der rund 9 Stunden bis zum Wiederstart läuft - auslesen. Diese Variablen sind volatile uint16 ! ! ! Das Auslesen solltest Du daher innerhalb einer sei();/cli();-Schranke machen, damit Dir die Timer-ISR nicht während des Auslesens die Werte verändert - DAS wäre sehr schlecht.
Aus dem 50µs-Zähler kannst Du im main bzw. einer geeigneten Routine den Sekundenbruchteil errechnen, die Sekunde bekommst Du ja frei Haus. Bei Rundenzeiten über 9 Stunden wäre ein Überlauf abzufangen. Du könntest natürlich auch einen Minuten- und/oder Stundenzähler bauen. Da der Interrupt nur alle Sekunden abläuft, wäre das praktischerweise ausserhalb der Timer-ISR zu erledigen. Aber wer braucht das schon - mit uint16 kann der controller gut umgehen.
Hilft Dir das?
Lesezeichen