Forum: Mikrocontroller und Digitale Elektronik "Syntaxbefehl" erstellen


von Hans Gruber (Gast)


Lesenswert?

Griaß eich,

Ich sags im vorraus ich kenn mich zu diesem Thema nicht besonders aus.

Ich möchte gerne, rein nur weil es mich interessiert, einen "Befehl" 
schreiben um mir unnötige Arbeit zu sparen.

Gleich ein Beispiel:

Beim ATmega gibt es den befehl "sbit" nicht, sondern man muss sich das 
jeweilige Bit maskieren.
Jetzt hab ich mir gedacht man könnte ja einen Befehl schreiben der einem 
diese Arbeit abnimmt.

d.h.: man schreibt im Programm    sbit variable = (PORTxy, PINnr);
und der compiler erkennt das sbit variable das PORTxy ist mit einer 
Maske die der PINnr entspricht das man das richtige Bit auf der Variable 
hat.

Muss man dazu jetzt Assembler-Programmieren können, oder muss man das 
nur in eine #include Datein einfügen...ich hab wirklich keine Ahnung.


Leider ist das sehr schlecht erklärt, aber ich weiß nicht wie ich mich 
ausdrücken soll. Wenn ihr es nicht versteht ist es auch nicht schlimm 
weil es wie gesagt nur eine Interesse von mir ist.


Danke
LG
Hans

von Karl H. (kbuchegg)


Lesenswert?

Hans Gruber schrieb:

> Ich möchte gerne, rein nur weil es mich interessiert, einen "Befehl"
> schreiben um mir unnötige Arbeit zu sparen.

In C?

> Muss man dazu jetzt Assembler-Programmieren können, oder muss man das
> nur in eine #include Datein einfügen...ich hab wirklich keine Ahnung.

Du kannst nicht einfach ein neues Schlüsselwort in den Compiler 
einfügen.
Was du machen kannst: du kannst dir entsprechende Makros machen, die dir 
eine alternative Schreibweise ermöglichen. Letzten Endes läuft es aber 
immer darauf hinaus, das du wissen musst, wie man das in reinem C 
schreiben würde.

> Leider ist das sehr schlecht erklärt,

es ist ganz einfach.
Erst mal musst du wissen, wie sich das in C #ohne# dein Makro schreiben 
würde.

um Bit 4 am Port C auf 1 zu setzen würdest du schreiben

     PORTC |= ( 1 << 4 );

so.
was davon ist jetzt variable und was ist konstant?
der Port Name ist offensichtlich variabel und auch die Bitnummer. 
Allgemein würde man also schreiben können

     port |= ( 1 << bit );

gut.
Nachdem feststeht, was in C Form rauskommen muss, überlegt man sich, wie 
man es stattdessen schreiben möchte

     SBIT( port, bit );

auch gut. d.h. der Text

     SBIT( port, bit )

muss durch den Text

     port |= ( 1 << bit )

ersetzt werden, wobei die 'unbekannten' Dinge port und bit einfach 
übernommen werden können.

Also muss dein Makro so aussehen

#define SBIT( port, bit )    port |= ( 1 << bit )


schreibst du dann im C-Programm

    SBIT( PORTD, 6 )

dann ersetzt der Präprozessor diesen Text anhand des #define durch

    PORTD |= ( 1 << 6 )

und du hast eine dir genehme Schreibweise in deinem C-Programm 
eingeführt.

Das ganze kann man jetzt natürlich auch noch wesentlich weiter treiben. 
Mit Strukturen und Bitfeldern lässt sich da noch einiges machen, aber 
fürs erste sei das mal so genug.

Und kauf dir ein C-Buch!

von Jim M. (turboj)


Lesenswert?

> Beim ATmega gibt es den befehl "sbit" nicht

Das ist eine Erweiterung, die ich bisher nur für 8051ger gesehen habe. 
Und auch da nur für den Speicher, der einzelne Bits addressieren kann.

> der compiler erkennt das sbit variable

Dann müsstest Du den Compiler modifiziern. Schau Dir mal die Sourcen vom 
AVR-GCC an, die sind öffentlich verfügbar da open source. C- Makros 
reichen da nicht ohne weiteres.


Aber: Will man eigentlich auch nicht. Viel besser ist sowas:
1
#define LED_ROT_PIN  1
2
#define LED_ROT_PORT PORTA
3
#define LED_ROT_AN   do { LED_ROT_PORT &= ~(1<<LED_ROT_PIN); } while (0)
4
#define LED_ROT_AUS  do { LED_ROT_PORT |= (1<<LED_ROT_PIN); } while (0)
5
6
while (1) {
7
  LED_ROT_AN;
8
  delay(250);
9
  LED_ROT_AUS;
10
  delay(250);
11
}

von Markus (Gast)


Lesenswert?

Jim Meba schrieb:
> #define LED_ROT_AN   do { LED_ROT_PORT &= ~(1<<LED_ROT_PIN); } while (0)
> #define LED_ROT_AUS  do { LED_ROT_PORT |= (1<<LED_ROT_PIN); } while (0

Was sollen die do ... while?

von Hans Gruber (Gast)


Lesenswert?

@ Karl Heinz Buchegger:

Vielen Danke für die rasche Antwort. UNd im Prinzip ist das eig genau 
das was ich will.
Kann man dies jetzt vl noch in eine #include Datei einbauen, dass man 
dieses Makro nicht immer bei jedem Programm dazuschreiben muss?


LG
Hans

von lager (Gast)


Lesenswert?

ja

von Peter D. (peda)


Lesenswert?


von Hans Gruber (Gast)


Lesenswert?

und wie, lieber herr lager? ;-)


LG
Hans

von lager (Gast)


Lesenswert?

Eine neue Datei erzeugen. Zum Beispiel makro.h
Dort die Makros reinkopieren und in deinem Hauptprogramm dann schreiben:
#include "makro.h"

von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

Hier noch die sbit.h

Peter

von Lukas T. (tapy)


Lesenswert?

Noch ein nachgeschobener Grund, warum so etwas gar nicht gehen soll:
Wenn sich jeder so seine "Sprache" zusammenbastelt, sind alle Vorteile 
der Hochsprache wieder weg, da diese gerade den Vorteil leicht zu 
merkender und halbwegs universeller Schlüsselworte hat.

von Hans Gruber (Gast)


Lesenswert?

Lukas T. schrieb:
> Noch ein nachgeschobener Grund, warum so etwas gar nicht gehen soll:
> Wenn sich jeder so seine "Sprache" zusammenbastelt, sind alle Vorteile
> der Hochsprache wieder weg, da diese gerade den Vorteil leicht zu
> merkender und halbwegs universeller Schlüsselworte hat.

Macht Sinn, danke.







Peter Dannegger schrieb:
> Hier noch die sbit.h
>
> Peter

Wenn du mir diesen Teil jetzt noch kurz erklären könntest wärs göttlich 
von dir. :-)




#include <avr/io.h>

//                      Access bits like variables:
struct bits {
  uint8_t b0:1, b1:1, b2:1, b3:1, b4:1, b5:1, b6:1, b7:1;
} __attribute__((_packed_));
#define SBIT_(port,pin) ((*(volatile struct bits*)&port).b##pin)
#define SBIT(x,y)       SBIT_(x,y)

#ifdef PORTA

#define  PORT_A0    SBIT( PORTA, 0 )
#define  PORT_A1    SBIT( PORTA, 1 )
#define  PORT_A2    SBIT( PORTA, 2 )
#define  PORT_A3    SBIT( PORTA, 3 )
#define  PORT_A4    SBIT( PORTA, 4 )
#define  PORT_A5    SBIT( PORTA, 5 )
#define  PORT_A6    SBIT( PORTA, 6 )
#define  PORT_A7    SBIT( PORTA, 7 )

#define  DDR_A0    SBIT( DDRA, 0 )
#define  DDR_A1    SBIT( DDRA, 1 )
#define  DDR_A2    SBIT( DDRA, 2 )
#define  DDR_A3    SBIT( DDRA, 3 )
#define  DDR_A4    SBIT( DDRA, 4 )
#define  DDR_A5    SBIT( DDRA, 5 )
#define  DDR_A6    SBIT( DDRA, 6 )
#define  DDR_A7    SBIT( DDRA, 7 )

#define  PIN_A0    SBIT( PINA, 0 )
#define  PIN_A1    SBIT( PINA, 1 )
#define  PIN_A2    SBIT( PINA, 2 )
#define  PIN_A3    SBIT( PINA, 3 )
#define  PIN_A4    SBIT( PINA, 4 )
#define  PIN_A5    SBIT( PINA, 5 )
#define  PIN_A6    SBIT( PINA, 6 )
#define  PIN_A7    SBIT( PINA, 7 )

#endif

von Klaus W. (mfgkw)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Und kauf dir ein C-Buch!

Schon gemacht? Das wäre toll von DIR! (Hans Gruber, nicht KHB)

von Klaus W. (mfgkw)


Lesenswert?

Markus schrieb:
> Jim Meba schrieb:
>> #define LED_ROT_AN   do { LED_ROT_PORT &= ~(1<<LED_ROT_PIN); } while (0)
>> #define LED_ROT_AUS  do { LED_ROT_PORT |= (1<<LED_ROT_PIN); } while (0
>
> Was sollen die do ... while?

Das hatten wir schon mindestens einmal.
Es bewirkt letztlich, daß die ganze Ersetzung immer als eine Anweisung 
erscheint, egal ob mit oder ohne geschweifte Klammern drumrum.
 -> Suchfunktion

von Klaus W. (mfgkw)


Lesenswert?


von R. M. (rmax)


Lesenswert?

Peter Dannegger schrieb:
> Hier noch die sbit.h

Gibt es einen bestimmten Grund für diese Indirektion?
1
#define SBIT(x,y)       SBIT_(x,y)

von Klaus W. (mfgkw)


Lesenswert?

ja

von Klaus W. (mfgkw)


Lesenswert?

PS: Weil sonst das ## nicht funktioniert

von lager (Gast)


Lesenswert?

Interessant, dass in fast jedem C-Thread immer ein "Kauf Dir ein C-Buch" 
auftaucht.
Bei Java, PHP, Elektronik, AVR, VHDL ... ist das nie so.

von R. M. (rmax)


Lesenswert?

Klaus Wachtler schrieb:
> PS: Weil sonst das ## nicht funktioniert

Habs eben getestet und bekomme vom Präprozessor den gleichen Output, 
egal ob ich SBIT oder SBIT_ verwende (gcc 4.6.2).

von Klaus W. (mfgkw)


Lesenswert?

lager schrieb:
> Interessant, dass in fast jedem C-Thread immer ein "Kauf Dir ein C-Buch"
> auftaucht.

Weiß nicht, ob da anderes Publikum unterwegs ist.
Aber was soll es, hier jeden Tag erneut den K&R abzuschreiben, nur weil 
manche nicht selber nachschlagen wollen?

Der OT hier hat 0 Ahnung von C, und mit jeder Erklärung tun sich bei ihm 
neue Lücken auf.
Wieso soll er nicht erstmal selber etwas lesen?

Wenn er nicht weiß, wie man ein Makro in einer Headerdatei bekommt, hat 
er halt noch nicht viel aktiv gelernt.
Ist in Ordnung, seine Sache.
Aber weisst du, wieviele Leute C lernen wollen oder müssen?
Soll man denen jede Trivialität einzeln vorkauen, nur damit sie kein 
Buch aufschlagen müssen?

Bei AVR kommt übrigens (oft zu Recht) der heiße Tip, mal das 
AVR-Tutorial zu lesen.
Das beantwortet 95% der Fragen zu dem Thema, und ist genau dafür da, daß 
nicht jeder einzeln mit dem Löffel gefüttert werden muß.

von Klaus W. (mfgkw)


Lesenswert?

R. Max schrieb:
> Klaus Wachtler schrieb:
>> PS: Weil sonst das ## nicht funktioniert
>
> Habs eben getestet und bekomme vom Präprozessor den gleichen Output,
> egal ob ich SBIT oder SBIT_ verwende (gcc 4.6.2).

Mag sein, daß es nicht mit allen Compilern nötig ist (ggf. nur bei 
älteren).
Ich kann mich dunkel erinnern, daß ich so eine Konstruktion vor ein paar 
Jahren auch brauchte. Vielleicht hat es sich erledigt.

von Peter D. (peda)


Lesenswert?

Hans Gruber schrieb:
> Wenn du mir diesen Teil jetzt noch kurz erklären könntest wärs göttlich
> von dir. :-)

http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=67368&start=all

Peter

von Yalu X. (yalu) (Moderator)


Lesenswert?

Hans Gruber schrieb:
> Wenn du mir diesen Teil jetzt noch kurz erklären könntest wärs göttlich
> von dir. :-)

Hier kannst du übrigens die Entstehungsgeschichte der von Peter
geposteten Methode nachlesen:

Byte als Bitfelder darstellen:

  Beitrag "attribute packed"

Mappen dieser Darstellung auf ein I/O-Register:

  Beitrag "Re: #define in C"
  Beitrag "Re: sbit macro für avr-gcc"

Und schließlich noch ein Convenience-Makro drumherum:

  Beitrag "Re: sbit macro für avr-gcc"

R. Max schrieb:
> Gibt es einen bestimmten Grund für diese Indirektion?
> #define SBIT(x,y)       SBIT_(x,y)

Ja. Wenn du dem SBIT-Makro als zweites Argument keine Zahl, sondern ein
weiteres Makro übergibst, also z.B.
1
#define TIMSK_TOIE0  SBIT(TIMSK, TOIE0)

dann funktioniert die korrekte Expansion nur mit dem Zwischenschritt
über SBIT_(). Das hängt mit der Reihenfolge zusammen, in der der
C-Präprozessor Makroargumente expandiert.

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.