CoIDE LPC11C24 Cortex M0, wie ISR ausfrufen?

OP #3592554
Lesenswert?

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?
Gast #3592572
Lesenswert?

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.
Gast #3592697
Lesenswert?

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?
Gast #3592701
Lesenswert?

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.
OP #3592810
Lesenswert?

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)
    {

    }

}
Gast #3592816
Lesenswert?

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.
OP #3592905
Lesenswert?

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

 }
Gast #3592927
Lesenswert?

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.
OP #3593829
Lesenswert?

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

 }
Gast #3594103
Lesenswert?

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?
Gast #3597064
Lesenswert?

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...

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren