mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik LPC2134, Timer


Autor: Sergey S. (Firma: ARM LPC2134, uVision3, in C) (serik00)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
LPC2134
ARM UVision 4
Programmiersprache C

Guten Morgen,

ich hbae ein Timerproblem:
Bei mir läuft die Peripherieclock PCLK mit 55.592 MHz (PCLK = CCLK).
Mit Vorteiler 553dez (55.296 MHz / 553dez) erreiche ich 99.992,766 KHz
T0PR = 0x00000229; 553dez = 229hex
99.992,766 KHz / 100dez (0x64) = 999,927 Hz (1ms)
T0MR0 = 0x0064;
D.h die ISR wird jede 1 ms aufgerufen. In der ISR Routine zähle 
incrementiere ich timer0_MS_counter bis 1000, da wird timer0_SEC_counter
incrementiert um Secunden zu zählen.

Aber irgendwie wird die Secunde nach 4 sec incrementiert?
Sind meine Berechnungen falsch.
Ich brauch für meinen Code einen Timer mit 1ms Auflösung.
Für Korrekturen oder Alternativen bin ich sehr dankbar.

int timer0_init(void)
{ 
  // Timer 0 Interrupt reset, Interrupt Register                                 
    T0IR = 0x000000FF; 
  // Timer Counter und Prescale Counter are enable for counting, Timer Control Register                              
    T0TCR = 0x00000001;    
  // Choise for Timer Counter: every rising PCLK edge                                               
    T0CTCR = 0x00000000;                      
  // 55.296 MHz / 100 = 552,960 -> Divider 553dez  
  T0PR = 0x00000100;  // Prescaler auf 99,99 KHz 
  //T0PR = 0x00000229;  // Prescaler auf 99,99 KHz    
  // 0x64, Match mit 999,9Hz (1ms)                      
    T0MR0 = 0x0064;        // Timer0 Match Register                                     
    // Match Control Register                                              
    T0MCR = 0x00000003;                                                                     
    T0EMR &= 0x00000000;    // External Match Register (Status lesen und Kontrolle)   
  VICVectAddr0 = (unsigned long)tc0;          // set interrupt vector in 0 ISR=tc0
  VICVectCntl0 = 0x20 | 4;                    // use it for Timer 0 Interrupt
  VICIntEnable = 0x00000010;                  // Enable Timer0 Interrupt   
  return 0;
}


unsigned int timer0_SEC_counter = 0;
unsigned int timer0_MS_counter = 0;

void tc0 (void) __irq
{  
  timer0_MS_counter++;
  if ( timer0_MS_counter == 1000 )
  {
      timer0_SEC_counter++;      //Increment Timer each 5 ms
      timer0_MS_counter = 0;          
  }
  T0IR = 1;                                 // Clear interrupt flag
  VICVectAddr = 0; 
}

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eugen Spaß schrieb:

> Bei mir läuft die Peripherieclock PCLK mit 55.592 MHz (PCLK = CCLK).

Ganz sicher? Von Haus aus hat der CCLK/4.

Weshalb verwendest du krampfhaft Hexzahlen, wo dezimale Zahlen mehr 
Aussagekraft haben? Compiler und Maschine ist das völlig egal.

Weshalb lässt du den Compiler nicht selber rechnen, also beispielsweise 
sowas wie
  T0PR = PCLK / 100000;
  T0MR0 = 100000 / 100;
Keine Sorge, das wird schon vom Compiler und nicht erst zu Laufzeit 
gerechnet.

Dann wäre auch diese Diskrepanz vom Tisch:
  T0PR = 0x00000229; 553dez = 229hex
  T0PR = 0x00000100;  // Prescaler auf 99,99 KHz

Autor: Sergey S. (Firma: ARM LPC2134, uVision3, in C) (serik00)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Danke für den Tipp.
Die PCLK = CCLK, VBP DIVIDER ist auf 0x01 eingestellt,
hab unter Peripherals kontrolliert.

Jetzt läuft die Variable timer0_MS_counter sehr langsam, es sieht als 
wäre es secunden counter, ich lasse das ganze im Simulation Modus 
laufen.

Ist meine Rechung falsch?
T0PR = 553;
T0MR0 = 100
#define PCLK           55296000     // PCLK (Perepherie Clock) = CCLK (CPU Clock)
#define PRESCALER_REGISTER    553
#define MATCH_REGISTER       100  

int timer0_init(void)
{                                
    T0IR = 0x000000FF;                            
    T0TCR = 0x00000001;                                                 
    T0CTCR = 0x00000000; 
  T0PR = PRESCALER_REGISTER;
  T0MR0 = MATCH_REGISTER;                                              
    T0MCR = 0x00000003;                                                                     
    T0EMR &= 0x00000000;    // External Match Register (Status lesen und Kontrolle)   
  VICVectAddr0 = (unsigned long)tc0;          // set interrupt vector in 0 ISR=tc0
  VICVectCntl0 = 0x20 | 4;                    // use it for Timer 0 Interrupt
  VICIntEnable = 0x00000010;                  // Enable Timer0 Interrupt   
  return 0;
}   
unsigned int timer0_SEC_counter = 0;
unsigned int timer0_MS_counter = 0;


void tc0 (void) __irq
{  
  timer0_MS_counter++;
  T0IR = 1;                                 // Clear interrupt flag
  VICVectAddr = 0; 
}

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mich stört, dass das Prescaler-Limit (PR im Bild) ein bischen grösser 
ist als 533. Da läuft was schief.

Ausserdem muss timer0_MS_counter volatile sein.

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.