Hi, Meine Versuche einen Timer des LPC2294 als Intervall -Timer zu programmieren schlugen bislang fehl. Der Timer wird richtig initialisiert und nach der vorgegebenen Zeit wird auch ein Interrupt ausgelöst. Problem ist nur, dass die ISR des Timers nie ausgeführt wird. In der ISR wird lediglich die Systemuhr aktualisiert und das Interrupt-Flag gelöscht. Die von mir definierte ISR sieht folgendermaßen aus: // this function is to be called when a timer interrupt is generated void __attribute__((interrupt("IRQ"))) timerIntHandler(void); void timerIntHandler(void) { timeNow+= ####; // #### is the time between 2 timer interrupts T0IR = (1<<0); // Clear interrupt flag by writing 1 to Bit 0 VICVectAddr = 0; // Acknowledge Interrupt } Die Adresse dieser Funktion wird auch in den entsprechenden Interrupt-Vektor geschrieben: VICVectAddr0 = (unsigned long)timerIntHandler; Ich habe mehrmals gecheckt, ob irgend etwas bei der Initialisierung vergessen wurde und meiner Meinung nach müsste alles richtig sein. Ich würde mich freuen, wenn der eine oder andere einen Tipp parat hat. PS: ARM-gcc-Toolchain Vielen Dank Hammoud
Hallo, interessant wäre nicht nur die ISR Routine sondern die Initialisierung selbst. Der VIC braucht noch die dazugehörige Interruptfreigabe. Beim LPC2138 sieht das in etwa so aus: VICIntSelect &= ~0x10; VICIntEnable = 0x10; VICVectCntl0 = 0x24; /* vectored interrupt control reg */ VICVectAddr0 = (unsigned long)timerIntHandler; TOTCR = 0; /* stop timer */ T0PR = 0; /* prescaler */ T0MR0 = wert; /* set match register */ T0MCR = 1; /* interrupt bei match */ T0TCR = 1; /* start timer */ ... global interrupt enable nicht vergessen Beim LPC2294 vorher mal im Datenblatt nachschauen. MfG Jens
uint32_t timetick; // globale Variable // Timer Counter 0 Interrupt initialisieren void init_timer (void) { T0MR0 = 14999; // 1mSec = 15.000-1 counts T0MCR = 3; // Interrupt and Reset on MR0 T0TCR = 1; // Timer0 Enable VICVectCntl0 = 0x20 | 4; // IRQ Slot0 für Timer 0 (VIC-Channel 4) VICVectAddr0 = (uint32_t)tc0; // IRQ Slot0 auf Funktion tc0 setzen VICIntEnable = 0x00000010; // Enable Timer0 Interrupt (Bit4=1) } // Timer Counter 0 Interrupt executes each 1ms @ 60 MHz CPU Clock void tc0 (void) __irq { ++timetick; // Interrupt-Aktion: Zeitvariable erhöhen T0IR = 1; // Clear interrupt flag VICVectAddr = 0; // Acknowledge Interrupt }
Sieht ziemlich richtig aus. Verwendest du den Keil? Ich habe hier eine Initialisierungsroutine für einen LPC2138. Versuch die mal. Die Routinen sehen ziemlich kompatibel aus. Es kann sein, dass der Prozessor bei irgendeiner Reihenfolge ein Problem hat. Diese Routine hat bei mir funktioniert: VICVectAddr1 = (unsigned long)timercomp_irq; // set interrupt vector in 1 VICVectCntl1 = 0x20 | 4; // Vic UART0 VICIntEnable = 0x0000010; // Enable Timer Interrupt T0TCR=0x2; // Timer Reset T0CTCR=0x0; // Timermode T0MR0=119; // Vergleichsregister // Überlauf bei 2µs T0MCR=3; // IRQ-Vergleich 0, Timer=0 im Vergleichsregister 0 T0TCR=0x1; // Timer startet void timercomp_irq(void) __irq { T0IR=0x01; if(flag==1) { IOCLR0=x; flag=2; } else { IOSET0=x; flag=1; } VICVectAddr = 0; // Acknowledge Interrupt } Schreib uns, ob du es geschafft hast. Tschüss Martin
Hallo, wir haben mit dem Timer-Demo unter dem folgenden Link schnell einen brauchbaren Timer-Interrupt hinbekommen: http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/ Allerdings haben wir jetzt mit mehrkanaligem Match-IRQ Betrieb Probleme (Rücksetzen der IRQ-Bits), scheint am Chip zu liegen, in den Erratas steht auch eine ganze Menge... Viel Erfolg! Hier Auszüge aus unserem Code: /* Setup the Timer Counter 0 Interrupt */ void init_timer0 (void) { T0PR = 5;//T0 prescaler: clk/(1+prescaler) => 1 tick = 0,1 us T0MR0 = 10000; // 1mSec = 10000 counts T0MR1 = 10000000; // 1Sec = 10 mio counts T0MR2 = 10000000; T0MCR = ( 0x01 | 0x08 | 0x40 ); // Interrupt on MR0 + MR1 + MR2 T0TCR = 1; // Timer0 Enable VICVectAddr0 = (unsigned long)tc0; // set interrupt vector in 0 VICVectCntl0 = 0x20 | 4; // use it for Timer 0 Interrupt VICIntEnable = 0x00000010; // Enable Timer0 Interrupt timerticks = 0; } void _attribute_ ((interrupt("IRQ"))) tc0 (void) { if ( T0IR & 0x01 ) { //Match Register 0: 1ms-Interrupt i_timerticks |= 0x04; T0MR0 += 10000; T0IR = 0x01; // Clear interrupt flag VICVectAddr = 0; // Acknowledge Interrupt } }
Hallo, die Zeile: VICVectAddr = 0; muss ausserhalb des if body stehen, sonst wird der Interrupt Controller nicht zurück gesetzt, außer die if Bedingung ist erfüllt. Gruß, Joachim
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.