Difference between revisions of "AVR Embedded Tutorial - Random/de"

From Free Pascal wiki
Jump to navigationJump to search
(Created page with "{{Translate}} =Zufallsgenerator= ==Vorwort== Ein Zufallsgenerator ist auf einem AVR gar nicht so einfach. Ein '''Random(...)''' aus der Unit '''System''' geht leider '''nich...")
 
Line 38: Line 38:
 
   // UART
 
   // UART
 
   UARTInit;                    // UART inizialisieren.
 
   UARTInit;                    // UART inizialisieren.
   asm sei end;                // Interrupts einschalten.
+
 
 +
  // Interrupts einschalten.
 +
   asm sei end;                 
  
 
   // Hauptschleife
 
   // Hauptschleife
Line 48: Line 50:
  
 
end.</syntaxhighlight>
 
end.</syntaxhighlight>
 +
 +
==Mehrere Würfel==
 +
===Schlechte Lösung===
 +
Man könnte auf den Gedanken kommen und bei mehreren Würfel folgendes zu machen:
 +
<syntaxhighlight lang="pascal">
 +
    Str(Random + 1: 4, s);    // Die Zufallszahl abholen.
 +
    UARTSendString(s);        // Zufallszahl ausgeben.
 +
    Str(Random + 1: 4, s);    // Ist abhängig vom ersten Wurf.
 +
    ...
 +
</syntaxhighlight>
 +
Nur bekommt man das Problem, das die Reihenfolge der Würfe voraussehbar ist. Daher ist die unbrauchbar.
 +
 +
===Ideale Lösung===
 +
Aus diesem Grund habe ich folgenden Code, da kommt es unvorhersehbar.
 +
 +
Einziges Manko, es ist etwas komplizierter, dafür ist jede Zufallszahl unabhängig von den anderen.
 +
Bei diesem Beispiel sind es 15 Würfel.
 +
Der Timer musste noch etwas langsamer gestellt werden, als bei dem Beispiel mit nur einem Würfel.
 +
<syntaxhighlight lang="pascal">
 +
const
 +
  anzWuerfel = 15;
 +
var
 +
  Random: array[0..anzWuerfel - 1] of byte;
 +
 +
  procedure Timer0_Interrupt; public Name 'TIMER0_OVF_ISR'; interrupt;
 +
  const
 +
    RandomCount = 6;
 +
  var
 +
    i: integer;
 +
    rnd: array [0..anzWuerfel - 1] of byte;
 +
  begin
 +
 +
    for i := 0 to anzWuerfel - 1 do
 +
    begin
 +
      Inc(rnd[i]);
 +
      if rnd[i] > i then
 +
      begin
 +
        rnd[i] := 0;
 +
        Inc(Random[i]);
 +
        if Random[i] >= RandomCount then
 +
          Random[i] := 0;
 +
      end;
 +
    end;
 +
  end;
 +
 +
var
 +
  s: ShortString;
 +
  i: integer;
 +
 +
begin
 +
  // Timer 0
 +
  TCCR0A := %00;              // Normaler Timer
 +
  TCCR0B := %011;              // Clock = CPU / 16.
 +
  TIMSK0 := (1 shl TOIE0);    // Enable Timer0 Interrupt.
 +
 +
  // UART
 +
  UARTInit;
 +
 +
  // Interrupts einschalten.
 +
  asm SEI end;             
 +
 +
  // Hauptschleife
 +
  repeat
 +
    UARTReadChar;
 +
    for i := 0 to anzWuerfel - 1 do
 +
    begin
 +
      Str(Random[i] + 1: 4, s);
 +
      UARTSendString(s);
 +
    end;
 +
    UARTSendString(#13#10);
 +
  until 1 = 2;
 +
end.
 +
</syntaxhighlight>
  
 
== Siehe auch ==
 
== Siehe auch ==

Revision as of 17:45, 27 December 2017

Template:Translate

Zufallsgenerator

Vorwort

Ein Zufallsgenerator ist auf einem AVR gar nicht so einfach. Ein Random(...) aus der Unit System geht leider nicht. Dieses Tutorial zeigt, wie man wenigstens einen Würfel auf einem AVR programmieren kann.

Der Bereich der Zufallszahl muss von Anfang an bekannt sein, bei einem klassischen Würfel ist dies 6.

Für die Kommunikation über UART siehe hier:

Ein einfacher Würfel

var
  Random: byte; // Gibt die Zufallszahl zurück.

  procedure Timer0_Interrupt; public Name 'TIMER0_OVF_ISR'; interrupt;
  const
    RandomCount = 6; // Anzahl Würfelaugen
  begin
    Inc(Random);
    if Random >= RandomCount then
      Random := 0;
  end;

var
  s: ShortString;

begin
  // Timer 0
  TCCR0A := %00;               // Normaler Timer
  TCCR0B := %001;              // Clock = CPU
  TIMSK0 := (1 shl TOIE0);     // Enable Timer0 Interrupt.
  
  // UART
  UARTInit;                    // UART inizialisieren.

  // Interrupts einschalten.
  asm sei end;                 

  // Hauptschleife
  repeat
    UARTReadChar;              // Simuliert einen Tastendruck. 
    Str(Random + 1: 4, s);     // Die Zufallszahl abholen.
    UARTSendString(s);         // Zufallszahl ausgeben. 
  until 1 = 2;

end.

Mehrere Würfel

Schlechte Lösung

Man könnte auf den Gedanken kommen und bei mehreren Würfel folgendes zu machen:

    Str(Random + 1: 4, s);     // Die Zufallszahl abholen.
    UARTSendString(s);         // Zufallszahl ausgeben. 
    Str(Random + 1: 4, s);     // Ist abhängig vom ersten Wurf.
    ...

Nur bekommt man das Problem, das die Reihenfolge der Würfe voraussehbar ist. Daher ist die unbrauchbar.

Ideale Lösung

Aus diesem Grund habe ich folgenden Code, da kommt es unvorhersehbar.

Einziges Manko, es ist etwas komplizierter, dafür ist jede Zufallszahl unabhängig von den anderen. Bei diesem Beispiel sind es 15 Würfel. Der Timer musste noch etwas langsamer gestellt werden, als bei dem Beispiel mit nur einem Würfel.

const
  anzWuerfel = 15;
var
  Random: array[0..anzWuerfel - 1] of byte;

  procedure Timer0_Interrupt; public Name 'TIMER0_OVF_ISR'; interrupt;
  const
    RandomCount = 6;
  var
    i: integer;
    rnd: array [0..anzWuerfel - 1] of byte;
  begin

    for i := 0 to anzWuerfel - 1 do
    begin
      Inc(rnd[i]);
      if rnd[i] > i then
      begin
        rnd[i] := 0;
        Inc(Random[i]);
        if Random[i] >= RandomCount then
          Random[i] := 0;
      end;
    end;
  end;

var
  s: ShortString;
  i: integer;

begin
  // Timer 0
  TCCR0A := %00;               // Normaler Timer
  TCCR0B := %011;              // Clock = CPU / 16.
  TIMSK0 := (1 shl TOIE0);     // Enable Timer0 Interrupt.

  // UART
  UARTInit;

  // Interrupts einschalten.
  asm SEI end;              

  // Hauptschleife
  repeat
    UARTReadChar;
    for i := 0 to anzWuerfel - 1 do
    begin
      Str(Random[i] + 1: 4, s);
      UARTSendString(s);
    end;
    UARTSendString(#13#10);
  until 1 = 2;
end.

Siehe auch