- 12V Akku mit 280 Ah bauen         
Ergebnis 1 bis 3 von 3

Thema: Problem mit Capture-Interrupt beim TIMER1 (IR-Empfaenger)

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    09.10.2005
    Beiträge
    17

    Problem mit Capture-Interrupt beim TIMER1 (IR-Empfaenger)

    Anzeige

    LiFePo4 Akku selber bauen - Video
    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:
    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:
    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

  2. #2
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.802
    Mal was anderes: Du kannst in der InCapt-Routine die Flanke für den Capture umpolen, und somit eine "richtige" Auswertung des Signals machen.
    Disclaimer: none. Sue me.

  3. #3
    Neuer Benutzer Öfters hier
    Registriert seit
    09.10.2005
    Beiträge
    17
    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!

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

Labornetzteil AliExpress