PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Inline Assembler



Che Guevara
27.01.2010, 18:46
Hallo liebe Leute,

nach einer Weile des grübelns und überlegens hab ich mich dazu entschieden, ein bischen Assembler zu "lernen".
So weit, so gut.
Allerdings macht mir mein erstes Programm schon Probleme :-(
Hier mal der Code:


$regfile = "m32def.dat"
$crystal = 16000000
$framesize = 30
$hwstack = 30
$swstack = 30

$asm

ldi r16, 0xFF
Out Ddrc , R16

ldi r16, 0b11110000
Out Portc , R16

Lop:

rjmp lop

$end Asm

End


Nach meinem Verständnis sollten jetzt ja 4 leds leuchten und die anderen 4 nicht. Jedoch leuchtet keine!

Hier mal der Code, der meiner Meinung nach genau das selbe macht:


$regfile = "m32def.dat"
$crystal = 16000000
$framesize = 30
$hwstack = 30
$swstack = 30

DDRC = 255

PORTC = &b11110000

Do

Loop

End


Dieser Code funktioniert.
Könnt ihr mir sagen, wo mein Fehler ist?

Vielen Dank
Gruß
Chris

peterfido
27.01.2010, 21:18
Versuch mal die Schreibweise des Wertes zu ändern:


$regfile = "m32def.dat"
$crystal = 16000000
$framesize = 30
$hwstack = 30
$swstack = 30

$asm

ldi r16, &hFF
Out Ddrc , R16

ldi r16, &b11110000
Out Portc , R16

Lop:

rjmp lop

$end Asm

End

Che Guevara
27.01.2010, 21:47
Hallo peterfido,

vielen dank, jetzt funzts :-)

Aber kannst du mir erklären, warum das so gemacht werden muss??

Gruß
Chris

Mitch64
28.01.2010, 05:31
Hallo,

das DDRC bestimmt welche Ports am Port C als Eingänge und welche als Ausgänge verwendet werden sollen. Erst wenn man dann auf den Port schreibt, steht ein Wert an.

In Deinem Fall waren die Port-Ausgänge auf Low nachdem das DDRC gesetzt wurde. Deine LED's sind vermutlich vom Port über Vorwiderstand auf Masse geschaltet.

Mitch.

PicNick
28.01.2010, 08:31
Hi, Che !
vielleicht magst du gucken :
http://www.rn-wissen.de/index.php/Assembler_Einf%C3%BChrung_f%C3%BCr_Bascom-User

Che Guevara
28.01.2010, 15:16
Vielen Dank für eure Antworten,

aber ich meinte eigentlich, worin der Unterschied besteht, wenn ich astatt


0xFF


dieses schreibe:


&hFF

??

Das sind doch eigentlich die gleichen Werte, oder nicht?

Gruß
Chris

PicNick
28.01.2010, 15:21
"&H" ist das, was Bascom versteht, "0x" ist was für "C" und diverse andere Sprachen.
Da is wohl noch jeder schon mal ins Schleudern gekommen *g*

Che Guevara
28.01.2010, 21:07
Vielen Dank, jetzt weis ich das auch :-)

Jetzt habe ich aber wieder mal eine Frage:
Mit folgendem Code möchte ich bei Tastendruck (Pina.0) eine Led an Portc.0 toggeln.
Allerdings wird diese nicht getoggelt, sondern sie leuchtet nur solange, solange ich den Taster drücke.
Hier der Code:


$regfile = "m32def.dat"
$crystal = 16000000
$framesize = 30
$hwstack = 30
$swstack = 30

$asm

.def Null = R20
.def Eins = R21
.def K = R22
.def I = R23
.def J = R24

ldi null, &b00000000
ldi eins, &b11111111

ldi r16, &b11111111
Out Ddrc , R16

ldi r16, &b00000000
Out Ddra , R16

ldi r16, &b11111111
Out Portc , R16

ldi r16, &b11111111
Out Porta , R16


Lop:

sbis pina , 0
rjmp taster_an

rjmp lop


Taster_an:
ldi r16, &b00000000
sbis pinc , 0
ldi r16, &b11111111
cpi r16 , &b00000000
breq led_ein
sbi portc,0
rjmp ende_taster_an
Led_ein:
cbi portc,0
Ende_taster_an:
'rcall wait
ret

Wait:
ldi k,10
loop_k:
nop
nop
dec k
cpi k,0xFF
brne loop_k
dec j
cpi j,0xFF
brne Wait
dec i
cpi i,0xFF
brne Wait
ret

$end Asm

End


Warum wird die Led immer wieder ausgeschaltet (also 0 = ein und 1 = aus)??

Gruß
Chris

peterfido
28.01.2010, 22:36
Du setzt r16 auf 1 und vergleichst im nächsten Schritt auf 0.. Das Ergebnis wird immer 1 sein...
Hier mal ein Wechsellicht zwischen PortD 5 und PortD 6. Der Taster liegt auf PinD2, Pulldown, geschlossen auf High:




$regfile = "m32def.dat"
$crystal = 8000000
$framesize = 30
$hwstack = 30
$swstack = 30

$asm


ldi r16, &b01100000
Out Ddrd , R16
ldi r16, &b01000000
Out Portd , R16

Lop:
sbic Pind , 2
rcall Invled
rjmp lop
Invled:
ldi r16, &b00100000
sbis pind,6
ldi r16, &b01000000
Out Portd , R16
Loslassen:
sbic pind,2
rjmp Loslassen
ret
$end Asm

End

Che Guevara
31.01.2010, 18:10
Hallo Leute,

erstmal vielen Dank für eure Antworten.
Aber ich hab mich grad soooo stark aufgeregt!

Der einzige Fehler in meinem Programm ist der, dass ich im Mainloop (lop)


Lop:
sbis pina , 0
rjmp taster_an
rjmp lop


anstatt



Lop:
sbis pina , 0
rcall taster_an
rjmp lop


geschrieben habe.
Der einzige Fehler war also das "RJMP" ...
Kann mir jemand erklären, warum ich hier "RCALL" benutzen muss??

Gruß
Chris

Besserwessi
31.01.2010, 18:21
Der RJMP ist ein einfacher Sprung, ohne Rückkehr.
RCall ist dagegen der Aufruf eines Unterprogramms, so dass man per RET auch wieder zurückkommt.
Das enspricht ziehmlich 1:1 den Basic Befehlen Goto und Gosub.

peterfido
31.01.2010, 18:31
Hm war mir gar nicht aufgefallen. Natürlich musst Du ein RCALL einsetzen. Da wird ja dann die Adresse auf dem Stack abgelegt, wo nach dem RET wieder zurückgesprungen werden soll. Ein relativer Sprung springt ja nur und merkt sich, lapidar gesagt, nicht, wo er her kommt. Trotz dem meine ich, dass Du in R16 eine 255 schreibst und im nächsten Schritt mit 0 vergleichst. Oder sollte ich mich da irren.

Allerdings finde ich, dass Deine Fragen eher Off Topic sind und in den ASM Bereich sollten. Da kennen sich bestimmt mehr Leute mit aus als hier. Ich selbst progge hauptsächlich in Hochsprachen und nutze nur für Zeitkritisches oder Platzkritisches Inline ASM. Habe also eher wenig Erfahrung und sehe so gut wie jedesmal neu im Datenblatt nach, wie die Befehle zu nutzen sind...

Che Guevara
31.01.2010, 20:24
So... jetzt hab ich das nächste Problem, welches diesmal wirklich mit Bascom zu tun hat ;-)
Ich habe die Demoversion (V: 1.11.9.5). Wenn ich folgenden Code compilieren möchte, dann kommt eine Fehlermeldung.


$regfile = "m32def.dat"
$crystal = 16000000
$framesize = 30
$hwstack = 30
$swstack = 30

$asm

.def Temp = R16

.def A = R17

.org $000 Rjmp Main

.org $002 Rjmp Int0_handler


Main:

ldi temp, &b11111111
Out Ddrc , Temp

ldi temp, &b00000000
Out Ddrd , Temp

ldi temp, &b11111110
Out Portc , Temp

ldi temp, &b11111111
Out Portd , Temp

ldi a,&b00000011
Out Mcucr , A

ldi a,&b01000000
Out Gimsk , A

sei 'interrupts allgemein aktivieren (enable interrupts)



Lop:

nop

rjmp lop

Int0_handler:
sbi portc , 0
reti

$end Asm

End

Folgende Meldung kommt dann:


Access violation at address 0024572E in module 'BASC-AVR.DLL'. Write of address 05BF1000.

Wenn ich allerdings das


.org $000 RJMP Main

rausnehme, dann kommt die Meldung nicht.
An was liegt das?
Und stimmt mein Programm ansonsten (also INT0 auf fallende Flanke)??

Gruß
Chris

Mitch64
31.01.2010, 22:24
Hallo,

ich Progge viel mit Bascom und verwende auch viel den Inline-Assembler.
Bei deinem Code fällt mir auf, dass du alles in Assembler schreiben willst, auch die Interrupt-Vector Tabelle.

Bascom ist eigentlich ausgelegt um in Basic zu proggen. Natürlich kann man auch vieles in Assembler machen, aber Interrupt-Vectortabelle erstellen geht nicht.

Auch Befehle wie .org .data .eep etc geht nicht.

Wenn du in reinem Assembler Proggen willst, dann nimm besser AVR-Studio.

Das Assembler in Basom ist als Inline-Assembler gedacht.

Interrupts sollten deshalb besser mit Bascom-Statements configuriert werden. Das Spart Zeit und man behält die Übersicht. Korzer wird der Code nicht in Assembler.

Wenn du mit Bascom Assembler lernen willst, dann versuche dich anfangs auf einzelne Routinen zu konzentrieren. Deine versuchte Initialisierung sieht sehr nach AVR-Studio aus. In Bascom wird das nur bedingt compiliert und vermutlich nicht funktionieren.

Wenn du trotzdem in dieser Richtung experimentieren willst, dann schau dir mal die Befehle der Bascom Hilfe an. Z.B. $NoInit, $NoRam, $Initmicro, $Loader, $Loadersize, NoRamclear, $RomStart und so weiter an. Da findest du viele Hinweise. Dann wird für dich bestimmt vieles klarer.

Che Guevara
01.02.2010, 16:57
Hallo Mitch64,

erstmal danke für deine Antwort.
An AVR-Studio hab ich auch schon gedacht, jedoch hab ich keine Seite gefunden, auf der man das downloaden kann (bzw. ich weiß nicht, welche Datei ich brauche, weil teils französisch). Außerdem bin ich mir nicht sicher, ob das auch mit dem USB-ISP (von robotikhardware) funzt??

Gruß
Chris

Mitch64
01.02.2010, 17:29
Hallo,

das AVR-Studio gibts kostenlos direkt bei www.atmel.com. Das ist der Hersteller dieser Controller. Ob das mit deinem USB-Programmer funktioniert kann ich dir nicht sagen. Muste in der Doku schauen von Studio.

Alternativ brennste das hex eben mit Bascom, das geht auch.

sechsrad
01.02.2010, 19:25
lies das hier :

http://www.rn-wissen.de/index.php/Bascom_Inside-Code