Forum: Mikrocontroller und Digitale Elektronik STM32F4 GPIO port masking


von Florian R. (rager)


Lesenswert?

Hallo,
ich möchte mit meinem STM32F4 einen Display ansteuern und benötige dafür 
einen 8Bit parallel Port. Nun hat der STM nur 16bit Ports und ich bin 
mir nicht sicher wie ich die 8 Pins über eine einfache 8bit (0xAB) 
Hexzahl ansteuern kann ohne die anderen Pins zu manipulieren. Habt ihr 
da eine Idee wie ich das anstellen kann?
Das hier ist das beste was mit eingefallen ist:

PortVal = GPIOx->ODR;
GPIOx->ODR = (PortVal & 0x00)| 0xAB;

Geht das immer und sicher? Und gibt es eine bessere Lösung?

Vielen Dank und Grüße,
Florian

von Dr. Sommer (Gast)


Lesenswert?

Indem du C lernst. "(PortVal & 0x00)" ist immer 0. Du musst lediglich 
die unteren 8 bits des Port-Registers modifizieren und die oberen gleich 
lassen. z.B. so:
1
uint8_t daten = ... ;
2
GPIOx->ODR = (GPIOx->ODR & (0xFF00)) | daten;

von Irgendwer (Gast)


Lesenswert?

"PortVal & 0x00"

UND-Verküpfung mit Null, da kannst du das ganze auch gleich ganz 
weglassen und "GPIOx->ODR = 0xAB" Schreiben.-)

Du meinst wohl eher:
GPIOx->ODR = (GPIOx->ODR & 0xFF00) | 0x00AB;

von Florian R. (rager)


Lesenswert?

Ja, ich hab die 0x"FF"00 vergessen, danke. Es geht mir aber vorallem um 
einen noch effizientern Weg. Gibt es Einen, oder ist der das schon?

von (prx) A. K. (prx)


Lesenswert?

GPIOx->BSRR = 0xFF << (16+N) | value << N;
Wobei N die Nummer des untersten Bits im Port ist.
Im Unterschied zu den anderen Lösungen ist diese atomar.

: Bearbeitet durch User
von Dr. Sommer (Gast)


Lesenswert?

Der Compiler wird das zu einem "strb" optimieren. Effizienter geht 
nicht.

von (prx) A. K. (prx)


Lesenswert?

Dr. Sommer schrieb:
> Der Compiler wird das zu einem "strb" optimieren.

Nein, das wird er hoffentlich nicht, wenn ODR so angegeben wird. Da das 
als volatiles 32-Bit Wort deklariert ist, muss der Compiler den 
Zugriff auch in dieser Breite durchgeführen.

Da muss man schon selber Hand anlegen.

: Bearbeitet durch User
von Steel (Gast)


Lesenswert?

A. K. schrieb:
> GPIOx->BSRR = 0xFF << (16+N) | value << N;

Blödsinn

Um ein Bit zu setzen reicht es, dies in die unteren 16 Bit des BSRR 
Registers zu schreiben.

GPIOx->BSRR = (1 << N) Setzt das nte Bit und lässt alle anderen Bits 
unangetastet. usw.

von Dr. Sommer (Gast)


Lesenswert?

Achja, stimmt. Das mit dem BSRR müsste aber ein "str" werden ;)

von Dr. Sommer (Gast)


Lesenswert?

Steel schrieb:
> Um ein Bit zu setzen reicht es, dies in die unteren 16 Bit des BSRR
> Registers zu schreiben.
Es geht aber darum, nicht nur zu setzen, sondern auch zu löschen!

von (prx) A. K. (prx)


Lesenswert?

Steel schrieb:
> Blödsinn

Ebenfalls Blödsinn. Wenn man einen 8-Bit Wert in einen Port schreiben 
will, so dass er 1:1 da ankommt, dann reicht es nicht aus, die Bits zu 
setzen. Man muss die vorher gesetzten Bits auch löschen. Und das kann 
man mit dem BSRR in einem Rutsch.

: Bearbeitet durch User
von Steel (Gast)


Lesenswert?

Dr. Sommer schrieb:
> Es geht aber darum, nicht nur zu setzen, sondern auch zu löschen!

Dann funktioniert die obige Anweisung trotzdem nicht. Da das löschen 
priority gegenüber dem Satzen hat geht es nicht in einer Anweisung.

von Steel (Gast)


Lesenswert?

A. K. schrieb:
> Man muss die vorher gesetzten Bits auch löschen. Und das kann
> man mit dem BSRR in einem Rutsch.

Dann darf man aber zum löschen nicht FF verwenden sondern muss dort die 
Bits aussparen, die man setzen will.

von (prx) A. K. (prx)


Lesenswert?

Steel schrieb:
> Dann funktioniert die obige Anweisung trotzdem nicht. Da das löschen
> priority gegenüber dem Satzen hat geht es nicht in einer Anweisung.

Hältst du ST für bescheuert? "If both BSx and BRx are set, BSx has 
priority."

> Dann darf man aber zum löschen nicht FF verwenden sondern muss dort die
> Bits aussparen, die man setzen will.

Nein.


Apropos: Wer sich schon immer fragte, weshalb die Ports nur 16 Bits 
breit sind: vermutlich genau deshalb, also damit ein solches Register 
möglich ist.

: Bearbeitet durch User
von Florian R. (rager)


Lesenswert?

Okay klasse,
was genau ist denn nun effizienter oder "besser"(falls man das sagen 
kann) ?

GPIOx->ODR = (GPIOx->ODR & ~(0xFF << N)) | daten << N;
versus:
GPIOx->BSRR = 0xFF << (16+N) | daten << N;

Das Letztere oder?

von (prx) A. K. (prx)


Lesenswert?

Florian Roesner schrieb:
> Das Letztere oder?

Definitiv.

Die effizienteste Form ist allerdings bei den Bits 0..7 Dr.Sommers 
Variante in ihrer korrekten Form, nur sieht die etwas gewürgt aus:
  *(volatile uint8_t *)&GPIOx->ODR = value;
Das ist nun wirklich nur ein STRB Befehl.

: Bearbeitet durch User
von Florian R. (rager)


Lesenswert?

Dann danke ich euch vielmals für die super schnellen Antworten!

Grüße,
Florian

von (prx) A. K. (prx)


Lesenswert?

PS: Die Dr.Sommer Variante funktioniert nur bei den STM32 mit GPIO am 
AHB. Bei den STM32F1 mit dem alten APB-Modul funktioniert sie nicht, 
da nur Wortzugriffe zulässig sind.

von Pete K. (pete77)


Lesenswert?

Immer wieder gern gelesen:
http://diller-technologies.de/stm32.html

von (prx) A. K. (prx)


Lesenswert?

Pete K. schrieb:
> Immer wieder gern gelesen:
> http://diller-technologies.de/stm32.html

So wie ich das verstanden habe, hat er die schnellste Version gesucht.
Nicht die langsamste.

: Bearbeitet durch User
von Pete K. (pete77)


Lesenswert?

Nein, die effizienteste :-)
Ist für mich die, die auch andere verstehen oder man selbst nach 4 
Wochen auch noch.

von (prx) A. K. (prx)


Lesenswert?

Pete K. schrieb:
> Ist für mich die, die auch andere verstehen oder man selbst nach 4
> Wochen auch noch.

Für mich ist die Lib-Version auch dann die ineffizienteste. Weil ich
- zum Verständnis des STM32 und fürs Debugging dessen Doku lesen muss,
- für die Nutzung der Lib zusätzlich deren Doku lesen muss,
- trotzdem oft zusätzlich in deren Quellcode schauen muss,
- und wenn ich Pech habe noch Bugs anderer Leute fixen muss.
Bei direktem Zugriff reicht der erste Punkt.

: Bearbeitet durch User
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.