- SF800 Solar Speicher Tutorial         
Seite 49 von 53 ErsteErste ... 394748495051 ... LetzteLetzte
Ergebnis 481 bis 490 von 524

Thema: Tutorial für alle Assembler-Anfänger _

  1. #481
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    30.09.2004
    Ort
    In der Nähe von Esslingen am Neckar
    Beiträge
    706
    Anzeige

    Powerstation Test
    Guten Morgen!
    Jemand schon wach?
    hab ne Frage was bringt das eigentlich:
    Code:
    push tmp                     ;tmp sichern 
    in tmp, SREG 
    push tmp                ;SREG sichern
    und das:
    Code:
    pop tmp                        ;SREG wiederholen 
    out SREG, tmp 
    pop tmp                        ;tmp wiederholen
    ich weiß schon dass mit den Befehlen das Statusregister und das Universalregister r16(tmp) auf dem Stack abgelgt wird und dem Befehl pop wieder vom Stack geholt wird aber was ich nicht kapier wozu das ganze? Im Statusregister werden doch die ganzen Flags gesetzt?
    Gruß Michi

  2. #482
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    29.07.2005
    Ort
    Berlin
    Alter
    40
    Beiträge
    289
    Hi,

    stell dir mal vor im Register tmp hast du wichtige Werte, die du später (nach der Interruptroutine) noch brauchst. Aber das Register tmp brauchst du auch in der Interruptroutine. Dann sichert man das alles lieber erstmal auf dem Stack und kann dann die Register benutzen wie man will und mit pop holt man sich die alten Werte wieder zurück.

    Hoffe, das ist verständlich
    Gruß
    Thomas

  3. #483
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    30.09.2004
    Ort
    In der Nähe von Esslingen am Neckar
    Beiträge
    706
    Hi,
    ok danke hab es verstanden! Ihr sichert die Register also immer kurz auf dem Stack da ihr sie kurzzeitig für nen anderen Zweck verwenden wollt!
    Was mir auffällt das es nicht immer ne Interruptroutine ist! Oft ist es ein ganz normaler abschnitt der dazwischen kommt! Aber woher weißt du wann du die Dateien speichern sollt, denn der Interrupt kommt ja ohne Vorwarnung und verändert die Register!
    Gruß Michi

  4. #484
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    29.07.2005
    Ort
    Berlin
    Alter
    40
    Beiträge
    289
    Der Interrupt kommt ohne "Vorwarnung", ja, aber du weißt do, wo er hinspringt, wenn der Interrupt aufgerufen wird. Also kann du dort dann auch die Register sichern.
    Was mir auffällt das es nicht immer ne Interruptroutine ist! Oft ist es ein ganz normaler abschnitt der dazwischen kommt!
    Da isses ja genauso, da weißte ja auch, wann er da und da ist und kannst deine Register sichern. Obwohl ich das mittem im Programm für unsinnig halte *denk* Außer man ist ganz knapp mit den Registern, weiß ja nicht.

    Gruß
    Thomas

  5. #485
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    30.09.2004
    Ort
    In der Nähe von Esslingen am Neckar
    Beiträge
    706
    Ok dass hab verstanden! Hab noch ne Frage wegen des Simulators!:
    Wenn ich mich mit Step into(F11) durch den ode klicke komme ich nie in die Interrupts! Ich bleibe immer in der Mainschleife hängen und kann so nie die Interrupts mit den ganzen Timersachen kontrollieren!! Wie macht ihr das?
    Gruß Michi

  6. #486
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    29.07.2005
    Ort
    Berlin
    Alter
    40
    Beiträge
    289
    Timer im Simulator zu simulieren ist sehr zeitaufwendig.
    Wenn du im Simulator bist, dann schau mal in deinem Workspace unter Processor -> Stop Watch und drücke dann wieder F11, da siehst, wie langsam sich die Zeit dort ändert. Ich empfehle dir, bevor du simulierst, deine ganzen Timer auf weniger als 1 Sekunde einzustellen, sonst sitzt du ziemlich lange davor.
    Also:
    1. Simulieren mit Timer, nur, wenn sie < 1 Sekunde sind
    2. Dann "Start Debugging", kennste ja schon
    3. Dann klickst du mit der Maus auf die Zeile, wo er nach dem Timerüberlauf hinspringen soll, also z.b hier:
    Code:
    .org OVF0addr
    	rjmp zeitum					;Interruptvektor für Timer0 Überlauf, hier springt
    								;das Programm hin, wenn der Timer überläuft
    Da blinkt dann also der Cursor.
    4. Dann klickst du auf "Run to Cursor. Entweder dieses Symbol ->{} oder Strg + F10 oder unter Debug -> Run to Cursor. Wenn du 1 Sekunde eingestellt hast, siehst du schon, wie lange dein Rechner braucht, bis er dort angekommen ist.
    Ich stelle meine Timer meistens auf 256-1, sodass er gleich dort hinspringt, wenn ich auf Run to Cursor klicke.

    Hoffe, dir geholfen zu haben
    Thomas

  7. #487
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    29.07.2005
    Ort
    Berlin
    Alter
    40
    Beiträge
    289
    So, hab die Ampel hinbekommen, aber leider nicht mit der Nutzung von:
    Code:
    timerwerte:
    	.dw 65536-7200, 65536-1800
    Ich zeig hier erstmal den Code, der funktioniert. Also die rote und grüne Phase sollen logischerweise länger dauern als das Umstellen von gelb auf grün oder von gelb auf rot. Ihr wisst ja, wie eine Ampel funktioniert
    Code:
    .equ time1 = 65536-7200			
    .equ time12 = 65536-1800
    Meine 2 Timer, wie man sieht, der erste ist der lange Timer (für rote und rüne Phase) und der zweite Timer ist der kurze (für das Umschalten von gelb auf grün/rot)
    Code:
    ldi tmp, HIGH(time1)
    	out	TCNT1H, tmp
    	ldi tmp, LOW(time1)
    	out TCNT1L, tmp
    Timer wird bei "reset:" vorgeladen, also am Anfang ist die Ampel rot, deswegen der lange Timer. Bei der Interruptroutine (zeitum), also wenn der Timer überläuft, wird dann abgefragt:
    Code:
    zeitum:
    	push tmp						;tmp auf Stack sichern
    	in tmp, SREG
    	push tmp						;SREG auf Stack sichern
    		cpi statusAmpel, 0b00000010	;Ist rot an?
    		breq rotgelban				;JA -> gelb dazuschalten
    		cpi statusAmpel, 0b00000110	;Ist rot UND gelb an?
    		breq gruenan				;JA -> grün anmachen
    		cpi statusAmpel, 0b00001000	;Ist grün an?
    		breq gelban					;JA -> gelb anmachen
    
    rotan:
    	ldi tmp, HIGH(time1)
    	out TCNT1H, tmp
    	ldi tmp, LOW(time1)
    	out TCNT1L, tmp					;"TCNT1H" und TCNT2L"
    	ldi statusAmpel, 0b00000010		;rot an
    	rjmp ende
    
    rotgelban:
    	ldi tmp, HIGH(time12)
    	out TCNT1H, tmp
    	ldi tmp, LOW(time12)
    	out TCNT1L, tmp					;"TCNT1H" und TCNT2L"
    	adiw ZL, 1
    	ldi statusAmpel, 0b00000110		;rot und gelb an
    	rjmp ende
    
    gruenan:
    	ldi tmp, HIGH(time1)
    	out TCNT1H, tmp
    	ldi tmp, LOW(time1)
    	out TCNT1L, tmp					;"TCNT1H" und TCNT2L"
    	sbiw ZL, 3
    	ldi statusAmpel, 0b00001000		;grün an
    	rjmp ende
    
    gelban:
    	ldi tmp, HIGH(time12)
    	out TCNT1H, tmp
    	ldi tmp, LOW(time12)
    	out TCNT1L, tmp					;"TCNT1H" und TCNT2L"
    	adiw ZL, 1
    	ldi statusAmpel, 0b00000100		;gelb an
    Folgende Info erstmal:
    0b00000010 <-- rot
    0b00000110 <-- rot und gelb
    0b00001000 <-- grün
    0b00000100 <-- gelb
    Also je nachdem was an ist, wechselt er die LEDs und lädt den Timer neu. Dieser Code funktioniert auch einwandfrei, nur nun wollt ich ja eigentlich mit dem Speichern arbeiten (wie oben schon erwähnt), aber irgendwie hab ich da einen logischen Fehler drinne, der sich einfach nicht finden lässt, also folgendes:
    Ich brauche dann oben nur noch eine Konstante für den Timer:
    Code:
    .equ time1 = 65536-7200
    [...]
    ldi tmp, HIGH(time1)
    	out TCNT1H, tmp
    	ldi tmp, LOW(time1)
    	out TCNT1L, tmp
    Dieser Timer wird wieder wie gewohnt im "reset:" vorgeladen (rot ist von Anfang an an.
    Und hier der Code der Interruptroutine:
    Code:
    zeitum:
    	push tmp						;tmp auf Stack sichern
    	in tmp, SREG
    	push tmp						;SREG auf Stack sichern
    		cpi statusAmpel, 0b00000010	;Ist rot an?
    		breq rotgelban				;JA -> gelb dazuschalten
    		cpi statusAmpel, 0b00000110	;Ist rot UND gelb an?
    		breq gruenan				;JA -> grün anmachen
    		cpi statusAmpel, 0b00001000	;Ist grün an?
    		breq gelban					;JA -> gelb anmachen
    
    ;Wenn alle drei Rechnungen != 0 ergeben, dann ist gelb an
    rotan:
    	sbiw ZL, 3
    	ldi statusAmpel, 0b00000010		;rot an
    	rjmp ende
    
    rotgelban:
    	adiw ZL, 2
    	ldi statusAmpel, 0b00000110		;rot und gelb an
    	rjmp ende
    
    gruenan:
    	sbiw ZL, 3
    	ldi statusAmpel, 0b00001000		;grün an
    	rjmp ende
    
    gelban:
    	adiw ZL, 1
    	ldi statusAmpel, 0b00000100		;gelb an
    		
    ende:
    	lpm					
    	;TIMER1 wird neu geladen
    	mov tmp, lpm_reg
    	out TCNT1L, tmp
    	adiw ZL, 1
    	mov tmp, lpm_reg
    	out TCNT1H, tmp
    
    	out PORTB, statusAmpel			;Ampel richtig umschalten
    	pop tmp					
    	out SREG, tmp
    	pop tmp				
    	reti
    Nun zur Erklärung, warum ich wie Z hoch oder runterzähle.
    Meine Werte sind ja wie folgt beschrieben:
    Code:
    timerwerte:
    	.dw 65536-7200, 65536-1800
    Am Anfang ist ja rot an, diese Lampe bleibt solange an, bis der Timer1 überläuft. Z zeigt zu diesem Zeitpunkt noch auf das LOW-Byte von 65536-7200 (oder?). Dann springt er zu "rotgelban:" dort addiert er den Zeiger mit 2, sodass er dann auf das LOW-Byte von 65536-1800 (der kurzen Zeit) zeigt. Wenn ich das nur mit 1 addieren würde, dann würde er ja auf das HIGH-Byte von der langen Zeit zeigen, also quatsch.
    So, er schreibt als LOW (kurze Zeit) in TCNT1L, addiert Z mit 1 und schreibt dann HIGH (kurze zeit) in TCNT1H.
    Jetzt zeigt Z auf das HIGH-Byte von der kurzen Zeit.
    Beim nächsten Überlauf springt er zu "gruenan", dort subtrahiert er mit 3.
    Also müsste er wieder auf das LOW-Byte von 65536-7200, also von der langen Zeit zeigen. Schreibt das dann in TCNT1L, addiert Z mit 1 und schreib das dann in TCNT1H usw. bis wieder rot ist.
    Problem ist aber, dass die Zeit anscheinend nicht stimmt. Rot bleibt richtig an, da liegt noch nicht das Problem (ist ja auch oben bei "reset:" vorgeladen). Doch RotGelb bleibt genauso lange an, obwohl ich den Timer eigentlich mit der kurzen Zeit vorgeladen habe. Und das geht dann so weiter, ein totales Durcheinander.

    Ich hoffe, ich hab das einißgermaßen verständlich rübergebracht, ist leider ein wenig lang geworden mein Beitrag
    Aber ich hoffe trotzem, dass mir einer bei meinem (kleinen?) Problem helfen kann.

    Gruß
    Thomas

  8. #488
    Neuer Benutzer Öfters hier
    Registriert seit
    04.08.2005
    Beiträge
    22
    Moin moin,

    ich habe auch ein paar Fragen.

    16-bit Timer:
    Wofür ist TCCR1A gut? Wieso haben wir TCCR1B benutzt?

    Interrupts:
    Wird eine Interruptbehandlugsroutine von einem anderen
    Interrupt unterbrochen oder nicht?

    Sonst kann es ja passieren, dass beim Laden des 16-Bit Counters wir korrupte Werte in dem Counter haben.

    Best wishes

  9. #489
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    29.07.2005
    Ort
    Berlin
    Alter
    40
    Beiträge
    289
    Hi,

    ich kann dir leider nur eine deiner Fragen beantworten.
    Interrupts:
    Wird eine Interruptbehandlugsroutine von einem anderen
    Interrupt unterbrochen oder nicht?
    Nein, soweit ich weiß nicht, deshalb sollten die Interruptroutinen so kurz wie möglich gehalten werden.

    Gruß
    Thomas

  10. #490
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    53
    Beiträge
    2.236
    Hallo Leute, wie ich sehe ist Thomas wieder und nicht mehr und hilft sogar
    anderen Leuten,

    also zu den Fragen mit den push und pops von tmp, es geht auch anders!

    wenn man genug Register zu Verfügung hat, kann man sich ein extra Register nur für die
    Interruptsroutinen deklarieren, z.B tmpi oder z.B. meinInterruptarbeitsregister .
    und damit nur in den Interrupts arbeiten, womit man dann den tmp nicht benutzen und sichern muß.

    @Tekeli,
    Der Timer 1 und Timer 2 haben mehrere Modes, man kann auch andere Sachen damit machen, als nur Zeit zu Zählen (sehe DattenBlatt seite 97 ) und Suche mal nach PWM , falls es Dir,Euch nichts sagt.
    Bei Deinem Asuro wird z.B. der Timer 1 in 8 bit PWM mode benutzt um die Geschwindigkeit der Motoren einzustellen ich will jetzt nicht näher daraf eingehen, weiß nicht was wir mit PWM hier Programmieren könnten (Außer bei Deinem Asuro)
    sehe Dir mal asuro.c an. In der Init u. in der Speed Funktion sieht man wie man das benutzen kann.
    Ich hoffe , daß Dir das reicht, am sonsten zieh Dir dashier
    rein, da ist es gut beschrieben

    @Thomas,

    Ich tippe der Fehler liegt hier irgendwo :
    Code:
    rotan:
       sbiw ZL, 3
       ldi statusAmpel, 0b00000010      ;rot an
       rjmp ende
    
    rotgelban:
       adiw ZL, 2
       ldi statusAmpel, 0b00000110      ;rot und gelb an
       rjmp ende
    
    gruenan:
       sbiw ZL, 3
       ldi statusAmpel, 0b00001000      ;grün an
       rjmp ende
    
    gelban:
       adiw ZL, 1
       ldi statusAmpel, 0b00000100      ;gelb an
    Bedenke, es steht zwar z.B. so:
    .dw 12345,12121

    drin aber in der Wirklichkeit sind das 4 Bytes
    z.B. (es Stimmt nicht mit den Werten!)

    10,20,30,40
    Die ersten zwei gehören zu 12345 die letzten zwei zu 12121

    Wenn Dein Z Zeiger auf der Low Byte von 12345 (hier 10 ) zeigt,
    Du aber den zweiten wert (12121) einlesen willst mußt Du vor lpm adiw ZL,2 machen
    (dann Z -> 30) einlesen, adiw ZL,1 (dann Z -> 40) und mit lpm einlesen.
    Willst Du irgendwann den zweiten Wert nochmal haben sbiw ZL,1 und für den ersten sbiw ZL,3

    Ich denke gelban:
    adiw ZL, 1
    wird falsch sein , damit landest Du "dazwischen" und jetzt kommt alles durcheinander,
    verstehst Du wie ich das meine ?

    Gruß Sebastian

Seite 49 von 53 ErsteErste ... 394748495051 ... LetzteLetzte

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

12V Akku bauen