2017-06-08 6 views
-1

Vielleicht ist diese Aufgabe ein bisschen komplizierter als das, was ich unten geschrieben habe, aber der Code, der folgt, ist meine Dezimal zu BCD übernehmen. Die Aufgabe besteht darin, eine Dezimalzahl aufzunehmen, sie in BCD und dann in ASCII umzuwandeln, so dass sie auf einem Mikrocontroller angezeigt werden kann. Soweit ich weiß, funktioniert der Code ausreichend für die grundlegende Operation der Konvertierung in BCD, aber ich bin fest, wenn es darum geht, dies in ASCII zu konvertieren. Die Gesamtausgabe ist ASCII, so dass ein inkrementierter Wert auf einem LCD angezeigt werden kann.Dezimal zu BCD zu ASCII

Mein Code so weit:

int dec2bin(int a){    //Decimal to binary function        
    int bin;              
    int i =1; 
    while (a!=0){            
    bin+=(a%2)*i;           
    i*=10;             
    a/=2;             
    }               
    return bin; 
} 

unsigned int ConverttoBCD(int val){ 

    unsigned int unit = 0; 
    unsigned int ten = 0; 
    unsigned int hundred = 0; 

    hundred = (val/100); 
    ten = ((val-hundred*100)/10); 
    unit = (val-(hundred*100+ten*10)); 
    uint8_t ret1 = dec2bin(unit); 
    uint8_t ret2 = dec2bin((ten)<<4); 
    uint8_t ret3 = dec2bin((hundred)<<8); 
    return(ret3+ret2+ret1); 
} 
+2

Mit Bezug auf Ihre Frage, wie denken Sie, ASCII unterscheidet sich von dezimal, binär usw.? Warum in BCD konvertieren und dann in ASCII, wenn Sie diesen Wert bereits haben? –

+0

Ich verstehe, ASCII ist einfach 48 (Dez) über einer bestimmten Ziffer, aber ich habe keine Ahnung, wie Sie das hier implementieren. Ich verstehe, dass dies eine riesige Anfängerfrage ist, aber ich bin seit Stunden damit beschäftigt, ohne Glück –

+1

Können Sie bitte definieren, was ist Ihre Eingabe und was sollte die Ausgabe sein? Einschließlich ihrer Arten. –

Antwort

1

Die Idee für eine ASCII-Darstellung einer Zahl in BCD zu konvertieren ist eigentlich die „richtige“. Bei BCD müssen Sie nur '0' zu jeder Ziffer hinzufügen, um den entsprechenden ASCII-Wert zu erhalten.

Aber Ihr Code hat mehrere Probleme. Der wichtigste ist, dass Sie versuchen, einen um 8 Bits nach links verschobenen Wert in einen 8-Bit-Typ zu stopfen. Das kann nie funktionieren, diese 8 Bits sind Null, denke darüber nach! Dann mache ich absolut nicht verstehen, was Ihre dec2bin() Funktion soll tun.

So werde ich Ihnen eine mögliche richtige Lösung für Ihr Problem vorstellen. Die Schlüsselidee ist die Verwendung einer char für jede einzelne BCD-Ziffer. Natürlich benötigt eine BCD-Ziffer nur 4 Bits und eine char hat mindestens 8 von ihnen - aber Sie brauchen char sowieso für Ihre ASCII-Darstellung und wenn Ihre BCD-Ziffern bereits in einzelnen char s sind, alles, was Sie tun müssen, ist tatsächlich hinzuzufügen '0' zu jedem.

Während es bei: Umwandlung in BCD durch Teilen und Multiplizieren ist eine Verschwendung von Ressourcen. Es gibt einen netten Algorithmus namens Double dabble für die Umwandlung in BCD nur mit Bitverschiebung und Additionen. Ich verwende es in dem folgenden Beispielcode:

#include <stdio.h> 
#include <string.h> 

// for determining the number of value bits in an integer type, 
// see https://stackoverflow.com/a/4589384/2371524 for this nice trick: 
#define IMAX_BITS(m) ((m) /((m)%0x3fffffffL+1) /0x3fffffffL %0x3fffffffL *30 \ 
        + (m)%0x3fffffffL /((m)%31+1)/31%31*5 + 4-12/((m)%31+3)) 

// number of bits in unsigned int: 
#define UNSIGNEDINT_BITS IMAX_BITS((unsigned)-1) 


// convert to ASCII using BCD, return the number of digits: 
int toAscii(char *buf, int bufsize, unsigned val) 
{ 
    // sanity check, a buffer smaller than one digit is pointless 
    if (bufsize < 1) return -1; 

    // initialize output buffer to zero 
    // if you don't have memset, use a loop here 
    memset(buf, 0, bufsize); 
    int scanstart = bufsize - 1; 
    int i; 

    // mask for single bits in value, start at most significant bit 
    unsigned mask = 1U << (UNSIGNEDINT_BITS - 1); 
    while (mask) 
    { 
     // extract single bit 
     int bit = !!(val & mask); 

     for (i = scanstart; i < bufsize; ++i) 
     { 
      // this is the "double dabble" trick -- in each iteration, 
      // add 3 to each element that is greater than 4. This will 
      // generate the correct overflowing bits while shifting for 
      // BCD 
      if (buf[i] > 4) buf[i] += 3; 
     } 

     // if we have filled the output buffer from the right far enough, 
     // we have to scan one position earlier in the next iteration 
     if (buf[scanstart] > 7) --scanstart; 

     // check for overflow of our buffer: 
     if (scanstart < 0) return -1; 

     // now just shift the bits in the BCD digits: 
     for (i = scanstart; i < bufsize - 1; ++i) 
     { 
      buf[i] <<= 1; 
      buf[i] &= 0xf; 
      buf[i] |= (buf[i+1] > 7); 
     } 
     // shift in the new bit from our value: 
     buf[bufsize-1] <<= 1; 
     buf[bufsize-1] &= 0xf; 
     buf[bufsize-1] |= bit; 

     // next bit: 
     mask >>= 1; 
    } 

    // find first non-zero digit: 
    for (i = 0; i < bufsize - 1; ++i) if (buf[i]) break; 
    int digits = bufsize - i; 

    // eliminate leading zero digits 
    // (again, use a loop if you don't have memmove) 
    // (or, if you're converting to a fixed number of digits and *want* 
    // the leading zeros, just skip this step entirely, including the 
    // loop above) 
    memmove(buf, buf + i, digits); 

    // convert to ascii: 
    for (i = 0; i < digits; ++i) buf[i] += '0'; 

    return digits; 
} 

int main(void) 
{ 
    // some simple test code: 
    char buf[10]; 

    int digits = toAscii(buf, 10, 471142); 
    for (int i = 0; i < digits; ++i) 
    { 
     putchar(buf[i]); 
    } 

    puts(""); 
} 

Sie nicht brauchen diese IMAX_BITS() „magic Makro“, wenn Sie tatsächlich Ihre Zielplattform kennen und wie viele Bits gibt es in der Integer-Typ Sie wollen umwandeln.