- Labornetzteil AliExpress         
Seite 9 von 53 ErsteErste ... 789101119 ... LetzteLetzte
Ergebnis 81 bis 90 von 524

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

  1. #81
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    29.07.2005
    Ort
    Berlin
    Alter
    40
    Beiträge
    289
    Anzeige

    Praxistest und DIY Projekte
    Ich bin mir nicht ganz sicher, dass ich 4Mhz hab. Aufm Board find ich auch nirgends ne Angabe dazu. Wie sieht son Quarz eigentlich aus? *schäm* Hab das Board hier: http://www.myavr.de/shop/artikel.php?artID=4

    Hier der Code, den ich nun geändert hab, geht aber immer noch net, oder lad ich den Timer falsch neu?
    Code:
    pruefZaehler: 
       inc zaehler               ;Zählregister um 1 erhöhen 
       cpi zaehler, 0b01000001      ;Wenn Zählregister = 65 ist 
       breq zeitum               ;spring zu "zeitum:" wenn zaehler = 65 
       ldi tmp, time
       out TCNT0, tmp
       reti
    [edit] In der Beschreibung vom Board steht:
    Standardquarz: 3,686411-HC49U-S

  2. #82
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    53
    Beiträge
    2.236
    Passauf,

    4MHz / 1024 / 254 = 65 Hz = ca. 15,4ms
    Da liegt der Hund begraben.....

    Ich weiß zwar nicht wie Du darauf kommst, aber es soll heißen

    4MHz / 1024 / 254 =15,4 Hz = 65 ms

    Mithin muß zeahler 15 mal durchlaufen, um etwa eine sekunde zu bekommen.

    Ich habe so gerechnet:

    1/4000000 = 250 ns -> dauer eines Taktes
    bei 1024 Prescaler 250 nS * 1024 = 256 µs

    also ein Timerschritt dauert 256 µS

    Jetzt heißt es Anzahl der Schritte zu finden, damit man einen schönen Teiler der Sekunde hat.
    Ich habe 98 genommen 256µ * 98 = 25,088 ms

    Wenn Du das jetzt mit 40 malnimmst bist Du auch bei einer Sekunde.
    Also Doch Timing Problem entweder änderst Du in dem jetzigem Code Deine 65 ? in 15 um, oder lädst den Timer mit 98 und zaehler mit 40.
    Wie Du siehst gibt es mehrere Wege eine Sekund zu erzeugen....

    Ich hoffe, daß es jetzt bei Dir klappt.

    P.S. Quarz auf diesem Board ist das kleine Dingen aus Metall unter dem Mega,
    auf dem Bild Rechts davon.

    Gruß Sebastian

  3. #83
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    53
    Beiträge
    2.236
    Ja den Timer hast Du richtig geladen, aber bedenke Du hast (noch) 2 retis in Deinem Code drin!!!

  4. #84
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    29.07.2005
    Ort
    Berlin
    Alter
    40
    Beiträge
    289
    Ok, auf dem Quarz steht auch die 3,6864, also 4 Mhz dann. Hab die 65 nun in 15 umgewandelt. Muss mich nur nochmal damit auseinandersetzen, wann ich mit 1000 multipliziere und wann ich durch 1000 teile und so.
    Aber genau 1 Sekunde blinkt er nicht, ist ein wenig länger, glaube aber nicht, dass es an den 3ms liegt, denn bei 25,088 * 40 kommt ja 1003,52 raus.

    Und wieso muss ich vor dem "reti" den Timer neu laden, er springt doch eh zurück zum reset nach dem reti, oder?

    Gruß
    Thomas

    [edit]
    Ja, aber das zweite reti bei "zeitum2" brauch ich ja eigentlich auch

  5. #85
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    53
    Beiträge
    2.236
    Ok, auf dem Quarz steht auch die 3,6864 , also 4 Mhz dann
    das ist nicht ganz richtig, es sind 313600 Takte weniger, dazu kommen ja noch die anderen
    Ungenauigkeiten usw.

    Und wieso muss ich vor dem "reti" den Timer neu laden, er springt doch eh zurück zum reset nach dem reti, oder?
    Falsch, warum soll er nach reset zurück?
    dann würde das Programm immerwieder neu Anfangen, oder?

    Die Sache mit dem reti ist die, wenn ein Interrupt ausgelöst wird,
    merkt sich der µC SOFORT wo er sich gerade im Hauptprogramm (hier loop)
    befindet, also in welcher Zeile er gerade arbeitet(wie er sich das merkt, kann ich Dir mal später irgendwann sagen, im moment reicht es wenn Du das nur weißt), die Zeile macht er noch zu ende,
    und geht in die Interruptroutine rein.
    In diesem Moment werden auch Interrupts allgemein abgeschaltet, damit nichts zwischenfunken kann(das macht der µC aber von alleine, haben wir nichts mit am Hut)
    So wo sind wir jetzt, achso in der Interruptroutine, naja das weißt ja schon,
    er geht Zeile für Zeile runter BIS er reti findet.
    reti kann man ganz einfach so beschreiben: -> Hey µC du hast Dir mal gemerkt wo ich(Interrupt) Dich unterbrochen habe (irgendwo im Hauptprogramm),
    so ich bin jetzt fertig(Interrupt) dann GEHE sofort an die Stelle zurück, wo ich(Interrupt)
    Dich (µC) unterbrochen habe, mach dort (also nicht genau dort sondern eine Zeile tiefer)
    weiter UND schalte die Interrupts wieder ein!

    Ich hoffe, daß man mich hier nicht auslacht, für Diese schreibweise, aber ich muß beruflich auch die heutige Jugend ausbilden, und so kappieren sie das am schnellsten!

    Gruß Sebastian

  6. #86
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    29.07.2005
    Ort
    Berlin
    Alter
    40
    Beiträge
    289
    Hehe, jo, klingt einleuchtend
    also springt er genau da hin (eine Zeile tiefer (logisch, denn er soll ja den nächsten Befehl ausführen)), wo er vor dem Auslösen des Interrupts herkam? Wunderbar

    Nun noch das Problem, warum zwei retis unsauber sind? Ich überleg schon die ganze Zeit, ob ich das reti bei zeitum2 wegnehmen kann, aber ich glaub nicht, denn er soll ja wieder zurückspringen und das geht ja nur mit reti...

    Gruß
    Thomas

  7. #87
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    53
    Beiträge
    2.236
    und so kappieren sie das am schnellsten!
    was habi ich gesagt?
    Vollkommen richtig, was Du da sagst.
    also muß er einfach nur in rjmp loop reinspringen, weil wir garkein Hauptprogramm haben,
    nur die eine Zeile

    Jetzt zu den zwei retis.
    Du hast Dein Blinkprogramm auf der Grundlage von meinem Taster/Entprellprogramm aufgebaut, ist auch nicht schlimm, nur auf einmal mußtest Du doch was abändern, und dadurch wurde es unsauber.
    Das Programm von mir enthält noch Sachen, die Du noch nicht verstehst, und ich habe keine Lust jetzt Dich durcheinanderzubringen, wo Du langsam anfängst kein Beginner mehr zu sein !!!

    Ich entferne mal sachen aus der Interruptroutine, die JETZT keinen Sinn ergeben,
    und dann kannst Du mal schauen, wie Du mit nur einem reti auskommen kannst.

    Code:
    pruefZaehler:
       inc zaehler               ;Zählregister um 1 erhöhen
       cpi zaehler, 0x28     ;Wenn Zählregister = 65 ist
       breq zeitum               ;spring zu "zeitum:" wenn zaehler = 65
    	ldi tmp, time               ;Hier wird der Timmer vorgelaen und zwar mit 255-254
    	out TCNT0, tmp 
    	reti
    
    zeitum:
       clr zaehler               ;Zählregister auf 0 setzen
       sbrs status, sperre         ;überspringe, wenn r17.7 = 1 ist (LED an?)
       rjmp zeitum0            ;zu "zeitum0:" springen
       sbrc status, sperre         ;überspringe, wenn r17.7 = 0 ist (LED aus?)
       rjmp zeitum1            ;zu "zeitum1:" springen
    
    zeitum0:
       sbr status, (1<<sperre)      ;r17.7 = 1 setzen (LED an)
       sbi PORTD, LED            ;B.2 = 1 setzen -> LED an
       rjmp zeitum2
    
    zeitum1:
       cbr status, (1<<sperre)      ;r17.7 = 0 setzen (LED aus)
       cbi PORTD, LED            ;B.2 auf 0 setzen -> LED aus
       rjmp zeitum2
    
    zeitum2:
         reti                  ;die Interrupt-Routine wird verlassen
    So, frag aber bitte noch nicht, warum ich dort etwas weggemacht habe,
    dabei kommen wir noch aus, irgendwann ......
    Schaue Dir diese Code an überlege, lass Dir Zeit, und schicke Das Programm zurück,
    wo nur ein reti ganz unten im code steht, vor dem Du dann den zaehler neu lädst.

    Müßte jetzt gaaaaanz einfach sein, was kannst Du sonst noch schreiben an der stelle, wo das erste reti steht.......


    Gruß Sebastian

  8. #88
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    29.07.2005
    Ort
    Berlin
    Alter
    40
    Beiträge
    289
    Code:
    pruefZaehler:
       inc zaehler               ;Zählregister um 1 erhöhen
       cpi zaehler, 0x28     ;Wenn Zählregister = 65 ist
       breq zeitum               ;spring zu "zeitum:" wenn zaehler = 65
       rjmp zeitum2
    
    zeitum:
       clr zaehler               ;Zählregister auf 0 setzen
       sbrs status, sperre         ;überspringe, wenn r17.7 = 1 ist (LED an?)
       rjmp zeitum0            ;zu "zeitum0:" springen
       sbrc status, sperre         ;überspringe, wenn r17.7 = 0 ist (LED aus?)
       rjmp zeitum1            ;zu "zeitum1:" springen
    
    zeitum0:
       sbr status, (1<<sperre)      ;r17.7 = 1 setzen (LED an)
       sbi PORTD, LED            ;B.2 = 1 setzen -> LED an
       rjmp zeitum2
    
    zeitum1:
       cbr status, (1<<sperre)      ;r17.7 = 0 setzen (LED aus)
       cbi PORTD, LED            ;B.2 auf 0 setzen -> LED aus
       rjmp zeitum2
    
    zeitum2:
         ldi tmp, time
         out TCNT0, tmp
         reti                  ;die Interrupt-Routine wird verlassen
    Funzt

    [edit]
    Kann mir schon vorstellen, warum du das Interruptzeug da rausgenommen hast. Denn mit dem ganzen Zeug, also das Sichern der Register blinkt die LED nimmer so wie sie soll. Logisch, denn tmp hat am Ende den falschen Wert. Aber darauf wollten wir ja später kommen

  9. #89
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    08.05.2005
    Ort
    Issum
    Alter
    53
    Beiträge
    2.236
    Ich bin begeistert, das ist echt eine sehr schöne Interrupt Routine, und Du sagtest, es geht nicht mit einem reti

    Denn mit dem ganzen Zeug, also das Sichern der Register blinkt die LED nimmer so wie sie soll. Logisch, denn tmp hat am Ende den falschen Wert. Aber darauf wollten wir ja später kommen
    Ich sehe, daß Du wirklich alles auf einmal wissen willst, aber wie gesagt, das Thema machen wir irgendwann, jetzt nicht, ich sag nur dazu, das es nicht stimmt, was Du da sagst.

    Aber wenn Du denkst, daß wir Dein Code jetzt wirklich 100% haben, dann irst Du gewaltig,
    es klappt zwar, man könnte aber noch sehr viel verbessern \/

    Also die nächste Aufgabe (Ich hoffe Du hast Lust Dazu)
    Du benutzt den status Register mit der sperre, um Dir zu merken ob die LED an oder aus ist.
    Damit hast Du uns schön gezeigt, wie man Register als Variablen nutzen kann,
    Man braucht keine variablen an Funktionen zu übergeben, oder irgendeinen Wert zurückzuerwarten wie bei C, sondern hat sie alle sozusagen Global zu verfügung, sie sind überall gültig in Hauptprogramm und in den Interruptroutinen.

    So, aber......
    Wir wollen Sparen!
    Stell Dir vor, Du hast wirklich keinen Register mehr frei, Sram ist voll, und mußt das Programm so umschreiben, daß Du ohne sperre auskommst !

    Warum schreib ich das jetzt?
    Weil Du Dir die Befehlsliste nicht genau angeschaut hast [-X

    Und alle Register auch noch nicht kennst.

    es gibt da Register, die PIN heißen, für jeden Port einen also bei Mega8 PINB PINC PIND
    Da Du Deine LED an PORTB dranhast, ist Der Register PINB schon Deine Variable, wo der Zustand der LED gespeichert ist

    Wenn Du jetzt den Befehl in tmp,PINB schreibst wird der Zustand deines Portes B in tmp geschrieben, aber noch nichmals das brauchst Du,
    es gibt Befehle wie sbic PINB,LED und sbis PINB,LED ,
    und was meinst Du was die machen ?

    Versuch das Programm jetzt so abzuändern, daß Du mit hilfe einer der Befehle sbic und sbis auskommst.

    Dürfte nicht so schwer sein, denke ich, aber dadurch wird Dein Programm noch schmaler, und eleganter!

    Gruß Sebastian

  10. #90
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    29.07.2005
    Ort
    Berlin
    Alter
    40
    Beiträge
    289
    YEAH, ich habs gewusst. Hab schon zu meiner Freundin gesagt, dass ich noch was unnötiges drinne habe, aber so hab ich eben gelernt mit Registern umzugehen
    Also ist nicht schwer die Aufgabe, hier der Code:
    Code:
    .include "m8def.inc"
    
    .equ time = 255 -254		;Damit wird der Timer vorgeladen
    .equ LED = PB2				;LED an B.2
    .def tmp = r16				;Mein Universallregister
    .def zaehler = r18			;Mein Zählregister
    
    .org 0x000
    	rjmp reset				;Interruptvektor "reset:"
    
    .org OVF0addr
    	rjmp pruefZaehler		;Interruptvektor für Timer0 Überlauf, hier springt
    							;das Programm hin, wenn der Timer überläuft
    
    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
    
    	sbi DDRB, LED				;B.2 als Ausgang
    	cbi PORTB, LED				;B.2 auf LOW stellen -> LED aus am Anfang
    
    	;Timer Register werden belegt, hier Timer 0
    	ldi tmp, (1<<CS02) | (1<<CS00)	;prescaler ist 1024
    	out TCCR0, tmp					;Register TCCR0 ist für den Prescaller zuständig
    	ldi tmp, (1<<TOIE0)				;Hier werden Interrupts nach Timer0 Überlauf eingeschaltet
    	out TIMSK, tmp					;Register TIMSK ist dafür zuständig
    	ldi tmp, time					;Hier wird der Timmer vorgelaen und zwar mit 255-254
    	out TCNT0, tmp					;Er läuft 254 mal durch, bevor ein Interrupt auftritt
    	sei								;Interrupts zulassen
    
    loop:
    	rjmp loop					;Immer wieder selbst aufrufen -> Endlosschleife
    
    pruefZaehler:
    	inc zaehler					;Zählregister um 1 erhöhen
    	cpi zaehler, 0b00001111		;Wenn Zählregister = 65 ist
    	breq zeitum					;spring zu "zeitum:" wenn zaehler = 65
    
    	rjmp zeitum2				;zu "zeitum2:" springen
    
    zeitum:
    	clr zaehler					;Zählregister auf 0 setzen
    	sbis PINB, LED              ;überspringe, wenn B.2 = 1 ist (LED an?)
    	rjmp zeitum0				;zu "zeitum0:" springen
    	rjmp zeitum1				;zu "zeitum1:" springen
    
    zeitum0:
    	sbi PORTB, LED				;B.2 = 1 setzen -> LED an
    	rjmp zeitum2
    
    zeitum1:
    	cbi PORTB, LED				;B.2 auf 0 setzen -> LED aus
    	rjmp zeitum2
    
    zeitum2:
    	ldi tmp, time				;Hier wird der Timer vorgelaen und zwar mit 255-254
    	out TCNT0, tmp				;Er läuft 254 mal durch, bevor ein Interrupt auftritt
    	reti						;die Interrupt-Routine wird verlassen
    								;und es wird weiter im Hauptprogramm gearbeitet
    Ich finds echt nett von dir, dass du dir so viel Mühe mit mir gibst. Darf ich mal so nebenbei fragen, was du beruflich machst? Ich tipp mal auf Lehrer?

    Gruß
    Thomas

    PS: Ich glaub, Assembler wird noch richtig lustig
    Mir wird nur schlecht, wenn ich seh wie man Timer in C oder Basic programmiert, wie wenig Zeilen das da sind *g*

    [edit]
    Hab noch ein Befehl rausgenommen Wieder eine Zeile weniger.

Seite 9 von 53 ErsteErste ... 789101119 ... LetzteLetzte

Berechtigungen

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

Solar Speicher und Akkus Tests