Code:
'Hier mal eine Routine für die Eigenverarbeitung von RC5 Signalen.
'Ich hatte immer wieder Probleme mit der langen Wartezeit von dem Standard Getrc5 gehabt.
'Daher habe ich mir eine Routine geschrieben, die keine Wartezeiten und auch kein Polling macht,
'sondern einen externen Interrupt benutzt
'
'Der Timer wird nicht ausschliesslich für den RC5 benutzt, läuft also immer mit 8kHz durch.
'Es wird in Impuls_laenge nur die Anzahl der overflows festgehalten.
'Außerdem kann man festlegen, ob mehrfach Empfang ohne loslassen erlaubt ist (wiederholen_erlaubt=1)
'oder nicht (wiederholen_erlaubt=0).
'Eingehende Impulse werden nach Länge überprüft und dann in die Variable Temp_daten geschoben,
'also 14-bit bei einem korrekten Befehl.
'Wenn man sich die möglichen Zeiten zwischen zwei steigenden Flanken ansieht,
'stellt man fest, dass es drei verschiedenen geben kann:
'kurze Impulselänge (1,778ms ~ 14 Überläufe) ->
' gleicher Wert empfangen wie beim letzten Impuls, also vorher 0 jetzt 0 oder vorher 1 und jetzt 1
'lange Impulselänge (2,677ms ~ 21 Überläufe) ->
' vorher war es eine 0, jetzt kommt eine 1 und eine 0 (also 2 bit zusammen)
'mittl Impulselänge (3,556ms ~ 28 Überläufe) ->
' entweder war es vorher eine 0, dann jetzt eine 1 oder vorher eine 1 dann jetzt eine 1 und eine 0
'Wenn dann 14 bit zusammen sind, extrahiere ich daraus die Adresse und den Befehl und überprüfe, ob die Sinn machen.
'Dann wird der Befehl ausgegeben, falls er ungleich dem letzten Befehl ist bzw. wiederholen erlaubt ist.
$crystal = 16000000
$regfile = "m128def.dat"
Dim Impuls_laenge As Word , Bit_nummer As Byte , Temp_daten As Word
Dim Befehl As Byte , Adresse As Byte , Empfangs_fehler As Byte , Wiederholen_erlaubt As Byte
Dim Letzte_adresse As Byte , Letzter_befehl As Byte , Startwert As Byte
Dim Interrupt_vektor As Byte
Config Timer0 = Timer , Prescale = 8
On Ovf0 Tim0_isr
Enable Timer0
Startwert = 160 '6144000/8/(256-160)=8000 Überläufe pro Sekunde,
Timer0 = Startwert 'also alle 0,125ms, Impulslänge bei RC5 1,778ms, also ca. 14
Config Int0 = Rising 'externer interrupt, dauernd high, falls Signal dann low
'falls dauernd low, dann auf falling ändern und PORTD.2=0 setzen
On Int0 Get_rc5_isr
Enable Int0
Ddrd.2 = 0 'ausgang des RC5-empfängers
Portd.2 = 1 'Pullup ein, auf Pulldown ändern, wenn dauernd low kommt
Wiederholen_erlaubt = 0 'auf 1 setzen, wenn wiederholen erlaubt sein soll, sonst 0
$baud1 = 115200
Open "COM2:" For Binary As #1
Enable Interrupts
Do
If Interrupt_vektor.7 = 1 Then
'Print #1 , Impuls_laenge 'Vorsicht, wenn das Print aktiv ist, können sich bei geringer
'Übertragungsrate die Zeiten verändern
Select Case Impuls_laenge
Case Is > 1500: '-> startimpuls, nach empgfangsfehler muss immer erst ein solcher kommen.
Bit_nummer = 1
Temp_daten = 1
Empfangs_fehler = 0
Case 26 To 29: '-> große Länge: vorher 0, jetzt 1 + 0
If Empfangs_fehler = 0 Then
Shift Temp_daten , Left 'hinzufügen einer 0
Incr Temp_daten 'umwandeln in 1
Shift Temp_daten , Left 'hinzufügen einer 0
Incr Bit_nummer 'bei Kombination '10' fehlt ein Impuls
End If
Case 19 To 22: '-> mittlere Länge: vorher 1, jetzt 1 + 0 oder vorher 0 jetzt 1
If Empfangs_fehler = 0 Then
Shift Temp_daten , Left 'hinzufügen einer 0
Incr Temp_daten 'umwandeln in 1
If Temp_daten.1 = 1 Then 'vorher gab es eine 1
Shift Temp_daten , Left 'hinzufügen einer 0
Incr Bit_nummer 'bei Kombination '10' fehlt ein Impuls
End If
End If
Case 12 To 15: '-> kleine Länge --> gleicher Wert wie vorher
If Empfangs_fehler = 0 Then
Shift Temp_daten , Left 'hinzufügen einer 0
If Temp_daten.1 = 1 Then 'vorher gab es eine 1
Incr Temp_daten 'umwandeln in 1
End If
End If
Case Is > 400: 'aber kleiner 1500, dann war's eine Pause zwischen Befehlen beim Dauerdrücken
If Empfangs_fehler = 1 Or Wiederholen_erlaubt = 1 Then
Bit_nummer = 1
Temp_daten = 1
Empfangs_fehler = 0
End If
Case Else
Empfangs_fehler = 1
End Select
If Bit_nummer = 14 Then
Befehl = Temp_daten And &B00111111
Shift Temp_daten , Right , 6
Adresse = Temp_daten
If Befehl < 64 And Adresse > 191 Then '-C6 wird nicht benutzt, also immer 1
If Wiederholen_erlaubt = 1 Or Befehl <> Letzter_befehl Or Adresse <> Letzte_adresse Then
Letzter_befehl = Befehl
Letzte_adresse = Adresse
Print #1 , "Befehl=" ; Befehl
End If
End If
End If
Impuls_laenge = 0
Interrupt_vektor.7 = 0
End If
Loop
End
Tim0_isr:
Timer0 = Startwert
Incr Impuls_laenge
If Impuls_laenge > 65000 Then 'Überlauf von Impuls_laenge verhindern (nach 65535 kommt 0),
'damit Start (Impuls_laenge > 500) sicher erkannt wird
Impuls_laenge = 1501
End If
Return
Get_rc5_isr: 'RC5 Impuls erkannt
'Print #1 , "Received Get_rc5 Interrupt" 'wenn gar nichts geht, dies mal aktivieren
Incr Bit_nummer
Interrupt_vektor.7 = 1
Return
Schau mal, ob du damit zurecht kommst.
Lesezeichen