Forum: Mikrocontroller und Digitale Elektronik LED Blinken / Lauflicht


von Sheester (Gast)


Lesenswert?

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

von Philipp B. (philipp_burch)


Lesenswert?

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)

von Christian Erker (Gast)


Lesenswert?

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

von Sheester (Gast)


Lesenswert?

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.

von Sheester (Gast)


Lesenswert?

schieb;)

von Johannes M. (johnny-m)


Lesenswert?

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.

von Philipp B. (philipp_burch)


Lesenswert?

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.

von Holger K. (krulli) Benutzerseite


Lesenswert?

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
Noch kein Account? Hier anmelden.