Forum: Compiler & IDEs Wie am einfachsten einfachsten einen Übertrag erkennen?


von TOM (Gast)


Lesenswert?

Hallo,
ich möchte zu einer uint16 Variable "sum" zyklisch eine zweite uint16
Variable "Wert" addieren. Jedes mal, wenn bei dieser Addition ein
Übertrag stattfindet möchte ich eine dritte uint8 Variable "cnt"
inkrementieren.
In Assembler würde ich nun einfach nach der Addition das Carry-Flag
prüfen und gegebenenfalls die Inkrementierung auslösen.
Wie kann ich dies am einfachsten in C realisieren. Meine einzige Idee
wäre die Werte der Variablen "sum" vor und nach der Addition zu
vergleichen. Ist die nachher kleiner als vorher, so hat ein Übertrag
stattgefunden. Quasi so:

ISR:
{
...
sum_old=sum;
sum+=wert;
if (sum<sumold) cnt++;
...
}


Geht das nicht einfacher ohne zusätzliche Variable? Oder kann ich nach
der Addition einfach das Carryflag über "bit_is_set" prüfen?

Danke

Gruß

Thomas

von Peter Dannegger (Gast)


Lesenswert?

So schlimm ist das doch gar nicht, sollten beim ATMega nur 2 Zyklen mehr
sein.

Daher würde ich den Code portabel lassen, d.h. nicht das Bit 0 im SREG
direkt testen.


Peter

von A.K. (Gast)


Lesenswert?

uint32_t sum;
sum += wert.

und später:

cnt = sum >> 16;

von TOM (Gast)


Lesenswert?

Was Rechenzeit und Speicherbedarf angeht, versuch ich halt immer das
beste rauszuholen, sonst bin ich nicht zufrieden.

@Peter:
Um die 2 Zyklen geht es mir dann doch nicht, war mir nur ein Dorn im
Auge, da man es in ASM einfacher haben könnte. Ich dachte, dass es
vielleicht auch in C noch ne bessere Möglichkeit gäbe.

@A.K.
Daran hab ich auch schon gedacht, aber dann hantiere ich ja bei jeder
Addition immer (teils unnötig) mit 4 Bytes rum, wobei ich eins nun ganz
nutzlos zum Spaß mitschleppe.

Danke für eure Meinungen, wenn jemand noch was besseres weiß, darf er
das natürlich trotzdem noch mitteilen.

Danke

Gruß

Thomas

von Detlef A (Gast)


Lesenswert?

Es geht auch ohne zusätzliche Variable:
if((sum+wert)<sum) cnt ++;
sum += wert;

zumindest winavr ist schlau genug, die Summe nicht 'zweimal' zu
berechnen, der Schuß geht aber trotzdem vom Speicher/Rechenzeitbedarf
nach hinten los, siehe angehängte listings, schade.

Cheers
Detlef

00000096 <tttt>:
static UINT16 sum;
static UINT8  cnt;
      UINT16  sum_old;

sum_old=sum;
      96:  20 91 f6 01   lds  r18, 0x01F6
      9a:  30 91 f7 01   lds  r19, 0x01F7
sum += wert;
      9e:  82 0f         add  r24, r18
      a0:  93 1f         adc  r25, r19
      a2:  90 93 f7 01   sts  0x01F7, r25
      a6:  80 93 f6 01   sts  0x01F6, r24
if(sum<sum_old) cnt ++;
      aa:  82 17         cp  r24, r18
      ac:  93 07         cpc  r25, r19
      ae:  28 f4         brcc  .+10       ; 0xba
      b0:  80 91 f8 01   lds  r24, 0x01F8
      b4:  8f 5f         subi  r24, 0xFF  ; 255
      b6:  80 93 f8 01   sts  0x01F8, r24
      ba:  08 95         ret


00000096 <tttt>:
static UINT16 sum;
static UINT8  cnt;
      //UINT16  sum_old;

if((sum+wert)<sum) cnt ++;
      96:  20 91 f6 01   lds  r18, 0x01F6
      9a:  30 91 f7 01   lds  r19, 0x01F7
      9e:  a9 01         movw  r20, r18
      a0:  48 0f         add  r20, r24
      a2:  59 1f         adc  r21, r25
      a4:  42 17         cp  r20, r18
      a6:  53 07         cpc  r21, r19
      a8:  28 f4         brcc  .+10       ; 0xb4
      aa:  80 91 f8 01   lds  r24, 0x01F8
      ae:  8f 5f         subi  r24, 0xFF  ; 255
      b0:  80 93 f8 01   sts  0x01F8, r24
sum += wert;
      b4:  50 93 f7 01   sts  0x01F7, r21
      b8:  40 93 f6 01   sts  0x01F6, r20
      bc:  08 95         ret

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.