PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Problem mit Capture-Interrupt beim TIMER1 (IR-Empfaenger)



Ulfens
19.03.2006, 22:26
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?option=com_content&task=view&id=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_accept.jsp?key=IJHVH84CZDMjG%2F1LiElm5J8 qpsR9mOWID6nF%2F%2BoDHa1NW6YOMmcvNw%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:


'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


Die sofort ausgegebenen Werte sind Gleich den Werten im Array - egal ob ich "Wcapture" direkt über einen Print-Befehl ausgebe,
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:


'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

SprinterSB
20.03.2006, 09:56
Mal was anderes: Du kannst in der InCapt-Routine die Flanke für den Capture umpolen, und somit eine "richtige" Auswertung des Signals machen.

Ulfens
20.03.2006, 12:46
Ja, das kann ich mal versuchen - aber dazu muss ich dann den ganzen Timer umkonfigurieren und mein Programm umstricken.
Vielleicht reicht es ja, nur die entspr. Bits in den Timer-Int-Steuerregister
umzuprogrammieren. Ich mach das heute Abend mal!

Gute Idee - Vielen Dank!