- LiFePO4 Speicher Test         
Seite 1 von 3 123 LetzteLetzte
Ergebnis 1 bis 10 von 23

Thema: sehr Kurze Warteschleifen für das korrekte Timing

  1. #1
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076

    sehr Kurze Warteschleifen für das korrekte Timing

    Anzeige

    Powerstation Test
    Ich hab mal eine Frage in die Runde:

    Wenn ich z.B. ein LCD Display ansteuere und im Datenblatt steht:
    Data Setup Time mindestens 500ns,

    muss ich damit rechnen, dass meine CPU schneller arbeitet und demnach
    ist ein Wartezyklus erforderlich.

    Im Einfachsten Falle geht das natürlich mit delay_ms(1);
    Einen Millisekundentimer hat man ja meist immer am laufen.

    Ist natürlich "reine Zeitverschwendung"

    Nicht lachen.....

    Nun könnt ich mit NOP's die Zeit überbrücken.
    ein NOP bei mir sind 13,88ns (72MHz Takt)
    das wären dann 500ns / 18,88 = 36,023 NOPs für 500ns, also 37
    Ist natürlich recht speziell und nicht sonderlich kompatibel

    Oft sehe ich "for i" Schleifen, die je nach Optimierung und Compiler Einstellungen
    aber völlig undefinierte Zeiten erzeugen.

    Leide ich am Zeitverschwendungssyndrom ? oder wie macht Ihr das...

    Siro

  2. #2
    HaWe
    Gast
    ich verwende für solche "Probleme" grundsätzlich Multitasking, und zwar
    - für Arduino: Scheduler.h (kooperativ), bei delay() wird die Timeslice trotzdem auf den nächsten Task weitergestellt, es geht also keine cpu-Zeit "verloren" ("non-blocking"),
    - und für den Raspberry Pi: POSIX pthread (preemptiv), da kann sowieso jeder Task tun was nötig ist, sogar mit verschiedener Priorität, und delay() klappt hier ebenso "zeitsparend" ("non-blocking") über die wiringPi lib.

    (ein Display ist ja nicht zeitkritisch, man kann sowieso nur alle 50 Milli- (!) Sekunden ein neues Bild wahrnehmen - es darf nur der übrige Programmablauf dadurch nicht blockiert werden.)

  3. #3
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076
    Hallo HaWe, Danke für deine Rückmeldung.
    Mit Multitasking ist das sicher eine gute Lösung.
    Habe bisher nur mit "einem" Task und tonnenweise Interrupts gearbeitet.
    Da möcht ich mein System natürlich nicht ausbremsen.

    Ich hab grad ein Paradebeispiel für "unsicheren" Code.

    Ohne meine Compileroptimierung läuft das Display einwandfrei.
    Schalte ich die "C" Optimierung ein, egal welche Stufe, funktioniert das Display nicht mehr.

    Das Problem ist hier eindeutig das "Timing" was ich grad versuche "sinnvoll" zu ordnen.

    Code:
    void LCD_DataOut8(U8 data)
    {
      LCD_RS_LOW;
      LCD_RW_LOW;
      LCD_EN_HIGH;
      Delay_ms(2);  /* ist hier nicht erforderlich */
    
      /* write the data byte, THREAD SAFE ??? RMW problem auf den PORTs */
      GPIO_CLR1 = LCD_DATA_BITS;
      GPIO_SET1 =  ((U32)(data) << 20);
      Delay_ms(2);   /* OHNE Delay gibt es ein TIMING PROBLEM sofern die C-OPTIMIERUNG eingeschaltet ist */
    
      LCD_EN_LOW;
      Delay_ms(2);   /* normalerweise nicht erforderlich */
    }

  4. #4
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    04.09.2011
    Ort
    Hessen
    Beiträge
    707
    Warten mit NOPs geht natürlich bei "richtigen" Mikrocontrollern. Alles was z.B. die Taktfrequenz regelt oder mehrere Kerne hat, ist da weniger geeignet.

    Für hardwarenahe Programmierung fehlt mir meist die Zeit, meist greife ich für schnelle Entwicklungen auf Dinge wie mbed zurück, da gäbe es mehrere Ansätze:
    https://developer.mbed.org/handbook/Timeout
    https://developer.mbed.org/handbook/RTOS#rtos-timer
    https://docs.mbed.com/docs/getting-s...l_Guide/MINAR/

  5. #5
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    11.12.2007
    Ort
    weit weg von nahe Bonn
    Alter
    39
    Beiträge
    3.416
    meiner Erfahrung nach, haben alle Controller < 100Mhz irgendwo ein Register oder ein Makro zur Compilezeit, welches über die Taktrate informiert und in der regel innerhalb der <delay.h> ausgewertet wird. An diese Methode kann man sich ja anhängen! Controller > 100Mhz (in der Regel auch Mehrkerner) haben fast immer ein Cycleregister, weches nebenher in einem festen Takt (i.d.R. definiert aber auch manchmal programmierbar) mitzählt. Der Zugriff darauf ist dann immer die Kunst
    Es gibt 10 Sorten von Menschen: Die einen können binär zählen, die anderen
    nicht.

  6. #6
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    05.11.2007
    Beiträge
    1.076
    @Picture.
    Bei den PICs hab ich auch die ASM Zyklen gezählt, das ging wunderbar.

    Bei "C" weia man aber leider nicht was der Compiler draus macht. Ich hab grad das kalte Grausen bekommen als ich mir den "optimierten" ASM Code angesehen habe.
    Kann man kaum noch nachvollziehen.
    Ich möcht halt "möglichst sicher" programmieren und da lohnt es ab und an mal etwas genauer "nachzuhaken" wie man das am besten macht.
    Oder sogar mal etwas "experimentieren"

    @Mxt:
    Ich programmiere immer "alles neu" ganz unten. Benutze keine Bibliotheken.
    Damit mache ich mir zwar das Leben schwer, aber ......

    @Ceos:
    Ja, da bin ich auch grad dran. Ich lasse einen Timer frei laufen, im Mikrosekundentakt.
    Den Zählerstand lese ich und warte bis er xxx Mikrosekunden überschritten hat.

    count = TimerCount+20; /* warte 20 Mikrosekunden */
    while (Timercount < count) ;

    Problem: Der Timer läuft bei 32 Bit nach rund 1,19 Stunden über
    Das muss ich noch berücksichtigen....
    Geändert von Siro (23.06.2016 um 16:17 Uhr)

  7. #7
    Erfahrener Benutzer Roboter-Spezialist
    Registriert seit
    13.01.2014
    Beiträge
    454
    Blog-Einträge
    3
    Überlaufproblem: Sofern 'TimerCount' und 'old' unsigend sind, geht folgendes:
    Code:
    old = TimerCount;
    while (Timercount-old < 20) ; // warte 20µs

  8. #8
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    07.03.2011
    Beiträge
    1.899
    Zitat Zitat von Siro Beitrag anzeigen
    @Picture.
    Bei den PICs hab ich auch die ASM Zyklen gezählt, das ging wunderbar.
    In C muß man das natürlich nicht. Dafür gibts fertige Funktionen bzw Macros (XC8 Users Guide)
    __DELAY_MS, __DELAY_US, __DELAYWDT_US, __DELAYWDT_MS
    Synopsis
    __delay_ms(x) //request a delay in milliseconds
    __delay_us(x) //request a delay in in microseconds

    Description
    It is often more convenient to request a delay in time-based terms, rather than in cycle
    counts. The macros __delay_ms(x) and __delay_us(x) are provided to meet this
    need. These macros convert the time-based request into instruction cycles that can be
    used with _delay(n). In order to achieve this, these macros require the prior defini-
    tion of preprocessor symbol _XTAL_FREQ, which indicates the system frequency. This
    symbol should equate to the oscillator frequency (in hertz) used by the system.
    On PIC18 devices only, you can use the alternate WDT-form of these functions, which
    uses the CLRWDT instruction as part of the delay code. See the _delaywdt function.
    The macro argument must be a constant expression. An error will result if these macros
    are used without defining the oscillator frequency symbol, the delay period requested
    is too large, or the delay period is not a constant.
    Diese Funktionen/Macros werden natürlich nicht "wegoptimiert". Also am Anfang des Codes
    #define _XTAL_FREQ xxxx

    und dann einfach

    _delay_us(1)

    Bei Zeiten im Submikrosekundenbereich lohnt die Verwendung eines Timers nicht wirklich.

    MfG Klebwax

    PS: warum du eigentlich ein Delay von 2 Millisekunden programmierst, obwohl du eigenlich 500 Nanosekunden brauchst, erschließt sich mir nicht ganz.
    Geändert von Klebwax (23.06.2016 um 17:01 Uhr)
    Strom fließt auch durch krumme Drähte !

  9. #9
    Erfahrener Benutzer Robotik Einstein
    Registriert seit
    27.08.2013
    Ort
    Region Basel
    Alter
    66
    Beiträge
    2.435
    Hallo, Siro,
    Zitat Zitat von Siro Beitrag anzeigen
    Nicht lachen.....

    Nun könnt ich mit NOP's die Zeit überbrücken.
    ein NOP bei mir sind 13,88ns (72MHz Takt)
    das wären dann 500ns / 18,88 = 36,023 NOPs für 500ns, also 37
    Ist natürlich recht speziell und nicht sonderlich kompatibel
    NOPs verwendet man eigentlich nur, wenn man nur ein paar braucht, sonst bremst man die CPU aus.
    Etwas längere Zeiten erreicht man mit einem Aufruf einer leeren Unterroutine, besonders das Retten und Laden vom Stack braucht doch einige Zyklen mehr als ein NOP.

    Zitat Zitat von Siro Beitrag anzeigen
    Oft sehe ich "for i" Schleifen, die je nach Optimierung und Compiler Einstellungen
    aber völlig undefinierte Zeiten erzeugen.

    Leide ich am Zeitverschwendungssyndrom ? oder wie macht Ihr das...
    Auf Hochsprachen-Ebene muss man sich halt mit dem Compiler auseinandersetzen und die Optimierung für so eine Schleife ausschalten. Sonst optimiert der Compiler diese Zeitverschwendung einfach weg Schon ein Compiler- oder Interpreter-Update kann da alles verändern.
    Die for-Schleife kann man noch etwas optimieren, indem man die CPU-Frequenz berücksichtigt oder das Timing der Schleife misst.

    BTW: In alten Zeiten hat der Norton-Benchmark eine Multiplikation als Zeitelement verwendet. Da dieser Befehl im 8086 als Mikrocode implementiert war, brauchte er eine Unmenge am CPU-Takten. Ab dem 80186 war dieser Befehl dann aber als Hardware implementiert. Die Benchmarks schossen dann auf diesen CPUs durch den Bildschirm!

    Wenn man einen passenden Timer-Interrupt hat, kann man es über diesen lösen. Das Problem dabei ist, die Grenze zwischen NOPs und Interrupt zu finden. Das Aufrufen eines Interrupts kostet ja zusätzliche Zeit.

    Je nachdem kann die DMA auch helfen, diese braucht nur zum Aufsetzen CPU-Zeit.

    Eine weitere Möglichkeit sind noch Wait States, falls vorhanden. und entsprechend programmierbar. Allerdings wird dabei auch nur CPU-Zeit verbraten, wie bei NOPs.

    MfG Peter(TOO)
    Manchmal frage ich mich, wieso meine Generation Geräte ohne Simulation entwickeln konnte?

  10. #10
    Erfahrener Benutzer Roboter-Spezialist Avatar von witkatz
    Registriert seit
    24.05.2006
    Ort
    NRW
    Alter
    54
    Beiträge
    542
    Blog-Einträge
    17
    Hallo Siro,
    Zitat Zitat von Siro Beitrag anzeigen
    count = TimerCount+20; /* warte 20 Mikrosekunden */
    while (Timercount < count) ;
    mit while blockierst du wieder den µC. Wenn der PIC in der Wartezeit noch andere Sachen tun soll, geht das nur über kooperatives Multitasking. Für Routinen, die "nebenbei" laufen sollen, könnte man eine Schrittkette nach folgendem Muster verwenden:
    Code:
    void DoJob1(void){
        static unsigned short Evt = 0;
        static char step = 0;
        
        // getaktete Schrittkette
        if((TMR0 - Evt) < 0x7fff ) {
            Evt = TMR0 + 1000; // nächter Schritt in mind. 1ms
            switch (step){
                case 0: 
                    // Do Something
                    step ++;
                    break;
                case 1: 
                    // Do Something
                    step ++;
                    break;
                case 2: 
                    // Do Something
                    Evt = TMR0 + 5000; // nächter Schritt in 5ms
                    step = 0;
                    break;
            }
        }
    }
    mit Timer0 konfiguriert mit 1MHz und 16Bit Breite auf PIC18F. Die Funktion muss mindestens alle 30ms gepollt werden. Wenn die Zeit "reif" ist, wird ein Schritt ausgeführt und der Zeitwert für den nächsten Schritt gesetzt.

Seite 1 von 3 123 LetzteLetzte

Ähnliche Themen

  1. Lipo-Ladegerät auf korrekte Funktion prüfen
    Von Che Guevara im Forum Elektronik
    Antworten: 2
    Letzter Beitrag: 17.03.2013, 11:51
  2. Korrekte Beschaltung eines Relais an einem AVR
    Von Björn im Forum AVR Hardwarethemen
    Antworten: 51
    Letzter Beitrag: 10.08.2009, 18:20
  3. Korrekte Schallmessung
    Von Dolfo im Forum Sensoren / Sensorik
    Antworten: 3
    Letzter Beitrag: 15.09.2008, 23:54
  4. Antworten: 3
    Letzter Beitrag: 18.01.2007, 22:10
  5. Warteschleifen bei ATMEL
    Von monoton im Forum C - Programmierung (GCC u.a.)
    Antworten: 8
    Letzter Beitrag: 08.09.2004, 01:15

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

12V Akku bauen