PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Timer0 oder Timer2 benutzen, aber wie?



H3llGhost
20.12.2007, 10:07
Hallo Leute,

wie kann ich mit den Timer0 und Timer2 arbeiten?


ldi temp, (1 << CS02)
out TCCR0, temp

[...]

timer_reset: ; Zeit für den Timer wieder auf 0,3 s setzen
ldi temp, 255
out TCNT0, temp
ldi temp, (1<<CS02)
out TCCR0, temp
ret

timer_schleife:

tloop:
in temp,TIFR
sbrs temp,TOV0
rjmp tloop

ldi temp,(1<<TOV0)
out TIFR,temp

ret


Nur wie kann ich den Timer mit höheren Zeitwerten benutzen?

damaltor
20.12.2007, 11:00
hmm also in C wäre das einfacher glaub ich... aber zuerst einmal: der timer läuft automatisch "durch". du musst ihn also nicht immer weider neu einstellen.

der trick ist folgender: der counter läuft und läuft und läuft. bei jedem durchlauf wird genau ein interrupt generiert. wenn du in diesem interrupt eine zählvariable hochzählst, kannst du längere zeiten verarbeiten.

H3llGhost
20.12.2007, 19:22
Hmm ...
Wie lange läuft denn der Counter?

Ach ja ...
Als Info ich müsste den Code in Assembler haben ... ;-)
Danke!

damaltor
20.12.2007, 20:05
oh oh ich bin nicht gut in assembler.. da warte lieber noch ein wenig. =)

der counter läuft (ohne prescaler) 256 systemtakte lang. jedesmal wenn er wieder bei 0 ankommt wird ein interrupt ausgelöst, in der ein register oder eine zählvariable hochgezählt werden kann. diese variable würde dann also
1 sec / 8000000 * 256 = 32 µs
alle 32 mikrosekunden um 1 erhöht werden. alternativ könntest du den prescaler zuschalten. dann läuft der counter mit halber, viertel, achtel ... ich glaub mit einigen unterbrechungen bis tausendvierundzwanzigstel der systemfrequenz. so könntest du sehr lange zeiten schaffen.

liggi
22.12.2007, 09:03
wie sieht das den in c aus???

mfg liggi

HAWK-Matze
23.12.2007, 11:25
will nur benachrichtigt werden wenn hier ne antwort erstellt wird habs anders nicht hinbekommen sorry. Kann mir jemand erklären wie ich das hinbekommen ohne sinnlos zu posten?

oberallgeier
23.12.2007, 15:08
wie sieht das den in c aus???
mfg liggiIst doch klar - gut sieht das aus.


Möglicherweise ist das eine Antwort:

/* ================================================== ===============================
Target MCU : ATmega16
Target Hardware : RNControl
Target cpu-frequ. : 16 MHz, externer Quarzoszillator
================================================== =================================
Enthaltene Routinen:
void TMR_0_init( void ) // ISR Timer0 initialisieren
SIGNAL(SIG_OUTPUT_COMPARE0) // Timer0 ISR, Zeitmarke hochzählen
int main(void)
================================================== ============================== */

#include <stdlib.h>
#include <avr/io.h>
#include <avr/interrupt.h>

#define MCU = ATMega16

// Mit Quarz 16 Mhz-CPU
#define F_CPU 16000000

/* beachte: volatile! und Vorzeichenlos */
volatile uint16_t Izeit_1; /* Timer läuft hoch
Die Interruptroutine läuft mit 10 kHz */
/* ================================================== ============================ */

/* === Initialisierung fuer Timer mega16(32) ================================== */
void TMR_0_init( void )
{ //Initialisiere 8-Bit-Timer auf 10 kHz
TCCR0 |= (1<<CS01 | 1<<CS00); // Prescaler 1/64 / Clock <- CPU
TCCR0 |= (1<<WGM01 | 0<<WGM00); // Timer im CTC-Mode
OCR0 = 25; // Preset 25 für 100µs bei 16Mhz
TIMSK |= (1<<OCIE0); // Compare Match IRQ
}
/* ================================================== ============================ */

/* === Nicht unterbrechbare ISR für timer ====================================== */
/* Diese Routine zählt hoch im Takt 10 kHz. */
SIGNAL(SIG_OUTPUT_COMPARE0)
{
{
if (Izeit_1 <= 10000)
Izeit_1 ++; //Zeitstand Interupt-Timer läuft von 1 .. 10 000
else
Izeit_1 = 0;
}
{ // von hier bis Ende (LED2 toggeln) nur Testphase
if (Izeit_1 == 1)
PORTC ^= (1<<PC2); //LED3 toggeln alle Sekunde
}
PORTC ^= (1<<PC1); //LED2 toggeln jeden Interrupt
}
/* ================================================== ============================ */



// ------------------------------------------------------------------
/*### Hauptschleife ###*/
int main(void)
DDRC |= 0xFF; //11111111 -> Ausgänge
TMR_0_init(); //Initialisiere den Timer0-Interrupt (10 kHz)
sei(); //Globalen Interrupt freigeben

for(;;) {
// Dieses Programm toggelt Ausgänge PC1 und PC2
}
}
. . . aber wenns nicht deine Frage war - dann stell die Frage doch präzise.

damaltor
27.12.2007, 22:17
über antworten wirst du automatisch per email benachrichtigt. das kannst du in deinem profil einstellen. oder, wenn du eine antwort schreibst, unter der eingabe-textbox auswählen.

CsT
28.12.2007, 10:18
@HAWK
Unten rechts steht "Bei Antworten zu diesem Thema benachrichtigen" .. da draufklicken, dann bekommst du Mails ohne selbst geantwortet zu haben.

Zum Thema selbst:
Ist eigentlich schon alles gesagt .. ;)

H3llGhost
07.01.2008, 16:56
oh oh ich bin nicht gut in assembler.. da warte lieber noch ein wenig. =)

der counter läuft (ohne prescaler) 256 systemtakte lang. jedesmal wenn er wieder bei 0 ankommt wird ein interrupt ausgelöst, in der ein register oder eine zählvariable hochgezählt werden kann. diese variable würde dann also
1 sec / 8000000 * 256 = 32 µs
alle 32 mikrosekunden um 1 erhöht werden. alternativ könntest du den prescaler zuschalten. dann läuft der counter mit halber, viertel, achtel ... ich glaub mit einigen unterbrechungen bis tausendvierundzwanzigstel der systemfrequenz. so könntest du sehr lange zeiten schaffen.

Wie hohe Zeiten kann ich denn schaffen, wenn ich den Prescallor auf 1024 setze?
Und was genau rechnst du mit "1 sec / 8000000 * 256 = 32 µs" aus?

damaltor
07.01.2008, 20:01
folgendes habe ich gerechnet:

der prozessor arbeitet mit 8.000.000 takten pro sekunde. bei einem prescaler von 1 wäre also die zeit zwischen zwei takten 1sec/8000000 = 125 nanosec.

der interrupt wird generiert wenn der timer überläuft, also von 255 wieder auf 0 springt. das geschieht alle 256 zähleinheiten; also 125 ns * 32 = 32µs.


wird der prescaler aktiviert, wird der counter nur alle [prescaler] takte erhöht. mit einem prescaler von 1024 würde der counter also nur mit einem 1024stel der geschwindigkeit hchzählen. wir hätten also zwischen zwei interrupts
32µs * 1024 = 32,768 millisec.

H3llGhost
07.01.2008, 21:03
Ist aber auch nicht gerade die Welt ...
Aber dazu gibt es ja den Trick um aus den 8-Bit Timer einen 16-Bit Timer zu machen ...

damaltor
08.01.2008, 00:16
da brauchts keinen trick. entweder man nimmt direkt den 16bit timer der hardwaremäßig vorhanden ist, oder man zählt eine vriable in der interruptroutine. dann kann man beliebige verzögerungen erreichen.

H3llGhost
08.01.2008, 08:12
Und wie sieht es aus wenn man noch zustätzliche den PWM nutzen möchte?
Dann geht das doch nicht oder?

damaltor
08.01.2008, 16:04
hmm.. man kann die hardware-pwm nutzen. oder man programmiert eine software-pwm... was meinst du?

H3llGhost
08.01.2008, 17:05
Ich habe an die Hardware-PWM von Timer1 gedacht ... ;)

damaltor
08.01.2008, 17:07
tja... und wo ist das problem dabei? :D

H3llGhost
08.01.2008, 17:15
Wie lasse ich den mit dem Timer0 zusammenlaufen?

Siehe Klick (https://www.roboternetz.de/phpBB2/viewtopic.php?t=37041) ...

Da habe ich ja das Problem ... :(