Forum: Mikrocontroller und Digitale Elektronik Programm verlangsamen Atmega8 Assembler


von Werner (Gast)


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

von Olli (Gast)


Lesenswert?

Versuchs mal mit dem Debugger :-)

von M. V. (-_-)


Lesenswert?


von rene (Gast)


Lesenswert?

Ich hab da mal n' timer interrupt geschrieben.
http://www.ibrtses.com/embedded/avrasmuartint.html

von Werner (Gast)


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

von uninteressent (Gast)


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.

von Werner (Gast)


Lesenswert?

Also das Programm lädt immer verschiedene Konstanten in Regsiter nud 
gibt diese auf den Ports aus.
was bedeutet "gepollt"?

von uninteressent (Gast)


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.

von Werner (Gast)


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

von Werner (Gast)


Lesenswert?

Kann man eigentlich auch einen Uhrenquarz als Taktgeber verwenden?

von uninteressent (Gast)


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...

von lontano (Gast)


Lesenswert?

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!

von Werner (Gast)


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.

von Karl H. (kbuchegg)


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

von Werner (Gast)


Lesenswert?

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.

von spess53 (Gast)


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

von lontano (Gast)


Lesenswert?

Mit Uhrenquarz verlierst du das beste was ein MC kann....

Hardwareaenderung ?  Wozu gibt es SOFTWARE !?

ic nic verstehn...und habe fertig

von mr.chip (Gast)


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

von Karl H. (kbuchegg)


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

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.