Forum: Mikrocontroller und Digitale Elektronik banksel so oder so schreiben?


von Michael B. (auchduliebergott)


Lesenswert?

Hallo zusammen,
ich habe folgende Unsicherheit:

Ich definiere "STROM", wie folgt:
#define  STROM  LATB,7

Um "STROM" zu verändern, habe ich die folgende Möglichkeit:
  banksel  LATB
  bcf  STROM
  banksel  .0

Besser würde mir gefallen, wenn ich schreiben könnte:
  banksel  STROM
  bcf  STROM
  banksel  .0

Sind beide Schreibweisen gleichwertig?

von Andras H. (kyrk)


Lesenswert?

Erzeugte HEX file angucken oder den Listing file. Da siehst du was aus 
den konstrukten gemacht wird.

von Michael B. (auchduliebergott)


Lesenswert?

Hallo Andreas,

danke für den Tipp. Das habe ich versucht, aber leider bin ich (noch) 
nicht in der Lage, bei MPLAB/Assembler ein Listing oder den Disassembler 
aufzurufen.
Vielleicht weißt Du die Antwort, so dass ich weiter kommen kann? Ich 
wäre Dir sehr dankbar!

von Michael B. (auchduliebergott)


Lesenswert?

Problem gelöst:

Die folgende Schreibweise funktioniert nicht und erzeugt eine 
Fehlermeldung.

#define  STROM  LATB,7

  banksel  STROM
  bcf  STROM
  banksel  .0

D.h. der Assembler gibt die Meldung aus, "Illegal character (,)".
Ich kann zwar kein Komma sehen, aber wenn das funktionieren würde, würde 
keine Fehlermeldung kommen.

Also muss ich weiterhin schreiben:

  banksel  LATB
  bcf  STROM
  banksel  .0

Danke für die Anregung, Andreas, die letztendlich zum Ziel geführt hat!

von Bernd M. (berndmm)


Lesenswert?

Das mit dem Komma ist schon richtig. Aus
banksel STROM
macht der Präprozessor
banksel LATB,7
und dieses Komma sieht jetzt der Assembler und kann damit nichts 
anfangen.

Bernd

von Jens M. (schuchkleisser)


Lesenswert?

Du musst das Teilen.
#define StromPort LATB
#define StromPin 7

Dann klappt
1
banksel StromPort
2
bcf StromPort,StromPin

Vorteil ist dabei das du beliebig Port und Pin ändern kannst und Banksel 
trotzdem stimmt.
Bei deiner Methode ist Strom und Banksel entkoppelt, und wenn du mal was 
änderst oder einen Codeteil woanders nochmal benutzen willst knallts, 
weil du oben das define geändert hast, aber nicht dran gedacht das hier 
und da ein banksel auch angepasst werden muss.

: Bearbeitet durch User
von Michael B. (auchduliebergott)


Lesenswert?

Hallo Bernd,

herzlichen Dank für Deine Hilfe!
Hierdurch ist jetzt klar, woher das Komma und die Fehlermeldung kommt.
Das war mir bislang nicht klar!

Michael

von Michael B. (auchduliebergott)


Lesenswert?

Hallo Jens,

das ist ja toll!
Es gibt also doch eine Lösung, wie ich sie am liebsten hätte!
Darauf wäre ich allerdings nie alleine gekommen! Hierzu fehlt mir 
mindestens die Erfahrung...
Das werde ich gleich einmal ausprobieren, denn genau nach dem Ändern des 
Portes gab es Schwierigkeiten, wie Du sie erklärt hast!
Wunderbar und vielen Dank für Deine Mühe!

Michael

von Peter D. (peda)


Lesenswert?

Probier mal das hier:
1
#define xbanksel(x,y) banksel x
2
3
#define  STROM  LATB,7
4
5
  xbanksel  STROM
6
  bcf  STROM
7
  banksel  .0

von Michael B. (auchduliebergott)


Lesenswert?

Hallo Peter,

ich kann das gerade nicht ausprobieren, aber dennoch die Fragen:

"xbanksel(x,y)" ist scheinbar selbst definiert.

Was bedeutet "(x,y)"?
Ist "x" Platzhalter für "LATB"?
Ist "y" Platzhalter für die "7"?
Bei "Banksel x" ist dann "x" Platzhalter für "LATB"?

Was mir sehr gut gefällt, ist, dass man dann nur noch mit dem Label 
"STROM" arbeitet.
Die ganze Lösung ist jedenfalls - wenn sie funktioniert - äußerst 
raffiniert und ich frage mich, was ich tun soll, um solche Lösungen 
künftig selbst zu finden!
Herzlichen Dank für Deine Mühe und für die Idee!

Michael

von Daniel A. (daniel-a)


Lesenswert?

Falls das der C Präprozessor ist, müsste das nicht eher so aussehen:
1
#define xbanksel(x) xbanksel_eval(x)
2
#define xbanksel_eval(x,y) banksel x
3
#define  STROM  LATB,7
4
  xbanksel(STROM)
5
  bcf  STROM
6
  banksel  .0

(das xbanksel_eval, weil "STROM" erst dort aufgelöst wird, und klammern 
bei xbanksel(STROM), weil sonst macht das doch gar nichts).
1
$ gcc -P - -E <<EOF
2
#define xbanksel(x) xbanksel_eval(x)
3
#define xbanksel_eval(x,y) banksel x
4
#define  STROM  LATB,7
5
  xbanksel(STROM)
6
  bcf  STROM
7
  banksel  .0
8
EOF
1
  banksel LATB
2
  bcf LATB,7
3
  banksel .0

von Michael B. (auchduliebergott)


Lesenswert?

Hallo Daniel,

es handelt sich um MPLAB X-IDE, Assembler für PIC16F1512, also nicht um 
den C-Präprozessor!

Michael

von Daniel A. (daniel-a)


Lesenswert?

Das ist nicht unbedingt ein entweder oder...

https://ww1.microchip.com/downloads/en/DeviceDoc/MPLAB%20XC8%20PIC%20Assembler%20User%27s%20Guide%2050002974A.pdf
> 5. Assembler Features
> The PIC Assembler provided access to a **C preprocessor** and many predefined
> psects and identifiers that you can use in your programs.

von Michael B. (auchduliebergott)


Lesenswert?

Hallo Daniel,

danke für den Hinweis. Ich muss aber gestehen, dass dies doch über mein 
Verständnis weit hinaus geht.
Kannst Du mir vielleicht erklären, was die folgenden beiden Zeilen 
bedeuten?

   #define xbanksel(x,y) banksel x
   #define  STROM  LATB,7

Ist es so, dass "x" ein Platzhalter für "LATB" ist und "y" für "7"?

Michael

von Daniel A. (daniel-a)


Lesenswert?

Michael B. schrieb:
> #define xbanksel(x,y) banksel x
>    #define  STROM  LATB,7
>
> Ist es so, dass "x" ein Platzhalter für "LATB" ist und "y" für "7"?

`#define` definiert ein Macro. Macros ersetzen Text. Wenn also irgend wo 
im Dokument `STROM` vorkommt, wird es durch `LATB,7` ersetzt. Kommt 
irgend wo `xbanksel(hello, world)` vor, wird es durch `banksel hello` 
ersetzt (ja, x und y sind dort Platzhalter die wiederum ersetzt werden).

Bei `xbanksel(STROM)` verhält es sich so, dass zuerst `xbanksel()` mit 
Parameter `STROM` ersetzt wird, und nicht zuerst `STROM` vor `xbanksel`. 
Bei der Definition oben ist das ein Argument zu wenig. Falls der 
Präprozessor es trotzdem zulässt, wird es mit `banksel LATB,7` ersetzt 
werden, (Parameter `x` ist `STROM` und wird mit `LATB,7` ersetzt).

Bei meinem Macro:
1
#define xbanksel(x) xbanksel_eval(x)
2
#define xbanksel_eval(x,y) banksel x

passiert in dem fall aber folgendes. `xbanksel(STROM)` wird zu 
`xbanksel_eval(LATB,7)` wird zu `banksel LATB,7`. Parameter x von 
xbanksel war wieder `STROM`, wurde aber durch `LATB,7` ersetzt, bevor 
`xbanksel_eval()` ausgewertet wurde, dort wurde dann also effektiv 
`xbanksel_eval(LATB,7)` ersetzt, mit Parameter `x` als `LATB` und `y` 
als `7`.

Das ganze funktioniert so hauptsächlich aus historischen gründen. Hatte 
sich damals wohl einfach so ergeben.

Und zum schluss noch, bei:
> xbanksel  STROM

Da ja xbanksel() und nicht xbanksel definiert wurde, sollte das 
eigentlich nicht ersetzt werden, aber ich weiss nicht, ob alle 
Präprozessoren das gleich behandeln. `STROM` würde aber trotzdem mit 
`LATB,7` ersetzt.

PS: Es gibt da noch weitere Eigenheiten, und Tricks, wann was wie 
ersetzt wird. Muss man einfach wissen.

: Bearbeitet durch User
von Michael B. (auchduliebergott)


Lesenswert?

Hallo Daniel,

herzlichen Dank für Deine ausführliche Erklärung und für die Zeit, die 
Du Dir genommen hast!
Das ist ja ausgesprochen trickreich und Deine Bemerkung, dass das wohl 
aus "historischen Gründen" funktioniert, finde ich interessant.
Gibt es eigentlich eine Textstelle, die man nachlesen könnte, um sich in 
diese Technik einzulesen?

Als Hobbyist, habe ich einmal nachgezählt, an wieviel Stellen meines 
Programmes ein relozierbarer Code nützlich wäre.
Ich zähle nur 10 Stellen, die man natürlich auch so beherrschen kann.
Außerdem ist es so, dass ich nur einmal den Controller / die Verdrahtung 
gewechselt habe. In der Folgezeit wird erst mal keine weitere Änderung 
stattfinden.
Aber darum geht es ja nicht, sondern ich vermute, dass man mit dieser 
Technik noch ganz andere Sachen lösen könnte.
Die Arbeit mit Macros erscheint mir an dieser Stelle ausgesprochen 
kompliziert und man muss schon Routine haben, sich darin fehlerfrei 
auszukennen.

Dennoch würde ich gerne hierüber etwas mehr erfahren und deshalb die 
Frage nach Textdokumenten, die zum Thema relozierbarer Code / Macros 
etwas aussagen.

Michael

von Jens M. (schuchkleisser)


Lesenswert?

Daniel A. schrieb:
> Das ganze funktioniert so hauptsächlich aus historischen gründen. Hatte
> sich damals wohl einfach so ergeben.

Das find ich interessant.
Ich progge PICs schon seit 30 Jahren in Asm, aber den kannte ich noch 
nicht.
1
#define xbanksel(x,y) banksel x
2
3
#define STROM PORTA,7
4
#define WASSER TRISA,2
5
#define GAS BORCON,5
6
7
xbanksel(STROM)
8
bcf STROM
9
xbanksel(WASSER)
10
bsf WASSER
11
xbanksel(GAS)
12
bcf GAS
funzt bei mir in MPLAB 8.92 mit MPASM5.51 und einem ASM-Projekt für 
einen PIC16F1516. Nicht wegen der Namen und Register meckern, ich hab da 
nur schräge Werte reingekloppt damit ich das im Disasm erkenne.
Die Version mit dem eval dagegen wirft Fehler.

von Daniel A. (daniel-a)


Lesenswert?

Jens M. schrieb:
> Ich progge PICs schon seit 30 Jahren in Asm, aber den kannte ich noch
> nicht.

Ich habe jetzt nochmal im C Standard nachgesehen, was der dazu sagt. Ich 
kannte es bisher nur so wie es gcc und clang machen, aber es scheint 
nicht explizit definiert zu sein.

Zuerst dachte ich, es wäre in 
https://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf Abschnitt 
6.10.3 Paragraph 11, letzter Satz, beschrieben, aber dort ging es um 
Sachen wie `MY_MACRO(#define Y\n)`. Dazu, in welcher Reihenfolge die 2 
Typen von makros ersetzt werden, scheint nichts zu stehen...

Eventuell muss ich solche Sachen mal aus meinen Programmen raus nehmen. 
Dass es schon im Preprozessor UB drin haben könnte, auf die Idee bin ich 
vorher noch gar nie gekommen...

: Bearbeitet durch User
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.