Hallo Ihr,
hab es soeben mit einem Code zu tun, wo ich es am besten so haben
möchte, dass eine LED getoogelt wird. Nun hab ich in der StdLib
geschaut, aber ich kann dort nur ein Bit setzen oder rücksetzen. Wie geh
ich nun am besten vor?
Hab es dann so versucht, dass ich zuerst auslese und es dann einfach von
eins subtrahiere.
Grundsätzlich würde ich von den Funktionen zur Bitmanipulation Abstand
nehmen und direkte Registerzugriffe nutzen. Also Beispielsweise so:
Setzen:
GPIOA->BSRR = GPIO_Pin_2;
Rücksetzen:
GPIOA->BRR = GPIO_Pin_2;
Vorteil: Wesentlich (Vielfaches) schneller als die Funktionen in deinem
Beispiel und meines Erachtens genausogut/besser lesbar.
Zusätzlich kannst du noch eine Zustandsvariable einführen um dann zu
togglen.
> Habt Ihr eine andere Idee wie man das elegant lösen könnte?> Funktionieren tut das jedoch ;-)
Via "Register direkt". Variable würde ich mir sparen, welche
Toggle-Frequenz ist angestrebt?
Einfach mal machen und messen - Register direkt mit/ohne Variable.
tip schrieb:> Setzen:> GPIOA->BSRR = GPIO_Pin_2;>> Rücksetzen:> GPIOA->BRR = GPIO_Pin_2;
Welcher stm32 bzw. welche "std periph lib"-Version ist das?
Sieht nach stm32f1 aus, m. W. geht das so nicht mit stm32f4.
Die Konstanten für die Bits im BSSR heißen beim stm32f4 übrigens
GPIO_BSRR_BS_* und GPIO_BSRR_BR_* - das GPIO_Pin_* kommt aus
stm32f4xx_gpio.h. Das ist letztlich dasselbe, aber dann wird "Register
direkt" und "lib" munter durcheinandergewürfelt.
Hi Roland,
das Beispiel von mir ist für den stm32F1. Ich weiß ja nicht welchen µC
der Dennis benutzt.
Ich bin jedoch der Meinung, dass man sich diese Lib-Funktionsaufrufe gar
nicht erst angewöhnen sollte. Früher oder später kommt dann nämlich der
Zeitpunkt, wo man merkt, dass das ein x-faches an Zeit in Anspruch
nimmt. Bei mir war es, als ich eine schnelle Soft-SPI machen wollte.
Mit direktem Registerzugriff meinte ich einen Zugriff, der so direkt
ist, dass er die minimal mögliche Zeit in Anspruch nimmt. Also nicht
erst über eine Funktion, welche dann aufgerufen werden muss und die auch
noch "Bremsen" eingebaut hat. Was für Bremsen das sind, kann man sich ja
angucken.
lg
tip
Also ich benutze den STM32F103 hab aber im nächsten Projekt auch einen
415er. Der ist nur um allgemein ein bisschen in die ARM-Welt zu finden.
Wenn ich mal Zeit finde werde ich das mit dem Toogle nachprüfen, lad die
Ergebnise natürlich hier hoch!
Dennis
Dennis P. schrieb:> DeinPORT->ODR ^= GPIO_PIN_xx;
Kann man so machen. Das sollte man aber nur so machen, wenn kein
einziges Bit dieses Port in einem Interrupt-Handler verändert wird.
Sicherer ist beispielsweise:
DeinPORT->BSRR = (DeinPORT->ODR ^ GPIO_PIN_xx) | (GPIO_PIN_xx << 16);
A. K. schrieb:> DeinPORT->BSRR = (DeinPORT->ODR ^ GPIO_PIN_xx) | (GPIO_PIN_xx << 16);
Das wäre dann quasi die perfekte Lösung, wenn ich das richtig verstanden
habe.
> DeinPORT->BSRR = (DeinPORT->ODR ^ GPIO_PIN_xx) | (GPIO_PIN_xx << 16);
Blöde Frage: Über das BSRR-Register kann doch nur gesetzt werden und
nicht rückgesetzt werden. Korrigier mich wenn ich falsch liege.
lg
tip
tip schrieb:>> DeinPORT->BSRR = (DeinPORT->ODR ^ GPIO_PIN_xx) | (GPIO_PIN_xx << 16);>> Blöde Frage: Über das BSRR-Register kann doch nur gesetzt werden und> nicht rückgesetzt werden. Korrigier mich wenn ich falsch liege.>> lg> tip
Joa hätt ich jetzt auch gesagt ;-)
>Blöde Frage: Über das BSRR-Register kann doch nur gesetzt werden und>nicht rückgesetzt werden. Korrigier mich wenn ich falsch liege.
Dann schau besser noch mal ins Datenblatt.
tip schrieb:> Blöde Frage: Über das BSRR-Register kann doch nur gesetzt werden und> nicht rückgesetzt werden. Korrigier mich wenn ich falsch liege.
Was meinste warum das "Bit Set/Reset Register" heisst?
Der Charme dieses recht clever gestalteten Registers liegt darin, dass
man über dessen obere Hälfte definieren kann, welche Bits überhaupt
verändert werden sollen (der "Reset" Teil), und über die untere Hälfte,
auf welchen Wert (der "Set" Teil).
> Warum werden dann aber oben in dem Stück Lib. was ich gepostet hab zwei> verschiedene angesprochen?!
Die Frage stelle ich mir auch grade und komme sogleich zur Nächsten:
Wozu gibt es überhaupt das BRR-Register, wenn ich doch mit dem BSRR
-Register auskommen würde?
Oder anders formuliert: Was kann das BRR-Register, was das BSRR-Register
nicht kann?
lg
tip
Dennis X. schrieb:> Warum werden dann aber oben in dem Stück Lib. was ich gepostet hab zwei> verschiedene angesprochen?!
Weil es beide Register gibt. ;-)
tip schrieb:> Oder anders formuliert: Was kann das BRR-Register, was das BSRR-Register> nicht kann?
Nichts, nur eben rechts statt links. Für Details fragt STM.
tip schrieb:> das Beispiel von mir ist für den stm32F1. Ich weiß ja nicht welchen µC> der Dennis benutzt.
Ich wollte nur darauf hinweisen, dass es da Unterschiede zwischen den
stm32-Familien gibt.
stm32f1xx: BRR/BSRR, ebenso in stm32f1xx.h
stm32f4xx: Nur BSRR, aufgeteilt in BSRRL und BSRRH in stm32f4xx.h
> Ich bin jedoch der Meinung, dass man sich diese Lib-Funktionsaufrufe gar> nicht erst angewöhnen sollte. Früher oder später kommt dann nämlich der> Zeitpunkt, wo man merkt, dass das ein x-faches an Zeit in Anspruch> nimmt.
Nee, lass mal stecken, nicht schon wieder ;-)
Bei GPIO ist es m. E. allerdings eindeutig "pro Register".
tip schrieb:> Man baut> doch nicht aus Spaß ein nutzloses zusätzliches Register ein?
Sonst hätten wir doch nichts zum diskutieren und spekulieren :-)
Vielleicht hatten die bei STM mal große Pläne, die Ports mit 32 Pins zu
bestücken (die LPCs machen das so), würde ja auch zum µC passen. Und wg.
der Pin-Abwärtskompatibilität haben sie es wieder fallen gelassen, beim
stm32f4 gibt das Ding nicht mehr. Ist aber reine Spekulation.
A. K. schrieb:> Sicherer ist beispielsweise:> DeinPORT->BSRR = (DeinPORT->ODR ^ GPIO_PIN_xx) | (GPIO_PIN_xx << 16);
Sorry für's wiederbeleben :-)
Die obige Anweisung ist pfiffig, danke für die Inspiration. Sie ist aber
weiterhin nicht Interrupt-save, weil unbetroffene GPIOs ebenfalls
nochmals explizit gesetzt werden. Ein Interrupt, der zwischen dem Lesen
von ODR und Schreiben von BSSR zuschlägt, kann zu unerwünschtem
Verhalten führen.
Eine verbesserte Version erfordert eine zusätzliche UND-Verknüpfung.
DeinPORT->BSRR = ((DeinPORT->ODR ^ GPIO_PIN_xx) & GPIO_PIN_xx) |
(GPIO_PIN_xx << 16);
BitSet hat gegenüber BitReset eine höhere Priorität, womit man sich ein
paar Operationen spart.
Eddy Current schrieb:> BitSet hat gegenüber BitReset eine höhere Priorität, womit man sich ein> paar Operationen spart.
Ausprobiert, oder steht das irgendwo in einem offiziellen Dokument?
Uwe Bonnes schrieb:> batuu schrieb:>> Ausprobiert, oder steht das irgendwo in einem offiziellen Dokument?>> rm0008.pdf, Seite 168.
Danke,
war mir entgangen ...