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
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