Hi.
Ich Programmiere grad was größeres in Assembler.
Plötzlich habe ich nun ein Problem mit einem Call / Ret Befehl!
Nach dem Befehl jnb P1.1,prog2 springt er ja unten zu "prog2" (Wenn
das Bit auf 0 ist). "prog2: call pro2" Dieser Befehl springt ja dann
zu meinem Programm. Am Ende dieses Programmes habe ich "ret" stehen.
Problem dabei: Er springt nach dem ret nicht in die Zeile des
Call-Befehles zurück sondern Ôô springt zu meiner Startsprungmarke!
Ich benutze Keil µV3 und den Controller Infineon 80c535 N
Das seltsame ist, dass bei jedem call- und ret-Befehl alles gut
funktioniert. Es werden manche Unterprogramme noch min20 mal aufgerufen
und es geht immer. nur hier nun nicht. was könnte das für Ursachen
haben?
1
Start: ; Startsprungmarke, Anfang des Programmes
2
jnb P1.1,prog2 ; Springt wenn P1.1 auf 0 gesetzt zu prog2
3
call pro1 ; Aufruf von Programm 1
4
jmp Start ; Sprung zurück zum Programmstart
5
star1: jnb P1.2,prog3 ; Springt wenn P1.2 auf 0 gesetzt zu prog3
6
jnb P1.3,prog4 ; Springt wenn P1.3 auf 0 gesetzt zu prog4
7
jnb P1.4,prog5 ; Springt wenn P1.4 auf 0 gesetzt zu prog5
8
jnb P1.5,prog6 ; Springt wenn P1.5 auf 0 gesetzt zu prog6
9
jnb P1.6,prog7 ; Springt wenn P1.6 auf 0 gesetzt zu prog7
10
jnb P1.7,prog8 ; Springt wenn P1.7 auf 0 gesetzt zu prog8
Oje Kann es auch daher kommen, dass ich ion den Jeweilig aufgerufenen
programmen den Call verschachtelt habe, also ein weiteres Unterprogramm
(z.B. ne Zeitschleife) aufrufe?
Das ist der Fall. Aber dann wird das Problem in allen Programmteilen
auftreten. bis jetzt kommts ja nicht weiter wie Prog 1 und 2.
Mein Prob dann is nur, wie komme ich zu meinen Programmen, wenn ein
einfacher jmp Befehl von der entfernung (Prog hat knapp 900 Zeilen)
nicht geht und ein Call-Befehl nicht verschachtelt werden kann?
MfG T-G-läser
Calls können sehr wohl verschachtelt sein, es muß nur zu jedem CALL ein
RET gehören.
Du wirst also irgendwo ein RET zuviel haben und das lädt dann den
Inhalt von R6,R7 in den PC (wenn SP auf 007h steht).
@Tobias,
das sind JMP-Befehle, je nach Sprungdistanz.
Peter
Stackinitialisierung? wofür benötige ich diese? Und wie mache ich diese
mit reinem Assembler?
Ich habe nun das Programm bisschen abgeändert, da ich kein weiteres ret
gefunden habe (thx Peter).
Start: jnb P1.1,prog2
call loop
mov P4,#01010101b
mov P5,#01010101b
call loop
mov P4,#10101010b
mov P5,#10101010b
jmp Start
star1: jnb P1.2,prog3
jnb P1.3,prog4
jnb P1.4,prog5
jnb P1.5,prog6
jnb P1.6,prog7
jnb P1.7,prog8
ljmp pro1
prog2: ljmp pro2
prog3: ljmp pro3
prog4: ljmp pro4
prog5: ljmp pro5
prog6: ljmp pro6
prog7: ljmp pro7
prog8: ljmp pro8
Die Rücksprünge der Programme 1,3-8 erfolgen über "ljmp star1"
Der Rücksprung des Programmes 2 erfolgt über "ljmp Start"
Das funktioniert nun alles wie erwünscht =)
Autsch.
Das Thema solltest du dir zu Gemüte führen. Die Stackinitialisierung
legt fest wo im SRAM dein Stack liegt. Im Klartext: initialieren den
Stackpointer.
Steht auch hier:
http://www.mikrocontroller.net/articles/AVR_Checkliste
Gruß Andreas
Ich glaube nun dass ich meine call und ret nicht richtig verschachteln
konnte, weil ich übergreifend in den Programmen den Stackpointer
benutzt habe.
Ich wusste nicht dass call ebenfalls die adr im Stack speichert. Habe
ich mir keine Gedanken darüber gemacht
MfG T-G-läser
@Baitronic,
schaut auch er über seinen Tellerrand, sieht er in der Überschrift
>>>>> AVR Checkliste <<<<<
Wir reden hier von einem 8051 ér !!!
Der hat nach einschalten bereits 07h im SP !!!
Ohne Interrupts reicht das völlig !!!!!
............oh du schöner 51er !!!!
Danke @ Wolfram und Baitronic
Jedoch ist mein internes RAM randvoll und ich hab ja nen ganz anderen
Controller-Typ.
kann ich auch eine Adresse im externen RAM bei ca. 4100h wählen? wenn
ja wie?
Hmmmm Macht Sinn @ Stephan.
Was hat es jedoch mit den genannten 07h auf sich?
Mein internes RAM is nun im mom von 0h bis 87h komplett belegt, jedoch
brauch ich davon sogar noch etwas mehr... Wied einer dieser Bereiche
etwa schon von einem anderem Teil des µ-Controllers verwendet oder habe
ich den Platz sicher frei?
Ich habe eben bisher nur in einer Simulation gearbeitet, da die
Zusatzplatinen meines µ-Controller-Boards noch nicht fertig sind.
moin moin,
Tobias, Du solltest Dich unbedingt mit den Grundlagen des 8051
befassen. Direkte Probleme und Fragen zum nachlesen hast Du ja jede
Menge.
In Deinem Prog ist ein Call loop drin, das überschreibt den Inhalt von
RAM 8+9.
Wenn Du in die Doku zum 8051 siehst, den Stack kannst Du z.B. mit
mov sp,#160 weit nach hinten legen. In Deinem Prog kannst nun rumkallen
ohne unerklärliche Sachen zu bekommen.
Der 80C535 hat ein externes EPROM, da kann leich ein RAM mit
angefrickelt werden. Wie? Steht auch in der Doku.
Oder nimmst gleich einen mit interen FlashROM und XRAM z.B. 89C5152ED2,
89C5131A, 89C51RC2.
Na ja, vor 20 Jahren habe ich auch solche Fragen gestellt. Nur damals
gabs noch kein Internet. Da blieb nur der Gang in die nächste Bibliotek
und ein passendes Buch ausleihen....
Mit Gruß
Pieter
Ups !!!!
ab 80h fangen doch die SFR an !!!! Ab da gehts nur mit MOVx !!!
Nich das da noch was passiert !!
Was den SP angeht.... Wie gesagt der steht nach dem internen Reset den
die MCU macht immer auf 07H. Ab dort wird im RAM zB. das PSW bei einem
CALL abgelegt und nach RET wieder geholt. Aber auf zB 0Bh leigt der
Einsprung für Timer 0 Int. Daher legt man den SP so ab 20h aufwärts
sofern man mit ISR ( Interrupt Service Routine ) arbeitet.
Was machst du denn mit dem RAM ???
Ich glaube du hast na nen Denkfehler!
externes RAM.:
zB. MOV DPTR,#4100h
MOVX A,@DPTR
alles klar ???
"weil ich übergreifend in den Programmen den Stackpointer benutzt
habe."
Dafür gibts knallhart die rote Karte !
Als Anfänger darf man den Stackpointer nur ein einziges mal anfassen
und zwar bei der Initialisierung, danach gehört er ganz und gar der CPU
bis zum Abschalten !
Sinnvoll ist es bei 8052-ern den SP in den indirekten SRAM (080h..0FFh)
zu legen, minimal 16 Byte groß, also nicht über 0EFh.
Zum indirekten Zugriff auf Daten hat man schließlich seine 8
Pointerregister (R0,R1 in Bank 0..3).
Nachm Reset ist SP = 07h, d.h. ab 10h wird gepusht, solange man SP
nicht anders initialisiert.
Peter
@Peter,
Du bist ja grausam als Lehrer !!!! :-))
Aber vielleicht besser so als wenn sich gleich am Anfang Unarten
einschleichen. Wobei ich nicht in die oberen 128 gehen würde.
Wenn er mal nen anderen 8051 nimmt...... und nicht dran denkt...
moin moin,
@Stephan
Du bist ja grausam als Lehrer !!!! :-))
... und aus "meinen" Azubis ist immer was geworden...
Mein USB-89C5131 läuft soweit auch schon.
Nachtrag zum RAM (und wieder mal ein Blick in die Doku...;-)
00..7F RAM direkt
80..FF SFR direkt UND 80..FF RAM indirekt mit @Rn
00..FFFF RAM extern mit movx
es gibt z.B. die RAM Zelle 80H gleich 3 mal unter der selben Adresse.
===========
StackPointer:
So wie der andere Peter sagt: EINMAL einstellen und vergessen.
>>Nachm Reset ist SP = 07h, d.h. ab 10h wird gepusht
Einspruch Euer Ehren, der 1. Push geht auf die 8.
Mit Gruß
Pieter
uiuiuiuiuiui!!!!
Also erstma thx....!
Dad gibt nu riesen Arbeit glaub ich.
Es werden nämlich unmengen von Daten, die ich über einen AD-Wandler
einlese (Abstandssensor unlinear für ein Projekt) im Internen RAM
gespeichert. Ich benutze ein Board wo ein externes RAM dabei ist. da
habe ich sogar etwa 200h frei (4000h-41FFh).
Jedoch habe ich nun wohl noch ne ewigkeit zu tun, diese gesamten
Befehle im gesamten Prog (mittlerweile über 900 Zeilen) zu ersetzen
fg
MOV DPTR,#4000h ; Is ja nun frei bis 41FFh
MOVX A,@DPTR ; Ram in Akku laden
und andersrum
MOV DPTR,#4000h ; Is ja nun frei bis 41FFh
MOVX @DPTR,A ; Akku in Ram laden
oda wie? (und das sind jeweils auch 8 Bit?^^)
MfG T-G-läser
Hallo Pieter
Du hast doch gar keine rote gegeben !!!!
Hast Du nen Moment ??? Im progr. Logik Abteil ist jemand mit C code der
compiliert werden muß. Kannst Du ihm helfen ???
Habe keinen Compiler !!!
An meinem ED2 ist jetzt nen LTC1093 dran. Interesse ??
machs gut
High Stephan
och nee, keine Rote Karte, Tobias soll ja am Ball bleiben und nicht
duschen gehen...
- LTC1093 macht "nur" 10Bit.
- 89C51ED gibs bei Angelika wieder als DIL40.
Derzeit einen Testaufbau:
1.Transverter 5/12 + Optokoppler für seriell
2.89C2051 zur Umsetzung
3. MAX186/LTC1446 auf einem DIL24 Modul
Das ganze Modul liefert potentialgetrennte 12Bit AD/DA mit -1/+5/+11V.
@Tobias
Tip:Zeilen ersetzen mit Copy&Paste
Unmengen an Daten und 512Byte RAM?
Bei einem Temperaturlogger (89C2051+DS18S20) habe ich die Daten (pro
Minute 2Byte) in ein 24C512 (64Kx8Bit) geschrieben. Reicht ein paar
Tage.
Mit Gruß
Pieter
Morgen!
@ Pieter
Ich hab zwar net wiel Speicher (Nun schon mehr), aber es wird ja
dauerhaft gemessen, dann alle gespeichert und wo anders ausgegeben, in
der zeit wo das Alte schon wieder überschrieben wird. Also es ist nicht
so, dass ewig alles drin bleibt. 17Byte alleine sind es nur, die immer
bleiben. genau genommen 17Byte und ein nippel.
Thx für die Hilfe gestern!
MfG T-G-läser
Noch etwas... Habe ja noch das Problem dass ich die Werte anders
auslese.hier ein kleines Beispiel
SPEICHERUNG
mov P4,#00000000b
mov P5,#01000000b
call pause
call ADmess
mov 38h,a
VERARBEITUNG
m130: call ADmess
cjne a,38h,m112
m112: jc m131
mov P4,#00000000b
mov P5,#01000000b
jnc m122
MESSUNG
ADmess: clr mx0
clr mx1
clr mx2
clr adm
jb bsy,$
mov DAPR,#0
mov a,addat
ret
geht das auch alles mit einem Register also so(??):
(.....)
mov P4,#00000000b
mov P5,#01000000b
call pause
call ADmess
mov a,R1
mov DPTR,#4000h
movx @DPTR,a
(.....)
m130: call ADmess
mov DPTR,#4000h
movx a,@DPTR
cjne R1,a,m112 ;(geht glaub net... aber ka wie sonst. Ideen?)
m112: jc m131
mov P4,#00000000b
mov P5,#01000000b
jnc m122
(.....)
ADmess: clr mx0
clr mx1
clr mx2
clr adm
jb bsy,$
mov DAPR,#0
mov R1,addat
ret
(.....)
Habts andere Ideen, Wie ich des machen kann? Werden halt nacheinander
viele gespeichert. in einem anderem prog diese dann verarbeitet....
also es muss vom Prinzip so bleiben, wie es nun ist.
MfG T-G-läser
Sry für den dreifachpost...
Letzter Problembefehl:
cjne a,20h,m112
Abänderung mit 2 Variablen (ERROR - nicht möglich):
cjne R1,a,m112
Abänderung mit anderem Wert direkt (WARNIMG - unbekannt):
cjne a,2020h,m112
Wie kann ich noch 2 Werte Vergleichen, Carry setzen oder löschen je
nachdem ob der Speicher größer/kleiner ist wie der Akku/Register
Habts ne Möglichkeit mit wenig Befehlen, so dass diese Funktion "cjne
a,2020h,m112" erfüllt wird?
@Tobias
( MOV R1,womit auch immer )
mov P4,#00000000b
mov P5,#01000000b
call pause
call ADmess
mov a,R1
mov DPTR,#4000h
movx @DPTR,a
wenn R1 vorher den richtigen Wert hat sicher warum nicht.
CJNE @R1( oder R0 ), #data,reladdr ist auch richtig.
Allerdings scheint Deiner nicht zu verzweigen.
m130: call ADmess
mov DPTR,#4000h
movx a,@DPTR
cjne R1,a,m112 ;(geht glaub net... aber ka wie sonst. Ideen?)
Woher kommt R1 ?????? LADEN oder übergeben nicht vergessen !!!
Macht sich blöd wenn man nur Stücken hat.
Aber ich denke R1 hast Du schon an diesem Punkt.
CJNE Compare Jump not Qual
Also ist Ergebnis gleich mache nächste Zeile Weiter.
Ist Ergebnis nicht gleich, springe zu XY
Dort kann man jetzt nach C fragen. Und somit Größer bzw. Kleiner
unterscheiden. zB. mit Jb C, XY
Du verzewigst nur nach m131 wenn R1 kleiner Akku .Wenns so sein soll.
o.k.
Sieht glaube ich gut aus auf die Schnelle.
Bin auf Arbeit.
das geht alles mit CJNE
Nur Akku läßt ein Vergleich mit "Zahlen" zu.
Vergleiche bei Registern wie R0 und R1 immer mit Akku.
Falls 2020h eine Speicherstelle ist, dann erst mit Movx a,@dptr
in den Akku rein.
Falls es ein Wert ist....... Sorry. 8 Nur Bit soweit ich weis.
Ne CJNE ist schon genial.
http://www.8052.com/51cjne.phtml
Woher kommt R1 ?????? LADEN oder übergeben nicht vergessen !!!
In Beiden Fällen gilt doch noch das Unterprogramm. Sowohl oben beim
Speichern, sowie unten bei der Ausgabe. Es ist ja immer ein "call
ADmess" vorhanden.
ADmess: clr mx0
clr mx1
clr mx2
clr adm
jb bsy,$
mov DAPR,#0
mov R1,addat
ret
Daher mein R1 -> Also meine AD-Messung wird jedesmal neu im R1
zwischengespeichert.
Der Cjne geht leider nicht mit 2 Variablen. Aber habe eine neue Idee.
so âla:
(.....)
mov P4,#00000000b
mov P5,#01000000b
call pause
call ADmess
mov a,R1 ;Messwert zum Speichern
mov DPTR,#4000h ;Adresse
movx @DPTR,a ;Akku in ext. RAM ablegen
(.....)
m130: call ADmess ;Messung in R1 speichern
mov DPTR,#4000h ;Adresse
movx a,@DPTR ;Alter Wert in Akku
mov 0h,a ;Akku auf 0h(oder was halt sicher frei ist)
mov a,R1 ;Messwert in Akku
cjne a,0h,m112 ;Alt+Neu vergleichen
m112: jc m131
mov P4,#00000000b
mov P5,#01000000b
jnc m122
(.....)
ADmess: clr mx0
clr mx1
clr mx2
clr adm
jb bsy,$
mov DAPR,#0
mov R1,addat
ret
(.....)
Macht doch Sinn, oda nit?
Kann es leider nur hier im Geschäft nun net testen, aber so kann ich es
in Jeder Zeile dann leicht anwenden, Wobei das massig an zusätzlichen
Zeilen gibt.... Dazu kommt meine Begrenzung des Speichers die ich schon
fast erreicht hatte!!!
Nuja mal sehn evt kann man Teile gekürzt in ein unterprogramm
schmeißen.
Danke MfG T-G-läser
Ich kann nun Leider nicht mehr Weiterprogrammieren hier, da ich in eine
andere Abteilung versetzt werde (Schaltschrankbau).
Von daher kann ich nur wieder nach Feierabend da sein um an den Problem
weiter zu machen.
Wenn jmd Interesse hat kann ich die Dateien ja auch irgendwo auf meinem
Server zur Verfügung stellen.
Allgemein Kann ich anbieten für Leute hier Dateien auf meinem Server
auf ewig anzubieten (gratis und ohne Werbung), wenn mir jmd ne kleine
Downloadseite machen kann. Ansonsten nur mit direkten links auf die
jeweiligen Dateien.
Bitte bei mir melden E-Mail oben, ansonsten auch ICQ: 236-690-456
Dankeschön und bis dann
MfG T-G-läser
www.tobias-glaeser.de
www.tobias-glaeser.de/Startseite/Index.html