Die akzeptierte Antwort von jfpoilpret ist sehr gut geschrieben, vollkommen gültig und in 99% der Fälle werde ich genau das tun, was er erklärt. Seine Lösungen liegen gut innerhalb Ihrer definierten Parameter, daher sollten sie sehr gut funktionieren. Aber was ist besser als " sehr gut "? Perfektion! Schließlich geht es darum, einen genauen Wert zu generieren. Wie gesagt, nah genug ist in den meisten Fällen gut (wohl alle), und selbst wenn Sie mit etwas wie einer Uhr arbeiten, wenn 1 Sekunde 1 Sekunde sein muss, müssen Sie immer noch Unvollkommenheiten bei ererbten Teilen erleiden.
Was ich vorschlagen werde, ist nicht immer möglich. In einigen Fällen ist dies möglich, jedoch mit viel mehr Aufwand und Aufwand als in diesem Fall. Ist es wert, von Fall zu Fall abhängig zu sein. Mein Ziel ist es hauptsächlich, eine Alternative für zukünftige Referenzen aufzuzeigen, die in Randfällen besser ist. Dies wurde für unerfahrene Arduino-Benutzer geschrieben, die keine umfassende Erfahrung in der Elektronik haben.
Für fortgeschrittene Leute wird dies wahrscheinlich zu ausführlich und niedergeschlagen aussehen. Aber ich glaube, dass dieselben Leute es wahrscheinlich bereits wissen und diese Antwort nicht brauchen. Dies gilt auch für jeden Mikrocontroller sowie jeden Hersteller und jede Architektur. Bei anderen Mikrocontrollern müssen Sie jedoch das richtige Datenblatt konsultieren, um die richtigen Register sowie Namen und Werte für die Vorskalierung zu ermitteln.
In Ihrem Fall benötigen Sie eine bestimmte Frequenz und das Schöne daran ist, dass genau 56 kHz tatsächlich sehr einfach erreicht werden können (ohne praktische Mängel der Teile). Dies ist also auch ein perfekter Beispielfall.
Das Erzeugen eines Signals hängt von den Zeitgebern und der Taktquelle des Mikrocontrollers ab, wie durch jfpoilpret gut erklärt. Seine Antwort befasst sich nur mit dem Problem einer Sichtweise, und das ist das Spielen mit Timern. Sie können aber auch an der Taktquelle herumspielen oder sogar an Synergieeffekten und hervorragenden Ergebnissen. Durch Ändern der Umgebungsparameter, in diesem Fall Hacken des Systems und Ersetzen der Taktquelle, können wir ein bestimmtes Problem viel, viel einfacher und einfacher lösen.
Um daran zu erinnern, müssen Sie aufgrund des Umschaltens des Pin-Status den ISR zweimal mehr als die Signalfrequenz ausführen. Dies ist 112.000 Mal pro Sekunde. 56.000 und 16.000.000 summieren sich nicht sehr gut, wie bereits erwähnt. Wir müssen entweder die Signalfrequenz oder die Taktfrequenz ändern. Lassen Sie uns zunächst mit einer unveränderlichen Signalfrequenz umgehen und eine bessere Taktrate finden.
Es wäre am einfachsten, einen Takt mit einer Größenordnung größer als 56 kHz (oder 112 kHz, aber praktisch gleich) zu wählen, da Sie nur Nullen hinzufügen und diese Art der Mathematik für die meisten Menschen am einfachsten ist. Leider ist alles auf dieser Welt eine Art Kompromiss mit etwas. Nicht jeder Wert wird funktionieren.
Das erste Beispiel ist eine zu niedrige Taktgeneratorgeschwindigkeit.
Wenn Sie eine 56.000-Hz-Uhr wählen, können Sie nichts tun, da Sie den ISR in jedem Zyklus aufrufen müssen und nichts anderes tun können. Es ist völlig nutzlos. Wenn Sie eine 10-mal schnellere Geschwindigkeit (560 kHz) wählen, haben Sie 9 (10 Zyklen, damit der Timer seinen Maximalwert erreicht - ein Zyklus, um die ISR-Funktion aufzurufen) Mikrocontroller-Zyklen, um Ihre Arbeit zu erledigen, und dies kann durchaus nicht ausreichen. Sie benötigen einfach oft mehr Rechenleistung.
Wenn Sie andererseits einen viel zu großen Wert als 56 MHz wählen, kann der Mikrocontroller einfach nicht damit arbeiten. Es ist viel zu schnell. Wenn Sie also einfach den größten Wert im Shop auswählen, wird dies auch nicht schaden.
Das Original Arduino Uno R3 verfügt über einen Standardtakt mit 16 MHz, sodass alles, was langsamer ist, garantiert funktioniert. Der nächste Wert, der eine Größenordnung größer als 56 und kleiner als 16 MHz ist, ist 5,6 MHz. Dies führt dazu, dass der ISR alle 50 Zyklen aufgerufen werden kann und die perfekte Timerfrequenz von 112.000 Hz erzeugt wird. Und Ihr Signal wird genau 56 kHz sein. Sie haben 49 MCU-Zyklen, um Ihr Programm zwischen ISR-Aufrufen auszuführen, aber es ist immer noch ungefähr 1/3 der Geschwindigkeit der ursprünglichen Uhr. Man kann 112 als Basis verwenden und einen 11,2-MHz-Takt verwenden, und dies ergibt ungefähr 2/3 des 16-MHz-Resonators. Die ISR-Funktion wird alle 100 Zyklen aufgerufen und erzeugt immer noch ein perfektes 56-kHz-Signal.
Bei diesen Werten bestehen jedoch zwei Hauptprobleme.
Das erste Problem hängt stark von Ihren Anforderungen ab: Sie opfern etwa 1/3 (mit 11,2 MHz) Ihrer maximalen Rechenleistung, um die genaue Signalfrequenz zu erhalten, die einen leicht zu findenden Registerwert (OCR iirc ) verwendet. Sie können damit einverstanden sein oder Sie können nicht.
Das zweite Problem ist ein harter Showstopper : Es ist sehr einfach, Werte zu finden, aber sehr oft existieren sie einfach nicht als hergestellte Taktquelle. Dies ist Farnells Resonator-Webseite , auf der einfach sowohl 5,6 MHz als auch 11,2 MHz fehlen.
Um dies zu umgehen, können wir uns die verfügbaren Resonatorwerte ansehen und etwas anderes herausfinden, mit dem genau die gewünschten Werte erzeugt werden können. Wenn wir 56 durch 4 teilen, erhalten wir 14 und zum Glück gibt es einen 14-MHz-Resonator. Dies bietet uns eine viel höhere Geschwindigkeit und Leistung sowie einen ebenso leicht zu findenden Registerwert. Um den ISR 112.000 Mal pro Sekunde aufzurufen, müssen wir den Wert der Dezimalzahl 124 oder der Hexadezimalzahl 0x7C in das OCR-Register eingeben. Wenn wir also 124 Zyklen + 1 zählen, um den ISR aufzurufen, erhalten wir unseren gewünschten perfekten Wert.
NB
- ISR - Interrupt Service Routine (dies ist der Code, der nur bei generierten Interrupts ausgeführt wird)
- Wie groß Ihr Programm sein kann, hängt von der Speichergröße ab! Es hat nichts mit der Taktrate zu tun und hat nichts damit zu tun, wie oft Sie den ISR anrufen.
Wenn der Mikrocontroller mit dem Programmbefehl startet, wird ein Zähler erhöht. Wenn ein Interrupt generiert wird, wird der ISR aufgerufen und dieser Wert in einem speziellen Register gespeichert. Wenn der ISR-Code vollständig ist, wird der Wert des Programmzählers aus diesem speziellen Register wiederhergestellt und das Programm wird dort fortgesetzt, wo es unterbrochen wurde, als wäre es nie geschehen.
Ich werde ein äußerst niedergeschlagenes Beispiel geben. Wenn Sie Purist sind, warne ich Sie: Nasen- und Augenblutungen können auftreten.
Stellen Sie sich vor, Sie müssen von irgendwo nach irgendwo gehen. Die schrittweisen Routenanweisungen sind Ihr Hauptprogramm und seine Befehle. Wie schnell Sie gehen oder laufen, hängt von Ihrer "Taktrate" ab, jedoch nicht von den Routenanweisungen (30 Schritte vorwärts, 1 Umdrehung 90 Grad links, 10 Schritte vorwärts, 45 Grad rechts usw.). Sie sind immer gleich . Stellen Sie sich jetzt vor, ein kleines Kind oder ein gieriger korrupter Lokalpolitiker lösen ab und zu Ihre Schuhe. Dies ist das Ereignis, das einen Interrupt erzeugt. Dann halten Sie nach Ihrem letzten Schritt an, knien nieder und binden Ihren Schuh erneut. Dies ist Ihr ISR-Programm.
Dann fahren Sie von der Stelle fort, an der Sie angehalten haben. Sie beginnen nicht von vorne. Wenn Sie ohne Sorge in der Welt und mit der ganzen Zeit gehen, ist es Ihnen egal, auch wenn Sie Ihren Schuh bei jedem zweiten Schritt binden müssen. Wenn Sie dies jedoch mit zeitlichen Einschränkungen tun, z. B. bei den Olympischen Spielen in 100 Metern Entfernung (oder vor einem hungrigen, fleischfressenden Raubtier), kann das Anhalten und Binden Ihrer Schuhe schwerwiegende Folgen haben. Gleiches gilt für Mikrocontroller. Selbst wenn Sie nur eine Codezeile ausführen, wird Ihr Programm fortgesetzt, wenn auch langsam. Wenn Sie sich überhaupt nicht für Geschwindigkeit interessieren, ist dies kein Problem. Wenn Sie einige zeitbezogene Aktionen ausführen müssen, z. B. andere zeitabhängige Aktionen, können Interferenzen sehr unerwünscht und problematisch sein.
Weniger ist mehr! Eine schnellere Uhr ist nicht immer besser. Langsam getaktete Geräte verbrauchen erheblich weniger Strom. Dies kann ein entscheidender Punkt in einem batteriebetriebenen Gerät sein.
Die benötigten Zyklen werden aus folgenden Formeln abgeleitet:
(Taktrate / (Prescaler-Wert * benötigte ISR-Ruffrequenz)) - 1