Ein Rechtecksignal mit hoher Frequenz direkt aus dem Arduino Uno ausgeben

Mit der schon vorher besprochenen Funktion lassen sich hohe Rechteck Frequenzen erreichen.

while(k==10) {
  PORTB=B00111100; // 15
  asm("nop\n nop\n");
  PORTB=B00000000; // 0
}

Zwei Assembler Takte (nop Befehle) werden zur Symmetrie hinzugefügt, da die while(1) Schleife auch zwei Takte benötigt. Das sind 6 Takte. 16.000 kHz / 6 Takte = 2666,7 kHz.

Wenn zusätzlich 2 x 1 nop Anweisungen eingefügt wird, ergeben sich 8 Prozessor Takte oder eine Frequenz von 16 MHz / 8 Takte = 2 MHz.

while(k==10) {
  PORTB=B00111100; // 15
  asm("nop\n nop\n");
  asm("nop\n");    // + 1 nop
  PORTB=B00000000; // 0
  asm("nop\n");    // + 1 nop
}

Hier die Tabelle für weitere nop Befehle und die sich dazu ergebenden Frequenzen.

nop Tabelle

1. Die Berechnung der Frequenz aus vorgegebenen nops.

2. Für eine gewünschte Frequenz ergeben sich diese nops.

Durch ein wenig rumspielen mit den Berechnungen 1. und 2. bekommt man schnell zu der gewünschten Frequenz und sieht was machbar ist.

Das sind beim Arduino Uno die höchsten realisierbaren Frequenzen.
Nur mit einem schnelleren Prozessortakt bekommt man noch höhere Frequenzen.

Nun liegt nahe die nops in eine for Schleife zu legen. Und das funktioniert auch für 0 – 6 Schleifendurchläufe. Hier scheint der Übersetzer 0 – 6 asm-nop Anweisungen auszuführen, genau wie oben beschrieben. Bei 7 Schleifen Durchläufen ändert sich das aber gänzlich und es wird eine Frequenz wie bei 50 einzelnen nops ausgegeben, also 150,94 kHz. Bei 8 nops in der Schleife sind es 133,33 kHz  und bei 9 dann 119,40 kHz. Das wird dann so fortgesetzt.

Das Testprogramm hierfür sieht so aus.

int k=10, n=10, i;

while(k==10) {
  PORTB=B00111100; // 15
  asm("nop\n nop\n");
  for(i=0;i< n; i++)
    asm("nop\n");
  PORTB=B00000000; // 0
  for(i=0;i< n; i++)
    asm("nop\n");
  }

Hier lässt sich die Frequenz für 7 oder mehr nops berechnen.

Das ganze etwas übersichtlicher in Tabellenform

nop Tabelle2

Hiermit lassen sich also nur ausgewählte Frequenzen realisieren. Gegenüber den einzelnen nop Anweisungen, ist in der Schleife nur noch jede 7. Frequenz auswählbar. Das Programm ist dann jedoch wesentlich übersichtlicher und universeller einsetzbar.

von Matthias Busse

2 Gedanken zu „Ein Rechtecksignal mit hoher Frequenz direkt aus dem Arduino Uno ausgeben

  1. Markus

    Hallo,

    das mit den nop-Anweisungen ist eine gute Idee und hat mir bei meinem vorhaben schon etwas weiter geholfen. Wobei so richtig will es bei mir nicht laufen.

    Ich bin aktuell dabei mit einem Arduino Mega einen Simulator für Inkrementelle Drehgeber zu basteln.
    Als 2 90° Phasenversetzte Rechtecksignale.
    Das ganze würde ich gerne mit Vor- und Rückwärtsschalter und 3 Geschwindigkeitsstufen machen.

    Bisher regele ich die Geschwindigkeitsstufen per Interrupt und nop-Anweisungen in for-Schleifen:
    void loop(){
    PORTA = B01000100;
    for(i=0;i< n+80; i++)
    asm("nop\n");
    PORTA = B10000100;
    for(i=0;i< n+80; i++)
    asm("nop\n");
    PORTA = B10001000;
    for(i=0;i< n+80; i++)
    asm("nop\n");
    PORTA = B01001000;
    for(i=0;i< n+80; i++)
    asm("nop\n");
    }

    Die Interrupts 0 und 1 verändern den Wert von n.

    Allerdings bekomme ich bei höheren Frequenzen nur 1 sauberes Signal, das zweite ist ziemlich verschliffen und der Pegel ist viel zu klein für minen 5V/24V umsetzer. . Hast du eine Idee wie man das ganze besser/anders lösen kann?

    Antworten
    1. admin Beitragsautor

      Hallo,

      die Port Ausgaben sehen gut aus.
      Wenn aus einem Port nur ein viel zu kleines Signal kommt, hat vielleicht der Ausgang einen mit bekommen, oder ist falsch geschaltet?

      Grüße,
      Matthias

      Antworten

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.