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
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 | }
|
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
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.