2017-04-07 6 views
-1

Ich habe die 8051 seit etwa zwei Monaten programmiert und bin ein wenig Neuling in der C-Sprache. Ich arbeite gerade mit Flash-Speicher, um es zu lesen, zu schreiben, zu löschen und zu analysieren. Ich arbeite gerade an der Schreibphase und eine der Aufgaben, die ich ausführen muss, ist die Angabe eines Adressstandorts und das Füllen dieses Standorts mit Daten, dann das Inkrementieren zum nächsten Ort und das Füllen mit ergänzenden Daten. So weiter und so weiter, bis ich das Ende erreiche.C - Inkrement 18 Bits in C 8051

Mein Dilemma ist, ich habe 18 Adressenbits zu spielen und haben derzeit drei Bytes für diese 18 Bits zugeordnet. Gibt es trotzdem, dass ich diese 18 Bits zu einem int oder unsigned int kombinieren und so inkrementieren könnte? Oder ist meine einzige Option, das erste Byte zu inkrementieren, und wenn dieses Byte auf 0x00 rollt, das nächste Byte inkrementieren und wenn das nächste übergeht, inkrementieren Sie das nächste?

Ich habe derzeit:

void inc_address(void) 
{ 
    P6=address_byte1; 
    P7=address_byte2; 
    P2=address_byte3; 
    P5=data_byte; 

    while(1) 
    { 
     P6++; 
     if(P6==0x00){P7++;} 
     else if(P7==0x00){P2++;} 
     else if(P2 < 0x94){break;} //hex 9 is for values dealing with flash chip 
     P5=~data_byte; 
    } 
} 
+0

Haben Sie Bitfelder zur Verfügung? OK, also wurde die 8051 an der CT-Grenze fast ausgelöscht und hat weniger RAM als ein flatlined Goldfisch, aber wenn Sie 18 Bits von 24 für ein Bitfield int var verwenden können, könnte das tun ... – ThingyWotsit

+0

Ihr Inkrement sieht fehlerhaft aus Wenn P6 und P7 beispielsweise bei 255 beginnen, erhalten Sie P6 und p7 = 1, wenn beide Null bleiben sollen. Die Schleife ist nicht notwendig - die "Übertragstests" sollten verschachtelt sein. – Clifford

+0

Es wäre auch viel besser, die Adressvariable zu erhöhen und sie dem Port zuzuweisen, anstatt sie dem Port zuzuweisen und die Portwerte zu inkrementieren. – Clifford

Antwort

0

Gibt es trotzdem, dass ich die 18 Bits in ein int oder unsigned int und Schritt wie das kombinieren könnten?

Sicher. Angenommen, dass int und unsigned int sind mindestens 18 Bit breit auf Ihrem System, können Sie dies tun:

unsigned int next_address = (hi_byte << 16) + (mid_byte << 8) + low_byte + 1; 
hi_byte = next_address >> 16; 
mid_byte = (next_address >> 8) & 0xff; 
low_byte = next_address & 0xff; 

Die << und >> sind bitweise Shift-Operatoren, und die binären & das bitweise „und“ Operator.

Es wäre ein bisschen sicherer und tragbarer, keine Annahmen über die Größen Ihrer Typen zu treffen. Um zu vermeiden, dass, umfassen stdint.h, und verwenden Sie Typ uint_least32_t statt unsigned int:

uint_least32_t next_address = ((uint_least32_t) hi_byte << 16) 
     + ((uint_least32_t) mid_byte << 8) 
     + (uint_least32_t) low_byte 
     + 1; 

// ... 
+0

Sie sagen also, eine neue Variable zu erstellen und bitweise Operationen an ihnen auszuführen, um die 18-Bit-Variable zu erstellen, die ich brauche, um zu inkrementieren. Können Sie erklären, warum Sie die +1 am Ende der ersten Zeile setzen? Ich denke das sollte danach kommen und nicht in der Initialisierung richtig? Die folgenden drei Zeilen definieren nur die ursprünglichen Variablen neu, aber warum der bitweise "und" Operator? –

+0

Sie benötigen einen Platz zum Speichern der assemblierten Adresse, da Sie mehrmals darauf zugreifen müssen, um die drei interessierenden Bytes herauszuziehen.Das erfordert eine Variable. Ich habe die +1 im Initialisierer hauptsächlich aus Gründen der Kürze ausgeführt und die Variable so benannt, dass sie mit dieser Initialisierung konsistent ist. Das +1 hätte stattdessen danach gemacht werden können; es ist nur eine stilistische Wahl. Beim Auslesen der aktualisierten Bytes maskiert das bitweise "&" die unerwünschten Bits. Wenn die einzelnen Byte-Variablen einen vorzeichenlosen 8-Bit-Typ haben, ist eine solche Maskierung unnötig, aber harmlos. –

+0

Okay, ich verstehe jetzt. Vielen Dank für deine Hilfe. –

1

Wo address ist uint32_t:

void inc_address(void) 
{ 
    // Increment address 
    address = (address + 1) & 0x0003ffff ; 

    // Assert address A0 to A15 
    P6 = (address & 0xff) 
    P7 = (address >> 8) & 0xff 

    // Set least significant two bits of P2 to A16,A17 
    // without modifying other bits in P2 
    P2 &= 0xFC ;     // xxxxxx00 
    P2 |= (address >> 16) & 0x03 ; // xxxxxxAA 

    // Set data 
    P5 = ~data_byte ; 
} 

aber es ist nicht klar, warum die Funktion inc_address genannt wird, sondern weist auch P5 mit ~data_byte, die vermutlich den Datenbus behauptet? Es tut etwas mehr, als eine Adresse zu erhöhen, die es scheint, also wird es schlecht und verwirrend benannt. Ich schlage auch vor, dass die Funktion Adresse und Daten als Parameter anstatt global data nehmen sollte.