Das Erzeugen wirklich zufälliger Zahlen auf einem Mikrocontroller ist eine bekannte schwierige Aufgabe.
Eine Möglichkeit besteht darin, zwei verschiedene Uhren zu betreiben und die Zeitverschiebung zwischen ihnen zu messen.
Der PIC16F1783, den ich benutze, hat zwei Uhren. Eine mit einem externen Kristall und dem LFINTOSC, der den Watchdog antreibt.
Gibt es eine Möglichkeit, an den LFINTOSC zu gelangen, während Sie von der externen Kristalluhr aus laufen?
Eine Idee, die ich hatte, war, den Watchdog ablaufen zu lassen und den Wert von TMR2 zu überprüfen, aber es funktioniert nicht, weil TMR2 durch Watchdog-Resets zurückgesetzt wird.
Man könnte einen Zähler in einer engen Schleife in das EEPROM schreiben und den Watchdog ablaufen lassen und dann den Inhalt des EEPROM überprüfen, aber dies scheint sehr unelegant zu sein. Bearbeiten: Es ist viel besser, in den Arbeitsspeicher zu schreiben, wie in einem der Kommentare vorgeschlagen.
Gibt es einen besseren Weg? Ohne externe Schaltkreise und ohne ADC-Rauschen (das möglicherweise nicht immer vorhanden ist)?
Datenblatt: http://ww1.microchip.com/downloads/en/DeviceDoc/40001579E.pdf
Bearbeiten: Ich möchte, dass die Zufallszahl eine GUID generiert, damit mehrere Geräte, die denselben RS485-Bus verwenden, voneinander unterschieden werden können. Meine Idee ist es, etwas Ähnliches wie die 1-Draht-Geräteerkennung zu verwenden. Dazu muss ich jedoch auf verschiedenen Geräten unterschiedliche GUIDs haben, und ich möchte den Aufwand vermeiden, sie mit eindeutigen IDs programmieren zu müssen.
quelle
Antworten:
Okay, ich habe einen Weg gefunden, genau das zu tun, was ich in der Frage gestellt habe, ohne die WDT einzubeziehen.
Es ist, gelinde gesagt, ein kleiner Hack und opfert zwei Pins (BEARBEITEN: nur ein Pin wird geopfert) (erfordert jedoch keine externen Komponenten. Wenn Sie also zwei nicht verwendete Pins haben, ist dies "kostenlos").
Die Idee ist, die PSMC (Programmable Switch Mode Control) des PIC16F1783 zu verwenden.
Dies kann vom INTOSC aus getaktet werden, indem der HFINTOSC mit der 4x PLL verbunden wird, wodurch eine Frequenz von 64 MHz zum Takten des PWM-Ausgangs erhalten wird.
Der PWM-Ausgang kann dann an einen anderen Pin auf der Platine geleitet werden.
Wenn nun der externe Kristall zum Takten der CPU verwendet wird, kann das PWM-Signal in einer engen Schleife gelesen werden. Da die beiden Takte nicht synchronisiert sind, sollte zwischen den beiden Takten Jitter auftreten, und der PWM-Eingang sollte einen unvorhersehbaren Jitter enthalten.
Um diesen Jitter zum Erstellen zufälliger Werte zu verwenden, könnte ein 16-Byte-Prüfsummenarray verwendet werden. Der TMR1 könnte dann so konfiguriert werden, dass er so schnell wie möglich läuft, und jedes Mal, wenn sich das PWM-Signal ändert, könnte der TMR1-Wert an den Anfang des Arrays geschrieben werden. Dann könnte die MD5-Summe des Arrays genommen und in dasselbe Array zurückgeschrieben werden.
Durch einige tausendmaliges Wiederholen dieser Prozedur könnte ein 16-Byte-MD5-Hash erstellt werden, der völlig zufällig sein sollte.
Ein MD5-Prüfsummenalgorithmus passt jedoch kaum auf den PIC16F1783, sodass dies bei etwas leistungsstärkeren Chips eher von Nutzen ist. Die gleiche Idee könnte jedoch verwendet werden, indem einfach ein Byte um den TMR1-Wert erhöht und einige tausend Mal umbrochen wird, bevor es als "zufällig genug" betrachtet wird.
Dies kann nur fehlschlagen, wenn die interne 500-kHz-Quelle irgendwie mit dem Quarzoszillator synchronisiert wird. Ich habe keine Ahnung, ob das möglich ist.
Aktualisieren:
Der folgende Code scheint in meinem Labor in der Praxis zu funktionieren:
Update 2:
Es wird nur ein Pin geopfert, da der PWM-Pin des Ausgangs gelesen werden kann. Sie müssen ihn nicht an einen Eingang weiterleiten und diesen lesen.
quelle