Bei manchen Anwendungen wie z. B. Spielen werden Zufallszahlen benötigt, doch nicht immer steht ein
Zufallsgenerator zur Verfügung. In dem folgenden Experiment versuchen wir Zufallszahlen selbst zu generieren. Das Problem
bei Erzeugung von Zufallszahlen beschränkt sich meistens auf die erste Zahl. Nachdem ein Mikrocontroller eingeschaltet
wurde, die erste Zufallszahl bereits generiert wurde, können bei Bedarf für die Folgezahlen diverse Algorithmen eingesetzt
werden. Diese interessieren uns hier nicht.
In dem Beispiel wird die erste Zahl durch das Betätigen eines Tasters erzeugt. Dabei gehen wir davon aus, dass
der Mensch kaum in der Lage ist, einen Taster stets gleich lang zu drücken. Die Unterschiede, auch wenn sie im Bereich
von Mikrosekunden liegen, sind stets da. Die Zeit der Betätigung kann erfasst werden. Daraus kann anschließend eine Zahl
ermittelt werden, die durchaus als eine Zufallszahl betrachtet werden kann.
Mikrocontroller PIC12F509
Der Mikrocontroller PIC12F509 hat in dem Versuch die Aufgabe, die Betätigung eines Tasters zu erkennen und
auszuwerten. Anschließend erfolgt, nachdem eine Zufallszahl ermittelt worden ist, die codierte Ausgabe der Zahl an den
7-Segmentanzeige-Treiber 74HC4511N. In dem Versuch werden alle GPIOs des Mikrocontrollers in
Anspruch genommen.
Ohne den Treiber könnte man nicht ohne Weiteres eine 7-Segmentanzeige ansteuern. Der PIC12F509 stellt
lediglich fünf Ausgänge zur Verfügung. Eine 7-Segmentanzeige besteht jedoch aus sieben Elementen, die einzeln angesprochen
werden möchten.
Die 7-Segmentanzeige 51011AH verfügt über 10 Anschlüsse. Sieben davon werden für die einzelnen Elemente der Anzeige
gebraucht. Zwei Pins müssen an die Masse angeschlossen werden. Der 10. Pin (Nummer 5) wird für den Punkt gebraucht, den
wir jedoch in dem Versuch nicht berücksichtigen.
// ***************************************************************************
// Zufallszahlen mit PIC12F509
// MPLAB X IDE v6.00
// XC8-Compiler 2.4
// ***************************************************************************
#pragma config OSC = IntRC // Internal RC oscillator
#pragma config WDT = OFF // Watchdog Timer Enable bit (disabled)
#pragma config CP = OFF // Code Protection bit
#pragma config MCLRE = OFF // GP3/MCLR Pin Function Select bit
#include <xc.h>
#include <stdbool.h>
#define _XTAL_FREQ 4000000 // Taktfrequenz
#define Ausgang_D1 GPIObits.GP0 // Ausgänge für den Treiber
#define Ausgang_D2 GPIObits.GP1
#define Ausgang_D3 GPIObits.GP5
#define Ausgang_D0 GPIObits.GP4
#define Taster_NO GPIObits.GP2 // Schließer
#define Taster_NC GPIObits.GP3 // Öffner
int Zufallszahl = -1; // Zufallszahl Startwert
void main(void) {
TRIS = 0b00001100; // GPIOs: 0-Ausgang, 1-Eingang
while (true) { // Endlosschleife
if (Taster_NO == true & Taster_NC == false) { // Taster EIN
Zufallszahl = -1;
__delay_ms(10);
while (Taster_NO == false & Taster_NC == true) { // Taster AUS
++Zufallszahl; // Inkrementieren
if (Zufallszahl > 9) { Zufallszahl = -1; } // Zurücksetzen
__delay_us(100); // Warten 100 Mikrosek.
}
}
Ausgang_D0 = false; // Alle Ausgänge AUS
Ausgang_D1 = false;
Ausgang_D2 = false;
Ausgang_D3 = false;
if (Zufallszahl == -1) { // Keine Zufallszahl = Anzeige Aus
Ausgang_D0 = true;
Ausgang_D1 = true;
Ausgang_D2 = true;
Ausgang_D3 = true;
}
switch (Zufallszahl) { // Treiber-Ausgänge setzen
case 1: Ausgang_D0 = true;
break;
case 2: Ausgang_D1 = true;
break;
case 3: Ausgang_D0 = true;
Ausgang_D1 = true;
break;
case 4: Ausgang_D2 = true;
break;
case 5: Ausgang_D0 = true;
Ausgang_D2 = true;
break;
case 6: Ausgang_D1 = true;
Ausgang_D2 = true;
break;
case 7: Ausgang_D0 = true;
Ausgang_D1 = true;
Ausgang_D2 = true;
break;
case 8: Ausgang_D3 = true;
break;
case 9: Ausgang_D0 = true;
Ausgang_D3 = true;
}
__delay_ms(100); // Wartezeit 100 ms
}
}
Die Testschaltung
Testschaltung
Die Verwendung eines mechanischen Schalter bzw. Tasters bringt mit sich gleich das Problem des Prellens.
Ohne Gegenmaßnahmen wird die Schaltung einwandfrei nicht funktionieren. Daher kommt hier ein Taster mit einem
Wechslerkontakt zum Einsatz. Bei der Betätigung des Tasters werden gleichzeitig beide Kontakte, Schließer und Öffner
auf ihre Zustände abgefragt. Gekoppelt mit einer kleinen Wartezeit von 10 ms bekommt man durchaus zufriedenstellende Ergebnisse.
Nach Betätigung des Tasters geht das Programm in eine While-Schleife, die sich alle 10 Mikrosekunden wiederholt. Bei
jedem Durchlauf wird die Zufallszahl beginnend mit -1 inkrementiert. Hier gehen wir davon aus, dass ein Tastendruck mindestens
1ms andauert
(nachdem die 10 ms der Prellzeit abgelaufen sind). Sobald die Zufallszahl den Wert 10 erreicht, wird sie wieder auf -1
zurückgesetzt. So werden laufend die Zahlen (Ziffern) 0 bis 9 „produziert“. Die Schleife wird unterbrochen, wenn der
Taster wieder losgelassen wird. Am Ende bleibt eine Zahl, die, da die Zeiten extrem kurz sind, vom Menschen nicht
reproduziert werden kann: eine Zufallszahl.
Die Zahl wird dann anschließend BCD-codiert an den Anzeigentreiber weitergeleitet. Dafür sind die Ausgänge des
Mikrocontrollers GP0, GP1, GP4 und GP5 zuständig. Der Anzeigentreiber entschlüsselt dann ohne unsere Einwirkung den
Code und schaltet entsprechende Elemente der 7-Segment-Anzeige ein. Es werden Ziffern von 0 bis 9 generiert. Sollte durch
Störung keine Zufallszahl generiert werden, bleibt die Anzeige aus.