Hallo zusammen, 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.
Hallo, hast Du denn auch einen Wert ins ARR Register geschrieben? Ist das zugehörige CEN Bit gesetzt? Jogibär PS: Code ist mir lieber als diese klikibunti Bilder.
Terence S. schrieb: > Wenn noch weitere > Informationen gebraucht werden, gern erfragen. 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 ...
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.
:
Bearbeitet durch User
Terence S. schrieb: > Daher meine Frage, woran könnte das liegen? 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.
Gregor J. schrieb: > Du wirst Dich leider mit > den Registern Deines Timers beschäftigen und dort im Reference Manual > nachschauen müssen Nein! Gregor J. schrieb: > 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.
Wastl schrieb: > Nein! 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.
:
Bearbeitet durch User
Gregor J. schrieb: > Hört sich nach Arduino-Vorgehensweise an. 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.
Wastl schrieb: > Hört sich nach "keiner Ahnung" Ja, das hört sich tatsächlich auch nach „keine Ahnung” an, wenn man Register beim STM32 völlig meiden und verbannen will.
:
Bearbeitet durch User
Gregor J. schrieb: > oweit ich mich erinnern kann, vermutlich auch > die Ausgänge und Kanäle einschalten (Enable) Das macht der generierte Code automatisch. Man muss den Timer lediglich noch starten.
Niklas G. schrieb: > 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.
:
Bearbeitet durch User
Gregor J. schrieb: > 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.
Wastl schrieb: > 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.
Wastl schrieb: > 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. Die auch wunderbar dokumentiert sind. Gregor J. schrieb: > 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.
Rahul D. schrieb: > Und jedesmal das Rad neu erfinden? 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.
:
Bearbeitet durch User
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.
Gregor J. schrieb: > 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). Gregor J. schrieb: > 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?
Rahul D. schrieb: > 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.
Gregor J. schrieb: > 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.
:
Bearbeitet durch User
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. Wastl schrieb: > 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. Wastl schrieb: > 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.
Wastl schrieb: > 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.
Terence S. schrieb: > 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.
@Gregor J.: Danke, damit erscheint der STM32 immer besser sinnvoll benutzbar zu sein. Das alles hat mir wirklich sehr weitergeholfen.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.