STM32 Pin-Toogle!

Gast #2570716
Lesenswert?

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.
1
GPIO_WriteBit(GPIOA, GPIO_Pin_2, (BitAction)((1-GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_2))));

Habt Ihr eine andere Idee wie man das elegant lösen könnte? 
Funktionieren tut das jedoch ;-)

Dennis
Gast #2570734
Lesenswert?

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

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

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

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

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

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 ;-)
1
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
2
{
3
  /* Check the parameters */
4
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
5
  assert_param(IS_GPIO_PIN(GPIO_Pin));
6
  
7
  GPIOx->BSRR = GPIO_Pin;
8
}
9

10
/**
11
  * @brief  Clears the selected data port bits.
12
  * @param  GPIOx: where x can be (A..G) to select the GPIO peripheral.
13
  * @param  GPIO_Pin: specifies the port bits to be written.
14
  *   This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
15
  * @retval None
16
  */
17
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
18
{
19
  /* Check the parameters */
20
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
21
  assert_param(IS_GPIO_PIN(GPIO_Pin));
22
  
23
  GPIOx->BRR = GPIO_Pin;
24
}
#2571027
Lesenswert?

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

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

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

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.

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