www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik LPC2368: RTC löst dauernd IRQ aus


Autor: Christian J. (elektroniker1968)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

vielleicht sollte ich doch einen Sammelthread aufmachen....

Ich möchte einfach nur jede Minute durch die RTC im LPC2368 einen IRQ 
auslösen. Die IRQs werden auch ausgelöst aber dauernd, d.h. der uC ist 
sofort nach Verlassen der ISR wieder drin, hat kaum für was anderes 
Zeit. Die LEDS flimmern beide gleichmässig, statt jede Minute zu 
wechseln.

Dabei lösche ich doch die IRQ Anforderung
RTC_ILR  |= RTC_ILR_RTCCIF;     // 1= RTC IRQ Flags
in der ISR.

Mir fällt nichts mehr ein, habe das Keil Beispiel studiert, das sieht 
genauso aus wie meines. Das  __ARMLIB_enableIRQ() ist übrigens nur ein 
Makro für Rowley Programme, ähnliche dem IEENABLE bei Keil. 
VECTORED_IRQ_INTERRUPTS habe ich im Präprozessor auch definiert, sonst 
läuft die ISR gar nicht.

Der Aufruf
 Init_RTC();
 Init_RTC_ISR(RTC_CIIR_IMMIN);
 __ARMLIB_enableIRQ();


Hier der Code

void Init_RTC()
{
  RTC_CCR = 0;         // RTC ausschalten
  PCONP    |=  (1 << 9);   // RTC mit Strom versorgen
  RTC_AMR  = 0xff;       // Alle Alarms deaktivieren
  RTC_CIIR  = 0;       // Alle IRQs aus

  // Die RTC starten und auf 32khz Quarz legen
  RTC_CCR |= (1<<CCR_CLKSRC_BIT);
  RTC_CCR |= (1<<CCR_CLKEN_BIT) ;
}


// ISR installieren (mode, s. header file)
BOOL Init_RTC_ISR(uint8_t mode)
{

  RTC_ILR &= ~(1 << RTC_ILR_RTCCIF);  // Lösche das RTC_ILR, pending IRQ's
  RTC_CIIR  = mode;            // Setze 1s IRQ Auslösung, alle anderen Bits = 0

  // Installiere die ISR

/* alternativer Code statt Keil, läuft auch
  VICVectAddr13 = (uint32_t)&RTC_ISR;
  VICIntEnable = 1 << RTC_INT;
*/

  if ((Install_irq (RTC_INT, (void*)RTC_ISR,LOWEST_PRIORITY)) == FALSE)
  return FALSE;

  return TRUE;

}

Die ISR
/ Die ISR der RTC
void __attribute__ ((interrupt("IRQ"))) RTC_ISR (void)
{
  static char sw = 0;

  if (sw == 0)  {
  LED1_ON();
  LED2_OFF();
    sw  = 1;
  }
  else if (sw == 1)
  {
  LED1_OFF();
  LED2_ON();
  sw = 0;
  }

  RTC_ILR  |= RTC_ILR_RTCCIF;     // 1= RTC IRQ Flags löschen
  VICVectAddr = 0;         // IRQ löschen

}

Die Defines
#define RTC_ILR_RTCCIF    0x01      //ILR Register, Bit für pending IRQs der Uhr

// RTC: Counter Increment IRQ Register Bits
#define RTC_CIIR_IMSEC    0x00000001
#define RTC_CIIR_IMMIN    0x00000002
#define RTC_CIIR_IMHOUR    0x00000004
#define RTC_CIIR_IMDOM    0x00000008
#define RTC_CIIR_IMDOW    0x00000010
#define RTC_CIIR_IMDOY    0x00000020
#define RTC_CIIR_IMMON    0x00000040
#define RTC_CIIR_IMYEAR    0x00000080


Autor: Christian J. (elektroniker1968)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hinweis:

Das Blinken funktioniert, wenn ich in der ISR das IF Flag abfrage und 
nur dann die LEDS ansteuere

if (RTC_ILR & (1<<RTC_ILR_RTCALF))

Leider nütztt das nur wenig, weil die ISR nach wie vor dauernd 
aufgerufen wird und ich nicht weiss warum. Testweise habe ich auch die 
Zeile eingefügt.

RTC_ILR  |= (1<<RTC_ILR_RTCCIF) | (1<<RTC_ILR_RTCALF) | 
(1<<RTC_ILR_RTSSF);

die alle IRQ Quellen der RTC zurücksetzt (1=IRQ löschen)

Ratlos.....

Autor: Kai F. (k-ozz)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaube, du würfelst in deiner Notation etwas durcheinander.
Du hast folgendes Define gemacht:
#define RTC_ILR_RTCCIF    0x01      //ILR Register, Bit für pending IRQs der Uhr
Dann verwendest du dieses Define aber für ein Shift-Befehl.
Wenn du nun aber (1 << RTC_ILR_RTCCIF) schreibst, dann kommt doch 0x02 
raus!? Das willst du aber eigentlich nicht!
Noch ein anderes "Problem". Die Schreibweise RTC_ILR |= xxx bzw. RTC_ILR 
&= xxx ist unnötig, da Bits in dem Register nur gelöscht werden, wenn 
man 1en (Einsen) schreibt. In deiner ISR solltest du also einfach 
schreiben:
RTC_ILR = RTC_ILR_RTCCIF;

Zur Sicherheit solltest du evtl. in der ISR alle anliegenden Interrupts 
löschen, d.h. folgendes schreiben:
RTC_ILR = (RTC_ILR_RTCCIF | RTC_ILR_RTCALF | RTC_ILR_RTSSF);

Der schuldige dürfte bei dir wohl der Sub-Second Interrupt sein:
füge mal folgendes in deine Init_RTC_ISR ein:
RTC_CISS = 0x00;
Damit wird der Sub-Second Interrupt deaktiviert.

Autor: Christian J. (elektroniker1968)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Kai,

der "Schuldige" war der Sub Second IRQ, weil der bei Reset undefiniert 
ist.
(Das weiss man aber auch nur, wenn  mal mal in die Falle reingelaufen 
ist)
Habe ich auch erst herausgefunden als ich mir mal das ILR Register im 
Debugfenster angeschaut habe. Natürlich auch das was Du bemerkt hast.

Ich habe aber noch eine "doofe"  Frage:

Vom PIC her bin ich es gewohnt zu sparen, d.h. Flags kriegen nur ein Bit 
spendiert in einem Byte. Das geht bei dem CCS Compiler, da er den Typ 
bit kennt. Nun lese ich aber immer wieder dass selbst Flags mit uint32_t 
oder unsigned long definiert werden. d.h. sie knallen ganze 32 Bit weg.

Manche RTC Register scheinen nur 8 Bit zu haben, andere 32 Bit. Oder 
haben alle 32 Bit? Oft sieht man ja : Bit 15:32 undefined oder so. Aber 
eben nicht beim IRL; das wird zB als 4 Bit register beschrieben.

Wie adressiert der ARM7 denn nun besser? Wenn ich uint8 für ein kleine 
Zahl nehme oder uint32?

Das Battery RAM wird beschrieben dass es nur 32 Bitr adressierbar ist 
mit "Alignment = 4". Dh. kann man dort gar keine Bytes speichern sondern 
nur uint32.

PS: Spezi Frage: Hat schonmal jemand versuche die RTC genau zu stellen? 
Uhr daneben, Debugger an, los bei genauer Zeit und Debugger wieder 
stoppen. Da der Wiggler ständig resettet, auch wenn man das Debuggen 
abbricht wird die Set Routine auch immer wieder neu durchlaufen und die 
Zeit wieder verstellt bis man den Set Befehl auskommentiert hat. Einzige 
Chance die ich hatte war eine Variable im Battrery Ram anzulegen und die 
nach dem Setzen der Zeit zu verstellen, dass das Setzen nicht erneut 
durchlaufen wird....


Gruss,
Christian

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.