PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Variable nur während interrupt gültig?



MarkusH
15.05.2005, 12:12
Hallo, ich hab ein kleines problem mit bascom. Und zwar möchte ich das aus einer interrupt-routine ein unterprogramm mit parameterübergabe gestartet wird. Aber egal was ich an das sub übergebe es geht nicht, die variable ist dann immer null oder 255. Hier mal ein ganz primitiver quelltext mit dem es auch nicht geht:


$regfile = "m8def.dat"

Dim Var As Byte

Declare Sub Prog(byval Var As Byte)

Config Int0 = Rising
On Int0 Bla
Enable Int0
Enable Interrupts

Do
Loop

Sub Prog(byval Var As Byte)
Print Var
End Sub

Bla:
Var = 55
Call Prog(var)
Return

Ich versteh das nicht, hab ich irgendwas falsch gemacht??? Oder muss ich die variable anders deklarieren damit sie überall gültig ist?
Danke und Gruß, Markus

PicNick
15.05.2005, 13:44
Probier einfach mal Soft-Stack u. Frame größer zu definieren. die Default-Werte sind in bißchen knapp

Baudrate paßt ?

MarkusH
15.05.2005, 14:01
Hey, danke, du hattest recht! Wenn ich Soft-Stack auf 16 setzte (default=8 ) funktionierts. Hat das irgendwelche nachteile wenn man den softstack vergrößert? Wird der wert den ich hier angeb vom Flash als "Arbeitsspeicherzusatz" abgezwackt oder was soll das sein?

PicNick
15.05.2005, 14:09
Er wird leider abgezwackt. (vom SRAM)
Für jedes "byval" muß er eine Kopie anlegen + 2 byte Param-addresse für die Subroutine und für die umwandlung Byte-> printstring braucht er eben auch platz
Und was du was bestellst, mußt du es eben auch bezahlen.
:mrgreen:
sellerie ! (wie die Franzosen sagen)

MarkusH
15.05.2005, 14:57
Oh... mir ist gerade aufgefallen das es nur in meinem beispielprogramm funktioniert. Da wo ich es eigentlich gebraucht hätte gehts nicht. Ich wollte einen schrittmotor ansteuern und über die variabe die position übergeben die er anfahren soll. Ich hab jetzt bemerkt das im simulator ständig "Stack pointer and software stack overlap" in der statuszeile steht. Egal was ich bei softwarestack oder bei frame eintrage, es geht nicht. Die Variable wird im simulator unter locals als 255 ausgewiesen, wenn ich im quelltext mit der maus drüberfahre sagt er 20 wie ich es eigentlich haben wollte. Das ist total verwirrend. Hier mal der code den ich eigentlich nicht posten wollte weil er auf den ersten blick etwas verwirrend aussieht O:)


$regfile = "m8def.dat"
$crystal = 3686400
$baud = 9600

Config Int0 = Rising

Dim I As Byte
Dim Servo_pos As Byte
Dim Servo_byte As Byte

On Int0 Null
Enable Int0
Enable Interrupts

Declare Sub Servo(byval I As Byte)

Servo_byte = 2
Servo_pos = 0

Do
Loop

Sub Servo(byval I As Byte)
Print I
If Servo_pos > I Then 'ist i kleiner als die aktuelle position, dann links rum drehen
If Servo_byte = 1 Then Goto A1 'wo stand der motor als letztes? dort weitermachen
If Servo_byte = 3 Then Goto A3
If Servo_byte = 4 Then Goto A4

Do
Portb = &B00001000
Servo_byte = 4 'motor stnadpukt verändern
Decr Servo_pos 'position -1
If Servo_pos = I Then Goto Fertig 'wenn position = i dann ende
Waitms 50
A4:
Portb = &B00000100
Servo_byte = 3
Decr Servo_pos
If Servo_pos = I Then Goto Fertig
Waitms 50
A3:
Portb = &B00000001
Servo_byte = 1
Decr Servo_pos
If Servo_pos = I Then Goto Fertig
Waitms 50
A1:
Portb = &B00000010
Servo_byte = 4
Decr Servo_pos
If Servo_pos = I Then Goto Fertig
Waitms 50
Loop

Else 'oder rechts rum drehen

If Servo_byte = 1 Then Goto B1 'gleiches spiel wie oben nur umgekehrt
If Servo_byte = 3 Then Goto B3
If Servo_byte = 4 Then Goto B4
Do
Portb = &B00000001
Servo_byte = 4
Incr Servo_pos
If Servo_pos = I Then Goto Fertig
Waitms 50
B1:
Portb = &B00000100
Servo_byte = 3
Incr Servo_pos
If Servo_pos = I Then Goto Fertig
Waitms 50
B3:
Portb = &B00001000
Servo_byte = 1
Incr Servo_pos
If Servo_pos = I Then Goto Fertig
Waitms 50
B4:
Portb = &B00000010
Servo_byte = 4
Incr Servo_pos
If Servo_pos = I Then Goto Fertig
Waitms 50
Loop

End If
Fertig:
Portb = &B00000000
End Sub

Null:
I = 20
Call Servo(i)
Return
End

Würde mich freuen wenn mir jemand weiterhelfen kann, ich hab keine ahnung was daran falsch sein soll.

*edit
mir ist auch noch aufgefallen das sich die variable aus dem ersten, einfachen programm nur mit [print var] ausdrucken lässt. wenn ich [print "variable:" ; var] eingebe dann ist sie wieder 255?! Was soll das??? Ich bin am verzweifeln.

PicNick
15.05.2005, 16:05
Zwischenfrage: was hast du nun f. die Stacks etc. definiert ?
ein Interrput braucht schon mal ca 64 Byte für sich allein, um Mensch zu sein.
Hat er die nicht, schreibt er den Softstack nieder ( result unpredictable)

Ich hab (z.B. allerdings in einem 20K Programm)
HW 128
SW 256
Frame 64
definiert.

Im Vertrauen: "Do..Loop" und "waitms" in einer Interrupt routine werden normalerweise mit öffentlichem Auspeitschen honoriert. Ich rate dringend zu einem re-design.
Is aber nicht bös' gemeint. :!:

PicNick
15.05.2005, 16:18
Noch ne Zwischenfrage: Das scheint ja wohl ein Prototype zu sein. Um was geht's den zirka mit dem Int0 ? (dzt. gibt's ja nur den werte 20 und sonst nix)

MarkusH
15.05.2005, 18:04
also letztendlich wird der motor nicht über den int0 sondern über die serielle schnittstelle angesprochen, so das man anstelle der 20 eben die position eingeben kann die man gern hätte. das mit dem int0 ist noch vom obigen beispielprogramm hängen geblieben, aber ist ja das gleiche prinzip nur das eben jetz nicht der urxc sondern der int0 als interrupt verwendet wird. Ich hab bisher nur mit dem frame u. softstack rumexperimentiert, hatte auch beide schon auf 256 ohne erfolg, hw-stack steht noch auf 32.
Aber ich glaub das Problem hat sich vorerst mal erübrigt weil mir gerade mein letzter Mega8 abgeraucht ist 8-[
Jetzt muss ich wieder wegen einem popligen AVR beim reichelt bestellen.
AAARRRRGGHHHHH

PicNick
15.05.2005, 18:29
O je, ](*,) dann entfällt natürlich jede weiter Strafe.
Rühr' dich halt wieder, du mußt ja das Rad nicht neu erfinden, und einiges bei deinem Konzept ist so'n ding
:D

MarkusH
22.05.2005, 09:04
Hi! Ich bins wieder. War zufällig in der nähe eines Conrad-Ladens diese Woche. Dann hab ich nen neuen Atmega mitgenommen, die wollten da 9,50eur für, wasn wucher! Naja, jedenfalls hab ich noch ne allgemeine frage zu meiner schrittmotorsteuerung. Wenn man wärend eines Interrupts keine schleifen verwenden sollte (ist ja verständlich), was mach ich dann? Setz ich dann ne variable auf true die in der hauptschleife ständig abgeprüft wird oder wie?
Im großen und ganzen... ist meine motorsteuerung akzeptabel oder eher grauenvoll? Ich wüsste nicht wie ich das anders lösen sollte.
Grüßle, Markus

PicNick
22.05.2005, 10:12
Hi !
Ich mach das im Prinzip so:
In einer DO .. LOOP schleife frag' ich immer zwei Dinge ab:
1 Ein Flag vom Timer0 (1mS)
(der Time0-Interrupt tut nix, außer diesen Flag setzen)
den lösch ich und geh einmal in die Motor-routinen (links & rechts)

2 Ischarwaiting vom "config serialin =buffer, size = 64"

Motorroutine: Jeder motor hat eine Soll- und eine Istposition
sind die zwei gleich, macht er nix
wenn nicht, macht er einen Schritt in die richtige richtung und ändert sein "IST"

Ischarwaiting: holt die Zeichen vom Terminal (solange "ischarwaiting") und ändert dann ggf. die SOLL-Position von einem Motor oder nicht.

Vorteil (u.A) : du kannst auch "SOLL" ändern, während der Motor schon läuft

ungefähr klar ?

MarkusH
24.05.2005, 08:07
Ich hab nochmal so ne allgemeine Frage. Nicht das ich da wieder nen falschen ansatz hab. Und zwar dreht sichs um die kommunikation mit dem PC. Ich hab das bisher so gemacht das ich alles über die COM-schnittstelle übertrage. Ich übertrag das alles im ASCII Format. Oder ist das bitweise besser? Er sendet dann z.B. ein A und dann den wert. Dann kann ich am pc anhand von dem buchstaben sehen was das jetzt für ein wert war (ob ultraschall, akku, oder infrarot oder so). Dann hab ichs bisher so das der AVR 500ms wartet zwischen jeder übertragung damit auch immer der buchstabe als erstes kommt und er mir die pakete nicht so blöd aufteilt. Allerdings ist das natürlich höllisch langsam. Ist es sinnvoller ein trennzeichen mitzusenden nachdem dann immer ein neuer wert kommt oder vielleicht gleich direkt als bit-werte einlesen, ich hab keine ahnung. Oder sollt ich in meinem (VB)-Programm nochmal einen extra puffer anlegen der dann ab und zu ausgelesen wird? Wie machst du das?
Danke schonmal für deine Hilfe.
Gruß, Markus

PicNick
24.05.2005, 11:22
Hi, sehr gut wär in ASCII eine CSV-Format, daß kannst du das direkt auch als File schreiben und in Excel einlesen (für Graphik u Diagramme)

A;0.000<CR><LF>

also

PRINT "A;";str(variable)

für sagen wir 10 Zeichen brauch er zum senden bei 9600 etwa 10 mS
da brauchst du nicht solange warten. und wait brauchst du schon garnicht

Für die Umwandlung str(variable) braucht er natürlich Zeit, aber so schlimm ist das auch wieder nicht

du kannst ja mal probieren

dim Wordvar as word

do
wordvar = getadc(n)
PRINT "A;";str(variable)
LOOP

das fetzt schon dahin

MarkusH
24.05.2005, 12:00
Hi, danke für die schnelle antwort. Mein größtes problem ist das die USART-Interrupt-routine im meinem VB-Programm am pc ja nur aufgerufen wird wenn ein Paket reinkommt. Wenn ich jetzt ganz viele werte schnell nacheinander schicke, packt er mir die in das gleiche paket (ne, frame... ach egal). D.h. es kommt dan halt ne zahlen/buchstabenkombination rein die irgendwann abreißt wenn das nächste paket anfängt und die interrupt routine nochmal aufgerufen wird. Kann ich das nicht irgendwie so senden das er mir pro wert den ich verschicke genau 1 paket macht? Dann hätt ich mir das suchen nach trennzeichen im empfangenem string erspart und ich wüsste das er immer mit nem buchstaben beginnt. Weißt du was ich meine??? Ich glaub das war jetzt ziemlich verkorkst erklärt. Das CR und LF hab ich abgestellt, ist ja eigentlich überflüssig wenn man pro paket nur einen wert hat.

PicNick
24.05.2005, 13:44
Na ja, zwei Möglichkeiten:

Vielleicht kann man dem VB einen größeren Buffer angeben (ich kenn aber VB zu wenig)

Oder du pollst. d.h.

Der AVR schreibt seine Werte ganz einfach in ein jeweiliges (Sensor)-Feld und sonst nix
Und der VB sendet, wenn er grad Zeit hat, an den Avr zB ein "A", worauf der AVR den Wert, den "A" grad hat, auf die Reise schickt und dann wieder weiter wurstelt, bis z.B. "B" kommt

Ja, noch eine Variante (on demand): Erst wenn "A" kommt, macht der AVR den Getadc() und schickt den Wert dann
(schneller als es der VB bearbeiten kann, braucht er's ja eh nicht messen)