Forum: Mikrocontroller und Digitale Elektronik ASM Befehl gesucht


von blutengel (Gast)


Lesenswert?

Hi!

habe folgenden Code:
1
AVR-Assembler-Code
2
ldi aus,0b11111111
3
4
rcall spi_send
5
6
spi_send:
7
rjmp start
8
carry_zero:
9
cbi porta,0
10
sbi Porta, 2
11
cbi porta,2
12
13
start:
14
inc zaehler
15
BRCC carry_zero
16
sbi Porta,0
17
sbi Porta, 2
18
cbi porta,2
19
rjmp start
20
ret

Und zwar will ich damit ein 8BIT
Register seriell ausgeben(SPI Versuch)die Timings werden noch nicht 
stimmen.Mit Rotieren über Carry gebe ich das Register Bit für Bit 
aus.Bei der Einzelschritt Simulation ist mir aufgefallen das nach dem 8 
Bit das Carry 0 wird und nach einem weiteren Durchgang alles von vorne 
anfängt. Wie bekomme ich es hin das ch nach genau 8 Bit´s (Durchläufen) 
aus der Schleife raus springe. Ich hatte die Idee ein Weiteres Register 
mit einer 8 zu laden und dies mit meiner Variable zaehler zu vergleichrn 
und sobald es gleich ist zu springen. Mit welchem Befehl kann ich das 
machen oder gibt es eine andere Möglichkeit


MFG

blutengel

von blutengel (Gast)


Lesenswert?

Sorry falscher Code es fehlte was
1
AVR-Assembler-Code
2
ldi aus,0b11111111
3
4
rcall spi_send
5
6
spi_send:
7
rjmp start
8
carry_zero:
9
cbi porta,0
10
sbi Porta, 2
11
cbi porta,2
12
13
start:
14
ror r17;Rotieren Links über Carry
15
inc zaehler
16
BRCC carry_zero
17
sbi Porta,0
18
sbi Porta, 2
19
cbi porta,2
20
rjmp start
21
ret

von Karl H. (kbuchegg)


Lesenswert?

blutengel schrieb:

> aus der Schleife raus springe. Ich hatte die Idee ein Weiteres Register
> mit einer 8 zu laden und dies mit meiner Variable zaehler zu vergleichrn
> und sobald es gleich ist zu springen.

Ziemlich genau so wird es im AVR-Tutorial gemacht. NUr wird dort ein 
Register mit 8 geladen, nach jedem Schleifendurchlauf das Register um 1 
runtergezählt und wenn dann das Ergebnis 0 ist, dann sind 8 Durchläufe 
vorbei.

http://www.mikrocontroller.net/articles/AVR-Tutorial:_Schieberegister#Ansteuerung_per_Software

von blutengel (Gast)


Lesenswert?

Danke hat schon gut weiter geholfen:

Habe es jetzt mal so gemacht:
1
AVR-Assembler-Code
2
.include"m32def.inc"
3
4
;SPIOUT Porta.0  (SI
5
;SPIIN  Porta.1  (A0)
6
;CLK    Porta.2  (SCL)
7
;CS    Porta.3  (CS1B)
8
;
9
;
10
11
12
.def temp = r16
13
.def aus = r17
14
.def zaehler = r18
15
16
17
 
18
         ldi temp, HIGH(RAMEND)            ; HIGH-Byte der obersten RAM-Adresse
19
         out SPH, temp
20
         ldi temp, LOW(RAMEND)             ; LOW-Byte der obersten RAM-Adresse
21
         out SPL, temp
22
23
ldi r16,0xff
24
out ddra,r16
25
26
ldi zaehler,8
27
28
haupt:
29
ldi aus,0b11000011
30
31
rcall spi_send
32
33
spi_send:
34
rjmp start
35
carry_zero:
36
cbi porta,0
37
sbi Porta, 2
38
cbi porta,2
39
40
start:
41
BReq end
42
ror r17;Rotieren Links über Carry
43
44
dec zaehler
45
46
BRCC carry_zero
47
sbi Porta,0
48
sbi Porta, 2
49
cbi porta,2
50
rjmp start
51
ret
52
53
54
end:
55
rjmp end

Ist jetzt nur ein Test um ein Register NUR EIN MAL auszugeben.Gibt es da 
noch was zu verbesser oder ist es so OK?

MFG

blutengel

von Karl H. (kbuchegg)


Lesenswert?

Für meinen Geschmack wird da zuviel hin und her gesprungen

Bei jedem BREQ oder BRNE oder anderem Sprung der auf dem Zustand von 
Flags basiert, solltest du dich unbedingt immer Fragen: Wenn eine 
Funktion betreten wird, wer garantiert man dann den Zustand der Flags

Wenn aus deinem (späteren) Programm heraus spi_send angesprungen wird, 
dann ist die Abarbeitung

  Aufruf von spi_send

  spi_send:
     rjmp start

ok weiter bei start

  start:
    BReq end

Ooops. Du selbst hast das Zero-Flag nie gelöscht. Wenn es der Aufrufer 
nicht tut und zufällig zuletzt ein 0-Ergebnis ausgerechnet hat, dann 
gehts hier sofort wieder aus der Funktion raus.

Je weniger Dinge beim Aufruf einer Funktion zu beachten sind, umso 
besser. Du willst einem Aufrufer nicht die Umsicht aufbürden, das 
Zero-Flag löschen zu müssen ehe er die Funktion aufruft. Das ist ein 
vermeidbarer Fehler.

zaehler wird ebenfalls innerhalb der Funktion nicht zuverlässig auf 8 
gesetzt. Deine Funktion funktioniert nur für 1 Aufruf und dann nie 
wieder.


(Und benutze das bitte nicht als Ausrede, dass noch nicht mehr gefordert 
ist. Einen Wert ausgeben kann ich auch mittels

  cbi porta,0
  sbi Porta, 2
  cbi porta,2

  cbi porta,0
  sbi Porta, 2
  cbi porta,2

  cbi porta,0
  sbi Porta, 2
  cbi porta,2

  cbi porta,0
  sbi Porta, 2
  cbi porta,2

  cbi porta,0
  sbi Porta, 2
  cbi porta,2

  cbi porta,0
  sbi Porta, 2
  cbi porta,2

  cbi porta,0
  sbi Porta, 2
  cbi porta,2

  cbi porta,0
  sbi Porta, 2
  cbi porta,2


das würde auch das gewünschte leisten und durch Austausch von ein paar 
cbi durch sbi kann ich das anpassen. Also dieses Argument gilt nicht. 
Programmieren fängt dort an, wo eine Funktion zuverlässig und ohne 
Vorbedingungen das Richtige tut. Und zwar wieder und immer wieder.

von blutengel (Gast)


Lesenswert?

Mir ist erstmal wichtig das es vom Prinzip her richtig ist. Das ich 
Zähler Flags und sonstiges vor dem aufruf säuber bzw. rücksetzen muss 
ist mir klar.Meine Frage ist jetzt ob ich nach dem Prinzip Daten über 
SPI senden kann?

MFG

blutengel

von spess53 (Gast)


Lesenswert?

Hi

Vielleicht hilft dir das weiter:
1
spi_out:                push r16
2
                        push r18
3
                        ldi r16,8
4
spi_out10:              cbi lcdato,lc_dat
5
                        cbi lcdato,lc_clk
6
                        sbrc r18,7
7
                        sbi lcdato,lc_dat
8
                        lsl r18
9
                        nop
10
                        sbi lcdato,lc_clk
11
                        nop
12
                        dec r16
13
                        brne spi_out10
14
                        cbi lcdato,lc_clk
15
                        pop r18
16
                        pop r16
17
                        ret

Datenbyte wird in r18 übergeben. Port und Pins sind mit lcdato, lc_dat 
und
lc_clk frei wählbar.

MfG Spess

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.