PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ISR per Output Compare funktioniert nicht wie gewünscht



Sebastian132
23.07.2006, 11:33
Hallo! Ich komme hier gerade nicht weiter: Bin gerade dabei ein Programm zu erstellen, in dem u.A. alle 5 Sekunden ein Zeichen auf dem Display (Fleury Lib) ausgegeben werden soll. Nur irgendwie läuft der Timer und die dazugehörige ISR nicht so wie sie soll. Controller ist nen etwas betagtes Modell, der 90s8515, er läuft bei 4 MHz.

Folgendes Problem: Mit dem unten stehenden Code, gibt er etwa jede Sekunde ein Zeichen aus. Aber warum? 4.000.000 1/s /64 (Prescaler) macht nach meiner Ansicht immernoch 62500 1/s, bzw. alle 0,1µs einen Interrupt, warum er dann trotzdem nur jede Sekunde etwas ausgibt verstehe ich nicht. Ebenso tritt keine Änderung ein, wenn ich OCR1B irgendeinen Wert zuweise, immer die gleiche Geschwindigkeit. Nur wenn ich am Prescaler drehe, ändert sich was. Ich weiss immoment echt nicht weiter, auch wenn es bestimmt ein ganz blöder Fehler ist ;).

Hier mal ein Snippet:


#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/delay.h>
#include <avr/pgmspace.h>
#include "lcd.h"
#define F_CPU 4000000
#define CPU_CLK_64 (F_CPU/64)
#define TIMER_SECOND (CPU_CLK_64/2)




int main( void )
{
sei();



lcd_init(LCD_DISP_ON);


TCCR1B |= (1<<CS11)|(1<<CS10); // CPU_CLK/64
//OCR1B=TIMER_SECOND;
TIMSK |= (1<<OCIE1B);





for(;;)
{
}


}

ISR(TIMER1_COMPB_vect) //Interruptroutine
{
lcd_puts("a");

}

Sebastian132
23.07.2006, 12:12
Nochmal per LED ausprobiert (wollte sichergehen, dass die LCD-Lib nicht irgendwas stört). Verhalten leider immernoch wie oben ;(.



#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/delay.h>
#include <avr/pgmspace.h>

#define F_CPU 4000000
#define CPU_CLK_64 (F_CPU/64)
#define TIMER_SECOND (CPU_CLK_64/2)




int main( void )
{
sei();

DDRB |= (1 << DDB2);


//lcd_init(LCD_DISP_ON);


TCCR1B |= (1<<CS11)|(1<<CS10);// CPU_CLK/64
cli();
//OCR1B=TIMER_SECOND;
sei();
TIMSK |= (1<<OCIE1B);





for(;;)
{
}


}

ISR(TIMER1_COMPB_vect) //Interruptroutine
{
if(bit_is_clear(PINB,PB2))
PORTB|=(1<<PB2);
if(bit_is_set(PINB,PB2))
PORTB&=~(1<<PB2);

}

linux_80
23.07.2006, 13:02
Hallo,
da der Timer1 16 Bit hat, würde ich sagen, mit den Einstellungen läuft der Counter einmal rum, und erzeugt den IRQ.
Wenn ich das ausrechne komme ich auf 1,048576s.
Also alle 4MHz/64 wird einmal weitergezählt, beim überlauf 65535, wird der IRQ erzeugt, ist dann etwas mehr als 1 Sekunde.

Sebastian132
23.07.2006, 13:24
Hallo, das klingt durchaus plausibel. Aber wie kann ich den Überlauf auf <65535 festlegen? Mit OCR1B funktioniert das nicht (auch wenn ich vorher die interrupts sperre), und ich habe es auch schon mit CTC1 probiert, dann blinkt gar nichts mehr :(.

linux_80
23.07.2006, 15:08
Schau mal im Wiki unter
https://www.roboternetz.de/wissen/index.php/AVR#Timer.2FCounter
da gibts ein paar sachen wie man mit dem Timer umgeht.
Wenns Dir nur um eine bestimme Zeit geht, kann man das mit dem vorladen eines bestimmten Wertes machen.
Evtl. ist auch der CTC Modus interessant.

Sebastian132
23.07.2006, 15:36
Danke, jetzt klappt es, man muss mittels TCNTx vorladen. Andersherum, so wie ich es gedacht hätte (obere Schranke heruntersetzen) geht es wohl nicht.

SprinterSB
24.07.2006, 06:53
Doch. Wie linux_80 schon geschrieben hat. Der Timer muss in den CTC-Modus.

Sebastian132
24.07.2006, 11:22
Aber im Prinzip läuft es für meinen Anwendungszweck ja aufs selbe hinaus :). Ich werds aber aus didaktischen Gründen nachher nochmal ausprobieren :D.