ich habe hier ein Platinchen mit einem STM32G071CB, externem Quarz, Tastern, LEDs und weiterer Peripherie. Um zu testen, ob der Microcontroller überhaupt läuft, habe ich ein kleines Programm geschrieben, das einen Taster auswertet und davon abhängig eine LED angesteuert - er läuft.
Nun wollte ich eine PWM generieren, habe dafür PA8 auf TIM1_CH1 und PA2 auf TIM15_CH1 konfiguriert. Bei beiden (und bei TIM16) haben ich die Clock Source auf "Internal Clock" gestellt, "Counter Period" auf 10000 gestellt und "auto-reload preload" auf "Enable". Ich bekomme aber keine PWM heraus. Daraufhin bin ich zur Problemanalyse direkt an die Wurzel gegangen und mir den Zählerwert der Timer angeschaut. Dazu das Programm geschrieben, gestartet, angehalten und im reiter SFRs den Wert vom Register CNT angeschaut. Der ist immer 0, egal welcher Timer. Damit ist für mich klar, warum da keine PWM herauskommt, aber noch nicht, warum der Zähler sich nicht verändert. Um den externen Quarz auszuschließen, habe ich wieder auf die interne Taktquelle umgestellt, aber keine Änderung. Daher meine Frage, woran könnte das liegen?
Anbei noch die Bilder von der Konfiguration. Wenn noch weitere Informationen gebraucht werden, gern erfragen.
Du hast nur im CubeMX konfiguriert aber keinen Code geschrieben? Du musst den Timer auch starten. Die Funktion heißt HAL_TIM_Base_Start oder so ähnlich... Normalerweise in die main(), vor die Endlosschleife.
Einerseits hat Dein Timer den Startschuss nicht gehört (Enable), andererseits muss man, soweit ich mich erinnern kann, vermutlich auch die Ausgänge und Kanäle einschalten (Enable). Du wirst Dich leider mit den Registern Deines Timers beschäftigen und dort im Reference Manual nachschauen müssen, wo das ist und was das ist. Alternativ kann man das bestimmt auch über das Datenblatt mit den HAL- und LL-Funktionen herausfinden und entsprechend einschalten.
Alternativ kann man das
bestimmt auch über das Datenblatt mit den HAL- und LL-Funktionen
herausfinden und entsprechend einschalten
Ja!
Man kann heutztage praktisch alle Register eines Controllers mittels
HAL-Lib- oder LL-Lib-Funktionen und -Makros steuern ohne jemals ein
Controller-Register genannt oder adressiert haben zu müssen. Und das
in den meisten Fällen ohne Zeitverlust im Maschinencode. Ausgenommen
möglicherweise HAL-Aufrufe in denen komplexe Abläufe realisiert
sind.
Da hat wohl einer eine Registerallergie oder -aversion – keine schöne Sache. Wie ich bereits sagte, man sollte sich so früh wie möglich mit dem passenden Reference Manual anfreunden und dort stehen nun mal die Register, ob es einem passt oder nicht.
Man kann heutztage praktisch alle Register eines Controllers mittels
HAL-Lib- oder LL-Lib-Funktionen und -Makros steuern ohne jemals ein
Controller-Register genannt oder adressiert haben zu müssen. Und das
in den meisten Fällen ohne Zeitverlust im Maschinencode. Ausgenommen
möglicherweise HAL-Aufrufe in denen komplexe Abläufe realisiert
sind.
Hört sich nach Arduino-Vorgehensweise an. Die Strategie „Bloß keine Register in meinem Leben” wird eines Tages nicht aufgehen und voll in die Hose gehen.
Hört sich nach "keiner Ahnung" an was im HAL- und LL-Gefüge
gemacht wird bzw. was damit zu tun hat.
Bei Arduino instanziert man Klassen und ruft deren Methoden auf.
Das hat mit Programmierung im Sinne von HAL und LL nicht im
Entferntesten etwas zu tun. Also lieber mal still sein wenn
man es nicht besser weiss.
Das macht der generierte Code automatisch. Man muss den Timer lediglich
noch starten.
Das Durchgeklickte und der daraus generierte Code macht eben leider nicht alles automatisch – deswegen erwähne ich es auch. Das kann von µC zu µC und auch von Timer zu Timer innerhalb eines µControllers variieren – und genau deswegen sollte man sich in das passende Reference Manual vertiefen, um das herausfinden zu können.
Das Durchgeklickte und der daraus generierte Code macht eben leider
nicht alles automatisch
Und das ist auch seitens STM so beabsichtigt. Wer weiss was
der User genau machen will - sicherlich nicht bei einer
Vielzahl von initialisierten Timern einfach mal alles starten
was so da ist und Unheil anrichten könnte.
Dafür gibt es mundgerecht in den HAL- und LL-Libs einfache
Aufrufe - wiederum ohne Register-Adressen oder -Namen sondern
als sinnbringende Makros. Siehe Anhang.
Dafür gibt es mundgerecht in den HAL- und LL-Libs einfache
Aufrufe - wiederum ohne Register-Adressen oder -Namen sondern
als sinnbringende Makros. Siehe Anhang.
Dafür gibt es vor allem das Reference Manual – wo man zuerst nachschauen und nachforschen sollte, auch als Registerallergiker. Danach kann man sich dann den passenden Weg für einen aussuchen – es gibt was für Registerallergiker und auch etwas für Leute, die weniger oder gar keine Registerallergie haben. Wie gewohnt – ohne Fleiß kein Preis.
Dafür gibt es mundgerecht in den HAL- und LL-Libs einfache
Aufrufe - wiederum ohne Register-Adressen oder -Namen sondern
als sinnbringende Makros. Siehe Anhang.
Dafür gibt es vor allem das Reference Manual – wo man zuerst nachschauen
und nachforschen sollte, auch als Registerallergiker. Danach kann man
sich dann den passenden Weg für einen aussuchen – es gibt was für
Registerallergiker und auch etwas für Leute, die weniger oder gar keine
Registerallergie haben. Wie gewohnt – ohne Fleiß kein Preis.
Und jedesmal das Rad neu erfinden?
Am Besten noch mit den absoluten Speicheradressen arbeiten. Wozu man sich wohl sowas wie Makros und Libs ausgedacht hat.
Das Reference Manual hat seine Daseinsberechtigung - HAL- und LL-Libs erleichtern das Leben.
Selbstverständlich nicht – aber einen auf Deutsch geschriebenen Text muss man vorher auch richtig verstehen können, was ich explizit vor so einem Reference Manual empfehle, dann erübrigen sich solche und ähnliche unsinnigen Unterstellungen.
Am Besten noch mit den absoluten Speicheradressen arbeiten. Wozu man
sich wohl sowas wie Makros und Libs ausgedacht hat.
Das Reference Manual hat seine Daseinsberechtigung - HAL- und LL-Libs
erleichtern das Leben.
Wenn Du meine Aussage verstanden hättest, bräuchtest Du solche absurden Sachen nicht zu schreiben.
Die knappe Doku der HAL alleine reicht nicht. Nur zusammen mit dem Reference Manual erfährt man, was die einzelnen HW Komponenten können, und wie sie zusammen spielen ( bzw. welche Kombinationen nicht gehen ).
Ohne Reference Manual kommt es schnell dazu, dass man Funktionalität erwartet, die nicht vorhanden ist. Gleiches Thema wie bei Arduino.
Die HAL vereinheitlicht die Nutzung der STM32, und erleichtert damit die Portierung von Code auf andere STM32 Modelle.
Selbstverständlich nicht – aber einen auf Deutsch geschriebenen Text
muss man vorher auch richtig verstehen können, was ich explizit vor so
einem Reference Manual empfehle, dann erübrigen sich solche und ähnliche
unsinnigen Unterstellungen.
Welchen meinst du?
Für mich klingen deine Post mach "Ne! Bloß keine Libs benutzen!" (inkl. Arduino-Bashing).
Wenn Du meine Aussage verstanden hättest, bräuchtest Du solche absurden
Sachen nicht zu schreiben.
Wenche du auch immer meinst.
Andere haben sie wohl auchb "falsch" verstanden...
Ob das dann wirklich an denjenigen liegt, die deine Posts kommentiert haben?
Welchen meinst du?
Für mich klingen deine Post mach "Ne! Bloß keine Libs benutzen!" (inkl.
Arduino-Bashing).
Dein Klingen in den Ohren ist leider falsch. Das ist nur eine weitere Bestätigung, dass Du meine auf Deutsch geschriebene Aussage nicht verstanden hast. Und bitte nicht vergessen: immer alles, was der Siliziumgott gegeben hat, auch schön weiternutzen, aber in der richtigen Priorisierung und Reihenfolge.
Dein Klingen in den Ohren ist leider falsch. Das ist nur eine weitere
Bestätigung, dass Du meine auf Deutsch geschriebene Aussage nicht
verstanden hast. Und bitte nicht vergessen: immer alles, was der
Siliziumgott gegeben hat, auch schön weiternutzen, aber in der richtigen
Priorisierung und Reihenfolge.
Post, der unter Kategorie "Du hast Recht, und ich meine Ruhe." fallen.
Ganz schön arrogant.
Nochmal an alle Manuals-, Registerphobiker oder -allergiker: ohne die Reference Manuals (ja, es gibt quasi für jeden µC eins) lesen, verstehen und gebrauchen wird man sich in der STM32-Welt nur peripher und oberflächlich auskennen und sich dort gewissermaßen wie auf einem Arduinotrip befinden oder auf so einer Art Welle schwimmen. Die Kenntnis der Hardware ist das A und O, mit weichgespülten Methoden wie „Ach, bitte bloß keine Register oder Datenblätter!” aus der Arduinojüngerszene wird man hier immer im Sandkasten bleiben – aber in gewisser Weise finde ich das auch gerecht und gut so, dass es so ist.
Danke erst einmal für die Antworten. Der Timer läuft nun, die PWM wird generiert. Es fehlte tatsächlich der Befehl zum Starten des Timers.
1
HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);
Vor einigen Jahren hatte ich schon mal einen STM32 programmiert und auch PWMs generiert, aber so genau konnte ich mich nicht mehr dran erinnern und den Teil habe ich beim Vergleich mit dem alten Projekt einfach übersehen.
Was hindert dich daran, dein *.ioc File zu posten? Ist deine
Kreation so geheim dass man sie nicht nachvollziehen darf?
Ein komplettes Projekt (ohne *.obj und sonstigen Debug-Ballast)
wäre noch hilfreicher ...
Mich hindert gar nichts daran, die ioc-Datei oder das ganze Projekt zu posten, das ist abgesehen von dem Timer sowieso leer. Ich hielt es nur für sinnvoller, Screenshots der relevanten Konfiguration zu posten, weil da jeder direkt reinschauen kann, selbst ohne installierte IDE. Deshalb schrieb ich doch, wenn noch etwas benötigt wird, einfach fragen. Aber jetzt geht es ja.
Dafür gibt es mundgerecht in den HAL- und LL-Libs einfache
Aufrufe - wiederum ohne Register-Adressen oder -Namen sondern
als sinnbringende Makros. Siehe Anhang.
Danke, das war ein sehr guter Hinweis, denn mir war nicht bekannt, dass es neben den HAL- auch die LL-Bibliotheken gibt. Bei Recherchen im Netz hatte ich immer nur gefunden, dass ST heute nur noch HAL vorsieht und die LL-Bibliotheken seit Jahren nicht mehr weiterentwickelt werden. Aus diesem Grund habe ich ST-Mikrocontroller bisher kaum eingesetzt, weil der ganze HAL-Mist schnarchlangsam ist und ich nie verstehe, was ich da wirklich gerade mache. Normalerweise programmiere ich deshalb mit direkten Registerzugriffen. Die LL-Bibliotheken sehen aber ziemlich übersichtlich aus, damit lässt sich arbeiten.
Und die Diskussion hier noch ein wenig anzuheizen: Wenn ich ein Hardwaremodul richtig verwenden möchte, muss ich genau wissen, wie es funktioniert und jeden Teil konfigurieren können. Das Manual erklärt, wie das Modul aufgebaut ist, was es kann und welchen Einfluss Register haben bzw. welche Informationen sie enthalten. Die Erklärung enthält keinerlei Bezug zu den Funktionen in den Bibliotheken. Das Einfachste ist daher, direkt auf die Register zuzugreifen. Andernfalls muss ich mir erst anschauen, was ich mit den Registern tun muss und dann selbst in den Bibliotheken stöbern, welche Funktion das tut, was ich möchte. Das ist schon mal aufwendiger und im schlimmsten Fall langsamer. Ohne eigene Dokumentation ist der Programmcode mit den vorgegebenen Funktionen natürlich leichter verständlich, was gerade dann nützlich ist, wenn mehrere an einem Projekt arbeiten. Aber gut dokumentiert ist der Code mit direkten Registerzugriffen ebenfalls gut verständlich und sogar besser bearbeitbar, weil wieder eine direkte Arbeit mit dem Manual möglich ist. Ich muss nicht raten oder lange nachschauen, wie nun die andere Funktion heißt, die ich jetzt brauche. Und wer ein wenig mit einem Controller gearbeitet hat und die Module kennt, versteht auch den Code mit direkten Zugriffen.
Man kann heutztage praktisch alle Register eines Controllers mittels
HAL-Lib- oder LL-Lib-Funktionen und -Makros steuern ohne jemals ein
Controller-Register genannt oder adressiert haben zu müssen.
Ja. Wenn aber irgendein verschissenes nötiges Bit noch nicht gesetzt ist, was dann? Dann muß man erstmal herausfinden, welches das ist. Dazu muß man halt die Hardware kennen, dann kann man das herausfinden. Klappert man "einfach" im Debugger alle relevanten Register ab. Das können schon mal eine ganze Menge sein und man muss die Zusammenhänge der Hardware verstehen, um überhaupt erstmal rauszufinden, welche das alles sein könnten.
Kennt man das Bit erstmal, ist es dann nur noch mittelmäßiger Aufwand, die zuständige HAL-Routine zu ermitteln. Und die dann aufzurufen, kostet am Ende tatsächlich nur noch ein kühles Arschrunzeln.
Das Problem ist halt: diese verschissene HAL sagt dir an keine Stelle, dass dieses Bit von der Initialisierung nicht mit abgedeckt ist, sondern zur Laufzeit explizit zusätzlich zur generierten Initialisierung gesetzt werden muss, damit die Sache läuft.
Und (u.a. deswegen) ist sowas wie die HAL ein ziemlicher Berg SCHEISSE.
Normalerweise programmiere ich deshalb mit
direkten Registerzugriffen. Die LL-Bibliotheken sehen aber ziemlich
übersichtlich aus, damit lässt sich arbeiten.
Mit den LL-Befehlen ist man de facto auf der Registerebene und die nutze ich zu 90-95% auch, der Rest sind eigene Macros, die ich dann ähnlich wie die LL-Macros gestaltet habe und auch so nutzen kann, weil die LL-Macros nicht immer alles abdecken, manchmal aber auch fehlerhaft oder unsinnig geschrieben sein können – man sollte also wenigstens einmal mit der Maus in der IDE nachschauen, wie die LL-Macros aussehen und was sie tatsächlich so im Hintergrund tun. Manchmal offenbaren sie eben die Unfähigkeit der Personen, die diese für die Allgemeinheit geschrieben haben – diese Unfähigkeit offenbart sich beispielsweise sehr gut in der RTC-Domain (Real-Time-Clock). Um die LL für die jeweilige Peripherie richtig nutzen zu können, muss man das auch explizit so für die Codegenerierung umschalten – meistens muss man dabei wenigstens eine Peripherie auf HAL-Ebene lassen, z.B. die RCC-Domain (Screenshot im Anhang), damit die aufgeblähte Moloch-IDE später beim Build fehlerfrei funktioniert (es war zumindest in den früheren IDE-Versionen so fehlerbehaftet konstruiert).
So, und nun dürfen sich hier im Thread die Reference-Manual-Verweigerer und Registerphobiker wieder zusammentun, sich gegenseitig stärken und dazu ermuntern, der Welt zu zeigen, wie man die STM32 – ohne jemals den Registeraufbau im Reference Manual gesehen zu haben – benutzen kann. Manchmal hilft auch hoffen und beten, dass das, was da im HAL so für die breite Masse zusammengedichtet wurde, auch immer ordnungsgemäß funktioniert. Und falls der Sand im Sandkasten nicht mehr so schön ist, darf Papi neuen holen und den verbrauchten austauschen, damit es wieder Spaß macht, sich eine ordentliche Sandburg zu bauen oder damit einfach auch mal zu bewerfen oder zu zeigen, wer der größte König im Sandkasten ist. Hält alles übrigens maximal so lange bis der nächste Regen kommt.