Forum: Mikrocontroller und Digitale Elektronik Overlay und Funktionsübergabe in Bascom


von Manfred S. (Firma: Manfred) (xfred343)


Lesenswert?

Hallo,

habe folgendes Thema, aus einem Webserver und einem I2C Bus wird jeweils 
ein eigener Befehlsbuffer gefüllt, der in einem gemeinsamen Interpreter 
analysiert werden soll.

<code>
dim strBuffer1 as string*127
Dim BufferBytes(128) As Byte At strBuffer1 Overlay
dim strBuffer2 as string*127
Dim BufferBytes(128) As Byte At strBuffer2 Overlay
..
Call sInterpreter(strBuffer1)
...
Call sInterpreter(strBuffer2)


sub sInterpreter(strBuffer)
...
end sub
</code>

Wie kann ich hier auf die einzelnenBytes über Overlay zugreifen??
Bin momentan irgendwie planlos

von Weingut P. (weinbauer)


Lesenswert?

Über den Index??

Du hast ja

dim strBuffer1 as string*127
Dim BufferBytes(128) As Byte At strBuffer1 Overlay

das bedeutet, die beiden Variablen liegen übereinander also auch den 
gleichen RAM-Zellen.

Wenn Du nun

strBuffer1="test" machst, dann liegt der ASCII-Wert in:

BufferBytes(1) = 116 ("t")
BufferBytes(2) = 101 ("e")
BufferBytes(3) = 115 ("s")
BufferBytes(4) = 116 ("t")


anders herum geht genau so, nur das ein String mit dem Zeichen 0 
abgeschlossen wird, also

BufferBytes(5) = 0 (NUL)

von Manfred S. (Firma: Manfred) (xfred343)


Lesenswert?

@weinbauer,

ja - danke für die Info - so gehts auch,
das Besondere - hab ich leider im ersten Posting nicht so genau 
ausgedrückt - liegt im Zugriff in der Subroutine sInterpreter, denn hier 
kann einerseits der strBuffer1 oder der strBuffer2 übergeben werden - 
und auch hier möchte ich auf die einzelnen Bytes zugreifen.

von Name (Gast)


Lesenswert?

Hallo Manfred S.,

an dieser Fragestellung bin ich auch schonmal gescheitert.
Habs dann umgangen und ein Bit/Byte übergeben anhand dessen entschieden 
wird, mit welcher Variable es weitergeht.

lG
ich

von Oliver (Gast)


Lesenswert?

Manfred S. schrieb:
> aus einem Webserver und einem I2C Bus wird jeweils
> ein eigener Befehlsbuffer gefüllt,

Das widerspricht dem Ansatz mit "overlay". Solche exotischen Spielereien 
sollte man nur nutzen, wenn es gar nicht anders geht, und man genau 
weiß, was man da tut.

Manfred S. schrieb:
> das Besondere - hab ich leider im ersten Posting nicht so genau
> ausgedrückt - liegt im Zugriff in der Subroutine sInterpreter, denn hier
> kann einerseits der strBuffer1 oder der strBuffer2 übergeben werden -

Die Übergabe eines Parameters an eine Funktion ist eigentlich seit 
Erfindung der alleresten prozeduralen Programmiersprache DAS 
Standardkonzept überhaupt.

Manfred S. schrieb:
> und auch hier möchte ich auf die einzelnen Bytes zugreifen.

Dann mach das doch einfach. Innerhalb von sInterpreter geht das mit
strBuffer(index).

Oliver

von Weingut P. (weinbauer)


Lesenswert?

sorry, wie ist denn die Sub deklariert?

declare sub sInterpreter(byref strBuffer2 as string)

oder

declare sub sInterpreter(byval strBuffer2 as string)

letzteres wäre hanebüchen, dann gehts nämlich erstens nicht mit der
Overlayvariable, weil ja der Inhalt von strbuffer in den Frame kopiert 
wird,
zudem brauch die kopiererei noch unnötige Rechenzeit weil ja die Strings 
eh
schon als globale Variablen deklariert wurden.

Bei ersterem kannst Du zwar auf das Array zugreifen, musst aber der Sub 
auch mitteilen welches es nun sein soll ... macht auch wenig Sinn, da 
der String eh global deklariert ist.

Die sinnvollste Variante ist die von "Name" beschriebene, nur ein Flag 
zu übergeben und in der Sub dann das Flag zu verarbeiten welches Array / 
Sting nun verarbeitet werden soll.

von MWS (Gast)


Lesenswert?

Oliver schrieb:
> Dann mach das doch einfach. Innerhalb von sInterpreter geht das mit
> strBuffer(index).

Ja, es ist möglich auf die Einzelbytes des Argumentes zuzugreifen.
Aber dann solltest Du dem TE vielleicht auch noch sagen wie, denn mit 
der Logik des gezeigten Codes wird's eben nicht klappen.

von Manfred S. (Firma: Manfred) (xfred343)


Lesenswert?

Die Sub ist so definiert:
declare sub sInterpreter(byref strBuffer as string)

Danke für die vielen Rückmeldungen, geb Oliver recht, nur so einfach ist 
der Zugriff über den Index natürlich nicht,

hab jetzt 3 Ansätze:
1) Ansatz mit Flag, welche Variable übergeben wird:
interessanter Ansatz, aber dann muss ich erst in der Subroutine wieder 
zwischen den beiden Variablen unterscheiden

2) die Lösung von MWS - eigentlich genial, ich habe den Link soeben 
gefunden
http://bascom-forum.de/showthread.php?3039-Übergabe-eines-Arrays-an-eine-Sub-oder-Funktion&s=587d925f63a1152846bbc74e35f27b2d
aber über die Hilfe von Bascom wär ich da nicht draufgekommen

3) mit varptr sollte es auch irgendwie gehen

von MWS (Gast)


Lesenswert?

Manfred S. schrieb:
> declare sub sInterpreter(byref strBuffer as string)

Das ist in diesem Fall eben unbrauchbar.

Der Link wird Dir nur begrenzt helfen, denn Du willst einen String 
übergeben und nicht ein Array. Overlay ist hier keine sinnvolle Option.
Aber das hilft Dir:
1
Declare Sub StrSub(S As Byte)
2
3
S = "Hallo"
4
   $notypecheck
5
      StrSub S
6
   $typecheck
7
...
8
Sub StrSub(S)
9
  S(2) = "*"
10
End Sub
Mit Byref, was übrigens Standard ist und nicht extra angegeben werden 
muss, wird ein Zeiger übergeben. Nur wird sich Bascom beschweren, da die 
übergebene Variable sich vom definierten Typ unterscheidet. Das lässt 
sich aber abstellen. Zugriff mit VarPtr(), INP(), OUT() ginge auch, ist 
aber zu kompliziert.

von Manfred S. (Firma: Manfred) (xfred343)


Lesenswert?

Danke, MWS, das mit dem $notypecheck ist super - und das der 
Stringzugriff dann so einfach wird auch.

Hab jetzt aber mein Programm weiterentwickelt und gemerkt, dass ich 
sowohl für Serielle als auch I2C mit einem ByteArray statt einem String 
auskomme.

ByRef schreibe ich zur Dokumentation immer dazu, ganz einfach weil z.B. 
Excel VBA wie Bascom defaultmäßig ByRef hat, .NET allerdings genau 
umgekehrt - so gilt: sicher ist sicher..

<code>
$regfile = "m644def.dat"
$crystal = 8000000
$swstack = 128
$hwstack = 128
$framesize = 128
$baud=19200
Config Serialin = Buffered , Size = 127 , Bytematch = 13
Enable Interrupts
Declare Sub Sinterpreter(byref Arr As Byte , Byref Bytlaenge As Byte) 
'immer erstes Element übergeben
Dim I As Byte
Dim Lngcode As Long
'**************************** Globale Buffer-Variablen, 
Interpretervariablen
Dim Bytarri2c(128) As Byte
Dim Strtext As String * 127
Dim Strzahl As String * 127                                 'max. 10 
Stellen, aber zum Abfangen von Fehleingaben

Do
   'Logik: shared RAM lese und wenn neue Bytes, dann SInterpreter 
aufrufen
'   I = 17                                                   'Länge der 
empfangenen Bytes, hier nur Beispiel
'   Call Sinterpreter(bytarri2c(1) , I) 
'0-Terminierung des Strings nicht erforderlich!
Loop


Serial0charmatch:
  I = _rs_bufcountr0 - 1
  Call Sinterpreter(_rs232inbuf0(1) , I)
  Clear Serialin
Return


Sub Sinterpreter(byref Arr As Byte , Byref Bytlaenge As Byte) 
'immer erstes Element übergeben
'Achtung: wenn I für Bytlänge übergeben wird, wird I auch gleich 
geändert
'Befehle, z.B. Code12345678 oder 4711 oder X343
Strzahl = ""
Strtext = ""
For I = 1 To Bytlaenge                                      'trenne 
Ziffern und Text
  If Arr(i) >= 48 And Arr(i) <= 57 Then
     Strzahl = Strzahl + Chr(arr(i))
  Else
     Strtext = Strtext + Chr(arr(i))
  End If
Next I
Lngcode = Val(strzahl)
Select Case Strtext
Case "x"
Case "y"
Case Else
   'nur Zahl oder 0 oder falscher Befehl
End Select
End Sub
</code>

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.