mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Programm verlangsamen Atmega8 Assembler


Autor: Werner (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Olli (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Versuchs mal mit dem Debugger :-)

Autor: M. V. (-_-)
Datum:

Bewertung
0 lesenswert
nicht lesenswert

Autor: rene (Gast)
Datum:

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

Autor: Werner (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: uninteressent (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Werner (Gast)
Datum:

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

Autor: uninteressent (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Werner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
also habe mal das Programm hier:
.include "m8def.inc"
.def temp = r17
.def ebene1 = r23
.def ebene2 = r24
.def ebene3 = r25
.org 0x0000
        rjmp    main                  ; Reset Handler
.org OVF0addr
        rjmp    timer0_overflow       ; Timer Overflow Handler
 
main:
        ldi     temp, LOW(RAMEND)     ; Stackpointer initialisieren
        out     SPL, temp
        ldi     temp, HIGH(RAMEND)
        out     SPH, temp
  
        ldi     temp, 0xFF            ; Port B auf Ausgang
        out     DDRB, temp
     ldi    temp, 0xFF
    out    DDRC, temp
 
        ldi     temp, 0b00000001      ; CS00 setzen: Teiler 1
        out     TCCR0, temp
 
        ldi     temp, 0b00000001      ; TOIE0: Interrupt bei Timer Overflow
        out     TIMSK, temp
    sei
    ldi    ebene1, 0b10000000
    ldi    ebene2, 0b01000000
    ldi    ebene3, 0b00100000
;T dreht sich über die Außenwände:
 
;2, 2, 1,2,3    ;1.Seite
;6, 6, 3,6,9    ;2.Seite
;8, 8, 7,8,9    ;3.Seite
;4, 4, 1,4,7    ;4.Seite

    ldi  r16, 0b00000000
t_dreht_sich1:
    ldi    temp, 0b01000000
    out   PortD, temp
    out   PortC, ebene1
    ldi    temp, 0b01000000
    out   PortD, temp
    out  PortC, ebene2  
    ldi    temp, 0b11100000
    out   PortD, temp
    out  PortC, ebene3      ;1.Seite
    clz
    rcall zaehlen
    brne  t_dreht_sich1

    ldi  r16, 0b00000000
t_dreht_sich2:
    ldi    temp, 0b00000100
    out   PortD, temp
    out   PortC, ebene1
    ldi    temp, 0b00000100
    out   PortD, temp
    out   PortC, ebene2
    ldi    temp, 0b00100100
    out   PortD, temp
    ldi    temp, 0b11111111  
    out   PortB, temp
    out   PortC, ebene3      ;2.Seite
    clz
    rcall zaehlen
    brne  t_dreht_sich2

    ldi  r16, 0b00000000
t_dreht_sich3:
    ldi    temp, 0b00000001
    out   PortD, temp
    out   PortC, ebene1
    ldi    temp, 0b00000001
    out   PortD, temp
    out   PortC, ebene2
    ldi    temp, 0b00000011
    out   PortD, temp
    ldi    temp, 0b11111111  
    out   PortB, temp
    out   PortC, ebene3      ;3.Seite
    clz
    rcall zaehlen
    brne  t_dreht_sich3

    ldi  r16, 0b00000000
t_dreht_sich4:
    ldi    temp, 0b00010000
    out   PortD, temp
    out   PortC, ebene1
    ldi    temp, 0b00010000
    out   PortD, temp
    out   PortC, ebene2  
    ldi    temp, 0b10010010
    out   PortD, temp
    out   PortC, ebene3       ;4.Seite      
    clz
    rcall zaehlen
    brne  t_dreht_sich4
 

;Untere Ebene geht nach oben:

    ldi  r16, 0b00000000
schieb1:
    rcall ebeneschieben
    out   PortC, ebene1
    clz
    rcall zaehlen
    brne  schieb1

    ldi  r16, 0b00000000
schieb2:
    rcall ebeneschieben
    out   PortC, ebene2
    clz
    rcall zaehlen
    brne  schieb2

    ldi  r16, 0b00000000
schieb3:
    rcall ebeneschieben
    out   PortC, ebene3
    clz
    rcall zaehlen
    brne  schieb3
 
timer0_overflow:                      ; Timer 0 Overflow Handler
        reti

zaehlen:
    inc  r16
    cpi  r16, 0b11111111
    nop
    ret

ebeneschieben:
    ldi    temp, 0b11111111  
    out   PortD, temp      ;alles auf die beiden anderen   
    out   PortB, temp       ;Ebenen multiplexen
    ret
      

Autor: Werner (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann man eigentlich auch einen Uhrenquarz als Taktgeber verwenden?

Autor: uninteressent (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: lontano (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Werner (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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 :-)

Autor: Werner (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: spess53 (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: lontano (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mit Uhrenquarz verlierst du das beste was ein MC kann....

Hardwareaenderung ?  Wozu gibt es SOFTWARE !?

ic nic verstehn...und habe fertig

Autor: mr.chip (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.