Hi, ich möchte eine Programm schreiben in dem ich 16 verschiedene Unterprogramme gespeichert hab. Diese sollen in Abhänigkeit von einem Wert im internen Speicher ausgewählt werden. Dieser Speicher wird dann durch externe Interrupts inkrementiert oder dekrementiert. Und je nach dem welchen Wert dieser Speicher hat, wird das dazugehörige Unterprogramm aufgerufen. Ich habe gehört da gibt es Tabellen oder Datenbanken dafür. Aber im Forum bzw Google habe ich nichts brauchbares gefunden oder nicht gesehen. Kann mir jemand einen Tipp geben? Ich verlange keine Lösung ;) Meine Utensilien: - AT89C51 - Assembler, 8051 Vielen Dank
Zuwenig Infos... müssen die Unterprogramme ihre Daten behalten, oder dürfen die Variablen durch die anderen UPs überschrieben werden? Was sollen die UPs leisten können? Vielleicht gibts einen anderen Weg, das gleiche zu erreichen als über mehrere "Programme". Ausserdem ist zu beachten, dass ein 89x5_1_ nur 128Byte RAM hat, was der Sache etwas entgegensteht... Ralf
Hi Ralf, danke für deine Antwort! es sollen 3 Register mit anderen Werten geladen werden. Diese Werte stehen in den Unterprogrammen. Die darin stehenden Werte dürfen nicht überschrieben werden. Ich kann auch mit 10 UPs oder weniger leben wenn der Interne RAM nicht ausreicht. Daran hab ich garnicht gedacht. Danke. Ich glaube der Ansatz ist nicht ganz richtig. Noch eine andere Idee. Man könnte diese Werte irgendwo im Internen Speicher ablegen und diese dann aufrufen.
Doppelpost, sry. Das würde nich gehen, da ich 3x2Byte beschreiben muss. Da müssen wohl Unterprogramme her.
> es sollen 3 Register mit anderen Werten geladen werden. Okay. > Diese Werte stehen in den Unterprogrammen. Die darin stehenden Werte > dürfen nicht überschrieben werden. Dann stehen die Werte nicht in Unterprogrammen, sondern in Wertetabellen! Der externe Interrupt erhöht/dekrementiert eine Zählervariable, die die Wertposition innerhalb der Tabelle angibt. Anhand der Position liest du die entsprechenden Werte aus und schreibst sie in die Register. Der Interrupt muss darauf achten, dass die Variable beim Inkrementieren nicht größer als die Anzahl an Werten minus eins und beim Dekrementieren von null automatisch gleich der Anzahl an Werten minus eins wird. Ralf
Hi, Die 3 Register müssen gleichzeitig mit neuen Werten beschrieben werden. In der Wertetablle kann man, soweit ich weiss, nur 1 Wert Ablegen? Ich hab mir das so gedacht. mov R0 , 10h mov R3 , 11h mov R6 , 12h 10h-12h sind meine variablen Register die ich überschreiben möchte. UT1: mov 10h,#11h mov 11h,#15h mov 12h,#FFh ret Sobald das Unterprogramm UT1 aufgerufen wird, werden die 3 Register mit den Werten geladen.
> In der Wertetablle kann man, soweit ich weiss, nur 1 Wert Ablegen?
An einer Adresse, ja -> logisch :)
An der nächsten Adresse, nächster Wert -> auch logisch
Und das erst gibt ja dann ne Tabelle...
Was das "3-Register/Werte-auf-einmal" betrifft, mach dir klar, dass du
doch einfach die Tabelle so sehen kannst, dass drei Werte einen
Datensatz bilden :)
Ralf
Du machst einfach in der Mainloop eine Statemachine und je nach Zustand der Variable wird die entsprechende Funktion ausgeführt. Mit externem Interrupt wirds knifflig (Prellen). Deutlich besser und einfacher ist daher, mit Timerinterrupt entprellen und dann die Variable bei Tastendruck hochzählen. Die 16 Funktionen müssen natürlich mit der Mainloop zusammen compiliert werden. Dein MC hat ja kein OS, welches DLLs nachladen kann. Peter
Wie sieht denn sowas aus? Ich hab das noch nie gemacht und kanns mir nicht vorstellen was du meinst. Gibts da ein Beispiel oder ein Stichwort nach dem ich suchen kann?
Das mit der Entprellung ist kein Problem. Ich hab da schon etwas fertig geschrieben. Meinst du eine Abfrage? Würde das nicht zu lange dauern bis der richtige Wert gefunden wurde?
> Meinst du eine Abfrage? Würde das nicht zu lange dauern bis der richtige > Wert gefunden wurde? Wie könnte es sonst gehen? Die einzig andere Möglichkeit wäre gleich eine Sprungtabelle, also eine Tabelle, in der die Adresse der Routinen steht. In Abhängigkeit des Wertes wird die entsprechende Adresse geladen und dann dorthin gesprungen. Das kann sich schon mal lohnen, aber nicht in einem Projekt der Größenordnung, wie du sie beschrieben hast :) Du wirst da kaum einen Unterschied spüren. Ralf
Wie Peter Dannegger geschrieben hat, fährst du mit einer Statusmaschine am besten. Ich habe dies mit einem AT89C51 kürzlich in etwa so programmiert. Ist ziemlich einfach zu realisieren. Wie Peter schon beschrieben hast brauchst du nur: - Eine Statusmaschine mit einer Variable. Je nach dem was die Variable für einen Wert hat, wird eine andere Funktion ausgeführt. - Timerinterrupt in welchem du die Tasten einliest und entprellts. Je nach dem was für eine Taste gedrückt wurde, wird die Variable von der Statusmaschine dekrementiert oder inkrementiert. gruss
quick and dirty... als Unterprogramm aufrufen. push acc push dph push dpl mov dptr,#returnadresse push dpl ; in den Kellerspeicher push dph mov a,programmauswahl anl a,#00001111B push b mov b,a add a,b ; * 2 add a,b ; * 3 pop b mov dptr,#unterprogramme jmp @a+dptr unterprogramme: jmp programm1 jmp programm2 ; ... weitere unterprogramme ; ... mit RET beenden! jmp programm16 returnaddresse: pop dpl pop dph pop acc ret programm1: ret programm2: ret programm16: ret
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.