PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : beschleunigen mit timer



exile
16.08.2005, 22:10
Hallo allerseits,

ich versuche seit geraumer Zeit auf meinem Atmega16 mittel des timer0 eine Wartefunktion zu implementieren.

Meine Funktion timer_set(unsigned short ms) erechnet aus dem übergebenem Parameter ms, wie oft der voreingestellte Timer durchlaufen werden muss. In meiner SIGNAL ( SIG_OVERFLOW0 ) soll aber kein spezieller Code aufgeführt werden, ausser den timer stoppen wenn er fertig ist.
Der Timer selbst funktioniert gut aber ein Aufruf wie:


for (i = 160; i > 0; i--) {
pwm ( A | B, i);
timer_run(100);
}
um eine beschleunigung beider Motoren A und B zu erzeugen, funktioniert aber nicht. Ich vermute, dass der Timer gestartet wird, aber der µC parallel dazu den Rest ausführt.

Gibt es eine Möglichkeit so eine Wartefunktion zu implementieren, ohne zb Zeiger auf Funktionen, oder eine while-Schleife mit "nop", zu benutzen?
Denn ein _delay_ms(xyz) funktioniert, aber der µC führt Befehle erst nach dem beenden von _delay_ms aus, selbst Interrupts.

Vielleicht gibts ja eine bessere Lösung?!

mfg
Martin

exile
17.08.2005, 13:20
Jetzt läuft der timer, zwar nicht ganz so wie ich es wollte, aber er läuft =).

timer:

volatile unsigned short time;
volatile unsigned short time_org;
void (*timer_func) (void);
volatile unsigned int pause;
volatile unsigned short counter = 0;
volatile unsigned char reload;


// timer 0 initialisieren
void timer_init (void) {
// prescale auf 1024 stellen (S.83)
// -> 8MHz/1024 = 7812.5 Hz
// TCCR0 = _BV (CS02) | _BV(CS00);

// startwert des timers einstellen
// von 0 bis 256 (2^8), default: 0
// 80000 Takte fuer 10 ms / 1024 prescaler
// -> 78,125 zaehler fuer 10 ms
// => 256 - 78 = _178_
reload = 178;
TCNT0 = reload;

// bei einem Überlauf des Datenregisters des Timer/Counter 0
// ein Timer Overflow 0 Interrupt ausgeloesen (S. 83-84)
// TIMSK = _BV(TOIE0);

// Global Enable Interrupt Flag
// sei();
}

void timer_off (void) {
TCCR0 = 0x00;
}

void timer_run (unsigned short ms, void (*func) (void), unsigned char count ) {
//void timer_run (unsigned short ms) {
timer_func = func;
counter = count;
time = ms/10;

// alle 80 ms geht es 1 s nach
time += time / 80;
time_org = time;

TCCR0 = _BV (CS02) | _BV(CS00);
TIMSK = _BV(TOIE0);
}

overflow interrupt:

SIGNAL ( SIG_OVERFLOW0 ) {
TCNT0 = reload;

if (!time) {
timer_func();
counter--;
time = time_org;

if (counter <= 0)
timer_off();
}
time--;
}

Testfunktion (blinker):


void blink (void) {
PORTB ^= (1<<PB0);
}

und der aufruf:

timer_run(1000, blink, 20);

Der Timer führt alle 1000ms die Funktion blink() aus und wiederholt das Ganze 20 mal bis er sich selbst ausschaltet.

Mein Frage jetzt:
Ist das eine brauchbare Lösung? Oder ergeben sich dadurch mir noch nicht ersichtliche Nachteile?