... hier mal Beispiele in C, wie mit dem VPort der neueren AVR's
umgegangen werden kann. Der Vorteil es werden bit-manipulation
instructions verwendet z.b. sbi/cbi.
Die Makros garantieren die lowest Code Size und highest Speed, weil
diese dedicated toggle/clear/set registers und bit-accessible I/O memory
space registers (virtual ports) nutzen.
//fast digital read/write
typedef struct {
uint8_t p0:1, p1:1, p2:1, p3:1, p4:1, p5:1, p6:1, p7:1;} pin_t;
#define pinModeFast(b,v) _PORTA_DIR(b,v)
#define _PORTA_DIR(b,v) ((pin_t*) &VPORTA.DIR)->p##b=v
#define digitalWriteFast(b,v) _PORTA_OUT(b,v)
#define _PORTA_OUT(b,v) ((pin_t*) &VPORTA.OUT)->p##b=v
#define digitalReadFast(b) _PORTA_IN(b)
#define _PORTA_IN(b) ((pin_t*) &VPORTA.DIR)->p##b
#define clearPortIntFlag(b) _PORTA_INTFLAGS(b)
#define _PORTA_INTFLAGS(b) ((pin_t*) &VPORTA.INTFLAGS)->p##b=1
Für Power Reduction im Sleep Mode, wenn möglich analog Input wählen,
hier also digital Input und den digital Input Buffer und Pull-up
disabled setzen.
//digital input buffer on/off, p = attiny port pin number
#define DINPUT_ON(p) _DINPUT_ON(p)
#define _DINPUT_ON(p) PORTA_PIN##p##CTRL &= ~PORT_ISC_INPUT_DISABLE_gc
#define DINPUT_OFF(p) _DINPUT_OFF(p)
#define _DINPUT_OFF(p) PORTA_PIN##p##CTRL |= PORT_ISC_INPUT_DISABLE_gc
//digital input pull-up on/off, p = attiny port pin number
#define PULLUP_ON(p) _PULLUP_ON(p)
#define _PULLUP_ON(p) PORTA_PIN##p##CTRL |= PORT_PULLUPEN_bm
#define PULLUP_OFF(p) _PULLUP_OFF(p)
#define _PULLUP_OFF(p) PORTA_PIN##p##CTRL &= ~PORT_PULLUPEN_bm
... die Macros sind für PortA/ATtiny412,814,1614,1616,3216 und lassen
sich leicht umbauen mit einen weiteren Parameter, damit diese für
beliebe Port Adressen auch gelten.
Snafu schrieb:> Der Vorteil es werden bit-manipulation> instructions verwendet z.b. sbi/cbi.
Dazu braucht man aber keine Macros.
Man kann es einfach weiterhin so machen, wie bei den klassischen AVRs.
Der einzige Unterschied ist nur der Zugriff über ein struct, statt über
verschiedene Namen.
klassisch:
Peter D. schrieb:> Dazu braucht man aber keine Macros.
... das scheint mir nicht ganz richtig, weil
die jetzt umgeschriebenen Macros als Funktionsaufruf für alle Ports
gelten
UND set/clear die gleiche Funktion sind!
Du müsstest unterscheiden zwischen set/clear ... und alles "hart"
codieren.
Oder habe ich deinen Einwand nur halb verstanden, dann zeige doch mal
wie du das meisterst.
Arduino Fanboy D. schrieb:> Da bevorzuge ich doch meinen Arduino C++ Weg.
Dann zeige mal mehr und lass uns z.b. die Code Size oder die max Pin
Toggle Frequenz vergleichen und auch mal daran denken, dass z.B. ATtiny
nur 4K Flash mitbringt.
Arduino Fanboy D. schrieb:> Davon wird mir schwindelig!
Ich stelle mir vor, dass du auch von 10-20 Minuten Dauerlauf mit Zunge
raus schwindelig rumläufst, oder täusche ich mich?!
Ich habe mir einen kompletten ATtiny Arduino PicoCore neu geschrieben
und die ATtiny HW Resourcen vollständig eingesetzt. Es gibt nichts
Vergleichbares und es war richtig Arbeit!
Ich bin an Ideen interessiert, ABER die Masse hier kann wenig mehr als
nur Sprüche klopfen.
Also zeigt doch mal gute konkrete Ideen hier auf!
Snafu schrieb:> Dann zeige mal mehr und lass uns z.b. die Code Size oder die max Pin> Toggle Frequenz vergleichen und auch mal daran denken, dass z.B. ATtiny> nur 4K Flash mitbringt.
Offensichtlich willst du deine Vorurteile bestätigt sehen.
Snafu schrieb:> Ich stelle mir vor, dass du auch von 10-20 Minuten Dauerlauf mit Zunge> raus schwindelig rumläufst, oder täusche ich mich?!
Und das eingepackt in Beleidigungen und Herabwürdigungen!
> die max Pin Toggle Frequenz
Arduino UNO, also ATMega328p mit 16MHz
Arduino Pin 13 entspricht PORTB5
1
#include<CombiePin.h>
2
3
Combie::Pin::OutputPin<13>pin;
4
5
intmain()
6
{
7
pin.init();
8
for(;;)
9
{
10
pin.toggle();// 2,66667MHz
11
}
12
}
--------
Auszug aus: Disassembly of section .text:
Peter D. schrieb:> Hier mal klassisch und mit meinem SBIT Macro:
"mit meinem SBIT Macro"
Also sind wir wieder bei Macros!?
Der Unterschied zu deinen Macro's und meinen Ansatz scheint mir
maginal. Da ich Arduino kompatibel sein wollte ...
differnzieren/abstrahieren meine höher die Funktion im Gegensatz zu
deinen.
Mir gefällt aber dein "minimalistischer" Ansatz, wenn ohne Arduino Link
gedacht.
"klassisch"
Ja geht immer, aber ugly diese redundante Schreibweise und wenig
flexibel.
Schreib doch mal klassich und vergleiche mit diesen Macro
//r: register, m: bit change mask, v:value
#define wBITM(r,m,v) (r ^= (r^(v))&(m))
Wie das wohl in c++ gehen/aussehen könnte?
Arduino Fanboy D. schrieb:> Und das eingepackt in Beleidigungen und Herabwürdigungen!
So etwas interessiert mich nicht!
Scheint so, ich habe damit auf deinen "Klingelknopf" gedrückt?
Arduino Fanboy D. schrieb:> Davon wird mir schwindelig!
Ist das dein Beispiel von vorurteilsfrei und positiven Denken?
leo schrieb:> Der Name SBIT ist sehr verwirrend.
Für Leute, die den 80C51 programmieren, nicht. Beim Keil C51 ist sbit
ein gültiges Schlüsselwort.
http://www.keil.com/support/man/docs/c51/c51_le_sbit.htm
Mein SBIT ist daran angelehnt. Ich finde die Zuweisung von 0 oder 1 bzw.
Auswertung auf 0 oder 1 gut zu lesen.
Peter D. schrieb:> Beim Keil C51 ist sbit> ein gültiges Schlüsselwort.
Und beim AVR-Assembler ein Opcode zum Bit-Setzen. Da das Macro ja auch
zur Pinabfrage verwendet wird, ist halt "set-bit" verwirrend. Aber ja,
Geschmackssache. Ich bevorzuge direkte Bitmanipulationen. Da sieht man
gleich, was passiert.
leo
Peter D. schrieb:> leo schrieb:>> Und beim AVR-Assembler ein Opcode zum Bit-Setzen.>> Nö, der ist "SBI", bei "SBIT" meckert der Assembler.
Danke, ja - verwirrend ;-)
leo
Peter D. schrieb:> Beim Keil C51
Ich habe mir gerade AT89LP51ED2 (Dallas390 ist dagegen bescheiden) von
Microchip schenken lassen und will da mal Camelforth drauf laufen lassen
oder Intel 52-Basic - irgend wann in ferner Zukunft. Der Hauptgrund ist
aber mein Philips Freq.-zähler, der hat einen 8049 und der soll mal
ersetzt (pin remapping) werden um neue Funktionen (z.b. remote control)
zu ermöglichen.
Ich habe noch rtx51 rumliegen tiny and full version, falls du mal damit
spielen willst.
Hallo,
man muss sich keine extra Makros schreiben oder was das im
Eingangsbeitrag auch immer darstellen soll, wenn das alles fertig
definiert im Header steht. Samt Registerbits und Bitmasken usw. Hier hat
Microchip ganze Arbeit geleistet. Allerdings ist die Auswahl doppelt
vorhanden. Man kann es so oder so schreiben.
PORTF_DIR = PIN5_bm;
PORTF.DIR = PIN5_bm;
Aber wenn du schon die Methoden von MCUdude seiner "Lib" verwendest
digitalWriteFast()
digitalReadFast()
...
Warum dann damit nochmal extra Makros bauen? Macht keinen Sinn. Ich sehe
da jedenfalls keinen.
Im Bsp. von Peter würde ich noch abändern in
1
VPORTA.OUT|=PIN7_bm;
2
VPORTB.OUT&=~PIN6_bm;
Dann ist das noch leichter lesbar und Bit schubsen fällt weg. :-)
anderes Bsp.
1
PORTF.OUTSET=PIN5_bm;
2
PORTF.OUTCLR=PIN5_bm;
3
4
odergleicheFunktionalität
5
6
PORTF_OUTTGL=PIN5_bm;
_gc sind Gruppenbits. gc könnte für "group change" stehen o.ä. Auch so
eine feine vordefinerte Sache. Du willst zum Bsp. einen Prescaler
ändern, verwendest den Namen vom vordefinierten Prescaler und fertig.
Man muss nicht jedes Bit einzeln setzen für den einen Prescaler den man
möchte. Warum die das allerdings im Header nochmal schieben weiß ich
nicht, vielleicht haben die dafür irgendwelche Softwaretools die das für
verschiedene µC generiert. Weil eigentlich sind _gc auch nur fertige
Bitmasken.
Was mir mal bitte jemand erklären könnte wäre, wann man virtuelle Ports
verwenden sollte und wann nicht?
Snafu schrieb:> Mir gefällt aber dein "minimalistischer" Ansatz, wenn ohne Arduino Link> gedacht.
Ja, ich mag es nicht, wenn ich mir nen Haufen verschiedener Macronamen
merken müßte.
Arduino kam erst lange nachdem ich mit AVRs angefangen habe. Dessen
spezielle Syntax ist mir daher nicht bekannt.
Arduino ist schon etwas eigenes gegenüber herkömmlichen C.
Snafu schrieb:> "klassisch">> Ja geht immer, aber ugly diese redundante Schreibweise und wenig> flexibel.
Dieses klassische |= und &= mit Bitshifts sollte jeder gestandene
C-Programmierer leicht verstehen können. Es sieht nur für den Anfänger
umständlich aus.
Snafu schrieb:> So etwas interessiert mich nicht!
Fehleinschätzungen zugeben, liegt dir wohl nicht....
----------
Peter D. schrieb:> Arduino kam erst lange nachdem ich mit AVRs angefangen habe. Dessen> spezielle Syntax ist mir daher nicht bekannt.> Arduino ist schon etwas eigenes gegenüber herkömmlichen C.
Nöö ...
Abseits der Arduino typischen Framework Funktionen nicht.
Keine spezielle Syntax. C++11 einfach.
OK, die Pinnummerierung ist eine Extrawurst, welche gebacken werden
will, damit man die aufgedruckten Pinnummern im Code auch wiederfindet.
Veit D. schrieb:> Was mir mal bitte jemand erklären könnte wäre, wann man virtuelle Ports> verwenden sollte und wann nicht?Veit D. schrieb:> Warum dann damit nochmal extra Makros bauen? Macht keinen Sinn. Ich sehe> da jedenfalls keinen.
Erst denken hilft oft richtig viel ...
Wenn man nicht verstanden hat für was VPort's gut sind, dann kann man
auch nicht verstehen über was wir hier reden. Du denkt also die Headers
haben wir nicht gelesen? Klippschule/Arduino-Boy lässt wiedermal
grüssen.
Meine Macros z.B. machen den Anwender "frei" von den Details (welche HW
Register sind für was gut ...) der neuen IO-Features und den Header
Definitions. Alle anderen hier genannten Varianten setzen dieses
Detailwissen gerade voraus!
Außerdem gibt es Macros, damit der digital Inputbuffer on/off gehen
kann, was Arduino zu den tinyAVR-1 auch nicht kennt oder verstanden hat.
Gibt ja immer noch den Irrglauben, das digital Input+Pull-up/max 50K die
richtige Wahl für deep sleep wäre ...
_gc = group change, ja so habe ich das auch gesehen, aber der Sinn zu
_bm erschließt sich mir nicht.
Weil damit kein Thread sicherer Group change möglich ist, andere Bits
werden damit tangiert, halt wie bei _bm
Snafu schrieb:> //r: register, m: bit change mask, v:value> #define wBITM(r,m,v) (r ^= (r^(v))&(m)
Dieses Macro ermöglicht Group Change threadsicher, wenn keine
zeitgleiche Überlappung stattfindet, daher ich kann das untere Nippel im
Hauptprogram ändern UND gleichzeitg kann eine ISR das obere Nippel
manipulieren! Sehr praktisch, weil wegen IO-read/write/change muss sonst
atomarer Zugriff mit cli/sei erfolgen.
Und da leuchtet auch schon der Grund für VPorts hervor, sichern atomaren
Zugriff auf IO Port-Bits via Bit-Field Register!
Hallo,
irgendwas stimmt mit dir aber auch nicht. Mir und anderen Vorwürfe
machen mit Denkfehler u.ä. aber selbst nicht den Unterschied erkennen
zwischen _bm und _gc obwohl ich das erläutert habe. Dafür müßte man nun
wirklich nur den Header lesen und ins Datenblatt schauen.
_bp und _bm stehen für einzelne Bits.
_gc steht für eine Gruppe von Bits für eine bestimmte Funktionalität.
Dagegen kommt keine vernünftige Erklärung zu vports. Aber wenn du nicht
willst, lass es, ich bekomme das auch so raus mit der Zeit.
Veit D. schrieb:> Was mir mal bitte jemand erklären könnte wäre, wann man virtuelle Ports> verwenden sollte und wann nicht?
vorlesen tue ich nicht!
16.3.2.3 Virtual Ports
The Virtual PORT registers map the most frequently used regular PORT
registers into the I/O Register space with
single-cycle bit access. Access to the Virtual PORT registers has the
same outcome as access to the regular
registers but allows for memory specific instructions, such as bit
manipulation instructions, which cannot be used in
the extended I/O Register space where the regular PORT registers reside.
(data sheet attiny3216)
Veit D. schrieb:> _bp und _bm stehen für einzelne Bits.> _gc steht für eine Gruppe von Bits für eine bestimmte Funktionalität.
Echt darauf wäre ich nie gekommen!
Veit D. schrieb:> Dagegen kommt keine vernünftige Erklärung zu vports. Aber wenn du nicht> willst, lass es, ich bekomme das auch so raus mit der Zeit.
Ich hoffe mit dir! Ich kann es nicht so simple, wie es hier gebraucht
wird ...
Snafu schrieb:> Veit D. schrieb:>> _bp und _bm stehen für einzelne Bits.>> _gc steht für eine Gruppe von Bits für eine bestimmte Funktionalität.>> Echt darauf wäre ich nie gekommen!
Warum fragst du dann überhaupt? Kopfschüttel.
Veit D. schrieb:> Warum fragst du dann überhaupt? Kopfschüttel.
Schüttel doch einfach noch mehr den Kopf!
Ich lese von dir hier nur bekannte Dinge, das Thema neue Io-Features ist
dir fremd. Vorher darüber nachlesen wolltest du auch nicht, aber
anzunehmen dass ich auch nicht lesen kann, weil du es nicht vollbringst
ist unlogisch.
Hinweise zum Nachdenken lösen bei dir/anderen eher Aggressionen aus,
aber dafür bin ich nicht verantwortlich!
Peter D. schrieb:> 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)
Gedanken dazu:
A)
Das "volatile" ist hier übeflüssig/sinnfrei, weil HW Register Zugriff
...
B)
Das __attribute__((_packed_)), Richtung Portierbarkeit 16/32Bit
Machine ok, aber hier reden wir über eine 8bit Machine und da ist es
dann nur redundant
C)
Die äußere Klammer () ist redundant, hier kann es keine Seiteneffekte
geben
Für mich sind die Klammerorgien die oft in if/else Anweisung praktiziert
werden prinzpiell schmerzhaft, weil die Precedence der
Operatoren/Sprachdefinition verinnerlich und angewendet werden sollte.
Jetzt gibt es bestimmt wieder Schläge von euch Helden?!
Arduino Fanboy D. schrieb:> Widerlicher Typ.
Ganz schön böse für einen selbsternannten Gutmenschen UND auch richtig
ehrverletzend.
Hallo Moderator, Ehrverletzung ist strafbar und sollte hier nicht
erlaubt sein. Ich erwarte, dass das gelöscht wird!
Oder soll ich mal den Absender hinterfragen und Anzeige erstatten, das
wird dann richtig teuer.
@Fanboy D. wiederhole das doch einfach nochmal und teste meine Volition!
Snafu schrieb:> Arduino Fanboy D. schrieb:>> Widerlicher Typ.>> Ganz schön böse für einen selbsternannten Gutmenschen UND auch richtig> ehrverletzend.
LOL.
> Hallo Moderator, Ehrverletzung ist strafbar und sollte hier nicht> erlaubt sein. Ich erwarte, dass das gelöscht wird!
MegaLOL.
> Oder soll ich mal den Absender hinterfragen und Anzeige erstatten, das> wird dann richtig teuer.
Dazu fehlt dir das Rückgrat.
Martin schrieb:> Dazu fehlt dir das Rückgrat.
Mach doch einfach mal die Probe, beschimpfe mich hier öffentlich und
warte was passiert. Ich würde das an deiner Stelle sofort mal
ausprobieren. So teuer wird es bestimmt auch wieder nicht, nur ein paar
Hundert €.
Ich warte!
Hallo,
ich frage mich allmählich wofür der Eingangspost überhaupt dienen
sollte.
Brachte ja nun keine wichtigen Erkenntnisse.
Es gibt eben immer wieder solche und solche anonymen Schreiberlinge.
Austeilen kann jeder. An den Nehmerqualitäten erkennt man das Wesen.
Edit:
jetzt mutiert er noch zum Troll - man sollte ihn nicht mehr füttern
Snafu schrieb:> Martin schrieb:>> Dazu fehlt dir das Rückgrat.>> Mach doch einfach mal die Probe, beschimpfe mich hier öffentlich und> warte was passiert. Ich würde das an deiner Stelle sofort mal> ausprobieren. So teuer wird es bestimmt auch wieder nicht, nur ein paar> Hundert €.>> Ich warte!
Alles leeres Geschwätz von dir, was einfach zu belegen ist.: Du bist -
nach deiner eigenen Einlassung - bereits beleidigt worden (Zitat: "...
Ehrverletzung ist strafbar ...").
Also, werde einfach aktiv. Gibt bestimmt viel zu lachen, wenn du
versuchst deine Ehre zu verteidigen.
Ich wiederhole mich: Du hast einfach nicht das Rückgrat, deine verletzte
Ehre zu schützen.
Martin schrieb:> Ich wiederhole mich: Du hast einfach nicht das Rückgrat, deine verletzte> Ehre zu schützen.
Das reicht mir nicht, du musst erkennbarer mehr gemein/böse sein!
Veit D. schrieb:> Brachte ja nun keine wichtigen Erkenntnisse.
Davon hast du ja schon gesprochen, dass du nicht verstehst worum es hier
geht. Aber du redest ja auch lieber unbekannterweise über andere/mich
oder wiederholst Altbekanntes und gibst gerne anderen Teilnehmern
Ratschläge wie sie sich verhalten sollen, ... halt ein ewig Gestriger.
So ein Ansatz kann nicht konfliktfrei sein, das ist erkennbar das
Verhaltensmuster der entfremdeten Generation 65+.
Snafu schrieb:> Hallo Moderator, Ehrverletzung ist strafbar und sollte hier nicht> erlaubt sein. Ich erwarte, dass das gelöscht wird!
hmmm, schreit nach dem Moderator und möchte weiter beleidigt werden,
Kindergarten große Gruppe
Snafu schrieb:> Martin schrieb:>> Ich wiederhole mich: Du hast einfach nicht das Rückgrat, deine verletzte>> Ehre zu schützen.>> Das reicht mir nicht, du musst erkennbarer mehr gemein/böse sein!
Bist du tatsächlich so dumm, dass du glaubst von mir Handlungsweisen zu
fordern? Hat du über eine Ehre, die es zu verteidigen gilt? Du hast kein
Rückgrat. Nicht einmal die löschfreudige Moderation nimmt dich ernst und
kommt deiner Forderung nach.
kwt
Peter D. schrieb:> LED0 = 1;> bc: 4a 9a sbi 0x09, 2 ; 9> MOTOR_LEFT = 1;> be: 6b 9a sbi 0x0d, 3 ; 13
Setze mal immer den gleichen Port, dann gibt es eine kleine Überraschung
vom Compiler!
Dann werden die zwei Portzugriffe zusammen gelegt und mit in/ori/out
codiert.
Also ein extra Byte Redundance eingefügt.
Prinzipiell kann das natürlich Sinn bei 4 und mehr Portzugriffen machen,
aber nicht bei 2/3.
Und wenn das Sequence Timing der Port set/clear Zugriffe wichtig war,
dann muss man das jetzt berücksichtigen und z.b. ein nop dazwischen
schieben ...
Snafu schrieb:> Dann werden die zwei Portzugriffe zusammen gelegt und mit in/ori/out> codiert.
Falsch.
Es sei denn, man stellt sich blöd an!
Z.B. so wie du:
Snafu schrieb:> A)> Das "volatile" ist hier übeflüssig/sinnfrei, weil HW Register Zugriff
Totalversagen, nenne ich sowas.
Veit D. schrieb:> Aber wenn du schon die Methoden von MCUdude seiner "Lib" verwendest> digitalWriteFast()> digitalReadFast()
Zur Info es gibt keine fast IO-Lib zum tinyAVR-1 und es kann daher auch
keine Methode kopiert worden sein aus dem Nichts, sondern an den
bekannten Funktionsname wurde angelehnt.
Du und einige andere Schwätzer haben hier keinen einzigen brauchbaren
inhaltlichen Beitrag zurückgelassen oder habe ich was übersehen, äh?!
Falls du mal Hilfe brauchst, z.B. wie man ein Oszi bedient und sinniges
Ground Probing anwendet, kann ich dir helfen bis 2GHz RF in meinem Home
Lab mit kompletten Meßzoo, aber ich habe wenig Gedult bei
Mittelmäßigkeit!
Kopiert?
Arduino Fanboy D. schrieb:> Totalversagen, nenne ich sowas.
Das Verständnis zu Sinn/Unsinn bzgl. volatile und Machine HW Register
ist nichts für Arduino Boys!
Hast du dich schon mal gefragt für was die GPIOR bei AVR gut sind, wenn
du diese überhaupt kennst, ich glaube never ever!
Aber erklär doch dann mal deine Denke/Überzeugung warum volatile und HW
Machine Register Sinn macht, aber bedenke Zitronenfalter falten nicht
unbedingt Zitronen!
Snafu schrieb:> Das Verständnis zu Sinn/Unsinn bzgl. volatile und Machine HW Register> ist nichts für Arduino Boys!
In der Tat ich muss zurückrudern, das volatile unterbindet die
Zusammenlegung der Zugriffe!
Tja...
Dann haben wir ja jetzt die Messlatte für deine Fachkompetenz gefunden.
Und die zeigt: Großes Maul, und nix dahinter.
Merke:
Selbsterhöhung kann keine Fachkenntnis ersetzen.
Auch die stete Erniedrigung anderer, trägt nicht zur Fachkompetenz bei.
PS:
Trotz deines ekelhaften Verhaltens, darfst du mich jederzeit um Hilfe
bitten, falls du mal Fragen zu AVR, Arduino, oder zu der Sprache hast,
welche du da verwendest.
Snafu schrieb:> Das "volatile" ist hier übeflüssig/sinnfrei, weil HW Register Zugriff
Da sind die Autoren der io.h aber anderer Ansicht. Und sie haben Recht,
wen wunderts.
Will man z.B. einen Port wiederholt einlesen, dann darf der Compiler das
nicht wegoptimieren und eine alte Kopie aus einen CPU-Register nehmen.
Jeder HW-Zugriff hat genau zu dem Zeitpunkt und in der Reihenfolge zu
geschehen, wie es im Code steht. Die beiden Ausgänge müssen also
nacheinander gesetzt werden, gleichzeitig wäre ein Compilerbug.
Castet man nun eine volatile Variable zu einem anderen Typ, muß dieser
natürlich auch volatile sein.
Dieses Macro ist schon sehr alt, Fehler wären schon längst bemerkt
worden.
Beitrag "Re: sbit macro für avr-gcc"