PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Bascom-Bytevariable in ein Register laden



tobimc
29.08.2005, 09:20
HI!

Ich möchte eine 0815-Bytevariable aus Bascom in ein Register (R0 - R31, bzw. von R16 - R28) laden, um sie mit ASM weiterverarbeiten zu können.
Das Laden sollte möglichst schnell gehen...

Gaht das überhaupt, oder...?

Danke schonmal!

VLG Tobi

oe9vfj
29.08.2005, 11:01
Das geht folgendermaßen:

lds r24, {Variablenname}

für z.B. für eine Byte-Variable in das Register r24.


Für Word könnte man verwenden

lds r24, {WordVariable}
lds r25, {WordVariable+1}


Für Long ist folgende Variante kürzer:

loadadr VariablenName, X ' Adresse in X laden
ld r20, X+
ld r21, X+
ld r22, X+
ld r23, X+

loadadr ist eine BASCOM-Funktion, welche benötigt wird, um die von BASCOM vergebene Adresse für eine Variable in ein Pointer-Registerpaar X (r26,r27) oder Z (r30,r31) zu laden. Y (r28,r29) darf nicht verwendet werden, da hier BASCOM den Soft-Stack verwaltet.

Wieso Du in Deinem Post r16 bis r28 noch einmal erwähnst, da diese ja schon in R0 - r31 enthalten sind, ist mir nicht klar?

tobimc
29.08.2005, 11:37
Hi!

Danke!
Ich wollte eigentlich R16 bis R26 sasgen, weil ja Bascom damit die Speicher anspricht.
(Da wollte ich nicht stören... :D)

Die geschweiften Klammern muss man also auch setzen... da bin ich erst drauf reingefallen... :D

Danke!

VLG Tobi

PicNick
29.08.2005, 15:25
Ganz gemeine Leute nehmen auch
INP adr, val oder
OUT adr, val
z.B.
OUT &h10 , 255 ' schreibt FF ins Register 16
byteval = INP( &h10 ) ' liest das dann.

Ähnlich wie Peek & Poke

tobimc
29.08.2005, 16:07
Hi!

LDS ist genau das, was ich brauche.
Wen wir schon bei ASM sind.
Ich bräuchte eine Möglichkeit, wie ich möglichst schnell die Variable in R16 oder in welchem R auch immer an verschiedene Pins verteilen.
Also z.B. R16.0 -> Portd.4 ; R16.1 -> Portc.3 usw.
Lässt sich das halbwegs bewerkstelligen?
Ich galube, dass mein Bascom-Code dazu etwas langsam ist...
Das ganze sollte nach Möglichkeit auch rückwärts funktionieren...

Danke!

VLG Tobi

PicNick
29.08.2005, 16:43
@TObi: kommt auch drauf an, wie du die tabelle dazu gedacht oder gegeben hast.
Das CPU-mäßig schnellste wäre ein stück assembler-spaghetti code, der gleichzeitig das Mapping bildet


CBI PORTD, 4 ; outpin löschen
SBRC R16, 0 ; nächsten Befehl überspringen, wenn das bit = 0
SBI PORTD, 4 ; sonst outpin setzen
..
CBI PORTC, 3
SBRC R16, 1
SBI PORTC, 3
..
CBI PORTx, n
SBRC R16, 7
SBI PORTx, n

Zyklenmäßich ist das recht flott. Bei jeder Schleifenkonstruktion brauchst du ein vielfaches

Ich weiß auch, daß das saumäßig auschaut

tobimc
29.08.2005, 16:54
Hi!

Das hat mit dem RAM-Zugriff zu tun, das wird pro Durchlauf etwa 16000 mal aufgerufen. wenn das also schnell ist, dann ist schon Zeit gespart...

Hm. Nur zum codeverständnis:
Du löschst (=0) zuerst den Pin.
dann fragst du den Status des Bits ab.
Wenn der 1 ist, dann führst du die nächste anweisung aus,
wenn nicht, dann nicht, oder wie?

Danke!

VLG Tobi

PicNick
29.08.2005, 17:12
Ja, genau so.
SBI u. CBI haben jeweils 2 Cycles,
SBRC hat 1 oder 2 (ohne skip / mit skip)
d.h Je Bit (also 8 mal)
ist das R16 bit = 0, brauchst du 4 Cyklen,
ist das R16 bit = 1, brauchst du 5 Cyklen
also minimal 32 Cyklen (alles Null)
maximal 40 Cyklen (alles Eins)

bei 8 MHZ also ca 4 - 5 uS

Schneller wird's nicht gehen, denk' ich. (Vorschläge werden aber gerne angenommen)


Edit: wer nicht schreiben kann, soll's bleiben lassen :oops:

tobimc
29.08.2005, 17:19
Hi!

Sehr sehr schön!
Danke!

Habe 16MHz... :D

Werd' das demnächst mal einbauen.

Hm habe gerade einen chronischen Absturz (habe ihm glaub ich ne Wordvariable zu viel verpasst...)Naja, das ist das erst mal, dass ich nen AVR zum abstürzen gebracht habe... :D )

Sothen, Danke an alle Beteiligten, ihr habt mir sehr geholfen!

VLG Tobi

tobimc
16.09.2005, 19:51
Hi!

Da gibts jetzt nur ein kleines Problem...:

$asm
lds R30, {value}
......
Das gibt dann einen
Error 5,..., No space for BIT [valaue]
Alle Register voll, oder wie...?? (wär nicht so gut...)

VLG Tobi

oe9vfj
16.09.2005, 21:42
This is not a register problem. I get this problem, if the name of the variable in the brackets {} is wrong.
In your case, do you dimmed a variable with name valaue as shown in the error message, or is there a typing error of valaue instead of value

tobimc
17.09.2005, 10:21
HI!

Hm. The variable I use is a byval-Variable of a function.
It is just like that:


Function Laybus(byval Value As Byte)

'Variable In Register Kopieren:
$asm
lds R32, {Value}

CBI PORTC, 3
SBRC R1, 0
SBI PORTC, 3



$end Asm


End Function

The error message (spelling-corrected... :D ):
Error: 5 Line: 884 No more space for BIT [VALUE] , in File.....

Isn't ist possible, that there is no farther space?

VLG Tobi

oe9vfj
17.09.2005, 10:37
Hi,

there is no register r32 (r0 to r31).

You can not use the syntax

lds r31, {value}

for a function/sub parameter or local variable. The address of a parameter or local variable is not known at compile time, so no SRAM address can be generated for {value}. Only the addresses of global variables are known at compile time and can be used with this syntax.


You can work with following way:

loadadr value, X
ld r24, X

loadadr can get the address of parameter/locals from the soft-stack, where the addresses of parameters and local variables are stored at runtime

tobimc
17.09.2005, 10:57
AH!

Yes thanks! Now it works!

Thank you!

best regards,
Tobi

tobimc
17.09.2005, 11:16
Hi!

I have one more question about that...

How can I load a register (R16) to my Value-Variable?
ld X, r16??
I don't think...

VLG Tobi

oe9vfj
17.09.2005, 12:01
Hallo Tobi,

ich habe gerade eben gemerkt, dass ich da in einem Post auf Englisch geantwortet habe. Das ist wahrscheinlich passiert, als ich auch gleichzeitig das Forum auf http://www.mcselec.com/forum offen hatte in Kombination mit der englischen Fehlermeldung in Deinem Post. Ich bitte um Vergebung, falls sich da jemand daran gestört hat.

Der Umkehrbefehl ist:

st X, r16

Wenn Du Dich etwas weiter in ASM-Programmierung vertiefen willst, empfehle ich Dir, die ASM-Befehlsbeschreibung von ATMEL http://www.atmel.com/dyn/resources/prod_documents/DOC0856.PDF herunterzuladen und Dir mal die möglichen Befehle anzuschauen.
Weiters ist in jedem Datenblatt zu den AVR ziemlich hinten eine Auflistung der Befehle, welche dieser Prozessor beherrscht mit einem Hinweis, was dieser macht. Damit hast schon die Grundlagen für die ASM-Programmierung.

tobimc
17.09.2005, 14:11
HI!

Ich hab mir schon überlegt, ob ich dich fragen soll, ob es da vllt. Login-Probleme gibt...

ah.. st store.. danke ;D
danke für den Tip, mein ASM reicht gerade mal zum Ports ein und ausschalten... :D

Englisch stört mich generell nie, da muss man mal den Grips anstrengen!

Danke dann nochmal!

VLG Tobi

tobimc
17.09.2005, 16:00
Hi!

Da das mit dem Schreiben so gut klappt, habe ich das gleich mal auch mit dem Lesen versucht.

Folgender Code...:


Function Readbus() 'Den Wert vom Bus lesen
Dim Value As Byte

Ddrb = &B00000000 'Alles Eingänge
Ddrc = &B11111100 'Umschaltung, dass es keine Crashes gibt.

$asm

in R17, pinc


CBR R16, 0b00000001
SBRC R17, 1
SBR R16, 0b00000001

CBR R16, 0b00000010
SBRC R17,0
SBR R16, 0b00000010

in R17, pinb


CBR R16, 0b00000100
SBRC R17, 5
SBR R16, 0b00000100

CBR R16, 0b00001000
SBRC R17, 4
SBR R16, 0b00001000

CBR R16, 0b00010000
SBRC R17, 3
SBR R16, 0b00010000

CBR R16, 0b00100000
SBRC R17, 2
SBR R16, 0b00100000

CBR R16, 0b01000000
SBRC R17, 1
SBR R16, 0b01000000

CBR R16, 0b10000000
SBRC R17, 0
SBR R16, 0b10000000

Loadadr Value , X
st X, r16

$end Asm

Readbus = Value

End Function


Compiler schluckt's, liefert aber nur Datenmüll.

Ich habe ja den verdacht, dass ich vlaue diesmal mit einer lds(nur andersherum) ähnlcihen funktion laden muss, oder?

Nochmal Danke!

VLG Tobi

pebisoft
17.09.2005, 16:31
hallo tobi, warum nimmst du die langsame "funktion".
nimm eine "sub" die ist etwas schneller. nimm ein "goto" und das ist noch schneller. wenn du mit ein varptr die sram-adresse einer variable erfragst, bekommst du die variable am schnellsten über die direkte adressenanfrage.
habe ich mit fastavr-basic herausbekommen, wo ich mir den asm-source-code
angeschaut habe.
mfg pebisoft

oe9vfj
17.09.2005, 16:56
Ich nehme mal an, dass diese Funktion irgendwo mit

Declare Function ReadBus () as Byte

deklariert ist.

Warum Du das B-Port mit
Ddrb = &B00000000 auf Input stellst, ist nicht ersichtlich. Das C-Port wird mit
Ddrc = &B11111100 für die Pins 2-7 auf Output und die Pins 0-1 auf Input gestellt.
Im nachfolgenden Code scheinst aber alle 8 vom Port C eingelesenen Bits auszuwerten.

Und nun zu Deiner eigentlichen Fragestellung.
Einen Funktionswert kann Du auf folgende Weise:

loadadr readbus, X
st X, r16

zurückgeben. Das obige Beispiel ist für den Fall, dass ReadBus einen Rückgabewert vom Type BYTE hat.
Du kannst den Funktionsnamen wie einen Variablennamen mit loadadr verwenden.

Ich gehe mal davon aus, dass diese Funktion primär einen experimentellen Charakter hat, um diverse Möglichkeiten zu testen. Befasse Dich mal mit dem BASCOM Simulator, damit kannst Du Schritt für Schritt verfolgen, was in den einzelnen Registern und Speicherstellen passiert. Damit kannst Du nach herzenslust experimentieren, weil Du auch während der Simulation die Input-Pins im Pegel verändern kannst.

tobimc
17.09.2005, 19:13
Hi Danke!

Nach 2 Bits wird in R17 pinb eingelesen, deshalb wird es auf input umgestellt.
Dann brauch ich die temporäre Variable garnicht? COOL!

Da das Programm auf die hardware geschrieben ist, kann ich den Sinulator nicht verwenden... :( ...

VLG Tobi

tobimc
17.09.2005, 19:21
Hi!


Function Readbus() 'Den Wert vom Bus lesen

Ddrb = &B00000000 'Alles Eingänge
Ddrc = &B11111100 'Umschaltung, dass es keine Crashes gibt.

$asm

in R17, pinc


CBR R16, 0b00000001
SBRC R17, 1
SBR R16, 0b00000001

CBR R16, 0b00000010
SBRC R17,0
SBR R16, 0b00000010

in R17, pinb ;<-- HIER wird auf Pinb umgeschaltet!


CBR R16, 0b00000100
SBRC R17, 5
SBR R16, 0b00000100

CBR R16, 0b00001000
SBRC R17, 4
SBR R16, 0b00001000

CBR R16, 0b00010000
SBRC R17, 3
SBR R16, 0b00010000

CBR R16, 0b00100000
SBRC R17, 2
SBR R16, 0b00100000

CBR R16, 0b01000000
SBRC R17, 1
SBR R16, 0b01000000

CBR R16, 0b10000000
SBRC R17, 0
SBR R16, 0b10000000

Loadadr Readbus , X
st X, r16

$end Asm

End Function
Das ist jetzt mein Code, aber der liefert nur Datenmüll......

Was geht da schief?!
Die Bits in der Maske werden schon so gezählt, gell:
0b76543210
und NICHT
0b01234567
,gell??

Naja, das würde bei meinem Monsterprogramm nochmal 0,8 Sec einspahrung bringen, wenn man das in ASM codet... :D

VLG Tobi

oe9vfj
17.09.2005, 23:05
Hallo Tobi,

das mit dem PinB einlesen habe ich übersehen.
Die Bit-Zählweise ist so wie Du beschrieben hast &B76543210

Wenn ich das richtig sehe werden in dem Ablauf alle Bits des r16 gelöscht.
Das kannst zu Beginn mit clr r16 machen und Du brauchst nicht 8 mal cbr r16,x.

Überprüf mal ob Du wirklich folgende Umsetzung von den Pins in das r16 vorgesehen hast?

pinc.1 -> r16.0
pinc.0 -> r16.1
pinb.5 -> r16.2
pinb.4 -> r16.3
pinb.3 -> r16.4
pinb.2 -> r16.5
pinb.1 -> r16.6
pinb.0 -> r16.7

Ich hab mal irgendwo gelesen (kann Dir aber jetzt nicht sagen wo das war), dass man nicht sofort nach einer Änderung an einem Port von dort Werte einlesen kann. Wird auf ein Port geschrieben, in Deinem Fall auf das DDRB und DDRC so kommt die Änderung mit Beginn des nächsten CPU-Takts (=ASM-Befehl) zum Tragen. Wird von einem Pin eingelesen, wird der Zustand vom Ende des vorhergehenden CPU-Takt ausgewertet. Es könnte also sein, dass Du auf ein
Ddrc = &B11111100
nicht sofort im nächsten Befehl mit
in r17, PinC
fortsetzen kannst.

Mit
ddrc = &B11111100
ddrb = &B00000000
clr r16
in r17, pinc

bekommst Du zwischen dem C-Port setzen und Einlesen schon mal 3 CPU-Takte.
Ich hoffe ich konnte Dir weiterhelfen.

pebisoft
17.09.2005, 23:14
"ldi r16,&b00000000"
werden die bytes nicht so geschrieben in bascom: &b00001111
denkt dran: &b..........
mfg pebisoft

oe9vfj
18.09.2005, 07:54
Hallo Tobi,

Du musst &B00000001 anstatt 0B00000001 verwenden.

0B....... wird immer zu 0 übersetzt.

cbr r16,0b00000001 wird daher zu
cbr r16,&B00000000 und damit nirgends das Bit gelöscht.

pebisoft
18.09.2005, 09:02
ihr müsst ruhiger werden und nicht so hudeln.
den text gaaaaaanz.... laaaaangsam... durchlesen.
wenn ihr mal in winavr-c proggen tut, müsst ihr noch besser aufpassen.
mfg pebisoft

tobimc
18.09.2005, 10:24
HI!

ASO!
Ich dachte, weil das ASM ist muss man die ASM-Schreibweise verwenden... :D

Dann haben wir den Übeltäter ja auch schon. Werd ich gleich mal testen.

CLR R16... das ist sehr praktisch! Das ist ja dann noch schneller! *freu*

@pebi: Mit dem Unterschied, dass die Maske in C warscheinlich richtig gewesen wäre...

Ich teste...

VLG Tobi

tobimc
18.09.2005, 10:48
Hi!

Also! ES FUNKTIONIERT!
Die Busfunktionen (pebisoft, wenn du willst bekommst du sie, sind viel schneller als die alten!!)

Mein 1243 Zeilen langer Code (wer hat jetzt auch geschrieben, man würde in nen MEGA32 nichts hineinbringen?? Und ich verwende einen M8...) läuft mit der ASM-Routine 1,4 Sekunden schneller!!!

VLG
Tobi