Integer performant durch 10 teilen?



  • Hallo!

    Ich hab da einen Interrupt auf einem Mikrocontroller, der mir Millisekunden nähert, und zwar in Sechzehntelschritten:

    1/16=0.0625s
    2/16=0.125s
    3/16=0.1875s
    [...]
    16=1.0s

    Der Interrupt wird 16 Mal pro Sekunde aufgerufen.

    Jetzt wollte ich die Millisekunden möglichst performant berechnen (;) ), was momentan so aussieht:

    // In der Interrupt-Routine:
    static int overflows = 0;
    static int val = 0;
    
    val += 625;
    gMilliSekunden = val / 10; // Globale Variable. Beispiel: 0.1875 wird zu 187 Millisekunden
    
        if(overflows == 16) {
            overflows = 0;
            val = 0;
        }
    

    Kann man das Teilen durch 10 noch entfernen? Geht das allgemein irgendwie besser? MicroKontrollerprogrammierung ist noch recht neu für mich 😉



  • /10 ist gut. Der Compiler macht daraus eine Multiplikation nebst shift.

    Aber ich sehe gar nicht, wozu Du durch 10 teilen mußt.

    static int val = 0;
    static int flipflop=0;
    
    val += 62;
    val += flipflop;
    flipflop^=1;
    
    gMilliSekunden = val;
    

    oder

    static int val = 0;
    
    val += 125;
    
    gMilliSekunden = val>>1;
    


  • volkard schrieb:

    /10 ist gut. Der Compiler macht daraus eine Multiplikation nebst shift.

    Aber ich sehe gar nicht, wozu Du durch 10 teilen mußt.

    static int val = 0;
    static int flipflop=0;
    
    val += 62;
    val += flipflop;
    flipflop^=1;
    
    gMilliSekunden = val;
    

    oder

    static int val = 0;
    
    val += 125;
    
    gMilliSekunden = val>>1;
    

    Hmm ich glaub ich hab ein Brett vor dem Kopf. Im letzten Beispiel teilst du doch mit ">>1" durch 2, weil du um eine Stelle nach rechts shiftest. Das liefert doch nicht das gewünschte Ergebnis?

    Die Idee mit dem FlipFlop ist... interessant 🤡



  • meicro schrieb:

    Hmm ich glaub ich hab ein Brett vor dem Kopf. Im letzten Beispiel teilst du doch mit ">>1" durch 2, weil du um eine Stelle nach rechts shiftest. Das liefert doch nicht das gewünschte Ergebnis?

    Der Plan wäre: Während val in 125-er Schritten hoppelt, hoppelt val/2 in den gewünschten 62.5-er Schritten.



  • Noch ne Idee, aber dazu mußt Du die Maschine kennen:

    struct MythicalTimer{
      union{
        struct{
          unsigned short highShort;
          unsigned short lowShort;
        };
        unsigned int theInt;
    };
    
    static MysticalTimer myt;
    unsigned short& gMilliSekunden=myr.highShort;
    
    myt.theInt+=4096000;//62.5*65536
    //gMilliSekunden = val;braucht man nicht mehr
    


  • Hab nochmal ein wenig überlegt: Da ich Millisekunden sowieso nicht genau bestimmen kann, ist das eigentlich total die Verschwendung sich die Mühe zu machen und auf Millisekunden zu runden. Ob nun genäherte 62 Millisekunden oder korrekt gerundet auf 63, genähert ist genähert.

    Deswegen addier ich nur noch 62 Millisekunden und hab dann am Ende eben nicht 1s, sondern 992 Millisekunden. Die Sekunden werden eh genau (separat) gezählt.


Log in to reply