Hallo Leute Wollt mir mit meinem STK500 und mienem ATMega8515 ein Lauflicht basteln. Da dies aber nicht so funktionierte wie ich wollte, hab ich mich entschlossen zuerst mal die LED's blinken zu lassen, da dies einfacher ist. Beim ersten versuch mit folgendem code hats nicht geklappt: //Codebeginn .include "8515def.inc" ;PortB als ausgang deginieren ser r16 out DDRB, r16 ser r18 Main: ldi r16, 0xFF out PortB, r16 Loop1: dec r18 brne Loop1 clr r16 ldi r16, 0x00 out PortB, r16 Loop2: dec r18 brne Loop2 rjmp Main //Codeende als ich dann aber dec r18 durch sbiw r30, 1 ersetzt habe, funktionierte es. Ich frage mich aber warum? bei dec r18 wird doch von 0xFF bis 0x00 runtergezählt bevor weitergemacht wird. Bei sbiw wird doch vom r30 welches mit 0xFF geladen ist immer eins abgezogen, bis es ebenfalls auf 0x00 ist. Seh ich das falsch? denn in meinen augen sollte beides das selbe bewirken. So nun hab ich mienen zuvor erstellten Lauflichtcode ebenfalls mit sbiw "erweitert" jedoch passiert nun nichts anderes, als dass ein led nach dem andern zu leuchten anfängt, bis alle leuchten. //Codeanfang .include "8515def.inc" ser r16 out ddrb, r16 ldi r16, 0xFF Main: sbiw r30, 1 brne main ror r16 out PortB, r16 sbiw r30, 1 brne main rjmp main //Codeende Was mache ich falsch? Hoffe ihr könnt mir meine beiden fragen beantworten;) Gruss Sheester
dec dekrementiert ein Register, zählt also eins ab. sbiw zählt von einem RegisterPAAR eins ab. Dein Blinklicht sollte schon mit dem ersten Code funktionieren, allerdings blinkt das so schnell, dass du es nicht siehst. Wenn du da jetzt sbiw reinhaust, dekrementierst du damit einen 16-Bit-Wert und deine Schleife läuft damit nicht nur 256, sondern 65536 Takte lang. Das wirst du schon eher wahrnehmen können. Für sowas solltest du aber einen Timer verwenden (Siehe Tutorial und Datenblatt). Dein Lauflicht hat einige Fehler drin: 1. Deine zweite Schleife ist Blödsinn (Die springt ja sofort wieder zu main, da wird also gar keine Zeit vertrödelt). 2. Nach brne main ist in jedem Fall das Carry-Bit gesetzt, was ror dazu veranlasst, eine 1 in das Register zu schieben. Wenn du das nicht willst musst du entweder lsr (logical shift right) verwenden oder aber vor dem schieben noch clc (clear carry) ausführen. 3. Sobald du einmal ganz durchgeschoben hast ist das Register leer, bzw. voll, dann passiert beim Schieben nix mehr. Du solltest also nach dem Schieben prüfen, ob das Carry-Bit gesetzt ist (Ist der Fall wenn ein Bit "rausfällt") und dieses dann gleich wieder reinschieben. Z.B.
1 | brcc PC + 1 ;Branch if carry clear |
2 | sbr r16, 1 |
(Ungetestet)
Weiterhin benutzt du die falsche Includedatei.. Die 8515def.inc ist für den AT90S8515, du brauchst die m8515def.inc. Noch mag es gehen aber wenn du mehr machen willst kann sowas die absurdesten Fehler machen dank falscher I/O-Adressen. Gruß, Christian
Vielen dank für die schnelle antwort Also das mit der schlaufe hab ich geändert, war wirklich sinnlos;) nun hab ich die weiteren tipps versucht umzusetzen, jedoch nicht wirklich mit erfolg. Also ich hab mal ne grundätzliche frage zum befehl ror bzw rol. Ich fülle ein register mit dem wert 0xFE das entspricht ja 11111110 Da beim board ja die LED's bei 0 leuchten leuchtet nur das Bit bzw LED 0. Soweit sogut. Wenn ich doch jetzt den befehl rol für das mit 0xFE gefüllte register andwende, sollte doch nichts anderes geschehen ausser dass alle bits nach links geschoben werden oder? das heisst es steht nun 11111101 im register, oder seh ich das falsch? Also müsste doch nun das LED 1 leuchten. Wenn ich aber das Programm durchlaufen lassen, fängt eines nach dem anderen zu leuchten an... Hoffe ihr könnt miene unklarheiten bzw. eventuelle fehlinterpretationen beseitigen.
Sheester wrote: > Also ich hab mal ne grundätzliche frage zum befehl ror bzw rol. > Ich fülle ein register mit dem wert 0xFE das entspricht ja 11111110 > Da beim board ja die LED's bei 0 leuchten leuchtet nur das Bit bzw LED > 0. So weit noch richtig... > > Soweit sogut. Wenn ich doch jetzt den befehl rol für das mit 0xFE > gefüllte register andwende, sollte doch nichts anderes geschehen ausser > dass alle bits nach links geschoben werden oder? So weit auch noch im Prinzip richtig... > das heisst es steht nun > 11111101 im register, oder seh ich das falsch? Das siehst Du tatsächlich falsch. Es werden zwar alle Bits im Register nach links geschoben. Allerdings wird das höchstwertige Bit (also das ganz links) ins Carry-Flag geschoben und das, was vorher im Carry stand, wird von rechts ins Register reingeschoben. Wenn im Carry aber vorher ne Null stand, dann wird von hinten auch eine Null reingeschoben. Konkret: C Register 0 11111110 rol -> 1 11111100 usw... Das Carry ist vor dem rol nur dann gesetzt, wenn bei der vorhergehenden Operation ein Überlauf aufgetreten ist. > Also müsste doch nun das > LED 1 leuchten. Wenn ich aber das Programm durchlaufen lassen, fängt > eines nach dem anderen zu leuchten an... Und das ist dann der Effekt davon. EDIT: Wenn Du mal in die Befehlssatz-Dokumentation schaust (entweder das Pamphlet mit dem Titel "Instruction Set Manual" von der ATMEL-Homepage oder die AVRStudio-Hilfe), dann steht da bei dem Befehl rol die Beschreibung "rotate left through carry" und weiter unten ist auch ein schönes Bildchen von der Prozedur. Das sollte eigentlich keine Fragen offenlassen.
Sry, da hatte ich mich oben wohl geirrt. Ich dachte, du willst eine einzelne 1 durchschieben, nicht einen 0. Ich ziehe es jedoch vor, LED EIN als 1 zu betrachten und erst direkt vor der Ausgabe die Daten mit com rxx umzudrehn.
1 | ;... |
2 | ldi r16, 1 |
3 | loop: |
4 | lsr r16 |
5 | brcc loop_a |
6 | sbr r16, 128 |
7 | loop_a: |
8 | |
9 | ;Bits umdrehen und ausgeben |
10 | com r16 |
11 | out PORTB, r16 |
12 | ;Und wieder zurückdrehen, damit es nachher wieder aufgeht |
13 | com r16 |
14 | |
15 | ;Mach mal 'ne Pause... |
16 | rcall delay_100ms |
17 | rjmp loop |
18 | ;... |
Das könnte irgendwie so aussehn. Zugegeben, das doppelte umkehren ist etwas sinnlos, aber auf das kommt es im Allgemeinen ja nicht an. Falls doch:
1 | ;... |
2 | ldi r16, 254 |
3 | loop: |
4 | sec ;Carry setzen, sonst wird eine 0 reingeschoben |
5 | ror r16 |
6 | brcs loop_a |
7 | cbr r16, 128 |
8 | loop_a: |
9 | |
10 | out PORTB, r16 |
11 | |
12 | ;Mach mal 'ne Pause... |
13 | rcall delay_100ms |
14 | rjmp loop |
15 | ;... |
Ist alles ungetestet. Achja, diese Variante funktioniert auch mit anderen Mustern als einzelnen LEDs.
Die Original Demo-Soft für das STK hat doch schon alles was du brauchst... ... Guck mal ins User Guide vom STK500... Abschnitt 9 http://www.atmel.com/dyn/resources/prod_documents/doc1925.pdf und hier... Beitrag "Re: Kann man einen AVR auch "auslesen" ??"
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.