Hallo, Im Rahmen eines Schulprojektes baue ich gerade einen mobilen Roboter. Nachdem ich es geschafft habe die Schrittmotoren anzeusteuern, möchte ich nun deren gemachte Schritte im SRAM speichern, sowie die dazu gehörende Richtung. In der angehängten Datei ist der Code für eine Testversion mit einem Schrittmotor. Es gibt vereinfacht fünf Richtungen, Vor1,Vor2... und STOP. Die Richtung soll im SRAM gespeichert werden, die zwei folgenden Bytes im SRAM, nach der zugehörigen Richtung, sollen für die Schrittzählung genutzt werden. Somit hat Jede Richtung mit ihren Schritten 3 Bytes Reservierung. Aus irgendeinem Grund wird jedoch nichts gespeichert. Warum speichert er nichts ab? Ich weiß nicht mehr weiter, habe schon alles durchsucht. HILFE! Danke im Voraus!
Hi Poste bitte ein assemblierbares Programm. Und nicht als *.txt sonder als *.asm. MfG Spess
Sry für die zwei Fehler im Programm, das eigentliche Programm ist größer und ich habe es nur auf das Nötigste um den Fehler zu finden reduziert. Im Anhang nochmal die Datei als ASM.
Hi Ohne das nochmal angesehen zu haben, stellt sich die Frage, warum du den Zirkus mit dem Z-Pointer veranstaltest. Lege einfach Speicherplätze mit passenden Labels für deine Variablen im RAM an. Auf die kannst du mit 'sts/lds' einfach darauf zugreifen. MfG Spess
da der Code nicht so lange ist hänge ichs mal direkt an, war ein sehr frühes Projekt von mir und ich habe da mit Variablennamen gearbeitet. Wenn du aber mit Pointern arbeitest kannst du es ja auch ab Speicherstelle X direkt reinschreiben. .DSEG ;Reserve jeweils 1 Byte / Variabl eim SRAM Voll1: .byte 1 Voll2: .byte 1 Voll3: .byte 1 Voll4: .byte 1 Halb1: .byte 1 Halb2: .byte 1 Halb3: .byte 1 Halb4: .byte 1 Halb5: .byte 1 Halb6: .byte 1 Halb7: .byte 1 Halb8: .byte 1 .CSEG .ORG 0x00 rjmp init init: ;Stackpointer initialisieren ldi temp, RAMEND out SP, temp ldi temp, 0b10100000 ;Speichere Schrittfolge im SRAM um Register zu sparen sts Voll1, temp ldi temp, 0b10010000 sts Voll2, temp ldi temp, 0b01010000 sts Voll3, temp ldi temp, 0b01100000 sts Voll4, temp ldi temp, 0b10100000 sts Halb1, temp ldi temp, 0b10000000 sts Halb2, temp ldi temp, 0b10010000 sts Halb3, temp ldi temp, 0b00010000 sts Halb4, temp ldi temp, 0b01010000 sts Halb5, temp ldi temp, 0b01000000 sts Halb6, temp ldi temp, 0b01100000 sts Halb7, temp ldi temp, 0b00100000 sts Halb8, temp oder halt .dseg Tabelle: .byte 12 und mittels Pointer auf die 12 letzten Bytes im SRAM wandern also immer + - für einen Schritt oder eben keinen neuen Schritt übertragen
Sry ich glaube ich habe mich missverständlich ausgedrückt oder etwas nicht verstanden. Ich möchte später mit dem Roboter eine Strecke fahren, und dan wieder abrufen können. das bedeutet z.B. 1567 Schritt geradeaus, 67 Schritt links, 405 nach hinten uns, nur ganz grob dergestellt. Die richtung und die schrittanzahl soll jeweils gespeichert werden. der code im anhang ist nur ein test mit einem moter.
das heist dein Roboter hat 2 Räder mit Schrittmotoren wodurch man auch wie beim Panzer lenken kann. Dann benötigst du 2 weitere Tabellen also für jedes Rad eine, wenn da jetzt drinsteht beide Räder 255 Schritte drehen um nach vorne zu fahren, musst du deinen Pointer z.B. 255 nach rechts über meine Tabelle wandern lassen und immer den ausgelesenen Wert an die Schrittmotortreiber ausgeben. Wenn du andersherum fahren willst musst du links über meine Tabelle wandern.
Hi >Sry ich glaube ich habe mich missverständlich ausgedrückt oder etwas >nicht verstanden. Die Bitmuster würde ich auch nicht im RAM speichern. Aber -Z/Z+ sind nicht unbedingt das geeignete Mittel um auf bestimmter RAM-Zellen zuzugreifen. Das ist sehr unübersichtlich. Besser du benutzt die Adressierung über Index:
1 | ; Offsets |
2 | |
3 | .equ steps_low = 0 |
4 | .equ steps_high = 1 |
5 | .equ direction = 2 |
6 | |
7 | .dseg |
8 | |
9 | Motor1: .Byte 3 |
10 | Motor2: .Byte 3 |
11 | |
12 | .cseg |
13 | |
14 | ; Schritte für Motor1 speichern |
15 | |
16 | ldi ZL,Low(Motor1) |
17 | ldi ZH,High(Motor1) |
18 | |
19 | std Z+steps_low,r16 |
20 | std Z+Steps_high,r17 |
21 | |
22 | ; Schritte für Motor2 speichern |
23 | |
24 | ldi ZL,Low(Motor2) |
25 | ldi ZH,High(Motor2) |
26 | |
27 | std Z+steps_low,r16 |
28 | std Z+Steps_high,r17 |
29 | |
30 | ; Schritte für Motor1 laden |
31 | |
32 | ldi ZL,Low(Motor1) |
33 | ldi ZH,High(Motor1) |
34 | |
35 | ldd r16,Z+steps_low |
36 | ldd r17,Z+Steps_high |
37 | |
38 | ; und so weiter |
Die Bitmuster für die Schritte würde ich im Flash ablegen:
1 | ; Schrittnummer in r16 |
2 | ; Richtung in r17 1 vorwärts |
3 | ; -1 ($FF) rückwärts |
4 | |
5 | |
6 | ldi ZL,Low(steps<<1) |
7 | ldi ZH,High(steps<<1) |
8 | |
9 | add r16,r17 |
10 | andi r16,0b00000011 |
11 | clr r17 |
12 | add ZL,r16 |
13 | adc ZH,r17 |
14 | lpm r16,Z ; nächstes Bitmuster |
15 | ; in r16 |
16 | |
17 | |
18 | steps: .db 0b11000000,0b01100000,0b00110000,0b10010000 |
MfG Spess
Ja, das mit dem Flash werde ich wohl übernehmen. Jedoch weiß ich nicht, wie das mit den 3 Bytes für jeden Motor funktionieren soll, da eine Strecke aus mehreren Abschnitten besteht, in denen der Roboter verschiedene Richtungen fährt. Es werden für eine Stecke mit 40 Richtungswechseln also 40x 3 Bytes für jeden Motor benötigt, einmal die Richtung und die dazu gehörige Anzahl an Schritten. Das wären dann mal eben 240 Bytes, die reserviert sein müssten, um eine einfache Stecke zu speichern.
Hi Dann muss ich mal dumm fragen, wie du die Strecke in den Roboter bekommst und wo du die speichern willst? Das Ganze lässt sich übrigens auch auf eine Streckenliste im RAM anwenden. Du musst nur aus der Länge der Parameter und der Nummer des Streckensegments die Adresse für Z ausrechnen. MfG Spess
Wie die Stecke in den Roboter kommt ist erstmal belanglos. Gedacht war es, dass der Roboter ferngesteuert wird und beim manuellen Betrieb die Strecke abspeichert und dann zurück fahren kann. Das kann aber auch erstmal über die serielle Schnittstelle simuliert werden.
Hi Eigentlich wollte ich dir nur zeigen, wie man von einer Basisadresse in Z verschiedene Werte in einem 'Datensatz' ausliest. MfG Spess
Ich denke dein Hauptfehler besteht darin, dass du relativ planlos an die Sache herangehst und aufs geratewohl losprogrammierst. Das geht mit etwas Übung in C, in Assmbler ist sowas aber tödlich. Fang damit an, dir deine Datenstruktur im Speicher zu formulieren. Und als nächstes beschreibst du deinen Programmaufbau in Prosa, ohne dich zunächst um die konkrete Implementierung zu kümmern.
1 | -- Voraussetzung: Z-Pointer zeigt auf den Anfang einer 3 Byte |
2 | -- Sequenz |
3 | -- die ersten beiden Bytes beschreiben die Anzahl der Schritte |
4 | -- das dritte Byte gibt die Richtung, in die gefahren werden soll |
5 | -- ist die Anzahl der Schritte gleich 0, dann bedeutet das: |
6 | -- Ende der Tabelle |
7 | |
8 | |
9 | |
10 | -- Z-Pointer vorbereiten, in dem er an den Anfang der |
11 | -- Beschreibung aller Teilstrecken gesetzt wird. |
12 | |
13 | -- Punkt B: den Schrittzähler laden (über den Z-Pointer) |
14 | |
15 | -- Anzahl Schritte 0 ? |
16 | -- Ja --> Ende der Strecke, gehe zu Punkt C |
17 | |
18 | -- Punkt A: mache diese Anzahl von Schritten |
19 | -- Dazu UP "1-Schritt aufrufen", welches 1 Schritt durchführt |
20 | |
21 | -- Schrittanzahl um 1 verringern |
22 | |
23 | -- Anzahl gleich 0 geworden? |
24 | -- Nein: gehe zu Punkt A |
25 | |
26 | |
27 | -- offenbar ist dieses Teilstück abgearbeitet, nächstes Teilstück |
28 | -- vorbereiten, indem der Z-Pointer auf den Anfang dieses Teil- |
29 | -- stückes gesetzt wird. Da der Z-Pointer immer auf den Anfang |
30 | -- zeigt, und ein Teilstück durch 3 Bytes beschrieben wird, |
31 | -- reicht es daher den Z-Pointer um 3 zu erhöhen |
32 | |
33 | |
34 | -- der Z-Pointer steht jetzt richtig |
35 | -- Teilstück abarbeiten lassen, dazu |
36 | -- gehe zu Punkt B |
37 | |
38 | |
39 | -- Punkt C: |
40 | -- alle Teilstrecken abgearbeitet, fertig |
Das ist jetzt nicht die einzgie Möglichkeit, wie man das organisieren kann. Ja nachdem kann man das auch ganz anders machen, wenn zb Interrupts ins Spiel kommen. Richtungswechsel sind auch nicht eingearbeitet (ist ja schliesslich dein Projekt). Der springende Punkt ist aber: Bereite dir erst mal in derartigen groben Plänen, die durchaus als Kommentare in deinen Code kommen können, kommen sollen, deine Arbeit vor! Du kannst zb ruhig erst mal den geplanten Ablauf in Form von Kommentaren in dein Programm schreiben. Diesen Ablauf gehst du dann auf logischer Ebene ein paar mal durch und siehst zu, dass du Fehler in der Logik findest. Und erst dann, wenn deine Logik soweit steht, fängst du an, in den Zwischenräumen zwischen den Kommentaren, den jeweiligen Code einzufügen, der die Aktion des vorhergehenden Kommentares implementiert. Abgesehen von kleinen Assemblerprogrammen, musst du eine derartige Vorgehensweise benutzen, wenn du dich nicht in selber in der Komplexität deines Programmes verlieren willst. Erst muss der Plan stehen, dann kann man ihn implementieren. Und nein. Gerade als Neuling reicht es nicht, wenn man so ungefähr eine vage Vorstellung davon hat, wie das ganze funktionieren soll. SChreib dir die Dinge auf, geh sie durch, wieder und immer wieder. Bis du keinen logischen Fehler mehr entdecken kannst. Da sind dann immer noch Fehler drinnen, aber zumindest das logische Konzept ist dann zumindest soweit gediehen, dass die noch verbleibenden Fehler korrigierbar sind und keine allzugroße Auswirkungen auf das Gesamtkonzept mehr haben, wenn man sie in der Simulation erst mal gesehen hat. Und noch was. Wenn dein SChrittzähler als 16-Bit Zähler ausgeführt ist, dann arbeite auch mit 16 Bit!
Danke für deine Hilfe, ich werde das Programm nochmal neu strukturieren. Bei Bedarf melde ich mich nochmal. Danke auch für alle anderen Beiträge!
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.