Forum: Mikrocontroller und Digitale Elektronik Atmega8 ASM-Unterprogramm funktioniert nur bei Simulation


von Paul H. (plan)


Angehängte Dateien:

Lesenswert?

Guten Tag

Dieses kleine Programm sollte eigentlich die LEDs an PortD 0 und 1 
jeweils beim Betätigen eines Tasters 0 oder 1 an PortB an- und 
umschalten und beim Betätigen eines dritten Tasters an PortB 2 
ausschalten.

Die Simulation im AVR-Studio funktioniert wie ich es mir vorstelle, der 
µC reagiert aber anders.
Beim Anschalten sind beide LEDs schwach an und beim Drücken eines 
Tasters leuchtet die jeweilige LED heller und beim Drücken des Tasters 2 
passiert nichts.

Ich wäre dankbar, wenn mir jemand die Fehler in meinem Programm erklären 
könnte und einen passenden Code schreiben könnte.

Lg Paul

von spess53 (Gast)


Lesenswert?

Hi

>Ich wäre dankbar, wenn mir jemand die Fehler in meinem Programm erklären
>könnte und einen passenden Code schreiben könnte.

Da fehlt die Stackinitialisierung.

MfG Spess

von Vivil (Gast)


Lesenswert?

Was sollte man nach einem rcall machen?

Dieses wäre deine richtige Frage gewesen.

Ist Dir die Antwort bekannt?

von Vivil (Gast)


Lesenswert?

Und was soll das?
1
led1:
2
  sbi portd, 0
3
  cbi portd, 1
4
  rcall taster1
5
6
  taster1: 
7
      sbic pinb, 1

Mein Tipp Kommentiere jeden Befehl mit deinem Gedankengang und Du wirst 
merken das du das zusammengestückelt hast. So wird das nix.

von Toni (Gast)


Lesenswert?

Bin ich leseschwach oder suche ich vergebens nach "RET"?

Am Ende eines Unterprogramms nötiger Befehl.

von Paul H. (plan)


Angehängte Dateien:

Lesenswert?

Danke für die Antworten und Fragen.

Ich habe mein Programm kommentiert und hoffe, dass Ihr es nachvollziehen 
könnt.
Mir ist jetzt auch das Problem mit dem Stack aufgefallen, nur weiß ich 
nicht wie ich den sichern soll, ohne das er abläuft.

LG Paul

von spess53 (Gast)


Lesenswert?

Hi

>Mir ist jetzt auch das Problem mit dem Stack aufgefallen, nur weiß ich
>nicht wie ich den sichern soll, ohne das er abläuft.

Nicht Sichern, sondern Initialisieren .

MfG Spess

von Toni (Gast)


Lesenswert?

Schau dir mal die Reihenfolge beim Push und POP an!

Richtig wäre z.B.

push zl
push zh; Speichere auf Stack

pop zh
pop zl; Vom Stack zurückholen.

Stelle Dir den Stack vor als einen Stapel auf dem
Du ein Blatt Papier nach dem anderen ablegst.
Welches liegt dann immer oben?
Richtig das zuletzt hingelegte!

von Vivil (Gast)


Lesenswert?

Du hast nicht jede zeile Kommentiert sonst würde dir mehr auffallen.

Mensch Maier wir sollen Dir helfen. So mach auch das was Dir gesagt 
wird.

Hättest Du jeden Befehl kommentiert würdest du ein der schwachsinnigen 
aktionen wie

led1:
  sbi portd, 0
  cbi portd, 1
  rcall taster1

  taster1:
      sbic pinb, 1




sehen

von Vivil (Gast)


Lesenswert?

Toni schrieb:
> Bin ich leseschwach oder suche ich vergebens nach "RET"?
>
> Am Ende eines Unterprogramms nötiger Befehl.

Net nachbabeln. Auch das Push würde Ihn nicht helfen. Genau so wenig 
eine Stackinitialisierung die aber sein muss.

Er hat nicht verstanden was er hier macht. Und das verständniss sollte 
erst mal da sein. Auch wenn er die Stackinitialisierung macht haut es 
ihm sein PROGRAMM auseinander. wegen einem StackOverFlow

von oldmax (Gast)


Lesenswert?

Hi
Also, dein Stack ist ja initialisiert. Nun wird bei jedem RCAll die 
Rücksprungadresse dort eingetragen und bei einem Ret wieder weggenommen.
Was dein Assemblerprogramm betrifft...... tja, da ist noch ein weiter 
Weg.
Zuerst, ja, die Initialisierung gehört vor die Programmschleife. Aber 
was um himmelswillen haben Push und POP in der Schleife zu suchen ? Wer 
hat dir denn sowas gezeigt ?
Zum anderen , es ist nicht grad geschickt, die Abfage der Taster in 
Unterprogramme zu packen, die du aufgrund der Tasterbetätigung aufrufst. 
Und wenn du die Taster nach GND schaltest, ist die Bedingung für den 
Aufruf immer da, solange du die Taster nicht drückst, weil die 
zugeschalteten Pull-Ups natürlich "1"-Signal auflegen.
Mein Vorschlag:
Lies zuerst die Eingänge in einer kleinen Sub-Routine in eine Variable.
1
Read_IO:
2
    In    Reg_A, PIn(x)      ; Irgendeinen Port lesen 
3
    LDI   Reg_B, 0b11111111  ; Bits invertieren, da Abfrage nach GND
4
    EOR   Reg_A, Reg_B       ; damit ist ein gedrückter Schalter auch "1"
5
    ANDI  Reg_A, 0b00001111  ; ungültige Bits ausmaskieren
6
    STS   New_In, Reg_A      ; Bspw. die Portbits 0-3 sind Eingänge
7
RET
Nun hast du einen ganzen Zyklus Zeit, mit diesen Informationen zu 
arbeiten. Es können ja nur die Bits 0-3 gesetzt sein, ja nachdem, welche 
Schalter dedrückt sind. Entsprechend bearbeitest du eine Variable auf, 
die für die Ausgabebits steht.
1
Loop:
2
   RCALL Read_IO             ; Einlesen der Eingänge
3
   LDS   Reg_A, New_I
4
   ANDI  Reg_A, 0b00000001   ; ist Portbit 0 beschaltet ?
5
   BREQ  Next_Bit1           ; Wenn nicht nächsten Eingang prüfen
6
   RCall Action_eins         ; Reaktion auf Eingang 0
7
                             ; Ausgang schreib in Variable z.B. Out_Port
8
Next_Bit1:
9
   ....                      ; weitere Bearbeitung
10
   RCALL Write_IO            ; hier schreibst du die Bits aus Port_Out in
11
                             ; den Ausgabeport
12
   RJMP Loop
 Das ist die klassische "EVA" Methode: Einlesen, Verarbeiten, Ausgeben
Für die einzelnen Bearbeitungen rufst du Subroutinen auf.
1
Action_eins:
2
  ....
3
RET
4
5
Action_zwei:
6
  .....
7
RET
8
 usw.
Niemals das RET vergessen und, bevor ich es vergesse: du brauchst kein 
Push und POP. Erst, wenn du dich an Interrupt-Programme heranwagst, mußt 
du Registerwerte sichern. Es gibt zwar auch noch andere Verwendung 
dieser Befehle, aber da bist du noch weit von weg.
Gruß oldmax

von Vivil (Gast)


Lesenswert?

@oldmax

Meinst du so lernt er was?
Selber hinter die Fehler kommen bringt was.

Und wenn er es nicht schafft seine Gedankengänge aufzuzeigen will er 
wohl auch nix lernen sondern sucht nur eine fertige lösung.

von oldmax (Gast)


Lesenswert?

Hi
@Vivil
Nun, so ein wenig Anleitung zur Vorgehensweise schadet nicht. So krass 
wie du seine Fähigkeiten beurteilst, würd ich nicht vorgehen. Jeder hat 
seine ersten Schritte mal getan und bis zum perfekten Samba sind dann 
doch ein paar Jährchen vergangen... auch mit viel (liebevoller) 
Anleitung.
Also, gebt ihm eine Chance. Bisher hat er ja nicht gesagt: "Macht mir 
mal ein Programm....."
Gruß oldmax

von Paul H. (plan)


Lesenswert?

Vielen Dank oldmax, das weiß ich zu schätzen.

von Walter (Gast)


Lesenswert?

Paul H. schrieb:
> Ich wäre dankbar, wenn mir jemand die Fehler in meinem Programm erklären
> könnte und einen passenden Code schreiben könnte.

oldmax schrieb:
> Bisher hat er ja nicht gesagt: "Macht mir
> mal ein Programm....."
> Gruß oldmax

von *kopfkratz* (Gast)


Lesenswert?

Walter schrieb:
> Paul H. schrieb:
>
>> Ich wäre dankbar, wenn mir jemand die Fehler in meinem Programm erklären
>
>> könnte und einen passenden Code schreiben könnte.
>
>
>
> oldmax schrieb:
>
>> Bisher hat er ja nicht gesagt: "Macht mir
>
>> mal ein Programm....."
>
>> Gruß oldmax

Das alles erbsenzählerei...

Wenn man genau so viel Energie reinstecken würde, wie die negativen 
Bemerkungen, dann würden einige schneller und besser lernen.

Respekt @oldmax, weiter machen...

BR

von Vivil (Gast)


Lesenswert?

Hätte der TE mal seine Gedankengänge aufgezeigt und sich die ARBEIT 
gemacht diese zu Kommentieren so wäre ihm schon mehr geholfen als er es 
bräuchte.

Nur wer selbst nix machen möchte der sollte auch nix vor die Füsse 
geschmissen bekommen.Wie war das mit den Perlen?????

Sein Code zeigt klar auf das er nicht die Bohne wusste was er da tat. 
Dieses sollte sich ändern aber nicht damit das man es Ihm schreibt. 
Selbsterkentniss ist der einzige weg wie man lernen kann.

Nun eventuell bekommt er es hin seine Taster ab zu fragen aber gekonnt 
hat er nix da er vieles noch nicht verstanden hat. Und genau darum geht 
es das Verständniss schaffen.

Aber Ihr macht das schon grins

von Paul H. (plan)


Lesenswert?

Vivil ich verstehe ja, dass wenn man seine Fehler selbst korregiert mehr 
und besser lernt.
Das Problem ist aber, dass ich sie nicht sehe, da ich wenig Erfahrung 
hab.
So nun meine Fragen:
Wie kann ich den Stack-Over-Flow beheben ?
Mit einer Stack initialisierung ist es doch nicht getan oder ?
Und die Sequenz von oldmax
1
Read_IO:
2
    In    Reg_A, PIn(x)      ; Irgendeinen Port lesen 
3
    LDI   Reg_B, 0b11111111  ; Bits invertieren, da Abfrage nach GND
4
    EOR   Reg_A, Reg_B       ; damit ist ein gedrückter Schalter auch "1"
5
    ANDI  Reg_A, 0b00001111  ; ungültige Bits ausmaskieren
6
    STS   New_In, Reg_A      ; Bspw. die Portbits 0-3 sind Eingänge
7
RET

wenn ich das richtig verstanden hab, muss man den Wert am Pinx einlesen
mit einem EOR und 0xFF Filtern und den Rest der Bits löschen.

Da mein Programm so wunderbar ist.. **hust** könnt ihr mir sagen, wo ich 
die Grundlagen erlernen kann? links oder Buchvorschläge wären sehr gut.
Mit dem Tutorial auf dieser Seite komme ich nicht ganz zurecht.

LG Paul

von Vivil (Gast)


Lesenswert?

Ich kann wieder nur schreiben. Kommentiere jeden deiner Befehle in 
deinem Code und schon wirst du es bemerken und etwas lernen.

von Steffen H. (avrsteffen)


Angehängte Dateien:

Lesenswert?

Hallo Paul

Ich finde das Tutorial echt super hier. Angefangen zu programmieren hab
ich ebenfalls in Assembler. Das ist für eine Simulation viel besser als
"C". (Meine Meinung)

Ich hatte damals das Buch "AVR-RISK Mikrocontroller" vom Franzis Verlag.
Die darin verwendeten Controller sind zwar veraltet, aber dafür ist die
Hardware super beschrieben und auch viele Programm Beispiele mit
Erklärung dabei.

Grüße Steffen

von Steffen H. (avrsteffen)


Angehängte Dateien:

Lesenswert?

Hab dir mal eine Seite wo der Stack erklärt ist rausgesucht. Ich hoffe 
man kann es lesen..

von Paul H. (plan)


Lesenswert?

Vielen Dank Steffen ;)

von Lordi (Gast)


Lesenswert?

Moin hast du dir das schon durchgelesen ?

http://www.mikrocontroller.net/articles/AVR-Tutorial:_Stack

Gruß

Lordi

von oldmax (Gast)


Lesenswert?

Hi
Nun, die Tutorials hier sind auch für mich sehr hilfreich gewesen und 
haben mir den Einstieg in die µC Welt erleichtert. Allerdings muß ich 
gestehen, das ich bereits in den 80ern mit Assembler und Z80 erste 
Begegnungen hatte. Ok, genug Geschichte. Schau mal bei den Kollegen von 
AVR-Praxis rein. Die haben einen Artikel zu "Keine Angst vor Assembler" 
unter FAQ's. Vielleicht hilft er dir etwas weiter. Wie andere und auch 
ich bereits erwähnten, ist die Kommentierung von Programmen hilfreich. 
Wenn du deine Gedanken, wie der Schritt arbeiten soll, aufschreibst, 
wird dir manchmal schon bei der Programmierung klar, das es so nicht 
funktionieren kann.
Zu meinen Erklärungen, Portbits einzulesen.
Du musst wissen, wir alle sitzen zig Kilometer von dir und deinen 
Gedanken weit weg. Immer mitzuschreiben, welche Portbits du einliest ist 
müßig, daher schreib ich einfach PortX. Welcher Port das sein soll, 
keine Ahnung, aber du weißt es und brauchst also nur den Buchstaben 
dafür einzusetzen. Nun zu den Bits.
Wenn du über In einen Port einliest, hast du immer die 8 Byte, also auch 
bits, die dich nicht interessieren. Wenn du aber deine Eingänge nach 
"0", also GND beschaltest, ist der Eingang immer wenn er nicht gedrückt 
ist "1" durch den internen Pull-Up Widerstand. Wenn du also ein 
Bitmuster 01011000 liest, ist der Schalter Bit 5 und Bit 7 
möglicherweise betätigt. Die Bits 0-2 sind keine Eingänge, erscheinen 
aber wie gedrückte Schalter. Also mußt du alles, was nicht von Interese 
ist ert einmal ausblenden. Da aber "0"en zu Denkfehlern führen, drehe 
ich erst mal die Bits mit einer EOR Anweisung. Danach sind die Bits mit 
den betätigten Eingängen "1". Nun wird über eine Und-Anweisung noch 
ausgeblendet, was nicht zu den Eingängen gehört. Geht sicherlich auch 
anders, aber an dieser Stelle habe ich nun die Möglichkeit, eine Flanke 
von einem Signal zu erfassen. Wie auch immer, jeder hat so seine 
Vorlieben, was den Programmierstil betrifft. Die Autoren von Büchern 
schreiben so oft Liebesromane, aber alle unterschiedlich, obwohl am Ende 
Adam seine Eva kriegt....
Gruß oldmax

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
Noch kein Account? Hier anmelden.