Forum: Mikrocontroller und Digitale Elektronik Anfängerfrage Eingänge "Verunden"


von leMe (Gast)


Lesenswert?

Hallo zusammen,

ich arbeite mich gerade in die Thematik Microcontroler ein.
Ich nutze das AVR Studio und Programmiere in Assembler.
Ich möchte gerne 2 Eingänge "Verunden" und anschließend einen Ausgang 
setzen.
Also, hier mein Code:
1
  //Ausgang im PORTB,7 auf "1" setzen wenn Alle Eingänge (0,2,3,5,6) auf "1"
2
  in r16,PINB
3
  ldi r17,0b01101101
4
  and r16,r17
5
  CP r16,r17
6
  BREQ _B7_AN
7
8
  //Ausgang im PORTB,7 auf "0" setzen wenn Mindestens 1 Eingang (0,2,3,5,6) auf "0"
9
  rjmp _B7_AUS
10
11
//Rücksprungmarke
12
_B7_DONE:

In den Routinen "_B7_AN" bzw "_B7_AUS" wird zum Schluss zur Marke 
"_B7_DONE" gesprungen.


Die Frage ist nun, gibt es eine "bessere" Lösung ?


mfg

von spess53 (Gast)


Lesenswert?

Hi

>Die Frage ist nun, gibt es eine "bessere" Lösung ?

Zumindest eine etwas kürzere:
1
  in r16,PINB
2
  andi r16,0b01101101
3
  cpi r16, 0b01101101
4
  BREQ _B7_AN
5
  ...

MfG Spess

von leMe (Gast)


Lesenswert?

Besten Dank für die Antwort.
Für mich war relevant das es funktionell Fehlerfrei ist.
Da ich mich gerade noch einlese werde ich, der Übersichtlichkeit wegen 
die "längere" variante nehmen.

Danke aber für die Kurzfassung.

mfg

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

leMe schrieb:
> Für mich war relevant das es funktionell Fehlerfrei ist.
Warum hast du das dann nicht gefragt?
leMe schrieb:
>>> Die Frage ist nun, gibt es eine "bessere" Lösung ?
Und ja, Spess hat eindeutig die bessere Lösung durch die Verwendung der 
immediate Befehle andi und cpi. Er spart dadurch die Verwendung des 
Registers 17 (Ressourcen) und einen Taktzyklus (Zeit).

> Da ich mich gerade noch einlese werde ich, der Übersichtlichkeit wegen
> die "längere" variante nehmen.
Es wäre toll, wenn man das am Anfang schon richtig lernen würde und sich 
nicht erst einen umständlichen Stil aneignet und hinterher umlernen 
muss. Und übersichtlicher ist die kürzere Variante allemal...
Und ich hatte die selbe Variante auch schon da stehen, nur war Spess 
schneller... ;-)

von leMe (Gast)


Lesenswert?

Hi,

ich komme Hobbymäsig aus der Programmierecke (c#).
Daher habe ich nicht den Blick für übermäßig Resourcen sparende 
Programme.
Ich habe es bisher so verstanden das die Register (in diesem Fall r17) 
so oder so vorhanden sind, und entsprechend genutzt werden könnnen, also 
würde ich doch eigentlich keine Resourcen sparen wenn ich es nicht nutze 
oder?
Und zum Thema Zeit:
Gibt es wirklich fälle in denen 1-Zyklus Relevant ist?
Ich meine mal gelesen zu haben das die Zykluszeit eine µC (Atmega8) 
~60nSec beträgt.
Gibt es da Fälle in denen +-60nSec den Unterschied machen?


mfg

von dochgast (Gast)


Lesenswert?

leMe schrieb:
> Ich meine mal gelesen zu haben das die Zykluszeit eine µC (Atmega8)
> ~60nSec beträgt.
Bei 16MHz 62,5ns pro Takt, richtig.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

leMe schrieb:
> Ich habe es bisher so verstanden das die Register (in diesem Fall r17)
> so oder so vorhanden sind, und entsprechend genutzt werden könnnen
Richtig, es ist aber nur 1 mal vorhanden. Und wenn du es jedesmal neu 
laden musst, weil jeder damit herumfroscht, kostet das Zeit und 
Speicherplatz...

> Und zum Thema Zeit:
> Gibt es wirklich fälle in denen 1-Zyklus Relevant ist?
Das schon auch.
> Ich meine mal gelesen zu haben das die Zykluszeit eine µC (Atmega8)
> ~60nSec beträgt.
Hängt vom Takt ab.
> Gibt es da Fälle in denen +-60nSec den Unterschied machen?
Es ist nicht dieser eine Befehl. Sondern du kannst alles elegant 
oder umständlich machen (so wie man es gelernt hat, eben). Und dann mach 
den Fehler mal 1000 mal hintereinander.


Mein Rechner hier hat ein paar GHz, und trotzdem ist der manchmal 
langsam. Das liegt u.A. daran, dass zuviel unnötiges Zeug gemacht 
wird...

von Karl H. (kbuchegg)


Lesenswert?

leMe schrieb:
> Hi,
>
> ich komme Hobbymäsig aus der Programmierecke (c#).
> Daher habe ich nicht den Blick für übermäßig Resourcen sparende
> Programme.
> Ich habe es bisher so verstanden das die Register (in diesem Fall r17)
> so oder so vorhanden sind, und entsprechend genutzt werden könnnen, also
> würde ich doch eigentlich keine Resourcen sparen wenn ich es nicht nutze
> oder?

Das kommt drauf an.
Dein komplettes Programm wird ja nicht nur aus diesen 5 Zeilen Code 
bestehen.

Natürlich gibt es für nicht benutzte Register kein Geld zurück. Aber 
jedes Register, welches irgendwo benutzt wird, beeinflusst unter 
Umständen Code an anderen Stellen. Dort muss dann beachtet werden, dass 
genau dieses Register eben nicht unbedingt zur Verfügung steht.
Benutzt du kein Register, weil du es nicht wirklich benötigst, musst du 
dich daher an anderen Programmstellen nicht daran erinnern, dass r17 
genau an dieser Stelle 'verbraucht' wurde. Möglichen Problemen dadurch 
aus dem Weg zu gehen, indem man sie erst gar nicht entstehen lässt ist 
meistens auf lange Sicht gesehen eine ziemlich gute Strategie :-)

> Und zum Thema Zeit:
> Gibt es wirklich fälle in denen 1-Zyklus Relevant ist?
> Ich meine mal gelesen zu haben das die Zykluszeit eine µC (Atmega8)
> ~60nSec beträgt.
> Gibt es da Fälle in denen +-60nSec den Unterschied machen?

Klar.
Wenn ich die Laufzeit eines Lichtstrahls auf 30 Zentimeter messen will, 
kommt es auf jede Nanosekunde an.

D.h. Du musst wissen, anhand deiner Aufgabenstellung, ob du die 
Zeitreserve hast oder nicht! Das kann dir keiner abnehmen, solange er 
die Aufgabenstellung nicht kennt.


Aber hier geht es eigenntlich um was anderes.
Auch wenn die allgemeine Direktive lautet: Optimiere erst, wenn alles 
fertig ist, und feststeht wo du überhaupt Optimierungsbedarf hast (wenn 
überhaupt), bedeutet das noch lange nicht, dass man wie wild 
drauflosprogrammieren kann/sollte. Die eigentliche Frage lautet an 
dieser Stelle: gewinnst du durch die Verwendung des Registers 
irgendetwas? Vielleicht Übersicht oder Zeit oder Programmspeicher? Und 
die Antwort lautet in allen 3 Fällen: Nein.
Warum willst du dann diese Variante verwenden?
Der einzige Grund scheint der zu sein, dass du bisher die entsprechenden 
Immediate-Befehle nicht kanntest. Das wäre dann zwar verständlich, ist 
aber trotzdem ein schlechtes Argument.

von leMe (Gast)


Lesenswert?

Hi,

besten Dank für die viellen Erlkärungen!
Jetzt ist mir das ganze etwas deutlicher geworden warum die von spess53 
gepostete Lösung klar favoriert wird.

Ursprünglich fand ich meine gepostete Lösung leichter verständlich, aber 
durch eure Erklärungen finde ich die gepostete Lösung klar besser, das 
liegt vor allem daran das ich jetzt weis warum genau diese Lösung so 
funktioniert, wie sie funktioniert, bzw was der Unterschied zw AND / 
ANDI ist.

Besten Dank!


mfg

von spess53 (Gast)


Lesenswert?

HI

>Ich habe es bisher so verstanden das die Register (in diesem Fall r17)
>so oder so vorhanden sind, und entsprechend genutzt werden könnnen, also
>würde ich doch eigentlich keine Resourcen sparen wenn ich es nicht nutze
>oder?

Ist richtig. Aber z.B. in einem Interrupt muss man das zusatzlich 
Register extra sichern.

>Gibt es wirklich fälle in denen 1-Zyklus Relevant ist?
>Ich meine mal gelesen zu haben das die Zykluszeit eine µC (Atmega8)
>~60nSec beträgt.

Aber nur bei 16MHz. Der kann beliebig langsam getaktet werden. Bei 
32768kHz sind es 30,5µs.
Und bei dem obigen Beispiel, Interrupt, werden mit dem push/pop aus 
einem zusätzlichen Takt schon fünf.

>Gibt es da Fälle in denen +-60nSec den Unterschied machen?

Auf die Schnelle fällt mit z.B. Videotiming ein.

MfG Spess

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

spess53 schrieb:
> Auf die Schnelle fällt mit z.B. Videotiming ein.
Bei Software-USB (VUSB) werden die Takte auch von Hand abgezählt...

von Karl H. (kbuchegg)


Lesenswert?

leMe schrieb:

> Ursprünglich fand ich meine gepostete Lösung leichter verständlich, aber
> durch eure Erklärungen finde ich die gepostete Lösung klar besser, das
> liegt vor allem daran das ich jetzt weis warum genau diese Lösung so
> funktioniert, wie sie funktioniert, bzw was der Unterschied zw AND /
> ANDI ist.

Eine kleine Zutat fehlt noch.

In diesem Code kommt die Binärkonstante (die wohl die inetressierenden 
Eingänge darstellst) 2 mal vor.
1
  andi r16,0b01101101
2
  cpi r16, 0b01101101

Beide Stellen müssen übereinstimmen, sonst gibt es Datensalat. Bei einer 
Änderung ist es daher wichtig, dass immer beide Stellen geändert werden. 
Und wenn dieselbe Konstante im Programm auch noch an anderen Stellen 
vorkommt, dann muss dort ebenfalls geändert werden.
Das alles ist aufwändig und vor allen Dingen fehleranfällig. Geh niemals 
davon aus, dass du als Programmierer keine Flüchtigkeitsfehler begehst. 
Ganz im Gegenteil, frag dich immer welche Flüchtigkeitsfehler du machen 
kannst und dann frag dich "Was kann ich dagegen tun?"

Im konkreten Fall ist es leicht, da Abhilfe zu schaffen: Schreib die 
Konstante einfach nicht 2-mal hin.

Wie kannst du das machen?

Ganz einfach, in dem du für diese spezielle Binärkonstante einen Namen 
einführst, der nach Möglichkeit irgendwas mit der Aufgabenstellung zu 
tun hat. Bei dir reräsentiert diese Binärzahl eine Maske, die alle 
Eingänge codiert, an denen Taster hängen. Also warum nicht einfach das 
ganze Dinge  ALL_KEY_INPUTS nennen?
1
.equ ALL_KEY_INPUTS = 0b01101101
2
3
....
4
5
  andi r16, ALL_KEY_INPUTS
6
  cpi  r16, ALL_KEY_INPUTS
7
...

Und wenn du dir die verwendende Stelle jetzt nochmal ansiehst und die 
Grundidee hinter der Sequenz ANDI/CPI erkannt hast (nämlich zu testen, 
ob irgendeines der in der Maske angegebenen Bits eine 0 aufweist), dann 
gewinnt dieser 2-Zeiler durch die Verwendung des Namens plötzlich eine 
neue Bedeutungsebene! Jetzt ist auch klar, was denn hier eigentlich 
konzeptionell gestestet wird: Nämlich die Eingabetaster! Noch ein 
kleiner Kommentar dazu, dass hier nach einem 0 Bit gefahndet wird
1
....
2
3
  andi r16, ALL_KEY_INPUTS    ; überprüfen ob irgendeiner auf 0 gegangen ist
4
  cpi  r16, ALL_KEY_INPUTS
5
...

und du hast vorgesorgt, dass du auch in 6 Monaten den Code aus dem 
Zusammenspiel von Code und Kommentar schnell erfassen kannst.

Und als Nebeneffekt ist es nicht mehr möglich, dass dir die beiden 
Konstanten im ANDI/CPI auseinanderlaufen :-)

Man könnte jetzt da noch weiter gehen und sich überlegen wie man die 
Binärkonstante wartungsfreundlicher gestalten kann, aber an dieser 
Stelle möchte ich es momentan damit belassen. Zuviel Information auf 
einmal kann auch kontraproduktiv sein.

von Bill Geht's? (Gast)


Lesenswert?

Lothar Miller schrieb:
> Mein Rechner hier hat ein paar GHz, und trotzdem ist der manchmal
> langsam. Das liegt u.A. daran, dass zuviel unnötiges Zeug gemacht
> wird...


Was zu einem Gutteil an solchen Leuten liegt: :)


leMe schrieb:
> ich komme Hobbymäsig aus der Programmierecke (c#).
> Daher habe ich nicht den Blick für übermäßig Resourcen sparende
> Programme.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Karl Heinz Buchegger schrieb:
> In diesem Code kommt die Binärkonstante (die wohl die inetressierenden
> Eingänge darstellst) 2 mal vor.
> andi r16,0b01101101
> cpi r16, 0b01101101
>
> Beide Stellen müssen übereinstimmen, ...
> Das alles ist aufwändig und vor allen Dingen fehleranfällig.
> ... frag dich "Was kann ich dagegen tun?"
>
> Im konkreten Fall ist es leicht, da Abhilfe zu schaffen:
> Schreib die Konstante einfach nicht 2-mal hin.
1
  in   r16,PINB
2
  com  r16            ; mach eine '0' aus einer '1'
3
  andi r16,0b01101101 ; sieh nach, ob alle interessanten Stellen '0' sind
4
  breq nur_einsen
;-)

von leMe (Gast)


Lesenswert?

Bill Geht's? schrieb:
> Was zu einem Gutteil an solchen Leuten liegt: :)

Ich will hier keine Grundsatzdiskusion starten, aber wie ich hier gerade 
mitbekommen habe gibt es einen großen Unterschied zw Programmentwicklung 
auf µC und PC.
Wer sollte denn schon Bits/Programmzyklen optimiert arbeiten wenn er ein 
1000faches an Speicher / Leistung zur verfügung hat?
Außerdem ging es um  " übermäßig Resourcen sparende Programme" .

Abgesehen davon bedeutet eine lange Lade/Rechendauer noch lange nicht 
das schlecht entwickelt wurde. Ein Algorithmus zum Sortieren von 
1.000.000 Werten dauert nun mal seine Zeit.
Wenn parallel noch weitere rechenintensive Prozesse laufen gibt es 
nunmal ein Nadelöhr.

premature optimization is the root of all evil

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.