PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : PWM/Timer wie auch immer. Kann so nich sein



m_priester
11.05.2007, 03:28
Hallo zusammen.

Ich versuche langsam die Timer des AVRs zu verstehen und zu programmieren. Klappt soweit auch wunderbar, nur bin ich jetzt an einer Stelle an der ich nicht alleine weiterkomme. Ich habe ein kleines Programm geschrieben, dass eine LED an- und ausschaltet. Dies soll im Sekundentakt geschehen.

Ich habe es in sofern realisiert, dass ich in einem definierten Zeitintervall immer wieder einen Interrupt auslöse, dort eine Variable um den Wert eins erhöhe und diese somit zu meinem Zeitmesser mache.

Jetzt habe ich aber einen Zeitunterschied, den ich mir nicht erklären kann: Wenn ich den Interrupt "seltener" auslöse, ist die Sekunde auch eine Sekunde lang (soweit ich das messen kann). Löse ich den Interrupt jedoch häufiger aus so ist meine definierte Sekunde keine Sekunde mehr lang.

Hier der Code:


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

volatile long x,i;

void timerinit(void)
{
DDRC = 0xFF;
PORTC = 0x00;
TCCR1A=0;
TCCR1B = (1<<CS10)|(0<<CS11)|(0<<CS12) ; // Teiler = 1 -> 16MHZ
TIMSK |= (1<< TOIE1);
sei();
}


int main(void)
{
long j;
timerinit();
for (;;) {}
}

//Sehr lange Sekunde, ca. 3 Sekunden:
ISR (TIMER1_OVF_vect)
{
if (i>=1000000) i=0; //Wenn i=1000000 (entspricht einer Sekunde) dann fang eine neue Sekunde an
if (i<= 500000) PORTC = (1<<PC0); //Mach 'ne halbe Sekunde die LED an
else PORTC &= ~(1<<PC0); //Ne halbe Sekunde aus
i++;
TCNT1 = 0-16; //Zähl' bis 16 => 1000000 mal pro Sekunde ein Interrupt
}


/* //Durch mitzählen kein Fehler:
ISR (TIMER1_OVF_vect)
{
if (i==1000) i=0; //Wenn i=1000 (entspricht einer Sekunde) dann fang eine neue Sekunde an
if (i<= 500) PORTC = (1<<PC0); //Mach 'ne halbe Sekunde die LED an
else PORTC &= ~(1<<PC0); //Ne halbe Sekunde aus
i++;
TCNT1 = 0-16000; //Zähl' bis 16000 => 1000 mal pro Sekunde ein Interrupt
} */



Wär' nett, wenn jemand mal darüber schaut.

Danke,
Stephan

robo junior
11.05.2007, 08:08
Hallo

also zuerst mal zu deiner Timer Einstellung. Was für ein AVR ist das denn? Bei dem Mega 8 wäre deine TCCR1B Einstellung z.B. "External clock source on T1 pin. Clock on rising edge"
Außerdem würde ich nicht um eine Sekunde zu messen den Prescaler auf 1 stellen und dann noch so vorladen, dass man 1000000 Interrupts pro Sekunde hat. Es gibt hier irgendwo ein kleines Programm (rnAVR) damit kann man recht gut bestimmen, was man so als Prescaler und Vorladewerte nehmen kann.
Ich würde das dann so machen: (für den Mega8, musst du dann übertragen)



int main(void) {

DDRC |= (1<<0);
PORTC &= ~(1<<0);

TCCR1B |= (1<<CS12); //Prescaler 256
TCNT1 = 3036; //Vorladewert für den Timer
TIMSK |= (1<<TOIE1);

sei();
}

ISR(TIMER_OVF_vect) {
PORTC ^= (1<<PC0);
TCNT1 = 3036;
}