Forum: Mikrocontroller und Digitale Elektronik mit Timer1 Zeit messen, Zeit teilen und damit Timer3 starten


von Hans Meier (Gast)


Lesenswert?

Hallo,

so langsam bin ich hier am verzweifeln :=(
Habe mich jetzt an einen (den größten) ATMEL, den ATMega 128
herangewagt. Nachdem auch ich Lehrgeld bezahlt hatte und die ISP
Verbindung falsch ("natürlich" an MOSI und MISO) angeschlossen hatte
(kann man ja zum Glück mit ein paar feinen Drähtchen auf PIN 2 und 3
wieder korrigieren), läuft der uC jetzt soweit (Ports lassen sich
setzen und PINs einlesen). Er hat die ganze Lötprozedur also
überstanden, juhu! Was ich jetzt machen wollte, ist eine
(komplizierte?) Zeitmessung.
Mit Timer3 soll eine Zeit gemessen werden (Timer3 zählt so lange, bis
ICP3 anspricht, d.h. der Input Capture Interrupt ausgelöst wird). Diese
gemessene Zeit soll dann durch 10 (nur ein Beispiel, wird später
variabel sein) geteilt werden und mit dieser Zeit soll dann Timer1
gestartet werden (d.h. Timer1 löst einen Overflow Interrupt nach einem
1/10 der Gesamtzeit/Timer3zeit aus). Aber irgendwie hapert es da, vor
allem beim Teilen durch 10, bzw. dem korrekten Starten des Timers1. Das
sind ja beides 16Bit Timer, die ihr Low und High Byte benötigen. Nur wie
schiebe ich das Ergebnis da hin?
Hier mal ein Codeauszug:


void timer_initialisieren (void)
{
 // Timer1 einfach mal mit 100msec initialsieren (wird später eh
überschrieben)
 TCCR1B = 0x00;
 TCNT1H = 0xBC;
 TCNT1L = 0x80;
 OCR1AH = 0x43;
 OCR1AL = 0x80;
 OCR1BH = 0x43;
 OCR1BL = 0x80;
 OCR1CH = 0x43;
 OCR1CL = 0x80;
 ICR1H  = 0x43;
 ICR1L  = 0x80;
 TCCR1A = 0x00;
 // Timer3 mit 300msec initialisieren (wird schon vorher durch ICP
angehalten/genullt)
 TCCR3B = 0x00;
 TCNT3H = 0xF0;
 TCNT3L = 0xBE;
 OCR3AH = 0x0F;
 OCR3AL = 0x42;
 OCR3BH = 0x0F;
 OCR3BL = 0x42;
 OCR3CH = 0x0F;
 OCR3CL = 0x42;
 ICR3H  = 0x0F;
 ICR3L  = 0x42;
 TCCR3A = 0x00;
 TCCR3B = 0x45; // Timer starten
}

#pragma interrupt_handler timer1_ovf_isr:15
void timer1_ovf_isr (void)
{
 TCNT1H = high_byte;
 TCNT1L = low_byte;
}

#pragma interrupt_handler timer3_capt_isr:26
void timer3_capt_isr(void)
{
 int zeit = 0;
 int temp = 0;
 // unterbrechen, low und high-byte auslesen, fortsetzen
 CLI();
 zeit  = ICR3L;
 zeit |= (int)ICR3H << 8;
 zeit = zeit / 10 // durch Anzahl der Schritte teilen

// hier klappt was nicht!!!

 temp = zeit << 8;
 high_byte = temp;
 low_byte = zeit;
 TCNT1H = high_byte;
 TCNT1L = low_byte;
 TCCR1B = 0x03; // Timer1 starten

// hier drüber muss der Fehler sein

 SEI();
}

Wie schiebe ich die Bits richtig, bzw. darf ich überhaupt "einfach
so" dividieren?

Gruß,

Hans

von Uwe Seidel (Gast)


Lesenswert?

DA fehlt auf jeden Fall mal ein Semikolon nach der "/10"

zeit = zeit / 10 // durch Anzahl der Schritte teilen

wird ja wohl nicht alles gewesen sein..... ?!?!?!

Ciao

von Peter D. (peda)


Lesenswert?

Wenn Dein Compiler keine 16-Bit Register kann, nimm WINAVR.

Der weiß dann auch die richtige Reihenfolge beim Lesen bzw. Schreiben.


Peter

von Hans Meier (Gast)


Lesenswert?

Hmm,

danke. Das mit dem Semikolon war es zwar nicht (hatte da statt der 10
ne Variable stehen), bin mittlerweile aber weiter. Muss mich wohl mal
näher mit WinAVR auseinadersetzen.

Gruß,

Hans

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.