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
>> RCC_AHB1PeriphClockCmd(GPIOA, ENABLE);
ich glaube GPIOA ist falsch. Da gibt es was in die Richtung
AHB1Periph_GPIOA oder so. Musste de mal nachgucken.
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?
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.
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?
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.
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_InitTypeDefgpioInit;
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.
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.
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.
Schaulus Tiger schrieb:
....
> Ich dachte, automatische Variablen wie hier "GPIO_InitTypeDef gpioInit;"> enthalten erstmal zufällige Werte?
....
Dafür gibt es GPIO_StructInit()
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?"