Hallo zuammen,
ich habe soeben zum ersten Mal mit CubeIDE eine Konfiguration für ein
Projekt auf dem STM32F103RB(nucleo) erstellt.
In "CubeMX" konfiguriert habe ich zunächst mal:
RCC intern
1x SPI
1x USART
3 LED Output Pins, mit den User Namen "LED1","LED2" und "LED3"
Alles soweit so gut.
Nun möchte ich einfach mal die LED's anschalten.
Soweit ich das verstanden habe, müsste ja der Code dafür in der main.c
in den Block USER3 (while-Loop innerhalb der main-Funktion) eingefügt
werden...oder ?
Aber wie setze ich da den Output Pin der LED1 auf High ?
z.B. LED1_Pin = 1;
funktioniert nicht. Gibt ne Fehlermeldung beim Build:
../Core/Src/main.c:103:13: error: lvalue required as left operand of
assignment
Soweit ich das in der main.h sehen kann, wurden die drei Pins aber
entsprechend benannt:
/* Private defines
-----------------------------------------------------------*/
#define LED1_Pin GPIO_PIN_1
#define LED1_GPIO_Port GPIOC
#define LED2_Pin GPIO_PIN_2
#define LED2_GPIO_Port GPIOC
#define LED3_Pin GPIO_PIN_3
#define LED3_GPIO_Port GPIOC
Ansonsten finde ich noch ne Menge verschachtelter "stm32f1xx_hal" Header
Files, die diverse typedefs oder defines enthalten....da komme ich aber
nicht so recht weiter....
Kann mir da jemand weiterhelfen ?
aduinist schrieb:>>> LED1_Pin = 1;>>>> Das ist kein gültiges C.>> Doch. Aber es ist "Arduinisch"-C.
nein, eher Mbed :) Arduino ist bei gpio prozedural und hat erst den
modernen Kram wie SPI oder I2C als Klasse eingebaut.
Stefan ⛄ F. schrieb:>> LED1_Pin = 1;>> Das ist kein gültiges C.
Doch, das ist grundsätzlich eine völlig korrekte Anweisung in C und
C-artigen Programmiersprachen. Wäre LED1_Pin eine normale Variable, gäbe
es auch kein Problem.
Bei dem STM32CubeMX-Kram ist es jedoch eine Konstante.
Und natürlich wäre es auch möglich, LED1_Pin als Makro zu definieren, so
wie in vielen anderen Ökosystemen üblich, z.B. als
1
#define LED1_Pin *((uint32_t *)0x12345678UL)
In in C++ könnte man die Peripheriezugriffe ggf. auch in überladenen
Operatoren verstecken.
Andreas S. schrieb:> Und natürlich wäre es auch möglich, LED1_Pin als Makro zu definieren, so> wie in vielen anderen Ökosystemen üblich
CubeMX erzeugt Makros.
Auschnitt aus einer main.h:
Andreas S. schrieb:> Doch, das ist grundsätzlich eine völlig korrekte Anweisung in C und> C-artigen Programmiersprachen. Wäre LED1_Pin eine normale Variable, gäbe> es auch kein Problem.
LED1_Pin ist aber eine Zahl. Man kann einer Zahl nichts zuweisen.
Danke für die Rückmeldungen.
Doch doch, ich habe durchaus schon ein bisschen mit C programmiert, bin
aber noch lange nicht routiniert unterwegs oder gar allumfassend
ausgebildet...
Stefan ⛄ F. schrieb:> Das ist eine Menge Lesestoff. Wir sehen uns in 6 Monaten wieder 😀
Ja, genau....! ;o))))
Stefan ⛄ F. schrieb:> Aber vorher solltest du das Reference Manual des Mikrocontrollers lesen,> das ist nämlich die Grundlage dafür. Sonst verstehst du nur Bahnhof.
Bin über einen guten Onlinekurs grundsätzlich schon ein bisschen
vertraut mit dem Coden von Drivern und APIs auf Basis des Reference
Manuals...
Bin nur durch die ganzen "verschachtelten" Header-Files mit all den
Makros, typedefs etc. nicht mehr ganz durchgestiegen, wie ich den Pin
denn nun ansprechen kann...und auch HAL-Treiber hab ich noch nicht
geschrieben...
Stefan ⛄ F. schrieb:> // LED On> HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_SET);> HAL_Delay(500);> // LED Off> HAL_GPIO_WritePin(LED1_GPIO_Port,LED1_Pin,GPIO_PIN_RESET);> HAL_Delay(500);
Aber damit komme ich jetzt schon gut weiter ! Danke !
Genau deswegen verzichte ich lieber auf die HAL. Das Thema
"wiederverwendbarer Code" ist für mich irrelevant, insbesondere wenn
dies bedeutet, dass ich mich mit ST verheiraten muss.
Stefan ⛄ F. schrieb:> Genau deswegen verzichte ich lieber auf die HAL. Das Thema> "wiederverwendbarer Code" ist für mich irrelevant, insbesondere wenn> dies bedeutet, dass ich mich mit ST verheiraten muss.
Ja....so langsam verstehe ich, was Du meinst....das ganze Cube-Ding
macht es dann doch nicht wirklich übersichtlicher oder einfacher....;-/
Dennoch kurz ne Anschlussfrage....
Ich versuche, über den UART MIDI Daten zu senden.
Wenn ich das eben im Moment auch wieder über HAL mache, muss ich ja
entsprechend HAL_UART_Transmit() verwenden.
In einem Probebeispiel mit
char message[30]= "Hello from CubeMX\r\n"; // im Konfigurationsblock
und
HAL_UART_Transmit(&huart1,(uint8_t*)message,30,100); // in main() vor
der while-Schleife
funktioniert das wunderbar (kann ich auch an TX mit meinem Logic
Analyzer entsprechend auslesen).
Jetzt möchte ich aber ja keinen String in Form eines char-Arrays mehr
senden sondern die drei Bytes Daten für MIDI (Statusbyte, Datenbyte1,
Datenbyte2)....
Wenn ich aber nun statt des char message[30] Arrays die drei uint8_t
Variablen
uint8_t status = 0x91;
uint8_t data1 = 0x45;
uint8_t data2 = 0x7f;
definiere, und diese dann entsprechend versenden möchte mit
HAL_UART_Transmit(&huart1,(uint8_t*)status,4,10);
HAL_UART_Transmit(&huart1,(uint8_t*)data1,4,10);
HAL_UART_Transmit(&huart1,(uint8_t*)data2,4,10);
(die Werte 4 für Size und 10 für Timeout habe ich mal willkürlich so
gewählt)
bekomme ich vom Compiler Fehlermeldungen wie:
warning: cast to pointer from integer of different size
[-Wint-to-pointer-cast]
Jetzt habe ich alles mögliche im Kreis ausprobiert, um den Compiler
"zufriedenzustellen".....;-) Aber ich komme nicht auf den Fehler...
Please help !!! ;-)
Und noch ganz allgmein gefragt:
Wenn ich diesen MIDI-Dreierpack an Bytes senden möchte, ist da mein
Ansatz mit den drei getrennten Zeilen richtig ? Oder wie geht das
kompakter?
Mir ist noch nicht klar, ob ich in der MIDI Spezifikation bestimmte
Timeout-Abstände zwischen den einzelnen Bytes halten muss, und wenn ja,
wie groß die sein müssten....
Uli A. schrieb:> char message[30]= "Hello from CubeMX\r\n"; // im Konfigurationsblock>> und>> HAL_UART_Transmit(&huart1,(uint8_t*)message,30,100);
Das ist schon mal Käse, so lange du Text übertragen willst.
So wäre es korrekt:
Uli A. schrieb:> Wenn ich aber nun statt des char message[30] Arrays die drei uint8_t> Variablen>> uint8_t status = 0x91;> uint8_t data1 = 0x45;> uint8_t data2 = 0x7f;
Das ist kein Array, sondern das sind 3 unabhängige Variablen.
Das wäre ein Array:
1
uint8_t data[3];
So ein Array kannst du dann auch am Stück versenden:
Harry L. schrieb:> Das ist kein Array, sondern das sind 3 unabhängige Variablen.
Genau. Hatte ich ja auch geschrieben....;-)
Uli A. schrieb:> statt des char message[30] Arrays die drei uint8_t> Variablen>> uint8_t status = 0x91;> uint8_t data1 = 0x45;> uint8_t data2 = 0x7f;
Aber davon abgesehen.....danke für Deine Erklärungen mit den Arrays,
aber die eigentlichen Fragen hast Du damit nicht berührt....;-)
Uli A. schrieb:> Ja....so langsam verstehe ich, was Du meinst....das ganze Cube-Ding> macht es dann doch nicht wirklich übersichtlicher oder einfacher....;-/
Zumindest die Konfiguration der Taktversorgung wird durch CubeMx
erheblich vereinfacht. Aber wenn man den Dreh einmal heraus hat, ist es
in neuen Projekten nur noch ein bisschen Copy-Paste und ggf. Anpassung.
Und dann gibt es da noch größere Anteile, zum Beispiel die USB Codes.
Die schreibt keiner mal eben schnell neu.
Dennoch ist es mir im Rahmen meines Hobbies lieber, auf die HAL zu
verzichten. Für mich ist das undurchschaubarer Code der übrigens auch
einige male fehlerhaft war. Ohne Fremde Hilfe (aus diesem Forum) hätte
ich die Fehler wahrscheinlich nie finden und beheben können.
Ich verstehe aber warum die das so strukturiert haben. Für jeden µC wird
nur genau der Teil ausgetauscht, der nötig ist. Es geht um maximale
Wiederverwendbarkeit von Code. Man bezahlt mit Bedarf an schnelleren und
größeren Mikrocontrollern und einer starken Bindung an die Marke. Das
ist nicht unbedingt schlimm, wenn man weiß, worauf man sich einlässt.
Danke Stefan für Deine Ausführungen...klar, das war natürlich auch mein
Beweggrund als Anfänger, mich für CubeIDE zu entscheiden - es ist
verlockend, eine vollintegrierte Arbeitsumgebung zu haben, und beim
anfänglichen Beschäftigen mit dem Thema erschien mir die schier
unübersichtliche Zahl an Arbeitsschritten alleine bei der Konfiguration
der IDEs und der Compiler - also BEVOR man überhaupt anfangen kann zu
arbeiten ;-) - als echter Abtörner....und dennoch wollte ich ja für mein
Projekt von Arduino weg zu einer etwas "professionelleren"
Herangehensweise und Plattform.
Ich denke nach meinen Einblicken der letzten Monate schon noch, dass
STM32 insgesamt ein gutes System für meine Art von Anwendungen liefert.
Aber man muss natürlich immer auch bestimmte spezifische Schwachstellen
kennen- und einschätzen lernen...das ist ja auch bei jeder anderen Hard-
und Software so....und da bin ich gerade angekommen...
Nebenbei gefragt: Was ist denn Deine aktuelle Entwicklungsumgebung, die
Dich gut und effizient arbeiten lässt, ohne eine "Bindung an die Marke"
ST ?
Und nochmal kurz zum Thema....könnest Du mir vielleicht noch mal zu
meiner UART/MIDI Übertragungsfrage weiterhelfen ?
Ein einfaches Beispiel für die Übertragung eines "MIDI-Blocks" über den
UART mit HAL_UART_Transmit() würde mir schon reichen...;-)
LG
Uli A. schrieb:> Was ist denn Deine aktuelle Entwicklungsumgebung, die> Dich gut und effizient arbeiten lässt, ohne eine "Bindung an die Marke"> ST ?
Ich benutze die Cube IDE, weil sie kostenlos ist.
Davor hatte ich die "System Workbench for STM32" verwendet, als es die
Cube IDE noch nicht gab. Die ersten Versionen der Cube IDE konnten noch
keine Projekte ohne HAL erzeugen, das ist aber inzwischen möglich.
Beide IDE's binden mich an ST. Dafür ist da aber alles drin was man
braucht. Ich habe einmal versucht mein heiß geliebtes Qt Creator zu
benutzen, bin da aber am Debugger gescheitert.
Letztendlich ist die IDE nur ein Werkzeug. Für andere Controller benutze
ich andere IDE. Die Idee "eine IDE für alles" ist sowieso langfristig
nicht haltbar.
> Und nochmal kurz zum Thema....könnest Du mir vielleicht noch mal zu> meiner UART/MIDI Übertragungsfrage weiterhelfen ?
Nein, das ist nicht mein Fachbereich.
> Ein einfaches Beispiel ... mit HAL_UART_Transmit()
Das erst recht nicht. Ich habe die Hal nur für einen LED Blinker und ein
"Hello World!" über USB benutzt. Also nur ganz kurze
Anfänger-Experimente. Und dann habe ich beschlossen, sie nicht mehr zu
verwenden.
Stefan ⛄ F. schrieb:> Die ersten Versionen der Cube IDE konnten noch> keine Projekte ohne HAL erzeugen, das ist aber inzwischen möglich.
Interessant.....wie kann ich das einstellen ?
Bedenke dass die CMSIS header für alle ARM Controller existieren, aber
die Makros SET_BIT(), CLEAR_BIT(), usw. hat ST hinzugefügt. Man kann sie
vermutlich für andere Controller ggf. kopieren.
Stefan ⛄ F. schrieb:> Da verwechselst du was. Diese Anleitung ist für die alte SPL, die war> mal vor der HAL aktuell.
Verstehe. Danke für die Richtigstellung...
Stefan ⛄ F. schrieb:> Die Hal baut auf CMSIS-Core auf. Ob die alte SPL auch darauf aufbaut,> weiß ich nicht.
Hab mir die Beschreibung im Dokument UM1850 nochmal ein bisschen
angesehen....da ist ja neben HAL auch alternativ die abgespeckte
Lowlayer(LL)-Variante beschrieben....hast Du damit schon gearbeitet ?
Und wenn ja, weißt Du, ob es eine Möglichkeit gibt, Cube so zu
konfigurieren, dass der generierte Code bzw. die generierten Header- und
C-Files nicht auf HAL aufgebaut werden sondern auf LL ?
Das könnte ja ggfs. ein interessanter Mittelweg sein...
Uli A. schrieb:> Stefan ⛄ F. schrieb:>> Die Hal baut auf CMSIS-Core auf. Ob die alte SPL auch darauf aufbaut,>> weiß ich nicht.>> Hab mir die Beschreibung im Dokument UM1850 nochmal ein bisschen> angesehen....da ist ja neben HAL auch alternativ die abgespeckte> Lowlayer(LL)-Variante beschrieben....hast Du damit schon gearbeitet ?>> Und wenn ja, weißt Du, ob es eine Möglichkeit gibt, Cube so zu> konfigurieren, dass der generierte Code bzw. die generierten Header- und> C-Files nicht auf HAL aufgebaut werden sondern auf LL ?>> Das könnte ja ggfs. ein interessanter Mittelweg sein...
Wenn du an HAL scheiterst, wirst du dir an LL erst Recht die Zähne
ausbeissen.
Sorry, aber, wenn ich deinen Code von Oben sehe, und den Thread
verfolge, verfestigt sich bei mir der Eindruck, daß weder HAL noch LL
oder CMSIS dein Problem ist, sondern der Mangel an grundsätzliche
C-Kenntnissen.
Solange das so ist, wirst du mit KEINEM Framework erfolgreich sein.
Uli A. schrieb:> Und wenn ja, weißt Du, ob es eine Möglichkeit gibt, Cube so zu> konfigurieren, dass der generierte Code bzw. die generierten Header- und> C-Files nicht auf HAL aufgebaut werden sondern auf LL ?
Meinst Du das?
STM32CubeMX => Project Manager => Advanced Settings => im "Driver
Selector" von HAL auf LL umstellen
Scheint aber nicht für alle Peripherals möglich zu sein, da bei einem
gerade geöffneten Beispiel für einen H7 stellenweise nur "HAL" als
einzige Option möglich ist.
Gruß,
Michael
> mit KEINEM Framework erfolgreich sein
Er kann ja "bare metal" mit den in der CMSIS verfuegbaren
Headerfiles schon mal anfangen.
Vorteil: Er braucht "nur" das Referenzmanual des Controllers
und das ARM-Referenzmanual lesen (und verstehen).
Fuer GPIOs, Timer, SPI, I2C, ADCs und DACs reicht das ja allemal.
Wenn etwas nicht wie gewuenscht funktioniert, kann er sich
Details des Registerumgangs in den Beispielen der alten
STM32 Standardlibrary ansehen.
Was landet wo in welcher Reihenfolge, und welche Bedingungen
werden geprueft.
... schrieb:> Er kann ja "bare metal" mit den in der CMSIS verfuegbaren> Headerfiles schon mal anfangen.> Vorteil: Er braucht "nur" das Referenzmanual des Controllers> und das ARM-Referenzmanual lesen (und verstehen).> Fuer GPIOs, Timer, SPI, I2C, ADCs und DACs reicht das ja allemal.>> Wenn etwas nicht wie gewuenscht funktioniert, kann er sich> Details des Registerumgangs in den Beispielen der alten> STM32 Standardlibrary ansehen.> Was landet wo in welcher Reihenfolge, und welche Bedingungen> werden geprueft.
Ja, so in die Richtung denke ich auch gerade...ich muss halt mal einen
möglichst sinnvollen Weg einschlagen, um mein Projekt irgendwann in
realisierbare Bahnen zu bekommen....und ich habe ja schon mit Baremetal
Programmierung begonnen....dachte nur, ich könnte das etwas einfacher
kombinieren mit einer Art Grundsetup in Cube - aber das entpuppt sich ja
eher als nur anders geartetes aber eben nicht gerade kleineres
Lernfeld...
Harry L. schrieb:> Wenn du an HAL scheiterst, wirst du dir an LL erst Recht die Zähne> ausbeissen.
Warum siehst Du das so ? Kannst Du mir das erklären ?
Kommentare wie
Harry L. schrieb:> Solange das so ist, wirst du mit KEINEM Framework erfolgreich sein.
sind wenig hilfreich, wenn sie auch in der Sache (noch viele
Wissenslücken bei mir) teilweise zutreffend sind.
Michael F. schrieb:> Meinst Du das?>> STM32CubeMX => Project Manager => Advanced Settings => im "Driver> Selector" von HAL auf LL umstellen
Ja, genau...danke, hatte ich noch nicht gefunden.
Michael F. schrieb:> Scheint aber nicht für alle Peripherals möglich zu sein, da bei einem> gerade geöffneten Beispiel für einen H7 stellenweise nur "HAL" als> einzige Option möglich ist.
Hmmm....das kann ich jetzt bei mir nicht feststellen...bei welcher
Einstellung genau ist bei Dir nur HAL einstellbar ?
Zumindest klappt bei mir alles bisher ausprobierte, wie
GPIO
RCC
USART
SPI
I2C
....
Sind bei mir alle auf LL umstellbar - sowohl als ganze Kategorie (z.B.
USART) als auch die einzelnen Items unabhängig voneinander (z.B. nur
USART1 als LL und USART2 auf HAL
Uli A. schrieb:> Harry L. schrieb:>> Wenn du an HAL scheiterst, wirst du dir an LL erst Recht die Zähne>> ausbeissen.>> Warum siehst Du das so ? Kannst Du mir das erklären ?>
Weil der Umgang mit LL sehr viel anspruchsvoller als HAL ist, und du
nicht einmal sattelfest bei der Nutzung von Pointern und Strukturen
bist.
> Kommentare wie>> Harry L. schrieb:>> Solange das so ist, wirst du mit KEINEM Framework erfolgreich sein.>> sind wenig hilfreich, wenn sie auch in der Sache (noch viele> Wissenslücken bei mir) teilweise zutreffend sind.
Du magst das ja als wenig hilfreich empfinden, aber C ist nun mal die
Grundvoraussetzung um mit HAL & Co. überhaupt was Sinnvolles
anzustellen, und bei dir ist nunmal nicht HAL das was dich ausbremst.
Das kannst du nicht überspringen - ob dir das gefällt oder nicht.
Uli A. schrieb:> Hmmm....das kann ich jetzt bei mir nicht feststellen...bei welcher> Einstellung genau ist bei Dir nur HAL einstellbar ?
Mit einem STM32H753 als Target ist z.B. bei ETH, SDMMC oder FMC nur HAL
verfügbar. Bei den von Dir genannten Peripherals ist sowohl HAL als auch
LL möglich.
Gruß,
Michael
Uli A. schrieb:> Hab mir die Beschreibung im Dokument UM1850 nochmal ein bisschen> angesehen....da ist ja neben HAL auch alternativ die abgespeckte> Lowlayer(LL)-Variante beschrieben....hast Du damit schon gearbeitet ?
Nein. Hier wurde mal diskutiert, dass sie schlanker und hardwarenäher
sei, allerdings nicht für alle STM32 Modelle verfügbar.
Uli A. schrieb:> Und wenn ja, weißt Du, ob es eine Möglichkeit gibt, Cube so zu> konfigurieren, dass der generierte Code bzw. die generierten Header- und> C-Files nicht auf HAL aufgebaut werden sondern auf LL ?
Bei den Modellen wo es geht, bietet die IDE das irgendwo in diesem
Code-Generator Dialog an.
Wenn du dich mal durchs Datenblatt und Referenzmanual gearbeitet
haettest, und die Register mit Hilfe des Headerfiles gesetzt
und geprueft haettest, waere die Initialisierung und Ansteuerung
von Controllertaktsystem und GPIOs schon lange fertig und erledigt.
Statt dessen wird wieder nur ueber weitere "Hilfsmittel" diskutiert.
Das wird dich kaum weiterbringen...