Welche ISR ist schneller?

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    Aufgrund technischer Veränderungen ist der Mailverkehr innerhalb des Forums (Private Nachrichten) nur noch eingeschränkt möglich. Die Einschränkung ist notwendig, um zusätzliche Betriebskosten für das Forum zu vermeiden. Näheres zu den Hintergründen im Thread "Aktuelles zum Forum".Wir bitten um Verständnis.

    Hinweis kann nach Kenntnisnahme deaktiviert werden!

    • Welche ISR ist schneller?

      Hallo Forum
      Für einen kleinen Motor-Incremental-Encoder habe ich zwei Varianten für die ISR.

      Variante 1:

      Encoder_c:

      If A = 1 And B = 1 Then Zähler = Zähler - 1
      If A = 1 And B = 0 Then Zähler = Zähler + 1
      If A = 0 And B = 1 Then Zähler = Zähler + 1
      If A = 0 And B = 0 Then Zähler = Zähler - 1

      Return


      Variante 2:

      Encoder_c:

      If A = 1 Then
      If B = 1 Then Zähler = Zähler - 1
      If B = 0 Then Zähler = Zähler + 1
      Elseif A = 0 Then
      If B = 1 Then Zähler = Zähler + 1
      If B = 0 Then Zähler = Zähler - 1
      End If

      Return


      A und B sind die Ausgänge des Encoder's, wobei A den Int. auslöst.Von der Auflösung her reicht das vollkommen aus. Ich muß A auch auswerten, da ich einen PCINT benutze, der reagiert nur auf steigende UND fallende Flanken.
      Jetzt würde ich gern wissen, welche Variante wohl schneller verarbeitet wird. Übrigens, Variante 2 benötigt 128 Byte weniger im Flash. Vielleicht gibt es auch eine noch schnellere Möglichkeit.
      Was meint Ihr

      LG Thomas
    • Limo schrieb:

      Vielleicht gibt es auch eine noch schnellere Möglichkeit.
      Vielleicht eine Select Case

      BASCOM-Quellcode

      1. Select Case A
      2. Case 0 :
      3. Select Case B
      4. Case 0 : Zaehler = Zaehler - 1
      5. Case 1 : Zaehler = Zaehler + 1
      6. End Select
      7. Case 1 :
      8. Select Case B
      9. Case 0 : Zaehler = Zaehler + 1
      10. Case 1 : Zaehler = Zaehler - 1
      11. End Select
      12. End Select
      Alles anzeigen
      Eine Lösung habe ich nicht, aber mir gefällt Ihr Problem.
    • Limo schrieb:

      Jetzt würde ich gern wissen, welche Variante wohl schneller verarbeitet wird.
      Hallo Limo
      Die schnellste Variante ist die von Pluto vorgeschlagene.
      Wenn die ISR-Routinen per Gosub aufgerufen wird (ich weiß es ist eine ISR), dann ist Plutos Variante mit 31 Takten nach meinem Testprogramm die schnellste.
      Deine 1. Variante ist mit 123 die langsamste von allen. Mit deiner 2. Variante liegst du schon sehr gut (35 Takte).

      Sowas kann man gut mit dem Simulator austesten.
      Hier mein Testprogramm:

      BASCOM-Quellcode: ISR-Varianten im Vergleich

      1. $Regfile = "m328pdef.dat"
      2. $HWStack = 30
      3. $SWStack = 20
      4. $Framesize = 30
      5. $Crystal = 160000000
      6. A Alias PinB.0
      7. B Alias PinB.1
      8. Dim Zähler as Word
      9. On PCInt0 ISR_VarianteNS NoSave
      10. Enable PCInt0
      11. Enable Interrupts
      12. Do
      13. Gosub ISR_Variante1
      14. Gosub ISR_Variante2
      15. Gosub ISR_Variante3
      16. Gosub ISR_Variante4
      17. Gosub ISR_Variante5
      18. Gosub ISR_Variante6
      19. Loop
      20. ' 123 Takte (mit Gosub aufgerufen)
      21. ISR_Variante1:
      22. If A = 1 And B = 1 Then Zähler = Zähler - 1
      23. If A = 1 And B = 0 Then Zähler = Zähler + 1
      24. If A = 0 And B = 1 Then Zähler = Zähler + 1
      25. If A = 0 And B = 0 Then Zähler = Zähler - 1
      26. Return
      27. ' 35 Takte (mit Gosub aufgerufen)
      28. ISR_Variante2:
      29. If A = 1 Then
      30. If B = 1 Then Zähler = Zähler - 1
      31. If B = 0 Then Zähler = Zähler + 1
      32. Elseif A = 0 Then
      33. If B = 1 Then Zähler = Zähler + 1
      34. If B = 0 Then Zähler = Zähler - 1
      35. End If
      36. Return
      37. ' 41 Takte (mit Gosub aufgerufen)
      38. ISR_Variante3:
      39. Select Case A
      40. Case 0 :
      41. Select Case B
      42. Case 0 : Zähler = Zähler - 1
      43. Case 1 : Zähler = Zähler + 1
      44. End Select
      45. Case 1 :
      46. Select Case B
      47. Case 0 : Zähler = Zähler + 1
      48. Case 1 : Zähler = Zähler - 1
      49. End Select
      50. End Select
      51. Return
      52. ' 31 Takte (mit Gosub aufgerufen)
      53. ISR_Variante4:
      54. If A = 1 Then
      55. If B = 1 Then
      56. Zähler = Zähler - 1
      57. Else
      58. Zähler = Zähler + 1
      59. End If
      60. Else
      61. If B = 1 Then
      62. Zähler = Zähler + 1
      63. Else
      64. Zähler = Zähler - 1
      65. End If
      66. End If
      67. Return
      68. ' 41 Takte (mit Gosub aufgerufen)
      69. ISR_Variante5:
      70. If A = B Then Zähler = Zähler - 1 Else Zähler = Zähler + 1
      71. Return
      72. ' 41 Takte (mit Gosub aufgerufen)
      73. ISR_Variante6:
      74. If A = B Then
      75. Zähler = Zähler - 1
      76. Else
      77. Zähler = Zähler + 1
      78. End If
      79. Return
      80. ' 56 Takte (als ISR aufgerufen)
      81. ISR_VarianteNS:
      82. !PUSH r16
      83. !IN r16,SREG
      84. !PUSH r16
      85. !PUSH r17
      86. !PUSH xl
      87. !PUSH xh
      88. If A = 1 Then
      89. If B = 1 Then
      90. Zähler = Zähler - 1
      91. Else
      92. Zähler = Zähler + 1
      93. End If
      94. Else
      95. If B = 1 Then
      96. Zähler = Zähler + 1
      97. Else
      98. Zähler = Zähler - 1
      99. End If
      100. End If
      101. !POP xh
      102. !POP xl
      103. !POP r17
      104. !POP r16
      105. !OUT SREG,r16
      106. !POP r16
      107. Return
      Alles anzeigen
      Da diese Routinen aber als ISR verwendet werden, kommt jetzt ein Overhead hinzu. Also Register retten und wieder herstellen. Das schluckt die meiste Verarbeitungszeit mit ca 120 Takten. Das ist vom Controller abhängig (Du hast keinen angegeben).

      Wenn die ISR also schnell abgearbeitet werden soll, macht es Sinn nur die Register zu sichern und wieder herzustellen, die auch tatsächlich in der ISR-Routine geändert werden. Bascom sichert fast alle Register.
      Um das zu erreichen musst du die Anweisung "On ISR <label> NOSAVE" mit NOSAVE angeben.Damit sichert Bascom keine Register mehr und du musst dich selber drum kümmern.
      Im Simulator kannst du dann prüfen, welche Register in der ISR durch den Code geändert werden. Und diese Register plus SREG müssen gesichert und restauriert werden.

      In meinem Testprogramm wurde bei der ISR_VarianteNS (NoSave) die Register r16,r17, r26 und r27 geändert. Wie man die Register sichert und restauriert siehst du in der ISR.
      Schneller gehts dann nur noch, wenn die ganze ISR in Assembler schreibt.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Mitch64 ()

    • Aber auch nur die halbe Auflösung. Der Motor-Encoder arbeitet mit Hall-Sensoren (heißen die heute noch so?), das prellen ist kein Thema. Und da er ohnehin auch bei HL-Flanke in die ISR springt und auf 1 prüft, kann ich auch beide Zustände zum zählen nutzen.

      Mitch64, hast Du Lust, mir mal zu erklären, wie Du die Takt-Anzahl der ISR im Simulator festgestellt hast? Ich werde mit ihm nicht warm. Auch im Lexikon gibt es (noch)nichts zum Simulator.

      Gruß Thomas