Forum: Mikrocontroller und Digitale Elektronik P89LPC9351- Zählerstand des Timer 2 zurücksetzen


von Djon M. (djon)


Lesenswert?

Hallo!

Ich habe folgendes Problem bei der Programmierung des P89LPC9351 
(8051-Derivat) von NXP. Ich verwende die Capture/Compare-Unit (CCU). Der 
Timer 2 ist als freilaufender Timer (Basic Timer) konfiguriert und auf 
das Hochzählen eingestellt. Ich möchte, dass bei jedem Capture-Interrupt 
der aktuelle Zählstand des Timer 2 zurückgesetzt wird (0x00). Wenn ich 
das Programm im Simulator ausführe (µVision4 von Keil), dann wird der 
Zählstand brav zurückgesetzt, aber auf dem Mikrocontroller selbst ist es 
leider nicht der Fall und der Zähler läuft über.
In dem Datenblatt habe ich gelesen, dass man zuerst das Register TH2 und 
anschliessend TL2 setzen sollte, aber es hat auch nicht geholfen. Muss 
ich vielleicht bei der Rücksetzung noch was beachten?

Vielen Dank im Voraus!

Mfg Djon

von Jobst M. (jobstens-de)


Lesenswert?

code?


Gruß

Jobst

von Djon M. (djon)


Lesenswert?

Hallo!

Hier ist der Code. Ich hoffe, es wird bei der Lösungssuche helfen :-)

Mfg Djon
1
#include "reg9351.h"
2
3
static bit LED1 = 0;
4
static bit LED2 = 0;
5
6
#define SENSORA ((unsigned char)0)
7
#define SENSORB ((unsigned char)7)
8
9
main()
10
{
11
  // Die Led-Portpins auf Push/Pull Modus setzen
12
  P2M1 &= ~(0x30);
13
  P2M2 |= (0x30);
14
15
  // Die beiden Leds ausschalten
16
  P2 |= (1<<4);
17
  P2 |= (1<<5);
18
19
  // Der Timer2 muss so schnell zählen, dass er nach 500ms ueberlauft
20
  // Prescaler auf 0x3C setzen
21
  TPCR2L = 0x3C;
22
23
  // Den Timer als einen freilaufenden Timer deklarieren
24
  TMOD21 = 0;
25
  TMOD20 = 1;
26
27
28
  // Die Portpins P2.0 und P2.7 muessen als Eingaenge (Input Only) definiert werden
29
  P2M1 |= (1<<SENSORB);
30
  P2M2 &= ~(1<<SENSORB);
31
32
  P2M1 |= (1<<SENSORA);
33
  P2M2 &= ~(1<<SENSORA);
34
35
  //! NoDelay
36
  CCCRA &= (0x1F);
37
  CCCRB &= (0x1F);
38
39
  // Der Eingang soll auf steigende Flanke getriggert werden
40
  CCCRA |= (1<<4);
41
  CCCRB |= (1<<4);
42
43
  //! Noise Filter
44
  CCCRA |= (1<<3);
45
  CCCRB |= (1<<3);
46
47
  // Timer Input Capture A Enable bit setzen
48
  TICR2 |= (1<<0);
49
50
  // Timer Input Capture B Enable bit setzen
51
  TICR2 |= (1<<1);
52
53
  // Das Interrupt freigeben
54
  ECCU = 1;
55
56
  // Die Zaehlrichtung des Timers setzen
57
  // TDIR2 = 0: Count up
58
  // TDIR2 = 1: Count down
59
  TDIR2 = 0;
60
61
  // Der Watchdog-Zähler wird auf 1 Sek. gesetzt
62
  WDL = 0x62;
63
64
  // Interrupts global freigeben
65
  EA = 1;
66
67
68
  // Hauptschleife
69
  while(1)
70
  {
71
    //! Überprüfen, ob der Timer2 übergelaufen ist
72
    if((TIFR2 & 0x80) == 0x80)
73
    {
74
      //! Timer2-Überlaufflag löschen
75
      TIFR2 &= ~(0x80);
76
77
      //! LED1 toggeln
78
      SS = LED1;
79
      LED1 = !(LED1);
80
    }
81
  }
82
}
83
84
85
void wheelSensorInterrupt() interrupt 11
86
{
87
  // Interrupts sperren
88
  EA = 0;
89
90
  // Ueberpruefen, welcher Sensor aktiviert wurde
91
  if ((TIFR2 & 0x01) == 0x01)
92
  {
93
    //! LED2 toggeln
94
    SPICLK = LED2;
95
    LED2 = !(LED2);
96
97
    // Interruptflag clearen
98
    TIFR2 &= ~(0x01);
99
  }
100
  else if ((TIFR2 & 0x02) == 0x02)
101
  {
102
    // Interruptflag clearen
103
    TIFR2 &= ~(0x02);
104
  }
105
106
  //! Zählerstand zurücksetzen
107
  TH2 = 0x00;
108
  TL2 = 0x00;
109
110
  // Erster Schritt der Sequenz
111
  WFEED1 = 0xA5;
112
113
  // Zweiter Schritt der Sequenz
114
  WFEED2 = 0x5A;
115
116
  // Interrupts freigeben
117
  EA = 1;
118
}

von R. W. (quakeman)


Lesenswert?

Bist du sicher, dass auch immer innerhalb von 1 Sekunde ein CCU 
Interrupt erzeugt wird?
Andernfalls läuft dein Watchdog ja über und versaut dir deinen gesamten 
Ablauf. Ich würde an deiner Stelle erst mal simpel anfangen und alles 
Überflüssige rauswerfen. Dazu gehört vor allem, den Watchdog zu 
deaktivieren bis alles läuft.

Und nachdem du scheinbar kein SPI benutzt, solltest du der 
Verständlichkeit halber lieber nicht die Bezeichnungen SS und SPICLK für 
die Pins benutzen.
Ebenfalls ist es zu empfehlen den Timer2 vor dem zurücksetzen zu stoppen 
und danach wieder zu starten. Denn ohne das kannst du im Worst Case ein 
Problem bekommen. Wenn du z.B. TH2 = 0 setzt und dabei TL2 = 0xFF war 
und du in der nächsten Zeile dann TL2 = 0 setzt, ist aber eventuell 
dazwischen schon ein Überlauf auf TH2 = 1 passiert.

Du kannst deine Konstanten auch direkt mit
#define SENSORA 0
#define SENSORB 7
definieren, da das (unsigned char) keine Auswirkung hat. Der Compiler 
benutzt automatisch die richtigen Typen je nach Verwendung.

Ciao,
     Rainer

von Jobst M. (jobstens-de)


Lesenswert?

Fox Mulder schrieb:
> Ebenfalls ist es zu empfehlen den Timer2 vor dem zurücksetzen zu stoppen
> und danach wieder zu starten. Denn ohne das kannst du im Worst Case ein
> Problem bekommen. Wenn du z.B. TH2 = 0 setzt und dabei TL2 = 0xFF war
> und du in der nächsten Zeile dann TL2 = 0 setzt, ist aber eventuell
> dazwischen schon ein Überlauf auf TH2 = 1 passiert.

Nein, das ist nicht nötig, aber zuerst sollte TL2 auf 0 gesetzt werden. 
Dann erst TH2. In der Zwischenzeit kommt TL2 nämlich nicht weit genug.


Gruß

Jobst

von R. W. (quakeman)


Lesenswert?

Jobst M. schrieb:
> Nein, das ist nicht nötig, aber zuerst sollte TL2 auf 0 gesetzt werden.
> Dann erst TH2. In der Zwischenzeit kommt TL2 nämlich nicht weit genug.

Es ist aber auch dann nur nicht nötig, wenn man deine Reihenfolge 
einhält. Bei der von ihm benutzen Reihenfolge macht es schon Sinn. ;)

Ciao,
     Rainer

von Djon M. (djon)


Lesenswert?

Hallo!

Ich bin mir ziemlich sicher, dass innerhalb einer Sekunde mehrere 
CCU-Interrupts erzeugt werden. Die beiden Eingänge hängen an einem 
Funktionsgenerator und so kann ich nach Belieben CCU-Interrupts 
erzeugen.
Ich habe die Variante mit dem Anhalten des Timers bereits ausprobiert, 
doch leider ohne Erfolg.
Ich habe jetzt die Sache mit Hilfe des Timer 1 gelöst. Dieser Timer 
lässt sich problemlos zurücksetzen.

Mfg Djon

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.