Wie programmiert man einen präzisen Timer in C für Linux

Ich wollte einen Timer in C für meinen Raspberry Pi programmieren, der sowohl für 1 ms als auch für 0,1 ms präzise Arbeitsanweisungen ausführt. Da Python zur Laufzeit kompiliert wird, war Python für diesen Zweck leider viel zu langsam. Aus diesem Grund wurde das Programm in C geschrieben. Die 1 ms und 0,1 ms wurden nach der Programmierung mit Hilfe eines Oszilloskops bestätigt.

Nachfolgend eine Erklärung wieso die Library „sys/time.h“ genutzt wurde, sowie ein Codebeispiel mit anschließender Erläuterung. Dieses Codebeispiel eignet sich sehr gut für bitweise Datenübertragung in der Kommunikationstechnik.

Das könnte Sie ebenfalls interessieren: Präzise Timer Interrupts für den Arduino programmieren!

Liste der Komponenten

Timer in C for Linux

Die Library „sys/time.h“

Funktionen wie „usleep()“ oder „nanosleep()“ würden das komplette Programm anhalten. Für einfache Anwendungen mag das vielleicht ausreichen, allerdings war das für meine Zwecke zu ungenau. Ich wollte einen Timer, der wirklich exakt im 1 ms Takt bzw. 0,1 ms Takt arbeitet. Deswegen wurde anstelle von „usleep()“ oder „nanosleep()“ eine andere Lösung gewählt. Die Library „sys/time.h“. Diese kann die aktuelle „System Clock Time“ (System Uhrzeit) auslesen und vergleichen.

Codebeispiel für präzisen Timer in C

#include <sys/time.h>

int main()
{
    struct timeval tval_before, tval_after, tval_result;
    int counter=0;
    bool stop=false;
   
    gettimeofday(&tval_before, NULL);
    while(stop!=true)
    {
        gettimeofday(&tval_after, NULL);
        timersub(&tval_after, &tval_before, &tval_result);
        double time_elapsed = (double)tval_result.tv_sec + ((double)tval_result.tv_usec/1000000.0f);
        
        while(time_elapsed < 0.001)  //1ms; you can change your desired time interval here
        {
            gettimeofday(&tval_after, NULL);
            timersub(&tval_after, &tval_before, &tval_result);
            time_elapsed = (double)tval_result.tv_sec + ((double)tval_result.tv_usec/1000000.0f);
        }
        gettimeofday(&tval_before, NULL);
        
        if (counter==10000)
        {
            stop=true;
        }
            
        else 
        {
            counter++;
        }
    }
    return 0;
}

Erklärung zum Codebeispiel:

Eine Funktion „gettimeofday“ schreibt die aktuelle System Uhrzeit in die Variable „tval_before“. Eine While Schleife wird anschließend solange ausgeführt bis die eigentliche Aufgabe erledigt ist.

Innerhalb der While Schleife wird als Erstes erneut die System Uhrzeit in eine Variable „tval_after“ abgespeichert. Anschließend wird die zeitliche Differenz zwischen „tval_after“ und „tval_before“ gemessen und in „tval_result“ abgespeichert.

Der nächste Schritt des Timers in C erschließt sich nicht sofort auf den ersten Blick: „tv_result“ besteht per Definition aus 2 Teilen. Zum einen ein Sekunden Anteil „.tv_sec“ und zum anderen ein Mikrosekunden Anteil „.tv_usec“. Eben dieser Mikrosekundenanteil muss erst noch durch eine Million geteilt werden, damit man den Wert in Sekunden erhält. Anschließend, kann der Mikrosekundenanteil zum Sekundenanteil addiert werden.

Der addierte Wert wird im Code als „time_elapsed“ bezeichnet. Falls dieser Wert kleiner als eine Millisekunde ist, wird eine weitere innere While Schleife geöffnet, die solange den Wert für „time_elapsed“ neu berechnet, bis exakt 1 ms vergangen ist. Anschließend wird mittels der „gettimeofday“ Funktion der Wert für „tval_before“ neu festgelegt.

Da zu diesem Zeitpunkt exakt 1 ms vergangen ist, kann der Timer nun seinen eigentlichen Arbeitsschritt ausführen. In diesem einfachen Codebeispiel wird lediglich eine Variable „counter“ um 1 erhöht. Das bedeutet für jeden Intervallschritt (im Codebeispiel 1 ms) erhöht sich der counter um 1. Sobald ein festgelegter Wert für counter erreicht wurde stoppt das Programm. In diesem Fall ist der festgelegte Wert 10000. Anschließend wird die While Schleife beendet. Aber dieser Teil des Codes kann natürlich problemlos für die eigenen Zwecke angepasst werden.

Meine Messungen mit dem Oszilloskop haben eine exakte Frequenz von 1 ms gemessen, sogar 0,1 ms wurde exakt gemessen. Dieses Codebeispiel eignet sich deswegen auch sehr gut für eine exakte Datenübertragung in der Kommunikationstechnik.

Dateien herunterladen

4 Gedanken zu “Wie programmiert man einen präzisen Timer in C für Linux

Schreibe einen Kommentar

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


*