Hallo,
ich habe einen Pin welcher definiert wurde z.B. GPIO_Pin_10. Gibt es
eine Möglichkeit einfach um 10 Pins zu schiften? Mir fällt nur ein
log(GPIO_Pin_10)/log(2) ein was ziemlich dämlich ist..
…….
Hintergrund:
Ich will Pins einlesen und kenne nur den Startpin per define. So sollte
es funktionieren, wenn GPIO_Pin_10 einfach eine 10 enthalten würde und
nicht (1<<10) = 0x0400.
Man kann beim GCC Masken in Bitnummern umrechnen, in dem man den
Maschinenbefehl CLZ verwendet:
#define BBitOfMask(mask) (31 - __builtin_clz(mask))
Bei Konstanten macht der Compiler das selbst.
(aus https://www.mikrocontroller.net/articles/ARM_Bitbanding)
Herlock Scholmes schrieb:> Jan K. schrieb:>> START_PIN_POS = ln(GPIO_Pin_10)/ln(2)>> Nicht auszuhalten.> Die Freitage kommen immer früher.>> Oder war das früher auch schon so schlimm?
Hä ich meine das Ernst. Wie würdest du es denn lösen? Wenn man es über
ein define macht könnte doch sein, dass der Compiler das erledigt.
A. K. schrieb:> Man kann beim GCC Masken in Bitnummern umrechnen, in dem man den> Maschinenbefehl CLZ verwendet:> #define BBitOfMask(mask) (31 - __builtin_clz(mask))> Bei Konstanten macht der Compiler das selbst.>> (aus https://www.mikrocontroller.net/articles/ARM_Bitbanding)
Cool Danke, dass schaue ich mir mal an.
Was wäre denn der normale Weg?
sowas wie
(GPIO_ReadInputData(PORT) & GPIO_Pin_10) >> 10;
müsste doch Standard sein. Es würde ja schon reichen, wenn GPIO_Pin_10
mit dem einfachen Zahlenwert definiert wäre. Die andere Richtung mit 1<<
x ist ja super einfach.
Jan K. schrieb:> Hä ich meine das Ernst. Wie würdest du es denn lösen? Wenn man es über> ein define macht könnte doch sein, dass der Compiler das erledigt.
Dir ist schon klar, dass
- Fliesskommarechnung schon mal 1-2 LSBs daneben landet,
- double=>int nicht rundet, sondern abschneidet?
A. K. schrieb:> Dir ist schon klar, dass> - Fliesskommarechnung schon mal 1-2 LSBs daneben landet,> - double=>int nicht rundet, sondern abschneidet?
Joooo und deine Lösung? Wenn es der Kompiler macht sollte er es
schaffen, auf dem µC sollte es bitte nicht live berechnet werden....
Jan K. schrieb:> ich habe einen Pin welcher definiert wurde z.B. GPIO_Pin_10.
Wie?
>Gibt es> eine Möglichkeit einfach um 10 Pins zu schiften?
Nein, nur Bits, keine Pins.
Mir fällt nur ein
> log(GPIO_Pin_10)/log(2) ein was ziemlich dämlich ist..
Ja. wenn der wert 0x400 ist, dann kannst Du auch einfach teilen.
Jan K. schrieb:> nicht (1<<10) = 0x0400.> #define MASK ( ( (1 << NUM_PINS) - 1) << START_PIN)> uint16_t Input = (GPIO_ReadInputData(PORT) & MASK) >> START_PIN; //> read port and mask relevant Pins> Hoffe das war einigermaßen verständlich...
Nö. das war zumindest für mich völlig unverständlich.
Also:
Pins kannst du nicht abfragen. Was du kannst, ist das Auslesen von
Hardware-Registern, hier vor allem die Register, die zur GPIO-Peripherie
gehören. Und da gibt es je nach Typ des Chips eine ganze Reihe
unterschiedlicher Register.
Zunächst erstmal so etwas wie GPIOx_IDR oder GPIOx->IDR (je nach Gusto
des Schreiberlings der betreffenden .h) Bei den meisten Cortexen (zu
denen auch die STM32 gehören) sind die diversen Pins des Chips zu Ports
unterschiedlicher Breite zusammengefaßt. Deren Bezeichnung ist
herstellerabhängig, z.B. GPIOA..GPIOF oder GPIO0..GPIO5 usw. Guck dazu
einfach in dein RefManual.
Wenn du also Port D Pin 10 abfragen willst, dann schreibst du einfach
W.S. schrieb:> Wenn du also Port D Pin 10 abfragen willst, dann schreibst du einfach
Anscheinend ist es genau umgekehrt.
Er bekommt einen wert (1<<10), also 0x400. Und möchte mit diesen 0x400
die 10 "zurückgewinnen", um dann 10 Bit zu schieben.
Das (wie schon angemerkt) geht ohne Zwischenritt "Bit-Ermitteln" einfach
durch Division seines ausgelesenen Wertes durch diese 0x400 (oder
welchen Wert auch immer).
Naja, es kann schon vorkommen, daß man aus der Definition eines
Einzelbits als Bitmaske (z.B. in der .h-Datei einer Library) die
Bitposition erzeugen muss, um die Addresse für's Bitbanding
auszurechenen.
Das kann man ggf. per Macros machen (z.B. für STM32F303):
So ganz verstehe nicht worauf du hinaus willst. Wenn GPIO_Pin_10 =
0x0400 ist kannst du den doch direkt verwenden und musst nichts mehr
durch die Gegend schieben (bei 10 müsstest du das).
boah... schrieb:> War ironisch gemeint. Ist doch nur ein fettes if Konstrukt. ;-)
Ja, aber es erfüllt seinen Zweck. Der Code, der hinten 'rauskommt, ist
i.d.R. effektiver, als ein Bit im Register mit "Register |= Bitmask" zu
setzen. Und letzteres ist nicht so einfach als "atomic" machbar.
Wenn Ironie heißen soll, daß die Lösung sch**** ist, dann schlag halt
'was besseres vor!
Thomas E. schrieb:> Naja, es kann schon vorkommen, daß man aus der Definition eines> Einzelbits als Bitmaske (z.B. in der .h-Datei einer Library) die> Bitposition erzeugen muss, um die Addresse für's Bitbanding> auszurechenen.> Das kann man ggf. per Macros machen (z.B. für STM32F303):
Ja sag mal, was hast du denn da für einen elendigen Bandwurm über 8
Zeilen gepostet?
Und nein, es kann eben nicht vorkommen, daß man..MUSS. Niemand muß,
sondern manche Leute stellen sich einfach nur zu dämlich an. Wenn ich im
Eröffnungspost sehe, daß der TO zu allererst mit seinem #define quasi
auf den Baum geklettert ist und anschließend nicht mehr heil herunter
kommt, dann sollte man ihn über's Knie legen, bis er begreift, daß man
all sowas auf eine sinnvollere Weise macht.
Ich sehe hier im Forum an so unsäglich vielen Stellen, daß die Leute
bloß eben Angelernte sind, die man mal auf C dressiert hat, anstatt sie
das Programmieren zu LEHREN. Deshalb halten sie sich selbst an den
unmöglichsten Stellen genau an ihre Dressur, ohne auch nur im Geringsten
zu VERSTEHEN, was sie da eigentlich anrichten.
Da gibt es Leute, die für einen bool unbedingt ein uint8_t nehmen, als
ob sie damit Integerartithmetik mit definierter Bitzahl betreiben
wollten.
Da gibt es Leute, die für einen String ebenfalls uint8_t nehmen.
Da gibt es Leute, die für jeden Kram unbedingt einen Namen nehmen
wollen, weil man ihnen eingetrichtert hat, daß ein (1<<xyz) genauso
bösartig sei wie ein goto - und die dann auf solche Abwege kommen wie
der TO.
Sind wir hier in der Klapsmühle?
W.S.
W.S. schrieb:> Und nein, es kann eben nicht vorkommen, daß man..MUSS. Niemand muß,
Klar, niemand MUSS ein Aufgabe auf eine ganz bestimmte Weise lösen. Man
KANN sich auch ggf. das Datenblatt vornehmen und jedes Bit, das der
Hersteller in seinen von ihm zur Verfügung gestellten Header-Dateien eh
schon symbolisch als Bitmaske definiert hat (weil das offenbar der
Standard dieses Herstellers ist), nochmal selbst neu mit der Bitnummer
definieren. Im Quelltext hat man es dann halt mit zwei verschiedenen
Symbolen für die gleiche Sache zu tun, je nachdem, ob man Maske oder
Bitnummer braucht. Wenn man den Controller wechselt, muss man dann eben
u.U. auch seine eigenen, nicht standardisierten Header-Files auch wieder
überarbeiten. Ob das für Portabilität und Fehlervermeidung hilfreich
ist?
Von mir aus ersetze das "muss" in meinem Satz durch "will". Ich warte
aber immer noch (wie wohl auch der Verfasser des original-Beitrags, der
den elendigen Bandwurm 2012 gepostet hat) auf die kurze und elegante
Lösung für dieses Problem. Für einen, der die hohe Kunst des
Programmierens wirklich beherrscht, sollte das ja ein Klacks sein.
In C++ kann man das stark schön mit constexpr machen, funktioniert dann
einheitlich für alle Typen. Falls man den GCC nutzt, kann man auch
automatisch die CLZ builtins nutzen; die werden dann je nach Architektur
schön optimiert, falls die Berechnung zur Laufzeit erfolgt. Wenn die
Eingabe dem Compiler bekannt ist, erfolgt die Berechnung immer durch den
Compiler selbst.
W.S. schrieb:> Ich sehe hier im Forum an so unsäglich vielen Stellen, daß die Leute> bloß eben Angelernte sind, die man mal auf C dressiert hat, anstatt sie> das Programmieren zu LEHREN.
Ja, Dich zum Beispiel. Wenn Du verstanden hättest, wie das funktioniert,
dann wüßtest Du auch, daß das keinen Laufzeit-Overhead erzeugt, weil der
Compiler die ganze Kette nämlich zur Compilezeit auswertet. Das ist der
Sinn dieser Makro-Definition. Beachte den Kontext - es geht darum, daß
dieses Makro nicht mit einer Variablen gefüttert wird, sondern mit einer
Bitmaske als #define.
Nop schrieb:> weil der> Compiler die ganze Kette nämlich zur Compilezeit auswertet
???
wird immer besser hier: der hellsehende compiler. gute erfindung.
brauche ich auch.
boah... schrieb:> gibt es auch templates. eine des unsinnigsten erfindungen, wie auch> looping loui. ;-)
Wer genau hinschaut sieht dass da sogar eins im Spiel ist. Wirklich so
unsinnig wenn es tut was der OP möchte?
boah... schrieb:> wird immer besser hier: der hellsehende compiler. gute erfindung.> brauche ich auch.
Wenn der Compiler die Eingabe und den Algorithmus kennt und dieser
"constexpr" ist, kann er die Ausgabe vorberechnen.
Niklas Gürtler schrieb:> Wenn der Compiler die Eingabe und den Algorithmus kennt und dieser> "constexpr" ist, kann er die Ausgabe vorberechnen.
C hat kein constexpr, so daß keine Algorithmen ausgewertet werden können
- Ausdrücke aber schon, weswegen hier der Elvis-Operator mit Vorteil
genutzt wird.
Nop schrieb:> C hat kein constexpr, so daß keine Algorithmen ausgewertet werden können> - Ausdrücke aber schon, weswegen hier der Elvis-Operator mit Vorteil> genutzt wird.
Ja, daher schrieb ich ja auch C++. Da es ja um ARM geht sind ja auch C++
Compiler verfügbar.
Niklas G. schrieb:> Ja, daher schrieb ich ja auch C++. Da es ja um ARM geht sind ja auch C++> Compiler verfügbar.
Und offensichtlich nicht im konkreten Projekt benutzt, weil man dann
keinen veketteten Ausdruck, sondern constexpr genommen hätte. Hat man
aber nicht. Es sind für ARM auch noch zig andere Sprachen verfügbar, die
aber hier ebenfalls nicht genutzt wurden. Wollen wir die jetzt auch alle
noch aufzählen, wie man es da machen würde?
Nop schrieb:> Und offensichtlich nicht im konkreten Projekt benutzt, weil man dann> keinen veketteten Ausdruck, sondern constexpr genommen hätte.
Vielleicht ist der Grund dafür ja auch Unkenntnis von constexpr - wozu
fragt man sonst im Forum?
Nop schrieb:> Es sind für ARM auch noch zig andere Sprachen verfügbar, die> aber hier ebenfalls nicht genutzt wurden.
Auf wie viele davon kann man mit so geringem Aufwand von C wechseln?
Nop schrieb:> Wollen wir die jetzt auch alle> noch aufzählen, wie man es da machen würde?
Warum nicht, wäre interessant zu sehen welche Sprachen das auch so
können.
Niklas G. schrieb:> Auf wie viele davon kann man mit so geringem Aufwand von C wechseln?
Prust.. ja nee, ist klar. Naja, halt die übliche ungefragte C++-Onanie,
die sich irgendwo zwischen Veganern und Zeugen Jehovas einreiht.
Nop schrieb:> Prust.. ja nee, ist klar. Naja, halt die übliche ungefragte C++-Onanie,> die sich irgendwo zwischen Veganern und Zeugen Jehovas einreiht.
Warum so ein Tonfall?
Niklas G. schrieb:> Warum so ein Tonfall?
Weil man keinen Fetzen C diskutieren kann, ohne daß einem C++-Fans
reingrätschen und ihre Lieblingssprache wie Sauerbier anpreisen, eine
Lösung auf der Suche nach einem Problem. Wilhelm ist da auch so ein
Kandidat. Aber aber aber in C++ ginge das soooooo.. Herr Lehrer, im
Keller brennt das Licht, aber ich hab's schon ausgemacht.
Nichtmal Arch-User kommen da mit. Gut, bei denen liegt's auch bloß
daran, daß sie die meiste Zeit damit beschäftigt sind, ihr System ans
Laufen zu kriegen.
Nop schrieb:> Weil man keinen Fetzen C diskutieren kann,
Es war nirgendwo gesagt, dass es C sein muss. Aber ich sehe schon, mit
Argumenten kommt man hier nicht weiter.
Vielleicht sollte erstmal genau geklärt werden was der Threadersteller
eigentlich überhaupt erreichen will. Ich sehe nämlich nicht daß das an
irgendeiner Stelle schon mal zur Sprache kam. Wahrscheinlich ist die
Lösung vollkommen trivial.
Bernd K. schrieb:> Vielleicht sollte erstmal genau geklärt werden was der Threadersteller> eigentlich überhaupt erreichen will.
Ich kann's mir denken. Er hat vermutlich ein Makro definiert, welches
den ersten Pin eines externen Busses angibt, welcher aus mehreren Pins
besteht:
1
#define BusStartPin GPIO_Pin_10
Jetzt möchte er mehrere Signale gleichzeitig ausgeben, also z.B. auf
Pins 10-13:
1
uint8_tdata=0x5;
2
GPIO->BSRR=(data<<10)|((~data&0xF)<<(10+16));
Nur wie kommt man hier an die 10 aus dem BusStartPin-Makro? GPIO_Pin_10
ist ja (1 << 10). Mit log2 geht das:
Etwas logischer wäre es, BusStartPin direkt als 10 zu definieren.
Allerdings erwarten diverse Funktionen der HAL es in der Form (1<<10),
d.h. man soll GPIO_Pin_10 o.ä. übergeben. Man könnte es bei der Übergabe
per "1<<BusStartPin" machen, aber das sieht auch komisch aus.
Niklas G. schrieb:> Es war nirgendwo gesagt, dass es C sein muss.
Hi Niklas,
wollte die o.a. Lösung gerade mal eben testen - so einfach geht es aber
leider nicht (zumindest offenbar nicht ohne gößeren Portierungsaufwand).
Habe diese Zeilen:
einfach mal an den Anfang eines C++ Sourcefiles in einem vorhandenen
Projekt eingefügt. Ergebnis:
1
compiling logwriter.cpp...
2
logwriter.cpp(64): error: #20: identifier "constexpr" is undefined
3
constexpr std::size_t log2 (const T& val, T bit = (std::numeric_limits<T>::digits-1)) {
4
logwriter.cpp(64): error: #147: declaration is incompatible with type "std::size_t" (declared at line 60 of "C:\Keil_v5\ARM\ARMCC\Bin\..\include\stdlib.h")
5
constexpr std::size_t log2 (const T& val, T bit = (std::numeric_limits<T>::digits-1)) {
6
logwriter.cpp(64): error: #65: expected a ";"
7
constexpr std::size_t log2 (const T& val, T bit = (std::numeric_limits<T>::digits-1)) {
8
logwriter.cpp(70): warning: #12-D: parsing restarts here after previous syntax error
9
...
Ohne jetzt lange weiter geforscht zu haben, dürfte das Problem wohl mit
der Compiler-Version zusammenhängen. ARM Compiler 6 statt 5 scheint
"constexpr" zu kennen, aber für den Umzug des Projekts auf diesen
Compiler wären zahlreiche Änderungen in vielen Dateien notwendig.
Fazit: die "unelegante" C-Lösung funktioniert wenigstens, sowohl für C,
als auch für C++ Sourcen, und mit jeder Compiler-Version.
Johannes S. schrieb:> ist der C++ Standard auch auf C++11 oder grösser eingestellt?
Das dürfte das Problem sein: es wäre wohl C++14 notwendig, aber der
Compiler 5 unterstützt nur C++11.
Thomas E. schrieb:> Ohne jetzt lange weiter geforscht zu haben, dürfte das Problem wohl mit> der Compiler-Version zusammenhängen
Ja, der Compiler muss C++11 kennen. Du könntest das "constexpr"
weglassen und schauen ob er in der Lage ist, es zu optimieren (bei
constexpr wäre das garantiert).
Thomas E. schrieb:> aber für den Umzug des Projekts auf diesen> Compiler wären zahlreiche Änderungen in vielen Dateien notwendig.
Wenn der Code derart unportabel ist, wäre eine Umstrukturierung nicht
unangebracht... Auf genau eine Version eines bestimmten Compilers
festgenagelt zu sein ist nicht so besonders zukunftssicher.
Thomas E. schrieb:> Fazit: die "unelegante" C-Lösung funktioniert wenigstens, sowohl für C,> als auch für C++ Sourcen, und mit jeder Compiler-Version.
Tja, manchmal kann man auch auf aktuelle Software wechseln...
"constexpr" gibt es schon seit 2011, das sollte mittlerweile
"angekommen" sein.
Thomas E. schrieb:> Fazit: die "unelegante" C-Lösung funktioniert wenigstens, sowohl für C,> als auch für C++ Sourcen, und mit jeder Compiler-Version.
Es sei den man wechselt die Plattform auf eine, auf welcher ein unsigned
int nicht 32bit groß ist (z.B. AVR). Und für erst zur Laufzeit bekannte
Variablen wird diese auch nicht zu "CLZ" optimiert.
Niklas G. schrieb:> Ja, der Compiler muss C++11 kennen.
Lt. Doku sollte der Compiler 5 C++11 kennen.
Ohne "constexpr" gibt es nur noch 2 Fehler:
1
logwriter.cpp(68): error: #18: expected a ")"
2
return val & (T { 1 } << bit) ? bit : log2 (val, bit-1);
3
logwriter.cpp(68): error: #29: expected an expression
4
return val & (T { 1 } << bit) ? bit : log2 (val, bit-1);
Niklas G. schrieb:> Es sei den man wechselt die Plattform auf eine, auf welcher ein unsigned> int nicht 32bit groß ist (z.B. AVR)
Soweit ich sehen kann, steckt im BITNR-Makro überhaupt kein Datentyp
drin.
Beim Wechsel auf eine andere Plattform wird man bei der Verwendung von
Bitbanding auch noch ganz andere Portierungs-Probleme haben, als die
Wortbreite der Maschine. Daß das Projekt mal auf einen AVR o.ä. portiert
wird, kann ich definitiv ausschließen.
Für Laufzeitberechnung ist das eh nicht gedacht.
Thomas E. schrieb:> Ohne "constexpr" gibt es nur noch 2 Fehler:
Achja, die Initialisierung ist auch C++11. Mit "((T) 1)" statt "T{1}"
sollte es gehen.
Thomas E. schrieb:> Soweit ich sehen kann, steckt im BITNR-Makro überhaupt kein Datentyp> drin.
Aber es nimmt implizit 32bits an, denn es fragt die Bits 0-31 ab.
Niklas G. schrieb:> Achja, die Initialisierung ist auch C++11. Mit "((T) 1)" statt "T{1}"> sollte es gehen.
Ok, danke, das geht, aber der Compiler erzeugt nun tatsächlich eine
log2()-runtime Funktion.
Niklas G. schrieb:> Aber es nimmt implizit 32bits an, denn es fragt die Bits 0-31 ab.
Diese Einschränkung wird aber erst bei Datenbreiten über 32 Bit
relevant. Bis wir mal STM64Fxxxx-MPUs einsetzen, bin ich garantiert in
Rente!
Thomas E. schrieb:> Diese Einschränkung wird aber erst bei Datenbreiten über 32 Bit> relevant.
Naja, wenn int 16bit ist gibt das bestimmt lustige Compiler-Fehler...
Wenn man sich auf eine einzelne Plattform beschränkt ist es aber ok.
Thomas E. schrieb:> Ok, danke, das geht, aber der Compiler erzeugt nun tatsächlich eine> log2()-runtime Funktion.
Auch bei maximaler Optimierungsstufe? Der ARMCC soll ja so toll
optimieren können...
Niklas G. schrieb:> Naja, wenn int 16bit ist gibt das bestimmt lustige Compiler-Fehler...
Ich wüsste nicht, wie ich die provozieren sollte.
Die Funktion
1
uint16_ttestfunc(uint16_tval)
2
{
3
returnBITNR(val);
4
}
führt jedenfalls nicht zu Fehlern.
Niklas G. schrieb:> Auch bei maximaler Optimierungsstufe? Der ARMCC soll ja so toll> optimieren können...
Aktuell verwende ich -O2. Mit -O3 (AFAIK die höchste Stufe) habe ich
nicht getestet. Aber selbst mit -O0 compiliert
Thomas E. schrieb:> Ich wüsste nicht, wie ich die provozieren sollte.
Indem du es für AVR kompilierst... Wie gesagt, das Problem tritt nur
beim Portieren auf.
Thomas E. schrieb:> Aktuell verwende ich -O2.
Dann kann der wohl die Rekursion nicht auflösen...
Niklas Gürtler schrieb:> Indem du es für AVR kompilierst... Wie gesagt, das Problem tritt nur> beim Portieren auf.
kapiere ich nicht - wieso sollte sich der Compiler da überhaupt für
Datentypen interessieren? Dann müsste ja eine Erweiterung des Makros auf
>32 Bit (bei int = 32 Bit) hier auch zu Fehlern führen - tut es aber
nicht!
Ich behaupte mal, daß das BITNR-Makro unverändert auch bei C-Compilern
füt AVR und sogar PIC12 funktioniert.
Thomas E. schrieb:> Ich behaupte mal, daß das BITNR-Makro unverändert auch bei C-Compilern> füt AVR und sogar PIC12 funktioniert.
Ok, kann sein dass das aufgrund der Integer Promotion Regeln doch geht,
die kann ich mir nicht merken. Gibt es keine Warnung wenn man einen 16
Bit Int mit 0x10000 vergleicht (außerhalb des Bereichs)?
Sollte int aber 64Bit sein, fehlen jedenfalls 32 Fälle...
Thomas E. schrieb:> Ich warte> aber immer noch (wie wohl auch der Verfasser des original-Beitrags, der> den elendigen Bandwurm 2012 gepostet hat) auf die kurze und elegante> Lösung für dieses Problem. Für einen, der die hohe Kunst des> Programmierens wirklich beherrscht, sollte das ja ein Klacks sein.
Ist es auch. Zu allererst wird die ganze ST-Lib einfach rausgehalten.
Dann wird sich davon verabschiedet:
Jan K. schrieb:> ich habe einen Pin welcher definiert wurde z.B. GPIO_Pin_10.
Dann schreibt man sich seinen Lowlevel-Treiber direkt und benutzt die
bei diesem Chip vorhandenen Möglichkeiten mit BSRR für Ausgaben in IDR
für Abfragen. Das ergibt dann nen Einzeiler, so wie ich das bereits
geschrieben habe.
Voraussetzung: Man übernimmt nicht ohne jegliches Nachzudenken sowas wie
GPIO_Pin_10 und rennt damit voll vor die Wand, sondern denkt VORHER
drüber nach, wie man sinnvoll zum Ziele kommt. Von wegen "ich habe einen
Pin welcher definiert wurde.." - das ist SichInDieHosenMach weil die
Kraft fehlt, das Problem zu überblicken und es an der richtigen Stelle
geradezurücken. Und DIESES Problem hier ist ja nun wirklich geradezu
winzig.
Ich sag's nochmal: Ich erwarte von den Leuten, daß sie wissen, was sie
tun, BEVOR sie es tun.
W.S.
Niklas Gürtler schrieb:> Ok, kann sein dass das aufgrund der Integer Promotion Regeln doch geht,> die kann ich mir nicht merken. Gibt es keine Warnung wenn man einen 16> Bit Int mit 0x10000 vergleicht (außerhalb des Bereichs)?
Bei einer Operation mit zwei unterschiedlich großen Integer-Datentypen
wird ja immer der kleinere Operand vor der Operation erstmal in den
größeren Datentypen umgewandelt. Für eine "nackte" Zahl wird zunächst
der Datentyp benutzt, in den die Zahl 'reinpasst. Wenn man also einen
uint8_t-Operanden mit 0x10000 verknüpft, wird er intern auf 32 Bit
gecastet, weil 0x10000 ja auch nicht mehr in 16 Bit passt und somit 32
Bits erforderlich sind. Dabei gibt der (zumindest der ARM-) Compiler
auch keine Warnung aus. Eine Warnung gibt er u.U. zu den Auswirkungen
aus, z.B. bei
if(var8bit & 0x10000)
return;
(mehr code)
kommt eine Warnung "statement is unreachable" für die Zeils (mehr code).
W.S. schrieb:> Zu allererst wird die ganze ST-Lib einfach rausgehalten.
Mach das halt, wenn Du es für richtig hältst. Viel Spass bei der
Erstellung Deiner eigenen Header-Dateien mit den tausenden
Bit-Definitionen der ganzen Pertipherie-Module. Aber schreib hier bitte
nicht, daß "man" es so macht!
W.S. schrieb:> Dann schreibt man sich seinen Lowlevel-Treiber direkt und benutzt die> bei diesem Chip vorhandenen Möglichkeiten mit BSRR für Ausgaben in IDR> für Abfragen. Das ergibt dann nen Einzeiler, so wie ich das bereits> geschrieben habe.
Das simple Setzen und Rücksetzen von Portbits per BSRR-Register geht
auch - oh Wunder! - mit dem Zeug von ST als Einzeiler, so daß es auch
jeder andere STM32-Programmierer ohne Deinen selbstgestrickten und
inkompatiblen Spezial-Treiber benutzen kann. Offensichtlich hast Du
nicht verstanden, worum es geht - der TO hat sicher auch kein Problem
damit, sein gewünschtes Portbit auf High zu setzen.
Thomas E. schrieb:> Offensichtlich hast Du> nicht verstanden, worum es geht - der TO hat sicher auch kein Problem> damit, sein gewünschtes Portbit auf High zu setzen.
Offensichtlich hast du weder Manieren noch eine Ahnung, worum es hier
geht. Also laß lieber deine unangemessenen Behauptungen und versuche,
die bisherigen Beiträge verstehend zu lesen.
W.S.