Hallo zusammen, ich bin gerade dabei eine Vakuumpumpe zu entwickeln und komm leider in meinem Programm nicht weiter.. Vielleicht könnt ihr mir ja weiterhelfen. Controller: AT89C51 Programm: Ride Das Programm im Anhang soll wenn es fertig ist wie folgt funktionieren. 1. Keine Betätigung --> P2=00h 2. P1.1 wird ein mal betätigt --> P2=0F7h 3. Poti wird so gedreht, dass durch den Subtraktionsbefehl das Carry-Bit gesetzt wird --> P2=00h 4. Wird der Poti wieder zurückgedreht, sodass das Carry-Bit nicht mehr gesetzt ist --> P2=0F7h Bis jetzt funktionieren die Punkte 1-3. Drehe ich das Poti und das Carry-Bit wird gesetzt, wird mir 00h an P2 angezeigt. Dreh ich jedoch wieder zurück bleibt 00h an P2 und es schalten nicht um auf 0F7h Ich bin wirklich am verzweifeln, weil ich einfach nicht weiß, was falsch sein soll. Ist vielleicht etwas mit meinem push/pop Befehl falsch?? Wäre super wenn mir jemand helfen würde! PS: Das Programm ist unten abgeschnitten. Steht aber nur noch die Warteschleife. Da bin ich mir sicher dass die richtig ist ;) Der Akku wird übrigens gezählt weil ich bei 01h im Akku die erste Leistungsstufe der Pumpe habe, bei 02h die zweite, 03h die dritte usw....Habe es versucht über Register zu machen, damit ich den Akku nicht retten/restaurieren muss für den "subb"-Befehl, funktioniert aber leider auch nicht. Er zählt zwar die Register hoch, aber Punkt 4 von oben (Wird der Poti wieder zurückgedreht, sodass das Carry-Bit nicht mehr gesetzt ist --> P2=0F7h) funktioniert immernoch nicht... Grüße Janis06
Ich kann Dir mit Assembler zwar nicht helfen, aber einen Tip habe ich: Auf Quelltextschnipsel als Bild werden die wenigsten anspringen. Besser ist es, wenn Du den Code in vollständiger und direkt verwendbarer Form als Text anhängst. Mag sein, daß in diesem Fall ein Asm-Kenner drauf schaut und sagt, wo der Fehler liegt, aber für die Zukunft ist es besser, Code als Code zu liefern und nicht als Bild :) Viel Erfolg, 42m
Was ich schon mal gefunden habe: Beim Sprung bei <jc aus> gehst Du an <pop Acc> "vorbei", zumindest der Stack wird dann überlaufen. Apropos: wo wird den Stack überhaupt initialisiert? Gruß Dietrich
moin,
das reinste Chaos...
-lade den Zahlenwert von Acc mal in R0, dann bleibt der so
-wo wird das Cy für SUBB gesetzt? Addiere 25 hat den selben Effekt wie
SUBB 230 setzt aber kein CY vorraus.
>>Apropos: wo wird den Stack überhaupt initialisiert?
steht ohne Init auf Adr. 7.
MfG
Pieter
Erstmal danke an alle die sich die Mühe gemacht haben sich das ganze anzuschauen! > -lade den Zahlenwert von Acc mal in R0, dann bleibt der so R0 verwende ich schon in der Warteschleife. Habe es aber gestern schon mit R3 versucht, was leider nichts gebracht hat... > -wo wird das Cy für SUBB gesetzt? Addiere 25 hat den selben Effekt wie SUBB 230 setzt aber kein CY vorraus. Das wird gesetzt wenn die Differenz kleiner als 0 ist. Sprich wenn ich 220 einlese und 230 abziehe habe ich theoretisch -10, wodurch das CY gesetzt wird. Bin jetzt am überlegen wie ich es mit dem ADD Befehl machen könnte. Gibt es einen Befehl der abfrägt, ob z.B Acc kleiner oder größer als 350 ist?
>> Sprich wenn ich 220 einlese und 230 abziehe habe ich theoretisch -10, RTFM: SUBB A,n -> A = A-n-CY Für A-n ist vorher CY auf 0 zu setzen. (CLR C) Oder Du benutzt CJNE... Oder diese Macro: ;-------------------------------------- ;Compare And Jump Less CJL MACRO Register, Value, Target CJNE Register, Value, @@1 @@1: JC Target ENDM ;-------------------------------------- >>Acc kleiner oder größer als 350 das ist jetzt ULK. Wertebereich Accu ist 0..255.
Janis H. schrieb: > Ist vielleicht etwas mit meinem push/pop Befehl falsch?? Könnte gut sein. Oben im ersten Block wird ja der Akku einmal gepusht, und bei Carry weg gesprungen, in diesem Fall nicht mehr zurück gepopt. Dort erhöht sich der Stack dann jeweils immer um 1, bis er irgendwann über läuft. Er läuft dann in die untere Registerbank hinein. Da im Programm Register verwendet werden, könnten diese bei Stacküberlauf verändert werden. Vertausch doch einfach mal die beiden Befehle, setze "pop acc" vor "jc aus". Das Carry-Flag bleibt dadurch auch erhalten.
> Für A-n ist vorher CY auf 0 zu setzen. (CLR C) Habe ich mittlerweile eingefügt. Bringt aber nichts... >>>Acc kleiner oder größer als 350 > > das ist jetzt ULK. > Wertebereich Accu ist 0..255. Hast natürlich recht ;) Frag mich auch gerade warum ich das geschrieben habe!?! Nehm einfach die 230 :) So sieht mein Listing mittlerweile aus: ------------------------------------------------------ include reg51.inc extern code Ain0 code at 0 mov A,#00h loop1: jb P1.1,hoch jb P1.0,runter cjne A,#01h,weiter1 mov P2,#0F7h push Acc lcall Ain0 subb A,#230d jc aus pop Acc mov P2,#0F7h ljmp loop1 weiter1: mov P2,#00h sjmp loop1 hoch: inc A lcall wait1 ljmp loop1 runter: dec A lcall wait1 ljmp loop1 aus: pop Acc clr c acall wait1 mov P2,#00h sjmp loop1 wait1: mov R2,#16 halt2: mov R1,#250 halt1: mov R0,#250 halt0: djnz R0, halt0 djnz R1, halt1 djnz R2, halt2 ret end --------------------------------------------------- Leider geht der oben genannte Punkt 3 nun auch nicht mehr. Das muss an dem pop Acc Befehlt im UP "aus" liegen. Kann es sein dass ich nur einen pop Befehl benutzen darf. Habe das aus folgendem Grund gemacht: Wenn ich bei "jc aus" in das UP "aus" springe wird der Akku nicht mehr restauriert, was nicht sein darf, weil wir in der letzten Zeile von UP "aus" wieder in "loop1" springen und dann immernoch den Wert von der Subtraktion im Akku hätten
> Vertausch doch einfach mal die beiden Befehle, setze "pop acc" vor "jc > aus". Das Carry-Flag bleibt dadurch auch erhalten. Danke für die Idee, aber das Carry scheint nicht erhalten zu bleiben. Habe es versucht und jetzt springt er nicht mehr in UP "aus"
Janis H. schrieb: > code at 0 > mov A,#00h > > loop1: jb P1.1,hoch > jb P1.0,runter > cjne A,#01h,weiter1 Wenn Du den Zustand 2 erreicht hast (Acc=1), wird P2 hier doch wieder sofort auf #0F7h gesetzt: > mov P2,#0F7h > push Acc > lcall Ain0 > subb A,#230d Dann wird nach dem Vergleich zwar wieder nach "aus" gesprungen: > jc aus > .... > > aus: pop Acc > clr c Aber dann wird erst gewartet: > acall wait1 ...bis P2 gelöscht wird: > mov P2,#00h > sjmp loop1 Und mit loop1 kommst Du gleich wieder nach oben, wo P2 wieder auf #0F7h gesetzt wird (s.o.). Ich glaube, Du solltest Dir mal ein Flussdiagramm malen. Dann ist besser zu überblicken, was wann passiert und wo was getan werden muss. Übrigens zum Thema push/pop: neben der Funktion, die bestimmt, welche Daten gerettet und wieder hergestellt werden müssen, müssen auf "push"s immer genau so viele "pop"s folgen, sonst verzählt sich der Stackpointer. Die Folgen sind dann beliebig unkalkulierbar. Gruß Dietrich
Janis H. schrieb: > aus: pop Acc > clr c Übrigens: Das "clr c" sollte besser direkt vor "subb A,#230d" stehen. Dann 1. weiß man, wozu das gehört und warum es gemacht wird 2. ist man sicher, dass "carry" ggf. nicht irgendwo anders wieder gesetzt wird, wenn man an dem Programm "rumbastelt". Gruß Dietrich
lade dir mal avr head http://www.avr-asm-tutorial.net/avr_de/avr_head/avr_head.html runter. Damit kannst du schöne ASM Dateien erstellen. Du behälst den überblick und andere können dir dann auch helfen! ps immer schön ;was mach ich schreiben
Janis H. schrieb: > Danke für die Idee, aber das Carry scheint nicht erhalten zu bleiben. Das kann ich mir nicht vorstellen. Carry wird nur verändert, wenn ein Befehl es ändert, und ich sehe dort an der Stelle keinen. Anstatt mit push und pop auf dem Stack kann man den Akku aber auch in einem nicht verwendeten Register sichern, z.B. R3 bis R7, oder z.B. im B-Register, wenn dieses anderweitig im Programm nicht verwendet wird, oder in einer Variablen, die man bspw. accsav nennen kann. Das würde die Stackgeschichte ja zunächst mal beseitigen. Dietrich L. schrieb: > Übrigens: Das "clr c" sollte besser direkt vor "subb A,#230d" stehen. Auf jeden Fall wird das Carry mit vom Akku subtrahiert. Man subtrahiert dann je nach Carry mal 230, und mal 231. Denn subb heißt sub with borrow, und borrow ist das Carry. Dietrich L. schrieb: > Ich glaube, Du solltest Dir mal ein Flussdiagramm malen. Das auf jeden Fall. Es erleichtert die Fehlersuche bereits vor der Codeerstellung, und hilft auch, das Programm gut zu strukturieren, damit es kein Spaghetti-Code wird.
Moin, so habe jetzt mal den Akku in R3 abgelegt und siehe da, es tut sich was. Aber es ist sehr komisch. Wenn ich P1.1 betätige bekomme ich an P2 wie schon die ganze Zeit mein 0F7h. Jetzt drehe ich an meinem Poti und erwarte eigentlich die die 00h an P2. Die kommen aber nicht. Wenn an P2 00h liegen müssten meine LEDs eigentlich alle leuchten, da ich das Signal über einen HEF40106 invertiere. Das komische ist, dass nur eine LED leuchtet und die andere glimmen ganz leicht. Drehe ich das Poti zurück gehe die LEDs wieder aus, wie es eigentlich sein soll. Also von der Funktion geht es jetzt, nur habe ich das Problem, dass 7 von 8 LEDs nur glimmen wenn ich das carry setze. Normalerweise wird man jetzt denken, dass es der HEF40106 nicht packt, aber wenn ich resete leuchten ja auch alle... Flussdiagramm hab ich mir mittlerweile auch gezeichnet :)
Janis H. schrieb: > Moin, > so habe jetzt mal ... Wie ist denn jetzt Dein Programm? Hast Du den von mir oben beschriebenen Fehler auch korrigiert? : Dietrich L. schrieb: > ... > Aber dann wird erst gewartet: >> acall wait1 > ...bis P2 gelöscht wird: >> mov P2,#00h >> sjmp loop1 > > Und mit loop1 kommst Du gleich wieder nach oben, wo P2 wieder auf #0F7h > gesetzt wird (s.o.). Wenn das noch so ist, können die LEDs durchaus glimmen, denn sie werden eingeschaltet (#00h) und ganz kurz danach alle außer D3 wieder ausgeschaltet (#F7h). Zeig mal dein aktuelles Programm + Flußdiagramm. Gruß Dietrich
DANKE,DANKE,DANKE!!!! Das habe ich total übersehen... Hier mein akutelles Listing. Funktioniert jetzt einwandfrei :)
1 | include reg51.inc |
2 | |
3 | extern code Ain0 |
4 | code at 0 |
5 | mov A,#00h |
6 | |
7 | loop1: jb P1.1,hoch |
8 | jb P1.0,runter |
9 | cjne A,#01h,weiter1 |
10 | mov R3,A |
11 | mov A,#00h |
12 | lcall wait1 |
13 | mov P2,#0FFh |
14 | lcall Ain0 |
15 | clr c |
16 | subb A,#230d |
17 | jc aus |
18 | mov P2,#0FFh |
19 | mov A,R3 |
20 | ljmp loop1 |
21 | |
22 | weiter1: mov P2,#00h |
23 | sjmp loop1 |
24 | |
25 | hoch: inc A |
26 | lcall wait1 |
27 | ljmp loop1 |
28 | |
29 | runter: dec A |
30 | lcall wait1 |
31 | ljmp loop1 |
32 | |
33 | aus: mov P2,#00h |
34 | mov A,R3 |
35 | sjmp loop1 |
36 | |
37 | wait1: mov R2,#8 |
38 | halt2: mov R1,#250 |
39 | halt1: mov R0,#250 |
40 | halt0: djnz R0, halt0 |
41 | djnz R1, halt1 |
42 | djnz R2, halt2 |
43 | ret |
44 | |
45 | |
46 | end |
Man sieht jetzt nur noch den LEDs an, dass sie kurz weggeschalten werden, aber damit kann ich leben. Ich zeichne dir auch noch schnell das aktuelle Flussdiagramm.
So hier das Flussdiagramm. Mit was für einem Programm zeichnet ihr das normalerweise? Hab das bisher nur in der Schule gemacht und da haben wirs immer von Hand gemacht. Hoffe man kann alles auf dem Bild erkennen ;) Vielen Dank nochmal an alle die mir geholfen haben!
Verwende C. Freie Compiler gibts dafür ja für MCS-51. Softwareentwiccklung in Assembler (bis auf wenige Ausnahmen abgesehen, an denen es sich nicht vermeiden lässt) ist nicht mehr state of the art.
Da gebe ich dir vollkommen recht, ich bin aber leider noch nicht groß dazugekommen mir C anzueignen....
EFA schrieb: > Verwende C. Freie Compiler gibts dafür ja für MCS-51. > Softwareentwiccklung in Assembler (bis auf wenige Ausnahmen abgesehen, > an denen es sich nicht vermeiden lässt) ist nicht mehr state of the art. Mit dem Argument hätte http://www.mikrocontroller.net/articles/AVR-Tutorial aber auch keine Berechtigung mehr. Wenn jemand, warum auch immer, etwas in Assembler lösen möchte - und sei es nur, um zu lernen - warum nicht? Außerdem war ja die Frage nicht: Wie mache ich es besser in einer anderen Sprache? :) Klar sind relativ hardwarenahe "Hoch"sprachen wie C in vielen Fällen besser, aber wenn jemand unbedingt ASM verwenden will sollte man ihn lassen. 42m
EFA schrieb: > Verwende C. Freie Compiler gibts dafür ja für MCS-51. > Softwareentwiccklung in Assembler (bis auf wenige Ausnahmen abgesehen, > an denen es sich nicht vermeiden lässt) ist nicht mehr state of the art. C auf einem 8051 macht eines nicht und das ist Spaß. Warum sollte man Assembler nicht lernen ? Hat durchaus seine Vorteile bei gewissen Dingen. :)
Ich sage nicht dass man Assembler nicht lernen sollte - aber für größere Projekte macht es eben keinen Sinn diese komplett in Assembler zu entwickeln. Man wird bei jedem Projekt einen kleinen Assembler-Anteil haben, mindestens für die crt0 und teileweise fürs Exceptionhandling.
Janis H. schrieb: > Hier mein akutelles Listing. Funktioniert jetzt einwandfrei :) > hoch: inc A > lcall wait1 > ljmp loop1 > > runter: dec A > lcall wait1 > ljmp loop1 > Dir ist bewusst, dass der Akku auch "überlaufen" oder "unterlaufen" kann? Also Du erhöhst ihn ständig und plötzlich ist er bei FF und danach bei 00 und es geht von vorne los. Vielleicht solltest du bei "hoch" und "runter" noch etwas Bereichsprüfung machen. Sollte dann ein Maximalwert erreicht sein, dann wird das "inc A" einfach übersprungen. Selbiges für Null und "dec A"... Gruß, Thomas
Janis H. schrieb: > So hier das Flussdiagramm. Mit was für einem Programm zeichnet ihr das > normalerweise? Hab das bisher nur in der Schule gemacht und da haben > wirs immer von Hand gemacht. Hoffe man kann alles auf dem Bild erkennen > ;) Mit diesem "Flussdiagramm" beschreibst du ja nur dein Programm. Du solltest es etwas "problemorientierter" gestalten: Nicht "P1.1" oder "P1.0", sondern "Taster 'hoch' gedrückt" und "Taster 'runter' gedrückt". Nicht "ACC + 1" und "ACC - 1", sondern nenne die Zählvariable beim Namen, viellicht "Geschwindigkeit + 1" oder ähnlich. Also das, was du mit dieser Variablen erreichen willst. Wie und wo diese Variable im Programm kodiert wird, also im Akku, Speicher oder Register, wird erst viel später entschieden. Selbiges gilt für die Ports im Absatz darüber... Mit einem Flussdiagramm sollte man ein Problem in unterschiedlichen Programmiersprachen kodieren können. Bei deinem Diagramm kann ich noch nicht mal das Problem erkennen... Gruß, Thomas
Thomas T. schrieb: > Mit diesem "Flussdiagramm" beschreibst du ja nur dein Programm. Du > solltest es etwas "problemorientierter" gestalten: Du hast ja im Prinzip recht, das sollte man als erstes machen. Aber Janis hatte Probleme mit der Umsetzung in Assembler. Da ist seine Darstellung nicht schlecht. Hätte er das gleich so gemacht, hätte er einige Fehler selber entdeckt. Gruß Dietrich
Janis H. schrieb: > So hier das Flussdiagramm. Mit was für einem Programm zeichnet ihr das > normalerweise? Hab das bisher nur in der Schule gemacht und da haben > wirs immer von Hand gemacht. Nur um da einzuhaken: Das ist völlig ok. Ganz im Gegenteil. Du bist mit der Hand und Papier und Bleistift (und Radiergummi) um Größenordnungen schneller unterwegs (und auch bei Änderungen schneller) als mit jedem Programm! Für die ersten Entwürfe kannst du dir diese Ganzen Boxen rund um die Blöcke oder auch Abfragen sparen, die kann man auch in der endgültigen Version machen. Aber es ist meistens ein Trugschluss, wenn man für derartige Dinge ein spezielles Programm benutzt, dass man dann schneller wäre. Oft genug erlebt: Durch den Einsatz solcher Programme konzentriert man sich nicht mehr auf die eigentlich zu leistende Arbeit, sondern vertrödelt seine Zeit damit Fonts umzustellen, Dinge farbig zu machen, Blöcke hin und her zu schieben damit es schön aussieht, etc. etc. Ich möchte keinem zu Nahe treten, aber sieh dir doch mal viele der 'Arbeiten' von BWL-ern oder Managern an. Das wichtigste ist immer, das alles bunt ist und möglichst viele Fonts benutzt werden. Da gibt es wunderbare Powerpoint-Präsentationen, die graphisch wunderbar gestaltet sind - aber der Inhalt ist ... nur heiße Luft oder so wischi waschi, dass selbst ein Grundschüler erkennen kann, dass der Vortragende selbst keine Ahnung hat und eigentlich nur Zeit schinden muss. Da ist mir jede Handskizze lieber. Die mag zwar nicht so schön aussehen, aber die inneren Werte stimmen.
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.