Willkommen in unserer Community

Werde Teil unserer Community und registriere dich jetzt kostenlos ...

  1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies. Weitere Informationen

Umrechnung von Dez zu Hex mit Kontrolle und Begrenzung

Dieses Thema im Forum "Software" wurde erstellt von achim S., 28. Oktober 2017.

  1. achim S.

    achim S. Mitglied

    Registriert seit:
    16. Januar 2010
    Beiträge:
    257
    Zustimmungen:
    5
    Map
    Hallo Gemeinde
    such ein Stück Code in C zur Umrechnung von Dezi zu Hex.
    Zum Problem (alles in C)

    0x30 bis 0x39 sind die Zahlen 0 bis 9
    0x41 bis 0x46 sind A bis F

    Zur Ansteuerung eines Graphigdisplays muss ich den Wert von 0x00 bis
    0xFF (hexa) übertragen (bis zu 3 mal). Zur Eingabe der Werte kann ich nur 0 bis
    255 (dezimal) nutzen.
    Wie kann ich die Werte in C umrechnen und gleizeitig die Eingabewerte
    kontrollieren (Begrenzung der Hexzahlen)?
    Hat da jemand eine Idde dazu?
    achim
     
  2. LotadaC

    LotadaC Sehr aktives Mitglied

    Registriert seit:
    22. Januar 2009
    Beiträge:
    2.698
    Zustimmungen:
    38
    Ort:
    Hennigsdorf
    Sprachen:
    BascomAVR, Assembler
    Map
    Das ist doch die ganz normale ASCII...
    0x30=48dezimal="0" als Character/String.
    Im AVR in jedem Fall 00110000 binär.
    Die Frage ist also nur, wie Du den Compiler auf die Speicherzelle zugreifen/ihn den Inhalt interpretieren läßt.
    Unter ASM kümmerst Du Dich eh umalles selbst.
    Unter BASCOM kann man dieselbe Variable (Speicherzelle) mit unterschiedlichen Namen (Overlay) als unterschiedliche Typen verwenden lassen.
    Unter C mußt Du wahrscheinlich beim Zugriff nur festlegen (casten?) ob da irgendein Ergebnis als Byte/Char/dezimal weiterzuverwenden ist.

    Wie gesagt. Im AVR ist das eh immer nur 8bit-binär.
    Mit einer If...Then-Abfrage, als Bedingung halt die vier HEX-Grenzen mit AND und OR?
     
  3. addi

    addi Mitglied

    Registriert seit:
    2. September 2013
    Beiträge:
    79
    Zustimmungen:
    3
    Ort:
    Hamminkeln
    Sprachen:
    BascomAVR, C, Assembler
  4. LotadaC

    LotadaC Sehr aktives Mitglied

    Registriert seit:
    22. Januar 2009
    Beiträge:
    2.698
    Zustimmungen:
    38
    Ort:
    Hennigsdorf
    Sprachen:
    BascomAVR, Assembler
    Map
    Irgendwie schnall ich die Frage nicht so richtig...
    In welcher Form werden denn die "dezimalen Zahlen" erhalten? Als ein Byte? als Zwei-Byte-Variable, oder wie?
    Und was soll da konkret zum Display gesendet werden?
    Der Wert der Zahl (der wäre ja in jedem Zahlensystem gleich)?

    Ähm...
    oder hast Du eine Zahl von 0..4095 dezimal bzw 000hex..FFFhex bzw 000000000000bin..111111111111bin, und willst die drei Zeichen der hex-Darstellung quasi als String, also die entsprechenden ASCII dazu senden?
     
  5. TommyB

    TommyB Premium Benutzer

    Registriert seit:
    17. Mai 2010
    Beiträge:
    1.612
    Zustimmungen:
    45
    Ort:
    127.0.0.1 ;)
    Sprachen:
    Assembler, LunaAVR, VB.Net, Python, C#
    So wie ich verstanden habe bekommst du also bis zu 3 Bytes (ASCII) und musst daraus ein Byte formen?
    Ich kann jetzt kein C, daher ungetesteter PseudoCode:



    CodeBox BascomAVR
    Function ConvertToByte(InBytes As Byte()) As Byte
    
      Dim RetVal As Byte = 0
      RetVal += ByteToBcd(InBytes(0)) * 100
      RetVal += ByteToBcd(InBytes(1)) * 10
      RetVal += ByteToBcd(InBytes(2))
      Return RetVal
    
    End Function
    
    Function ByteToBcd(InByte As Byte) As Byte
    
      Select Case InByte
        Case 0x30 To 0x39 : Return InByte - 0x30
        Case 0x41 To 0x46 : Return InByte - 0x37
        Case Else ' Fehler behandeln
      End Select
    
    End Function


    Select Case ist halt switch in c. Aber das Prinzip ist ja einfach.

    Edit: Könnte auch ggf. 2, 1, 0 sein statt 0, 1, 2, je nachdem, letzteres ist bei Ascii aber eher unwahrscheinlich.
     
    #5 TommyB, 28. Oktober 2017
    Zuletzt bearbeitet: 28. Oktober 2017
  6. LotadaC

    LotadaC Sehr aktives Mitglied

    Registriert seit:
    22. Januar 2009
    Beiträge:
    2.698
    Zustimmungen:
    38
    Ort:
    Hennigsdorf
    Sprachen:
    BascomAVR, Assembler
    Map
    Das wären Dezimalstellen in Form eines Stringes (Array of Char oder sowas), die zu einer Zahl (im Sinne des Controllers ein Byte) zusammengefaßt werden.
    Achim wollte aber dezimale Zahlen umwandeln... was er meinte, ist mir nicht klar.
    Ich hätte jetzt von C als Hochsprache bereits 'ne fertige ByteToBcd-Funktion erwartet...
     
  7. TommyB

    TommyB Premium Benutzer

    Registriert seit:
    17. Mai 2010
    Beiträge:
    1.612
    Zustimmungen:
    45
    Ort:
    127.0.0.1 ;)
    Sprachen:
    Assembler, LunaAVR, VB.Net, Python, C#
    So habe ich es interpretiert. Beispielsweise Eingabe per UART, Ausgabe als Byte.
    Mir auch nicht ;)
    Und zu C... Kann ich nich, will ich nicht, bin kein Klammeraffe ^^
    Ob es eine fertige Funktion dafür gibt... Könnte sein, kenn ich nicht.
    Aber in ASM hättst du es ja auch nicht viel anders gemacht, oder? ;)
     
  8. addi

    addi Mitglied

    Registriert seit:
    2. September 2013
    Beiträge:
    79
    Zustimmungen:
    3
    Ort:
    Hamminkeln
    Sprachen:
    BascomAVR, C, Assembler
    Hmmm...er wollte hex, nicht bcd..ist zwar auch hex, aber nur etwas :)
    Ausserdem, wenn er 255 in ein byte quetscht, dann ist die form(hex, dec oder bin) eigentlich egal.
    Es muss also die form des rüberschuebens eine andere sein.
    Addi
     
  9. TommyB

    TommyB Premium Benutzer

    Registriert seit:
    17. Mai 2010
    Beiträge:
    1.612
    Zustimmungen:
    45
    Ort:
    127.0.0.1 ;)
    Sprachen:
    Assembler, LunaAVR, VB.Net, Python, C#
    Das müsste eigentlich schon so passen. Streng genommen kann man den 2. Part (für A-F) weg lassen, wäre bei Dezimal ja unnötig / ungültig. Dann wäre "0" = 0x00, "1" = 0x01, ... Bei Einsern ist Hex und BCD identisch ;) Und dann pro Zehner-/ Hunderterstelle dementsprechend multipliziert und addiert.
    Ok, ich hab keine Overflow Überprüfung drin (Ascii > "255"). Details ;)
     
  10. LotadaC

    LotadaC Sehr aktives Mitglied

    Registriert seit:
    22. Januar 2009
    Beiträge:
    2.698
    Zustimmungen:
    38
    Ort:
    Hennigsdorf
    Sprachen:
    BascomAVR, Assembler
    Map
    Ich bin noch am Grübeln, ob es im ersten Teil nicht besser wäre, statt der Multiplikationen mit 10 und 100 zweimal mit 10 zu multiplizieren
    (Hunderter mal 10, Zehner addiert, mal zehn, Einer addiert). Zehn ist ja 00001010binär, Hundert hingegen 01100100binär.
    Man könnte die Multiplikationsschleife also bereits nach vier Durchläufen terminieren lassen (beim Schieben kommt das "Z"-Flag)...
    Hmm... andererseits sind die "Zehn" ja konstant - man braucht also eigentlich nichtmal wirklich die Schleife mit Prüfen auf "Bit=1" (Carry beim Schieben) usw... man kann das dann auch "blind" rechnen (Zahl einmal linksschieben, in ein Register kopieren, Zahl noch zweimal linksschieben, und in dasselbe Register addieren. Fertig)
    Entweder ich hab jetzt 'n Dejavu, oder wir hatten das hier irgendwo schon mal...
    Bei Controllern mit Multiplikationsinstruktion sieht das natürlich anders aus...
    Ich bin mir nicht sicher, ob das was er wollte dem was er schrieb entspricht...
     
  11. TommyB

    TommyB Premium Benutzer

    Registriert seit:
    17. Mai 2010
    Beiträge:
    1.612
    Zustimmungen:
    45
    Ort:
    127.0.0.1 ;)
    Sprachen:
    Assembler, LunaAVR, VB.Net, Python, C#
    Kann sein, gelegentlich hab ich n Hirn wie n Sieb, nur nicht ganz so dicht :D
    Mit MUL hatten wir mal was, also dem Befehl, nicht der von Hand Geschichte. Aber ich wüsste jetzt auch nicht mehr wo. Ist ja auch egal, soll ja in C.
     
  12. Dirk

    Dirk Administrator Mitarbeiter

    Registriert seit:
    28. Januar 2007
    Beiträge:
    4.070
    Zustimmungen:
    100
    Ort:
    Mittelhessen, Giessen
    Sprachen:
    C, Assembler, Pascal, C++, PHP, Java
    Map
    So ganz genau habe ich nicht verstanden, was erreicht werden soll.
    Aber vielleicht hilft hier ja schon einmal itoa().
     
  13. achim S.

    achim S. Mitglied

    Registriert seit:
    16. Januar 2010
    Beiträge:
    257
    Zustimmungen:
    5
    Map
    Guten Morgen
    Kurz zur Erklärung. Das Display verlangt die Eingabe der Farben Rot, Grün, Blau durcj die Eingabe dieser 6 Werte.


    CodeBox C und C++
    i2c_write(DOL);   bcc+=DOL;   // $ Vordergrund   
         i2c_write('F');   bcc+='F';   // Rot
         i2c_write('F');   bcc+='F'; 
       
         i2c_write('0');   bcc+='0';   // Grün
         i2c_write('0');   bcc+='0'; 
       
         i2c_write('0');   bcc+='0';   // Blau
         i2c_write('0');   bcc+='0';
    

    Eigentlich sieht es nach Hersteller Angaben so aus: $FF0000
    Muss also für die Darstellung einer Farbe 6 Werte in Hex übertragen. Das ganze muss ich mehrfach machen für Farbe Vordergrund, Transparent Vordergrung, Farbe Hintergrung und Transparenz Hintergrund.
    Mann könnte es so machen:


    CodeBox C und C++
    // YDC - TFM_Farbeinstellung
            // VR1-Vordergrund Rot, VG1-Vordergrund Grün, VB1-Vordergrund Blau, VT-Vordergrund Transparenz
            // VR2-Vordergrund Rot, VG2-Vordergrund Grün, VB2-Vordergrund Blau, VT-Vordergrund Transparenz
            // HR1-Hintergrund Rot, HG1-Hintergrund Grün, HB1-Hintergrund Blau, HT-Hintergrund Transparenz
            // HR2-Hintergrund Rot, HG2-Hintergrund Grün, HB2-Hintergrund Blau, HT-Hintergrund Transparenz
             TFM_Farbeinstellung( VR1, VR2, VG1, VG2, VB1, VB2);
    

    Bei dieser Angabe kann es viel Fehler geben, da sehr viel Parameter. Nehme ich die Eingabe von Windows, z.B. 210 für VR1 und VR2, übertrage ich die Farbe Rot durch die Eingabe von einer Zahl die je nach Sättigung zwischen 0 und 255 liegen darf. Das wieder 3 mal für die Farbe Vordergrund.
    Die Zahl 210 ist in Hex 0xD2. Jetzt besteht die Möglichkeit der falschen Eingabe. Die Hex Werte sind für
    0 - 9 > 0x30 bis 0x39
    A - F > 0x41 bis 0x46
    für die Eingabe der 3 Farben möchte ich es so machen
    TFM_Farbeinstellung( 255, 0, 0);
    Diese 3 Werte muss ich danach in Hex umrechnen und kontrollieren ob die Einstellung korrekt ist. Es besteht ja die Möglichkeit das statt 255 auch 256 eingeben könnte. Dann brauche ich die Kontrolle und Begrenzung auf 255. Das ist wahrscheinlich das kleinste Problem.
    Bei der Übergabe brauche ich teilweise bis zu 30 Parameter, was teilweise kompliziert ist.
    Das Display ist eine uniTFT von EA mit 64 Millionen Farben, gefühlte 200 Befehle, einem eigenen Prozessor und Übertragung mit dem I2C Bus und Prüfsummen bildung.
    Hoffe das ich mich Verständlich ausgedrückt habe
    achim
     
  14. Dirk

    Dirk Administrator Mitarbeiter

    Registriert seit:
    28. Januar 2007
    Beiträge:
    4.070
    Zustimmungen:
    100
    Ort:
    Mittelhessen, Giessen
    Sprachen:
    C, Assembler, Pascal, C++, PHP, Java
    Map
    Vielleicht hilft dies weiter ...



    CodeBox C und C++
    const uint8_t hextable[16] = {
       '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
    };
    
    void SendAsHexString(uint8_t data)
    {
       i2c_write(hextable[(data>>4) & 0x0F]);   // high
       i2c_write(hextable[data & 0x0F]);       // low
       
    }
    /* Beispiel:
     SendAsHexString(223);
     223d = 0xDF
     Sendet 'D' und 'F'
    */
    


    Bei RGB übertragen entsprechend drei mal verwenden und wenn notwendig die Checksumme berechnen.
     
  15. achim S.

    achim S. Mitglied

    Registriert seit:
    16. Januar 2010
    Beiträge:
    257
    Zustimmungen:
    5
    Map
    Hallo Dirk
    hatte bereits in etwa so was im Netz gefunden.
    Hatte gerade eine andere Version getestet. Die Ausgabe ist zwar korrekt, aber etwas fehlt. Es wird zwar 39 ausgegeb, müsste aber 0x39 sein.


    CodeBox C und C++
    itoa( Zah1, Buffer, 16 );
         lcd_printlc(4,1,Buffer);
         itoa( Zah2, Buffer, 16 );
         lcd_printlc(4,7,Buffer);
         itoa( Zah3, Buffer, 16 );
         lcd_printlc(4,12,Buffer);
    

    Nach meinen C-Buch ist doch die Wandlung mit itoa oder atoa (??) möglich.
    Werde deine Version testen.
    Es geht immer noch um das Display von den letzten Themen. Ist halt sehr anspruchsvoll (kompliziert)
    achim
     
  16. Dirk

    Dirk Administrator Mitarbeiter

    Registriert seit:
    28. Januar 2007
    Beiträge:
    4.070
    Zustimmungen:
    100
    Ort:
    Mittelhessen, Giessen
    Sprachen:
    C, Assembler, Pascal, C++, PHP, Java
    Map
    Ein String "0x" brauchst du doch nicht und überträgst du auch nicht, der String mit der Zahl stellt ja bereits den Wert als Hexadezimalzahl dar.

    Meine Version macht nichts anderes, ist nur etwas kürzer als itoa ;)
    Du kannst ja auch einfach die zwei Zeilen von meiner Funktion direkt bei dir einbauen. Ich denke mal kürzer, schneller und einfacher gehts nicht.
    Du brauchst dann nichtmal eine Funktion einbinden, das itoa bläht deinen Code noch etwas auf, da die Funktion komplexer ist.
     
  17. achim S.

    achim S. Mitglied

    Registriert seit:
    16. Januar 2010
    Beiträge:
    257
    Zustimmungen:
    5
    Map
    Hallo Dirk
    leider hat sich der Hersteller was ausgedacht.
    Gebe ich z.B. 0x39 oder eine andere Zahl in dieser Schreibweise gibt es keine Probleme. Gebe ich aber nur 39 ein kommt die korrekte Prüfsumme zurück aber das Display bleibt schwarz (Mist).
    Wennich das richtig verstanden habe, machst du damit eine Kontrolle der Eingabe


    CodeBox C und C++
    const uint8_t hextable[16] =
      {
       '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
      };
    

    Mit diesem Stück gibst du einen Wert von (Eingabe) 223 vor


    CodeBox C und C++
    /* Beispiel:
     SendAsHexString(223);
     223d = 0xDF
     Sendet 'D' und 'F'  */
    

    und sendest es an


    CodeBox C und C++
    void SendAsHexString(uint8_t data)
      {
        i2c_write(hextable[(data>>4) & 0x0F]);   // high
        i2c_write(hextable[data & 0x0F]);       // low
      }
    

    müsste also nur das ändern


    CodeBox C und C++
    i2c_write(Zah1);   bcc+=Zah1;   // Rot
         i2c_write(Zah2);   bcc+=Zah2; 
    

    Jeweils für eine Farbe.
    bleibt wieder die Frage zur Eingabe 39 oder 0x39.
    Vom Hersteller habe ich das bekommen. Einiges ist gleich. Komme leider nicht ganz klar damit.


    CodeBox C und C++
    static const char nybble_chars[] = "0123456789ABCDEF";
    void get_byte_hex( unsigned char b, char *buf)
      {
        buf[0] = nybble_chars[ ( b >> 4 ) & 0x0F ];
        buf[1] = nybble_chars[ b & 0x0F ];
      }
    Macht dann als Aufruf:
    Byte R,G,B;
    R=10; G=20; B=40;
    
    Byte buf[2];
    i2c_write(DOL);   bcc+=DOL;   // $ Vordergrund     
    get_byte_hex(R,buf);
    i2c_write(buf[0]);   bcc+= buf[0];   // $ Vordergrund     
    i2c_write(buf[1]);   bcc+= buf[1];   // $ Vordergrund     
    get_byte_hex(G,buf);
    i2c_write(buf[0]);   bcc+= buf[0];   // $ Vordergrund     
    i2c_write(buf[1]);   bcc+= buf[1];   // $ Vordergrund     
    get_byte_hex(B,buf);
    i2c_write(buf[0]);   bcc+= buf[0];   // $ Vordergrund     
    i2c_write(buf[1]);   bcc+= buf[1];   // $ Vordergrund     
    i2c_write(‘,’);   bcc+=’,’;   // $ Vordergrund     
    


    achim
     
  18. Dirk

    Dirk Administrator Mitarbeiter

    Registriert seit:
    28. Januar 2007
    Beiträge:
    4.070
    Zustimmungen:
    100
    Ort:
    Mittelhessen, Giessen
    Sprachen:
    C, Assembler, Pascal, C++, PHP, Java
    Map
    Nein, ich hole mit die Ascii Werte je Nibble (4bit) aus der Tabelle. Das entspricht ja deinem nybble_chars[] ... macht ja genau das selbe.

    Bei deinem Display kann ich dir selber leider nicht helfen.

    Wenn du als Parameter für eine Farbe einmal 39 und einmal 0x39 angibst, bedeutet es lediglich, dass bei der hexadezimalen Zahl der Farbanteil stärker sein wird, da ja 0x39>39.

    So wie ich es verstanden habe, benötigt das Display die Werte als hexadezimale Zahl (zwei Byte Ascii). Dein oberes Beispiel sollte in diesem Fall dann so stimmen, zumindest bezüglich der Bytes für Farbwerte.
     
  19. achim S.

    achim S. Mitglied

    Registriert seit:
    16. Januar 2010
    Beiträge:
    257
    Zustimmungen:
    5
    Map
    Hallo
    der erste Teil mit der Eingabe von 0-F hat jetzt wunderbar geklappt. Habe aber noch ein anderes Problem bekommen. Muss die transparenz eingeben und diese von 0-100 begrenzen.Der Code zur übertgabe ans Display sieht so aus


    CodeBox C und C++
    i2c_write(KOM);   bcc+=KOM;   // Komma
         i2c_write('1');   bcc+='1';   // Transparenz in Prozent
         i2c_write('0');   bcc+='0';   // Hintergrund
         i2c_write('0');   bcc+='0'; 
    

    habe erst mal Zahlen zur Kontrolle eingesetzt. Die Begrenzung auf max ist auch kein Problem, einfach durch eine if Abfrage ob grösser als 100.
    Bleibt aber noch das umrechnen der Zahlen. Im oberen Beispiel habe wir es ja so gemacht:


    CodeBox C und C++
    static const char nybble_chars[] = "0123456789ABCDEF";
    static const char nybble_charsT[] = "0123456789";
    
    void get_byte_hex( unsigned char b, char *buf)       // wird durch RGB aufgerufen
      {
       buf[0] = nybble_chars[ ( b >> 4 ) & 0x0F ];
        buf[1] = nybble_chars[ b & 0x0F ];
      }
     
    void get_byte_hex( unsigned char b, char *buf)       // wird durch RGB aufgerufen
    {
       buf[0] = nybble_charsT[ ( b >> 4 ) & 0x0F ];
       buf[1] = nybble_charsT[ b & 0x0F ];
    }
    

    habe mal angefangen, zwei Werte sind klar und wie mache ich das mit dem dritten Wert?
    achim
     
  20. Dirk

    Dirk Administrator Mitarbeiter

    Registriert seit:
    28. Januar 2007
    Beiträge:
    4.070
    Zustimmungen:
    100
    Ort:
    Mittelhessen, Giessen
    Sprachen:
    C, Assembler, Pascal, C++, PHP, Java
    Map
    Hallo Achim,
    das funktioniert so nicht. Über die Nibble geht es nur mit hexadezimalen Zahlen.

    Wenn du einen Dezimalwert als einzelne Ascii Character benötigst, könntest du es so machen ...
    (nicht getestet)



    CodeBox C und C++
    uint8_t d;
    
    d = 100;
    // vorher ggf. begrenzen
    buf[0] = ((d / 100) % 10) + '0';  // 100er
    buf[1] = ((d / 10) % 10) + '0';  // 10er
    buf[2] = (d % 10) + '0';  // 1er
    
     

Diese Seite empfehlen

  • Über uns

    Unsere immer weiter wachsende Community beschäftigt sich mit Themenbereichen rund um Mikrocontroller- und Kleinstrechnersysteme. Neben den Themen Design von Schaltungen, Layout und Software, beschäftigen wir uns auch mit der herkömmlichen Elektrotechnik.

    Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  • Coffee Time

    Unser makerconnect-Team arbeitet hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und unser eigener makerconnekt-Server regelmäßig gewartet wird. Wir nehmen das Thema Datensicherung und Datenschutz sehr ernst und sind hier sehr aktiv, auch sorgen wir uns darum, dass alles Drumherum stimmt!

    Dir gefällt das Forum und die Arbeit unseres Teams und du möchtest es unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft, unser Team freut sich auch über eine Spende für die Kaffeekasse :-)
    Vielen Dank!
    Dein makerconnect-Team

    Spende uns! (Paypal)