Forum: Mikrocontroller und Digitale Elektronik Arduino-C: Unklarheit bei '<< Operator'


von Roth (Gast)


Lesenswert?

Hallo

ich befasse mich mit den Timer-Interupts des Arduino. Soweit alles 
schlüssig und funktioniert im Testlauf erstaunlicherweise auch sofort.

Abgespickt habe ich auf dieser Seite: 
https://arduino-projekte.webnode.at/meine-projekte/servosteuerung/servotest/variante3/

Dort kommen mehrere gleichartige Zuweisungen vor, die ich zwar 
syntaktisch verstehe, aber beim WARUM klemmt mein Kopf. Wenn mit 'CS22' 
ODER-verknüpft wird, wieso muss dann CS22 vorher um 1 Bit nach links 
geschoben werden? Das ist bei fast allen Flag-Operationen auf der Seite 
so.

Beispiel:
1
// Setze CS20, CS21 und CS22 - Clock Select Bit 10,11,12
2
TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20);

Ich gehe davon aus, dass CS20, CS21 und CS22 einzelne Bits im 
repräsentierenden Register repräsentieren. Und wieso muss man die erst 
schieben, bevor man sie verwendet? Über kurze Erklärung würde ich mich 
wirklich freuen.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Roth schrieb:
> wieso muss dann CS22 vorher um 1 Bit nach links geschoben werden?

Das geschieht hier nicht.

x << y

schiebt x um y Bits nach links, nicht umgekehrt.

von Schieber (Gast)


Lesenswert?

1 << CS22
Hier wird nicht CS22 geschoben, sondern die "1" wird um CS22 nach links 
geschoben.

Beispiel: CSS22 ist 3, weil es das 3. Bit ist.
Dann steht da:
Schiebe die "1" um 3 nach links, es kommt also b000001000 raus

von Roth (Gast)


Lesenswert?

Alles klar, dankeschön :-)

von Georg A. (georga)


Lesenswert?

CS* sind nur die Bitpositionen der entsprechenden Bits, zB. 5. Um das 
Bitmuster zu erzeugen, muss man eine 1 an die passende Stelle im Byte 
bekommen. Und dazu schiebt man eine 1 einfach x-mal nach links.

Es gibt andere Hersteller, da sind diese Definitionen schon "richtig" 
(1, 2, 4, 8, 16, ...) und man kann sie ohne << zusammen-odern. Ist halt 
Geschmackssache, hat alles Vor- und Nachteile.

von Falk B. (falk)


Lesenswert?

@ Roth (Gast)

>syntaktisch verstehe, aber beim WARUM klemmt mein Kopf. Wenn mit 'CS22'
>ODER-verknüpft wird,

Die BitMASKE wird oder verknüpft. CS22 ist aber bei den Includes des avr 
gcc eine BitNUMMER.

> wieso muss dann CS22 vorher um 1 Bit nach links

Falsch. 1 wird um CS22 nach links geschoben, um aus der BitNUMMER die 
BitMASKE zu machen.

Siehe Bitmanipulation.

von Wolfgang (Gast)


Lesenswert?

Roth schrieb:
> Ich gehe davon aus, dass CS20, CS21 und CS22 einzelne Bits im
> repräsentierenden Register repräsentieren.

CS20, CS21 und CS22 sind Zahlen, die angeben, an welcher Bit-Position im 
TCCR2B-Register des Atmel Prozessors die Bit für CS20, CS21 bzw. CS22 
liegen. Mit Arduino hat das nichts zu tun.

von eProfi (Gast)


Lesenswert?

In einem h-file (Prozessordefinition) wird CS22 definiert als die 
Bitposition, z.B.

#define CS22 2

Da die Bits nebeneinander liegen, kann man auch schreiben:

TCCR2B |= 7 << CS20;

von Wolfgang (Gast)


Lesenswert?

eProfi schrieb:
> Da die Bits nebeneinander liegen, kann man auch schreiben:
>
> TCCR2B |= 7 << CS20;

Dann wäre aber die Bezeichnung CS20 eher irreführen und man würde sich 
sinnvollerweise ein CS2 definieren, falls das im Headerfile für den 
Prozessor nicht ohnehin schon geeignet festgelegt wurde.

von so, so (Gast)


Lesenswert?

Roth schrieb:
> Und wieso muss man die erst
> schieben, bevor man sie verwendet?

Entgegen aller anderen Hersteller hat Atmel in seinen header nicht über 
Masken sondern über Nummern codiert.

normal:
#define BIT_0    0x0000
#define BIT_1    0x0001
...

Atmel:
#define BIT_0    (1<<0)
#define BIT_1    (1<<1)
...

Das die Atmel-Variante total dämlich ist, haben wir hier schon öfter 
diskutiert.

von S. R. (svenska)


Lesenswert?

so, so schrieb:
> Das die Atmel-Variante total dämlich ist,
> haben wir hier schon öfter diskutiert.

Allerdings hatte Atmel damals einen Grund dafür, insofern ist es nicht 
total dämlich.

von npn (Gast)


Lesenswert?

S. R. schrieb:
> so, so schrieb:
>> Das die Atmel-Variante total dämlich ist,
>> haben wir hier schon öfter diskutiert.
>
> Allerdings hatte Atmel damals einen Grund dafür, insofern ist es nicht
> total dämlich.

Für jemanden, der die Notation nicht kapiert, muß es natürlich dämlich 
aussehen :-)

von FS (Gast)


Lesenswert?

eProfi schrieb:
> In einem h-file (Prozessordefinition) wird CS22 definiert als die
> Bitposition, z.B.
>
> #define CS22 2
>
> Da die Bits nebeneinander liegen, kann man auch schreiben:
>
> TCCR2B |= 7 << CS20;

Kann man machen, es verwirrt aber, da es nicht mehr so offensichtlich 
ist, welche und wie viele Bits nun gesetzt werden. Gegen die Langform 
spricht doch eigentlich nichts außer man ist Tippfaul :) (was einem aber 
früher oder später mal auf die Füße fallen kann). Der Compiler wird die 
Anweisung, da ja alles Konstanten und Makros, zur Kompilierzeit ohnehin 
vereinfachen und optimieren. Wichtig finde ich, das der Code für 
Menschen gut lesbar und auf den ersten Blick klar verständlich ist. Und 
"7 << CS20" sieht einfach kurios aus wenn man mit Registern auf Bitebene 
arbeitet.

von Wolfgang (Gast)


Lesenswert?

FS schrieb:
> Wichtig finde ich, das der Code für Menschen gut lesbar und auf den
> ersten Blick klar verständlich ist. Und "7 << CS20" sieht einfach
> kurios aus wenn man mit Registern auf Bitebene arbeitet.

Wenn es darum geht, würde man wohl eher "clkT2_1024" schreiben und 
irgendwo mal clkT2_1024 als "7 << CS2" definieren ;-)

von W.S. (Gast)


Lesenswert?

so, so schrieb:
> Das die Atmel-Variante total dämlich ist, haben wir hier schon öfter
> diskutiert.

Ach was, beide Varianten sind gleichermaßen dämlich. Immer wird 
behauptet, daß sich dadurch ein C-Quelltext besser lesen lassen würde, 
was in der Praxis schlichtweg nicht stimmt. Siehe hier. Der TO hat sich 
nämlich eben durch diese Möchtegern-Bezeichner verwirren und zu falschen 
Schlüssen leiten lassen.

Und jetzt kommen die Möchtegern-Fachleute und finden eine Notation 
"total dämlich", bloß weil sie nicht ihren jeweiligen Vorstellungen 
entspricht.

Mein Rat:
Blick ins Referenzmanual werfen und allen dicken Header-Dateien 
grundsätzlich mißtrauen, solange man nicht nachgesehen hat, was welche 
Makro-Definition tatsächlich bewirkt.

Noch ein Rat:
Alle die so tollen Bit-Definitionen lieber bleiben lassen und mit den 
Zahlen arbeiten, die im RefManual drinstehen - und die Kommentare dazu 
nicht vergessen.

Also sinngemäß etwa so:
1
TCCXYZ = (0 << 5) |   // Modus 0..3
2
         (1 << 4) |   // Dir: 0=vor,1=rück
3
         (1 << 3) |   // Sel: 0=ena,1=dis
4
         (5 << 0);    // subadr 0..7
Sowas ist problemlos lesbar und man braucht auch nicht ne Headerdatei 
zum Verständnis zu lesen, sondern nur das Refmanual. Und SO UNSÄGLICH 
VIEL zu schreiben ist es auch nicht.

W.S.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

W.S. schrieb:
> Noch ein Rat:

Von diesem Rat rate ich ab.

Das nur wenig besser als eine ausgerechnete Konstante als "magic number" 
auszurechnen und hinzuschreiben, auch wenn der Kommentar versucht, den 
Anschein zu erwecken, zu dokumentieren, was dort geschieht.

von Falk B. (falk)


Lesenswert?

@Rufus Τ. F. (rufus) (Moderator) Benutzerseite

>> Noch ein Rat:

>Von diesem Rat rate ich ab.

Wir wissen ja, von wem dieser "Expertentip" kommt . . .

Hier mal mein Tip.

Beitrag "Re: XC8 compiler - Register schreiben wie bei Atmel"

von Marcus (Gast)


Lesenswert?

>Von diesem Rat rate ich ab.
Der Meinung bin ich auch.

von Einer K. (Gast)


Lesenswert?

Naja...

Welche Form man verwendet, ist in der Sache egal.
Wenns funktioniert ist erstmal ok.

Und schöner gehts immmer.
(bzw. liegt im Auge des Betrachters)

Ich persönlich neige eher zum _BV() Makro.

DDRB |= _BV(PB5) | _BV(PB4);

von A. S. (Gast)


Lesenswert?

S. R. schrieb:
> Allerdings hatte Atmel damals einen Grund dafür, insofern ist es nicht
> total dämlich.

Was war denn damals der Grund?

Also was sprach gegen Sprechende Bitstrukturen, ggf. Unions, wo ich dann 
z.B. schreibe:
1
TCCR2B.CS2=5;
?

von (prx) A. K. (prx)


Lesenswert?

Arduino Fanboy D. schrieb:
> Wenns funktioniert ist erstmal ok.

Fürs erste Testprogramm ja. Wenn das Programm aber länger als 1h 
unverändert auf der Platte bleibt, dann nein.

Schlendrian angewöhnen geht schneller als abgewöhnen.

von S. R. (svenska)


Lesenswert?

Achim S. schrieb:
> Was war denn damals der Grund?

Dass der Assembler die Bitnummer für manche Befehle brauchte, und Atmel 
für C und Assembler die gleichen Headerfiles benutzen wollte.

Achim S. schrieb:
> Also was sprach gegen Sprechende Bitstrukturen, ggf. Unions, wo ich dann
> z.B. schreibe:
> TCCR2B.CS2=5;

Die Dinger sind - habe ich mir hier erklären lassen - für viele Fälle 
praktisch, aber im Allgemeinen ungeeignet. Denn damit kann man nicht 
alle Registerbits auf einmal setzen (= kostet Speicher und Zeit). Das 
macht manche Hardware unbedienbar. Außerdem müssen die Register volatile 
sein, d.h. jeder Zugriff geht auch auf die Hardware.

Zum Beispiel UCSRC (Atmega8515) ist mit so einem Ansatz nicht benutzbar, 
weil du URSEL nicht getrennt von den anderen Bits setzen/löschen kannst 
(lesen geht damit schon garnicht). Auf anderen Architekturen habe ich 
solche Hardwarekonstrukte auch schon gesehen.

Klar kann man in so einem Fall immer die Union mit dem ganzen 
Registerwert nehmen, aber damit verliert man den Vorteil des Bitfeldes 
(welches sowieso unportabel ist, aber das ist bei AVR eher irrelevant).

Außerdem funktioniert so ein Ansatz nur mit IO- oder MMIO-Registern 
vernünftig, aber nicht mit externen Registern (die via I2C, SPI oder 
sonstwas angesprochen werden).

von Falk B. (falk)


Lesenswert?

@Achim S. (achs)

>> Allerdings hatte Atmel damals einen Grund dafür, insofern ist es nicht
>> total dämlich.

>Was war denn damals der Grund?

>Also was sprach gegen Sprechende Bitstrukturen, ggf. Unions, wo ich dann
>z.B. schreibe:

>TCCR2B.CS2=5;

Beitrag "Re: XC8 compiler - Register schreiben wie bei Atmel"

von (prx) A. K. (prx)


Lesenswert?

Achim S. schrieb:
> Was war denn damals der Grund?

Die gleichen Files werden auch für Assembler-Quelltext verwendet. Da 
benötigt man bei den Einzelbitbefehlen aber die Nummer, nicht die Maske. 
Von Nummer zu Maske ist leichter als andersrum.

> Bitstrukturen

Sind ok, wenn man sich nicht dran stört, pro Bit einen oder mehrere 
Befehle zu investieren. Will man ein Steuerregister am Stück 
initialisieren, klappt das so nicht. Weshalb Bitfelder nur als Option 
sinnvoll sind, nicht als einziger Zugriffsmechanismus.

: Bearbeitet durch User
von A. S. (Gast)


Lesenswert?

S. R. schrieb:
> und Atmel
> für C und Assembler die gleichen Headerfiles benutzen wollte

OK, das war ein nachvollziehbarer Grund.

Würde irgendwer das heute noch in reinen C(++)-Headern so machen?

von (prx) A. K. (prx)


Lesenswert?

Achim S. schrieb:
> Würde irgendwer das heute noch in reinen C(++)-Headern so machen?

Ja. Das ARM Bitbanging benötigt ebenfalls Bitnummern statt Masken. 
Leider ist das bei den Headern der Cortex-Mx Controller nicht üblich.

von so so (Gast)


Lesenswert?

Achim S. schrieb:
> OK, das war ein nachvollziehbarer Grund.

Schreibt ihr 'mov' anstatt '='?

Nö, ein C header ist ein C header und kein ASM Krams.

von (prx) A. K. (prx)


Lesenswert?

Weshalb so verbissen?

von npn (Gast)


Lesenswert?

so so schrieb:
> Nö, ein C header ist ein C header und kein ASM Krams.

Du verwechselst Header mit Code...

von Christopher J. (christopher_j23)


Lesenswert?

A. K. schrieb:
> Achim S. schrieb:
>> Würde irgendwer das heute noch in reinen C(++)-Headern so machen?
>
> Ja. Das ARM Bitbanging benötigt ebenfalls Bitnummern statt Masken.
> Leider ist das bei den Headern der Cortex-Mx Controller nicht üblich.

Es gibt bei manchen Herstellern die Position des Bit bzw. der Gruppe von 
Bits. Bei ST haben diese immer das "_Pos"-Suffix, z.B.
1
#define TIM_CR1_ARPE_Pos          (7U)                                         
2
#define TIM_CR1_ARPE_Msk          (0x1U << TIM_CR1_ARPE_Pos)                   /*!< 0x00000080 */
3
#define TIM_CR1_ARPE              TIM_CR1_ARPE_Msk                             /*!<Auto-reload preload enable */

von Einer K. (Gast)


Lesenswert?

A. K. schrieb:
> Arduino Fanboy D. schrieb:
>> Wenns funktioniert ist erstmal ok.
>
> Fürs erste Testprogramm ja. Wenn das Programm aber länger als 1h
> unverändert auf der Platte bleibt, dann nein.
>
> Schlendrian angewöhnen geht schneller als abgewöhnen.

Wer redet hier von Schlampigkeit?
Du?
Scheinst ja selber ein Problem mit deiner Schlampigkeit zu haben, sonst 
müsstest du ja nicht sofort daran denken.

Ich rede von Verfahren.
Verschiedene Verfahren, welche man zur Anwendung bringen kann.

Und da ist im Grunde eins so gut wie das andere.

Natürlich ist das Geschmackssache und mit persönlichen Vorlieben 
verbunden.
Also wieder mal eine gute Gelegenheit für Grabenkriege.

von (prx) A. K. (prx)


Lesenswert?

Christopher J. schrieb:

>> Ja. Das ARM Bitbanging benötigt ebenfalls Bitnummern statt Masken.

Korrektur: Das Bitbanding ist natürlich gemeint.

> Es gibt bei manchen Herstellern die Position des Bit bzw. der Gruppe von
> Bits. Bei ST haben diese immer das "_Pos"-Suffix, z.B.

Gut zu hören. Vor einigen Jahren war das noch nicht so.

von Wolfgang (Gast)


Lesenswert?

so so schrieb:
> Nö, ein C header ist ein C header und kein ASM Krams.

Und bei inline stehst du dann doof da, oder wie stellst du dir das 
vor?

Sag jetzt nicht, inline wäre kein C.

von (prx) A. K. (prx)


Lesenswert?

Arduino Fanboy D. schrieb:
> Scheinst ja selber ein Problem mit deiner Schlampigkeit zu haben, sonst
> müsstest du ja nicht sofort daran denken.

> Also wieder mal eine gute Gelegenheit für Grabenkriege.

Und scheinbar eine gute, um ursprünglich sachliche Auseinandersetzungen 
in persönliche Angriffe umzuwandeln.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Arduino Fanboy D. schrieb:
> Ich rede von Verfahren.
> Verschiedene Verfahren, welche man zur Anwendung bringen kann.
>
> Und da ist im Grunde eins so gut wie das andere.


Wenn es nur um die Unterscheidung Bitnummern / Bitwertigkeit geht, 
stimme ich Dir zu.

Wenn man aber, wie hier im Thread (zum Glück nur einmal) vorgeschlagen, 
"magic numbers" verwendet, statt der im Datenblatt stehenden Namen, dann 
sieht das anders aus.

Das ist strikt abzulehnen.

von Einer K. (Gast)


Lesenswert?

Ja, in dem Beispiel, macht die Verwendung der magischen Zahlen eher 
keinen Sinn.

Auch finde ich, Kommentare sollten das "Warum" erklären.
Und nicht das "Was"

Nein, kein schönes Beispiel.....

Die Verwendung der Bezeichner, statt Zahlen, hat zumindest den Vorteil, 
dass der Kompiler viel bessere Chancen hat, einem (Tipp)Fehler um die 
Ohren zu hauen.
Oder, bei einem Wechsel des AVRs, kann sich der Code an andere 
Bitnummern anpassen, ohne Hand anlegen zu müssen.


Ein Gegenbeispiel, wo magische Zahlen schon etwas Sinn machen:
1
// tiny85
2
        enum AnalogReference : byte 
3
        {
4
          REF_VCC   = 0b00000000,
5
          REF_EXT   = 0b01000000,
6
          REF_11    = 0b11000000,
7
          REF_256   = 0b10010000,
8
          REF_256_C = 0b11010000,
9
        };
Das Bitmuster lässt sich aus dem Datenblatt leicht ablesen.
Ist dann aber auch sehr speziell, nur für diesen µC Type

Ja, auch diese magischen Zahlen könnte man mit den vorgefertigten 
Bezeichnern und << zusammenklöppeln, aber besser lesbar/überprüfbarer 
wirds dadurch auch nicht.

von W.S. (Gast)


Lesenswert?

Rufus Τ. F. schrieb:
> Von diesem Rat rate ich ab.
>
> Das nur wenig besser als eine ausgerechnete Konstante als "magic number"..

Das ist allemal die sauberste und klarste Lösung - und dies mit weitem 
Abstand von allen anderen Varianten.

Versuche du doch mal zu überlegen, was wohl besser ist:
a) direkt so, wie ich das geschrieben habe
b) mit irgendwelchen Bezeichnern zu arbeiten und NICHT ZU WISSEN, ob das 
nun eine Bitmaske ist oder eine Bitnummer.

Im Falle b) bleibt einem nichts weiter übrig, als zusätzlich zum Lesen 
des RefManuals auch noch die entsprechende Headerdatei herauszusuchen 
und dort nachzulesen, was denn tatsächlich mit dem Bezeichner gemeint 
ist.

Und nun guck dir mal ein paar typische Headerfiles z.B. von ST an. Die 
sind oft weit über 1 MB groß und man sucht sich die Hacken wund darin, 
weil dort die finalen Bezeichner fast immer mehrstufig (und dieses 
natürlich an verschiedenen Stellen) definiert sind, ganz abgesehen von 
netten Garnituren wie #ifdef, womit man erstmal herausfinden muß, 
welcher Quellteil in welchem Falle überhaupt gelesen wird. NEE, DANKE. 
Es gibt hübschere Text-Adventures.

Ich habe von der Unart, alles und jedes in irgend einen selbsternannten 
Bezeichner zu verpacken, schon genug gesehen, um definitiv zu wissen, 
daß genau DADURCH der größte Bockmist passiert. Eben aufgrund der 
Denkunterschiede zwischen dem Verfasser und dem Anwender.

Und nochwas:
Bitgefummel der hier diskutierten Art gehört nicht nach main(), sondern 
in einen LowLevel-Treiber. Den schreibt man einmal und testet ihn aus 
und anschließend hat man damit rein GARNICHTS mehr zu tun, sondern man 
benutzt eben das Interface des LowLevel-Treibers, wo solches Bitgefummel 
nicht vorkommen sollte.

So herum wird was Vernünftiges draus.

W.S.

von W.S. (Gast)


Lesenswert?

A. K. schrieb:
>> Bits. Bei ST haben diese immer das "_Pos"-Suffix, z.B.
>
> Gut zu hören. Vor einigen Jahren war das noch nicht so.

Ah ja. Grandios!

Und nun hast du nicht nur nicht nur die Bezeichnungen gemäß RefMan, 
sondern auch noch mehrere ellenlange dazuerfundene xxx_pos und xxx_msk 
Bezeichner. Und das ganze je nach geschmack des jeweiligen Autors auch 
noch nach unterschiedlichen Gestaltungsregeln.

Hier geht's wohl um den Wettbewerb, wer die meisten Bezeichner in seinen 
Headerdateien hat.

W.S.

von W.S. (Gast)


Lesenswert?

Rufus Τ. F. schrieb:
> Wenn man aber, wie hier im Thread (zum Glück nur einmal) vorgeschlagen,
> "magic numbers" verwendet, statt der im Datenblatt stehenden Namen, dann
> sieht das anders aus.
>
> Das ist strikt abzulehnen.

Ich kann dich nicht hindern, bockig zu sein und dabei ungewollt 
Obfuscation zu betreiben, bloß weil du Formalität anstatt Vernunft 
herrschen lassen willst.

Nur eines: Auf die Beschreibungen im RefManual kannst du  dich im 
Allgemeinen verlassen (mit Ausnahmen!!).

Aber die dortigen Bezeichnungen kannst du NIEMALS einfach so verwenden, 
denn dafür brauchst du Statements, wo eben diese Bezeichnungen in die 
von dir ja so gehaßten Zahlen übersetzt werden. Also sowas wie #define 
xyz  123

Entweder schreibst du dir selber was, wo die besagten Statements 
drinstehen oder du benutzt eine Datei von jemand anderem. Aber dort 
findest du eben nie die "im Datenblatt stehenden Namen", weil die eben 
nur ein Teil eines HW-Registers sind und folglich immer eine 
Sonderbehandlung brauchen: also so etwa:

XYZ = ABC | DEF | GHI;  // implizit true für alle 3
oder
XYZ = (1<<ABC) | (1<<DEF) | (1<<GHI);

aber NIE so:
ABC = true;
DEF = true;
GHI = true;
usw.

Also schreib nicht so einen rechthaberischen Stil. Sonst antworte ich 
dir: Was Rufus hier geschrieben hat, ist strikt abzulehnen, weil es 
mehrere Sachfehler enthält.

W.S.

von Christopher J. (christopher_j23)


Lesenswert?

W.S. schrieb:
> Und nun hast du nicht nur nicht nur die Bezeichnungen gemäß RefMan,
> sondern auch noch mehrere ellenlange dazuerfundene xxx_pos und xxx_msk
> Bezeichner.

Nein, es sind nämlich eben genau die Bezeichnungen aus dem RefMan, in 
diesem Fall aus jenem des STM32F031F6, also RM0091. In diesem findest du 
dann auf Seite 367 das "TIM1 Control Register 1", "Bit 7 ARPE: 
Auto-reload preload enable".

Man kann zu jeder Peripherie, zu jedem Register und zu jedem Bit des 
jeweiligen Registers den Namen zusammensetzen aus 
Peripherie_Register_Bit, in diesem Fall eben TIM_CR1_ARPE. Das ist im 
Übrigen bei allen Cortex-M der Fall. _Pos ist tatsächlich eine 
ST-spezifische "Erweiterung" aber irgendwie logisch. Bei Freescale ist 
es eben _SHIFT.

Hat man in einem Register ein Bitfeld, so wird eben Bit0 mit _0, Bit1 
mit _1, Bit2 mit _2, etc. im Suffix bezeichnet. _Msk ist dann eben die 
Maske für das Bitfeld und _Pos dessen Position, z.B.
1
#define TIM_CR1_CKD_Pos           (8U)
2
#define TIM_CR1_CKD_Msk           (0x3U << TIM_CR1_CKD_Pos)                    /*!< 0x00000300 */
3
#define TIM_CR1_CKD               TIM_CR1_CKD_Msk                              /*!<CKD[1:0] bits (clock division) */
4
#define TIM_CR1_CKD_0             (0x1U << TIM_CR1_CKD_Pos)                    /*!< 0x00000100 */
5
#define TIM_CR1_CKD_1             (0x2U << TIM_CR1_CKD_Pos)                    /*!< 0x00000200 */

Ich verstehe wirklich nicht wo da dein Problem damit ist.

PS: Den Header findet man z.B. hier: 
https://github.com/modm-io/cmsis-header-stm32/blob/master/stm32f0xx/Include/stm32f031x6.h#L4415

: Bearbeitet durch User
von so so (Gast)


Lesenswert?

Wolfgang schrieb:
> Und bei inline stehst du dann doof da, oder wie stellst du dir das
> vor?

???
Was willst du mir sagen?

Der Ursprang war, dass Atmel die header für c und asm verwendet. Und das 
ist mir egal, weil ein c header ein c header ist und kein asm krams. 
Jetzt verstanden?

von S. R. (svenska)


Lesenswert?

so so schrieb:
> Und das ist mir egal, weil ein c header ein c header
> ist und kein asm krams.

Na das ist aber schön, dass dir das egal ist.
Atmel war es offensichtlich nicht egal, und deswegen ist es so.

Du darfst dir gerne eigene Header schreiben. ;-)

von Christopher J. (christopher_j23)


Lesenswert?

Atmel hatte wohl auch verstanden, dass man auch in Assembler einen 
Header per #include reinziehen kann ;)

von Stefan F. (Gast)


Lesenswert?

Faszinierend. Die Erste Antwort war richtig und wurde vom TO mit Dank 
als ausreichend bestätigt.

Trotzdem kamen noch 40 weitere überwiegend nicht hilfreiche Beiträge. 
Und es geht munter weiter!

von so so (Gast)


Lesenswert?

S. R. schrieb:
> Atmel war es offensichtlich nicht egal, und deswegen ist es so.

... beschis...

Stefanus F. schrieb:
> Trotzdem kamen noch 40 weitere überwiegend nicht hilfreiche Beiträge.
> Und es geht munter weiter!

Inkl. Deinem wertlosen Beitrag?

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.