Behebung eines fehlerhaften MCU-Quarzoszillatordesigns

Ich arbeite an einem SMD-Hobbyprojekt (2-Lagen-Platine), bei dem ich eine STM32F405-MCU verwende, die mit 3,3 V läuft und von einem externen 25-MHz-Quarz getaktet wird. Ungeduldig entwarf ich hastig ein Board und bestellte es. Allerdings habe ich anscheinend eine ganze Menge Punkte in Bezug auf das PCB-Design in Bezug auf den externen Kristall verpasst.

Das Ergebnis funktionierte nicht so gut, wie Sie vielleicht erwarten würden. Wenn ich auf den externen Oszillator umschalte, scheint die CPU zu laufen. Aber der MCU-Takt ist sehr langsam, und das Ein- und Ausschalten eines GPIO in der Hauptschleife ergibt eine Rechteckwelle von ungefähr 1 kHz (ich hatte noch keine Zeit, die Frequenz mit einem Clock-Out-Pin zu überprüfen).

Der Kristall schwingt mit 25 MHz, aber ich messe nur eine Sinuswelle mit einer Amplitude von etwas unter 500 mV pp (mit einer x10-Oszilloskopsonde). Ich würde erwarten, dass dies näher an der Versorgungsspannung von 3,3 V liegt (ich kann nicht viel Dokumentation finden, die angibt, was zu erwarten ist.) Ich verstehe auch nicht, wie die MCU überhaupt läuft, da sie definitiv nicht in der Schleife anhält Warten auf den Start des Oszillators. Aber es läuft zumindest nicht mit der richtigen Geschwindigkeit. Also alle Hinweise auf das, was los ist, wäre willkommen.

Nachdem ich mich eingehender mit dem Thema MCU-Kristall-PCB-Design befasst habe, habe ich eine ziemlich gute Vorstellung davon, was ich richtig gemacht habe und wo ich spektakulär gescheitert bin. Aber ich bin immer noch ziemlich verwirrt darüber, was der definitiv richtige Weg ist, dies zu tun.

Das Zeug habe ich richtig:

  • Die Spuren zum Kristall sind kurz, etwa 6 mm von der MCU entfernt.
  • Spuren sind symmetrisch.

Das Zeug, das ich sehr falsch verstanden habe, ist:

  • Ich habe eine Masseebene unter dem Kristall und den Spuren zur MCU verwendet, was wahrscheinlich eine sehr hohe Streukapazität verursacht.

  • Ich habe das Konzept "Schutzring" völlig missverstanden. Ich fügte eine Füllzone für die oberste Schicht hinzu (umgibt den Kristall) und nähte sie stattdessen an die Grundebene.

  • Verwendung eines 25-MHz-Quarzes anstelle eines 8-MHz-Quarzes. Das von STMCubeMx vorgeschlagene PLL-Setup scheint den Eingang auf 1 MHz herunterzuteilen, bevor er auf 168 MHz hochmultipliziert wird. Ein 8-MHz-Quarz sollte also gut funktionieren, denke ich.

  • Die Reset-Leitung verläuft direkt unter dem Kristall. Dieser ist aber wiederum mit dem JTAG und einem Taster verbunden und ansonsten passiv.

Ich vermute daher, dass die Streukapazität des Designs das niedrige Vp-p im 25-MHz-Oszillator erklärt. Als erste Abhilfe plane ich also, auf einen 8MHz-Quarz umzusteigen, um ihn einfach zum Laufen zu bringen. Ist meine Annahme hier sinnvoll und hätte ein 8-MHz-Quarz eine bessere Chance, auf meinem schlechten Board zu arbeiten? (Ich würde gerne das aktuelle Board zum Laufen bringen, auch wenn das Design suboptimal/wirklich schlecht ist).

Natürlich ist der endgültige Plan, ein zweites Revisionsboard zu erstellen, auf dem das Design fixiert ist. Aber es gibt ein paar Dinge, die ich in Dokumenten, die ich bisher gelesen habe, immer noch verwirrend finde:

  • Einige Dokumente empfehlen, KEINE Erdungsebene unter dem Kristall zu verwenden, sondern einen Schutzring um den Stromkreis zu legen und ihn mit dem nächsten MCU-Erdungsstift zu verbinden. Das macht für mich aber Sinn:

  • Einige andere Dokumente empfehlen, eine separate Erdungsebene unter dem Kristall zu platzieren (zusätzlich zum Ring der obersten Schicht) und diese an einer Stelle mit der nächstgelegenen MCU-Erdung zu verbinden. Ich sehe jedoch nicht ganz ein, wie dies kapazitätsmäßig besser wäre als mein aktuelles Design, da die "separate" Ebene dann auch mit der Hauptmasseebene verbunden wäre. Ich verstehe, dass es in Bezug auf das HF-Rauschen viel besser wäre. Aber es widerspricht meiner Annahme, dass die Streukapazität der Grund dafür ist, dass mein aktuelles Design eine so schwache Oszillationsausgabe erzeugt.

Daher wäre jede Erklärung bezüglich dieses offensichtlichen Widerspruchs willkommen. Auch alle anderen Hinweise für mich bezüglich der "besten Art", mein Rev2-Board zu gestalten, wären sehr dankbar.

EDIT: Bilder der Platine sind unten zu finden. C3 und C4 sind die Kondensatoren und R6 (der sich zwischen den Caps befindet) ist Rext. (Sorry für den schlechten Kontrast).

PCB-Oberschicht PCB-Unterseite

Kannst du ein Bild von deinem alten Layout posten? Ganz und in den Oszillator hineingezoomt wäre nützlich :)
Um die tatsächliche Frequenz zu erhalten, können Sie einen Timer verwenden und einen GPIO auf Überlauf / Unterlauf umschalten. Überprüfen Sie außerdem den Ausgang auf konsistentes Timing (wenn er ein wenig herumspringt, wäre die Oszillatoramplitude definitiv verdächtig).
Ich denke, Sie ziehen voreilige Schlüsse, wenn Sie vermuten, dass die Oszillatoramplitude zu niedrig ist. Es kann sehr gut sein, dass die Pins X1 und X2 auf der MCU einfach so funktionieren. Überprüfen Sie auf jeden Fall die Frequenz dieses Signals (vorzugsweise des X2-Pins) und prüfen Sie, ob es sich in der Nähe der richtigen Frequenz befindet.
Sie könnten auch ein Problem mit der Programmierung der Taktauswahl und der PLL-Konfigurationsregister haben. Sofern Sie keinen direkten 1::1-Vergleich mit einer bekannten funktionierenden Referenzplatine haben, ist die Programmierung ein Detail, das Sie überprüfen und doppelt überprüfen müssen.
Es scheint, als hätten Sie viele Probleme. In Bezug auf die unerwünschte Masseebene können Sie mit einem Skalpell / scharfen Messer und Ihrem Lötkolben Teile davon abschneiden, um das Kupfer von der Glasfaser zu lösen. Es wird nicht schön aussehen, aber es wird funktionieren. Stellen Sie außerdem sicher, dass die für den Quarz verwendeten Kondensatorwerte korrekt sind und ein Leiterbahnlayout normalerweise im Datenblatt des Quarzes vorgeschlagen wird.
Ich habe vergessen zu erwähnen, dass der Sinus, den ich am osc_out-Pin messe, die richtige Frequenz von 25 MHz hat. Bilder vom Layout werde ich so schnell wie möglich posten. Ich bin ein absoluter Anfänger im PCB-Design, und das ist sehr viel "Learning by Doing" für mich. Aus diesem Grund bitte ich auch um Ihre Expertenmeinung, da die verfügbare Dokumentation (mit der ich jetzt viele Stunden verbracht habe) mich immer noch verwirrt und sowohl widersprüchlich als auch ohne nützliche Details erscheint (wie erwartete Vp-p und was passiert, wenn Sie bekommen es falsch).
Glückwunsch zum funktionierenden Oszillator. Der Grund dafür, einen kleinen GROUND-Bereich unter dem Kristall und seinen Spuren zu haben, wobei diese GROUNDED-Folie für nichts anderes verwendet wird, besteht darin, schnelle Spitzen in den Schaltkreis zu vermeiden, die Störungen der Wellenform und Nulldurchgänge verursachen -Timing-Fehler. Dies wird als Jitter (oder nicht zufälliges Phasenrauschen) bezeichnet.

Antworten (3)

Wenn der Kristall mit 25 MHz oszilliert, liegt Ihr offensichtliches Problem woanders, möglicherweise in der Konfiguration des Taktteilers, der PLL oder was auch immer dieser bestimmte Chip enthält. Stellen Sie sicher, dass Ihre Messung die Schwingung nicht beeinflusst.

Keines der von Ihnen erwähnten Elemente ist wahrscheinlich ein Deal-Killer. Es ist ganz normal, dass die Spannungen am Kristall relativ zur Versorgungsspannung klein sind, selbst wenn sie mit einer FET-Sonde richtig gemessen werden.

Manchmal wird sogar ein Vorwiderstand verwendet, um die Ansteuerung zu reduzieren, um eine Beschädigung des Quarzes durch übermäßige Ansteuerungsleistung zu vermeiden, insbesondere bei kleinen SMT-Quarzen, die auf 100 uW oder weniger Ansteuerung begrenzt sind.

Danke für deinen Beitrag. Für den Testcode habe ich ein Beispiel verwendet, das auf der libopemcm3-Bibliothek basiert, um die Uhr einzurichten (da diese Bibliothek sehr einfach zu verwenden ist). Aber ich werde versuchen, Code aus STMCubeMX zu generieren und diesen stattdessen auszuführen, nur um zu überprüfen, ob ich das gleiche Ergebnis erhalte. Die verwendete Lib kann natürlich kaputt sein. Wie bereits erwähnt, werde ich auch versuchen, den MCO1-Ausgangspin zu aktivieren, was mir eine Möglichkeit geben sollte, den tatsächlichen Takt zu messen, der von der MCU verwendet wird.

Wie in den beiden vorherigen Antworten und mehreren Kommentaren erwähnt, stellte sich heraus, dass das Problem die ganze Zeit durch eine falsche PLL-Konfiguration verursacht wurde. Das Problem scheint in "libopencm3" zu liegen, das ich wegen seiner Einfachheit für die Einrichtung der Uhr verwendet habe. Ich habe es mit Erfolg auf mehreren Entwicklungsboards verwendet, aber es scheint zumindest einige Probleme mit der 25-MHz-Quarzkonfiguration für STM32F405 zu geben. (Ich werde die Entwickler benachrichtigen).

Ich habe mit STM32CubeMX ein sehr einfaches Setup erstellt, und das Board schnurrt jetzt wie ein Kätzchen. Ich habe auch das MCO1 für HSE aktiviert und es gibt mir eine stabile 24,9998-MHz-Ausgabe auf PA8.

Ein großes Dankeschön an alle Mitwirkenden an diesem Beitrag, die sich die Zeit genommen haben, mich in die richtige Richtung zu weisen. Ohne Ihre Hilfe hätte ich wahrscheinlich viel mehr Stunden verbracht und mein Board wahrscheinlich vollständig dezimiert. Außerdem habe ich jetzt sehr wertvollen Input zu Designänderungen für meine nächste Überarbeitung und ich habe viele sehr nützliche Dinge gelernt :-)

BEARBEITEN: Es stellt sich heraus, dass das Root-Problem weder durch meinen ursprünglichen Code noch durch LibOpenCm3 verursacht wurde. Das Problem wurde durch das Meson-Build-System verursacht, und es ist das erste Mal, dass ich versuche, es in einem STM32-Projekt zu verwenden. Standardmäßig fügt es das gcc-Compiler-Flag "-fPIC" ein, was wiederum dazu führte, dass ein NULL-Zeiger an die libopencm3-Uhr-Setup-Funktion übergeben wurde (unsicher warum, aber es könnte sich um einen GCC-Fehler handeln).

Die Uhr-Setup-Funktion hat also die PLL aus Daten konfiguriert, die sich an der Speicheradresse 0x00000000 befinden. Ich bin ziemlich erstaunt, dass dies tatsächlich zu einem PLL-Ausgang von 2,44 MHz führte und nicht abstürzte.

Es ist ganz einfach, dieses Flag zu deaktivieren, indem Sie die folgenden Meson-Standardoptionen übergeben, wenn Sie das Projekt in der Stammdatei meson.build definieren: 'b_staticpic=false', 'b_pie=false'

Dann habe ich das Ninja-Build-Skript gelöscht und neu generiert, und alles war in Ordnung. Mein ursprünglicher Testcode läuft jetzt mit der gewünschten Taktrate von 168 MHz :-)

Für Ihr PCB-Design:

  • Ich habe eine Masseebene unter dem Kristall und den Spuren zur MCU verwendet, was wahrscheinlich eine sehr hohe Streukapazität verursacht.

Dies ist wahrscheinlich kein großes Problem und wahrscheinlich nicht Ihr Problem

  • Ich habe das "Guard Ring" -Konzept völlig missverstanden. Ich habe eine Füllzone für die obere Ebene hinzugefügt (um den Kristall herum) und sie stattdessen an die Grundebene genäht.

Auch nicht kritisch und wahrscheinlich nicht Ihr Problem.

  • Verwendung eines 25-MHz-Quarzes anstelle eines 8-MHz-Quarzes. Das von STMCubeMx vorgeschlagene PLL-Setup scheint den Eingang auf 1 MHz herunterzuteilen, bevor er auf 168 MHz hochmultipliziert wird. Ein 8-MHz-Quarz sollte also gut funktionieren, denke ich.

Dies müssen Sie mit Ihrem Mikrocontroller-Datenblatt überprüfen. Normalerweise können Sie die PLLs so einrichten, dass sie zu Ihrem Kristall passen, aber dies kann mit Sicherheit ein Problem sein. Die Frequenzen müssen bei jedem Schritt der PLL (Teiler, Multiplikator) innerhalb eines Bereichs bleiben.

  • Die Reset-Leitung verläuft direkt unter dem Kristall. Dieser ist aber wiederum mit dem JTAG und einem Taster verbunden und ansonsten passiv.

Es ist auch unwahrscheinlich, dass dies das Problem ist, und es scheint, dass Sie kein "Reset" haben.


Auf neu gestalteten Boards ist der Kristall oft ein Ärgernis, nicht nur das Design, sondern auch die richtige Konfiguration des Chips, weil es schwierig zu debuggen ist und es eher ein Trial-and-Error-Prozess ist, bis es funktioniert.

Auf Hardware-Ebene sollten Sie zuerst Ihren Lastkondensator überprüfen, es ist wahrscheinlich, dass Sie dort ein Problem haben (insbesondere wenn Sie den Quarz gewechselt haben). Einige Kristalle mit einigen MCUs benötigen auch einen seriellen Widerstand, aber ich habe noch nie "Regeln" gesehen, um zu definieren, wann sie verwendet werden müssen, oder die Werte, es scheint eher ein Trial-and-Error-Prozess zu sein.

Versuchen Sie, die Lastkappe des Kristalls mit anderen Werten zu ändern. Sie sollten etwa doppelt so hoch sein wie die im Datenblatt, da sie effektiv in Reihe geschaltet sind. Hier finden Sie weitere Details dazu.

Sehr wahrscheinlich sollten Sie auch die Konfiguration und den Code für die Taktumschaltung überprüfen.

Ich habe aufgehört, Crystal zu verwenden, wenn ich kann, und stattdessen eine externe Uhr verwendet, es ist normalerweise weniger schmerzhaft.

Vielen Dank für Ihren Beitrag. Ich habe tatsächlich schon versucht, die Load Caps zu ändern. Ich habe einige verwendet, die anfangs zu klein waren, und sie einmal durch 33 pF ersetzt. Dies erhöhte die Vpp auf leicht unter 500 mV, wie ich in meinem Beitrag erwähnt habe (vorher waren es ungefähr 300 mV). Der CL des Kristalls wird mit 20 pF angegeben. Nachdem ich gerade mehr gegoogelt habe, scheint es, als ob der STM32-Xin-Pin mindestens 1,2 Vpp benötigt, um zu funktionieren, aber ich habe dies noch in keiner offiziellen STM-Dokumentation gefunden :-/
@JohnnyEgeland - Überprüfen Sie diese Anforderung von 1,2 Vpp sorgfältig. Sehr wahrscheinlich gilt dies für die Verwendung einer externen Uhr, die an den Xin-Pin angeschlossen ist.
@MichaelKaras - Sie haben absolut Recht. Ich nahm an, dass dies auch bei Verwendung eines externen Quarzes der Fall war, und schloss daraus, dass meine gemessene Schwingung zu schwach war, als dass der HSE funktionieren würde. Ich hatte wirklich erwartet, dass die MCU einen Fallback-Mechanismus verwendet (wiederum etwas, was ich in einem nicht offiziellen Dokument gelesen habe), konnte dies aber in den STM-Dokumenten nicht bestätigen. Es stellte sich heraus, dass der Oszillator die ganze Zeit funktionierte, sogar mit sehr falschen Lastobergrenzen (die ich bereits korrigiert habe). Das Problem stellte sich als die von libopencm3 eingerichtete PLL-Konfiguration heraus :-/