Schiebeoperation mit int16_t-Variable

Gast #797605
Lesenswert?
• ▲
▼
Hallo,

ich möchte eine Division durch 4 mittels Schiebeoperation durchführen, 
da der Compiler (Optimierung -Os), das wohl nicht automatisch macht, 
sondern eine rechenzeitintensivere Division durchführt.
Wenn ich das richtig verstanden habe, funktioniert das Schieben 
folgendermaßen:

1<<3 bedeutet: 0000 0001 -> 0000 1000
3<<4 bedeutet: 0000 0011 -> 0011 0000

Eigentlich sollte ich das dann ja auch einach für eine als int16_t 
deklarierte Variable so anwenden können?

also:
int16_t mean;
mean = mean>>2

Wird das so funktionieren?
#797637
Lesenswert?
• ▲
▼
Dennis wrote:
> Hallo,
>
> ich möchte eine Division durch 4 mittels Schiebeoperation durchführen,
> da der Compiler (Optimierung -Os), das wohl nicht automatisch macht,

Was, zumindest beim gcc, im Übrigen nicht stimmt.
Der Compiler achtet nur darauf, nicht den gleichen Fehler zu
machen und bei negativen Zahlen in die falsche Richtung zu gehen :-)

Wenn die Variable aber sowieso nicht negativ werden kann, erhebt
sich die Frage, warum sie dann ein int16_t ist und kein uint16_t.
Denn dann klappts beim gcc auch wieder mit dem einfachen Schieben.

Ich bleibe dabei: Solche Low-Level Optimierungen überlässt man
sinnigerweise dem Compiler. Der kann das besser.
#797663
Lesenswert?
• ▲
▼
@  Karl heinz Buchegger (kbuchegg) (Moderator)

>Ich bleibe dabei: Solche Low-Level Optimierungen überlässt man
>sinnigerweise dem Compiler. Der kann das besser.

Nur bedingt. Ich hab vor kurzen ein kleines Projekt gemacht, Soft-PWM 
mit 20 Kanälen. Dort wird im Interrupt ein uint32_t gelesen und 
byteweise auf die Ports geschrieben.

1
ISR(TIMER1_COMPA_vect) {
2

3
    static uint8_t pwm_cnt;
4
    uint32_t tmp;
5

6

7
    OCR1A   += isr_ptr->time[pwm_cnt];
8
    tmp      = isr_ptr->mask[pwm_cnt];
9
    
10
    if (pwm_cnt == 0) {
11
        PORTA = tmp;                            // set ports at begin of PWM
12
        PORTC = tmp>>8;
13
        PORTD = tmp>>16;
14
        pwm_cnt++;
15
    }
16
    else {      
17
        PORTA &= tmp;                       // clear ports
18
        PORTC &= tmp>>8;
19
        PORTD &= tmp>>16;                        
20
        if (pwm_cnt == pwm_cnt_max) {
21
            pwm_sync = 1;                           // update now possible
22
            pwm_cnt=0;
23
        }
24
        else pwm_cnt++;
25
    } 
26
}

GCC ist in allen Optimierungsstufen NICHT clever genug, einfach die 
richtigen Register in die IO-Ports zu schreiben. Er erkennt zwar, dass 
man das per Bytekopie machen kann, kopiert und löscht aber noch 
unsinnigerweise Register, die in der realen Schiebeoperation gelöscht 
werden.

Erst der (halblegale) Trick per Union erreicht das gewünschte, optimale 
Ergebnis.

1
ISR(TIMER1_COMPA_vect) {
2
    typedef union {                 // little trick, to speed up data access
3
        uint32_t d32;
4
        uint8_t ary[4];
5
        } ut_t;
6

7
    static uint8_t pwm_cnt;
8
    ut_t tmp;
9

10

11
    OCR1A   += isr_ptr->time[pwm_cnt];
12
    tmp.d32  = isr_ptr->mask[pwm_cnt];
13
    
14
    if (pwm_cnt == 0) {
15
        PORTA = tmp.ary[0];                         // set ports at begin of PWM
16
        PORTC = tmp.ary[1];
17
        PORTD = tmp.ary[2];
18
        pwm_cnt++;
19
    }
20
    else {      
21
        PORTA &= tmp.ary[0];                        // clear ports
22
        PORTC &= tmp.ary[1];
23
        PORTD &= tmp.ary[2];                        
24
        if (pwm_cnt == pwm_cnt_max) {
25
            pwm_sync = 1;                           // update now possible
26
            pwm_cnt=0;
27
        }
28
        else pwm_cnt++;
29
    } 
30
}

Mfg
Falk

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.