Hallo,
ich bin gerade dabei mit Hilfe eines TSOP17xx und einem MEGA8 einen IR-Empfänger zu entwickeln, um mit ungenutzten Tasten meiner
zahlreichen IR-Fernbedienungen div. Geräte (z.B. Licht) ein- und auszuschalten. Leider ist der RC-Code kein RC-5, sodass ich die
BASCOM-Befehle (GETRC5) nicht verwenden kann.
Ich habe daher beschlossen analog der App-Note: "AN #120 - Sony IR receiver using the SIRCS protocol",
Quelle: http://www.mcselec.com/index.php?opt...d=84&Itemid=57 vorzugehen und den Timer-Capture-Int zu verwenden.
Prinzipiell funktioniert es so, dass ich bei jeder fallenden Flanke am ICP-Pin einen Capture-INT auslöse, und mir den aktuellen
Wert meines TIMER1 in einem Array wegspeichere. Ich kann damit zwar nicht das Bitmuster reproduzieren, da ich ja jeweils nur die Periodendauer
zwischen 2 fallenden Flanken messe, aber es ist dennoch möglich das Ergebnis für Schaltzwecke zu nutzen.
Bei 16MHz Taktfrequenz und einem PRESCALER von 1024 wird der Zähler alle 64µs um einen Wert erhöht.
Das Ergebnis des Capture-Timers - also die "gemessenen" Periodendauern zwischen den fallenden Flanken entsprechen 100% dem
Ergebnis einer Messung mit einem Speicheroszilloskop (Sensor only). Bilder sieh hier:
http://www.arcor.de/palb/einladung_a...YOMmcvNw%3D%3D
Eine Sequenz des IR-Signals (die, der Taste, die ich später nutzen möchte) sieht wie folgt aus
Werte (18 Werte) des Timer1:
200 / 17 / 50 / 50 / 50 / 33 / 50 / 50 / 50 / 66 / 50 / 34 / 66 / 50 / 50 / 34 / 66 / 34
In Millisekunden sind das:
12,8ms /1,088ms /3,2ms /3,2ms /3,2ms /2,112ms /3,2ms /3,2ms /3,2ms /4,224ms /3,2ms /2,176ms /4,224ms /3,2ms /3,2ms /2,176ms /4,224ms /2,176
Die Werte speichere ich in einem Array ab und gebe sie mir momentan für Debugzwecke gleich via serieller Schnittstelle aus.
Hier der Code:
Die sofort ausgegebenen Werte sind Gleich den Werten im Array - egal ob ich "Wcapture" direkt über einen Print-Befehl ausgebe,Code:'InputCapture mit Timer1 'INT0 mit Taste an Port D2 (nur für Debug-Zwecke) 'Hardware: TSOP17xx an ICP (PortB.0) ' TAster nach GND an INT0 (PortD.2) '---------------------------------------------------------- $regfile = "m8def.dat" $crystal = 16000000 '16 MHz-Quarz $baud = 9600 On Icp1 Oncapture 'Interrupt-Routine deklarieren On Int0 Int0_s Dim Wcapture As Word Dim Capvalues(50) As Word Dim Bytecount1 As Byte Dim Bytecount2 As Byte Dim Y As Byte Dim X As Byte Dim Z As Byte Dim Ssq1 As Bit Dim Ssq2 As Bit '---------------------------------------------------------- Bytecount1 = 1 ' Array-Index initialisieren (1) Bytecount2 = 0 Gosub Loesche_array ' Array löschen Enable Icp1 ' ICP INT einschalten Enable Int0 ' INT0 einschalten Config Timer1 = Timer , Prescale = 1024 , Capture Edge = Falling ' Timer-Cfg: 16000000/1024 (Prescaler=1024) = 64µs pro Zähler, fallende Flanke ' fallende Flanke an ICP-Pin (B0) löst Capture-Int aus Config Int0 = Falling ' fallende Flanke an INT0-Pin (D2) löst Int0 aus Enable Interrupts 'Interrupts global einschalten '---------------------------------------------------------- Main: 'Hauptschleife Goto Main '---------------------------------------------------------- Oncapture: 'Timer1-Capture-INT-Routine (wird bei jeder fallenden Falnke am ICP-Pin aufgerufen.) Timer1 = Timer1 - Capture1 'Timer neu initialisieren Wcapture = Capture1 'CAPTURE1-Register sichern If Wcapture < 501 Then ' Test auf gültige Werte (Alles was kleiner als: Zähler=501 ist gültig, Rest ignore) Capvalues(bytecount1) = Wcapture ' Wert im Array ablegen Print Capvalues(bytecount1) ; ","; Bytecount1 = Bytecount1 + 1 ' Array-Adresse +1 If Bytecount1 >= 50 Then ' Wenn Array droht überzulaufen, dann Array wieder von vorn beschreiben Bytecount1 = 1 ' Array-Index wieder auf 1 setzen End If 'Print Wcapture ; ","; End If Return '---------------------------------------------------------- Loesche_array: For X = 1 To 50 ' Gesamtes Array komplett mit Wert: 0 löschen Capvalues(x) = 0 Next Return '---------------------------------------------------------- Int0_s: X = 1 Print " Bytecount1 = " ; Bytecount1 ' Anzah der Werte im Array ausgeben (nur für Debug-Zwecke) For X = 1 To Bytecount1 ' von Byte 1 bis zum Ende der Zeichenkette (im Array) ... Print Capvalues(x) ; ","; ' .... die Werte im Array ausgeben Next Return
oder die abgespeicherten Wert "Capvalues(bytecount1)" verwende.
Nehme ich jetzt allerdings den Print-Befehl zur sofortigen Ausgabe aus der INT-Routine heraus, passen meine Zählerwerte nicht mehr !
Das Ganze sieht dann so aus:
Code:'InputCapture mit Timer1 'INT0 mit Taste an Port D2 (nur für Debug-Zwecke) 'Hardware: TSOP17xx an ICP (PortB.0) ' TAster nach GND an INT0 (PortD.2) '---------------------------------------------------------- $regfile = "m8def.dat" $crystal = 16000000 '16 MHz-Quarz $baud = 9600 On Icp1 Oncapture 'Interrupt-Routine deklarieren On Int0 Int0_s Dim Wcapture As Word Dim Capvalues(50) As Word Dim Bytecount1 As Byte Dim Bytecount2 As Byte Dim Y As Byte Dim X As Byte Dim Z As Byte Dim Ssq1 As Bit Dim Ssq2 As Bit '---------------------------------------------------------- Bytecount1 = 1 ' Array-Index initialisieren (1) Bytecount2 = 0 Gosub Loesche_array ' Array löschen Enable Icp1 ' ICP INT einschalten Enable Int0 ' INT0 einschalten Config Timer1 = Timer , Prescale = 1024 , Capture Edge = Falling ' Timer-Cfg: 16000000/1024 (Prescaler=1024) = 64µs pro Zähler, fallende Flanke ' fallende Flanke an ICP-Pin (B0) löst Capture-Int aus Config Int0 = Falling ' fallende Flanke an INT0-Pin (D2) löst Int0 aus Enable Interrupts 'Interrupts global einschalten '---------------------------------------------------------- Main: 'Hauptschleife Goto Main '---------------------------------------------------------- Oncapture: 'Timer1-Capture-INT-Routine (wird bei jeder fallenden Falnke am ICP-Pin aufgerufen.) Timer1 = Timer1 - Capture1 'Timer neu initialisieren Wcapture = Capture1 'CAPTURE1-Register sichern If Wcapture < 501 Then ' Test auf gültige Werte (Alles was kleiner als: Zähler=501 ist gültig, Rest ignore) Capvalues(bytecount1) = Wcapture ' Wert im Array ablegen ' Print Capvalues(bytecount1) ; ","; Bytecount1 = Bytecount1 + 1 ' Array-Adresse +1 If Bytecount1 >= 50 Then ' Wenn Array droht überzulaufen, dann Array wieder von vorn beschreiben Bytecount1 = 1 ' Array-Index wieder auf 1 setzen End If 'Print Wcapture ; ","; End If Return '---------------------------------------------------------- Loesche_array: For X = 1 To 50 ' Gesamtes Array komplett mit Wert: 0 löschen Capvalues(x) = 0 Next Return '---------------------------------------------------------- Int0_s: X = 1 Print " Bytecount1 = " ; Bytecount1 ' Anzah der Werte im Array ausgeben (nur für Debug-Zwecke) For X = 1 To Bytecount1 ' von Byte 1 bis zum Ende der Zeichenkette (im Array) ... Print Capvalues(x) ; ","; ' .... die Werte im Array ausgeben Next Return
Ich nutze den INT0, um mir die Ausgabe des Array's zu starten.
Werte im Array:
34 / 16 / 17 / 17 / 33 / 33 / 34 / 16 / 17 / 17 / 33 / 33 / 17 / 17 / 16 / 34 / 33 / 33 / 16
Abgesehen davon, dass es 19 statt 18 Werte sind passen die Zählerwerte - und damit auch die gemessenen Periodendauern überhaupt nicht mehr.
Wie kann denn sowas sein? Ich arbeite doch INT-bezogen! Okay der Print-befehl in der INT-Routine "klaut mir etwas Rechenzeit und müsste
meine "Messung" bzw. meine Werte verändern. Das das aber nicht der Fall ist bestätigt der Vergleich mit der Messung mit dem Speicheroszi. Hier passen die Werte meines µp-Programms mit den Werten der Speicheroszi-Messung, obwohl der "Print-Befehl" drin ist.
Ich wäre für jeden Tipp dankbar,
Gruß,
ulfens







					
					
					
						
Zitieren

Lesezeichen