Hallo zusammen, ich habe eine kleine Datei auf GitHub geworfen, die möglicherweise bei kleinen und schnellen Projekten helfen kann. Da ich auch von Verbesserungen profitieren kann, nehme ich Anregungen und Korrekturen gerne entgegen. Im Prinzip habe ich mir nur eine Header Datei gebaut, mit der ich extrem schnell und einfach auf Port und Pin Register zugreifen kann und ich deren Belegung per definements ändern kann. Gruß Björn https://github.com/BjWe/avr-minitools https://github.com/BjWe/avr-minitools/blob/master/EasyIO.h Beispiel: global.h ... #define SWITCH1 B,3 // (Für PORTB 3) ... main.c ... SETPIN(SWITCH1); // Als PIN definieren SETON(SWITCH1); // Pullups an if(ISNSET(SWITCH1)){ ... } ...
Schöne kleine Makro-Sammlung. Gefällt mir gut, werde das mal im nächsten Projekt mit einbauen. Danke fürs teilen.
Es ist zwar nicht immer gut zusätzliche Abstraktionsschichten einzubauen, aber das gefällt mir wirklich gut. Herzlichen Dank für's veröffentlichen.
@Andreas Pantle Was ist an defines jetzt eine zusätzliche Abstraktionsschicht? Das wird einfach vom Precompiler als C Code eingesetzt als hätt mans selber an die entsprechende Stelle getippt.
Naja, wie abstrahiert wird tut nichts zur Sache (Funktionen, #defines). Ein SetPin(PORTB, 0) ist einfacher als PORTD |= (1<<PB0). Aber ob das schon als "abstrahiert" oder nur umbenannt gilt, ist die Frage. Einfach wie bei Arduino. Alle freien Pins in einen "virtuellen Port" packen, drei Funktionen drumherum und keiner muss mehr denken.
Hmm - nochmals zum klarstellen: Ich finde den Code Klasse und spiele auch damit herum. Wie auch immer, für mich ist es eben so, auch über Defines und gerade da weil es u.U. nicht immer klar ist was da nun passiert. Übersichtlicher ist es für mich wenn ich den Code vor mir habe und nicht derjenige der nachher übersetzt wird.
Nils S. schrieb: > Einfach wie bei Arduino. Alle freien Pins in einen "virtuellen Port" > packen, drei Funktionen drumherum und keiner muss mehr denken. Hmm, das liest sich sehr abwertend. Ich zielte damit auf viel zu aufgeblasene Abstraktion im Allgemeinen ab und nicht auf irgend Etwas hier.
Nils S. schrieb: > Hmm, das liest sich sehr abwertend. Ich zielte damit auf viel zu > aufgeblasene Abstraktion im Allgemeinen ab und nicht auf irgend Etwas > hier. Hätte ich jetzt auch nicht so aufgefasst :) Bei Arduino kann ich es ebenfalls nachvollziehen. Wenn alle I/O's nochmal durch eine extra Lib gepeitscht wird, dauert es eben ein paar Takte mehr. Wenn der Compiler sauber arbeitet, müsste meine Makro-Sammlung direkt optimiert werden können, dass z.B. aus 2xSETON (auf dem gleichen Port) nur eine Anweisung wird. Gruß Björn
Björn W. schrieb: > Wenn der Compiler sauber arbeitet, müsste meine Makro-Sammlung direkt > optimiert werden können, dass z.B. aus 2xSETON (auf dem gleichen Port) > nur eine Anweisung wird. Darf er nicht, weil die Register volatile sind. Dein
1 | #define SETON(ex) DPORT_(ex) |= (1<<DBIT_(ex));
|
2 | |
3 | SETON(A,4) |
4 | SETON(A,5) |
löst ja letzten Endes auf zu
1 | PORTA |= (1 << 4); |
2 | PORTA |= (1 << 4); |
und das ist (je nach AVR ne andere Addresse)
1 | *((volatile uint8_t*)(0xAA + 0x20)) |= (1 << 4); |
2 | *((volatile uint8_t*)(0xAA + 0x20)) |= (1 << 5); |
Tja, da ist ja das volatile. Also muss der Compiler 2 mal schreiben, was dann entweder zu zwei sbi's führt oder zu 2x lds-ori-sts Aber daran hat deine Makro-Sammlung nicht die geringste Schuld, das wäre ohne sie exakt genau so. Ich finde sie jetzt auch nicht schlecht, aber ich zweifle den Nutzen in einem größeren Projekt an. Weil spätestens dort spielen die GPIOs ja nicht mehr eine so große Rolle und sollten sowieso von einer/mehreren Funktionen mit aussagekräftigen Namen gekapselt werden. Nebenbei: ich finde es persönlich schlecht, wenn an einem Makro ein Semikolon hinten dran steht, das kann zu sehr komischem verhalten führen, z.B. bei if-Abfragen. Deswegen würde ich auch diese Einzeiler umklammern mit do{...}while(0) . Dann setzt nämlich der Nutzer später das Semikolon
N. G. schrieb: > Nebenbei: > ich finde es persönlich schlecht, wenn an einem Makro ein Semikolon > hinten dran steht, das kann zu sehr komischem verhalten führen, z.B. bei > if-Abfragen. Oh ja. Ist mir beim überfliegen nicht aufgefallen. Das mag ich auch nicht. :-) Bei großen Projekten sollte man Makros nur gezielt einsetzen. Sonst kann es unübersichtlich werden und jemand anders, oder bei Hobbyfricklern eher wahrscheinlich, man selber nach paar Monaten steigt nicht mehr durch.
Noch kleiner Hinweis: TOGGLE funktioniert natürlich nicht auf den schon etwas betagteren AVRs, die aber häufig auch von Anfängern benutzt werden (Z.B. ATmega8/16/32). Ob die dann verstehen warum nicht, oder einfach das Zeug in die Ecke werfen?
Mw E. schrieb: > Was ist an defines jetzt eine zusätzliche Abstraktionsschicht? Wenn ich PORTB meine und B schreibe, dann ist das eine Form von Abstraktion. Mir erschließt sich der Nutzen nicht. Je nach Schreibweise der Bit-Manipulationen und Compiler-Laune werden das sehr unterschiedliche Maschineninstruktionen. Das Makro verschleiert das u.U. und es macht inline-Assembler o.ä. nicht überflüssig. Software-Entwicklung damit einfacher zu machen ist eine Illusion. Der Begriff dahinter heißt leaky abstraction.
Carl D. schrieb: > Noch kleiner Hinweis: TOGGLE funktioniert natürlich nicht auf den > schon etwas betagteren AVRs, die aber häufig auch von Anfängern benutzt > werden (Z.B. ATmega8/16/32). Ob die dann verstehen warum nicht, oder > einfach das Zeug in die Ecke werfen? Könntest du erklären warum das TOGGLE Makro bei älteren AVRs nicht funktioniert?
Ganz einfach: weil die Hardware es nicht kann. Toggle per Write auf PIN-Register wurde erst später eingeführt. Arduino-Benutzer haben da Glück, wer aber lieber einen Mega8 auf sein Steckbrett packt, der muß nicht nur mit Kondensatoren an der Versorgung kämpfen, was manchmal schwer scheint, sondern hat dann auch noch eine Library, die ihm Rätsel auf gibt.
Ach ja, da war was. Ich hatte da jetzt irgendeine Feinheit in den Makros und dem jeweiligen Prozessor-Befehlssatz vermutet.
Aber das PIN Write wird im Macro des TE gar nicht benutzt! #define TOGGLE(ex) DPORT_(ex) ^= (1<<DBIT_(ex)); Somit ist der Hinweis von Carl Drexler gegenstandslos - trotzdem gut von ihm, daran zu denken. Grüße, egberto
Was macht eigentlich die Doppelraute ##? Die taucht in meiner C Referenz gar nicht auf. Hab ich so noch nie gesehen. Hat da jemand vielleicht einen weiterführenden Link wie: https://de.wikibooks.org/wiki/C-Programmierung:_Ausdr%C3%BCcke_und_Operatore
Ich hab das mal für dich gegoogled ;-) http://www.cprogramming.com/tutorial/cpreprocessor.html Unter advanced, pasting tokens...... Grüße, egberto
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.