Forum: Mikrocontroller und Digitale Elektronik Mein erstes Programm, zu groß für die Funktion


von Agop A. (bike-led)


Angehängte Dateien:

Lesenswert?

Hallo,
ich bin noch blutiger Anfänger und habe fast selbständig ein kleines 
Programm geschrieben.
Das funktioniert auf meinem myAVR Board, aber es scheint mir viel zu 
groß für das was es tut.
Würde mich über Kritik und Tipps freuen


MfG
Ademann

;+----------------------------------------------------------------------
;| Title    : Lauflicht vorwärts, rückwärz, stop 6 LEDs
;+----------------------------------------------------------------------
;| Funktion    : Wenn Taster betätigt,Lauflicht hin und zurück
;    : LED1 leuchtet etwas länger, nach 3 Durchläufe, aus.
;+----------------------------------------------------------------------
;| Prozessor  : ATmega8
;| Takt    : 3,6864 MHz
;| Sprache         : Assembler
;| Datum           : 29.11
;| Version         : ...
;| Autor           : A41
;+----------------------------------------------------------------------
.include  "AVR.H"
;----------------------------------------------------------------------- 
-
;Reset and Interrupt vector             ;VNr.  Beschreibung
  rjmp  main  ;1   POWER ON RESET
  reti    ;2   Int0-Interrupt
  reti    ;3   Int1-Interrupt
  reti    ;4   TC2 Compare Match
  reti    ;5   TC2 Overflow
  reti    ;6   TC1 Capture
  reti    ;7   TC1 Compare Match A
  reti    ;8   TC1 Compare Match B
  reti    ;9   TC1 Overflow
  reti    ;10  TC0 Overflow
  reti    ;11  SPI, STC Serial Transfer Complete
  reti    ;12  UART Rx Complete
  reti    ;13  UART Data Register Empty
  reti    ;14  UART Tx Complete
  reti    ;15  ADC Conversion Complete
  reti    ;16  EEPROM Ready
  reti    ;17  Analog Comparator
  reti    ;18  TWI (I²C) Serial Interface
  reti    ;19  Store Program Memory Ready
;----------------------------------------------------------------------- 
-
;Start, Power ON, Reset
main:  ldi  r16,lo8(RAMEND)
  out  ioSPL,r16
  ldi  r16,hi8(RAMEND)
  out  ioSPH,r16
  ldi  r16,0b11111111
  out  DDRB,r16
  cbi  DDRD,2
  out  PORTD,r16
;----------------------------------------------------------------------- 
-
mainloop:  in  r20,PIND
  sbrc  r20,2
  rjmp  mainloop
  rjmp  lau
;----------------------------------------------------------------------- 
-

lau:  sbi  PORTB,0  ;hin 1,2,3,4,5,6
  rcall  wait
  cbi  PORTB,0
  sbi  PORTB,1
  rcall  wait
  cbi  PORTB,1
  sbi  PORTB,2
  rcall  wait
  cbi  PORTB,2
  sbi  PORTB,3
  rcall  wait
  cbi  PORTB,3
  sbi  PORTB,4
  rcall  wait
  cbi  PORTB,4
  sbi  PORTB,5
  rcall  wait
  cbi  PORTB,5
;----------------------------------------------------------------------- 
----
  sbi  PORTB,4  ;zurück 5,4,3,2,1
  rcall  wait
  cbi  PORTB,4
  sbi  PORTB,3
  rcall  wait
  cbi  PORTB,3
  sbi  PORTB,2
  rcall  wait
  cbi  PORTB,2
  sbi  PORTB,1
  rcall  wait
  cbi  PORTB,1
  sbi  PORTB,0
  rcall  wait
  cbi  PORTB,0
;----------------------------------------------------------------------- 
-----
  sbi  PORTB,0  ;LED1 bleibt dreimal länger an
  rcall  wait
  cbi  PORTB,0
  sbi  PORTB,0
  rcall  wait
  cbi  PORTB,0
  sbi  PORTB,0
  rcall  wait
  cbi  PORTB,0

;----------------------------------------------------------------------- 
------
;Alles noch mal
  sbi  PORTB,0
  rcall  wait
  cbi  PORTB,0
  sbi  PORTB,1
  rcall  wait
  cbi  PORTB,1
  sbi  PORTB,2
  rcall  wait
  cbi  PORTB,2
  sbi  PORTB,3
  rcall  wait
  cbi  PORTB,3
  sbi  PORTB,4
  rcall  wait
  cbi  PORTB,4
  sbi  PORTB,5
  rcall  wait
  cbi  PORTB,5
  sbi  PORTB,4
  rcall  wait
  cbi  PORTB,4
  sbi  PORTB,3
  rcall  wait
  cbi  PORTB,3
  sbi  PORTB,2
  rcall  wait
  cbi  PORTB,2
  sbi  PORTB,1
  rcall  wait
  cbi  PORTB,1
  sbi  PORTB,0
  rcall  wait
  cbi  PORTB,0
  sbi  PORTB,0
  rcall  wait
  cbi  PORTB,0
  sbi  PORTB,0
  rcall  wait
  cbi  PORTB,0
  sbi  PORTB,0
  rcall  wait
  cbi  PORTB,0

;----------------------------------------------------------------------- 
--------------------------------
;Alles noch mal
  sbi  PORTB,0
  rcall  wait
  cbi  PORTB,0
  sbi  PORTB,1
  rcall  wait
  cbi  PORTB,1
  sbi  PORTB,2
  rcall  wait
  cbi  PORTB,2
  sbi  PORTB,3
  rcall  wait
  cbi  PORTB,3
  sbi  PORTB,4
  rcall  wait
  cbi  PORTB,4
  sbi  PORTB,5
  rcall  wait
  cbi  PORTB,5
  sbi  PORTB,4
  rcall  wait
  cbi  PORTB,4
  sbi  PORTB,3
  rcall  wait
  cbi  PORTB,3
  sbi  PORTB,2
  rcall  wait
  cbi  PORTB,2
  sbi  PORTB,1
  rcall  wait
  cbi  PORTB,1
  sbi  PORTB,0
  rcall  wait
  cbi  PORTB,0
  sbi  PORTB,0
  rcall  wait
  cbi  PORTB,0
  sbi  PORTB,0
  rcall  wait
  cbi  PORTB,0
  sbi  PORTB,0
  rcall  wait
  cbi  PORTB,0

;----------------------------------------------------------------------- 
--
;Warteschleife
wait:  push  r16
  push  r17
  ldi  r17,255
loop:  nop
  nop
  nop
  nop
  dec  r16
  brne  loop
  dec  r17
  brne  loop
  pop  r17
  pop  r16
  ret

;----------------------------------------------------------------------- 
-

: Verschoben durch User
von Davis (Gast)


Lesenswert?

Man kann froh sein, dass du nicht noch längere Programme schreibst.

von P. M. (o-o)


Lesenswert?

Sieht nicht sooo schlecht aus, fürs erste.

Was man tun könnte: Anstatt jeden Port explizit zu setzen, könnte man 
das auch in eine Schleife packen. Bei jedem Schleifendurchlauf wird ein 
Counter erhöht, der dann angibt, welches Bit gesetzt und gelöscht werden 
soll. Ganz so direkt geht das nicht, aber denk mal darüber nach, wie man 
es machen könnte. Eine komplette Antwort gebe ich hier nicht, verstehe 
meinen Vorschlag eher als "Übungsaufgabe" :-)

Davis schrieb:
> Man kann froh sein, dass du nicht noch längere Programme schreibst.

Man wäre froh, wenn du deutlich kürzere Postings verfassen würdest.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Agop Ademann schrieb:
> Würde mich über Kritik und Tipps freuen

Der Forenbereich "Codesammlung" ist für derartiges der falsche.

von Karl H. (kbuchegg)


Lesenswert?

Fang mal damit an, dass du eine Sequenz die sich ein paar mal wiederholt 
dadurch realisierst, dass du ein Register bis auf 0 herunterzählst und 
so etwas bildest, was man eine Schleife nennt.

Also anstelle von
1
   A
2
;     nochmal
3
   A
4
;     und nochmal
5
   A

sowas
1
   ldi r18, 3
2
3
repeat:
4
   A
5
6
   dec r18
7
   brne repeat


(A steht für eine beliebige, immer gleiche Sequenz. Bei dir dann eben 
das Durchschalten der LED einmal hin und wieder zurück, welches 3 mal 
wiederholt werden soll)
Alleine dadurch fällt schon mal fast 2/3 deines Codes weg. Und wenn du 5 
Wiederholungen gehabt hättest, würden fast 4/5 deines Strickmuster-Codes 
wegfallen. Und bei 100 Wiederholungen .... du hast die Idee, um die es 
geht.

Ansonsten:
Man kann aus dem
AVR-Tutorial
auch eine Menge über Codeaufbau und sonstiges lernen!

von troll (Gast)


Lesenswert?

Was heisst viel zu groß?

Glaskugel: Du hast die Größe der ASM-Datei oder der HEX-Datei angeguckt. 
Das ist falsch. Was zählt ist die Codegröße die AVR-Studio nach der 
Assemblierung anzeigt.

von Karl H. (kbuchegg)


Lesenswert?

troll schrieb:
> Was heisst viel zu groß?

Es ist ihm selbst seltsam vorgekommen, dass eine einfache Funktionalität 
sich in 50 COdezeilen niederschlägt.


Jungs. Es gibt keinen Grund ihn zu verarschen!
Er wusste nicht, wie er das anders machen soll ausser durch 
Codeduplizieren im Editor. Und es ist zumindest beachtenswert, dass er 
selbst drauf gekommen ist, dass das wohl nicht der Weisheit letzter 
Schluss sein kann und es da etwas anderes geben könnte.

von troll (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Es ist ihm selbst seltsam vorgekommen, dass eine einfache Funktionalität
> sich in 50 COdezeilen niederschlägt.
Ah so.

> Jungs. Es gibt keinen Grund ihn zu verarschen!
? Ich verarsche niemanden.

von Eumel (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Jungs. Es gibt keinen Grund ihn zu verarschen!
> Er wusste nicht, wie er das anders machen soll ausser durch
> Codeduplizieren im Editor. Und es ist zumindest beachtenswert, dass er
> selbst drauf gekommen ist, dass das wohl nicht der Weisheit letzter
> Schluss sein kann und es da etwas anderes geben könnte.


So ist es, er hat ein Problem gelöst und sich trotzdem noch gedacht: 
"Das sollte auch besser gehen".
Und das ist doch ein toller Antrieb weiter zu lernen!

von Uwe (Gast)


Lesenswert?

Hi!
mal so als Tip:


nochmal: ldi R18,1
         out portB,R18
         rcall wait
         rol R18
         brcc nochmal
         ror R18
         .....
         .....
         .....
Viel Erfolg, Uwe

von oldmax (Gast)


Angehängte Dateien:

Lesenswert?

Hi
Na ja, so hab ich auch mal angefangen und mich dann auch oft gewundert, 
warum es was nur eine kurze Zeit das tut, wie man es erwartet. Daher 
hier mal die Fehler zuerst:
Du springst zu lau: mit einem JMP. Nicht schlimm, aber ich seh in diesem 
Programmteil kein JMP Mainloop. Daraus folgt, du läufst direkt in die 
Routine Wait und dann mit RET ?? ja, wohin ? Der Stack ist zu diesem 
Zeitpunkt ja leer.
Zweiter Fehler:
In Wait setzt du zwar R17, aber ich sehe keine Zuweisung an R16. Ist 
nicht schlimm, denn irgendwas wird da schon drin stehen, auch wenn 
vorher ein Push den Wert "gerettet" hat.
Zum Thema Push und POP. Bei einem Sprung zu einer Subroutine ist ja 
klar, welche Register nicht verändert werden dürfen und wenn du diese in 
der Sub nicht veränderst, brauchst du kein Push und POP. Anders ist es 
bei Interrupts. Da weißt du nicht, welche Register grad aktuell sind und 
daher ist es dort zwingend, Register zu "retten".
Nun mal etwas zur Sache. Das du mit Zählschleifen einiges kürzer machen 
kannst, haben dir die Kollegen ja schon gesagt. Das wäre denn auch der 
nächste Schrit für dich. Um aber ein Bild vom Programmablauf zu 
bekommen, an dem man sich orientieren kann, solltest du diesen 
skizzieren. Dieser Vorgang ist völlig unabhängig davon, welche Sprache 
du sprichst.
Im Anhang hab ich's mal skizziert.
Gruß oldmax

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.