Hallo bin Anfänger und brauche eure Hilfe.
Stichwort-Timer.
Ich will den Timer so konfigurieren, das er jede Sekunde die LEDs
(P1.24,P1.23) ein und ausschaltet.
Ich weiß der Code ist ziemlich ausbaufähig ist.
TIMER0 Initialisierung:
1
intinit_timer0(void)
2
{
3
//Timer0 ist 32 bit und läuft mit Quarzfrequenz Fosc (XTAL) 11.059200, CCLK (CLOCK) 55.296000
4
//Timer zählt bis 2 hoch 32 durch Prescaler
5
T0PC=//Prescaler einstellen
6
T0MR0=;// 1Sec
7
T0MCR=;// Interrupt and Reset on MR0
8
T0TCR=1;// Timer0 Counter and Prescale Counter Enable
9
//tc IRQ defineiren
10
VICVectAddr0=(unsignedlong)tc0;// set interrupt vector in 0
11
VICVectCntl0=0x20|4;// use it for Timer 0 Interrupt
Der Timer wird von PCLK getaktet, d.h. er läuft entweder mit CCLK, mit
CCLK/2 oder CCLK/4. Entsprechend muß der Wert für T0MR0 angepasst
werden.
Wenn die ISR 1x pro Sekunde aufgerufen werden soll, so muß T0MR0 =
PCLK-1 sein.
Als Alternative kann man die ISR z.B. auch 1x pro ms, d.h. mit 1kHz
aufrufen lassen und eine globale Zählervariable inkrementieren und diese
beim erreichen von 1000 wieder auf 0 zurücksetzen und die LEDs dann
umschalten.
Vielen Dank für den Beitrag!
Ich versuche hier die andere vom Kai vorgeschlagene Lösung.
Klappt nicht ganz. ich denke es liegt an der IRQ-Routine.
Hat jemand eine Idee?
1
T0IR=0x000000FF;//TIMER0 Interrupt Register, Disable all Interrupts
2
VICIntEnable=0x00000000;// Disable Timer0
3
T0TCR=2;// Timer Counter and Prescale Counter are reset
4
T0CTCR=0x00000000;// Choise for TIMER
5
T0PR=0x00000229;//Prescaler auf 99,98 KHz
6
T0MR0=0x0063;// Timer0 Match Register, 0x63 (dez. 99, Teiler 100), ergibt Match mit 999,8 Hz (1ms)
7
T0MCR=0x03;// Interrupt and Reset on MR0
8
T0TCR=1;// Timer Counter and Prescale Counter Enable
9
VICVectAddr0=(unsignedlong)tc0;// set interrupt vector in 0 ISR=tc0
10
VICVectCntl0=0x20|4;// use it for Timer 0 Interrupt
Die Variable timeval wurde global deklariert (also vor der Funktion),
sowie Kai F. es auch geschrieben hat.
Also die IRQ wird aufgerufen.
Die Variable timeval wird von 0 auf eine inkrementiert.
Das wars.
Bei 2. Durchlauf wird die Variable nicht mehr inkrementiert.
Also diese Aussage (short int timeval = 0;) setzt die globale Variable
timeval jedesmal auf 0. richtig?
Die timevar wird zwar einmal erhöht aber dann wieder auch 0 gesetzt.
Und kommt so nie auf 1000.
Also sollte ich doch die globale Variable nur deklarieren:
short int timeval;
Aber irgendwo muss ich die doch initiieren, also eine 0 zuweisen.
Die If-Abfrage funktioniert, wenn ich Wert auf 1000 setze, dann wird die
Abfrage ausgeführt.
>Also diese Aussage (short int timeval = 0;) setzt die globale Variable>timeval jedesmal auf 0. richtig?
Falsch. Nur am Programmstart wird sie auf 0 gesetzt.
>Also sollte ich doch die globale Variable nur deklarieren:>short int timeval;>>Aber irgendwo muss ich die doch initiieren, also eine 0 zuweisen.
Das macht der Compiler schon für dich.
Wenn du es mit Gürtel und Hosenträger möchtest,
kannst du es aber auch selber machen.
Nee, Gürtel reicht:)
Aber dann müsste es doch funktioneiren!?
die variable timevar wird global deklariert und auf 0 gesetzt.
Bei jedem IRQ Aufruf wird diese um eins erhöht.
Wenn Timeval == 1000 ist, dann wird die If-Abfrage ausgeführt und die
Variable wieder auf 0 gesetzt.
So sollte es funktionieren, tut es aber nicht.
Der neue Wert muss nach jeder Inkrementierung zurückgegeben werden.
Das passiert nicht. Richtig?
Wo liegt der Fehler?
>Also liegt es jetzt nicht an IRQ, sondern an Timer Initiierung?
Es liegt an der IRQ. Dort wird (theoretisch) etwas nur
alle 1000 mal ausgeführt, was jedesmal ausgeführt werden muß.
So, jetzt geh ICH essen ;)
Und hats geschmekt?
ja klar!
Der IR flag muss jedesmal gesetzt werden um interrupt wieder zu löschen
und die VICVectAddr muss wieder freigegeben werden.
Und zwar bei jedem Aufruf der IRQ!
Vielen Dank!
1
voidtc0(void)__irq
2
{
3
timeval++;
4
if(timeval==1000)
5
{
6
if(IO1PIN&(1<<24))// sind LEDs momentan aus?
7
IO1CLR=((1<<24)|(1<<25));// dann anschalten
8
else
9
IO1SET=((1<<24)|(1<<25));// sonst ausschalten
10
11
timeval=0;//Variable wieder zurücksetzen
12
}
13
T0IR=1;// Clear interrupt flag
14
VICVectAddr=0;
15
}
Ist diese Lösung sinnvoll?
Denn hier wird IRQ-Routine ständig aufgerufen.
Wird damit nicht die CPU belastet?