Vorstellung EasyIO.h

OP #4615154
Lesenswert?

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)){
  ...
}
...
#4620553
Lesenswert?

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.
OP #4622928
Lesenswert?

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
Persönliche Seite #4623033
Lesenswert?

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
Gast #4623999
Lesenswert?

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.
Persönliche Seite #4624196
Lesenswert?

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.
Gast #4628282
Lesenswert?

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?
#4628292
Lesenswert?

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.
Gast #4628332
Lesenswert?

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren