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
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!
> 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 | }
|
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?
@ 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
Ja, mit meiner sbit.h: http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&p=835728#835728 Peter
Eine neue Datei erzeugen. Zum Beispiel makro.h Dort die Makros reinkopieren und in deinem Hauptprogramm dann schreiben: #include "makro.h"
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.
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
Karl Heinz Buchegger schrieb: > Und kauf dir ein C-Buch! Schon gemacht? Das wäre toll von DIR! (Hans Gruber, nicht KHB)
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
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) |
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.
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).
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ß.
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.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.