PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : RC5 Abfrage funktioniert per Polling, aber nicht per INT0



luvat
16.03.2008, 16:58
Servus.

Ich stehe hier vor einem Phänomen, welches ich mir nicht ganz erklären kann.

Ich habe lange rumgedockert und gesucht um nun endlich eine RC5 IR Fernbedieung auswerten zu können.

Als Controllerboard verwende ich das RN-Control.
Programmiere mit BASCOM.
IR Fernbedienung: Phillips
Empfänger: Keine Ahnung. Hab ich aus einem Technisat Reciever ausgebaut.


Der funktionierende Polling basierte Code:



$regfile = "m32def.dat"
$crystal = 16000000
$baud = 9600

Config Rc5 = Pina.1

Enable Interrupts

Dim Address As Byte , Command As Byte

Print "Waiting for RC5..."

Sound Portd.7 , 400 , 450 'BEEP
Sound Portd.7 , 400 , 250 'BEEP
Sound Portd.7 , 400 , 450 'BEEP

Do
Getrc5(address , Command)
Command = Command And &B01111111
If Address < 255 Then
Print Address ; " " ; Command
End If
Loop
End

Der Code funktioniert vom feinsten.
Dieser oben gezeigte Code, war eig. nur um die generelle Funktionalität zu testen. Also: Zwekc erfüllt.

Da das Polling aber überaus unschön und unpraktikabel ist, wollte ich das ganze Interrupt gesteuert umsetzen. ... Dies ist mein bisheriger Code:



$regfile = "m32def.dat"
$crystal = 16000000
$baud = 9600

$lib "mcsbyte.lbx"

Config Rc5 = Pind.3

On Int0 Int0_int
Enable Int0
Enable Interrupts

Dim Address As Byte , Command As Byte , Rc5_flag As Bit

Sound Portd.7 , 400 , 450 'BEEP
Sound Portd.7 , 400 , 250 'BEEP
Sound Portd.7 , 400 , 450 'BEEP

Do
Print "Hallo"
Waitms 1000
Loop

End

'Lesen der RC5 Codes
Int0_int: 'Interrupt Handler For Int1
Disable Int0
Address = 0
Command = 0
Getrc5(address , Command)
Command = Command And &B01111111
Print Address ; " " ; Command
Enable Int0
Return


Hier funktioniert so ziemlich garnichts. In der Mail ist ein Print eingebaut, welcher jede Sekune "Hallo" sagt.

Wenn das Programm startet funktioniert die Ausgabe durch Print auch. Sobald einmal die IR Fernbedienung betätigt wird, scheint sich alles wegzuhängen.

Es wird keine Ausgabe des Empfangs getätigt. Das Programm springt nicht mehr in die Mainschleife zurück.

Hat da wer ne Idee woran das liegen könnte?

for_ro
16.03.2008, 17:17
Hallo,
ich glaube nicht, dass das so etwas wird.
Falls du dein Signal nicht auf Pind.2 und Pind.3 liegen hast, geht es eh nicht.
Dein Int0 liegt doch wohl auf Pind.2, RC5 ist auf Pind.3 konfiguriert.
Aber auch dann wird es eher nicht gehen. Zum einen hast du nicht konfiguriert, auf welcher Flanke der Interrupt ausgelöst werden soll. Ob es da einen Default gibt, weiss ich gerade nicht.
Die GETRC5() Funktion wird regelmäßig nicht den ersten Impuls mitkriegen, da die ISR Int0_int ja erst beim Flankenwechsel aufgerufen wird.
Davon ab würde ich so einen Zeitfresser wie GETRC5 niemals in eine ISR stecken. Ich meine mich zu erinnern, dass die 150ms braucht, um zu einem Output zu kommen. Während der Zeit tut sich nichts in deinem System.

Gruß

Rolf

Dirk
16.03.2008, 18:25
Hallo luvat,

probier 'mal dies hier:

'IR-Empfänger an Pind.2 initialisieren:
Config Rc5 = Pind.2
On Int0 Rc5_receive
Enable Int0
Config Int0 = Falling
Enable Interrupts

'Hauptprogramm:
Reset Rc5_flag
Do
For I = 1 To 4
Locate I , 1
Lcd "Warte auf IR ..."
If Rc5_flag = 1 Then
Reset Rc5_flag
Gosub Rc5_display
End If
Wait 1
Next I
Cls
Loop

'RC5 auf LCD anzeigen:
Rc5_display:
If Address <> 255 Then
Command = Command And &B01111111
Cls
Locate 2 , 1
Lcd "Addr: Cmd:"
Locate 3 , 1
Lcd Address ; " "
Locate 3 , 9
Lcd Command ; " "
Wait 1
Cls
End If
Return

'RC5 einlesen:
Rc5_receive:
Disable Int0
Enable Interrupts
Getrc5(address , Command)
Set Rc5_flag
Gifr = Gifr Or &B01000000 'Clear Flag Int0
Enable Int0
Return


Gruß Dirk

for_ro
16.03.2008, 22:24
Hallo,
wenn du schon einen externen Interrupt Pin benutzt, dann würde ich die Auswertung auch direkt selber machen.
Ich bin mir sehr sicher, dass GETRC5() das erste Paket nicht richtig erkennen kann, da die erste Flanke fehlt. Ist das Paket dann nach 25ms durch, kommt eine Pause von 114ms, bevor das zweite Paket gesendet wird.
Jetzt wird der Befehl in weiteren 25ms erkannt. Der µC hat bei 16MHz in der Zwischenzeit 2.500.000 Zyklen abgespult. Bleibt man einen Moment zu lange auf der Taste sind es wieder 2.500.000 Zyklen. Und auch bei Dirks Version findet das Ganze in einer ISR statt.
Hast du in der ISR die Zeiten der Flankenwechsel in einem kleinen Array mitgeloggt, brauchst du im Hauptprogramm nur diese paar Befehle um einen gültigen RC5 Befehl zu erkennen:


If Flanken_anzahl > 15 And Flanken_anzahl < 27 And Flanken_anzahl.0 = 0 Then
If Imp_array(2) > kurz_min And Imp_array(2) < kurz_max And Imp_array(3) > kurz_min And Imp_array(3) < kurz_max Then
I = 4
Daten = 1
While I < Flanken_anzahl
Shift Daten , Left
Daten.0 = Daten.1
If Imp_array(i) > kurz_min And Imp_array(i) < kurz_max Then
Incr I
If Imp_array(i) <= kurz_min Or Imp_array(i) >= kurz_max Then
Exit While 'fehlerhafter Empfang
End If
Elseif Imp_array(i) > lang_min And Imp_array(i) < lang_max Then
Toggle Daten.0
Else
Exit While 'fehlerhafter Empfang
End If
Incr I
Wend
If I >= Flanken_anzahl Then
If Imp_array(i) > lang_min And Imp_array(i) < lang_max Then
Shift Daten , Left
End If
Temp_daten = Daten
Rc5_befehl = Temp_daten And &B00111111
Shift Temp_daten , Right , 6
Rc5_adresse = Temp_daten And &B00111111
Print "Adresse=" ; Rc5_adresse ; ", Befehl=" ; Rc5_befehl
End If
End If
End If



Und das geht bestimmt 1000 mal so schnell, denn 2500 Zyklen braucht er sicher nicht dafür.

Gruß

Rolf

stefan_Z
17.03.2008, 05:10
Hier im Forum gibts irgendwo ne selbstgebastelte RC5-Routine die super im Interrupt funktioniert. Such die mal raus, die tuts fantastisch!