- Labornetzteil AliExpress         
Seite 42 von 53 ErsteErste ... 32404142434452 ... LetzteLetzte
Ergebnis 411 bis 420 von 524

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

  1. #411
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    53
    Beiträge
    2.236
    Anzeige

    Praxistest und DIY Projekte
    Dann leg Dir eine schöne Variable an, wo Du dann speicherst, ob Du rauf oder runter möchtest, und jenachdem machst Du sbiw oder adiw, aber vorsicht, nicht außerhalb der db.
    kommen!
    achso, und belege nicht einen Register damit, sondern nur ein Bit Du weißt ja sbr cbr damit kannst Du 8 Variablen !!! in einem Register Speichern, cool was ?

  2. #412
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    30.09.2004
    Ort
    In der Nähe von Esslingen am Neckar
    Beiträge
    706
    Hallo Zusammen,
    danke dass ihr soviel Geduld habt!!
    Also muss ich immer die Reihenfolge behalten!
    Es muss also immer so aussehen oder?:
    Speicher Info 1
    Speicher Info 2
    Speicher Info 3
    -----------------------
    -----------------------
    Lade Info 3
    Lade Info 2
    Lade Info 1

    ich kann aber nicht zuerst die 2 laden! <= stimmt so, oder?
    Gruß Michi

  3. #413
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    29.07.2005
    Ort
    Berlin
    Alter
    40
    Beiträge
    289
    Hab grad gemerkt, dass meine geänderte Version von der Tonleiter gar nicht geht. Also die ohne Hilfsvariable. Hab vorhin nämlich das alte nochmal draufgebrannt und nicht gemerkt

    Wäre nett, wenn du da mal reinschauen könntest:
    Code:
    ;Programm
    ;CDurTonleiter rauf spielen
    .include "m8def.inc"
    
    .def tmp = r16               	;Mein Universallregister
    .def tonwert = r17				;aktueller Wert für den Ton
    .def lpm_reg = r0				;Mein lpm-Register
    
    .equ Summer = PB2				;Summer an B.2
    .equ time0 = 256-255			;Timer0 für die Tonleiter
    .equ time1 = 65536-3600			;Damit wird der Timer1 vorgeladen, für die Sekunde
    .equ daten_laenge = 9			;Anzahl der Werte
    
    .org 0x000
       	rjmp reset					;Interruptvektor "reset:"
    
    .org OVF1addr
    	rjmp pruefSek				;Interruptvektor "pruefSek:"
    
    .org OVF0addr
    	rjmp timerSummer			;Interruptvektor "timerSummer:"
    
    reset:
       	;Stack einrichten
       	ldi tmp, HIGH(RAMEND)      	;HIGH-Byte der obersten RAM-Adresse
       	out SPH, tmp
       	ldi tmp, LOW(RAMEND)      	;Low-Byte der obersten RAM-Adresse
       	out SPL, tmp
    
    	;Timer Register für Ton werden belegt, hier Timer 0
    	ldi tmp, (1<<CS02)			;Prescaler ist 256
    	out TCCR0, tmp				;Register TCCR0 ist für den Prescaller zuständig
    	ldi tmp, time0				;Hier wird der Timer vorgeladen
    	out TCNT0, tmp
    
    	;Timer Register für Sekunde werden belegt, hier Timer 1
    	ldi tmp, (1<<CS12) | (1<<CS10)	;Prescaler ist 1024
    	out TCCR1B, tmp
    	ldi tmp, HIGH(time1)			;Für den Timer1 (16Bit) benötigen
    	out	TCNT1H, tmp					;wir 2 Register, in denen wir den Wert
    	ldi tmp, LOW(time1)				;für die 1 Sekunde (10000) speichern ->
    	out TCNT1L, tmp					;"TCNT1H" und TCNT2L"
    
    	ldi tmp, (1<<TOIE0) | (1<<TOIE1);Hier werden Interrupts nach Timer0 Überlauf eingeschaltet
    	out TIMSK, tmp				;Register TIMSK ist dafür zuständig
    
    	;Z-Register mit DB "tonleiter1" füllen
       	ldi ZH, HIGH(tonleiter1 * 2)
       	ldi ZL, LOW(tonleiter1 * 2)	
    	
    	sbi DDRB, Summer			;B.2 als Ausgang
    	sbi PORTB, Summer			;B.2 auf HIGH stellen	
    
       	sei                    		;Interrupts zulassen
    
    ;Die Hauptschleife, die sich immer wiederholt und den Tonwert neu einliest
    main:
    	lpm                  		;Daten von tonleiter1: holen 
       	mov tonwert, lpm_reg                ;Wrt von lpm_reg in tonwert speichern
    	rjmp main					;immer wieder zurück zu main springen
    
    ;Läuft Timer1 über, so wird erstmal geprüft, ob der letzte Ton
    ;erreicht ist und der Timer1 wird neu vorgeladen
    pruefSek:
    	push tmp					;tmp sichern
    	in tmp, SREG
    	push tmp					;SREG sichern
    		rjmp tonPruefen			;springe zu "tonPruefen"
    		ldi tmp, HIGH(time1)	;Für den Timer1 (16Bit) benötigen
    		out	TCNT1H, tmp			;wir 2 Register, in denen wir den Wert
    		ldi tmp, LOW(time1)		;für die 1 Sekunde (10000) speichern ->
    		out TCNT1L, tmp			;"TCNT1H" und TCNT2L"
    	pop tmp
    	out SREG, tmp				;SREG wiederholen
    	pop  tmp					;tmp wiederholen
    	reti						;Spring wieder dahin, wo du hergekommen bist
    
    ;Hier wird Z-Zeiger um 1 erhöht. Es wird hier auch verglichen,
    ;ob der letzte Ton erreicht, wenn ja, dann springt er zu "endeTon"
    tonPruefen:
    	lpm                  		;Daten von tonleiter1: holen 
       	adiw ZL,1            		;Z um 1 erhöhen, nächstes Byte 
       	ldi tmp, LOW  ((tonleiter1 * 2) + daten_laenge)   ;vergleiche LOW-Byte 
       	cp ZL, tmp 
    	ldi tmp, HIGH ((tonleiter1 * 2) + daten_laenge) ;vergleiche HIGH-Byte 
    	cpc ZH, tmp 
    	breq endeTon         		;springe zu "endeTon:", wenn letztes Byte ausgelesen 
    	ret							;zurück, wo du hergekommen bist
    
    ;Hier wird der Timer gestoppt, indem wir den Prescaler auf 0 setzen
    endeTon:
    	ldi tmp, (0<<CS02)         	;Timer stoppen 
       	out TCCR0, tmp
    	ret							;zurück wo du hergekommen bist
    
    ;Läuft Timer0 über, so wird B.2 umgeschaltet, sodass Ton
    ;aus dem Summer zu hören ist
    timerSummer: 
       push tmp               		;tmp sichern 
       in tmp, SREG 
       push tmp 					;SREG sichern
    	  sbis PINB, Summer         ;ist B.2 = 1?
          rjmp timerSummer1			;NEIN -> spring zu "timerSummer1:"
          cbi PORTB, Summer         ;JA -> setze B.2 auf 0 
    	  rjmp timerSummer2		;springe zu "timerSummer2:"
    
    timerSummer1:
    	sbi PORTB, Summer			;B.2 auf 1 setzen
    
    timerSummer2: 
       pop tmp                 		 ;SREG wiederholen 
       out SREG, tmp 
       pop tmp                 		 ;tmp wiederholen 
       reti
    
    ;Das sind die Werte, womit der Timer0 (Tonleiter-Timer) vorgeladen wird
    tonleiter1:
    	.db 256-55, 256-49, 256-44, 256-41			;Wert zum Vorladen für den Timer
    	.db 256-37, 256-33, 256-29, 256-27, 0		;für die Tonleiter
    Er spielt einfach nur den ersten Ton ab (Endlosschleife)

    @Michi: Genau so muss das aussehen! Richtig.

  4. #414
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    53
    Beiträge
    2.236
    ich kann aber nicht zuerst die 2 laden! <= stimmt so, oder?
    Genau, daß habe ich irgendwo oben schon geschrieben, stell Dir vor Du hast einen Gabelstapler, der nur eine Palette aufnehmen kann, du mußt also immer die oberste abnehmen, zwei auf einmal geht nicht, und dazwischen geht auch nicht, immer einen drauf oder einen runter.

  5. #415
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    53
    Beiträge
    2.236
    Wäre nett, wenn du da mal reinschauen könntest:
    Ich wollte vorhin schon was sagen, ich glaube Timer0 wird nicht mehr geladen, kann das?

  6. #416
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    29.07.2005
    Ort
    Berlin
    Alter
    40
    Beiträge
    289
    Ja, das war der Fehler, allerdings muss sich da noch irgendwo ein Fehler eingeschlichen haben, denn er spielt zwar jetzt nen anderen Ton, aber dann auch nur den. Und jede Sekunde kommt ein kurzer Stocker. Dann spielt er aber weiter den gleichen Ton, wieder für eine Sekunde.
    Code:
    ;Programm
    ;CDurTonleiter rauf spielen
    .include "m8def.inc"
    
    .def tmp = r16               	;Mein Universallregister
    .def tonwert = r17				;aktueller Wert für den Ton
    .def lpm_reg = r0				;Mein lpm-Register
    
    .equ Summer = PB2				;Summer an B.2
    .equ time0 = 256-255			;Timer0 für die Tonleiter
    .equ time1 = 65536-3600			;Damit wird der Timer1 vorgeladen, für die Sekunde
    .equ daten_laenge = 9			;Anzahl der Werte
    
    .org 0x000
       	rjmp reset					;Interruptvektor "reset:"
    
    .org OVF1addr
    	rjmp pruefSek				;Interruptvektor "pruefSek:"
    
    .org OVF0addr
    	rjmp timerSummer			;Interruptvektor "timerSummer:"
    
    reset:
       	;Stack einrichten
       	ldi tmp, HIGH(RAMEND)      	;HIGH-Byte der obersten RAM-Adresse
       	out SPH, tmp
       	ldi tmp, LOW(RAMEND)      	;Low-Byte der obersten RAM-Adresse
       	out SPL, tmp
    
    	;Timer Register für Ton werden belegt, hier Timer 0
    	ldi tmp, (1<<CS02)			;Prescaler ist 256
    	out TCCR0, tmp				;Register TCCR0 ist für den Prescaller zuständig
    	ldi tmp, time0				;Hier wird der Timer vorgeladen
    	out TCNT0, tmp
    
    	;Timer Register für Sekunde werden belegt, hier Timer 1
    	ldi tmp, (1<<CS12) | (1<<CS10)	;Prescaler ist 1024
    	out TCCR1B, tmp
    	ldi tmp, HIGH(time1)			;Für den Timer1 (16Bit) benötigen
    	out	TCNT1H, tmp					;wir 2 Register, in denen wir den Wert
    	ldi tmp, LOW(time1)				;für die 1 Sekunde (10000) speichern ->
    	out TCNT1L, tmp					;"TCNT1H" und TCNT2L"
    
    	ldi tmp, (1<<TOIE0) | (1<<TOIE1);Hier werden Interrupts nach Timer0 Überlauf eingeschaltet
    	out TIMSK, tmp				;Register TIMSK ist dafür zuständig
    
    	;Z-Register mit DB "tonleiter1" füllen
       	ldi ZH, HIGH(tonleiter1 * 2)
       	ldi ZL, LOW(tonleiter1 * 2)	
    	
    	sbi DDRB, Summer			;B.2 als Ausgang
    	sbi PORTB, Summer			;B.2 auf HIGH stellen	
    
       	sei                    		;Interrupts zulassen
    
    ;Die Hauptschleife, die sich immer wiederholt und den Tonwert neu einliest
    main:
    	lpm                  		;Daten von tonleiter1: holen 
       	mov tonwert, lpm_reg                ;Wrt von lpm_reg in tonwert speichern
    	rjmp main					;immer wieder zurück zu main springen
    
    ;Läuft Timer1 über, so wird erstmal geprüft, ob der letzte Ton
    ;erreicht ist und der Timer1 wird neu vorgeladen
    pruefSek:
    	push tmp					;tmp sichern
    	in tmp, SREG
    	push tmp					;SREG sichern
    		rjmp tonPruefen			;springe zu "tonPruefen"
    		ldi tmp, HIGH(time1)	;Für den Timer1 (16Bit) benötigen
    		out	TCNT1H, tmp			;wir 2 Register, in denen wir den Wert
    		ldi tmp, LOW(time1)		;für die 1 Sekunde (10000) speichern ->
    		out TCNT1L, tmp			;"TCNT1H" und TCNT2L"
    	pop tmp
    	out SREG, tmp				;SREG wiederholen
    	pop  tmp					;tmp wiederholen
    	reti						;Spring wieder dahin, wo du hergekommen bist
    
    ;Hier wird Z-Zeiger um 1 erhöht. Es wird hier auch verglichen,
    ;ob der letzte Ton erreicht, wenn ja, dann springt er zu "endeTon"
    tonPruefen:
    	lpm                  		;Daten von tonleiter1: holen 
       	adiw ZL,1            		;Z um 1 erhöhen, nächstes Byte 
       	ldi tmp, LOW  ((tonleiter1 * 2) + daten_laenge)   ;vergleiche LOW-Byte 
       	cp ZL, tmp 
    	ldi tmp, HIGH ((tonleiter1 * 2) + daten_laenge) ;vergleiche HIGH-Byte 
    	cpc ZH, tmp 
    	breq endeTon         		;springe zu "endeTon:", wenn letztes Byte ausgelesen 
    	ret							;zurück, wo du hergekommen bist
    
    ;Hier wird der Timer gestoppt, indem wir den Prescaler auf 0 setzen
    endeTon:
    	ldi tmp, (0<<CS02)         	;Timer stoppen 
       	out TCCR0, tmp
    	ret							;zurück wo du hergekommen bist
    
    ;Läuft Timer0 über, so wird B.2 umgeschaltet, sodass Ton
    ;aus dem Summer zu hören ist
    timerSummer: 
       push tmp               		;tmp sichern 
       in tmp, SREG 
       push tmp 					;SREG sichern
    	  sbis PINB, Summer         ;ist B.2 = 1?
          rjmp timerSummer1			;NEIN -> spring zu "timerSummer1:"
          cbi PORTB, Summer         ;JA -> setze B.2 auf 0 
    	  rjmp timerSummer2		;springe zu "timerSummer2:"
    
    timerSummer1:
    	sbi PORTB, Summer			;B.2 auf 1 setzen
    
    timerSummer2: 
       out TCNT0, tonwert                  ;Timer0 neu vorladen
       pop tmp                 		 ;SREG wiederholen 
       out SREG, tmp 
       pop tmp                 		 ;tmp wiederholen 
       reti
    
    ;Das sind die Werte, womit der Timer0 (Tonleiter-Timer) vorgeladen wird
    tonleiter1:
    	.db 256-55, 256-49, 256-44, 256-41			;Wert zum Vorladen für den Timer
    	.db 256-37, 256-33, 256-29, 256-27, 0		;für die Tonleiter
    Hab schon überprüft, also richtig hochzählen müsst er ja, also nach 1 Sekunde immer den nächsten Wert holen. Komisch...

    Ahh, es gibt Probleme mit dem Befehll "ret", irgendwann ruft er dann wieder "reset:" auf, hmm..mal schaun, wie ich das löse

  7. #417
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    53
    Beiträge
    2.236
    pruefSek:
    push tmp ;tmp sichern
    in tmp, SREG
    push tmp ;SREG sichern
    rjmp tonPruefen ;springe zu "tonPruefen"
    ldi tmp, HIGH(time1) ;Für den Timer1 (16Bit) benötigen
    out TCNT1H, tmp ;wir 2 Register, in denen wir den Wert
    ldi tmp, LOW(time1) ;für die 1 Sekunde (10000) speichern ->
    out TCNT1L, tmp ;"TCNT1H" und TCNT2L"
    pop tmp
    out SREG, tmp ;SREG wiederholen
    pop tmp ;tmp wiederholen
    reti ;Spring wieder dahin, wo du hergekommen bist

    ;Hier wird Z-Zeiger um 1 erhöht. Es wird hier auch verglichen,
    ;ob der letzte Ton erreicht, wenn ja, dann springt er zu "endeTon"
    tonPruefen:
    lpm ;Daten von tonleiter1: holen
    adiw ZL,1 ;Z um 1 erhöhen, nächstes Byte
    ldi tmp, LOW ((tonleiter1 * 2) + daten_laenge) ;vergleiche LOW-Byte
    cp ZL, tmp
    ldi tmp, HIGH ((tonleiter1 * 2) + daten_laenge) ;vergleiche HIGH-Byte
    cpc ZH, tmp
    breq endeTon ;springe zu "endeTon:", wenn letztes Byte ausgelesen
    ret ;zurück, wo du hergekommen bist

    ;Hier wird der Timer gestoppt, indem wir den Prescaler auf 0 setzen
    endeTon:
    ldi tmp, (0<<CS02) ;Timer stoppen
    out TCCR0, tmp
    ret ;zurück wo du hergekommen bist
    Das alles sieht echt nicht gut aus:

    1. Verlasse nie die Interruptroutine(außer mit reti), es sei denn es geht wirklich nicht anders!
    bezogen auf rjmp tonpruefen
    muß das sein? warum springst Du dahin? wäre es nicht einfacher das alles direkt
    drunter zu schreiben?
    2. Mal angenommen, es müßte wirklich so gelöst werden, was sollen die ret's darunter?
    bist Du Dir in klarem, wo er hinspringt, wenn da ein ret steht, und vorallem was danach passiert ?

    P.S. Jetzt nicht traurig werden, aber das ist Deine häufige Fehlerquelle !

  8. #418
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    29.07.2005
    Ort
    Berlin
    Alter
    40
    Beiträge
    289
    Mit dem ret wollte ich bezwecken, dass er wieder dahin springt, wo er hergekommen ist. Also in dem Falle hier:
    Code:
    pruefSek:
    	push tmp					;tmp sichern
    	in tmp, SREG
    	push tmp					;SREG sichern
    		rjmp tonPruefen			;springe zu "tonPruefen"
    		ldi tmp, HIGH(time1)	;Für den Timer1 (16Bit) benötigen
    		out	TCNT1H, tmp			;wir 2 Register, in denen wir den Wert
    		ldi tmp, LOW(time1)		;für die 1 Sekunde (10000) speichern ->
    		out TCNT1L, tmp			;"TCNT1H" und TCNT2L"
    	pop tmp
    	out SREG, tmp				;SREG wiederholen
    	pop  tmp					;tmp wiederholen
    	reti						;Spring wieder dahin, wo du hergekommen bist
    
    ;Hier wird Z-Zeiger um 1 erhöht. Es wird hier auch verglichen,
    ;ob der letzte Ton erreicht, wenn ja, dann springt er zu "endeTon"
    tonPruefen:
    	lpm                  		;Daten von tonleiter1: holen 
       	adiw ZL,1            		;Z um 1 erhöhen, nächstes Byte 
       	ldi tmp, LOW  ((tonleiter1 * 2) + daten_laenge)   ;vergleiche LOW-Byte 
       	cp ZL, tmp 
    	ldi tmp, HIGH ((tonleiter1 * 2) + daten_laenge) ;vergleiche HIGH-Byte 
    	cpc ZH, tmp 
    	breq endeTon         		;springe zu "endeTon:", wenn letztes Byte ausgelesen 
    	ret							;zurück, wo du hergekommen bist
    
    ;Hier wird der Timer gestoppt, indem wir den Prescaler auf 0 setzen
    endeTon:
    	ldi tmp, (0<<CS02)         	;Timer stoppen 
       	out TCCR0, tmp
    	ret							;zurück wo du hergekommen bist
    Springt er beim ersten ret wieder in die Zeile hier:
    ldi tmp, HIGH(time1) ;Für den Timer1 (16Bit) benötigen
    also 1 unter dem rjmp-Befehl, wo er ja vorher weggesprungen ist.

    PS: Traurig bin ich nicht, will nur nicht, dass du böse bist *g* Weiß ja nicht, wie du die Hände übern Kopf zusammenschlägst und dir denkst "Wie kann man nur so blöd sein"

  9. #419
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    53
    Beiträge
    2.236
    denkst "Wie kann man nur so blöd sein"
    Na ja jetzt übertreibst Du aber.
    aber mit ret hollt der sich zwei Bytes vom Stack und versucht zu dieser Adresse hinzuspringen....
    und was liegt ganz oben auf dem Stack?
    Abbild von SREG und darunter abbild von tmp
    Welche Rücksprungadresse errechnet er sich wohl daraus ?
    Lass das mit dem ret sein, versuche lieber tonPruefen: und ende_ton: in die Routine mit reinzunehmen (über reti) und springe da nicht so einfach hin, wozu (ich sehe du hast in C Programmiert bis jetzt hä?)

    Gruß Sebastian

  10. #420
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    29.07.2005
    Ort
    Berlin
    Alter
    40
    Beiträge
    289
    Ja, hab vorher in C, genauer gesagt in C++ programmiert.
    Also muss ich das dann so machen? Denn eine Sprungmarke brauch ich ja, damit ich den Timer dann abstelle, wenn er das Ende erreicht hat, oder?
    Code:
    pruefSek:
    	push tmp					;tmp sichern
    	in tmp, SREG
    	push tmp					;SREG sichern
    		ldi tmp, HIGH(time1)	;Für den Timer1 (16Bit) benötigen
    		out	TCNT1H, tmp			;wir 2 Register, in denen wir den Wert
    		ldi tmp, LOW(time1)		;für die 1 Sekunde speichern ->
    		out TCNT1L, tmp			;"TCNT1H" und TCNT2L"
    			lpm                  		;Daten von tonleiter1: holen 
    		   	adiw ZL,1            		;Z um 1 erhöhen, nächstes Byte 
    		   	ldi tmp, LOW  ((tonleiter1 * 2) + daten_laenge)	;vergleiche LOW-Byte 
    		   	cp ZL, tmp 
    			ldi tmp, HIGH ((tonleiter1 * 2) + daten_laenge)	;vergleiche HIGH-Byte 
    			cpc ZH, tmp 
    			breq endeTon         		;springe zu "endeTon:", wenn letztes Byte ausgelesen
    	pop tmp
    	out SREG, tmp				;SREG wiederholen
    	pop  tmp					;tmp wiederholen
    	reti						;Spring wieder dahin, wo du hergekommen bist
    
    endeTon:
    		ldi tmp, (0<<CS02)         	;Timer stoppen 
    	   	out TCCR0, tmp
    	pop tmp
    	out SREG, tmp				;SREG wiederholen
    	pop  tmp					;tmp wiederholen
    	reti
    Doch dann hab ich ja 3 Zeilen doppelt. Die 3 Zeilen zum Wiederholen der Register vom Stack. Ist also auch nicht die beste Möglichkeit.

Seite 42 von 53 ErsteErste ... 32404142434452 ... LetzteLetzte

Berechtigungen

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

LiFePO4 Speicher Test