PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ungewollt geänderte Variable in einer function - spuk?



mathias172
01.01.2008, 03:44
Hallo und Frohes Neues!

Ich kämpfe hier mittlerweile seit 2 Tagen mit einer Kleinigkeit herum, die in anderen Sprachen vielleicht in 2 Minuten erledigt ist aber irgendwie brauche ich mal eine kleine Aufklärung.

Ich versuche eine Kleine Routine zu schreiben, der ich einen Prozentwert übergebe. Ich möchte dann hinterher den Prozentwert als Balken auf einem Display ausgegeben haben. Ein ähnliches Programm habe ich hier bereits entdeckt, aber der Stolz... ;)

Hier die Deklaration:

Declare Function Ausgabe(byval Prozent As Byte) As String

Hier meine Funktion:


Function Ausgabe(byval Prozent As Byte)
Local Temp As Integer
Local Temp2 As Word
Local Temp3 As String * 20

Temp = Prozent / 10
For Temp2 = 1 To Temp Step 1
Temp3 = Temp3 + "#"
Next

Ausgabe = temp3
End Function



Mein Problem: Ich kann mit der Programmierung meiner Routine nicht fortfahren weil die übergebenen Werte ständig falsch ankommen.

Beispiel:
Ich rufe die Funktion auf: ausgabe(125)
Der Wert 125 kommt so momentan an. Fein.

Ändere ich die Funktion mit einer Kleinigkeit ab funktioniert nix mehr:


Function Ausgabe(byval Prozent As Byte)
Local Pe As Word
Local Temp As Integer


Allein die Deklaration von Pe als Word führt dazu, dass sich der Wert von "Prozent" auf den vollkommen unklaren Wert von 59 ändert.


Das kann und darf doch wohl auf keinen Fall sein, oder habe ich etwas übersehen? Ich hätte nie gedacht, dass ich mich mal an so einer Kleinigkeit so festbeissen würde.


Beste Grüße,
Mathias[/php]

Furtion
01.01.2008, 11:55
Hi,

ich würde das mit ner Sub machen:



$regfile = "m8def.dat" ' specify the used micro
$crystal = 1000000
$baud = 4800

Declare Sub Get_prozent
Dim Ausgabe As String * 20
Dim Eingabe As Byte

Do

Input "Eingabe: " , Eingabe
Call Get_prozent
Print "Ausgabe: " ; Ausgabe

Loop

End

Sub Get_prozent
Ausgabe = ""
Local Temp As Integer
Local Temp2 As Byte

Temp = Eingabe / 10

For Temp2 = 1 To Temp Step 1
Ausgabe = Ausgabe + "#"
Next

Temp2 = 0

End Sub


Das funktioniert bei mir in Simulator.

roboterheld
01.01.2008, 12:22
....ich würde das mit ner Sub machen: .....

warum nicht eine funktion. wenn die werte richtig übergeben werden funktioniert sie auch.

linux_80
01.01.2008, 13:11
Hallo,

@mathias172
evtl. musst Du Dir mal diese Seite durchlesen:
https://www.roboternetz.de/wissen/index.php/Bascom_Inside
und die Werte im Programm für $swstack und $framesize erhöhen !

mathias172
01.01.2008, 13:15
Hallo Furtion, hallo roboterheld,

mir gehts eigentlich gar nicht um die Lösung meiner Programmieraufgabe, sonder eher darum, dass ich herausbekomme, warum ausgerechnet diese Konstellation nicht funktioniert. So ein Kleinkram kann für eine Menge Verwirrung sorgen wenn man mal ein umfangreicheres Projekt hat.

Könnt ihr dasselbe Problem beobachten wenn ihr die Funktion mal bei euch laufen lasst?

Im Anhang nochmal das komplette Programm (mittlerweile recht zerrupft).
Allein durch die Zeile "Local Pe As Word" ändert sich der Ausgabewert der Funktion obwohl nirgens mit "Pe" gearbeitet wird.



$crystal = 8000000

Config Lcd = 20 * 4 'Anzeigemodus 40 x 4 Zeichen
Config Lcdpin = Pin , E = Portb.6 , Rs = Portb.7 , Db4 = Portb.3 , Db5 = Portb.2 , Db6 = Portb.1 , Db7 = Portb.0 , E2 = Portb.5

Dim X As Integer , Mini As Byte , Maxi As Byte , Ausgabe As Byte , Teststring As String * 10
Dim A As Long , B As Long
Dim ___lcdno As Byte

Config Servos = 1 , Servo1 = Portc.0 , Reload = 10 , Timer = Timer0
Config Portb = Output
Config Portd = Input
Enable Interrupts

Declare Function Ausgabe(byval Prozent As Byte) As String

___lcdno = 0
Initlcd
Cls


Portd = 1
Mini = 30
Maxi = 160
X = Maxi - Mini
X = X / 2
X = X + Mini


Do
If Pind.0 = 0 Then X = X + 1
If Pind.1 = 0 Then X = X - 1
If Pind.2 = 0 Then X = X + 10
If Pind.3 = 0 Then X = X - 10
Waitms 50

Dim P As Integer , P2 As Integer , Y As Integer
Y = X
P = Maxi - Mini
P = P / 100
P2 = Mini + Y
P = P2 / P


Locate 1 , 1
Teststring = Ausgabe(90)

Servo(1) = X
Loop
End


Function Ausgabe(byval Prozent As Byte)
Local Pe As Word
Local Temp As Integer
Lcd Prozent
Local Temp2 As Word
Local Temp3 As String * 20

Temp = Prozent / 10
For Temp2 = 1 To Temp Step 1
Temp3 = Temp3 + "##"
Next

Ausgabe = Str(prozent) + " " + Temp3
Temp3 = ""
Temp2 = 0
Ausgabe = Str(prozent)

End Function

StevieL
01.01.2008, 13:56
Hallo Matthias,

Linux_80 hat vermutlich die Problemlösung bereits aufgezeigt. Was hast du denn als Stackwerte eingetragen? Hast du schon versucht, die zu erhöhen?

mathias172
01.01.2008, 16:53
Hello again ;)

Es liegt/lag tatsächlich am swstack. Vielen Dank für die Hilfe.

Ich werde mal meine Zeilen entwirren und dann nochmal posten. Vielleicht kann ja mal jemand die Funktion brauchen.

PicNick
01.01.2008, 17:12
"local" geht direkt auf die Framesize, vorsicht !

https://www.roboternetz.de/wissen/index.php/Bascom_Inside

mathias172
01.01.2008, 23:24
Gibt es einen empfehlenswerteren Weg als lokale Variablen?
Mir fiel auch auf, dass die Locals Ihre Werte nach Ablauf der Funktion behalten und beim nächsten Aufruf immer noch zur Verfügung stehen, d.h. in meinem Fall jedes Mal wieder auf 0 gesetzt werden müssen.

Wie auch immer. Anbei nochmal mein gesamtes Programm mit der Funktion.
Kurzfassung: Das Ganze hat einen Servo an den Ports C und ein Wintek (Pollin) Display an Port B. An Port D hole ich mir Schalterzustände mit denen ich die Servoposition einstellen kann. In der ersten Display-Zeile wird der Prozentuale Wert angegeben, in der zweiten Zeile der Balken. Funktionsaufruf ist mit Prozentwert und Maximal möglicher Balkenlänge.


$crystal = 8000000
$framesize = 32 ' die Größe des Frames
$swstack = 320 ' die Größe des Software-stacks
$hwstack = 32 ' die Größe des Hardware-Stacks

Config Lcd = 20 * 4 'Anzeigemodus 40 x 4 Zeichen
Config Lcdpin = Pin , E = Portb.6 , Rs = Portb.7 , Db4 = Portb.3 , Db5 = Portb.2 , Db6 = Portb.1 , Db7 = Portb.0 , E2 = Portb.5
Dim ___lcdno As Byte

Config Servos = 1 , Servo1 = Portc.0 , Reload = 10 , Timer = Timer0
Config Portb = Output
Config Portd = Input

Dim X As Byte , Mini As Byte , Maxi As Byte , Ausgabe As Byte , Temp As Byte
Dim P As Single , P2 As Integer

Enable Interrupts

Declare Function Balken(byval Prozent As Single , Byval Laenge As Byte) As String

___lcdno = 1
Initlcd
Cls

___lcdno = 0
Initlcd
Cls
Cursor Off

Portd = 1
Mini = 40
Maxi = 155
X = Maxi - Mini
X = X / 2
X = X + Mini



Do

P = Maxi - Mini
P = P / 100
P2 = X - mini
P = P2 / P
P = Round(p)



If Pind.0 = 0 Then
Temp = X + 2
If Temp <= Maxi Then X = X + 2
End If

If Pind.1 = 0 Then
Temp = X - 2
If Temp => Mini Then X = X - 2
End If


If Pind.2 = 0 Then
Temp = X + 10
If Temp <= Maxi Then X = Maxi
End If


If Pind.3 = 0 Then
Temp = X - 10
If Temp => Mini Then X = Mini
End If

Locate 1 , 1
Lcd P
Locate 2 , 1
Lcd Balken(p , 20)
Servo(1) = X

Loop
End


Function Balken(byval Prozent As Single , Byval Laenge As Byte)
Local Temp1 As Single
Local Temp2 As Single
Local Temp3 As String * 40

Laenge = Laenge - 2

Temp1 = Prozent * Laenge
Temp1 = Temp1 / 100

If Prozent <= 1 Then Temp3 = "" Else Temp3 = "#"

For Temp2 = 1 To Temp1 Step 1
Temp3 = Temp3 + "#"
Next
Balken = Temp3 + " "
End Function

stefan_Z
02.01.2008, 01:48
Also die Locals werden glaubich im Simulator nur einfach nicht gelöscht.
Sobald die Sub zuende ist, werden die Speicherplätze wieder "recyclet" und beim neu initialisieren gelöscht.