Forum: Mikrocontroller und Digitale Elektronik Interrupt in ISR freigeben


von Hubert (Gast)


Lesenswert?

Hallo!

ich habe ein Problem, undzwar habe ich einen Interrupt, der absoluten 
Vorrang hat, das heißt es muss auch möglich sein, dass er einen anderen 
Interrupt unterbricht.

Ist dies überhaupt möglich?

Ich verwende AVR-GCC und einen AtMega644

Danke euch.

Besten Gruß
Hubert

von Klaus (Gast)


Lesenswert?

Nein. Bei den AVRs unterbricht ein Interrupt nicht die Ausführung einer 
gerade abgearbeiteten Interrupt-Routine.

Allenfalls könnte man das emulieren, in dem man in einer ISR die 
Interrupt-Flags prüft ob inzwischen ein anderer Interrupt aufgetreten 
ist.
Natürlich ist die Reaktionszeit länger im Vergleich zum eingebauten 
Interrupt-Mechanismus.

von Klaus (Gast)


Lesenswert?

Wenn Du mal beschreibst, warum Du das brauchst, könnte man sich noch 
andere Wege überlegen.

von Hubert (Gast)


Lesenswert?

Danke Klaus!

Ich verwende das One-Wire Bussystem von Peter Dannegger.

Dabei wird bei einem Pin Change, ein Interrupt ausgeführt, und mit dem 
Timerzustand verglichen, um zu wissen wie lange die Bitdauer war.

Problem ist nun, dass ich jede Sekunde mein Display mit neuen Werten 
aktualisieren, das ganze in einem Interrupt. Dieser dauert etwas länger, 
und wenn in dieser Zeit ein Pin Change Interrupt auftritt, kommt es 
zeitweise vor, dass es Timing Probleme gibt, und das Byte nicht korrekt 
erkannt wird.

Gruß
Hubert

von Klaus (Gast)


Lesenswert?

>Problem ist nun, dass ich jede Sekunde mein Display mit neuen Werten
>aktualisieren, das ganze in einem Interrupt.

Dann liegt hier der Ansatzpunkt für eine Lösung.
Ist das ein Interrupt dessen eigentlicher Zweck darin besteht die 1s 
abzumessen? Nur das Du halt darin auch noch das Display aktualisierst?
Was dauert in dem Interrupt so lange?
Verkürze es. Falls möglich setze in diesem Interrupt nur ein Flag und 
mache die Display-Aktualisierung aus einer Endlosen Schleife in main.

von J.-u. G. (juwe)


Lesenswert?

Hubert schrieb:
> Problem ist nun, dass ich jede Sekunde mein Display mit neuen Werten
> aktualisieren, das ganze in einem Interrupt.

Besser: in dem 1-Sekunden Interrupt nur ein Flag setzen und die
Displayaktualisierung dann ausserhalb der ISR machen.

von Hubert (Gast)


Lesenswert?

Danke euch zwei!

Das hört sich tatsächlich intelligenter an.

Es geht darum, dass ich einen Coloumb Zähler auch habe, daher muss ich 
auch alle 1 Sekunde den Strom messen, und zählen, um im endeffekt die 
entnommene Ladung zu kennen.

Ich habe für das Display leider auch viele Berechnungen und if-Abfragen, 
da ich Fonts verwende, da die Display eigenen zu klein sind für meinen 
Verwendungszweck.

Ich denke ich würde es verkürzen können, wenn ich Float variablen 
verwende, aber aus früheren Zeiten weiß ich, dass man dies tunlichst 
vermeiden sollte, gerade bei µC weils viel Speicher und Rechenfähigkeit 
bedarf.

Momentan "male" ich einfach das Komma hin.

das heißt ich habe eine Abfrage, bei allen 10er Schritten, um den 
Kommapunkt jeweils richtig setzen zu können.

Das heißt ich nehme die Integer Zahl, wandle sie in einen String, und 
danach setze ich den Punkt korrekt, daher muss ich je nach 10er Schritt 
den Punkt unterschiedlich setzen.

bei 1000 zb. an der 3 Stelle.
bei 100 an der 2. Stelle.

Ich hoffe man kann verstehen wie ich das meine.

Grüße
Hubert

von Klaus (Gast)


Lesenswert?

Aus einem anderen Grund war meine Aussage sowieso falsch. Enabled man in 
der einen Interruptroutine die interrupts wieder so kann ein weiterer 
Interrupt die laufende ISR unterbrechen. Sorry.

Ganz einfach ist das dennoch nicht und für einen Anfänger nicht zu 
empfehlen. Die Methode mit dem Flag ist einfacher zu verstehen und zu 
handhaben. Ausserdem ist nested interrupts in der Regel garnicht 
erforderlich.

von Klaus (Gast)


Lesenswert?

>Ich hoffe man kann verstehen wie ich das meine.

Das Problem ist, das ich nicht verstehe was Du damit sagen willst. Du 
stellst ja keine Frage.

Interrupts so kurz und einfach wie irgend möglich. Das ist alles.

von J.-u. G. (juwe)


Lesenswert?

Hubert schrieb:
> Momentan "male" ich einfach das Komma hin.
>
> das heißt ich habe eine Abfrage, bei allen 10er Schritten, um den
> Kommapunkt jeweils richtig setzen zu können.
>
> Das heißt ich nehme die Integer Zahl, wandle sie in einen String, und
> danach setze ich den Punkt korrekt, daher muss ich je nach 10er Schritt
> den Punkt unterschiedlich setzen.
>
> bei 1000 zb. an der 3 Stelle.
> bei 100 an der 2. Stelle.
>
> Ich hoffe man kann verstehen wie ich das meine.

Ist schon in Ordnung so. Aber bitte ausserhalb von Interrupt Routinen.

von Hubert (Gast)


Lesenswert?

Also besser viele Abfragen als eine Float variable zu verwenden?

Grüße
Hubert

von Klaus (Gast)


Lesenswert?

>Also besser viele Abfragen als eine Float variable zu verwenden?

Nein. Nur: Die ursprüngliche Frage ist beantwortet,

Falls Du ein noch ein anderes Problem hast mach besser einen neuen 
Thread auf.

Aber kurz: Float ist immer Sch.... Ob das nun "viele Abfragen" notwendig 
macht ist eine ganz andere Frage und hängt davon ab was Du tun willst 
und wie Du es tun willst. Aus Deiner Beschreibung geht das so nicht 
hervor. Intuitiv würde ich sagen, das Ausgaben von eigenen Fonts oder 
Kommas auf dem Display nicht mehr Abfragen benötigen wenn sie im 
Interrupt erledigt werden als wenn sie nicht im Interrupt erledigt 
werden.

von Klaus (Gast)


Lesenswert?

Ich habe so den Verdacht, dass Du den Font zur Laufzeit irgendwie neu 
berechnest. Das ist natürlich wenn möglich zu vermeiden. Aber mach am 
besten einen Thread für diese Problem auf.

von J.-u. G. (juwe)


Lesenswert?

Klaus schrieb:
> Das Problem ist, das ich nicht verstehe was Du damit sagen willst. Du
> stellst ja keine Frage.

Ich denke er hat ein paar if-Abfragen um herauszufinden, wo der 
Dezimaltrenner zu setzen ist.

Hubert schrieb:
> Also besser viele Abfragen als eine Float variable zu verwenden?

Wie sehen denn Deine Werte aus. Bei 16bit integer und zwei 
Nachkommastellen reichen doch zwei if-Abfragen.

von Sam .. (sam1994)


Lesenswert?

Hubert schrieb:
> Also besser viele Abfragen als eine Float variable zu verwenden?

Ja, float sollte man auf dem Avr grundsätzlich vermeiden (kostet dich 
übrigens ein paar kb Flash).

printf macht auch nichts anderes als bei Float einen Punkt reinzusetzen 
- nur der Rechenaufwand ist deutlich höher als bei Festkomma.

Und Funktionen sollte man in der ISR in C erst recht nicht aufrufen, da 
der Compiler da mal ein haufen register sichert, was pro register 2 
Takte kostet.

von Peter R. (pnu)


Lesenswert?

"Ich hab einen Interupt, der höchste Priorität hat,...usw." ist 
mißverständlich

m.E. richtiger formuliert:

"Ich möchte einem Interupt höchste Priorität geben, der im Moment 
niedrigrangiger ist"

Bei den AVR's ( kann nur für atmega8 sprechen) ist die Priorität 
entsprechend der Tabelle der Int-Vektoren zugeteilt, also int0 hat 
höchste Priorität.

Int0 kann aber, wenn er frei ist, per software aufgerufen werden.

Man schreibt also in die Routine niedriger Priorität den Befehl, mit dem 
das int0-flag gesetzt wird.

Int0 wird dadurch aufgerufen, als int0-Routine muss dann im Programm 
eben die Routine des Ints niedriger Priorität stehen.

mit den retis und den flags wirds eventuell verzwickt, aber gehen tuts 
wohl.

von Hubert (Gast)


Lesenswert?

Hallo Klaus

Natürlich macht es in der Geschwindigkeit keinen Unterschied ob ich 
diese Abfragen im Interrupt mache oder nicht, aber ich dachte, ich 
stelle diese Frage gleich hier, um nicht für alles einen neuen Thread 
aufmachen zu müssen.

Momentan sieht das ganze so aus:
1
ultoa(totalvolt,Text2,10);
2
3
if(totalvolt<100000)
4
{   Text2[7]=0;
5
  Text2[6]=0;
6
        Text2[5]=0;
7
  Text2[4]=Text2[1];
8
  Text2[3]='.';
9
  Text2[2]=Text2[0];
10
  Text2[1]=' ';
11
  Text2[0]=' ';
12
}
13
else if(totalvolt<1000000)
14
{   Text2[7]=0;
15
  Text2[6]=0;
16
  Text2[5]=0;
17
  Text2[4]=Text2[2];
18
  Text2[3]='.';
19
  Text2[2]=Text2[1];
20
  Text2[1]=Text2[0];
21
  Text2[0]=' ';
22
}
23
else if(totalvolt<10000000)
24
{   Text2[7]=0;
25
  Text2[6]=0;
26
  Text2[5]=0;
27
  Text2[4]=Text2[2];
28
  Text2[3]='.';
29
}
30
else
31
{   for(char i=0;i<10;i++)
32
    Text2[i]=0;
33
}
34
WriteText(Text2,179,10);

von Klaus (Gast)


Lesenswert?

>Natürlich macht es in der Geschwindigkeit keinen Unterschied

Das habe ich auch nicht geschrieben. Du hast von der Anzahl Abfragen 
geschrieben und ich habe geantwortet, das die Anzahl nicht 
unterschiedlich sein wird.

>aber ich dachte, ich stelle diese Frage gleich hier, um nicht für alles >einen 
neuen Thread aufmachen zu müssen.

Warum? Was ist daran nachteilig einen neuen Thread aufzumachen. Aber da 
das ein neues Thema ist, wird es hier als Vorteil empfunden, wenn dafür 
ein neuer Thread aufgemacht wird.

von Sam .. (sam1994)


Lesenswert?

> der Compiler da mal ein haufen register sichert, was pro register 2
> Takte kostet.
korriegiere: Sind 4, da sie zurückgeschrieben werden müssen.

Schreib doch deine eigene itoa Funktion inkl. Kommasetzung.

von Thomas E. (thomase)


Lesenswert?

Hubert schrieb:
> Ist dies überhaupt möglich?

Wenn ein Interrupt ausgelöst wurde, werden alle Interrupts global 
abgeschaltet. Alles, was du tun musst, ist am Anfang der ISR diese mit 
sei() wieder einschalten. Anstatt daruf zu warten, daß sie mit reti von 
selbst wieder eingeschaltet werden.

Kannst du auch vom  Compiler frühest möglich einbauen lassen:

ISR(XXX_vect, ISR_NOBLOCK)
{
  ...
}

siehe auch AVR-Libc >> Library Reference >> <avr/interrupt.h>:Interrupts
>> Nested Interrupts

mfg.

von Karl H. (kbuchegg)


Lesenswert?

Thomas Eckmann schrieb:
> Hubert schrieb:
>> Ist dies überhaupt möglich?
>
> Wenn ein Interrupt ausgelöst wurde, werden alle Interrupts global
> abgeschaltet. Alles, was du tun musst, ist am Anfang der ISR diese mit
> sei() wieder einschalten.

Im Prinzip geb ich dir recht. technisch wäre das eine Möglichkeit.

Aber in seinem Fall ist es die weitaus bessere Variante, seine ISR 
Routine auszumisten. Er hat da viel zu viele Dinge drinnen, im 
speziellen offenbar die Ausgabe auf ein GLCD, die da nicht 
hineingehören.

Spielt man nach den Regeln, dann benötigt man keine derartigen dirty 
Tricks, wie die Freigabe der Interrupts in einer ISR.

von Thomas E. (thomase)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Spielt man nach den Regeln, dann benötigt man keine derartigen dirty
> Tricks, wie die Freigabe der Interrupts in einer ISR.

Das ist sicherlich richtig. Aber die Frage war halt, ob es möglich ist. 
Das heisst ja nicht, daß man  das unbedingt machen muß. Wobei es bei 
wirklich zeitkritischen Sachen, wie beispielsweise Soft-USB, durchaus 
hilfreich sein kann.

mfg.

von Peter D. (peda)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Er hat da viel zu viele Dinge drinnen, im
> speziellen offenbar die Ausgabe auf ein GLCD, die da nicht
> hineingehören.

Besonders lustig wirds, wenn das Main ebenfalls aufs GLCD schreibt und 
die sich dann gegenseitig in die Quere kommen.
Das gibt dann nen hübschen Pixel-Salat.


Peter

von Hubert (Gast)


Lesenswert?

Hallo!

Ich habe gerade, wie empfohlen, meine eigene "itoa" geschrieben.
1
void itoa2(unsigned long n, char s[], char vor, char nach, char div)
2
{   char i=0;
3
    
4
    for(char x=0;x<div;x++)
5
    n /= 10;
6
    
7
    for(i;i<vor+nach+1;i++)
8
    {  if(i==nach)
9
       s[i] = '.';
10
       
11
       else
12
       {  if(n > 0)
13
           s[i] = n % 10 + '0';
14
   
15
           else
16
           s[i] = ' ';
17
          
18
          n /= 10;
19
       }        
20
    }
21
    s[i] = '\0';    
22
    reverse(s);
23
}

Kann das vielleicht jemand von euch Profis überfliegen, und mir sagen, 
ob das noch verbesserungswürdig ist.

Das ganze funktioniert so:

zb. 100000 soll zu 10.000 werden:
itoa2(100000,s,2,3,1);

Vorkomma  = 2
Nachkomma = 3
Divisor   = 1

Das heißt bei 10000 kommt " 1.000" heraus. So ist es gewunschen, es soll 
praktisch das Komma immer fix sein, wobei auch die Länge es Strings 
konstant sein muss, und alles davor mit ' ' aufgefüllt werden muss.

Danke schonmal

Grüße
Hubert

von Sam .. (sam1994)


Lesenswert?

Das /10 finde ich nicht so schön, da Divisionen auf dem Avr nicht so 
günstig sind. Wenn schon Divisionen im Programm sind, ist das aber egal. 
Mit einem 10^x Array könnte man da noch ein bisschen rausholen.

von Hubert (Gast)


Lesenswert?

Hallo!

naja ich brauche ja auch Zahlen wir 23442. Da sollte das 10^x Array doch 
keinen Vorteil haben oder ?

Wie siehts mit der restlichen Programmierung aus?

Das einzige Problem was ich habe ist bei Zahlen die "  .xx" ergeben, 
dass ich hier eine Null vor dem Komma erhalte, ich denke das geht nur 
mit paar Abfragen, was die Funktion wieder etwas länger und langsamer 
machen dürfte oder ?

Lg
Hubert

von Stefan P. (form)


Lesenswert?

Klaus schrieb:
> Nein. Bei den AVRs unterbricht ein Interrupt nicht die Ausführung einer
> gerade abgearbeiteten Interrupt-Routine.

Das geht schon,
1
ISR(INT0_vect, ISR_NAKED)
wenn man sich dann um das sichern der Register usw. selbst kümmert.

Aber wie schon erwähnt ist das nicht zu empfehlen, ausser es geht 
wirklich nicht anders.

von Sam .. (sam1994)


Lesenswert?

Hubert schrieb:
> naja ich brauche ja auch Zahlen wir 23442. Da sollte das 10^x Array doch
> keinen Vorteil haben oder ?

Ungetestet, so ähnlich mache ich es:
1
uint16_t _10[] = {10000, 1000, 100, 10}; //Hier nimmst du deine 10ner Zahlen raus und teilst nicht mehr durch 10
2
void itoa2(uint16_t n, char* s, uint8_t dot)
3
{   
4
    char* str = s;
5
    for(uint8_t i = 0; i < 4; i++, str++)
6
    {
7
        if(dot-- == 0)
8
            *str++ = '.';
9
        *str = '0';
10
        while(n >= _10[i])
11
        {
12
            n -= 10[i];
13
            (*str)++;
14
        }
15
    }
16
    *str = '0' + n;
17
     str = s;
18
     while(*str == '0')
19
        *str++ = ' ';
20
     if(*str == '.')
21
        *(str-1) = '0';
22
}

von Stefan E. (sternst)


Lesenswert?

Stefan P. schrieb:
> Klaus schrieb:
>> Nein. Bei den AVRs unterbricht ein Interrupt nicht die Ausführung einer
>> gerade abgearbeiteten Interrupt-Routine.
>
> Das geht schon,
> ISR(INT0_vect, ISR_NAKED)
> wenn man sich dann um das sichern der Register usw. selbst kümmert.

Auf was willst du hinaus? Zwischen einer naked ISR und sich 
unterbrechenden ISRs besteht überhaupt kein Zusammenhang.

von Sam .. (sam1994)


Lesenswert?

Verdammt! Abschließende 0 vergessen:
1
*str++ = '0' + n;
2
*str = 0;
3
str = s;

Meine Funktion braucht laut avrstudio kanpp 400Cycles. Deine liegt bei 
6000. Das liegt wahrscheinlich an den vielen Divisionen. Außerdem dreht 
deine Funktion das Ergebnis um.

von Hubert (Gast)


Lesenswert?

Hallo Samuel!

Wahnsinn dein Programm ist echt super.

Einzig eine Frage habe ich, undzwar, ich möchte einstellen können 
wieviele Nachkommastellen ich habe. Und leider weiß ich nicht, wie ich 
das integrieren kann. Genausowenig wie ich verstehe, warum es "i<4" ist.

So viel ich es auch versuche, ich kann es nicht 100%ig verstehen. Leider 
hab ich mit diesen vielen Pointer Operationen nicht so viel Erfahrung.

Danke !!!

Grüße
Hubert

von Sam .. (sam1994)


Lesenswert?

verstehen solltest du es schon. Ich kommentiere es mal ein bisschen.

Die < 4 steht für die 5 Stellen abzüglich der letzen, welche am Ende 
einfach addiert wird.

Ein Pointer zeigt auf die eine Stelle eines char arrays. Inkreminiert 
man ihn, zeigt er auf die nächste.
1
uint16_t _10[] = {10000, 1000, 100, 10}; //Hier nimmst du deine 10ner Zahlen raus und teilst nicht mehr durch 10
2
void itoa2(uint16_t n, char* s, uint8_t dot, uint8_t len)
3
{   
4
    char* str = s;           //Pointer kopieren
5
    for(uint8_t i = 0; i < 4; i++, str++)
6
    {
7
        *str = '0';          //0 an aktuelle string Position setzen
8
        while(n >= _10[i])   
9
        {
10
            n -= _10[i];     //sooft man 10^x subtrahieren kann
11
            (*str)++;        //inkreminiert man die vorige 0
12
        }
13
        if(--dot == 0)       //Punkt setzen wenn 
14
            *str++ = '.';    //dot == 0 ist
15
    }
16
    *str++ = '0' + n;        //letzte Ziffer ist das was übrig geblieben ist
17
    *(s+len) = 0;            //Abschließende 0
18
    str = s;                 //Startpos des strings
19
    while(*str == '0')       //Führende 0len löschen
20
        *str++ = ' ';
21
    if(*str == '.')          //Vor komma eine null setzen (falls gelöscht)
22
        *(str-1) = '0';
23
}

Wenn du alle Stellen ohne Komma haben willst musst du die Funktion mit 
len=5 und dot>=5 aufrufen. Mit Komma und alle Stellen mit len=6. Len 
bestimmt im Endeffekt nur die Länge des Strings.

von Hubert (Gast)


Lesenswert?

Hallo!
Danke das du es kommentiert hast, das hilft echt weiter! Und ich möchte 
es ja auch lernen, so gut programmieren würd ich auch gern können.

Allerdings gibt es ein Problem.

Gebe ich als Zahl "12345" an, als dot "2" und als len "4" dann kommt 
"1." heraus.

Ich hab mir die Funktion angeschaut, ändere ich die Funktion auf das:
1
    for(uint8_t i = 0; i < 4; i++, str++)
2
    {   if(dot-- == 0)       //Punkt setzen wenn 
3
            *str++ = '.';    //dot == 0 ist
4
            
5
        *str = '0';          //0 an aktuelle string Position setzen
6
        while(n >= _10[i])   
7
        {
8
            n -= _10[i];     //sooft man 10^x subtrahieren kann
9
            (*str)++;        //inkreminiert man die vorige 0
10
        }
11
    }

Dann funktioniert alles.

Kannst du mir eventuell sagen, was --dot macht? Ich kenne ausschließlich 
dot--

Eine weitere Frage wäre noch, und zwar
1
*str++ = '0' + n;
heißt dass, an die aktuelle Position wid '0' + n geschrieben, und erst 
DANN wird der Pointer incrementiert? Wenn ja, wie weiß man sowas? Es 
könnte doch genausogut vorher incrementiert werden und erst nachher 
hineingeschrieben?

Grüße
Hubert

von Hubert (Gast)


Lesenswert?

Folgendes wäre mir für eine Integer to Ascii Funktion eingefallen ( also 
signed )
1
    *str++ = ' ';
2
    
3
    if(n < 0)
4
    {   n = -n;
5
        *(str-1) = '-';
6
    }

Das  hätte ich am Anfang dazugeschrieben.
Was sagst du dazu?

Danke!

Grüße

Hubert

von (prx) A. K. (prx)


Lesenswert?

Hubert schrieb:

> Ich verwende das One-Wire Bussystem von Peter Dannegger.
> Dabei wird bei einem Pin Change, ein Interrupt ausgeführt, und mit dem
> Timerzustand verglichen, um zu wissen wie lange die Bitdauer war.

Ist der Controller hierbei der 1-Wire Master oder der Slave?

von Hubert (Gast)


Lesenswert?

Der Master !

Grüße
Hubert

von (prx) A. K. (prx)


Lesenswert?

Dann scheint mir die Methode, dafür einen Interrupt zu verwenden, 
ziemlich anspruchsvoll. Denn dadurch landest du bei der beschriebenen 
Forderung, auf diesen Interrupt extrem schnell reagieren zu können.

Was spricht dagegen, den 1-Wire Code wie sonst üblich im Hauptprogramm 
abzuwickeln? Der sorgt dort zwar für abgeschaltete Interrupts im Bereich 
von unter 20µs, um das Timing sicher einzuhalten, aber das wird nur zum 
Problem, wenn noch mehr derart Zeitkritisches dabei ist.

Ebenso unverständlich bleibt mir, weshalb die sekündliche komplexe 
Aktivität unbedingt im Interrupt ablaufen muss. Der übliche Ansatz ist 
eine sekündliche Signalisierung im Interrupt mit der eigentlichen 
Aktivität im diese Signalisierung abfragenden Hauptprogramm.

von Sam .. (sam1994)


Lesenswert?

Hubert schrieb:
> Gebe ich als Zahl "12345" an, als dot "2" und als len "4" dann kommt
> "1." heraus.

Hab das nochmal schnell debuggt:

Kleiner aber feiner Fehler:
1
uint16_t _10[] = {10000, 1000, 100, 10}; //Hier nimmst du deine 10ner Zahlen raus und teilst nicht mehr durch 10
2
void itoa2(uint16_t n, char* s, uint8_t dot, uint8_t len)
3
{   
4
    char* str = s;           //Pointer kopieren
5
    for(uint8_t i = 0; i < 4; i++, str++)
6
    {
7
        *str = '0';          //0 an aktuelle string Position setzen
8
        while(n >= _10[i])   
9
        {
10
            n -= _10[i];     //sooft man 10^x subtrahieren kann
11
            (*str)++;        //inkreminiert man die vorige 0
12
        }
13
        if(--dot == 0)       //Punkt setzen wenn 
14
            *++str = '.';    //dot == 0 ist
15
    }
16
    *str++ = '0' + n;        //letzte Ziffer ist das was übrig geblieben ist
17
    *(s+len) = 0;            //Abschließende 0
18
    str = s;                 //Startpos des strings
19
    while(*str == '0')       //Führende 0len löschen
20
        *str++ = ' ';
21
    if(*str == '.')          //Vor komma eine null setzen (falls gelöscht)
22
        *(str-1) = '0';
23
}
*++str = '.';
Das ++ muss hier vor str, da für den Punkt erst zum nächsten Zeichen 
gesprungen wird.
x++ gibt x zurück und erhöht x.
++x erhöht x und gibt dann x zurück.

Dadurch, dass dot nun unter While steht, kann der Punkt nur nach einer 
Zahl gesetzt werden (dot=1 heißt nach der ersten Zahl folgt der Punkt, 
dot=0 bedeutet kein Punkt). Nimm die Variante die dir besser gefällt.

von Hubert (Gast)


Lesenswert?

Hallo Samuel!

Das heißt es ist beides gleich schnell und gut und macht keinen 
Unterschied oder?

Empfiehlt es sich 2 Funktionen für long und integer zu schreiben, oder 
sollte ich immer die long to Ascii Funktion verwenden?

Grüße

Hubert

von Sam .. (sam1994)


Lesenswert?

Hubert schrieb:
> Das heißt es ist beides gleich schnell und gut und macht keinen
> Unterschied oder?

Einmal wird davor inkreminiert einmal danach. MAcht keinen zeitlichen 
Unterschied.

> Empfiehlt es sich 2 Funktionen für long und integer zu schreiben, oder
> sollte ich immer die long to Ascii Funktion verwenden?

Wenn du genügend Flash frei hast, ja, wenn nicht nimm nur Eine.
Evtl. sollte man bei einer Funktion, den Anfang des Strings zurückgeben, 
damit man bei 123 nicht 5 Leerzeichen davorhat:

while(*str == '0')       //Führende 0len löschen
        str++;
if(*str == '.')          //Vor komma eine null setzen (falls gelöscht)
       *--str = '0';
return str;

von Peter D. (peda)


Lesenswert?

Klaus schrieb:
>>aber ich dachte, ich stelle diese Frage gleich hier, um nicht für alles >einen
> neuen Thread aufmachen zu müssen.
>
> Warum? Was ist daran nachteilig einen neuen Thread aufzumachen. Aber da
> das ein neues Thema ist, wird es hier als Vorteil empfunden, wenn dafür
> ein neuer Thread aufgemacht wird.

Stimmt!

Wenn man hier auf das neue Thema antwortet, hilft das nur dem einen, da 
niemand anderes es hier suchen und finden wird.
Daher werde ich hier auch nicht antworten.
Ein bischen mitdenken sollte man schon und nicht so egoistisch sein.


Peter

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.