Forum: Mikrocontroller und Digitale Elektronik 8051: Timer im Capture Modus verwenden


von Chris H. (Gast)


Lesenswert?

Verehrtes µC Forum,

ich verwende ein Mikrocontroller Board von SiLabs: den 8051F580
Damit und mit einer Reflexlichtschranke möchte ich die Drehzahl eines 
Motors messen. Das testen mit einem Oszi hat auch funktioniert und an 
Hand der Frequenz konnte ich die Drehzahl per Hand errechnen.

Für den weiteren Verlauf ist wichtig zu sagen, dass der Motor mit einem 
Bit-Muster beklebt wurde, um mit der Software die Drehzahl berechnen zu 
können (4 Flanken = 1 Umdrehung). Bei einer Frequenz von 500 Hz komme 
ich auf eine Drehzahl von 7500 1/min.

Den Timer 4 habe ich so konfiguriert (im Capture Modus), dass bei jeder 
High-to-Low Transition ein Interrupt ausgelöst wird. Bei jedem Interrupt 
wird in der ISR der Null-Wert und der Wert nach 4 Interrupts des Timers 
in jeweils eine Variable geschrieben. Mit der Differenz beider Variablen 
komme ich an die Zeit zwischen zwei Flanken und somit an die Drehzahl 
(Theoretisch).

Die Drehzahl soll später mit dem UART an einen seriellen Monitor 
gesendet werden. Zum testen hab ich zunächst geschaut ob die ISR 
überhaupt aufgerufen wird. Was aber nicht der Fall ist.

Hier ist der Programmabschnitt für die Initialisierung des Timers:
1
#include "compiler_defs.h"
2
#include <C8051F580.h>
3
4
int counterR_motor1 = 0;
5
int RPM1;
6
7
static unsigned int first_capture_motor1, second_capture_motor1;
8
int capture_periode_motor1;
9
10
11
void Timer4_Init (void){
12
 TMR4H = 0x00;  // 65,535 ms Timer Overflow (65535/(24 MHz/ 2 /12)
13
 TMR4L = 0x00;
14
15
 TMR4CN = 0x09;                   // T4EX enabled: Überwachung des Ports fuer die High-to-Low Transitionen
16
                                          // Timer4 is in Capture mode
17
 TMR4CF = 0x00;                    // Timer4 uses SYSCLK / 12
18
                                  // Increment only
19
 EIE2 = 0x40;                      // Enable Timer 4 interrupts
20
 TR4 = 1;                    // Timer 4 run enabled
21
}

Und Hier der Programmabschnitt der ISR:
1
INTERRUPT (TIMER4_ISR, INTERRUPT_TIMER4){
2
// Wenn eine High to Low Transition registriert wird
3
 if(EXF4 == 1){
4
  EXF4 = 0;// Timer 4 Interrupt für External Flag muss Software-Seitig reset gesetzt werden
5
6
  // Testweise ein '$' übertragen um zu schauen ob die ISR überhaupt getriggert wird                                  
7
  SBUF0 = '$';              
8
  while (TI0==0);
9
  TI0 = 0;
10
  while (THRE0==0);
11
  
12
  // Aufnahme des Nullpunktes
13
  if(counterR_motor1 == 0){
14
   first_capture_motor1 = TMR4CAPH <<8 | TMR4CAPL; // Capture Register in Variable schreiben
15
  }
16
    
17
  counterR_motor1 ++; // Counter starten wenn der Nullpunkt aufgenommen wurde
18
19
  // Wenn 4 Takte erreicht wurden, dann die Timer Zeit festhalten    
20
  if(counterR_motor1 == 4){
21
   second_capture_motor1 = TMR4CAPH <<8 | TMR4CAPL;
22
   capture_periode_motor1 = second_capture_motor1 - first_capture_motor1;
23
 
24
   // RPM1-Wert berechnen
25
   RPM1 = 60000000/(4 * capture_periode_motor1);  // RPM Motor1
26
      
27
   // Timer Reset und wieder auf null
28
   EIE2 = 0x40;
29
   TR4 = 0;
30
   TMR4H = 0x00;
31
   TMR4L = 0x00;
32
  }
33
 }
34
}

Ich schätze das Problem liegt an der Initialisierung des Timers. Die 
gezeigten Programmabschnitte sind nur ein Teil meines Codes. Wenn ich
1
Timer4_Init();
in meinem Programm auskommentiere, dann funktioniert der Rest des 
Programms ohne Probleme, sobald aber diese Funktion zugeschaltet wird, 
hängt es in der Initialisierung des Timers. Ob die Berechnung der 
Drehzahl welche in der ISR getätigt wird auch stimmt, kann ich im Moment 
noch nicht sagen, da ich zu diesem Punkt nicht komme.

Ich hoffe ich habe mich einigermaßen deutlich ausgedrückt, ansonsten bin 
ich natürlich offen für Anmerkungen/Fragen und entschuldige mich für 
eventuelle Unklarheiten =)

Danke und Grüße

von Lothar (Gast)


Lesenswert?

Chris H. schrieb:
> hängt es in der Initialisierung des Timers

Bist Du für das Beschreiben der TMR4 Register in der richtigen SFR Page? 
Ist der Watchdog aus? Ist der globale Interrupt enabled?

http://community.silabs.com/t5/8-bit-MCU/How-to-make-a-UART-bridge-with-F580/m-p/58071/highlight/true#M23885

Ansonsten, da ich keinen 8051F580 da habe zum Testen, am besten hier 
fragen, da kommt recht schnell Antwort:

http://community.silabs.com/t5/8-bit-MCU/bd-p/1

Oder falls möglich TMR0 dafür verwenden, da muss deutlich weniger 
konfiguriert werden.

von Chris H. (Gast)


Lesenswert?

Lothar schrieb:
> Bist Du für das Beschreiben der TMR4 Register in der richtigen SFR Page?
> Ist der Watchdog aus? Ist der globale Interrupt enabled?
>http://community.silabs.com/t5/8-bit-MCU/How-to-make-a-UART-bridge-with-F580/m-p/58071/highlight/true#M23885

- Das mit der SFR Page hatte ich hier vergessen einzufügen, in meinem 
Programm stehen sie aber wie folgt:
1
U8 SFRPAGE_save = SFRPAGE;          // Save Current SFR page
2
SFRPAGE = ACTIVE2_PAGE;             // Set SFR Page
3
// ...
4
SFRPAGE = SFRPAGE_save;             // Restore SFR Page
Die sind auch so in einem Bespiel mit dem TMR4 im Capture Modus 
beschrieben. Das habe ich so übernommen. Mit dem Configuration Wizard 2 
kann man sich das ganze ja auch ansehen und vergleichen. Den TMR4 habe 
ich von "Hand" geschrieben, weil ich nicht will, dass die gesamte 
Peripherie zum selben Zeitpunkt initialisiert wird.

- Globale Interrupts sind enabled

- Watchdog bei TMR4? Für die Generierung der PWM für die Motoren habe 
ich den PCA0 im Gebrauch und da ist der Watchdog aus, aber das hängt ja 
nicht zusammen, oder?

> Ansonsten, da ich keinen 8051F580 da habe zum Testen, am besten hier
> fragen, da kommt recht schnell Antwort:
> http://community.silabs.com/t5/8-bit-MCU/bd-p/1
  Danke werde ich machen

> Oder falls möglich TMR0 dafür verwenden, da muss deutlich weniger
> konfiguriert werden.
TMR0 habe ich schon für einen anderen Zweck verwendet. Könnte ich den 
hier trotzdem ebenfalls verwenden? Würde mir einiges vereinfachen.

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.