PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : timer von atmega8



fed111
12.07.2005, 12:21
hallo leute!

ich weis dass dieses thema hier schon oft angesprochen wurde, hab aber trotzdem noch nichts gefunden, was ich gebrauchen konnte.
also: ich will mit einem atmega8 die zeit zwischen zwei ereignissen (tasterdruck) messen. die zu messende zeit liegt so im 0-2sec.-bereich. die zeit soll mehrfach hintereinander gemessen werden können, ohne den controller neu zu starten.

ich würde mich freuen, wenn mir jemand nen kleinen beispielcode posten würde. (edit: oder irgendwie sagen würde wie's geht)

vielen dank schonmal im vorraus
Frederic

SprinterSB
12.07.2005, 15:36
Ein Teil deiner Aufgabe erledigt folgender Code.

In timer.h werden Grundeinstellungen gemacht:
Interrupt-Rate und mit welcher Taktfrequenz gefahren wird.

timer.h:



#ifndef _TIMER_H_
#define _TIMER_H_

#define XTAL_PHI 8000000
#define INTERRUPTS_PER_SECOND 10000
#define INTERRUPTS_PER_MILLISECOND (INTERRUPTS_PER_SECOND / 1000)

extern void init_timer1 (void);

#endif /* _TIMER_H_ */



In timer.c::init_timer1() wird Timer1 so initialisiert, daß er INTERRUPTS_PER_SECOND mal pro Sekunde einen Interrupt auslöst:



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

#include "timer.h"

void init_timer1()
{
/* tmr1 is counter */
TCCR1A = 0;
#if defined (__AVR_AT90S2313__)
// Timer1 running on full MCU clock
// Clear on CompareMatch
TCCR1B = _BV (CS10) | _BV (CTC1);
#elif defined (__AVR_ATmega8__)
// Mode #4 für Timer1 (Manual S. 97)
// und full MCU clock
TCCR1A = 0;
TCCR1B = _BV (WGM12) | _BV (CS10);
#else
#error Dont know how to setup timer1
#endif

// set PoutputCompare to get desired Timer1 frequency
OCR1A = (unsigned short) ((uint32_t) XTAL_PHI / INTERRUPTS_PER_SECOND);

// output compare interrupt for timer 1
timer_enable_int (_BV (OCIE1A));
}



Nach Aufruf von init_timer1() und sei() kannst du zB Zähler in der entsprechenden Interrupt-Routine erhöhen oder was dir sonst noch einfällt, und den in deiner main-loop abtesten/zurücksetzen, etc.



#include <inttypes.h>
#include <avr/interrupt.h>
#include <avr/signal.h>

#include "timer.h"

SIGNAL (SIG_OUTPUT_COMPARE1A)
{
...
}


Der Rest ist eigener Gehirnschmalz...

fed111
12.07.2005, 16:10
danke für die schnelle antwort!!!! ich werd das sofort testen. das geht ja leichter als ich gedacht hab... 8-[ 8-[ 8-[

PS: bin übrigens aus Saarlouis, also nit so weit von SB weg...

SprinterSB
12.07.2005, 16:15
Klaro. Wie man die Timer initialisiert sieht man etwa an den Beispielen, die mit winavr mitkommen.
Und die AVRs sind ja einfach zu bedienen und die Manuals von Atmel sind super. Einfach lesen, proggen und es funzt...

fed111
12.07.2005, 18:24
ich habs jetzt mal ausprobert... und es hat super geklappt!!!

danke nochmal

SprinterSB
13.07.2005, 07:54
Hat sich aber wohl doch ein kleiner Fehler eingeschlichen.
In timer.c muss es heissen:


// set PoutputCompare to get desired Timer1 frequency
OCR1A = (unsigned short) ((uint32_t) XTAL_PHI / INTERRUPTS_PER_SECOND -1);


Oder?

fed111
13.07.2005, 15:36
kann auch sein... mich kannste da nicht fragen ich kenn mich da eh noch nicht so gut aus. aber trotzdem mal danke. ich probiers gleich mal aus (eigentlich hat's davor auch schon geklappt)

SprinterSB
13.07.2005, 16:21
Klar, funktionieren muss es nach wie vor. Aber wenn man das benutzt um ne Uhr zu betreiben, geht sie ohne die "-1" etwas nach.
Hab ich erst jetzt beim angucken der Codes bemerkt, weil ich die Zeit normal durch ein DCF-Modul bekomme.

Falls die Interrupts nur sehr selten kommen sollen, musst du mit dem Prescaler arbeiten, denn
XTAL_PHI / INTERRUPTS_PER_SECOND muss in 16 Bits reinpassen.
Um sicher zu sein, daß das der Fall ist, geht zB:

#if (XTAL_PHI / INTERRUPTS_PER_SECOND == 0) || (XTAL_PHI / INTERRUPTS_PER_SECOND > 655535)
#error INTERRUPTS_PER_SECOND ist zu gross oder zu klein
#endif


Oder die Interrupts zählen wie gehabt.