Forum: Mikrocontroller und Digitale Elektronik LPC2134, Timer


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


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.

1
int timer0_init(void)
2
{ 
3
  // Timer 0 Interrupt reset, Interrupt Register                                 
4
    T0IR = 0x000000FF; 
5
  // Timer Counter und Prescale Counter are enable for counting, Timer Control Register                              
6
    T0TCR = 0x00000001;    
7
  // Choise for Timer Counter: every rising PCLK edge                                               
8
    T0CTCR = 0x00000000;                      
9
  // 55.296 MHz / 100 = 552,960 -> Divider 553dez  
10
  T0PR = 0x00000100;  // Prescaler auf 99,99 KHz 
11
  //T0PR = 0x00000229;  // Prescaler auf 99,99 KHz    
12
  // 0x64, Match mit 999,9Hz (1ms)                      
13
    T0MR0 = 0x0064;        // Timer0 Match Register                                     
14
    // Match Control Register                                              
15
    T0MCR = 0x00000003;                                                                     
16
    T0EMR &= 0x00000000;    // External Match Register (Status lesen und Kontrolle)   
17
  VICVectAddr0 = (unsigned long)tc0;          // set interrupt vector in 0 ISR=tc0
18
  VICVectCntl0 = 0x20 | 4;                    // use it for Timer 0 Interrupt
19
  VICIntEnable = 0x00000010;                  // Enable Timer0 Interrupt   
20
  return 0;
21
}
22
23
24
unsigned int timer0_SEC_counter = 0;
25
unsigned int timer0_MS_counter = 0;
26
27
void tc0 (void) __irq
28
{  
29
  timer0_MS_counter++;
30
  if ( timer0_MS_counter == 1000 )
31
  {
32
      timer0_SEC_counter++;      //Increment Timer each 5 ms
33
      timer0_MS_counter = 0;          
34
  }
35
  T0IR = 1;                                 // Clear interrupt flag
36
  VICVectAddr = 0; 
37
}

von (prx) A. K. (prx)


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

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


Angehängte Dateien:

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
1
#define PCLK           55296000     // PCLK (Perepherie Clock) = CCLK (CPU Clock)
2
#define PRESCALER_REGISTER    553
3
#define MATCH_REGISTER       100  
4
5
int timer0_init(void)
6
{                                
7
    T0IR = 0x000000FF;                            
8
    T0TCR = 0x00000001;                                                 
9
    T0CTCR = 0x00000000; 
10
  T0PR = PRESCALER_REGISTER;
11
  T0MR0 = MATCH_REGISTER;                                              
12
    T0MCR = 0x00000003;                                                                     
13
    T0EMR &= 0x00000000;    // External Match Register (Status lesen und Kontrolle)   
14
  VICVectAddr0 = (unsigned long)tc0;          // set interrupt vector in 0 ISR=tc0
15
  VICVectCntl0 = 0x20 | 4;                    // use it for Timer 0 Interrupt
16
  VICIntEnable = 0x00000010;                  // Enable Timer0 Interrupt   
17
  return 0;
18
}   
19
unsigned int timer0_SEC_counter = 0;
20
unsigned int timer0_MS_counter = 0;
21
22
23
void tc0 (void) __irq
24
{  
25
  timer0_MS_counter++;
26
  T0IR = 1;                                 // Clear interrupt flag
27
  VICVectAddr = 0; 
28
}

von (prx) A. K. (prx)


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.

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
Noch kein Account? Hier anmelden.