- 12V Akku mit 280 Ah bauen         
Seite 40 von 53 ErsteErste ... 30383940414250 ... LetzteLetzte
Ergebnis 391 bis 400 von 524

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

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

    Powerstation Test
    Hi,
    ich hab's jetzt kapiert! Der Timer wird mit 1 vorgeladen damit er schon nach 254 Timerschritten nen Interrupt auslöst! <= ist das so oder? Sonst löst er doch nach 255 einen aus, oder?
    Gruß Michi

  2. #392
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    29.07.2005
    Ort
    Berlin
    Alter
    40
    Beiträge
    289
    Er löst nach 256 den Interrupt erst aus, da er bei 255 noch nicht überläuft, deswegen ja auch die 256 (so, nun hast die Erklärung )
    Und wenn du schreibst: 256-255, dann lädst du den Timer also mit 1 vor. Also läuft er nach 255 Schritten über und löst den Interrupt aus.

    @Sebastian:
    .equ time 65536-3600
    Denn
    1/3,6864 MHz = 271ns

    271ns * 1024 = 278µs

    278µs * 3600 = 1000,8 ms

    Wunderbar

  3. #393
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    53
    Beiträge
    2.236
    @Thomas, klappt es jetzt mit dem Timer1 ?
    Ich meine Dein Musikprogramm?
    @Tekeli,
    Danke für den Tip mit VMware, aber ich glaube daß Programm unterliegt nicht der GPL
    und Du kannst mich für bekloppt erklären, bei mit kommt nur opensource drauf

    Gruß Sebastian

  4. #394
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    29.07.2005
    Ort
    Berlin
    Alter
    40
    Beiträge
    289
    @Sebastian:
    Jo, klappt nun mit dem Timer1. Allerdings brauche ich immer noch eine Hilfsvariable, die ich beim Überlauf von Timer1 auf 255 setze und dann in der main prüfe und dementsprechend dann den nächsten Ton lade. Hier nochmal der Code:
    Code:
    ;Programm
    ;CDurTonleiter rauf und runter spielen
    .include "m8def.inc"
    
    .def tmp = r16               	;Mein Universallregister
    .def helpSek = r17
    .def tonwert = r19				;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
    
    ;Hier wird der nächste Ton geladen und in "tonwert" gespeichert
    ;Z-Zeiger wird um 1 erhöht, damit er beim nächsten mal den nächsten
    ;Ton lädt. Es wird hier auch verglichen,, ob der letzte Ton erreicht,
    ;wenn ja, dann springt er zu "endeTon"
    tonLaden:
    	clr helpSek					;helpSek auf 0 setzen
    	lpm                  		;Daten von tonleiter1: holen 
       	mov tonwert, lpm_reg   		;erstes Byte in tmp verschieben 
       	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 
    	rjmp main					;sonst springe zu "main:"
    
    ;Hier wird der Timer gestoppt, indem wir den Prescaler auf 0 setzen
    endeTon:
    	ldi tmp, (0<<CS02)         	;Timer stoppen 
       	out TCCR0, tmp
    
    ;Die Hauptschleife, die sich immer wiederholt
    main:
    	cpi helpSek, 0b11111111		;Ist helpSek auf 255? (also 1 Sekunde um?)
    	breq tonLaden				;dann lade den nächsten Ton
    	rjmp main					;immer wieder zurück zu main springen
    
    ;Läuft Timer2 über, so wieder zaehlerSek um 1 erhöht und
    ;Timer2 neu vorgeladen
    pruefSek:
    	push tmp					;tmp sichern
    	in tmp, SREG
    	push tmp					;SREG sichern
          	ldi helpSek, 0b11111111	;Hilfsvariable mit 255 belegen
    		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"
    	pop tmp
    	out SREG, tmp				;SREG wiederholen
    	pop  tmp					;tmp wiederholen
    	reti						;Spring wieder dahin, 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         ;zu "timerSummer2:" springen 
    
    timerSummer1: 
       sbi PORTB, Summer         	;wenn B.2 = 0 ist, dann auf 1 setzen 
    
    ;Hier wird Timer0 mit dem aktuellen Tonwert vorgeladen 
    timerSummer2: 
       out TCNT0, tonwert         	;Timer dementsprechen vorladen 
    
    timerSummer3: 
       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
    Weiß nicht, wie ich das sonst anders lösen sollte, also ohne Hilfsvariable.

  5. #395
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    53
    Beiträge
    2.236
    Hallo Thomas,
    Daß Dein Programm noch nicht ganz Perfekt ist, ist auch kein Wunder,
    überleg mal seit wann Du im Assembler programmierst?

    Jetzt nicht traurig sein, es war nicht böse gemeint!

    Hauptsache ist, daß es funktioniert, und verbessern kann man es immer noch.

    Ich persönlich hätte es fast nur in den Interrupt Routinen gelöst.
    Ob es besser oder schlechter als Deine Lösung ist, möchte ich hier nicht urteilen,
    ich bin selber kein Profi, sondern genauso wie Du und die meisten hier ein Freak,
    der von der Technik fasziniert ist.

    Ich schreibe Dir meinen Ansatz, wie ich mir daß vorstelle, ok ?
    Du kannst versuchen, das in einem Programm umzusetzen,
    abe tue mir ein Gefallen, schreib bitte ein neues Programm, sonst kommt
    wieder ein durcheinander dabei raus

    Also:
    ein Register, wo dein Tonwert gespeichert wird.
    wie gehabt ein universallregister.

    in loop zuerst mit lpm den ersten Ton in Tonwert einlesen, und den Timer0 damit laden.
    als nächstes den Timer1 laden, (könnte auch in reset stehen denke mir)
    und zum Schluß eine Endlosschleife.

    die Timer0 Interruptroutine, ist sehr einfach, nur mit Tonwert neu laden und raus.
    Timer1 Interruptroutine muß natürlich jetzt alles enthalten, was bis jetzt in Deinem Main:
    gestanden hat, also
    1. mit adiw den Z zeiger um eins erhöhen,
    2. Schauen ob Du schon den letzten Ton hattest, wenn ja noch in der routine Timer stopen
    und raus, sonst mit lpm Wert in den Register Tonwert schieben, Timer0 neu laden, und auch Interrupt verlassen.

    Nach Tekeli Version kommt unter 2 dann halt Wert einlesen, nach 0 prüfen und dann entsprechend verzweigen.

    Ob es schöner ist weiß ich nicht, aber es müßte auch so klappen (habe es nicht ausprobiert) , zum üben natürlich sehr gut geeignet.

    Wenn Du,Ihr Lust habt dann könnt Ihr es versuchen.

    Ich hoffe, daß ich es gut beschrieben habe, und vor allem, daß es so funktioniert

    Gruß Sebastian

  6. #396
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    53
    Beiträge
    2.236
    Ihr habt beide andere Wege genommen um die Aufgabe zu lösen.
    Beide haben vor und Nachteile.
    Es wäre wohl nicht schwer zu sagen welche vor und nachteile es sind...
    Habt Ihr das übersehen, oder war das zu einfach?

  7. #397
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    29.07.2005
    Ort
    Berlin
    Alter
    40
    Beiträge
    289
    Zu schwer würd ich sagen, wüsste nicht, welche Vorteile meine Version gegenüber Tekelis hätte.

    So, hier der Code ohne Hilfsvariable - geht ja doch ohne
    Code:
    ;Programm
    ;CDurTonleiter rauf und runter 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
    main:
    	lpm                  		;Daten von tonleiter1: holen 
       	mov tonwert, lpm_reg   		;erstes Byte in tmp verschieben - ersten Tonwert speichern
    	rjmp main					;immer wieder zurück zu main springen
    
    ;Läuft Timer2 über, so wieder zaehlerSek um 1 erhöht und
    ;Timer2 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
    Man muss sich erstmal den Ablauf vor Augen halten, darin liegt denk ich noch mein größtes Problem. Aber das bekomm ich schon hin mit der Zeit.

    Gruß
    Thomas

  8. #398
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    53
    Beiträge
    2.236
    Thomas,
    aber Du hast Das Programm doch nicht neu geschrieben, oder?

    z.B
    .org OVF1addr
    rjmp pruefSek ;Interruptvektor "pruefSek:"

    mithin gehe ich davon aus daß pruefSek der Interrupthandler von Timer1 ist....

    und schau was über pruefSek drüber steht

    Hmmmm

  9. #399
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    30.09.2004
    Ort
    In der Nähe von Esslingen am Neckar
    Beiträge
    706
    Hallo,
    ich hab me Frage zu diesem hier:
    Code:
    push tmp               ;Rette Universallregister 
    in tmp, SREG            ;Rette Statusregister 
    push tmp
    beim ersten wird doch was in den Stack geschrieben und was ich nicht versteh beim zweiten wird das doch überschrieben! Wie kann man dann beides nacheinander wieder aus dem Stack holen mit diesem hier?:
    Code:
    pop tmp                  ;stelle SREG wieder her 
    out SREG, tmp 
    pop tmp                  ;stelle Universalregister wieder her
    Gruß Michi

  10. #400
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    01.11.2003
    Ort
    Freiburg im Breisgau
    Alter
    36
    Beiträge
    2.624
    Lieber Michael! ;o)
    Du hast wohl noch immer nicht die xx Seiten durchgelesen, oder? *lol*
    Die Adressen werden ans Ende des SRAMs gesetzt und wie ein Bücherstapel behandelt!
    Du legst ein Buch drauf und nimmst eins runter, danach noch eins oder Du packst 3 drauf und nimmst 20 runter! *lol*
    BücherSTAPEL!

Seite 40 von 53 ErsteErste ... 30383940414250 ... LetzteLetzte

Berechtigungen

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

Solar Speicher und Akkus Tests