PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : RC5 mit Timer kombinieren funktioniert nicht



Enrico3
01.01.2005, 18:09
Hallo,

kann mir jemand erklären warum der folgende Code funktioniert:



$regfile = "m8def.dat"
$crystal = 3686400
$baud = 9600
$lib "mcsbyte.lbx"
Config Rc5 = Pinc.5

Enable Interrupts

Dim Zaehler As Byte
Dim Address As Byte , Command As Byte

Dim I As Byte
Dim Led1 As Byte
Dim Led2 As Byte
Dim Led3 As Byte

Dim D1 As Byte
Dim D2 As Byte
Dim D3 As Byte
Dim D4 As Byte
Dim D5 As Byte
Dim D6 As Byte
Dim D2_1 As Byte
Dim D4_1 As Byte
Dim D6_1 As Byte

Zaehler = 0

Do
Getrc5(address , Command)

If Command = 16 Then
Zaehler = Zaehler + 1
Elseif Command = 144 Then
Zaehler = Zaehler + 1
Elseif Command = 17 Then
Zaehler = Zaehler - 1
Elseif Command = 145 Then
Zaehler = Zaehler - 1
End If


Print Zaehler ; " " ; Led1 ; " " ; Led2 ; " " ; Led3


D1 = Zaehler 'aktueller Zählwert
D2_1 = Zaehler - 40 '40 subtrahieren, weil in 6er-Schritten bis 240
D2 = Not D2_1 'Wert invertieren -> LED wird dunkler
D3 = Zaehler - 80
D4_1 = Zaehler - 120
D4 = Not D4_1
D5 = Zaehler - 160
D6_1 = Zaehler - 200
D6 = Not D6_1

If Zaehler <= 40 Then
Led1 = 240
Led2 = D1 * 6
Led3 = 0
Else
If Zaehler <= 80 Then
Led1 = D2 * 6
Led2 = 240
Led3 = 0
Else
If Zaehler <= 120 Then
Led1 = 0
Led2 = 240
Led3 = D3 * 6
Else
If Zaehler <= 160 Then
Led1 = 0
Led2 = D4 * 6
Led3 = 240
Else
If Zaehler <= 200 Then
Led1 = D5 * 6
Led2 = 0
Led3 = 240
Else
If Zaehler <= 240 Then
Led1 = 240
Led2 = 0
Led3 = D6 * 6
Else
If Zaehler > 240 Then 'Restwert von 15 (255-240) "abschneiden"
Led1 = 240
Led2 = 0
Led3 = 0 'LED bleibt dunkel
End If
End If
End If
End If
End If
End If
End If
Loop

End



dieser hier nach Einbau eines Timers aber nicht mehr:



$regfile = "m8def.dat"
$crystal = 3686400
$lib "mcsbyte.lbx"
Config Rc5 = Pinc.5
$baud = 9600

Ddrd = &B11111111
Ddrb = &B11111111


Config Timer0 = Timer , Prescale = 8
On Timer0 Timer_irq
Enable Timer0
Enable Interrupts

Dim Zaehler As Byte
Dim Address As Byte , Command As Byte

Dim I As Byte
Dim Led1 As Byte
Dim Led2 As Byte
Dim Led3 As Byte

Dim D1 As Byte
Dim D2 As Byte
Dim D3 As Byte
Dim D4 As Byte
Dim D5 As Byte
Dim D6 As Byte
Dim D2_1 As Byte
Dim D4_1 As Byte
Dim D6_1 As Byte

Zaehler = 0

Do
'Hauptschleife
Getrc5(address , Command)

If Command = 16 Then
Zaehler = Zaehler + 1
Elseif Command = 144 Then
Zaehler = Zaehler + 1
Elseif Command = 17 Then
Zaehler = Zaehler - 1
Elseif Command = 145 Then
Zaehler = Zaehler - 1
End If


Print Zaehler ; " " ; Led1 ; " " ; Led2 ; " " ; Led3


D1 = Zaehler 'aktueller Zählwert
D2_1 = Zaehler - 40 '40 subtrahieren, weil in 6er-Schritten bis 240
D2 = Not D2_1 'Wert invertieren -> LED wird dunkler
D3 = Zaehler - 80
D4_1 = Zaehler - 120
D4 = Not D4_1
D5 = Zaehler - 160
D6_1 = Zaehler - 200
D6 = Not D6_1

If Zaehler <= 40 Then
Led1 = 240
Led2 = D1 * 6
Led3 = 0
Else
If Zaehler <= 80 Then
Led1 = D2 * 6
Led2 = 240
Led3 = 0
Else
If Zaehler <= 120 Then
Led1 = 0
Led2 = 240
Led3 = D3 * 6
Else
If Zaehler <= 160 Then
Led1 = 0
Led2 = D4 * 6
Led3 = 240
Else
If Zaehler <= 200 Then
Led1 = D5 * 6
Led2 = 0
Led3 = 240
Else
If Zaehler <= 240 Then
Led1 = 240
Led2 = 0
Led3 = D6 * 6
Else
If Zaehler > 240 Then 'Restwert von 15 (255-240) "abschneiden"
Led1 = 240
Led2 = 0
Led3 = 0 'LED bleibt dunkel
End If
End If
End If
End If
End If
End If
End If

Loop

Timer_irq: 'Timer-Interrupt
Timer0 = 237
I = I + 1

If I = 240 Then
I = 0
End If

If I >= Led1 Then
Portd.0 = 0
Portd.1 = 0
Portd.2 = 0
Portd.3 = 0
Portd.4 = 0
Portd.5 = 0
End If
If I < Led1 Then
Portd.0 = 1
Portd.1 = 1
Portd.2 = 1
Portd.3 = 1
Portd.4 = 1
Portd.5 = 1
End If

If I >= Led2 Then
Portd.6 = 0
Portd.7 = 0
Portb.0 = 0
Portb.1 = 0
Portb.2 = 0
Portb.3 = 0
End If
If I < Led2 Then
Portd.6 = 1
Portd.7 = 1
Portb.0 = 1
Portb.1 = 1
Portb.2 = 1
Portb.3 = 1
End If

If I >= Led3 Then
Portb.4 = 0
Portb.5 = 0
Portc.0 = 0
Portc.1 = 0
Portc.2 = 0
Portc.3 = 0
End If
If I < Led3 Then
Portb.4 = 1
Portb.5 = 1
Portc.0 = 1
Portc.1 = 1
Portc.2 = 1
Portc.3 = 1
End If

Return
End


Mir kommt es momentan vor allen auf die Print-Zeile an. Bei der ersten Code-Variante werden mir im Terminalprogramm permanent die Zählerwerte und die Berechneten Werte (LED) angezeigt.
Ber der zweiten Code-Variante wird mir nur ab und zu mal eine "0" angezeigt.
Woran kann das liegen, ich habe doch eigentlich nur einen Timer eingebaut???

Grüße und Danke
Enrico

01.01.2005, 18:48
Hi,
Vorsicht: Prescale = 8 und preload timer0 = 237
ist recht flott.
Kann sein, der Bursche macht ausser Interrupts überhaupt nix oder selten. mfg PicNick

Enrico3
01.01.2005, 19:10
Danke für deine Antwort.
Aber ich glaube nicht, dass es zu schnell geht. Zur Zeit versuche ich ja mit dem Code ein Infarot-Signal zum Zählen zu benutzen. Der Zähler geht bis 255. Vorher habe ich das ganze mit einem einfachen Potentiometer und A/D-Wandler ausprobiert. Dabei hat es problemlos funktioniert.

Ist es nicht so, dass die Hauptschleife unabhängig vom Timerinteruppt abläuft?
Was könnte ich denn im Programm ändern?

Grüße und danke
Enrico

PicNick
02.01.2005, 09:17
Hi, die Sache is so: Die Hauptschleife nudelt zwar vor sich hin, aber jeder Interrupt stoppt sie, und die Interruptroutine (timer_irq) läuft ab, dann geht's weiter.
Kommt nun die IRpt Routine zu oft dran, kommt die Hauptschleife einfach nicht voran.
Preload 237 heißt, er zÄhlt von dort bis 255, also 18 mal, das is nicht viel:
ein paar zerquetschte microSekunden, da schafft er grad ein paar Befehle

Man kann das alles auch berechnen, aber setz doch einfach zum Testen den Prescaler von 8 auf 1024 und den Preload von 237 auf 1, egal ob das Sinn macht. ABER:
Liegt das Problem darin, kommt der Print wieder regelmäßig und du weißt, wo der Hund liegt.
Dann kannst du dich ja wieder hinarbeiten zu schnelleren Interrupts
mfg robert

Enrico3
02.01.2005, 09:30
Hallo,

danke erst mal für deine Hilfe.
Leider funktioniert das aber nicht so wie gedacht.
Wenn ich die Einstellungen so vor nehme wie du gesagt hast, kommt der Print-Befehl nur wenn ich eine Taste auf der Fernbedienung drücke -> allerding kommt im Terminalprogramm auch nicht das was ich erwartet habe.

Wenn ich allerdings den folgenden Code:

Getrc5(address , Command)
If Command = 16 Then
Zaehler = Zaehler + 1
Elseif Command = 144 Then
Zaehler = Zaehler + 1
Elseif Command = 17 Then
Zaehler = Zaehler - 1
Elseif Command = 145 Then
Zaehler = Zaehler - 1
Else
Zaehler = Zaehler
End If


durch den hier ersetzte:

Incr Zaehler

kommt das was soll auch im Terminalprogramm. Es läuft zwar sehr langsam ab, aber es funktioniert. Leider kann ich so meine Fernbedienung nicht benutzen.
Der Print-Befehl soll am Ende sowieso wieder aus dem Programm verschwinden, der ist jetzt nur zum testen gedacht. Wenn ich ihn rausnehme, läuft es mit Incr Zaehler genau so ab wie ich mir das vorstelle.
Leider fällt mir momentan dazu keine Lösung ein... ;-(

Grüße und danke
Enrico

RCO
02.01.2005, 13:37
Also bei einem Prescaler von 8 und einem 8 Bit Timer mit 3686400 Hz löst dein Timer immhin 25600 mal in der Sekunde einen Interrupt aus, wenn ich das richtig sehe. Das heißt alle: 39,0625 Mikrosekunden!

"Incr Zaehler" heißt übrigens nur, dass Zähler um eins erhöht wird!

MFG Moritz

Enrico3
02.01.2005, 13:51
Ja, das ist schon klar, nur warum funktioniert es mit incr Zaehler problemlos und sobald ich stattdessen Getrc5(address , Command) schreibe nicht mehr.
Mir scheint es so, als ob der µC dann stehenbleibt.
Wie könnte ich es denn jetzt anstellen, dass ständig abgefragt wird ob ein neuer Befehl per Infarot reingekommen ist und mit diesem Befehl auch noch gearbeitet werden kann? Gleichzeitig muss aber auch noch der Timer ohne "ruckeln" ablaufen.

Selbst wenn ich den Timer sehr langsam ablaufen lasse funktioniert es nicht.

Grüße und danke
Enrico

uwe2
02.01.2005, 14:00
Hallo Enrico,
das funktioniert deshalb nicht, weil der Befehl GetRC5 intern den Timer0 verwendet, d.h. Du kannst ihn in Deinem Programm nicht verwenden und müßtest auf Timer 1 oder 2 ausweichen.

Gruß
Uwe

PicNick
02.01.2005, 14:02
Na ja, der GETRC5 wartet natürlich, bis was da is, vorher geht nix weiter.
INCR flutscht durch, klaro.
Zwei sachen passieren grad: Frau ruft zum Essen und
ich seh grad im HELP, daß GETRC5 selber den TIMER0 verwendet, da wirst du wohl besser auf einen anderen wechseln müssen.
Ich schau dann nach, ob's irgendeinen Interrrupt oder ischar für den RC5 gibt. mfg robert

Enrico3
02.01.2005, 19:23
danke für den Tip mit dem Timer0, ich werde das am Wochenende mal ausprobieren - momentan geht es leider nicht...
melde mich wieder, wenn ich soweit bin...

Grüße und danke
Enrico

Enrico3
07.01.2005, 18:00
Hallo,

also, ich habe das ganze jetzt gerade mal mit Timer2 ausprobiert, leider mit dem gleichen Ergebnis wie wenn ich Timer0 verwenden würde.
Hat noch jemand eine Idee dazu - wäre echt dankbar.

Grüße
Enrico