Forum: Mikrocontroller und Digitale Elektronik STM32F4 Port wird nicht (zumindest sichtbar) aktiviert


von repac3r (Gast)


Lesenswert?

Schönen späten Abend euch,

habe meinen stm32f4 mal wieder raus gekrustelt und wollte ein bisschen 
damit basteln, das blöde, ich darf wieder bei 0 anfangen, da ich so 
ziemlich nichts mehr weiß. Nun habe ich schon Probelme mit dem 
einfachsten Programm, den Hello-World. Hier mal mein Code:

1
#include "stm32f4xx_gpio.h"
2
#include "stm32f4xx_rcc.h"
3
4
void initPortA()
5
{
6
  GPIO_InitTypeDef gpioInit;
7
  SystemInit();
8
9
  RCC_AHB1PeriphClockCmd(GPIOA, ENABLE);
10
  gpioInit.GPIO_Pin = GPIO_Pin_8;
11
  gpioInit.GPIO_Mode = GPIO_Mode_OUT;
12
  gpioInit.GPIO_OType = GPIO_OType_PP;
13
  gpioInit.GPIO_Speed = GPIO_Speed_50MHz;
14
15
  GPIO_Init(GPIOA, &gpioInit);
16
}
17
18
int main()
19
{
20
  initPortA();
21
  GPIO_WriteBit(GPIOA, GPIO_Pin_8, Bit_SET);
22
23
  while(1)
24
  {
25
26
  }
27
}

Lässt sich kompilieren und erfolgreich flashen. Jedoch leuchtet die Led 
an diesem Port nicht auf. Das komische ist, vorher ging es noch, 
vermutlich habe ich irgendwas vergessen, aber keine Ahnung was.

Falls es was nützt, als Unterbau nutze ich ein myStm32-Board, eine Art 
Erweiterungplatine. Die Led selbst ist nicht defekt, auf VCC leuchtet 
diese.

Wo liegt das Problem?



Grüße Marcel

von fhfhd (Gast)


Lesenswert?

>> RCC_AHB1PeriphClockCmd(GPIOA, ENABLE);

ich glaube GPIOA ist falsch. Da gibt es was in die Richtung 
AHB1Periph_GPIOA oder so. Musste de mal nachgucken.

von Stefan (Gast)


Lesenswert?

Meistens werden Leds mit einem low-Pin eingeschaltet ...

von Markus M. (adrock)


Lesenswert?

fhfhd schrieb:
>>> RCC_AHB1PeriphClockCmd(GPIOA, ENABLE);
>
> ich glaube GPIOA ist falsch. Da gibt es was in die Richtung
> AHB1Periph_GPIOA oder so. Musste de mal nachgucken.

Stimmt.

Es muss RCC_AHB1Periph_GPIOA heißen und nicht GPIOA.

GPIOA zeigt ja auf die Struktur und damit kann diese Funktion nichts 
anfangen. Erstaunlich nur, dass es keinen Fehler bei der Typprüfung 
gegeben hat (=Warnung beim Übersetzen).

Oder hat es dass und der TE hat die Warnungen abgeschaltet/ignoriert?

: Bearbeitet durch User
von Bernd K. (prof7bit)


Lesenswert?

repac3r schrieb:
> und wollte ein bisschen
> damit basteln, das blöde, ich darf wieder bei 0 anfangen, da ich so
> ziemlich nichts mehr weiß.

Das ist also ein guter Zeitpunkt diese chaotischen unnötigen Libraries 
diesmal komplett links liegen zu lassen und stattdessen direkt auf die 
Register zuzugreifen, unter Zuhilfename des Reference Manual (und des 
Product Datasheet für das Pin/Port-mapping).

Dein Code wird erheblich(!) kürzer(!) und übersichtlicher(!) werden, die 
Zeit die Du benötigst wird kürzer weil Du weniger Dokumente lesen und 
verstehen musst und weniger impliziten nicht erwähnten Querverweisen auf 
andere nicht genannte Stellen in anderen nicht näher bezeichneten 
Dokumenten folgen musst in der chaotischen Library-Dokumentation.

: Bearbeitet durch User
von Repac3r (Gast)


Lesenswert?

fhfhd schrieb:
> RCC_AHB1PeriphClockCmd(GPIOA, ENABLE);
>
> ich glaube GPIOA ist falsch. Da gibt es was in die Richtung
> AHB1Periph_GPIOA oder so. Musste de mal nachgucken.

Danke sehr, das war's.

Bernd K. schrieb:

> Das ist also ein guter Zeitpunkt diese chaotischen unnötigen Libraries
> diesmal komplett links liegen zu lassen und stattdessen direkt auf die
> Register zuzugreifen, unter Zuhilfename des Reference Manual (und des
> Product Datasheet für das Pin/Port-mapping).
> Dein Code wird erheblich(!) kürzer(!) und übersichtlicher(!) werden, die
> Zeit die Du benötigst wird kürzer weil Du weniger Dokumente lesen und
> verstehen musst und weniger impliziten nicht erwähnten Querverweisen auf
> andere nicht genannte Stellen in anderen nicht näher bezeichneten
> Dokumenten folgen musst in der chaotischen Library-Dokumentation.

Das habe ich bisher immer nur anders herum gehört. Immer heißt es, man 
soll nicht auf die Register selbst zugreifen, warum?

von Christian J. (Gast)


Lesenswert?

Repac3r schrieb:

> Das habe ich bisher immer nur anders herum gehört. Immer heißt es, man
> soll nicht auf die Register selbst zugreifen, warum?

Weil es eine Fehlerquelle mehr ist. Und weil es sehr kompliziert werden 
kann sich da mit jedem Bit einzeln anzufreunden, denn meist sind ja ja 
mehrere bis viele bis mal ein Peripheral funktioniert, die Matrix 
richtig steht, der Takt usw.usw.

von Schaulus Tiger (Gast)


Lesenswert?

Christian J. schrieb:
> Repac3r schrieb:
>
>> Das habe ich bisher immer nur anders herum gehört. Immer heißt es, man
>> soll nicht auf die Register selbst zugreifen, warum?
>
> Weil es eine Fehlerquelle mehr ist.

Ja, das leuchtet ein, je mehr Code, umso weniger Fehlerquellen. 
Allgemein ist ja die Anzahl der Tippfehler umgekehrt proportional zur 
Anzahl der Worte.

> Und weil es sehr kompliziert werden kann sich da mit jedem Bit
> einzeln anzufreunden

Und weil das mit dieser Lib ja überhaupt nicht nötig ist:
1
GPIO_InitTypeDef gpioInit;
2
3
  gpioInit.GPIO_Pin = GPIO_Pin_8;
4
  gpioInit.GPIO_Mode = GPIO_Mode_OUT;
5
  gpioInit.GPIO_OType = GPIO_OType_PP;
6
  gpioInit.GPIO_Speed = GPIO_Speed_50MHz;
7
8
  GPIO_Init(GPIOA, &gpioInit);
Man sieht, mit Lib und nur 2 Zeilen mehr hat man schon ganz neue 
Möglichkeiten Fehler zu machen. Mal abgesehen von den 50MHz für eine 
LED.

Und von wegen "mit jedem Bit einzeln anfreunden": Was ist mit den 
Alternate Function Registern oder dem ODR? Woher weiß ich, dass die hier 
zufällig nicht gesetzt werden müssen? Und, müssen sie wirklich nicht? 
Ich dachte, automatische Variablen wie hier "GPIO_InitTypeDef gpioInit;" 
enthalten erstmal zufällige Werte?

Alleine die letzte Frage müsste ich erstmal klären, bevor ich GPIO_Init 
auf meine Hardware los lasse. Und sowas spare ich mir beim direkten 
Zugriff auf die Hardware. Das Reference Manual muss ich ja sowieso 
lesen, woher wüsste ich sonst, wie ich diese gpio struct initialisieren 
muss.

Ich sag' ja nichts gegen eine lib für USB, aber wenn ich bei so 
trivialen Sachen wie GPIO auch noch viel mehr schreiben muss, also dann 
ist etwas gründlich schief gegangen. Zum Vergleich: ich hab' mir für die 
GPIO-Intialisierung eine eigene Funktion gebastelt. Damit brauche ich 
pro Pin genau eine Zeile für alles, inkl. Definition vom Signalnamen.

Repac3r schrieb:

> Immer heißt es, man soll nicht auf die Register selbst
> zugreifen, warum?

VT: ARM hat die CMSIS nicht selbst gebaut sondern in Auftrag gegeben. 
Ein Chip-Hersteller, der keine ARM-Kerne im Programm hat, möchte den 
Siegeszug von ARM wenigstens etwas bremsen und hat seine Leute dort 
eingeschmuggelt. Dass die Theorie stimmt, sieht man z.B. daran, dass die 
neueren Sachen von ST nicht ganz so grauenhaft sind, wie die core-Teile 
von ARM.


P.S. Ironie- oder Sarkasmus-Tags sind gerade aus.

von Jens E. (surfjenser)


Lesenswert?

Schaulus Tiger schrieb:
> Zum Vergleich: ich hab' mir für die
> GPIO-Intialisierung eine eigene Funktion gebastelt. Damit brauche ich
> pro Pin genau eine Zeile für alles, inkl. Definition vom Signalnamen.

Dann zeig doch mal deine eigene Funktion. Hier wird so oft über die SPL 
hergezogen. Wenn dann aber mal die eigenen Alternativen vorgestellt 
werden, sind sie oft nur im Auge des Erstellers besser les- bzw. 
wartbar.

von Bernd K. (prof7bit)


Lesenswert?

Schaulus Tiger schrieb:
> Woher weiß ich, dass die hier
> zufällig nicht gesetzt werden müssen? Und, müssen sie wirklich nicht?
> Ich dachte, automatische Variablen wie hier "GPIO_InitTypeDef gpioInit;"
> enthalten erstmal zufällige Werte?

Du musst den struct vorher mit 0 initialisieren, hab ich auch auf die 
harte Tour gelernt, siehe hier: 
Beitrag "[arm] Kompileroption -flto bewirkt daß der uart (ungefähr) doppelt so schnell läuft"

Es ist eine wahre Erleichterung diesen ganzen Krampf hinter sich 
gelassen zu haben und direkt mit den Registern zu arbeiten. Man kommt 
schneller voran, es ist einfacher(!), man muss nur die Referenz lesen 
und nicht stattdessen die Referenz plus die andere Referenz plus die 
ganze Sekundärliteratur ohne die man kaum eine Chance hat da 
durchzusteigen plus die Beispielcodes (wenn man Glück hat und überhaupt 
welche existieren), etc.

In der Zeit die man bräuchte um rauszufinden welche obskuren Structs man 
mit welchen Werten füllen und welche obskuren Libraryfunktionen man in 
welcher Reihenfolge aufrufen muss oder irgendwelchen Beispielcode zu 
finden der was ähnliches macht habe ich das eine einzige notwendige 
Unter-Unter-Kapitel im Manual mittels Inhaltsverzeichnis gezielt 
lokalisiert, die Registerdokumentation kurz überflogen, die 3 nötigen 
Bits gesetzt (deren Namen in den CMSIS-Headern übrigens genau denen im 
Manual entsprechen), 2kb unnötigen Bloat-Code gespart, dem Ergebnis beim 
Funktionieren zugeschaut und dabei noch gemütlich einen Kaffee getrunken 
und bin trotz ausgiebiger Kaffeepause immer noch früher fertig. Und hab 
die Nerven geschont.

: Bearbeitet durch User
von Martin K. (martinko)


Lesenswert?

Schaulus Tiger schrieb:
....
> Ich dachte, automatische Variablen wie hier "GPIO_InitTypeDef gpioInit;"
> enthalten erstmal zufällige Werte?
....

Dafür gibt es GPIO_StructInit()

von Schaulus Tiger (Gast)


Lesenswert?

Jens E. schrieb:
> Schaulus Tiger schrieb:
>> Zum Vergleich: ich hab' mir für die
>> GPIO-Intialisierung eine eigene Funktion gebastelt. Damit brauche ich
>> pro Pin genau eine Zeile für alles, inkl. Definition vom Signalnamen.
>
> Dann zeig doch mal deine eigene Funktion. Hier wird so oft über die SPL
> hergezogen. Wenn dann aber mal die eigenen Alternativen vorgestellt
> werden, sind sie oft nur im Auge des Erstellers besser les- bzw.
> wartbar.

das scheint mir doch ein anderes Thema zu sein, außerdem wollte ich das 
schon lange mal fragen. Deshalb:

Beitrag "STM32 gpio_init() -- was haltet ihr von dieser Version?"

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.