Hallo, ich habe einen ADuC831 mit Assembler-Programm (8051), wo noch was zusätzliches rein soll. Dafür wäre es gut. von der Interruptroutine INT0 nicht normal sondern immer auf eine bestimmte Marke zurückzuspringen. Meine Idee: 2xpoppen(ich meine natürlich entkellern) und dann meine Wunschadresse pushen. Dazu müßte ich die absolute Adresse, die ja erst beim übersetzen entsteht, herbeizaubern. Hat jemand eine Idee? oder vielleicht eine Alternative?
Auch wenn ich dein Vorhaben für keine gute Idee halte ;) : Kennt dein Assembler kein "org"?
Wenn die Zieladresse als Label vorliegt, sollte es kein Problem sein, label&0xff sowie Label>>8 zu pushen. Manche Assemler bieten dafür auch Makros wie hi() und lo() an, und das dann einzukell(n)ern, um in Deinem eigenwilligen Sprachgebrauch zu bleiben.
Aber vielleicht schilderst Du lieber das Problem selbst, anstelle nach Hilfe bei einer vorgegebenen Lösung zu suchen, die doch ziemlich seltsam anmutet.
>Meine Idee: 2xpoppen(ich meine natürlich entkellern) und dann meine >Wunschadresse pushen. Da hab ich doch glatt was vergessen. Wer entkellert eigentlich den Stack wenn der Interrupt in einer Routine auftritt die eigentlich per return verlassen werden müsste?
holger schrieb: > Da hab ich doch glatt was vergessen. > Wer entkellert eigentlich den Stack wenn der > Interrupt in einer Routine auftritt die eigentlich > per return verlassen werden müsste? Der Kellner natürlich! In so einem fall könnte man einfach den Stackpointer wieder auf Anfang setzen, da eh alles wofür der Stack brauchbar wäre ab dem Moment verloren ist.
>Der Kellner natürlich! He, he;) >In so einem fall könnte man einfach den Stackpointer wieder auf Anfang >setzen, da eh alles wofür der Stack brauchbar wäre ab dem Moment >verloren ist. Wenn eventuelle unterbrochene Berechnungen in Unterprogrammen dann möglicherweise falsche Werte liefern ist das auch nicht so schön.
der mir über die Schulter schauende Kollege hatte halt bei "meine Idee: 2x poppen" gewisse Kommentare parat. Und ganz früher - ich bin nicht mehr der Jüngste - nannte man einen Stack eben gut deutsch Kellerspeicher. Stack auf Anfang finde ich ganz plausibel: Alles angefangene kann weg. Die Operation "label&0xff" bringe ich allerdings mit meinen verfügbaren Assembler-Kenntnissen nicht zusammen. Das sieht irgendwie nach 16 Bit aus - und ich habe doch nur 8 - oder?
eckhard03 schrieb:
> nannte man einen Stack eben gut deutsch Kellerspeicher.
War das nicht Siemens-Spezialsprache? Ich erinnere mich an beides, aber
Stapelspeicher war öfter zu hören.
Ist ausserdem Blödsinn, denn wer seinen Vorratskeller so stapelt, der
darf sich nicht wundern wenn viel vergammelt.
>Stack auf Anfang finde ich ganz plausibel: Alles angefangene kann weg. Dann wundere dich nicht über die Nebenwirkungen. Mach doch einfach einen Jump auf den Resetvektor. Dann ist alles angefangene einigermassen weg. Wenn auch nicht alles. >Die Operation "label&0xff" bringe ich allerdings mit meinen verfügbaren >Assembler-Kenntnissen nicht zusammen. Das sieht irgendwie nach 16 Bit >aus - und ich habe doch nur 8 - oder? Wenn dein uC nur 256 Byte Codespeicher hat, ja. Falls nicht solltest du dich mal näher über deinen uC informieren bevor du so einen Gurkenkram planst.
'Tschuldigung. Jetzt nochmal für Holger: Mit "8 bit" meinte ich natürlich nicht den Adressraum sondern die Verarbeitungsbreite der Befehle.
> Die Operation "label&0xff" bringe ich allerdings mit meinen verfügbaren > Assembler-Kenntnissen nicht zusammen. Das sieht irgendwie nach 16 Bit > aus - und ich habe doch nur 8 - oder? Das Label wird doch wohl 16 Bit sein. Obige Konstruktion macht zusammen mit der anderen gezeigten aus dem Label zwei 8-Bit-Happen, die Du bequem in Deinem Keller stapeln kannst. Zusammen ergeben sie die gewünschte 16-Bit-Adresse zum entstapeln.
Danke für Eure Geduld. Mein Problem ist aber eben gerade die 16-bit-Breite. Im 8051-Assembler gibt es kein 16-Bit-Arbeitsregister und damit auch keinen Befehl, der zwei 16-Bit-Werte verknüpft (marke&maske). Hier noch die eigentliche Aufgabe: Der µC steuert/regelt eine analoge Prozessgröße folgendermaßen: Bei Interrupt beginnt eine Rampenfunktion mit vorgegebenen Anstieg - bis erreichen eines vorgegebenen Endwertes. Dann wird dieser als Konstantwert nachgeregelt (Messen, Regelabweichung-->Stellwertkorrektur). Zu beliebigen Zeitpunkten kommt neuer Interrupt (während der Rampe oder dem Konstant-Plateau). Dann beginnt eine neue Rampe bis neuem Endwert, der wieder nachgeregelt wird. Die Endwerte variieren von Null bis Vdd. Die Anstiegszeiten von 10...300ms und die Interrupt-Abstände von 4...800ms. Alles soll in willkürlicher Kombination möglich sein.
Hört sich für mich so an, als ob sich das ohne Probleme sauber durch eine State-Maschine lösen lässt, ganz ohne schmutzige Stackvergewaltigungsmaßnahmen.
Wer den Stack vergewaltigt ist selber schuld wenns schief geht. Warum nich nicht in dem besagten Int ein Flag setzen, der Aduc hat eine ganzen Menge direkt anspechbare, und dann in der Main-Loop abfragen. Sauber, einfach und ohne obskure Stackmanipulation! Und das 16 Bit-Label auf den Stack bekommen: ldi acc,low(label) push acc ldi acc,high(label) push acc Achtung ggf. muss die Reihenfplge L-H vertaucscht werden! Aber besser KEINE Stack-Manipulation (brrr, Kopf-schüttel)
Sehe das wie Klaus. Das alles klingt für mich nach einem verkorkstem Ansatz. Wenn die Regelung ständig mitläuft, dann kann man auch Rampen dadurch realisieren, dass man den Sollwert für die Regelung verändert. Das kann ganz einfach gehen, indem man in regelmässigen Abständen den Sollwert mit einem Vorgabewert vergleicht. Ist der Sollwert kleiner als die Vorgabe, dann wird der Sollwert um einen bestimmten Anteil erhöht, ist der Sollwert größer als die Vorgabe, wird der Sollwert um einen konstanten Anteil verringert. Auf diese Art kann man den Vorgabewert ändern wann immer man will, der Sollwert (und damit hoffentlich auch der Istwert durch den PID-Regler) wird auf einer Rampe nachgeführt. Und das Ganze funktioniert auch dann, wenn die 'Sollwertrampe' gerade nach oben geht und ein neuer Vorgabewert eintrifft, der den Sollwert plötzlich auf ganz tief stellt. Die nach oben führende 'Rampe' wird sofort abgebrochen und der Sollwert fährt auf einer neuen Rampe nach unten. Durch die Zeitabstände dieser 'regelmässigen Sollwertnachführung' bzw. durch die Wahl des Inkrements/Dekrements kann die Steigung der Rampe bestimmt werden. Aber Stackmanipulation wie angedeutet braucht da kein Mensch.
> Mein Problem ist aber eben gerade die 16-bit-Breite. Im 8051-Assembler > gibt es kein 16-Bit-Arbeitsregister und damit auch keinen Befehl, der > zwei 16-Bit-Werte verknüpft (marke&maske). Es ist zwar viele Jahre her, dass ich 8051 gemacht habe, mit der Keil-Toolchain. Aber natürlich konnte dessen Assembler Grundarithmetik. Und natürlich brauchst Du dafür kein Register der CPU. Ich denke, dass Du da ein Grundproblem mit dem Verständnis von Assembler hast. Assembler-Arithmetik auf einem Label hat mit der CPU, deren arithmetischen Befehlen und deren Registern nichts, aber auch wirklich gar nichts zu tun. Abgesehen davon: Ich glaube, dass schon die Grundidee überprüft werden soll, wie ich und andere schon schrieben.
OK. Tut mir leid, kein Profi zu sein. Was ich hier habe ist ein vorhandenes Programm/Programmierumgebung auf Niveau 8051-Assembler. Da gibt's halt keinen Befehl "ldi" - siehe auch 8051-Befehlsliste - und nur 8-bit breite UND-Verknüpfungen. Dass mehr Progammiererfahrung für mich dienlicher wäre, weiß ich natürlich selber. Bin eben auf der Suche, wo/wie ich was dazulernen kann, um das hier zu schaffen. Das mit den variablen Sollwerten von Karl Heinz geht nicht, denn das eigentliche Problem bei dem Regler ist die Trägheit des Prozesses: Zeitverzögerung 2.Grades + Totzeit - leider nicht zeitkonstant. D.h. bei manchen Einstellungen reagiert derzeit einfach gar nichts. Meine eigentliche Aufgabe ist, da noch was sinnvolles rauszuholen. Und da wollte ich das Flagsetzen und immer in genügend kurzen Abständen abfragen usw. einsparen. Wenn Ihr Euch alle einig seid, dass man sowas niemals tut, nehm' ich's zur Kenntnis. Wäre aber eben schön gewesen.
Stimmt, der asm51 kennt kein ldi, heißt hier mov. Also ein 16Bit Label wird dann mit mov acc,low(label) ... und mov acc,high(label) ..... verarbeitet. Konnte schon der Intel-Asm und der Keil asm in den 80-er Jahren....... Ein suboptimales Programm, möglichst noch schlecht dokumentiert, zu ergänzen bzw. zu "verschlimmbessern", ist echt nicht einfach, manchmal wäre ein "Neuschreiben" schneller und einfacher. Ich wünsche Dir trotzdem viel Erfolg.
eckhard03 schrieb: > OK. Tut mir leid, kein Profi zu sein. Was ich hier habe ist ein > vorhandenes Programm/Programmierumgebung auf Niveau 8051-Assembler. Da > gibt's halt keinen Befehl "ldi" - siehe auch 8051-Befehlsliste - und nur > 8-bit breite UND-Verknüpfungen. Nochmal: Dein Assembler kann Arithmetik, die unabhängig vom Befehlssatz der CPU ist, denn sie dient dazu, lokale Berechnungen durchzuführen, bevor daraus ein Befehl für die CPU wird. Das hat nichts damit zu tun, ob irgendwelche CPU-Befehle ldi oder mov heißen (was sowieso nur ein syntaktischer, kein semantischer Unterschied ist - das Ding heißt anders, tut aber dasselbe). Es gibt so Dinger, die heißen Manuals. Da steht drin, welche Arithmetik ein Assembler für sich mitbringt, um Dinge zu berechnen, deren Rechenergebnis in die CPU-Befehle einfließt, ohne dass deshalb die CPU irgendwas zu rechnen hätte. Da steht drin, wie die Ausdrücke dafür auszusehen haben. Es sollte doch einem Assemblerprogrammierer klar sein, dass die (fiktive) Zeile
1 | mov acc,2+(3*13) |
eine einfaches Laden des Akkus mit einer Konstanten bewirkt und die Ziel-CPU keine Rechnung dabei ausführt, genauso wenig wie der Assembler-Ausdruck "label&0xff" etwas mit Registerbreiten zu tun hat. Ich bin vielleicht etwas zu ungeduldig, aber ich klinke mich jetzt aus.
Also, hier gibt's keinen Progammierer. Ich bin einfach das Mädchen für alles uns sehe was ich zu Stande bringe. Und vor vielen Jahren hab ich auch schon mal ein Assembler-Programm geschrieben (da gabs noch keine µCs). Ihr habt mir jedenfalls ein ganzes Stück weiter geholfen und dafür möchte ich mich bedanken. Und Entschuldigung, für die Nervigkeit. Eckhard
> Also, hier gibt's keinen Progammierer. Ich bin einfach das Mädchen für > alles uns sehe was ich zu Stande bringe. Gut, vielleicht habe ich überreagiert. Oder Du hättest es früher klarstellen können statt dabei zu bleiben, der Assembler könne nicht mit 16-Bit-Quantitäten rechnen. Heute war kein besonders guter Tag für mich, und Du kannst nichts dafür, belassen wir's dabei. Ich denke, dass der Assembler auch zum Rechnen mit Labels da ist und die Ziel-CPU mit diesen Rechnungen nichts zu tun hat, ist nun klar. Auch klar dürfte sein, dass die Manipulation der Rücksprungadresse im Stack nur in sehr seltenen Fällen eine gute Idee ist, die nur mit guten Assemblerkenntnissen angegangen werden kann.
sollte überhaupt keine Kritik sein. Ich meinte das ganz ehrlich, mit dem Dankeschön und auch mit der Entschuldigung. Bin jetzt echt ein ganzes Stück weiter. Der vergewaltigte Stack scheint zu funzen und ist immer noch meine Vorzugsversion. Wenn man ihn ständig nullt, kann er zumindest nicht überlaufen.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.