Hallo zusammen, Ich programmiere mit CoIde ein selbst zusammengestelltes Board mit LPC11C24 Controller. Ich will mittels eines Timer Interrupts LEDs pulsen. Hierfür nehme ich den 16_Bit_Timer_0. Mein Problem ist,dass mein Programm nicht in die ISR springt. Warum? Woher weiß der Controller, welche ISR er ausführen muss? Meine Code sieht folgendermaßen aus: #include "lpc11xx_gpio.h" #include <system_LPC11xx.h> #include "lpc_types.h" #include "lpc11xx_iocon.h" #include "lpc11xx_tmr.h" #include<My_functions.h> #define _LPC11xx_H_ #define Sysclock_16_Bit_0 0x40 void TIMER_16_0_IRQHandler(void) // ISR für Interrupt durch 16-Bit-Timer {ein();//LEDs werden eingeschalten LPC_TMR16B0->IR&=~0x3F; // Timer Interrupt löschen } void wait (void) { int i=0; for(i =0;i<=100000;i++) {} } int main(void) { NVIC_EnableIRQ(TIMER_16_0_IRQn ); // 16 - Bit - Timer Interrupt einschalten SYSCON_AHBPeriphClockCmd(Sysclock_16_Bit_0,ENABLE); // Clock für 16 Bit Time ein LPC_SYSCON->MAINCLKSEL = 0x01; LPC_TMR16B0->TCR |= 0x01; //16-Bit Counter ein LPC_TMR16B0->TC |= 0xFFFF;// Overflow bei 0xFFFF LPC_TMR16B0->PR |= 0x0FF; //Prescale 0xFF; LPC_TMR16B0->MCR |= 0x01; // Match Register Interrupt enable LPC_TMR16B0->MR0 |= 0xFFFF; // Interrupt, wenn Timer 1 FFFF erreicht ledinit(); // Pins für LED werden initialisiert wait(); aus();// LEDs werden ausgeschalten while(1) { } } Meine Leds schalten sich nicht wieder ein, was heißt, das er nicht in die ISR springt. warum?
Matthias R. schrieb: > Woher weiß der Controller, > welche ISR er ausführen muss? Am Namen - typischerweise ist im Startupcode oder so der ISR-Vektor hinterlegt, welcher die ISR's nach ihrem Namen abfragt und auflistet. Daher muss deine ISR genau den richtigen Namen haben - keine Ahnung ob das bei dir der Fall ist.
Dr. Sommer schrieb: > Matthias R. schrieb: >> Woher weiß der Controller, >> welche ISR er ausführen muss? > Am Namen - typischerweise ist im Startupcode oder so der ISR-Vektor > hinterlegt, welcher die ISR's nach ihrem Namen abfragt und auflistet. > Daher muss deine ISR genau den richtigen Namen haben - keine Ahnung ob > das bei dir der Fall ist. Wie wird die Datei übersetzt? als C oder C++? Sollte es C++ sein, dann geht es so nicht. Da muss die Interrupt-Routine als extern "C" deklariert werden. Dann machst du alles irgendwie verkehrt rum. Ich würde zuerst die Leds initialisieren, die Timer-Register setzen, dann den Interrupt im NVIC enablen und zum Schluss erst den Timer mit Enable im TCR loslaufen lassen. Hast du keinen Debugger?
der Code sieht erstmal nicht so verkehrt aus. Die ISR Namen sind üblicherweise im startup code zu finden. Darin ist eine Tabelle mit den Sprungvektoren abgelegt. Die sind mit defaults belegt die meist in einer Endlosschleife enden. Durch das Attribut 'weak' nimmt der Linker aber einen anderen IRQ-Handler wenn vorhanden. Von der Reihenfolge her würde ich den timer erst starten (TCR=1) wenn die restliche Timerconfig gesetzt ist.
Und mit die Interrupts müssen nochmal global freigegeben werden.
Danke für die schnellen Antworten!! ich programmiere in C. Habe die Header Datei mit den Namensbezeichnung der ISRs gefunden und den Ablauf des Programms geändert. Jetzt springt es ins Interrupt, aber nicht mehr heraus. Habe es mit return probiert, funktioniert aber nicht. Wie kann ich die ISR beenden? Mein Code sieht jetzt so aus: #include "lpc11xx_gpio.h" #include <system_LPC11xx.h> #include "lpc_types.h" #include "lpc11xx_iocon.h" #include "lpc11xx_tmr.h" #include <My_functions.h> #define _LPC11xx_H_ #define Sysclock_16_Bit_0 0x40 void TIMER16_0_IRQHandler(void) // ISR für Interrupt durch 16-Bit-Timer {ein();//LEDs werden eingeschalten LPC_TMR16B0->IR&=~0x3F; // Timer Interrupt löschen return(0); } void wait (void) { int i=0; for(i =0;i<=100000;i++) {} } int main(void) { ledinit(); // Pins für LED werden initialisiert LPC_SYSCON->SYSAHBCLKCTRL|=0x80;//// Clock für 16 Bit Time ein LPC_SYSCON->MAINCLKSEL = 0x01; LPC_TMR16B0->TC |= 0xFFFF;// Overflow bei 0xFFFF LPC_TMR16B0->PR |= 0x001; //Prescale 0xFF; LPC_TMR16B0->MCR |= 0x01; // Match Register Interrupt enable LPC_TMR16B0->MR0 |= 0xFFFF; // Interrupt, wenn Timer 1 FFFF erreicht NVIC_EnableIRQ(TIMER_16_0_IRQn ); // 16 - Bit - Timer Interrupt einschalten LPC_TMR16B0->TCR |= 0x01; //16-Bit Counter ein wait(); aus();// LEDs werden ausgeschalten while(1) { } }
wieder einer, der nicht begriffen hat, dass ein c-programm nicht mit main() beginnt. Schau dir den startup-code an, dann sollte alles klar sein.
Matthias R. schrieb: > Jetzt springt es ins Interrupt, aber nicht mehr heraus. Habe es mit > return probiert, funktioniert aber nicht. return braucht man nicht - und return (0) sollte auch einen Fehler geben bei einer Funktion mit Rückgabetype "void"... Vermutlich wird sofort die ISR nochmal aufgerufen.
Scheinbar wird das Interrupt schon wieder ausgelöst, bis die ISR zu Ende ist, da wenn ich das Interrupt innerhalb der ISR aussschalte, der Controller aus der ISR geht. #include "lpc11xx_gpio.h" #include <system_LPC11xx.h> #include "lpc_types.h" #include "lpc11xx_iocon.h" #include "lpc11xx_tmr.h" #include <My_functions.h> #define _LPC11xx_H_ #define Sysclock_16_Bit_0 0x40 void wait (void) { int i=0; for(i =0;i<=100000;i++) {} } int main(void) { ledinit(); // Pins für LED werden initialisiert LPC_SYSCON->SYSAHBCLKCTRL|=0x80;//// Clock für 16 Bit Time ein LPC_SYSCON->MAINCLKSEL = 0x01; LPC_TMR16B0->TC |= 0xFFFE;// Overflow bei 0xFFFF LPC_TMR16B0->PR |= 0xFFFF; //Prescale 0xFF; LPC_TMR16B0->MCR |= 0x03; // Match Register Interrupt enable LPC_TMR16B0->MR0 |= 0xFFFF; // Interrupt, wenn Timer 1 FFFF erreicht NVIC_EnableIRQ(TIMER_16_0_IRQn ); // 16 - Bit - Timer Interrupt einschalten LPC_TMR16B0->TCR |= 0x01; //16-Bit Counter ein ein();//LEDs werden eingeschalten wait(); aus();// LEDs werden ausgeschalten while(1) { } } void TIMER16_0_IRQHandler(void) // ISR für Interrupt durch 16-Bit-Timer {ein();//LEDs werden eingeschalten }
Matthias R. schrieb: > void TIMER16_0_IRQHandler(void) // ISR für Interrupt durch > 16-Bit-Timer > {ein();//LEDs werden eingeschalten > LPC_TMR16B0->IR&=~0x3F; // Timer Interrupt löschen > return(0); > } Zuallererst richtig im Handbuch lesen: Interrupt Register (TMR16B0IR and TMR16B1IR) The Interrupt Register (IR) consists of four bits for the match interrupts and one bit for the capture interrupt. If an interrupt is generated then the corresponding bit in the IR will be HIGH. Otherwise, the bit will be LOW. Writing a logic one to the corresponding IR bit will reset the interrupt. Writing a zero has no effect. Das heißt wenn schon dann so: LPC_TMR16B0->IR=0x1F Zusätzlich: Glückwunsch! Hier bist du schon bei deinen ersten Zeilen auf ein paar Fallstricke gestoßen die so nicht in den Dokumentationen auftauchen. Die Hardware (Timer u.s.w.) sind über einen Bus an die CPU angekoppelt. Das hat zur Folge, wenn du am Ende der Interruptroutine erst das IR-Flag löscht, ist dieser Zustand noch garnicht beim NVIC angekommen, aber dein Interrupt schon zu Ende. Danach wird er sofort neu gestartet. Wenn du das Flag vor deiner ein()-Funktion löscht sollte die Zeit ausreichen.
Habe jetzt 'LPC_TMR16B0->IR=0x1F' vor ein() und jetzt geht er wieder aus dem Interrupt raus. Was mich jedoch wundert ist, nachdem der Timer gestartet wurde , 2 Steps im Debug-Modus später schon das Interrupt auslöst und er das Interrupt nicht mehr aufruft. Warum? Ich kann den Timer Value währenddes debuggens leider nicht auslesen. Hat jemand ein Code Beispiel mit einem funktionierenden Timer-Interrupt ,welches immer wieder in gewissen Zeitabständen aufgerufen wird? Mein Code sieht jetzt so aus: #include "lpc11xx_gpio.h" #include <system_LPC11xx.h> #include "lpc_types.h" #include "lpc11xx_iocon.h" #include "lpc11xx_tmr.h" #include <My_functions.h> #define LPC11xx_H #define Sysclock_16_Bit_0 0x40 void wait (void) { int i=0; for(i =0;i<=100000;i++) {} } int main(void) { ledinit(); // Pins für LED werden initialisiert LPC_SYSCON->SYSAHBCLKCTRL|=0x80;//// Clock für 16 Bit Time ein LPC_SYSCON->MAINCLKSEL = 0x01; LPC_TMR16B0->TC |= 0xFFFE;// Overflow bei 0xFFFF LPC_TMR16B0->PR |= 0xFFFF; //Prescale 0xFFFF; LPC_TMR16B0->MCR |= 0x03; // Match Register Interrupt enable LPC_TMR16B0->MR0 |= 0xFFFF; // Interrupt, wenn Timer 1 FFFF erreicht NVIC_EnableIRQ(TIMER_16_0_IRQn ); // 16 - Bit - Timer Interrupt einschalten LPC_TMR16B0->TCR |= 0x01; //16-Bit Counter ein ein();//LEDs werden eingeschalten wait(); aus();// LEDs werden ausgeschalten while(1) { } } void TIMER16_0_IRQHandler(void) // ISR für Interrupt durch16-Bit-Timer {LPC_TMR16B0->IR|=0x1F; ein();//LEDs werden eingeschalten }
Den ersten Interrupt kriegst du, weil du TC mit dem selben Wert initialisierst wie MR0. Normalerweise braucht TC nicht gesetzt zu werden, das ist ja der eigentliche Zähler. Zusammen mit dem Prescaler von 0xffff ergibt das einen Überlauf nach 2^32 Takten. Macht bei 48Mhz rund 89 Sekunden. Hast du überhaupt solange gewartet?
Achso. Hab gedacht TC gibt den Wert an, bis den der Counter zählt. Hab den Befehl gelöscht, jetzt funktionierts :) Vielen Dank!
Die Beschreibung der relativ einfachen Timer der LPC11xx Serie ist eigentlich ganz gut. Dein Hauptproblem war wohl sich zu wenig mit der Doku beschäftigt zu haben. Das wäre aber dringen angeraten wenn du tiefer einsteigen willst ohne jedesmal frustriert hängen zu bleiben...
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.