PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Zeitmessung mit ATMega32



stormracer
22.01.2007, 18:14
Moin,
ich habe ein Problem und zwar weiß ich nicht wie ich die Timer des ATMegas einstellen muss, um die Zeit zwischen zwei Tastendrucks (einfach nur zu Übungszwecken) zu messen.

Ich programmiere in C.

Im I-Net habe ich noch nicht so wirklich hilfreiche Seiten gefunden, würde mich also freuen wenn da jmd. noch interessante Seiten kennt.

Freue mich über jeden hilfreichen Hinweis
Stormracer

bL1nK
22.01.2007, 18:26
naja timer initialisieren und dir nen algorithmus ausdenken.

zb. ne variable initialisieren die in der overflow ISR immer um eins erhöht wird ;)

stormracer
22.01.2007, 19:11
Danke für den Tipp, aber leider hab ich noch nicht wirklich viel Ahnung von dem Timer. Kennst du evtl. noch eine deutschsprachige Seite auf der das gut erklärt ist? ich lese mir grad das AVR-GCC Tutorial von mikrocontroller.net durch.
Stormracer

bL1nK
22.01.2007, 20:12
naja also der ultimative tip ist: schau mal ins datenblatt.

bei atmel sind immer gute beispiele in C und ASM drin, nachteil is halt auf englisch ;)

stormracer
23.01.2007, 19:34
So, da bin ich wieder.
Habe jetzt auch meine ersten Erfolge mit dem Timer, aber auch meine ersten Unverständlichkeiten.

Und zwar lasse ich mir den Wert des Timers und die Variable, die anzeigt wie oft der Timer schon übergelaufen ist per UART und HyperTerminal anzeigen.
Aber dort sehe ich, das der Timer seinen Überlauf immer bei 0 hat. Also der Zähler fängt bei Null an und zählt bis 32535, dann springt er nach -32536 und zählt bis Null, bei Null wird dann der Interrupt ausgelöst.

Egal was für einen Variablentyp ich auswähle, ich bekomme eine negativen Wert, das kann ja eigentlich nicht stimmen. :-k Habe jetzt den uint16_t.

Kann mir einer sagen, ob das so richtig ist, oder ob ich was falsch eingestellt habe.

Ich benutze einen ATMega32 und den Timer1 mit 16Bit.

Mein Code:


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


void uart_init (void);
int uart_putchar(char c, FILE *stream);
static FILE mystdout = FDEV_SETUP_STREAM( uart_putchar, NULL, _FDEV_SETUP_WRITE );

volatile uint16_t x=0;

int main (void)
{

uint16_t n=0;

stdout = &mystdout;
uart_init();

sei();

TCCR1B |= (1<<CS12)|(0<<CS11)|(1<<CS10); // Prescaler 1024
TIMSK |= (1<<TOIE1); // Interrupt bei Overflow

while(1)
{
n=TCNT1;
printf("Over: %d",x);
printf(" Counter: %d\n",n);
}
}

ISR(TIMER1_OVF_vect) //Interrupt bei Overflow Timer1
{
x++;
}


void uart_init (void)
{
/* USART-Init 19200 Baud bei 16MHz für Mega32 */
UCSRB |= ( 1 << TXEN ); // UART TX einschalten
UCSRC |= ( 1 << URSEL )|( 3<<UCSZ0 ); // Asynchron 8N1
UBRRH = 0;
UBRRL = 51;
}


int uart_putchar( char c, FILE *stream ) // Funktion für printf()
{
if( c == '\n' )
uart_putchar( '\r', stream );

loop_until_bit_is_set( UCSRA, UDRE );
UDR = c;
return 0;
}

ogni42
23.01.2007, 19:50
Der Timer zählt unsigned bis 0xffff und löst den Interrupt beim Überlauf 0xffff->0x0000 aus. Kurz gesagt: Das ist so richtig.

%d bei printf erwartet einen signed integer.

stormracer
23.01.2007, 20:25
%d bei printf erwartet einen signed integer.

THX für den guten Hinweis, an so etwas hatte ich noch gar nicht gedacht. ](*,) Hab es jetzt nach %u geändert und funktioniert einbahn frei.

bL1nK
23.01.2007, 21:37
du musst halt aufpassen wie du den timer einstellst, prescaler zum beispiel.

dann kannst du dir aus der F_CPU und prescaler die zeit ausrechnen die er braucht um einmal bis 0xFFFF zu zählen, es kann unter umständen sein das dir die auflösung dann zu grob ist.

z.b. F_CPU 8MHz Prescaler 1024 -> 8,38 sekunden für einen overflow

sprich du hast ne auflösung von 8,4 sekunden das kann unter umständen zu grob sein ;)

einfach das zählregister vorbelegen zb mit dem startwert 0xFE78 dann bekommst nen overflow alle 50ms das zählregister aber in jeder ISR wieder mit dem startwert belegen.