Na dann mal von mir Glückwunsch :)
Druckbare Version
Na dann mal von mir Glückwunsch :)
Herzlichen Glückwunsch ihr beiden!
Ihr seit nun nicht mehr nur Anfänger, sondern schon fortgeschrittene Anfänger! *lol*
Nein, ihr könnt euch jetzt glaube ich mit ein bischen mehr Routine und Übung schon fast Fortgeschrittene schimpfen! ;o)
Macht weiter so!Sagen wir doch schon lange, aber irgendwie denken viele, dass nur "Hochsprachen" Spass machen können! ;o)Zitat:
Es macht echt Spaß mit dem Assembler zu programmieren!
Das kannst Du laut sagen, ich habe vor kurzem einen Timer für meine Frau gebaut,Zitat:
Irgendwie nerven die Töne meine Freundin
naja Du weißt schon, für Kuchen zu Backen z.B 0-90 Minuten, man könnte natürlich
bei Real irgendwas Fertiges kaufen für 4,99 , aber nein, ich muß basteln.
Da habe ich auch so ein Piezo verwendet, wenn die Zeit um war und habe Ihn auf
etwa 4kHz eingestellt.
O weh ich durfte mir war anhören, muße auch tiefer gehen, so bei 800 Hz war sie zufrieden.
Ich glaube Frauen können solche Töne nicht vertragen, so wie Katzen, naja manchmal benehmen sie sich auch so
:lol:
Ich freue mich ein lächeln auf Deinem Gesicht zu sehen!
Und warum vergleichen wir gerade im Interrupt vom summer?
Ganz einfach, hier wird der Timer neugeladen, also hier bestimmst Du welche Frequenz Du hast, und wenn Du sie verändern willst, mußt Du auch genau dort eingreifen!
Wie ich sehe haben wir noch einen Glücklichen hier (o man warum muß ich immer so langsam Tippen)
@Tekeli,
ging das nicht gegen VCC ? hmmm, na egal, aber die LED kannst Du trotzdem benutzen, oder?
Der Piezo müßte ziemlich hochohmig sein, so daß er da nicht stört (Theorie)
Mach mal ein Foto und sende das den Asuro Freunden auf "Roboter Bausätze" vielleicht finden sie das auch interessant...
@Sebastian: Mein Freundin meint, dass Männer die Frequenz nicht stört, weil sie schlecht hören, so wie die meisten Fliegen, manchmal sind sie auch ebenso lästig ;)
Ich glaub, die will Krieg *Totenlied auffer Gitarre spiel :-({|= *gg*
So, hier nun der fertige Quellcode ohne LED, so wies "verlangt" war ;)
GrußCode:.include "m8def.inc"
.equ time0_1 = 256-20 ;Damit wird der Timer0 vorgeladen
.equ time0_2 = 256-30
.equ time2 = 256-90 ;Damit wird der Timer2 vorgeladen
.equ Summer = PB2 ;Summer an B.2
.def tmp = r16 ;Mein Universallregister
.def statusreg = r17 ;Mein Statusregister
.def zaehlerSek = r18
.def statusSummer = r19 ;Mein Status-Summer-Register
.org 0x000
rjmp reset ;Interruptvektor "reset:"
.org OVF2addr
rjmp timerSek
.org OVF0addr
rjmp timerSummer ;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, Summer ;B.2 als Ausgang
sbi PORTB, Summer ;B.2 auf HIGH stellen
ldi statusSummer, 0b00000000 ;statusSummer auf 0 setzen
ldi zaehlerSek, 0b00000000 ;Zähler auf 0 setzen
;Timer Register werden belegt, hier Timer 0
ldi tmp, (1<<CS02) ;Prescaler ist 512
out TCCR0, tmp ;Register TCCR0 ist für den Prescaller zuständig
ldi tmp, time0_1 ;Hier wird der Timer vorgeladen
out TCNT0, tmp
;Timer Register werden belegt, hier Timer 2
ldi tmp, (1<<CS22) | (1<<CS21) | (1<<CS20) ;Prescaler ist 1024
out TCCR2, tmp ;Register TCRR2 ist für den Prescaller zuständig
ldi tmp, time2 ;Hier wird der Timer vorgeladen
out TCNT2, tmp
ldi tmp, (1<<TOIE0) | (1<<TOIE2);Hier werden Interrupts nach Timer0 Überlauf eingeschaltet
out TIMSK, tmp ;Register TIMSK ist dafür zuständig
sei ;Interrupts zulassen
loop:
cpi zaehlerSek, 0b00010100 ;Wenn Zählerregister != 40 ist
breq pruefSek ;dann zu "pruefSek:" springen
rjmp loop ;immer wieder zu "loop:" springen
pruefSek:
clr zaehlerSek ;Zählerregister auf 0 setzen
sbrs statusSummer, 0 ;überspringe, wenn PIN 0 = 1 ist
rjmp umschalten ;wenn PIN 0 = 0 ist, dann springe zu "umschalten:"
ldi statusSummer, 0b00000000;wenn PIN 0 = 1 ist, dann PIN 0 auf 0 setzen
rjmp loop ;wieder zurück zu loop
umschalten:
ldi statusSummer, 0b00000001;wenn PIN 0 = 0 ist, dann auf 1 setzen
rjmp loop ;wieder zurück zu "loop:"
timerSummer:
in statusreg, SREG ;SREG sichern
sbis PINB, Summer ;überspringe, wenn B.2 = 1 ist
rjmp timerSummer1 ;wenn B.2 = 0 ist, dann spring zu "umschalten1:"
cbi PORTB, Summer ;wenn B.2 = 1 ist, dann B.2 auf 0 setzen
rjmp timerSummer2 ;zu "umschalten2:" springen
timerSummer1:
sbi PORTB, Summer ;wenn B.2 = 0 ist, dann auf 1 setzen
timerSummer2:
sbrs statusSummer, 0 ;überspringe, wenn PIN 0 = 1 ist
rjmp timerSummer3 ;wenn PIN 0 = 0 ist, dann springe zu "timerSummer3:"
ldi tmp, time0_1 ;wenn B.5 = 1 ist, dann 1 KHz-Timer laden
out TCNT0, tmp
rjmp timerSummer4 ;zu "timerSummer4:" springen
timerSummer3:
ldi tmp, time0_2 ;wenn B.5 = 0 ist, dann 4KHz-Timer laden
out TCNT0, tmp
timerSummer4:
out SREG, statusreg ;SREG wiederholen
reti ;wieder zurück, wo du hergekommen bist
timerSek:
in statusreg, SREG ;SREG sichern
inc zaehlerSek ;Zählerregister um 1 erhöhen
ldi tmp, time2 ;Hier wird der Timer2 vorgeladen
out TCNT2, tmp
out SREG, statusreg ;SREG wiederholen
reti
The Happy Thomas :-b
Ne,ne ich führe keinen Krieg gegen Frauen !!!!
Sie benutzen manchmal Waffen, wo wir arme schlucker nicht gegen ankommen !
Also schön den Ball flachhalten.
Das ohne LED hast Du auch gut gelöst, die Version mit war ja nur ein Übergang...
@Tekeli,
Du bist aber kein blutiger Anfänger ?
Hab mir Dein Code angeschaut, bin echt begeistert !
Ich find das gut daß Ihr zu zweit seid, Ihr könnt Euch gegenseitig helfen,
wenn was unklar ist.
Thomas, ich hoffe, Du hast Dir die Version von Tekli runtergeladen,
dort kannst Du sehen, daß es wie immer mehrere Wege gibt ein Problem zu lösen,
nur bedenke, der Asuro hat 8 Mhz, also hat er die Zeiten etwas anders.
Wenn Ihr Lust habt, haben wir beide mit Florian eine sehr schöne Aufgabe vorbereitet.
Ich war begeistert, was sich der Florian alles so einfallenlassen hat.
Nur um das anzupacken, müßten wir noch mehrere Sachen ansprechen, die erste wäre
was macht man, wenn man eine Zahl darstellen will, die größer 255 ist z.B 1000 ?
Irgendwelche Ideen ?
Kleine Nachricht, bevor ich in's Bettchen gehe und Bubu mache:
Wir sind jetzt in der Top-Ten-Statistik auf Platz 8! *angeb* ;o)
Und zur Ernüchterung, damit alle schlafen können:
Ihr solltet mal unbedingt an eurem Codedesign arbeiten!
Hier, lest das mal!
Sonst funktioniert der Code zwar, aber zwei Tage später wisst ihr nicht mehr was ihr da verbrochen habt! *g*
Ps:
Das Lied vom Tod auf einer Gitarre zu spielen ist unüblich, außerdem ist das eine Geige, auf der Du da rumgeigst! ;o)
Den Code von Tekeli hab ich mir runtergeladen und auch studiert. Wurde erstmal umgehaun von den rießigen Kommentaren oben *g*
Rechnen ist immer gut *g*
Bis jetzt haben wir ja immer nur mit 8 Bit gearbeite, und diese sind bei 255 (11111111) zu Ende.
Mit 16Bit bekommt man Zahlen bis 65025 (11111111 11111111). Also muss man irgendwie zwei 8 Bit Register miteinander verbinden.
Jaja, ich gebs ja zu, hab mich da schon ein wenig drüber informiert, interessiert mich halt, ist ja auch nicht verboten ;)
[edit] Dann eben Geige *g*
@Florian: Das mit den Kommentaren mach ich ja, also einrücken und alle Kommentare in der gleichen Spalte. Sieht man nur hier im Forum nicht, aber im AVR Studio isses wunderbar.
Ok, den Code könnt man noch mehr einrücken, wenn man Blöcke hat, die zusammengehören.
Thomas, es ist sogar angebracht selber zu forschen, ich hab Dir den link zum TutorialZitat:
ist ja auch nicht verboten
gegeben, damit Du auch ein Nachschlagewerk hast, und vor allem, daß Du Dir das alles da reinziehst!
Ich habe nur mit Dieser Seite und mit Dattenblättern gelernt.
Also Selbststudium ist wirklich das a und o.
Aber Du hast recht, man braucht zwei Register, und wenn die nicht reichen dann nimmst Du halt drei, oder 4 oder 8.
Zugegeben, mit solchen Zahlen ist es nicht einfach zu arbeiten, aber wenn man sie braucht
ist es kein Problem.
Spätestens in einem Monat, wenn Du Dir das anschaust, wirst Du froh sein,Zitat:
Wurde erstmal umgehaun von den rießigen Kommentaren oben
solche Komentare gemacht zu haben.
Das Problem an Assembler ist es, daß man verdammt viel Code hat, und wenn man
noch Programme von anderen Personen lesen und verstehen will, wo wenig oder keine Komentare sind, bekommt man graue Haare.
Warum Florian soviel Wert drauf legt wirst Du Morgen erfahren.Zitat:
Dann eben Geige *g*
Ich muß Morgen leider arbeiten ](*,) ](*,) ](*,) womit ich mir das Spielchen leider nicht
angucken kann, aber ich hoffe der Florian hat mehr Zeit und stellt Dir das vor.
Bis dahin kannst Du dich im Tutorial über Zahlen jenseits der 255 marke , den Befehl lpm und die Zeigerregister informieren, glaube mir, es ist wirklich einfach beschrieben.
Ich werde mich jetzt verabschieden, und Euch allen eine gute Nacht wünschen.
Ich freue mich wirklich , daß wir das heute mit der Sirene hinbekommen haben.
Gruß Sebastian
Ok, schade, dass du morgen arbeiten musst. Hoffentlich nicht so lange, wie in der Woche?
Najo, also dann bis morgen.
Gruß und gute Nacht
Thomas
Moin, moin!
Schade, dass Sebastian heute arbeiten muss! *schluchts*
Ich weiß leider nicht, wie viel Zeit ich heute habe bzw. wie lange ich an den PC kann, 5 Wochen habe ich nämlich noch meine Schwester als Anwärterin auf den PC! ;o)
Naja, ich werde versuchen das Ganze einzurichten!
Achso, nagut, ich gebe mich geschlagen! ;o)Zitat:
@Florian: Das mit den Kommentaren mach ich ja, also einrücken und alle Kommentare in der gleichen Spalte. Sieht man nur hier im Forum nicht, aber im AVR Studio isses wunderbar.
Ok, den Code könnt man noch mehr einrücken, wenn man Blöcke hat, die zusammengehören.
Ich muss zugeben, dass ich noch nicht so oft Code gepostet habe! *lol*
Ich habe angefangen mit www.mikrocontroller.net, danach habe ich mit www.avr-asm-tutorial.net weiter gemacht und zum Schluss habe ich noch die Tutorials von Gerhard Paulus durchgearbeitet.Zitat:
Ich habe nur mit Dieser Seite und mit Dattenblättern gelernt.
Ich werde versuchen es zeitlich einzurichten!Zitat:
Warum Florian soviel Wert drauf legt wirst Du Morgen erfahren.
Ich muß Morgen leider arbeiten womit ich mir das Spielchen leider nicht
angucken kann, aber ich hoffe der Florian hat mehr Zeit und stellt Dir das vor.
Und vor allem auch die Datenspeicher-Direktiven DW. und DB. und wo die Unterschiede liegen!Zitat:
Bis dahin kannst Du dich im Tutorial über Zahlen jenseits der 255 marke , den Befehl lpm und die Zeigerregister informieren, glaube mir, es ist wirklich einfach beschrieben.
Ich persönlich liebe DB. und lpm, es sind meine Lieblingsthemen! ;o)
Ich freue mich auch, aber ich bin auch gespannt, wie lange wir für das nächste Kapitel brauchen werden!?Zitat:
Ich freue mich wirklich , daß wir das heute mit der Sirene hinbekommen haben.
So, seit ihr beiden, Thomas und Tekeli, da? ;o)
Dann kann es ja theoretisch los gehen mit der Aufgabe! *freu*
Ist kein Problem wegen der Zeit. Einfach schreiben, wenn man Zeit hat ;) Hab mir gestern schon das mit den Zahlen durchgelesen und ich glaub, dass ich mir schon irgendwie vorstellen kann, wie man sie verbindet.
Bin gespannt, was sonst noch auf mich zukommt *g*
Muss jetzt eh erstmal einkaufen gehen, schau aber gleich wieder rein, wenn ich da bin *suchti* :/ *g*
Gruß
Thomas
[edit]
Da bin ich, pünktlich zum Unterrichtsbeginn ;) Aber wie gesagt, bin dann erstmal kurz wech.
Gut, dann bis gleich!
Melde Dich dann bitte, wenn es losgehen kann! ;o)
Ist Tekeli auch da?
Als online wird er ja angezeigt ;)
Meinte er nicht, er macht im Hintergrund mit? Najo, kannst ja schon die Aufgabe posten, dann kann ich mir im Auto schon Gedanken machen *g*
[edit]
So, nun wech, ich meld mich dann.
Moin moin,
bin ganz Ohr :)
Hier kommt die Aufgabe!
Seit bitte nicht zu geschockt, es ist nicht ganz leicht, aber Sebastian und ich werden euch langsam darauf hinzuführen!
Wir haben als nächstes vor, ein Soundmodul zu programmieren.
Wir werden einfach eine C-Dur-Tonleiter *für die Musiker unter uns* einmal rauf und einmal runter spielen.
Die Frequenzen findet ihr hier:
http://www.pianotip.de/frequenz.htm
Wir werden ersteinmal bei dem c' mit 261,63 Hz anfangen, über den Kammerton a' 440,00 Hz bis hin zum c'' 523,25 Hz.
Die Halbtonschritte lassen wir im ersten Teil weg, ich will euch ja nicht mit der Musiktheorie überfordern! ;o)
Damit wir nun nicht alle Töne einzeln mit großem Aufwand programmieren müssen, werden wir die Werte für die Töne im Speicher des AVR's ablegen.
Das machen mir mit den so genannten Direktiven .DW oder .DB!
Ich persönlich mache es gerne, dass ich die Daten ganz an's Ende des Codes lege.
Das sieht dann folgendermaßen aus:
Wenn man nun die Daten auslesen möchte, muss man das mit Hilfe des Z-Registers und des Befehls lpm machen.Code:.include "m8def.inc"
.
.
.
main:
...
subroutienen:
...
daten1:
.dw 65535 , 0 ; zwei sogenannte Words
daten2:
.db "Hallo!" , 10 , 13 ; immer eine gerade Anzahl an Bytes
Lest euch das bitte durch: http://www.avr-asm-tutorial.net/avr_...ner/index.html
Mit Hilfe des Z-Registers, welches ein 16-Bit-Register ist, legen wir die Position des Zeigers im Speicher fest.
An der Position wird dann mit lpm das Byte ausgelesen und in das Register 0 geschoben. Das können wir dann auslesen.
Schreibt jetzt bitte einen Code, der mit Hilfe des AVR-Speichers in r16 (temp) den Text "Hallo!" ausgibt. Ganz wichtig ist immer, dass ihr eine gerade Anzahl an Bytes benutzt, das hängt mit der Speicherstruktur zusammen.
So weit, so mehr oder weniger gut! ;o)
ich hoffe ihr habt wenigstens etwas verstanden, was ich von euch verlange! *g -> schäm für diesen unverständlichen Post*
Wenn ihr Fragen habt, dann fragt!
Viel Erfolg!
Also ich hab jetzt mal geschaut, aber irgendwie ist das ziemlich kompliziert geschrieben. Einmal benutzt er da Y und einmal Z. Muss ich da nun auch beide Register mit der "Adresse" belegen?
Vor allem seh ich da gar nicht durch, was ich da nun zum Lösen der Aufgabe brauch und wie sollen wir den Text denn ausgeben? Können wir den Text nicht einfach irgendwie in r16 kopieren?
Sorry, aber wahrscheinlich bin ich echt zu doof dafür *g*
Und dann multipliziert er im Tutorial einmal die Adresse mit 2, ja, weils ein Wort ist, also 2 Bytes. Versteh ich aber leider nicht, warum man das dann x2 nehmen muss.
Ich hatte bis jetzt immer Bücher zum lernen, aber da gibts ja leider keine guten...
So wie ich das verstanden habe, ist der Programmspeicher WORD-weise organisiert. Also unter einer Addresse im Programmspeicher findet man 2 Byte. Also z.B.
$3400 "0011 0100" "1000 0001"
Byte1 = "0011 0100"
Byte2 = "1000 0001"
Deswegen beim Zugriff sollte man schon sagen, was man will. Will man Byte1 oder Byte2.
Ist das richtig so?
[EDIT]
Und da man mit dem Programmspeicher arbeitet, benutzt man Z-Register.
@Masters
Wo sollen wir den "Hello!" ausgeben? Oder sollen wir eine Schleife machen, die Daten aus dem Programmspeicher byteweise einliest, und in der r16 schreibt?
Ja, das denk ich auch. Im Tutorial steht folgender Code:
Und weiter unten dann das hier:Code:.EQU Adresse = RAMEND ; In RAMEND steht die höchste SRAM-Adresse des Chips
LDI YH,HIGH(Adresse)
LDI YL,LOW(Adresse)
Aber das versteh ich nicht, brauch ich denn da nun beide Register, kann ich mir aber nicht vorstellen, reicht doch, wenn ich nur ein Registerpaar nehme, oder?Code:LDI ZH,HIGH(2*Adresse)
LDI ZL,LOW(2*Adresse)
LPM
Aber wie gesagt, versteh nicht, warum der mit 2 multiplizieren muss.
Hallo ihr Beiden!
Ich bin mir bewusst, dass es ziemlich verwirrend ist!
Das glaube ich weniger! ;o)Zitat:
Sorry, aber wahrscheinlich bin ich echt zu doof dafür *g*
Ihr braucht euch erstmal nur mit dem Zählerregister Z, also ZL und ZH beschäftigen, die anderen Anwendungen werdet ihr später kennenlernen!
Zitat:
Empfehlungen zur Registerwahl
1. Register immer mit der .DEF-Anweisung festlegen, nie direkt verwenden.
2. Werden Pointer-Register für RAM u.a. benötigt, R26 bis R31 dafür reservieren.
3. 16-Bit-Zähler oder ähnliches realisiert man am besten in R24/R25.
4. Soll aus dem Programmspeicher gelesen werden, Z (R30/31) und R0 dafür reservieren. (WICHTIG!)
5. Werden oft konstante Werte oder Zugriffe auf einzelne Bits in einem Register verwendet, dann die Register R16 bis R23 dafür vorzugsweise reservieren.
6. Für alle anderen Anwendungsfälle vorzugsweise R1 bis R15 verwenden.
Richtig!Zitat:
So wie ich das verstanden habe, ist der Programmspeicher WORD-weise organisiert. Also unter einer Addresse im Programmspeicher findet man 2 Byte.
Ich braucht euch da jetzt nicht große Angst machen, nehmt einfach mal zwei und fertig! ;o)
Also ladet ihr die Adresse der Daten so in das Z-Register:
Jetzt sollt ihr mit lpm die Daten dazu in r0 laden und das dann in r16 rüberschieben.Code:ldi ZL , LOW (datenlabel * 2) ; das kennt ihr ja schon mit Ramend!
ldi ZH , HIGH (datenlabel * 2) ; wie oben
Danach sollt ihr das Z-Register um 1 erhöhen, um das nächste Byte zu bekommen, somit hätte sich die Frage mit den Word's und Byte's erledigt! ;o)
Das ist alles, was ich von euch sehen will! *lol*
Ich hoffe, ich war jetzt verständlicher! *g*
Irgendwo scheint ja etwas nicht klar zu sein!
Wenn ihr möchtet zeige ich euch mal einen fertigen Code und erkläre euch das, ok?
Oder wollt ihr es jetzt selber herausfuseln!? *lol*
Wir lesen noch ein klein bißchen! :)
Gibt uns eine Chance!
http://www.mikrocontroller.net/tutorial/memory
Selber herrausfinden bringt wohl mehr, aber ich komm da ja nun gar nicht klar. Hier mal mein Code:
Wie man sieht, sieht man nichts *g*Code:;Programm
;CDurTonleiter rauf und runter spielen
.include "m8def.inc"
.def tmp = r16 ;Mein Universallregister
.org 0x000
rjmp reset ;Interruptvektor "reset:"
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
ldi ZH, HIGH(daten2 * 2)
ldi ZL, LOW(daten2 * 2)
lpm
sei ;Interrupts zulassen
loop:
adiw ZL,1
lpm
ST Z,tmp
rjmp loop ;immer wieder zu "loop:" springen
daten1:
.dw 65535 , 0 ;zwei Words
daten2:
.db "Hallo!" ;immer eine gerade Anzahl an Bytes
Ich versteh das nicht mit dem Programmspeicher und dem Z-Register und dann muss ich das Z-Register um 1 erhöhen und wieder auslesen und und und...
Vor allem, wozu brauch ich unten zwei Labels mit daten?
Schummler! *lol*
Da steht mein beispiel ja fast Wort für Wort! *rofl* *@ Thomas -> schau da mal*
@ Thomas:
Stell Dir ein Buchregal vor!
Mit dem Z-Register gibst Du nun die Position des Buches an.
Danach ziehst Du das passende Buch mit dem Befehl lpm aus dem Regal und packst es in den Einkaufswagen r0.Code:ldi ZL , LOW (datenlabel * 2)
ldi ZH , HIGH (datenlabel *2)
Da Du es aber nach dem bezahlen mit nach Hause nehmen möchtest musst Du es in einen Beutel packen, r16, da Du den Einkaufswagen nicht mitnehmen darfst/kannst bzw. willst -> für dieses beispiel!
Jetzt verstanden?
Wenn Du dann aber mehrere Bücher haben möchtest, musst Du mehrere Male einkaufen gehen.
Wenn Du vor dem regal stehst musst Du den Pointer für das Regal um eine Position (Byte) erhöhen, um das nächste Buch einzupacken!
Also mal in Stichworten:
- Datenpointer
- Schleife öffnen
- lpm
- r0 (lpm_reg) in r16 (temp) übertragen
- Datenzähler um 1 erhöhen
- Schleife wiederhohlen
Das wars!
Das ist eigentlich, wenn man es einmal verstanden hat, garnicht schwer!?
Ps:
Habs glatt überlesen! ;o)
Die beiden labels sind die Positionen für die daten, die Du auslesen willst, Dein Bücherregal!
Florian, kannst Du uns bitte das mit dieser 2 mal erklären.
Im Tutorial steht, dass.Zitat:
das unterste Bit gibt jeweils an, ob das untere oder obere Byte des Wortes im Programmspeicher geladen werden soll
Sagen wir mal unser speicher beginnt bei b0000 0000 0000 0000 an.
Also
b0000 0000 0000 0000: 0011 1100 0101 0011
Wenn wir die Adresse mal 2 nehmen, bleibt diese ja gleich: 2x0 = 0
Also das unterste Bit der Adresse ist gleich 0. Dann landet 0011 1100 in das r0. Ist das richtig so?
Jetzt erhöhen wir die Adresse um eins:
b0000 0000 0000 0001: 0000 1111 1111 0000
Adresse mal 2 = b0000 0000 0000 0010 -> das unterste Bit ist wieder 0!
hmm, irgendwie versteh ich das nicht :(
Soweit hab ich das erstmal verstanden mit dem Bücherregal, danke.
Hier mal mein Code:
Bloß wie überprüfe ich, ob er auch wirklich den String "Hallo!" in tmp kopiert? Im Debug-Modus seh ich in r16 auch keine Strings..hmm..Code:;Programm
;CDurTonleiter rauf und runter spielen
.include "m8def.inc"
.def tmp = r16 ;Mein Universallregister
.org 0x000
rjmp reset ;Interruptvektor "reset:"
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
ldi ZH, HIGH(daten1 * 2)
ldi ZL, LOW(daten1 * 2)
sei ;Interrupts zulassen
loop:
lpm ;nächstes Byte des String nach r0 einlesen
mov tmp, r0 ;Inhalt von R0 nach "tmp" kopieren
adiw ZL,1 ;Adresse des Z-Pointers um 1 erhöhen
rjmp loop ;immer wieder zu "loop:" springen
daten1:
.db "Hallo!" ;immer eine gerade Anzahl an Bytes
@Tekeli: Danke für den Link, bin grad nicht drauf gekommen, da nachzuschauen *g* Habs dadurch auch erstmal besser verstanden, aber das mit der 2x hab ich immer noch nicht verstanden, also keine Sorge. Im Tut steht ja auch "Über die Multiplikation der Adresse mit 2 sollte man sich erst mal keine Gedanken machen: "das ist einfach so"™" Da hat der Florian wohl den Satz geklaut ;) oder er weiß es selber nicht *duck* *gg*
@Tekeli: Hast du dir den Wert "0011 1100 0101 0011" jetzt nur ausgedacht, oder muss ich verstehen, was dahinter steckt?
Hallo Tekeli!!
Das Zitat ist etwas kompliziert, das habe ich auch zuerst nicht verstanden!
Der Speicher ist so aufgebaut:
00 00 00 00 00 00
das sind jeweils zwei Bytes zusammengefasst in ein Word!
Das erste Word hat die Adresse 0x0000.
Wenn ich jetzt das Z lade, dann steht darin 2*0 = 0, das ist richtig!
Jetzt erhöhe ich das ganze um eins, ohne es mal 2 zu nehmen, das ist wichtig, das muss man nur bei der initalisierung des Z machen!
2*0 = 0 + 0 = 0 -> erste Adresse
2*0 = 0 + 1 = 1 -> nächste Adresse
2*1 = 2 + 0 = 2 -> nächste adresse
2*1 = 2 + 1 = 3 -> nächste Adresse
Hmm..Achtung, doofe Frage, aber wieso addierst du einmal mit 0 und einmal mit 1? Also mit 1 addieren versteh ich ja, weil wir das nächste Byte haben wollen, aber mit 0?
Ok, alles klar!
Danke sehr!
Hey Thomas!
Herzlichen Glückwunsch!
Dein Code ist soweit richtig!
Kleiner Tipp: belege das R0 auch mit einem Namen über .def, z.B. lpm_reg!
*edit*:
War vielleicht etwas dumm, was ich da gemacht habe! *lol*
2*0 = 0 + 0 = 0 -> erste Adresse
erste Adresse + 1 = 1
zweite Adresse + = 2
.....................
Huch, lügst du mich an? *g* Hehe, war ja wirklich nicht so schwer. Hab nun oben noch
.def lpm_reg = r0
geschrieben und im Code dementsprechend geändert.
Florian: Kannst du mir bitte noch sagen, wie ich das mit dem Simulato vom AVR Studio kontrollieren kann, ob er auch wirklich den String in r0 lädt?
Noch eine Frage.
Sollen wir die Zeichenkette mit '\0' selbst abschließen, damit wir wissen wann diese zu Ende ist, oder macht das Assembler für uns?
Sobald Du den Simulator gestartet hast (blauer Pfeil), klickst Du oben im Menü auf View und Memory!
Dann vergleichst Du, ob er die richtigen Bytes aus dem Speicher zieht!
Frage:
Was ist an dem Programm noch nicht perfekt?#
*edit*
Das war meine Frage! *heul* *lol*Zitat:
Sollen wir Zeichenkette mit '\0' selbst abschließen, damit wir wissen wann diese zu Ende ist, oder macht das Assembler für uns?
Nein, wir machen das nicht mit 0!
Rechnet mal mitte aus, wie viele Bytes es sind, die ihr da auslest!
Hmm...seh da nicht richtig durch, Hab Memory, Memory2 und Memory3. Weiß auch nicht, auf welche Bytes ich da achten muss.
Das er immer wieder das Wort in r16 kopiert? Er sollte aufhören, wenn er das Wort fertig kopiert hat, oder?Zitat:
Zitat von Florian
6 Bytes? Da wir 6 Buchstaben haben? So hab ich das zumindest hierraus verstanden:
[edit]Zitat:
.db "Test", 0
ist äquivalent zu
.db 84, 101, 115, 116, 0
Platz 7 in der Statistik ;)
Nur den normalen Memory!Zitat:
Zitat von toeoe
Rechts steht dann alles als ASCII-String, da musst Du dann nach Deinem Hallo! suchen und dann die Maus draufhalten, bis die Adresse erscheint und dann das passende Word dazu raussuchen!
Richtig, er geht auch über den Datenspeicher von uns hinaus! (siehe edit oben)Zitat:
Das er immer wieder das Wort in r16 kopiert? Er sollte aufhören, wenn er das Wort fertig kopiert hat, oder?
Hallo Leute,
Ich habe es geschafft eben nachzuschauen, wie es Euch geht.
Florian hat Euch echt mit dem Holzhammer vor den Kopf gehauen \:D/
Das find ich gut, genau was Stimmt an diesem Code nocht nicht?
Der Florian hat nur Hallo gewollt, also irgendwie merken wann Hallo zu ende :-&
Ups, naja
Es ist jetzt wirklich wichtig, das zu verstehen, weil man den Flash nicht nur für das Programm an sich benutzen kann, sondern auch für Daten, so wie der Florian schon vor hat um z.B. Verschiedene Töne auszugeben (hab selber Angst vor, kenne mich mit Musik nicht aus)
Nur merk euch Ihr braucht erstmal nur den Z-Zeiger und lpm, der rest ist für SRam .
Ich glaube, ich mach mir auch ein Piezo dran, und mache hier mit.
Bis jetzt habe ich noch keine Musik mit dem AVR gespielt
Ahh, ok, da seh ich das "Hallo!" Allerdings steht dadrunter auch noch was, was er ja auch noch in r16 dann kopiert, hab mal ein Bild angefügt.
Das kommt doch bestimmt durch das nichtvorhanden Nullbyte zustande, oder?
Genau, 6 Bytes!
Jetzt schaut euch mal bitte die beiden Vergleichsbefehle cp und cpc an!
Schön, dass Du da bist, Sebastian, in erklären bin ich echt ne NULL! *lol*
Holzhammer war nicht gewollt, aber scheinbar da! *unglücklich guck*