Hi Steffen08,
für (m)einen mega168 gebe ich Dir ein Codebeispiel. Du müsstest die Variablen noch selbst deklarieren und Dir die entsprechenden Timerregister (-namen und -werte) aus dem mega8-Datenblatt raussuchen. >>> Das ist eine mögliche Lösung <<< und vermutlich nicht mal die beste. Also fixiere Dich nicht zu sehr darauf.
Hintergrund: als vielfach nutzbares Zeitsignal habe ich in meiner Software einen 50µs-Takt aufgebaut. Die entsprechende ISR (Interrupt-Service-Routine) zählt beim Aufruf immer die Varible Izeit_1 um 1 rauf, bis Izeit_1 bei 20000 ist - dann ist eine Sekunde um. Jetzt könnte ich in der ISR natürlich noch nen Sekundenzähler einbauen (habe ich in dem hier vorgestellten Beispiel der Übersichtlichkeit halber gestrichen). Wenn Du für den Sekundenzähler ein uint16_t nimmst, dann hast Du bei unter 45 000 Sekunden schon mal einen halben Tag zu zählen . . . . .
Die (uint_8-) Variable LEDon ist Dein "Schalter" für LED ein oder aus. Bei JEDEM Wert ausser "1" ist die LED aus, bei "1" klickert sie im Sekundentakt . . . . ok?
Code:
/* ============================================================================== */
/* === Initialisierung fuer Timer2 mega168 ===================================== */
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
}
/* ============================================================================== */
/* ============================================================================== */
/* === 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 < 20000) //Interrupt-Timer = 20 000 ... (1 sec blink)
{
Izeit_1 ++; // war: alle Sekunden wird 20000 erreicht
} // und Izeit_1 bleibt in der uint16-Grenze
else
{
if ( LEDon == 1 ) // LED nur toggeln, wenn erlaubt
{
PORTC ^= (1<<PC5); // LED auf Port PC5/I2C/SCL toggeln
}
Izeit_1 = 1; // ansonsten: Zeit zurückstellen
}
}
/* ============================================================================== */
Die Initialisierung erfolgt durch Aufruf von "TC2TMR_init();", danach müsste noch ein sei(); kommen um die Interrupts zu erlauben - und sobald Du dann schreibst "LEDon = 1;" fängt die LED nach spätestens 50 µs an zu blinken, bei "LEDon = 0" oder einem anderen Wert geht sie nach spätestens 50 µs wieder aus . . . . ok?
Ach so, ja, die ISR läuft natürlich im "Hintergrund". Du merkst davon garnix, Dein restlicher Code ist davon nicht betroffen (der wird nur in seinem Ablauf alle 50 µs für ein paar Maschinenzyklen unterbrochen). Beim Auslesen von Izeit_1 bzw. einem 2-Byte-Sekundenwert im main oder einer Subroutine vermeidest Du Probleme wenn Du "cli();" - Wert auslesen - "sei();" vorsiehst. Denn die ISR kann natürlich mitten im Auslesen - zwischen den beiden Bytes (MSB und LSB) den Wert verändern!
Lesezeichen