STM32F407 Mit diesem Code habe ich herausgefunden, dass die Dauer eines Ticks 1/16000000 == 62,5 ns beträgt #include "main.h" uint16_t delay_count=0; void SysTick_Handler(void) { if(delay_count>0) { delay_count--; } } void delay_ms(uint16_t delay_temp) { delay_count=delay_temp; while(delay_count) { } } int main(void) { RCC->AHB1ENR|=RCC_AHB1ENR_GPIODEN; GPIOD->MODER|=1<<(2*12); SysTick_Config(16000000); while (1) { GPIOD->ODR^=(1<<12); delay_ms(5); GPIOD->ODR^=(1<<12); delay_ms(5); } } Das Intervall zwischen den LED-Blitzen beträgt genau 5 Sekunden. Der SysTick-Timer zählt also in genau einer Sekunde von 16000000 auf Null. Bei CubeMX habe ich die einzige Stelle gefunden, wo 16 Megahertz steht. Dies ist SYSCLK. Aber selbst wenn ich SYSCLK mit einem externen Quarz auf 25 MHz ändere, ändert sich die Blinkfrequenz der LED nicht, mit dem gleichen Code SysTick_Config (16000000);
:
Bearbeitet durch User
Für den Systick ist der Systick-Timer zuständig. Ein extra 24Bit-Countdown-Timer beim M3 und M4. In Deine Clock-Configuration nutzt Du den internen 16Mhz RC-Schwingkreis, da ist es egal was für einen Quarz Du anschließt, der wird nicht benutzt. Genaueres findest Du in den Datenblättern zu Deinem Controller
Max M. schrieb: > Welcher Timer ist für die Dauer eines Ticks im SysTick verantwortlich? Das Systick ist ein Timer. Normalerweise stellt man den aber auf sinnvollers wie z.B. 1ms als intervall. System timer: The system timer (SysTick) is a 24-bit count-down timer. Use this as a Real Time Operating System (RTOS) tick timer or as a simple counter... Kap. "4.5 SysTick timer (STK)" - https://www.st.com/resource/en/programming_manual/pm0214-stm32-cortexm4-mcus-and-mpus-programming-manual-stmicroelectronics.pdf Kap. "6.2 Clocks" - https://www.st.com/resource/en/reference_manual/rm0090-stm32f405415-stm32f407417-stm32f427437-and-stm32f429439-advanced-armbased-32bit-mcus-stmicroelectronics.pdf
Ich habe die Antwort auf das, was ich unten geschrieben habe gefunden. So sollte es sein. Die externe Taktung erfolgt mit einer Frequenz, die 8-mal kleiner ist als die Prozessorfrequenz. ------------------------ Ok, die Dauer eines Ticks wird in den SysTick-Registern eingestellt. Das CLKSOURCE-Bit im SysTick Control and Status Register bestimmt, welche Taktquelle verwendet werden soll. 0 - externe Taktung des Referenzoszillators, 1 - von der Prozessorfrequenz. Aus irgendeinem Grund beträgt die Frequenz, die ich mit externer Taktung erhalte, 2 Megahertz, obwohl ich HSE bei 25 Megahertz haben sollte. Ich überprüfe die Dauer eines Ticks mit dem Code aus der ersten Nachricht. Einrichten von SysTick-Registern: SysTick->LOAD = (uint32_t)(2000000-1); SysTick->VAL = 0UL; SysTick->CTRL&= ~(1UL<<SysTick_CTRL_CLKSOURCE_Pos);//0-externe Taktung SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;
:
Bearbeitet durch User
Max M. schrieb: > STM32F407 Wo ist der drauf? Selbstgebautes Board oder Discovery oder Nucleo? Alles sehr verschwommen, solltest erst mal darstellen wie du zu den 25MHz kommen willst. Dann noch bitte: >>Wichtige Regeln - erst lesen, dann posten! >> ........ >> Formatierung (mehr Informationen...) [ c ]C-Code[ /c ]
Es geht um den Abstand, nicht die Dauer, oder?
Abstand ist Ticksdauer + Unterbrechungszeit(Interrupt).
Ich brauchte die Dauer eines Ticks. Nicht Abstand.
STM32F407VGT6
>>erst lesen, dann posten!
Ich habe gelesen, ich konnte es selbst nicht herausfinden, ihr habt mir
geholfen.
:
Bearbeitet durch User
Max M. schrieb: > Ich brauchte die Dauer eines Ticks. Nicht Abstand. beo bachta schrieb: > Wo ist der drauf? Selbstgebautes Board oder Discovery oder > Nucleo? Alles sehr verschwommen, solltest erst mal darstellen > wie du zu den 25MHz kommen willst.
> Wo ist der drauf? Selbstgebautes Board oder Discovery oder Ich habe STM32F407VGT6. Das ist Discovery Board. > wie du zu den 25MHz kommen willst. Ich dachte, die externe Taktquelle für SysTick sei HSE, und die HSE auf meinem Discovery Board beträgt 25 MHz. Es stellte sich heraus, dass dem nicht so ist. Die externe Taktquelle für SysTick hat eine Frequenz, die achtmal niedriger ist als die Prozessorfrequenz. Jetzt ist mir alles klar. Ich wusste nicht, wo die Dauer eines Ticks für den SysTick-Timer eingestellt ist. > Ich brauchte die Dauer eines Ticks. Nicht Abstand. Abstand zwischen was und was?) Es scheint mir, dass sie die Zeit meinten, für die der Zähler in SysTick Null erreicht + Interrupt-Zeit. Ich brauchte nur die Dauer eines Ticks. Diese Zeit wird im CLKSOURCE-Bit im SysTick Control and Status Register gesetzt.
Max M. schrieb: > Ich habe STM32F407VGT6. Das ist Discovery Board. Auf dem Discovery Board gibt es keine 25 MHz. Man kann im Schaltplan (RTFM) und auf dem Board sehen dass es einen 8MHz Quarz gibt.
Max M. schrieb: > Die externe Taktquelle > für SysTick hat eine Frequenz, die achtmal niedriger ist als die > Prozessorfrequenz. Du verwendest ja CubeMX. Warum lässt du dir nicht den Code für die Initialisierung von CubeMX generieren, dort siehst du doch wie alles gemacht wird. Natürlich musst du im CubeMX ein bisschen herumclicken um alles zu konfigurieren, aber es ist doch ziem- lich idiotensicher und für den Anfang genau der richtige Weg.
>Warum lässt du dir nicht den Code für >die Initialisierung von CubeMX generieren Um nicht für immer in CubeMx stecken zu bleiben) Ich will wissen, wie alles funktioniert. >auf dem Board sehen dass es einen >8MHz Quarz gibt. Ok, ich habe gefunden, 8 Megahertz externer Quarz.
:
Bearbeitet durch User
Max M. schrieb: > Ich will wissen, wie alles funktioniert. Dafür musst du aber sehr viel mehr wissen und tun als dein Code im Eröffnungsbeitrag zeigt. Vor allem musst du Wartezeiten einhalten damit PLL-Einstellungen wirksam werden. Max M. schrieb: > 8 Megahertz externer Quarz Es gibt als Pendant dazu keinen "internen Quarz". Also: interner Takt vs. externer Takt, und was extern gemacht wird steht auf einem anderen Blatt.
Max M. schrieb: > Ich dachte, die externe Taktquelle für SysTick sei HSE, und die HSE auf > meinem Discovery Board beträgt 25 MHz. Warum das? Cube MX zeigt dir doch an, woher der Timer seinen Takt erhält. Du hast es sogar rot markiert. Nur hast du linke Hälfte nicht genauer angeschaut. Schau dir an, wie dein "System Clock Mux" eingestellt ist: Auf HSI, und der hat nunmal fest ca 16 Mhz. Wenn du den Multiplexer auf HSE stellt, dann wird der Quarz verwendet. Das Board ist normalerweise mit einem 8 MHz Quarz bestückt, nicht 25! Du kannst auch den PLL Schaltkreis nutzen, indem du den "System Clock Mux" auf PLL auf PLL stellst, den "PLL Source Mux" auch auf HSE und dann dahinter im PLL Block die gewünschten Teiler und Multiplikatoren.
beo bachta schrieb: > Warum lässt du dir nicht den Code für > die Initialisierung von CubeMX generieren Ich programmiere die Register lieber "zu Fuß" ohne HAL, einfach weil ich mich mehr mit den Grundlagen befassen will. Im Hobby besteht für mich keine Notwendigkeit, schnell zum Ziel zu kommen. Da ist eher der Weg und das Erforschen das Ziel. Wie dem auch sei, ich benutze Cube MX aber gerne, um diese Taktkonfiguration vorher theoretisch durch zu spielen. Denn Cube MX zeigen einem komfortable an, was geht und was nicht. Mit den Registern sind nämlich durchaus einige Kombinationen möglich, die an nicht ganz so offensichtlichen Grenzen anstoßen. Die zeigt Cube MX in rot an.
Stefan ⛄ F. schrieb: > Ich programmiere die Register lieber "zu Fuß" ohne HAL Du warst überhaupt nicht gefragt. Ich habe dich nicht gefragt, also warum zitierst du meinen Betrag den ich dem TO geschrieben habe?
Nach wirklich zig Jahren an händischer Bitklempnerei bin ich mittlerweile auch ein großer Fan von STM32CubeMX geworden. Hierbei finde ich es äußerst lehrreich und ratsam, natürlich auch die generierten Quelltexten im Versionskontrollsystem (SVN, Git, ...) einzuchecken und nach jeder noch so kleinen Änderung am STM32CubeMX-Projekt ein Diff sowohl der IOC-Datei als auch der generierten Quelltexte durchzuführen. Dann sieht man sehr schön, was sich geändert hat und warum das der Fall ist. Ich hatte schon des öfteren ein Aha-Erlebnis, weil neben den erwarteten Änderungen manchmal auch noch an irgendeinem anderen Register, das ich nicht auf dem Plan gehabt hätte, das eine oder anderen Bit verändert wird. Bei rein händischer Programmierung sucht man sich wegen solcher Kleinigkeiten nämlich einen Wolf. Mit Grausen muss ich noch an Atmel AT91RM9200 usw. zurückdenken. Bei der Gurke musste man sich ständig zwischen Pest und Cholera entscheiden, d.h. entweder passte der USB-Takt, aber dafür lagen die UART-Takte ziemlich daneben. Man konnte sich auch eine Konfiguration bauen, in der beides einigermaßen hinkam, aber dafür musste man eine PLL außerhalb des spezifizierten Bereichs betreiben, usw.. Ein sehr wichtiges Hilfsmittel für die Inbetriebnahme und auch spätere Konfigurationsänderungen war tatsächlich ein Spektrumanalysator. Ich klebte auf den Prozessor ein Stück Kupferfolie und konnte dann mit dem SA sehen, wie sich die Spektrallinien änderten, wenn ich an der Taktkonfiguration in den Bootloadern und im Linux-System herumschraubte. Es war natürlich hochgradig lehrreich, so etwas mal wirklich en detail per Hand durchgeführt zu haben. Und bei meinem Kunden schauten auch die anderen Entwickler ziemlich blöd und konnte nicht nachvollziehen, was ich da überhaupt trieb. Aber wenn ich so etwas heutzutage bei jeder Inbetriebnahme eines jeden Microcontrollers wiederholen müsste, würde ich eher eine Umschulung zum Tischler oder Gärtner in Erwägung ziehen.
beo bachta schrieb: > Du warst überhaupt nicht gefragt. Du auch nicht (Kopfschüttel) Wenn du nicht zitiert werden möchtest, also wenn sich niemand auf deine Aussagen beziehen soll, dann mache keine öffentlichen Aussagen. So einfach ist das. Ich glaube du hast nicht verstanden, dass das hier ein öffentliches Diskussionsforum ist. Sogar noch viel öffentlicher als die meisten anderen. Gerne hätte dir diese pampige Antwort persönlich (nicht öffentlich) geschickt, aber das geht nicht, weil du dich nicht angemeldet hast.
Gerade am Anfang würde ich mir tatsächlich besonders die Clock-Configuration generieren lassen da es da einige Fallstricke gibt. Wenn man es genau verstehen will, kann man sich ja den Quelltext dann ansehen. Für den STM32F4 gibt es übrigens in der AN3988 eine Excel-Datei mit Makros die Dir ohne CubeMX genau den notwendigen Code erzeugt (auf Basis von der "alten" HAL, also nur den Includes): https://www.st.com/resource/en/application_note/an3988-clock-configuration-tool-for-stm32f40xx41xx427x437x-microcontrollers-stmicroelectronics.pdf Das hatte mir am Anfang auch geholfen das alles zu verstehen und richtig(!) zu initialisieren.
:
Bearbeitet durch User
>Wenn du den Multiplexer auf HSE stellt, dann wird der Quarz verwendet. >Das Board ist normalerweise mit einem 8 MHz Warum ist dann die SysTick-Frequenz bei externer Taktung 16/8=2 MHz? Ich habe nirgendwo eine Antwort auf diese Frage gefunden. Es wird einfach berichtet, dass bei externer Taktung die SysTick-Frequenz ist: Prozessorfrequenz / 8.
:
Bearbeitet durch User
Max M. schrieb: > Warum ist dann die SysTick-Frequenz bei externer Taktung 16/8=2 MHz? > Es wird einfach berichtet, dass bei externer Taktung die Frequenz > 8-mal geringer ist. Ich sage, dass der Systick Timer in deinem Eröffnungsbeitrag mit 1 Mhz getaktet wird, weil du im "System Clock Mux" den 16 Mhz HSI Oszillator gewählt hast und der AHB Prescaler auf "/2" gestellt ist. Dahinter kommt noch ein weiterer Teiler "/8". Also: 16 MHz ÷ 2 ÷ 8 Den anderen Fall solltest du mal hier zeigen, damit die Konfiguration klar ist. Jedenfalls ist das Resultat nicht immer zwingend 2 MHz.
Andreas S. schrieb: > Nach wirklich zig Jahren an händischer Bitklempnerei bin ich > mittlerweile auch ein großer Fan von STM32CubeMX geworden. Naja, hier sind eben die STM32-Fans unter sich. Aber: Was macht ihr, wenn ihr mal einen anderen µC verwenden sollt/wollt/müßt als einen von ST ? Da gibt es kein Cube. Ich hänge hier mal eine alte (etwa 6 Jahre) Konfigurationsdatei dran - als Beispiel dafür, wie man's auch ganz ohne Cube und Konsorten machen kann und trotzdem flexibel bleibt. Und sogar eine recht einfache Debugmögichkeit per Oszi (Funktion 'monitor') ist mit dabei. W.S.
W.S. schrieb: > Ich hänge hier mal eine alte (etwa 6 Jahre) Konfigurationsdatei dran - Da haben wir wieder deine magischen Zahlen. ST liefert diese bereits in Header Dateien. Es ist mir ein Rätsel, dass du sie teilweise nicht verwendest. Sorry, aber dieser Programmierstil ist keine gute Empfehlung. > Was macht ihr, wenn ihr mal einen anderen µC verwenden > sollt/wollt/müßt als einen von ST ? Da gibt es kein Cube. Wenn ich in einem Projekt Cube MX bzw. HAL benutze, entsteht dadurch keinerlei Zwang, es in allen Projekten zu nutzen. Schon gar nicht, wenn ganz andere Mikrocontroller im Spiel sind. Man nimmt das, was angeboten wird. Aber bitte erst nach dem Erlernen der Grundlagen. Der TO ist da schon auf dem richtigen Weg.
W.S. schrieb: > Aber: Was macht ihr, wenn ihr mal einen anderen µC verwenden > sollt/wollt/müßt als einen von ST ? Da gibt es kein Cube. Da hilft dein Code aber auch nicht weiter. So what?
Stefan ⛄ F. schrieb: > Da haben wir wieder deine magischen Zahlen. ST liefert diese bereits in > Header Dateien. Es ist mir ein Rätsel, dass du sie teilweise nicht > verwendest. Dann erkläre ich es dir: Ich sehe in unnötigen Bezügen und einer damit verbundenen Schwemme von zusätzlichen Bezeichnern einen ernsthaften Grund für Programmierfehler. Wenn man Bit 7 für irgend etwas braucht, dann kann man schreiben
1 | #define MeinBit 7
|
oder
1 | #define MeinBit (1<<7)
|
oder eines von beiden muß in einer referenzierten anderen Datei stehen. Von sowas wie 128 oder 0x80 wollen wir hier mal absehen. Um sicher zu sein, daß dort das drinsteht, was man braucht, muß man in der anderen Datei nachschauen. Und wenn jemand eine andere Toolchain hat, wo das gerade anders gehandhabt wird, dann handelt man sich einen Fehler ein, den man so schnell nicht bemerkt. Deshalb sollte man solche Dinge, die tatsächlich unbemerkt schiefgehen können, lieber nicht aus anderen Dateien beziehen, die obendrein nicht zum konkreten Projekt gehören. Maßhalten ist angesagt anstelle Extremismus. Headerdateien zu einem Chip sind OK, aber sie sollten nicht über das sinnvolle Maß aufgebläht sein. Davon mal abgesehen ist es mir auch bei ST bereits einmal untergekommen, daß Bits, die in völlig verschiedenen Registern vorkommen, den gleichen Namen hatten. Dann mußten in der zugehörigen Headerdatei Modifikationen am Namen vorgenommen werden, woraus sich obendrein ein Unterschied zum Manual ergab. In diesem Falle war dann das Lesen der Headerdatei und Vergleich mit dem Manual fällig, um den richtigen Namen zu erwischen. Ich weiß, sowas ist selten, es kommt aber vor. W.S.
Siehst du, da sind wir wieder bei deinem Stil, lieber eigene Header Dateien zu schreiben, als bewährte wieder zu verwenden. Das kann man machen, aber empfehlen werde ich es wahrscheinlich niemals.
>Ich sage, dass der Systick Timer in deinem Eröffnungsbeitrag mit 1 Mhz >getaktet wird Vielleicht verstehe ich etwas nicht, aber nein. Der SysTick-Timer wird beim internen Taktgeber auf 16 MHz und beim externen Taktgeber auf 2 MHz eingestellt. Ich überprüfe es mit dem Code, der in der ersten Nachricht geschrieben ist. Den internen Generator habe ich so eingerichtet:
1 | SysTick_Config(16000000); |
Externen Generator wie folgt eingerichtet:
1 | SysTick->LOAD = (uint32_t)(2000000-1); |
2 | SysTick->VAL = 0UL; |
3 | SysTick->CTRL &= ~(1UL << SysTick_CTRL_CLKSOURCE_Pos); |
4 | SysTick->CTRL = SysTick_CTRL_TICKINT_Msk | |
5 | SysTick_CTRL_ENABLE_Msk; |
Bernd schrieb: > Da hilft dein Code aber auch nicht weiter. > So what? Da hilft die Herangehensweise aber sehr. So that . Sozusagen. Es ist eben das Können einer Initialisierung des Chips oder das Angebundensein an ein spezielles Herstellertool. Sollte eigentlich erkennbar sein. So eine Konfigurationsdatei, die den Takt und die Pinverwendung aufsetzt, muß natürlich sowohl zum Chip als auch zum Projekt passen. Insofern ist das eine projektabhängige Datei, aber sie ist nicht maschinell erzeugt und braucht deshalb keine Herstellertools und obendrein hält man sich damit die anderen Dateien im Projekt von den hier gemachten Einstellungen frei. Was ich hier in diesem Forum allerdings oft sehe, sind Projekte, wo alles kreuz und quer durcheinander purzelt: Lowlevel-Einstellungen in main.c und so weiter. W.S.
Max M. schrieb: > Der SysTick-Timer wird beim internen Taktgeber auf 16 MHz und beim > externen Taktgeber auf 2 MHz eingestellt. Mag sein. Das hängt alles davon ab, wie die Multiplexer, Teiler und PLL in deinem Fall konfiguriert sind. Ohne konkrete Angaben kann ich das nicht weiter kommentieren. Zeige doch mal das korrespondiere Bild von Cube MX. Ich bin ganz sicher, dass da nicht magisches im Hintergrund passiert.
Ok habe es. Gut, danke. Ich lösche diesen Code, der diese Einstellungen vorgenommen hat.
Max M. schrieb: > Ich lösche diesen Code, der diese Einstellungen vorgenommen hat. Zeige ihn doch mal! Das lässt sich sicher erklären.
Stefan ⛄ F. schrieb: > Siehst du, da sind wir wieder bei deinem Stil, lieber eigene Header > Dateien zu schreiben, als bewährte wieder zu verwenden. Ach nö, wenn irgend ein Hersteller für seine Chips passable Headerdateien liefert, dann nehme ich die auch. Aber das heißt nicht, grundsätzlich alles daraus zu verwenden. Es ist ST ja beileibe nicht der einzige Hersteller, dessen µC ich verwende. Ich hab da schon einige durch und ein jeder Hersteller hat da seine eigenen Macken. Nicht nur beim schieren Silizium. W.S.
1 | #include "main.h" |
2 | void SystemClock_Config(void); |
3 | static void MX_GPIO_Init(void); |
4 | |
5 | int main(void) |
6 | {
|
7 | |
8 | HAL_Init(); |
9 | |
10 | SystemClock_Config(); |
11 | |
12 | MX_GPIO_Init(); |
13 | |
14 | while (1) |
15 | {
|
16 | |
17 | }
|
18 | |
19 | void SystemClock_Config(void) |
20 | {
|
21 | RCC_OscInitTypeDef RCC_OscInitStruct = {0}; |
22 | RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; |
23 | |
24 | __HAL_RCC_PWR_CLK_ENABLE(); |
25 | __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); |
26 | |
27 | RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; |
28 | RCC_OscInitStruct.HSEState = RCC_HSE_ON; |
29 | RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; |
30 | if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) |
31 | {
|
32 | Error_Handler(); |
33 | }
|
34 | |
35 | RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |
36 | |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; |
37 | RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE; |
38 | RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV2; |
39 | RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; |
40 | RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; |
41 | |
42 | if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) |
43 | {
|
44 | Error_Handler(); |
45 | }
|
46 | }
|
47 | |
48 | static void MX_GPIO_Init(void) |
49 | {
|
50 | |
51 | /* GPIO Ports Clock Enable */
|
52 | __HAL_RCC_GPIOH_CLK_ENABLE(); |
53 | __HAL_RCC_GPIOA_CLK_ENABLE(); |
54 | |
55 | }
|
56 | void Error_Handler(void) |
57 | {
|
58 | |
59 | __disable_irq(); |
60 | while (1) |
61 | {
|
62 | }
|
63 | }
|
64 | |
65 | #ifdef USE_FULL_ASSERT
|
66 | |
67 | void assert_failed(uint8_t *file, uint32_t line) |
68 | {
|
69 | }
|
Hier waren vielleicht void SystemClock_Config (void) alle Timer-Einstellungen, ich habe sie aus dem Code entfernt.
In dem Zusammenhang ist neben dem RCC die Beschreibung des "SysTick control and status register" relevant, welche leider nicht im Reference Manual des Chips dokumentiert ist, sondern in einem weiteren Dokument, dem "STM32 Cortex-M4 programming manual". Der Code, den du weiter oben mit "Externen Generator wie folgt eingerichtet:" hat nichts mit HSE (Quarz) versus HSI zu tun, sondern beeinflusst den Teiler an den ich den grünen Pfeil gemalt habe. Zitat:
1 | SysTick->LOAD = (uint32_t)(2000000-1); |
2 | SysTick->VAL = 0UL; |
3 | SysTick->CTRL &= ~(1UL << SysTick_CTRL_CLKSOURCE_Pos); |
4 | SysTick->CTRL = SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; |
Max M. schrieb: > C-Quelltext Hier nutzt du also nun den HSE ohne PLL. Der AHB Bus hat bei deiner Einstellung Systemtakt geteilt durch 2. Also vermutlich 4 MHz, da ich von einem 8 MHz Quarz ausgehe. Nun kann der Systick Timer am AHB Bus also wahlweise mit den 4 MHz oder 0,5 MHz (4 MHz nochmal geteilt durch 8) getaktet werden.
Max M. schrieb: > Der SysTick-Timer wird beim internen Taktgeber auf 16 MHz und beim > externen Taktgeber auf 2 MHz eingestellt. Die Verwirrung kommt daher, dass der SYSTICK nicht STM gehört, sondern ARM, wobei der Teiler /8 schon wieder STM gehört. Deshalb ist "extern" relativ. ARM meint damit "außerhalb des M4-Kerns". Im ARM v7-M Architecture ® Reference Manual ist es minimal verständlicher formuliert:
1 | CLKSOURCE, bit[2] Indicates the SysTick clock source: |
2 | 0 SysTick uses the IMPLEMENTATION DEFINED external reference clock. |
3 | 1 SysTick uses the processor clock. |
4 | If no external clock is provided, this bit reads as 1 and ignores writes. |
Solche kleinen Probleme mit der Doku werden dir noch öfter begegnen, z.B. Signalnamen aus der Chip-Design-Ecke, die sonst nirgendwo auftauchen. Woher soll auch der Entwickler von z.B. einem ADC wissen, auf welchen Chip und wie sein ADC-Modul mal eingebaut wird. Und der Autor der Doku erfährt es vielleicht nur nebenbei beim Kaffee ;)
Wie ätzend. Aber es bestätigt meine Empfehlung mit AVR anzufangen, weil deren Doku erheblich Anfänger-freundlicher ist. Gibt es eigentlich Cortex-M basierte Mikrocontroller mit ähnlich guter und einfacher Doku wie bei AVR?
Stefan ⛄ F. schrieb: > Aber es bestätigt meine Empfehlung mit AVR anzufangen, weil deren Doku > erheblich Anfänger-freundlicher ist. Vor allem aber dürften diese denen für die meisten Zwecke ausreichen.
In dem von CubeMx generierten Code werden Interrupts von einem anderen Timer behandelt, nicht von SysTick. Und immer werden diese Interrupts für einen Tick auf 1 Millisekunde gesetzt. Also 1 Kilohertz. Unabhängig von den Einstellungen, die ich in der CubeMx Clock Configuration vornehme, werden Interrupts immer auf 1 Millisekunde für einen Tick gesetzt. Weiß jemand wo diese Interrupts gesetzt sind? Ich denke, dass dies irgendwo in der Funktion HAL_RCC_ClockConfig ist, ich habe nicht gefunden, wo genau Interrupts in dieser Funktion konfiguriert sind.
1 | HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) |
HAL_RCC_ClockConfig passt sich an alle vorhandenen Teiler an und setzt Interrupts immer auf 1 Kilohertz, mit beliebigen HAL_RCC_ClockConfig-Einstellungen.
Beitrag #7081251 wurde vom Autor gelöscht.
Ich habe nur den Frequenzteiler im Register RCC->CFGR gefunden. Das RCC_CIR-Register kann Interrupts konfigurieren, aber ich habe dieses Register nicht in der HAL_RCC_ClockConfig-Funktion gesehen. In der HAL_RCC_OscConfig-Funktion habe ich das RCC_CIR-Register gefunden. Ich habe es noch nicht ganz verstanden, aber es scheint, dass Interrupts in dieser Funktion konfiguriert sind.
:
Bearbeitet durch User
Max M. schrieb: > In dem von CubeMx generierten Code werden Interrupts von einem anderen > Timer behandelt, nicht von SysTick. Vielleicht so: auch von einem anderen Timer? Hast du nicht selbst irgendwas mit einem anderen Timer gemessen? > Unabhängig von den Einstellungen, die ich in der CubeMx Clock > Configuration vornehme, werden Interrupts immer auf 1 Millisekunde für > einen Tick gesetzt. Weil: 1ms sieht doch verdammt nach systick aus; genau dafür hat ARM den eingebaut. > Weiß jemand wo diese Interrupts gesetzt sind? Die systick-Interrupts werden mit dem Bit STK->TICKINT eingeschaltet, mehr ist dafür nicht nötig. Bei allen anderen Interrupts muss zusätzlich der NVIC programmiert werden. Max M. schrieb: > In der HAL_RCC_OscConfig-Funktion habe ich das RCC_CIR-Register > gefunden. > Ich habe es noch nicht ganz verstanden, aber es scheint, dass Interrupts > in dieser Funktion konfiguriert sind. In den RCC-Registern gibt es Interrupt-Enable-Bits für alles, was mit Oszillatoren und PLLs zu tun hat. Timer haben ihre eigenen Register. Die Hardware ist in der Hinsicht relativ aufgeräumt. Was man scheinbar vom HAL nicht sagen kann... Diese Rätsel wären doch ein guter Anlass, den CubeMX- und HAL-Code zu entsorgen. Du musst ja sowieso die Hardware verstehen. Dafür reicht das Reference Manual und ggf. eine AppNote. Warum solltest du zusätzlich noch die HAL-Magie lernen? Immerhin: Max M. schrieb: >>Warum lässt du dir nicht den Code für >>die Initialisierung von CubeMX generieren > Um nicht für immer in CubeMx stecken zu bleiben) > Ich will wissen, wie alles funktioniert.
>mit beliebigen HAL_RCC_ClockConfig-Einstellungen.
Hier meinte: ich mit beliebigen CubeMx Clock Configuration Einstellungen
:
Bearbeitet durch User
Stefan ⛄ F. schrieb: > es bestätigt meine Empfehlung mit AVR anzufangen, weil > deren Doku erheblich Anfänger-freundlicher ist. Es wäre ja schon viel gewonnen, wenn Anfänger unterscheiden könnten, welche Kapitel nur für Experten wichtig sind. Warum beschäftigen sich Anfänger mit der Taktkonfiguration? Das ist bei praktisch allen STM32 völlig überflüssig, die Defaults nach Reset funktionieren einfach so. Oder Interrupt-Prioritäten -- total egal, es funktioniert von alleine. Aber nein, überall werden erstmal die sub priorities erklärt -- die braucht man vielleicht, wenn man ein Betriebssystem baut. Mit HAL kommt man aber kaum dran vorbei.
Bauform B. schrieb: > Warum beschäftigen sich > Anfänger mit der Taktkonfiguration? Weil der Takt wohl eines der grundlegenden Dinge in einem Mikrocontroller ist. Darum. Und man sollte das Taktsystem auch zu verstehen lernen, bevor man irgendwelche anderen Teile eines µC benutzen will. Wer das nicht kann oder will oder aus anderen Gründen ablehnt, der sollte ein geeignetes Ingenieurbüro mit dem Projekt beauftragen. Dann kann man sich auf andere Dinge konzentrieren, BWL zum Beispiel. Die Alternative für Leute die unbedingt programmieren wollen wäre, das nicht für einen µC zu tun, sondern auf dem PC zu bleiben. Dort hat man zumeist ein fertiges OS, was einem die Details der Hardware abnimmt. Allerdings tut sich da ein weiteres Problem auf: Man lernt nix über die Hardware dazu. Und so kommt weitere Verwirrung auf, die letztlich zu solchen Dingen führt: Max M. schrieb: > Mit diesem Code habe ich herausgefunden, dass die Dauer eines Ticks > 1/16000000 == 62,5 ns beträgt Also, zum Verständnis: Es gibt diverse Teile auf dem Silizium deines Controllers, die einen Interrupt erzeugen können. Diese werden im Interruptcontroller verwaltet, der sie in geordneter Reihenfolge benutzt, um damit den gewöhnlichen Ablauf der Arbeit der CPU zu unterbrechen. Von da her kommt der Name 'Interrupt'. Bei den Cortexen ist es nun so, daß zu jedem möglichen Interrupt, der auf dem betreffenden Stück Silizium vorkommen kann, ein Adress-Zeiger im Programmspeicher gehört, der auf den zuständigen Interrupthandler hinzeigt. Diese Adress-Zeiger sind zu einer Tabelle zusammengefaßt, die gewöhnlich ab Adresse 0 beginnt. Bei manchen Cortexen kann diese Tabelle auch woanders hin verlegt werden, was hier aber nicht das Thema ist. So. Einer der Interupts ist der, welcher vom Systemtimer (Timertick) hervorgerufen wird. Dieser Timer wird selten von den Manuals der Chiphersteller behandelt, weil er Teil der CPU ist, die bekanntlich von Arm kommt. Um da nachzulesen, muß man eher die Dokumente lesen, die von Arm kommen. Besagter Timertick arbeitet zumeist mit dem Takt, den auch die CPU benutzt, also dem Systemtakt. Kann aber bei manchen Chips auch von woanders getaktet werden. Sinn und eigentlicher Zweck dieses Timers ist, daß er Interrupts in geordneten zeilichen Abständen liefern soll, so daß man damit eine Systemuhr o.ä. machen kann. Normalerweise lädt man also diesen Timer mit einer solchen Zahl, daß sich ein Tick (d.h. ein Interrupt) alle 1 ms oder 10 ms ergibt und läßt ihn dann in Ruhe vor sich hin arbeiten. Und wenn du Zweifel an der Frequenz des Systemtaktes hast, dann leite dir diesen Takt oder den heruntergeteilten Teil dieses Taktes auf den dafür vorgesehenen Pin deines Chips und schau ihn dir per Oszi oder Frequenzmesser an. Walter T. schrieb: > Es geht um den Abstand, nicht die Dauer, oder? Ja, natürlich. Aber wie so oft hat man es auch hier mit unpräzisen Ausdrücken zu tun, die aus nur nebulösen Vorstellungen herrühren. Von da her tut Erklärung not. W.S.
W.S. schrieb: > Und man sollte das Taktsystem auch zu verstehen lernen, bevor man > irgendwelche anderen Teile eines µC benutzen will. Nein. Nicht, wenn es für das Programm völlig unwichtig ist.
W.S. schrieb: > Die Alternative für Leute die unbedingt programmieren wollen wäre, das > nicht für einen µC zu tun, sondern auf dem PC zu bleiben. Die Alternative wären zunächst mal schlicht einfachere Mikrocontroller die es genauso tun.
Bauform B. schrieb: > Warum beschäftigen sich > Anfänger mit der Taktkonfiguration? Das ist bei praktisch allen STM32 > völlig überflüssig, die Defaults nach Reset funktionieren einfach so. Sehr gut, volle Zustimmung. In meinem STM32 Heft gehe ich genau diesen Weg. W.S. schrieb: > Die Alternative für Leute die unbedingt programmieren wollen wäre, das > nicht für einen µC zu tun, sondern auf dem PC zu bleiben. Ja, ich finde es auch nicht besonders geschickt, die Programmiersprache auf einem µC zu lernen. Anfassbare Hardware (z.B. einen Roboter) zu programmieren mag zwar verlockend klingen, aber da hat man rasch zu viele Baustellen gleichzeitig offen.
Bauform B. schrieb: > Warum beschäftigen sich > Anfänger mit der Taktkonfiguration? Das ist bei praktisch allen STM32 > völlig überflüssig, die Defaults nach Reset funktionieren einfach so. Gibt es eine allgemeine Aussage dazu wie diese Defaults aussehen? Also es werden ja wohl eher nicht alle STM32 per Default auf den maximalen Takt konfiguriert sein, so aus einem internen Oszillator? Es werden aber auch nicht alle STM32 per Default mit 16MHz laufen? Oder sind die Default-Werte individuell für jeden Typ? Pro Familie wird das wohl eher auch nicht gelten, innerhalb einer Familie haben ja nicht alle Typen den gleichen Maximal-Takt. Wenn ja, wo steht das im Reference-Manual? Nehmen wir als Beispiel doch mal STM32F446, STM32L073 und STM32G081. Ich habe jetzt mal kurz das Reference-Manual vom STM32F446 überflogen aber nicht direkt eine Tabelle mit den Default-Werten gefunden. Ja, die Register haben Reset-Default-Werte und man könnte sich das zusammen suchen, die Aussage oben ist doch aber, das man das zunächst nicht braucht. Wo steht das konkret? Und ich meine das Ernst, ich habe keine Ahnung wie man STM32 programmiert, bin aber geneigt das zu ändern wenn man die denn 2024 oder so wieder bekommen kann. Eine HAL Funktion gibt es dafür auch nicht, oder? Also sowas wie HAL_CLOCK_Init(48000000)?
Bob schrieb: > Gibt es eine allgemeine Aussage dazu wie diese Defaults aussehen? Bei den mir bekannten STM32 läuft die L Serie standardmäßig auf 2 MHz und die F Serie auf 8 MHz. > Wenn ja, wo steht das im Reference-Manual? Die Info ist über die RESET Werte zahlreicher Register verstreut. In Cube MX kannst du es schneller sehen, da gibt es einen Button der den Standardfall nach Reset anzeigt. Bob schrieb: > Eine HAL Funktion gibt es dafür auch nicht, oder? > Also sowas wie HAL_CLOCK_Init(48000000)? Nein, weil es da ja viele weitere Optionen gibt. Willst 48 Mhz aus dem R/C Oszillator oder externen Quarz. Wie viel Mhz hat der Quarz? Manche Modelle haben mehrere R/C Oszillatoren. Soll der Oszillator mit dem USB Takt synchronisiert werden? Außerdem gibt es ja noch zahlreiche Teiler für die Peripherie. Der eine möchte sie vielleicht so schnell wie möglich takten, der andere nicht um z.B Strom zu sparen oder damit Timer langsame/länger laufen.
Bob schrieb: > Gibt es eine allgemeine Aussage dazu wie diese Defaults aussehen? Du willst ne allgemeine Aussage? OK: Im allgemeinen wird (sofern vorhanden) zu allererst ein interner RC-Oszillator als Taktquelle benutzt. Sofern vorhanden, wird die PLL und der dazu gehörige schnelle VCO am Anfang nicht benutzt. Gleiches gilt für einen externen Quarz oder sonstwie von außen zugeführtes Taktsignal. Der µC kann damit erstmal arbeiten, aber er wird damit nicht seine vorgesehene Geschwindigkeit erreichen. W.S.
Bob schrieb: > Ich habe jetzt mal kurz das Reference-Manual vom STM32F446 überflogen > aber nicht direkt eine Tabelle mit den Default-Werten gefunden. > > Ja, die Register haben Reset-Default-Werte und man könnte sich das > zusammen suchen, die Aussage oben ist doch aber, das man das zunächst > nicht braucht. > > Wo steht das konkret? Im Datenblatt im Kapitel "Functional Overview", Abschnitt "Clocks and Startup". Das Datenblatt ist auch viel kürzer als das Reference Manual (falls man suchen muss). Und es ist die offizielle Quelle für Daten, die evt. von Baustein zu Baustein unterschiedlich sein könnten. Die Reference Manuals behandeln ja oft viele verschiedene Typen.
Top, danke. Bauform B. schrieb: >> Wo steht das konkret? > > Im Datenblatt im Kapitel "Functional Overview", Abschnitt "Clocks and > Startup". Das Datenblatt ist auch viel kürzer als das Reference Manual > (falls man suchen muss). Und es ist die offizielle Quelle für Daten, die > evt. von Baustein zu Baustein unterschiedlich sein könnten. Die > Reference Manuals behandeln ja oft viele verschiedene Typen. STM32F446: 16MHz STM32L073: 2,1MHz STM32G081: scheinbar keine Angabe im Datenblatt, oder nicht direkt Das ist ein guter Tipp, leider sind die Datenblätter von STM alles andere als konsistent zueinander. Stefan ⛄ F. schrieb: > In Cube MX kannst du es schneller sehen, da gibt es einen Button der den > Standardfall nach Reset anzeigt. Ok, ich habe ein neues Projekt für den STM32G081 aufgemacht, danach läuft der per Default mit 16MHz. Stefan ⛄ F. schrieb: >> Eine HAL Funktion gibt es dafür auch nicht, oder? >> Also sowas wie HAL_CLOCK_Init(48000000)? > > Nein, weil es da ja viele weitere Optionen gibt. Willst 48 Mhz aus dem > R/C Oszillator oder externen Quarz. Wie viel Mhz hat der Quarz? Manche > Modelle haben mehrere R/C Oszillatoren. Soll der Oszillator mit dem USB > Takt synchronisiert werden? Nun, um sowas aufzulösen gibt es die HAL doch? Nur wohl eben nicht für den Takt. Was schade ist, wenn man die entsprechenden HAL Includes einbinden würde, dann könnte man ja die gleichen Aufrufe für mehrere Targets verwenden. Genau wie man eben LL_SPI_TransmitData8() querbeet durch den ganzen STM32 Zoo verwenden kann. Stefan ⛄ F. schrieb: > Außerdem gibt es ja noch zahlreiche Teiler für die Peripherie. Der eine > möchte sie vielleicht so schnell wie möglich takten, der andere nicht um > z.B Strom zu sparen oder damit Timer langsame/länger laufen. Ja, nun, das gehört ja schon irgendwie zur Konfiguration der Peripherie. Wobei ich gerade überrascht bin von der "Clock Configuration" vom STM32G081, ein großer Teil der Peripherie hängt wohl einfach so am "APB peripheral clock", etwa die SPI. Auf den ersten Blick scheinen die Möglichkeiten üppig zu sein, auf den zweiten Blick ist das doch schon schwer eingeschränkt. Der Prescaler für den SPI erinnert mich gerade an AVR, hmm.
Bob schrieb: > Nun, um sowas aufzulösen gibt es die HAL doch? > Nur wohl eben nicht für den Takt. Doch klar, CubeMX generiert entsprechend den Einstellungen in dem grafischen Dialog einen Code, der komplett auf HAL basiert. Zum Beispiel:
1 | void SystemClock_Config(void) |
2 | {
|
3 | RCC_OscInitTypeDef RCC_OscInitStruct = {0}; |
4 | RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; |
5 | RCC_PeriphCLKInitTypeDef PeriphClkInit = {0}; |
6 | |
7 | /** Configure the main internal regulator output voltage
|
8 | */
|
9 | __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1); |
10 | |
11 | /** Initializes the RCC Oscillators according to the specified parameters
|
12 | * in the RCC_OscInitTypeDef structure.
|
13 | */
|
14 | RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE|RCC_OSCILLATORTYPE_HSI48; |
15 | RCC_OscInitStruct.HSEState = RCC_HSE_ON; |
16 | RCC_OscInitStruct.HSI48State = RCC_HSI48_ON; |
17 | RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; |
18 | RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE; |
19 | RCC_OscInitStruct.PLL.PLLMUL = RCC_PLLMUL_8; |
20 | RCC_OscInitStruct.PLL.PLLDIV = RCC_PLLDIV_2; |
21 | if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) |
22 | {
|
23 | Error_Handler(); |
24 | }
|
25 | |
26 | /** Initializes the CPU, AHB and APB buses clocks
|
27 | */
|
28 | RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |
29 | |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2; |
30 | RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; |
31 | RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; |
32 | RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; |
33 | RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; |
34 | |
35 | if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1) != HAL_OK) |
36 | {
|
37 | Error_Handler(); |
38 | }
|
39 | PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USB; |
40 | PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_HSI48; |
41 | if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) |
42 | {
|
43 | Error_Handler(); |
44 | }
|
45 | }
|
Du kannst diese HAL Funktionen (in diesem Fall HAL_RCC_OscConfig, HAL_RCC_ClockConfig und HAL_RCCEx_PeriphCLKConfig) selbstverständlich auch selbst benutzen, ohne den Code Generator von Cube MX zu benutzen. Aber kopieren kann man diese Zeilen nur bedingt, denn das funktioniert ja bei jedem Modell (in Details) anders.
Stefan ⛄ F. schrieb: > Doch klar, CubeMX generiert entsprechend den Einstellungen in dem > grafischen Dialog einen Code, der komplett auf HAL basiert. Nö, muss nicht auf HAL basieren. Man kann CubeMX genau so gut dazu veranlassen, Low-Level-Code (also Code für die LL Library) zu generieren. Hier ein Beispiel für den F411. Generiert aus CubeMX. Es kommt zwar einmal das Token HAL_OK vor aber sonst sind die Calls alle für die LL Library ausgeführt.
1 | void SystemClock_Config(void) |
2 | {
|
3 | LL_FLASH_SetLatency(LL_FLASH_LATENCY_3); |
4 | |
5 | if(LL_FLASH_GetLatency() != LL_FLASH_LATENCY_3) |
6 | {
|
7 | Error_Handler(); |
8 | }
|
9 | LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); |
10 | LL_RCC_HSE_Enable(); |
11 | |
12 | /* Wait till HSE is ready */
|
13 | while(LL_RCC_HSE_IsReady() != 1) |
14 | {
|
15 | |
16 | }
|
17 | LL_RCC_PLL_ConfigDomain_SYS(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_25, 192, LL_RCC_PLLP_DIV_2); |
18 | LL_RCC_PLL_ConfigDomain_48M(LL_RCC_PLLSOURCE_HSE, LL_RCC_PLLM_DIV_25, 192, LL_RCC_PLLQ_DIV_4); |
19 | LL_RCC_PLL_Enable(); |
20 | |
21 | /* Wait till PLL is ready */
|
22 | while(LL_RCC_PLL_IsReady() != 1) |
23 | {
|
24 | |
25 | }
|
26 | LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); |
27 | LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_2); |
28 | LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); |
29 | LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_PLL); |
30 | |
31 | /* Wait till System clock is ready */
|
32 | while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_PLL) |
33 | {
|
34 | |
35 | }
|
36 | LL_SetSystemCoreClock(96000000); |
37 | I2C_SetSystemCoreClock(96000000); |
38 | |
39 | /* Update the time base */
|
40 | if (HAL_InitTick (TICK_INT_PRIORITY) != HAL_OK) |
41 | {
|
42 | Error_Handler(); |
43 | };
|
44 | LL_RCC_SetTIMPrescaler(LL_RCC_TIM_PRESCALER_TWICE); |
45 | }
|
stefanuswidersprecher schrieb: > Nö, muss nicht auf HAL basieren. Man kann CubeMX genau so gut > dazu veranlassen, Low-Level-Code (also Code für die LL Library) > zu generieren. Ja, aber Bob hatte ja nach HAL Funktionen zum Konfigurieren des Taktes gefragt. Also habe ich ihm gezeigt, wie es geht: Bob schrieb: > Eine HAL Funktion gibt es dafür auch nicht, oder? > Also sowas wie HAL_CLOCK_Init(48000000)?
Stefan ⛄ F. schrieb: > Bob schrieb: >> Eine HAL Funktion gibt es dafür auch nicht, oder? >> Also sowas wie HAL_CLOCK_Init(48000000)? > > Nein, weil es da ja viele weitere Optionen gibt. Stefan ⛄ F. schrieb: > if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) > { > Error_Handler(); > } Schön, also die richtige Antwort wäre gewesen, ja, gibt es, aber deutlich komplizierter, da es viele weitere Optionen gibt. Und statt HAL_CLOCK ist das HAL_RCC. Ok, ja, das einfachste wird wirklich sein das zumindest am Anfang aus der STM32CubeIDE für jedes Target einzeln zu generieren. stefanuswidersprecher schrieb: > Nö, muss nicht auf HAL basieren. Man kann CubeMX genau so gut > dazu veranlassen, Low-Level-Code (also Code für die LL Library) > zu generieren. Interessant, spontan gefunden wo man das einstellt habe ich allerdings nicht. https://www.e-tinkers.com/2022/04/a-bettery-way-to-setup-stm32cubeide/ Also falls die Webseite verschwinden sollte, in der project.ioc den Project Manager Tab auswählen, Links auf "Advanced Settings" stellen und im "Driver Selector" da wo per Default "HAL" steht im DropDown Menü auf "LL" umstellen. Ein weiterer Link in der Sammlung STM32 Links für "später".
Bob schrieb: > Schön, also die richtige Antwort wäre gewesen, ja, gibt es, aber > deutlich komplizierter, da es viele weitere Optionen gibt. Nein, doch, Oooh! Schau mal wie ich die Frage beantwortet hatte: Stefan ⛄ F. schrieb: > Nein, weil es da ja viele weitere Optionen gibt. Willst 48 Mhz aus dem > R/C Oszillator oder externen Quarz. Wie viel Mhz hat der Quarz? Manche > Modelle haben mehrere R/C Oszillatoren. Soll der Oszillator mit dem USB > Takt synchronisiert werden? > Außerdem gibt es ja noch zahlreiche Teiler für die Peripherie. Der eine > möchte sie vielleicht so schnell wie möglich takten, der andere nicht um > z.B Strom zu sparen oder damit Timer langsame/länger laufen.
Stefan ⛄ F. schrieb: > Gibt es eigentlich Cortex-M basierte Mikrocontroller mit ähnlich guter > und einfacher Doku wie bei AVR? Einfach ist relativ. Bei den schier unendlich mehr Möglichkeiten von praktisch allen Cortex-M Prozessoren und deren gewaltig besserer/umfangreicherer Peripherie gegenüber den Atmel Dingern, muss zwangsweise auch die Dokumentation komplexer sein. Persönlich war ich froh und erstaunt, als ich mich vor mehr als einer Dekade in die EnergyMicros (EFM32) eingearbeitet habe. Um Welten besser als Atmel, Microchip, Infineon, Freescale, Intel, ... Sauberer Aufbau der Dokus, Headers, Beispielprogramme, AppNotes, Peripherie, ... Leider wurden auch da die Tools seit der Übernahme durch SiliconLabs IMO dann doch wieder komplizierter. Zumindest für Einsteiger. Es gibt mittlerweile auch bei den EFM32 schon wieder verschiedenen Subfamilien mit unzähligen Derivaten. Damit steigt automatisch die Komplexität. Auch der Tools und der Dokus.
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.