Programm verlangsamen Atmega8 Assembler

Gast #728769
Lesenswert?

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
Gast #728818
Lesenswert?

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
Gast #728873
Lesenswert?

>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.
Gast #728881
Lesenswert?

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.
Gast #728887
Lesenswert?

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
Gast #728901
Lesenswert?

>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...
Gast #728927
Lesenswert?

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.
#728950
Lesenswert?

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 :-)
Gast #728975
Lesenswert?

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
Gast #728979
Lesenswert?

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.)
#728980
Lesenswert?

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 :-)

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren