Hallo, ich habe in Assembler ein Programm für ein Cube geschrieben. Ich aber nicht so viel Ahnung in der Programmierung, fange erst an. So funktioniert das Programm ersteinmal, soweit zeigt es jedenfalls der Simulator. Ich habe nur ein Problem: Das Programm ist in ein paar Milisekunden durchgerast, da sieht man dann ja nichts. Wie kann ich das Programm verlangsamen, ohne Massenweise an Zählschleifen einzuabeuen, ein paar habe ich schon drin. mfg
Ja, also mit einem Timer könnte es man ja machen. Es müsste ja im Prinzip so sein, das immer wenn der Timer ein Intrerupt auslöst, einen Schritt im Programm witer gehen. Dafür habe ich aber noch keine Lösung gefunden, wie man das am besten umsetzten könnte. Vielleicht hat ja schon mal jemand so etwas ähnlichs gemacht und kann mir da weiterhelfen. mfg
>ich habe in Assembler ein Programm für ein Cube geschrieben.
Genauere Infos zu Programm? Was tut es?
idR. verwendet man Timer so, dass man eine (volatile) Variable ändert,
welche in der Mainloop gepollt wird und bei deren Änderung dann
entsprechende Aktionen folgen.
Also das Programm lädt immer verschiedene Konstanten in Regsiter nud gibt diese auf den Ports aus. was bedeutet "gepollt"?
Pollen = Immer wieder Abfragen >Also das Programm lädt immer verschiedene Konstanten in Regsiter nud >gibt diese auf den Ports aus. Sehr aussagekräftig. Wenn du uns keine Informationen gibst, kann dir keiner helfen. Derzeit kann ich nur sagen: Nimm einen Quarz/Oszillator mit einer entsprechend niedrigeren Frequenz.
also habe mal das Programm hier:
1 | .include "m8def.inc" |
2 | .def temp = r17 |
3 | .def ebene1 = r23 |
4 | .def ebene2 = r24 |
5 | .def ebene3 = r25 |
6 | .org 0x0000 |
7 | rjmp main ; Reset Handler |
8 | .org OVF0addr |
9 | rjmp timer0_overflow ; Timer Overflow Handler |
10 | |
11 | main: |
12 | ldi temp, LOW(RAMEND) ; Stackpointer initialisieren |
13 | out SPL, temp |
14 | ldi temp, HIGH(RAMEND) |
15 | out SPH, temp |
16 | |
17 | ldi temp, 0xFF ; Port B auf Ausgang |
18 | out DDRB, temp |
19 | ldi temp, 0xFF |
20 | out DDRC, temp |
21 | |
22 | ldi temp, 0b00000001 ; CS00 setzen: Teiler 1 |
23 | out TCCR0, temp |
24 | |
25 | ldi temp, 0b00000001 ; TOIE0: Interrupt bei Timer Overflow |
26 | out TIMSK, temp |
27 | sei |
28 | ldi ebene1, 0b10000000 |
29 | ldi ebene2, 0b01000000 |
30 | ldi ebene3, 0b00100000 |
31 | ;T dreht sich über die Außenwände: |
32 | |
33 | ;2, 2, 1,2,3 ;1.Seite |
34 | ;6, 6, 3,6,9 ;2.Seite |
35 | ;8, 8, 7,8,9 ;3.Seite |
36 | ;4, 4, 1,4,7 ;4.Seite |
37 | |
38 | ldi r16, 0b00000000 |
39 | t_dreht_sich1: |
40 | ldi temp, 0b01000000 |
41 | out PortD, temp |
42 | out PortC, ebene1 |
43 | ldi temp, 0b01000000 |
44 | out PortD, temp |
45 | out PortC, ebene2 |
46 | ldi temp, 0b11100000 |
47 | out PortD, temp |
48 | out PortC, ebene3 ;1.Seite |
49 | clz |
50 | rcall zaehlen |
51 | brne t_dreht_sich1 |
52 | |
53 | ldi r16, 0b00000000 |
54 | t_dreht_sich2: |
55 | ldi temp, 0b00000100 |
56 | out PortD, temp |
57 | out PortC, ebene1 |
58 | ldi temp, 0b00000100 |
59 | out PortD, temp |
60 | out PortC, ebene2 |
61 | ldi temp, 0b00100100 |
62 | out PortD, temp |
63 | ldi temp, 0b11111111 |
64 | out PortB, temp |
65 | out PortC, ebene3 ;2.Seite |
66 | clz |
67 | rcall zaehlen |
68 | brne t_dreht_sich2 |
69 | |
70 | ldi r16, 0b00000000 |
71 | t_dreht_sich3: |
72 | ldi temp, 0b00000001 |
73 | out PortD, temp |
74 | out PortC, ebene1 |
75 | ldi temp, 0b00000001 |
76 | out PortD, temp |
77 | out PortC, ebene2 |
78 | ldi temp, 0b00000011 |
79 | out PortD, temp |
80 | ldi temp, 0b11111111 |
81 | out PortB, temp |
82 | out PortC, ebene3 ;3.Seite |
83 | clz |
84 | rcall zaehlen |
85 | brne t_dreht_sich3 |
86 | |
87 | ldi r16, 0b00000000 |
88 | t_dreht_sich4: |
89 | ldi temp, 0b00010000 |
90 | out PortD, temp |
91 | out PortC, ebene1 |
92 | ldi temp, 0b00010000 |
93 | out PortD, temp |
94 | out PortC, ebene2 |
95 | ldi temp, 0b10010010 |
96 | out PortD, temp |
97 | out PortC, ebene3 ;4.Seite |
98 | clz |
99 | rcall zaehlen |
100 | brne t_dreht_sich4 |
101 | |
102 | |
103 | ;Untere Ebene geht nach oben: |
104 | |
105 | ldi r16, 0b00000000 |
106 | schieb1: |
107 | rcall ebeneschieben |
108 | out PortC, ebene1 |
109 | clz |
110 | rcall zaehlen |
111 | brne schieb1 |
112 | |
113 | ldi r16, 0b00000000 |
114 | schieb2: |
115 | rcall ebeneschieben |
116 | out PortC, ebene2 |
117 | clz |
118 | rcall zaehlen |
119 | brne schieb2 |
120 | |
121 | ldi r16, 0b00000000 |
122 | schieb3: |
123 | rcall ebeneschieben |
124 | out PortC, ebene3 |
125 | clz |
126 | rcall zaehlen |
127 | brne schieb3 |
128 | |
129 | timer0_overflow: ; Timer 0 Overflow Handler |
130 | reti |
131 | |
132 | zaehlen: |
133 | inc r16 |
134 | cpi r16, 0b11111111 |
135 | nop |
136 | ret |
137 | |
138 | ebeneschieben: |
139 | ldi temp, 0b11111111 |
140 | out PortD, temp ;alles auf die beiden anderen |
141 | out PortB, temp ;Ebenen multiplexen |
142 | ret |
Kann man eigentlich auch einen Uhrenquarz als Taktgeber verwenden?
>Kann man eigentlich auch einen Uhrenquarz als Taktgeber verwenden?
Natürlich.
Muss man allerdings dann die Clockfuses anpassen und Vorsicht auch beim
ISP sind eventuell auch Dinge zu beachten. So muss in PonyProg zB in der
Configurationsdatei was geändert werden, bei usbasp muss man einen
Jumper setzen usw..
Zum Programm:
Sieht sehr unübersichtlich aus, aber vllt. bin ich Asm auch einfach
nicht mehr gewohnt.
Eine Möglichkeit wäre, vor allen Ausgaben Zähleschleifen bzw. Schleifen,
die auf das Ändern eines vom Timer veränderten Registers warten.
Eine andere Möglichkeit wäre, das Programm neu zu konzeptionieren, denn
bei dem bisherigen Konzept, wäre eine softwaremässige Anpassung
umfangreich und unästhetisch (vor jedem out ein rcall auf die
Warteschleife).
Demnach würde ich vorschlagen, du verwendest den Uhrenquarz...
Haenge doch Schleifen rein wo und wie es nur geht. Der MC hat ja eh nix zu tun....so bleibt die Maschine geoelt. Lass dir nichts vorschreiben .Du bist der Schoepfer...und der bestimmt!
Naja das mit den Schleifen ist halt so eine Sache. Der µc hat zwar nichts zu tun, aber das Programm wird dann ja ewig lang und umständlich. Mit Uhrenquarz wird wohl die einfachste Lösung sein.
Werner wrote: > Naja das mit den Schleifen ist halt so eine Sache. Der µc hat zwar > nichts zu tun, aber das Programm wird dann ja ewig lang und umständlich. Schon mal was von Unterprogrammen gehört? Ein Unterprogramm, welches eine definierte Zeit wartet. Dieses UP rufst du dann an strategischen Stellen auf. Wird nicht wirklich unübersichtlich. > Mit Uhrenquarz wird wohl die einfachste Lösung sein. Jungs, ich gratuliere euch. Ihr habt es geschafft :-)
Ja kalr macht man dann die Schleifen in ein UP, wird trotzdem sehr lang, wenn man vor jeden 2. Befehl ein UP aufrufen muss. Also ich weerde einen Uhrenquarz nehmen.
Hi .... clz rcall zaehlen brne schieb3 <------------------------------------------------ timer0_overflow: ; Timer 0 Overflow Handler reti Hast du dir schon mal überlegt,was an der Stelle passiert wenn das Z-Flag gesetzt ist? MfG Spess
Mit Uhrenquarz verlierst du das beste was ein MC kann.... Hardwareaenderung ? Wozu gibt es SOFTWARE !? ic nic verstehn...und habe fertig
Ich mache das jeweils folgendermassen: Du hast ja meist eine Sequenz an Aktionen, die das Programm machen soll. Beispielsweise: LED1 an (Zustand 1), LED2 an (Zustand 2), beide LEDs aus (Zustand 3). Sind also 3 Zustände, die sequentiell Ablaufen. Du kannst also eine Schleife machen, die alle Zustände durchläuft - irgendwo in der Schleife baust du noch eine Verzögerung ein. Alternativ kannst du diesen Zustandswechsel auch in einem Timer-Interrupt machen. Wenn du Eingaben von aussen hast, kannst du diese ebenfalls die Zustände beeinflussen lassen, z.B wenn du in Zustand 1 bist und der Taster gedrückt wird, springst du direkt in Zustand 3. Den Zustand speichert man dann am besten direkt in einer Variable, der Zustandwechsel kann man gut in einem if-else oder switch-case und je nach Zustand wird dann wiederum eine bestimmte Aktion ausgelöst. State-machine nennt sich sowas und eignet sich herrvorragen zur Implementation von solchen sequentiellen Programmen. (Jetzt mehr so als Denkanstoss als eine konkrete Lösung.)
Werner wrote: > Ja kalr macht man dann die Schleifen in ein UP, wird trotzdem sehr lang, > wenn man vor jeden 2. Befehl ein UP aufrufen muss. Wozu willst du vor jeden 2.ten Befehl eine Verzögerung einbauen? Ich sagte: an strategischen Stellen rufst du das auf. zb. dann wenn deine Cube Site komplett zusammengebaut ist. Dann und nur dann brauchst du eine kurze Wartezeit, damit der Benutzer das Ergebnis auch betrachten kann. Ich habe jetzt dein Programm nicht wirklich anaylsiert, was das überhaupt macht, aber schätzomativ ist das UP zaehlen genau der richtige Punkt um dort eine Verzögerung einzubauen. (Wozu dieses UP im übrigen gut sein soll, ist nicht wirklich klar. Ich schätz mal das sollte sowas wie eine Verzögerung sein, die aber nicht funktioniert) > Also ich weerde einen Uhrenquarz nehmen. Wenn du willst. Macht ja auch Sinn einen Ferrari im 1. Gang und mit angezogener Handbremse zu fahren :-)
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.