www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Variablen überlauf erkennen(C, Carry Flag, IAR)


Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

hab das Problem das ich über die USART eine ASCII Ziffernfolge (0-9) 
bekomme.
Normalerweise liegen die im Bereich von 0 bis 100. Dieser Wert wird dann 
entsprechen konvertiert und in einem unsigned char gespeichert.
Bis jetzt habe ich die Umwandlung so gelöst:
unsigned char value=0, temp=0;

temp=UDR;

if(temp>='0' && temp<='9')
{
   value *= 10;
   value += (temp-'0');
}

Jetzt gibt es aber einen Ausnahmefall in dem noch eine 4. Ziffer folgt. 
Wie kann ich jetzt den Überlauf der Variablen bei der Multiplikation 
erkennen?
Kann ich da in C einfach das Carry Flag im SREG abfragen?
Gibt es da eine elegantere bessere Methode? Soweit ich weiß ist eine 
solche Abfrage in ANSI C nicht vorgesehen, oder?
Oder lieber die Multiplikation direkt als inline assembler ausführen und 
da das Carry Flag abfragen?

Vielen Dank
Peter

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
speichere halt in einer int-Variable. Kannst ja hinterher wieder in char 
konvertieren, falls <100.

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja, hab ich auch schon überlegt. Aber da das in der ISR läuft würde ich 
das gern vermeiden...

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
was spricht dagegen in der if einer if abfrage kurz mit einem short zu
rechnen

also einfach bevor du mal 10 nimmst
short temp2=value;
temp2*=10;

if(temp2>255)
     /*mach was */
else
    /*was auch immer*/


Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Mmmmm, schon richtig, war auch meine erste Idee.
Würds das aber wie gesagt lieber vermieden.

Autor: frettchen (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich glaube zwar, dass die Lösung mit short trotzdem effizienter ist, 
aber so sollte es auch gehen:


temp = UDR - '0';

if (temp <= 9)
{
   if (value<=25)
   {
      value *= 10;
      value += temp;
      if (value>=temp)
      {
          //alles in Ordnung, kein Overflow
      }
   }
}

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum lässt du nicht ganz einfach einen Zähler mitlaufen, den du ständig 
mit einem if-Konstrukt auf > 3 überprüfst

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ frettchen
Ja, da hast wohl recht. Währe aber auch eine Möglichkeit.

@simon
Ja, aber da braucht ich dann eine static Variable wegen ISR und die 
belegt dann wieder zusätzlichen SRAM...

Würde das halt gern irgendwie über das Carry Flag lösen, hab halt nur 
keine Ahnung wie sich das unter C verhält und ob das überhaupt geht...

Autor: Simon K. (simon) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Peter wrote:
> @simon
> Ja, aber da braucht ich dann eine static Variable wegen ISR und die
> belegt dann wieder zusätzlichen SRAM...

Machst du für 1 Byte SRAM jetzt so einen Aufstand?

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@simon
Hast ja schon recht. Würde nicht wirklich was ausmachen.
Aber im Moment würde mich einfach nur interessieren wie bzw. ob das mit 
dem Carry Flag geht. Finde währe eine recht elegante Lösung...

Autor: crazy horse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
vergiss es einfach. Du steckst nicht drin, was der Compiler macht. 
Selbst wenn du es jetzt hinbekommen würdest (was machst du eigentlich, 
wenn tatsächlich ein Überlauf erkannt wird?), kann das schon mit dem 
nächsten Compilerupdate hinfällig sein, mit ziemlicher Sicherheit ist es 
nach einem Compilerwechsel eine recht potente Fehlerquelle. Schon mit 
einem anderen AVR kann das schief gehen (Hardware-Multiplier). 
Irgendwelche Hilfskonstrukte, die ausserhalb jeder Norm sind, machen dir 
nur Probleme. Und in deinem Fall kann ich nicht mal einen Nutzen 
erkennen - wozu also? Was treibt dich? Tatsächlich das eine Byte??

Autor: Ralph (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eine andere Möglichkeit wäre, das du die 4 Ziffern ohne Konvertierung in 
ein Array schreibst, und ein Flag setzte.
Außerhalb der Interuptroutine nimmst du bei gesetzem Flag das array und 
konvertierst in aller ruhe die Ziffernfolge.

Bei der Variante gibt es die kleinste Interruptdauer und was noch 
entscheidender ist, jeder Interruptdurchlauf dauert gleich lang.
Mit IF Bedingungen in der Interruptroutine ist das nicht der Fall.

Autor: Hans (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@crazy horse
Nein eigentlich geht es mir nicht wirklich um das eine Byte. Findet 
dieser Überlauf statt soll einfach fix 100 als Wert zugewiesene werden.
Dachte halt das mit dem Carry Flag währe eine recht elegante Sache. Aber 
die von Dir angesprochenen Kompatibilitätsprobleme hatte ich auch schon 
befürchtet.

@ Ralph
Stimmt schon, aber da in meiner ISR aber eh eine state machine läuft, 
und dies eh einer der kleineren Teile ist, würde eine zusätzliche if 
Abfrage auch nichts ausmachen.


Werde das jetzt denke ich ähnlich machen wie frettchen vorgeschlagen hat 
(if Abfragen). Denke das macht so in diesem Fall am meisten Sinn.

Vielen Danke an alle,
Gruß
Hans

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
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.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.