Hallo! Ich bin gerade dabei mir assembler für avrs anzueignen. dazu wollte ich ein wenig mit den leds des stk500 spielen. Ich würde die leds gerne von aussen nach innen rotieren lassen, aber von beiden seite, ungefähr so: x------x x = led an -x----x- - = led aus --x--x-- ---xx--- ---xx--- --x--x-- -x----x- x------x dabei bin ich auf folgende zwei probleme gestossen: 1. Wie rotiere ich nur ein bit durch ein register? (wenn ich rol oder ror aufrufe, gehen alle leds nacheinander an) 2. Wie lasse ich nur die unteren bzw oberen 4 Bit des registers rotieren(ich muss ja unten nach links schieben und die oberen rechts) hier meine interrupt routine: schieben_leds: push temp;temp speichern clr mili ;milisekunden zähler zurücksetzen mov temp, leds;register leds in temp laden ror temp;temp nach recht schieben mov leds, temp;geschobenes temp zurück in leds laden out PORTB, leds;ausgabe des led registers pop temp;temp laden
Hallo Markus, sowas machst du am einfachsten mit Tabellen in denen du die Bitmuster ablegst. Schiebeoperationen sind dafür zu umständlich. Gruß, SIGINT
http://www.mikrocontroller.net/articles/AVR-Tutorial:_Mehrfachverzweigung#Sprungtabelle Nur noch ein Zähler, der von 0-7 oder 8 zählen kann und fertig Ach ja in den Zweigen schreibst du einfach was wie:
1 | zweig_3: ldi temp2, 0b001000100 rjmp ende_vergleich |
2 | zweig_4: ldi temp2, 0b..... |
MfG Steven
das funktioniert nicht... ich denke mal ich mach auch irgendwas falsch .include "m16def.inc" .def leds = r16 .def temp = r17 .def mili = r18 .def sek = r19 .def status = r20 .def temp2 = r21 .equ minimum = 3 .equ maximum = 7 .org 0x00 rjmp main .org OVF0addr rjmp schieben main: ldi temp, LOW(RAMEND) ; Stackpointer initialisieren out SPL, temp ldi temp, HIGH(RAMEND) out SPH, temp ldi leds, 0xFF ; lade Arbeitsregister r16 mit der Konstanten 0xFF out DDRB, leds ; Inhalt von r16 ins IO-Register DDRB ausgeben ldi leds, 0xfe ; 0b11111100 in r16 laden out PORTB, leds ; r16 ins IO-Register PORTB ausgeben ldi temp, 1 << CS02 out TCCR0, temp ldi temp, 1 << TOIE0 out TIMSK, temp sei rjmp loop schieben: push temp ; temp 1 sichern in temp,sreg ; SREG sichern push temp inc mili ldi temp, 0x0F cp mili, temp breq schieben_leds rjmp end_tim_ovf0 schieben_leds: push temp clr mili subi temp,minimum ; Nullpunkt verschieben cpi temp,(maximum-minimum+1) ; Index auf Maximum prüfen brsh end_tim_ovf0 ; Index zu gross -> Fehler ldi ZL,low(Mustertabelle) ; Tabellenzeiger laden, 16 Bit ldi ZH,high(Mustertabelle) add ZL,temp ; Index addieren, 16 Bit ldi temp,0 adc ZH,temp ijmp out PORTB, leds ; aktualisieren pop temp end_tim_ovf0: pop temp out sreg,temp ; sreg wieder herstellen pop temp reti Mustertabelle: rjmp m0 rjmp m1 rjmp m2 rjmp m3 m0: ldi leds, 0b10000001 ret m1: ldi leds, 0b01000010 ret m2: ldi leds, 0b00100100 ret m3: ldi leds, 0b00011000 ret loop: rjmp loop ; Sprung zur Marke "ende" -> Endlosschleife
Ja man veröffentlicht sowas als Anhang! Wo ist da jetzt der Unterschied?
Ja nur 2,3 Befehle reichen halt auch nicht. Das ist mir schon klar. Aber du hast das doch ganz gut hinbekommen. So in der Art meinte ich es. Ich hab meine Sammlung leider nicht da, aber ich kann dir ja morgen früh mal ein Beispiel von mir geben, wenn du willst.
ja aber es passiert gar nichts... das mit dem beispiel wäre nett. in c würde ich mir jetzt einen char array anlegen und den durchgehen. ist sowas auch in assembler möglich?
also... das mit der sprungtabelle funktioniert jetzt so weit. aber das programm springt immer nur in m2. warum?
Hi
>in c würde ich mir jetzt einen char array anlegen und den durchgehen.
In Assembler(und binär):
Leds: .db 0b10000001,0b01000010
.db 0b00100100,0b00011000
.db 0b00011000,0b00100100
.db 0b01000010,0b10000001
Zugriff mit:
ldi ZL,Low(leds<<1)
ldi ZH,High(leds<<1)
add ZL,Offset ;Offset: in Register rxy
adc ZH,NULL ;NULL: Register mit 0 geladen
lpm ry,Z
Das Register Offset musst du in deinem Programm errechnen.
Wenn du Z nicht weiter brauchst:
ldi ZL,Low(leds<<1)
ldi ZH,High(leds<<1)
lpm tyx,Z+
Jetzt sollte Enderkennung kommen
MfG Spess
PS@ Falk: Das ist aber nur die halbe Wahrheit.
Das geht auch ohne Tabelle: M2: ldi Hilf,$01 ldi Hilf2,$80 ldi temp,8 ; 8mal M1: ldi Muster,$00 or Muster,Hilf or Muster,Hilf2 com Muster ; für STK500 invertieren out PortB, Muster rcall delay05s lsr Hilf2 lsl Hilf dec temp brne M1 rjmp M2 Hilf2 wird nach rechts geschoben und Hilf nach links und die Bits jeweils mit "oder" in Muster gesetzt.
>ja aber es passiert gar nichts geh mir nicht auf dem Keks!!! Das ginge, wenn du wüsstest was ich meine! Im Anhang ein Programm mit einer Tabelle, das 2 LEDs zeigt, die in einen dunklen Raum gehen, dann aber Angst bekommen und zurückrennen. MfG Steven
Cool, aber echt umständlich... IJMP und ICALL sind verdammt starke und auch sehr nützliche Befehle, aber für diesen Zweck einfach Unfug (zuviel Overhead). Es ist je nach Zählerstand ein anderes Bitmuster an den Port auszugeben. Dies erreicht man am einfachsten mittels LPM über den Z-Pointer. Das Verfahren wurde bereits von Spess53 beschrieben, weshalb ich mir jetzt ein weiteres Beispiel spare. KH
Ok scheint einfacher zu sein. Werd ich beim nächsten Mal berücksichtigen. Danke! MfG Steven
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.