MezData-Logo Creative Commons License 310 Lösungen Button :AVR: FAQ zu AVR µController

Allgemeine Fragen

Eine ALU ist doch ein Schaltnetz, kein Schaltwerk. Hab ich recht in dieser Annahme?

Jein, in unserem Fall ist es ein Schaltnetz. Es gibt allerdings ALU's die mit einem Mikroprogramm rechnen FPU's Floating Point Units..

Wie sollen wir vorgehen, wenn bei einer Mikrocontroller-Aufgabe explizit nach Akku gefragt wird, wogegen wir doch nur Register zur Verfügung haben?

Nerven behalten, wir haben praktisch 32 Akkus! Tipp: Nehmt einfach das Register R16 als temp als "Ersatz-Akku". Die Lösung zu der µC-Aufgabe muss ich sowieso selber erstellen, bzw. besprechen, daher zählen funktionierende sinnvolle Lösungen mit "unserem" System...

Muss/sollte man Assemblerprogrammcode kommentieren?

Man sollte, wenn es nicht klar ist kommentieren, besonders wenn man keine aussagekräftigen Bezeichner verwendet hat!
Ich tendiere dazu "schlampige" Lösungen schlechter zu bewerten als klare ordentliche saubere einfach lesbare ;-)

Befehle, die offensichtlich das selbe tun?

BRCC k Branch if Carry Cleared If (C=0) THEN PC:=PC+k+1 None 1/2
BRSH k Branch if Same or Higher If (C=0) THEN PC:=PC+k+1 None 1/2

BRCS k Branch if Carry Set If (C=1) THEN PC:=PC+k+1 None 1/2
BRLO k Branch if Lower If (C=1) THEN PC:=PC+k+1 None 1/2

Bei AT90S2313 wird jeweils der selbe OP-Code erzeugt somit ist BRCC gleich BRSH und BRCS gleich BRLO. Warum zwei Bezeichnungen für die selbe Sache verwendet werden ist mir noch schleierhaft..

Verzweigungen, Schleifen und Sprungbefehle

BREQ Branch If Equal (to Zero) IF (Z = 1) THEN PC <- PC + k + 1

Was passiert bei

.def temp = R16
ldi temp, 0b00000111
cp temp, 0b00000111
BREQ 1
RJMP foo
RJMP bar
foo:
...
bar:
...

springt er zu foo oder bar?

Also da z = 1 wird er wohl zu bar springen, bedenke wir zählen Wörter = 2 Byte im Programmspeicher.
Keine Panik, das macht man nicht von Hand, man springt auf Marken und das Ausrechnen von k übernimmt der Assembler!

if(a>13) a=13;

Ist es dann alleine mir überlassen wie ich ihn verarbeite, also z.B. zur schnelleren Umsetzung einfach negiere?
Würde in meinem Programmcode dann so aussehen:

  ldi c,13
  cp c,a
  brpl spring ;wenn das N flag nicht gesetzt ist, also a = c || a < c, dann spring
  ldi a,13
spring:

Die andere Möglichkeit hierbei wäre dann, anstatt brpl zwei Befehle zu nehmen und das ganze etwas anders aufzubauen:

  cpi a,13
  brmi spring ; wenn a - 13 < 0, also 13 > a
  breq spring ; wenn a = 13, nötig um Negation von a>13 zu vervollständigen
  ldi a,13
spring:

Welche der zwei Möglichkeiten ist besser geeignet, und welche passt eher zur Aufgabenstellung? ( die zwei Möglichkeiten geben sich nicht viel in Hinsicht der Programmlänge, aber die erste Möglichkeit hat nur 2 unterschiedliche Ausführungslängen, die andere 3, wobei 2 davon die gleiche Länge haben.

Antwort: Bei Lösung1 wird ein Register c benötigt, würde ich vermeiden, unterschiedliche Ausführungslängen sind aber manchmal auch unerwünscht.. Wenn es so gut kommentiert ist wie hier hab ich mit beiden Lösungen kein Problem!

b=3;if(a=2)b=7;

setze ich das am besten so um:

  ldi b,3
  cpi a,2
  brne spring ; wenn sie nicht gleich sind springe
  ldi b,7
spring:

Ist das so OK, oder muss ich mich stärker nach der Vorgabe richten, auch wenn das Ergebnis das gleiche ist?

Antwort: Ist so bestens! Lösung soll kurz, einfach, gut verständlich und schnell sein. Trifft hier alles zu.

for(i=0;i<=10;i++) a=i;

Ich würde es nun so lösen:

  ldi c,10
  ldi i,0
schleife:
  mov a,i
  inc i
  cpi c,i
  brpl schleife ; solange c>=i ist, also N=0, gehe zu schleife

würde diese Lösung vom Aufbau her passen?

Antwort: Nein, es sind Fehler enthalten: cpi c,i und die Schleife ist fuß-gesteuert, For-Schleifen sind aber Kopf-gesteuert. Hier eine richtige Lösung:

  ldi i,0  ;i initalisieren
schleife:
  cpi i,11 ;i-11 testen, für 0 bis 10 ist es negativ (N = 1)
  brpl ende;wenn Ergebnis positiv, ist Bedingung falsch
  mov a,i  ;den Rumpf ausführen
  inc i    ;i++
  rjmp schleife
ende:  

Sonstige Fragen

Was bedeuten die Load Indirect Befehle? ( bzw. der Teil Indirect )

Indirektes Adressieren von Speicher, haben wir noch nicht behandelt.

Folgende Fragen zu Mezgers Lösung bei HP 03/04 Gruppe 1 Aufgabe 2 zu der Assembler Aufgabe:

(zu A4) geht es auch wenn ich anstelle von den Unterprogrammaufrufen (rcall) die Programmteile nacheinander hinschreib, weil wenn kein sprung angegeben ist, ja automatisch in des nächste Unterprogramm gegangen wird z.B.:

anfang:
    in R16, PINB
    andi R16, 0b001 1111 (<- fehlt da bei dir nicht ne Null?) stimmt es fehlt eine! 0b0001 1111
 
umcodieren:
    ...
 
anzeigen:
    ...
    sbis PINB, 7
    rjmp anfang
 
speichern:
    ...
 
ruecksetzen:
    ...
    rjmp anfang

Klar geht das, es kommt nur darauf an, dass die Befehle in der richtigen Reihenfolge abgearbeitet werden ;-)

Wenn man mit rcall ein Unterprogramm aufruft, springt er dann automatisch wieder zur Aufrufstelle zurück und wenn ja wann? oder braucht man rjmp oder vergleichbares dazu?

Bei rjmp bla wird einfach der PC mit neuem Wert belegt somit dumm zur Stelle bla gesprungen. Bei rcall blub passiert etwas mehr: Es wird auch zur stelle blub gesprungen, zusätzlich wurde aber die die Adresse des Befehls der auf das rcall blub folgt auf einen Stapel (engl. Stack) gelegt. Am Ende des Unterprogramms steht ein ret, das bewirkt, dass mit der obersten Adresse auf dem Stack weiter gemacht wird, also zurückgesprungen wird.

Gruppe I: Worin besteht der Unterschied zwische PORT und PIN? Kann mir das jemand anhand eines Beispieles erklären?

http://mezdata.de/avr/200_schnelleinstieg/

Bei der Zeichnung eines Pins (Anschluss) zu sehen: Es gibt eine Möglichkeit den Eingang abzufragen die Adresse lautet PIN.. Und zu jedem Pin (Anschluss) gibt es ein D-FF (Adresse PORT) das den Wert des Ausgangs speichern kann. Der Wert des D-FF wird zum Ausgang durchgeschaltet wenn ein Richtungs D-FF (Adresse DD) eine 1 gespeichert hat.

Frage zum SRAM Adressieren bei AVR

Auf http://mezdata.de/avr/120_indirektes-adr/ wurde ersten Bild beim SRAM geschrieben, dass er 128 Byte groß ist. Weiter unten (bei den 4 Beispielen zur direkten Adressierung) hast im 4. Bsp geschrieben, dass der SRAM ne 16 Bit Adresse hat. Handelt es sich hier um den gleichen µContoller oder gilt für des Beispiel das was in den Klammern dahinter steht und ist somit für uns nicht relevant? denn für die 128 Byte würden doch 7 Bit zur Adressierung reichen, da er wortweise organisiert ist die indirekte Adressierung, braucht man doch nur wenn man was Zusammenhängendes (Liste, ...) in den RAM schreiben/lesen will oder?

Unser Controller hat 128 Byte somit würden 7 Bit reichen, aber man will ja Programme universeller schreiben und den Quelltext auch mühelos auf fettere Teile anwenden können z.B. auf den Mega32... Da sind 8Bit zu wenig, somit noch ein Register somit 16 Bit!

03/04 Biathlon 4. PAP sind in dem vorgegeben ein paar Befehlszeilen in einem Kasten zusammengefasst und erklärend beschrieben was passiert, also ohne so zuweisungspfeile usw. können wir das auch so machen?

Jein, mir sind klare Zuweisungen lieber, aber hier wird auch klar beschrieben was gemacht wird, somit ist es akzeptabel.. Allerdings welches Register wird konkret gemeint?? Konkrete Lösung ist immer besser als nebulöse Gedanken! 

AVR-Pins: DDBn PORTBn I/O Pull-up Kommentar

0 0 Input No Tri-State (Hochohmig)
0 1 Input Yes Der Ausgang liefert einen Strom für z.B. Taster auf GND

das PORTB setzen brauch ich wenn ich den eingangswert definieren will ... d.h. bei taster -> PORTB auf 1 damit eingangszustand definiert ist?

Also DDBn ist 0 damit ein Eingang. PORTBn ist 1 damit ist der PullUp Transistor geschaltet und liefert einen PullUp-Strom. D.h. der Pin hängt auf Log 1 ohne Beschaltung -> wenn wir den auf 0, Ground (GND) mit nem Taster ziehen, dann ist da 0 zu lesen via PINBn, wenn Taster gedrückt.