Assembler für Assembler - Anfänger (bin selber noch einer)

Hier nochmal das Ende vom Code:
Code:
            brcs   nachladen
            rjmp   weiter
nachladen:  ldi    temp1,115  
weiter:
Warum hast Du hier 2 Sprünge?
Du brauchst nur einen!
Entweder Du überspringst 'nachladen' oder Du läßt es bleiben.

Gruß, Wolfgang
 
Hallo Rolf

So löst du den Sprung aus, wenn du bei der vorhergehenden Operation
Code:
Dec Temp1
das Carry-Bit setzt. Es sind halt bedingte Sprünge. Ist das Bit gesetzt, dann wird der BRCS ausgeführt, wenn nicht, dann mach mit dem nächsten Befehl weiter. Ich hab das Gefühl, du machst es dir selber schwer. Think simple. Assembler ist grad eine Sprache, die wirklich nicht einfacher aufgebaut sein kann.
Gruß oldmax

Code:

;da liegt mein Denkfehler wenn ich mit
;breq so weiter mache..als Beispiel:

dec temp1 ;r17=0>>Z=1
breq reinit ;Verzweig. wenn Z=1
ldi akku,0x07
out PORTB,akku
reinit: ldi temp1,115
reti
;reinit: wird ja jedesmal ausgeführt, ob mit
;oder ohne Verzweigung
 
Warum hast Du hier 2 Sprünge?
Du brauchst nur einen!
Entweder Du überspringst 'nachladen' oder Du läßt es bleiben.

Gruß, Wolfgang

das hab ich ja versucht, aber dann läuft nichts mehr...alle 3LEDs =EIN
Das sieht dann so aus:

Code:
;Interrupt-ISR

TIMER0_OVF:
            push   akku
            in     akku,SREG
            dec    temp1       
            cpi    temp1,23
            brcs   nachladen
            
nachladen:  ldi    temp1,115  
            

            out    SREG,akku
            pop    akku   
            reti

Oder sollte es wieder meine Problemchen mit den brxx sein?
 
Code:
            cpi    temp1,23
            brcs   nachladen
           
nachladen:  ldi    temp1,115
Dieser Sprung ist doch jetzt vollkommen für die Katz!
Wenn Du den 'brcs' weg läßt landest Du an der gleichen Stelle, wie wenn Du ihn stehen läßt.
Wenn das Carry-Flag gesetzt ist landest Du bei 'nachladen' weil Du springst und wenn es nicht gesetzt ist wird der Sprung nicht ausgeführt und Du landest deshalb an der gleiche Stelle: 'nachladen'.
 
Du hast schon Recht, hier lag ja auch mein Denkfehler. Geht man davon aus temp1 wäre bei 23 angekommen, so zeigte mir
der Debugger, daß C noch auf 0 lag. Jetzt dachte ich, der Sprung nach "nachladen"wird nicht ausgeführt, also diese
Kommandozeile "nachladen: temp1,115" übergangen. Das dem nicht so ist hat mich erst LotadaC drauf gebracht.
Erst als temp1=22 war wurde C gesetzt.
Aber es läuft jetzt zu meiner Zufriedenheit und ändere jetzt nichts mehr dran..sonst komme ich ins "UFERLOSE"!
Ich glaube, ich bin schon bei Seite 9 angekommen.

Nochmals meinen Dank an Alle die mitgewirkt haben bei mir Licht ins dunkle zu bringen

Rolf
 
Code:
gehe03:    
           cbi     PORTB,PB0     ;PB2-PB0 = 0
Ende:      rjmp    loop
                   
;Interrupt-ISR

TIMER0_OVF:
            push   akku
            in     akku,SREG
            dec    temp1       
            cpi    temp1,23
            brcs   nachladen
            rjmp   weiter
nachladen:  ldi    temp1,115  
            
weiter:
            out    SREG,akku
            pop    akku   
            reti
           .EXIT

gehe03: habe ich verjüngt und die ISR abgeändert. Auffallend war, als ich noch kein "rjmp weiter" hatte, lief garnichts
mehr...alle LEDs leuchten...
Waahhhh.... Warum das denn jetzt schon wieder?
Das mit dem Reload hattest Du Doch eigentlich hier schon richtig (bis auf das Registerretten und den Reloadwert(*)):
...
Code:
          ldi     temp1,115     ;lade r17 mit 115 (dez.)
            
          
loop:      cpi     temp1,92      ;wenn temp1 kleiner 92..C=1
           brcs    gehe01        ;dann  Verzweigung "gehe01"
           ldi     akku,0x07
           out     PORTB,akku
           rjmp    Ende   
           
gehe01:    cpi     temp1,69      ;wenn temp1 kleiner 69..C=1
           brcs    gehe02        ;dann Verzweigung "gehe02"
           cbi     PORTB,PB2     ;PB1-PB0 = 1 (PB2=0)
           rjmp    Ende   

gehe02:    cpi     temp1,46      ;wenn temp1 kleiner 46..C=1
           brcs    gehe03        ;dann Verzweigung "gehe03"
           cbi     PORTB,PB1     ;PB0 = 1 (PB2 und PB1=0)
           rjmp    Ende         

gehe03:    cpi     temp1,23      ;wenn temp1 kleiner 23..C=1
           brcs    Ende          ;dann Verzweigung "Ende"
           cbi     PORTB,PB0     ;PB2-PB0 = 0
Ende:      rjmp    loop
                   
;Interrupt-ISR

TIMER0_OVF:
            dec    temp1       ;(r17-1) wenn r17=1>>Z=0
            brne   hinterinit  ;Verzweigung, wenn Z=0
            ldi    temp1,115  
            ldi    akku,0x07
            out    PORTB,akku
hinterinit:
           
            reti
          .EXIT

Von Beginn an erlöschen die 3 LEDS an PB2 bis PB0 im ca. 5 Sek. Rythmus....alles ok.
Das Umschalten (wenn alle LEDs=0) zum Leuchten dauert das doppelte.
Vom logischen Ablauf in "gehe03" muß es auch dazu kommen, denn ab Zählerstand 45 bis runter 23 wird
PB0 ständig auf LOW gesetzt.
Bis aber der Zähler temp1 in der ISR zu Null kommt dauert es nochmal 23.
...
Eigentlich willst Du doch folgendes:
-von 92 bis 69 -> alle LEDs an (1)
-von 68 bis 46 -> B2=0 (2)
-von 45 bis 23 -> B1=0 (3)
-von 22 bis 01 -> B0=0 (4)
(=->Reload) (1)

(1) erschlägst Du bereits in der ISR
(2) wäre also (temp1<69)? (cpi temp, 69 -> C=1)
(3) wäre also (temp1<46)? (cpi temp, 46 -> C=1)
(4) wäre also (temp1<23)? (cpi temp, 23 -> C=1)

Wenn Du das jetzt aber in dieser Reihenfolge abfragst, und jeweils am Ende des Zweiges zum Ende der Loop springst, erschlägt (2) auch (3) und (4). Die einfachste Lösung ist, die Reihenfolge umzukehren, also
(4)
(3)
(2)
klar? ((1) erledigt ja die ISR. Reload wäre dann 92)

Jetzt noch was zu den Interrupts und dem Stack: Sieh das nicht so kompliziert.
Der Stack ist ein LiFo-Speicher für Bytes, den die Hardware mehr oder weniger selbst verwaltet (wenn er einmal initialisiert ist, brauchst Du Dich nicht um die Adressen kümmern, das erledigen Push und Pop. Du mußt Dich dann nur um die Reihenfolge kümmern (LiFo - was zuletzt draufgepackt wurde, wird zuerst runtergenommen) Außerdem müssen sich "draufpacken" und "runternehmen" die Waage halten, klar. Solange man nicht rekursiv programmiert, oder Fehler drinnhat, läuft da auch nix über (bzw muß man dann schon ordentlich verschachteln...)).
Was ist nun zu retten?
Alles, was in der Hauptschleife verwendet wird (bzw werden könnte(*)), und in der ISR manipuliert wird. (Außer den Registern, die die ISR für die Hauptschleife verändern soll).
In Deinem Fall verändert die ISR:
-temp1: aber das ist ja genau die Aufgabe der ISR, also-> nicht retten
-akku: wird sowohl in der Hauptschleife, als auch in der ISR zum setzen der 3 LEDs verwendet (und dazu mit 0x07 beladen). Es nimmt nie (mehr) einen anderen Wert an. Strenggenommen müßtest Du es also gar nicht retten (und nur einmal vor der Hauptschleife mit 7 beladen), ABER wenn später irgendwas am Programm geändert/hinzugefügt wird, stimmt das ggf nicht mehr -> deswegen sollte man einfach alle (in der ISR) verwendeten Register (bis auf die, mit reservierten Funktionen) retten.(*)
-SREG: wird in der ISR durch DEC manipuliert -> Retten

Wohin Retten?
Generell in irgendeine freie/dafür reservierte Byte-Speicherstelle. Dafür das Eeprom oder indirekt adressiertes SRAM zu nehmen, wird zu kompliziert, direkt adressiertes SRAM könntest Du verwenden, dann mußt Du aber selbst die Adressen verwalten. Sehr ähnlich dazu wäre, nicht verwendete Rechenregister dafür zu reservieren (wenns zeitkritisch wird, eine Option.) - immerhin verwendest Du hier nur 2 der 32 Rechenregister. Dann muß man die ja ggf gar nicht dahin kopieren - da stehen sie ja schon. Aber auch hier gilt wieder das mit der zukünftigen Erweiterbarkeit.
Oder man verwendet dafür den, extra dafür eingerichteten Stack. Der verwaltet dann selbst die Adressen.
-beim IRQ (also bei der Exekution) wird automatisch die Rücksprungadresse auf den Stack gelegt (2 Bytes)
-danach legst Du Deine zu sichernden Register darauf
-jetzt kannst Du auf den entsprechenden Registern nach belieben Rumwurschteln
-Am Ende mußt Du die geretteten Register wieder vom Stack holen, in umgekehrter Reihenfolge natürlich (LiFo)
-RETI holt auch die Rücksprungadresse wieder vom Stack.
Beim SREG (als I/O-Register) ist zu beachten, daß Du es nicht direkt auf den Stack packen kannst, sondern es erst in ein Rechenregister laden mußt. folglich muß also (zumindest) dieses also vorher zu Retten (und hinterher wiederherzustellen - umgekehrte Reihenfolge).
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)