Pin-Alias an Sub übergeben

    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!

    • Das lässt sich kompilieren.
      Aber es funktioniert nicht!

      BASCOM-Quellcode: Funktioniert nicht

      1. ' Demo Übergabe von Alias an Routinen
      2. $Regfile = "m328pdef.dat"
      3. $HWStack = 48
      4. $SWStack = 48
      5. $FrameSize = 48
      6. $Crystal = 16000000
      7. LED1 Alias PortB.1
      8. Config LED1 = Output
      9. Declare Sub MeineRoutine(Byval x as Byte)
      10. Do
      11. Call MeineRoutine(LED1)
      12. Loop
      13. Sub MeineRoutine(Byval x as Byte)
      14. Set x
      15. Reset x
      16. End Sub
      Alles anzeigen
      Im Simulator rührt sich nichts am Pin. Und in der Routine ist x = 0 beim Aufruf.

      Haste noch ein anderer Vorschlag?

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

    • Wenn ich in der Deklaration und in Sub-Header ByVal durch ByRef ersetze oder weglasse, bekomme ich Fehlermeldung.

      BASCOM-Quellcode: Funktioniert nicht

      1. ' Demo Übergabe von Alias an Routinen
      2. $Regfile = "m328pdef.dat"
      3. $HWStack = 48
      4. $SWStack = 48
      5. $FrameSize = 48
      6. $Crystal = 16000000
      7. LED1 Alias PortB.1
      8. Config LED1 = Output
      9. Declare Sub MeineRoutine(x as Byte) ' funktioniert nicht
      10. Do
      11. Call MeineRoutine(LED1)
      12. Loop
      13. Sub MeineRoutine(x as Byte)
      14. Set x
      15. Reset x
      16. End Sub
      Alles anzeigen
      Fehlermeldung:
      Error : 248 Line : 18 BYVAL should be used in declaration [[ 24]] , in File : Alias_als_Parameter\Demo.bas

      Der Code oben ist vollständig. Ihr dürft es gerne auch probieren.

      Ich meine mich dumpf zu erinnern, dass ich das vor Jahren mal hinbekommen habe. Allerdings musste ich da Port und Pin-Nr . in 2 Parametern übergeben, soweit ich mich erinnere.
    • Pluto25 schrieb:

      Ich hatte es andersrum getestet:
      Bei Übergabe Byval X as Byte wird eine lokale Variable angelegt. Die wird vor Aufruf mit 0 belegt.

      Ergo:
      Wenn du dann x abfrägst, fragst du immer nur die lokale Variable X ab. Die ist immer 0 und deswegen wird auch immer "LED aus" ausgegeben.
      Das frägt nicht den Port-Pin ab!

      Man kann aber den Alias eines Ports oder den Port direkt mit Byref übergeben.

      BASCOM-Quellcode: funktioniert

      1. Sub SetPort(ByRef portName as Word)
      2. portName.1 = 1
      3. portName = &hFF
      4. portName.4 = 0
      5. End Sub



      So kann man zumindest mal auf den Port Einfluss nehmen. Aus Port-Abfragen sollte gehen.

      Will man einzelne PortPins übergeben, funktioniert das scheinbar nur, wenn man Port und Pin separat übergibt.
      Der Port Byref as Word und der Pin Byval as Byte.

      Quellcode

      1. Sub TogglePortPin(ByRef portName as Word , Byval pin as Byte)
      2. Set portName.pin
      3. Reset portName.pin
      4. ' Toggle portName.pin ' das funktioniert leider nicht!
      5. End Sub
      Jetzt denkt sich der eine oder andere bestimmt, was das soll.
      Man kann die Ports doch direkt setzen, Löschen und Toggeln. Wozu also die Routinen?

      Es geht nicht darum, jetzt umständlich Pins zu setzen/löschen/toggeln. Die Routinen zeigen nur, ob und wie auf den übergebenen Alias zugegriffen werden kann.

      Man stelle sich eine Include-Datei vor, die Routinen für ein Baustein enthält, der an diversen Pins angeschlossen ist. Das kann ein Sensor oder auch ein Display sein. Dann kann man die Include-Datei nie ohne Veränderung in anderen Projekten übernehmen.
      Bei jedem Projekt muss man eine Kopie der Include zu seinem neuen Projekt legen und dann in der Include die Pin-Aliasse ändern.
      Das Problem bleibt auch, wenn man aus der INC eine Lib macht.

      Daher die Idee beim Initialisieren der INC/LIB die Pins per Alias zu übergeben
      Damit kann man dann die Pins in der INC speichern in Variablen. Die Lib greift dann über die Variablen auf die Hardware zu.

      Das Händling wäre dann ähnlich wie beim Arduino, wo man Pin-Nummern beim Initialisieren übergibt.
      Pins aber in Bascom wieder auseinander zu wurschteln in einer INC ist Zeitaufwendig. Daher die Übergabe der Aliasse.

      Bleibt noch die Frage, wie man die Aliasse in der INC/Lib speichern kann.
      Nun bei der Übergabe der Register (z.B. PortB oder anderen Registern) wird die Adresse des ioPorts auf den Software-Stack gelegt.
      Den muss man einmalig ermitteln und in einer Variablen speichern. Separat speichern muss man auch den zugehörigen Pin.

      Die Adresse kann man dann z.B. so ermitteln:


      BASCOM-Quellcode: funktioniert

      1. ' Adresse eines Register's ermitteln
      2. ' Rückgabe Memory-Adresse (nicht IO-Adresse)
      3. Function GetRegAdr(ByRef ioName as Word) as Word
      4. LoadAdr ioName , X ' Adresse ioName -> X
      5. LoadAdr GetRegAdr , Z ' Adresse Rückgabe -> Z
      6. !ST z+,xl ' Adresse zurückgeben
      7. !ST z+,xh
      8. End Function
      Der Zugriff auf die Register/Ports kann dann z.B. mit den Basic-Befehlen INO und OUT erfolgen. Hier muss ja die Adresse angegeben werden.

      Übrigens wird bei der Übergabe von Alias nicht die ioAdresse übergeben, sondern die entsprechende Memory-Adresse. Daher ist es mit den INP/OUT möglich, auf alle Register zuzugreifen, auch die, welche sich oberhalb der IO-Adresse $3F befinden.

      Vielleicht hilft jemanden die Info mal.

      Hier noch der komplette Demo-Code (lauffähig)

      BASCOM-Quellcode: Demo (lauffähig)

      1. ' Demo
      2. ' Übergabe von Alias an Routinen und Zugriff
      3. ' Diese Demo kann im Simulator geprüft werden.
      4. $Regfile = "m328pdef.dat"
      5. $HWStack = 48
      6. $SWStack = 48
      7. $FrameSize = 48
      8. $Crystal = 16000000
      9. BUS_Port Alias PortC ' Alias für PortC
      10. Dim tmpReferenz as Word ' speichert Adresse von Register
      11. Declare Sub SetPort(ByRef portName as Word) ' Port-Alias übergeben
      12. Declare Sub TogglePortPin(ByRef portName as Word , Byval pin as Byte) ' Port-Alias + Pin übergeben
      13. Declare Function GetRegAdr(ByRef ioName as Word) as Word ' Adresse eines Registers ermitteln
      14. Do
      15. tmpReferenz = GetRegAdr(TIMSK2) ' Adresse von Register TIMSK2 ermitteln
      16. Call TogglePortPin(PortB , 1) ' Port direktübergabe
      17. Call SetPort(BUS_Port) ' Port-Alias Übergabe
      18. Loop
      19. ' ------------------------------------
      20. ' Übergabe Port / Port-Alias
      21. ' Zeigt Zugriff auf den Port
      22. ' ------------------------------------
      23. Sub SetPort(ByRef portName as Word)
      24. portName.1 = 1
      25. portName = &hFF
      26. portName.4 = 0
      27. End Sub
      28. ' ------------------------------------
      29. ' Übergabe Port / Port-Alias und PortPin
      30. ' Zeigt Zugriff auf Pins
      31. ' ------------------------------------
      32. Sub TogglePortPin(ByRef portName as Word , Byval pin as Byte)
      33. Set portName.pin
      34. Reset portName.pin
      35. ' Toggle portName.pin ' das funktioniert leider nicht!
      36. End Sub
      37. ' ------------------------------------
      38. ' Adresse eines Register's ermitteln
      39. ' Rückgabe Memory-Adresse (nicht IO-Adresse)
      40. ' ------------------------------------
      41. Function GetRegAdr(ByRef ioName as Word) as Word
      42. LoadAdr ioName , X ' Adresse ioName -> X
      43. LoadAdr GetRegAdr , Z ' Adresse Rückgabe -> Z
      44. !ST z+,xl ' Adresse zurückgeben
      45. !ST z+,xh
      46. End Function
      Alles anzeigen

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

    • Mitch64 schrieb:

      Die wird vor Aufruf mit 0 belegt
      Nur wenn das alias bit auch 0 ist sonst mit 1. Auch mit 1 wenn das alias eine andere Nummer hat (0-7(-15 bei einem Word)) Womit die Information verloren geht wessen und das wievielte Bit das war.


      Mitch64 schrieb:

      Toggle portName.pin
      = Set Portname-2.pin bzw Portpin = Portname-2: Set Portpin.pin
      Für den Portnamen reicht auch ein Byte.
    • Pluto25 schrieb:

      Nur wenn das alias bit auch 0 ist sonst mit 1. Auch mit 1 wenn das alias eine andere Nummer hat (0-7(-15 bei einem Word)) Womit die Information verloren geht wessen und das wievielte Bit das war.
      Bei deiner Methode übergibst du nur den momentan anstehenden Pinwert der Routine. Aber keine Referenz auf den Pin.
      Bedeutet, dass das Lesen eingeschränkt funktioniert. Der Pin kann sich ändern, während sich das Programm in der Routine befindet, die das aber nicht mitbekommt.
      Es ist ja nur eine Kopie des Pinwertes, der vor Aufruf der Routine angelegen hat.

      Drauf schreiben geht nicht. Auch nicht den Pin als Eingang oder Ausgang konfigurieren.
      Und das mit der Bit-Nr, also welches Bit am Port gelesen wurde, wäre egal. Das interessiert ja in der Routine nicht.

      Pluto25 schrieb:

      Für den Portnamen reicht auch ein Byte.
      Das war mir bewusst. Aber wenn etwas ByRef übergeben wird, wird eine Adresse übergeben und die ist typischerweise 16 Bit, also Word.
    • Pluto25 schrieb:

      Sicher geht das
      Set Portname.pin schaltet den Pin ein
      Set Portname-1.pin macht ihn zum Ausgang
      Reset schaltet ihn ab / macht ihn zum Eingang
      Set Portname-2.pin toggelt ihn (nicht bei allen Avr)
      Da bewirkt Reset rein gar nichts, ähnlich sinnlos wie Pinb=0
      Dann zeig ein Beispiel (lauffähig), wie das geht.

      Keine Ahnung was du mit Portname-1 und Portname-2 meinst. Sowas war zumindest in meinem Programm nicht definiert.

      Nochmal zum Verständnis.

      Im Hauptprogramm definierst du z.B.
      LED1 Alias PortB.0

      Fertig.

      Jetzt schreibst du eine Routine, die LED1 als Parameter erhalten soll.
      In der Routine soll nun über den Parameter (LED1)
      der Pin als Ausgang konfiguriert und der Pin High geschaltet werden.

      LED1 Alias PortB.0

      Die Routine soll so aussehen:

      BASCOM-Quellcode

      1. Sub InitLed( Referenz auf Portpin)
      2. Config Portpin=Output
      3. Set Portpin
      4. ' alternativ:
      5. Portpin=1
      6. End Sub

      Der Portpin (Alias) wird übergeben und über diesen soll der Pin konfiguriert und eingestellt werden können.

      Was ich nicht meine ist das:

      Quellcode

      1. LED1 Alias PortB.0
      2. Sub Init_Led(Referenz Portpin)
      3. Config LED1=Output
      4. Set LED1
      5. End Sub
      Ich verstehe nicht wie du das meinst, oder wir reden aneinander vorbei.

      Bitte mach ein Beispiel zum Verständnis.
    • Hallo Mitch,
      ich bin mir nicht sicher, ob ich richtig verstanden habe, was du erreichen willst.
      Schau dir mal dies an, ob es deinen Vorstellungen entspricht.

      BASCOM-Quellcode

      1. $regfile = "attiny4313.dat"
      2. $crystal = 20000000
      3. $hwstack = 20
      4. $swstack = 10
      5. $framesize = 40
      6. Declare Sub Pin_change(portx As Byte , Byval Px As Byte)
      7. 'Declare Sub Pin_change(x As Byte)
      8. Ddrb = &B0011_0011
      9. Portb = &B0001_0001
      10. Do
      11. Pin_change Portb , 6
      12. Loop
      13. End
      14. Sub Pin_change(portx As Byte , Byval Px As Byte)
      15. Local Ddrx As Byte
      16. Local Pinx As Byte
      17. Local Valddrx As Byte
      18. Local Valpinx As Byte
      19. Local Valportx As Byte
      20. Ddrx = Varptr(portx) - 1 'adresse von DDRx, wahrscheinlich µC abhängig
      21. Pinx = Varptr(portx) - 2 'adresse von PINx, wahrscheinlich µC abhängig
      22. Valddrx = Inp(ddrx)
      23. Valpinx = Inp(pinx)
      24. Valportx = Portx
      25. Valddrx.px = 1
      26. Valportx.px = 1
      27. Out Ddrx , Valddrx 'set ddrx.px
      28. Portx = Valportx 'set portx.px
      29. Toggle Portx.px 'toggle portx.px
      30. Portx = Valpinx 'set portx=pinx
      31. End Sub
      Alles anzeigen
      Nur im Simulator getestet.
    • Hallo Franz.
      Danke für deinen interessanten Einwurf. Im Prinzip ist es das schon, was ich meine.
      Und mir war auch schon klar, dass ich Port und Pin getrennt übergeben muss.
      Min INP und OUT habe ich auch schon experimentiert, um wieder auf die Register zuzugreifen.

      Allem in allem aber ziemlich umständlich.
      In Assembler habe ich es auch versucht. Es ist zwar schneller, aber auch umständlich.

      Die Frage, die ja noch offen war war, ob man einen PortPin auf einmal übergeben kann.
      Nicht port und pin trennen.

      Pluto ist da ja anderer Ansicht als ich.

      Dennoch finde ich dein Beispiel nachahmenswert.
    • Hallo Mitch,
      dies hier ist ja deswegen so umfänglich, weil ich alles reingepackt habe.
      Also Portx.y als Ausgang definieren, Portx.y setzen und toggeln, und dann noch Pinx einlesen.

      Direkt Portx.y im Aufruf angeben, kann meiner Meinung nach im Moment aus zwei Gründen nicht funktionieren:
      1. Bit-Werte sind als Parameter nicht erlaubt, könnte MCS aber wahrscheinlich mit etwas Aufwand ändern. Dies ist ja grundsätzlich interessant.
      2. Damit Portx.y in der Sub oder Funktion richtig verwendet werden kann, müsste neben dem Wert auch die Referenz auf das Register übergeben werden. Auch dies könnte MCS programmieren, evtl über einen zusätzlichen Übergabetyp Portpin. Aber im Moment kann das nicht funktioneren.
    • Mitch64 schrieb:

      Keine Ahnung was du mit Portname-1 und Portname-2 meinst
      Portname ist Dein Konstrukt. Und wenn Deine Routine den kennt sowie die Pinnummer, kann damit sicher auch die Richtung (DDR) und der Eingang (Pin) bestimmt werden. Da Ddradresse = Portname -1 und Pinadresse=Portadresse-2


      Mitch64 schrieb:

      Sowas war zumindest in meinem Programm nicht definiert.

      Mitch64 schrieb:

      Sub TogglePortPin(ByRef portName as Word , Byval pin as Byte)
      Lese ich da nicht deutlich Portname?

      Mitch64 schrieb:

      Pluto ist da ja anderer Ansicht als ich.
      keineswegs, natürlich kann man ein Bit als Parameter übergeben nur das

      Pluto25 schrieb:

      die Information verloren geht wessen und das wievielte Bit das war.

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von Pluto25 ()