Guten Abend, Ich habe ein 32 Bit Integer Zahl und will diese ins EEPROM bringen. Das EEPROM ist aber als 8 Bit Register aufgebaut, was bedeutet das ich die 32 Bit Zahl in 4 x 8 Bit Blöcke zerlegen muss. Das zerlegen ist weniger Problematisch mit den Befehlen (Highest, Higher, High, Lo). Nun meine Frage beim zusammensetzen der Zahl kann ich ja nich die Dezimalenwerte addieren sondern muss die Binären nehmen. Wie könnete ich das machen ? Der Mikrocontroller ist ein PIC16F628A mein Vorschlag 32bitz= 8.1reg+8.2reg+8.3reg+8.4reg aber ich denke dort addiere ich eben nur die dezimalwerte ? Vielen Dank für die Antworten Andreas
Nimm ne Union aus dem zu speichernden Typ und nem Bytearray. Peter
naja, wenn du C benutzt, sehr einfach, zum Beispiel mit ner Union:
1 | typedef union { |
2 | uint32_t i32; |
3 | struct { |
4 | uint8_t b0; |
5 | uint8_t b1; |
6 | uint8_t b2; |
7 | uint8_t b3; |
8 | };
|
9 | } convert32to8; |
(frei nach dem AVR-GCC Tutorial hier auf der Seite und ohne Gewähr) Wenn du den PIC in Assembler programmierst, wäre mir unklar, wo das Problem liegt, denn dann müsstest du eigentlich schon wissen, wie du mit den 4 Bytes rechnest. Soweit ich weiß haben die PIC16F ja auch nur 8 bit Datenbreite.
Wie schon gesagt ich programmiere mit mikroC, bei einer multiplikation von 32 bit Zahlen übernimmt für mich der Compiler die notwendige Zerlegung in berechenbare Blöcke. Vielen Dank für die Antworten
Andreas wrote: > Wie schon gesagt ich programmiere mit mikroC, bei einer multiplikation > von 32 bit Zahlen übernimmt für mich der Compiler die notwendige > Zerlegung in berechenbare Blöcke. Da wird überhaupt nichts zerlegt oder berechnet. Eine Union ist einfach nur eine unterschiedliche Typdefinition des selben Speicherplatzes. Peter
So jetzt hab ich das Gnaze mal mit einer 16 bit Zahl probiert: unsigned int input; typedef struct { unsigned short bit8_low; unsigned short bit8_high; } bit16; bit16 value; value.bit8_low=125; value.bit8_high=52; input=value; In Value. schreib ich nur testweiße die Werte, das funktioniert alles bis auf die letzt Programmzeile. Irgendwie schreibt er den Wert nicht in die neue Variable. Der Compiler bringt nur die Meldung "Kann value nicht Input zuweisen" Aber warum ? Integer ist eine 16bit zahl und short sind jeweils 8 bit, also müsste das doch funktionieren ?
Hab das Problem gefunden !
1 | unsigned int input; |
2 | |
3 | typedef struct { unsigned short bit8_low; |
4 | unsigned short bit8_high; } bit16; |
5 | bit16 value; |
6 | value.bit8_low=125; |
7 | value.bit8_high=52; |
8 | |
9 | input = *(unsigned*) &value; |
In der Dokumentation war ein fehlerhaftes Beispiel http://www.mikroe.com/forum/viewtopic.php?p=55658&sid=18724aa0b02a34fa1c5f818c602a496e
Das ist aber nicht die feine englische. Siehe oben bei den Beiträgen mit der union.
1 | unsigned int input; |
2 | |
3 | typedef struct { unsigned short bit8_low; |
4 | unsigned short bit8_high; } bit16; |
5 | bit16 value; |
6 | value.bit8_low=125; |
7 | value.bit8_high=52; |
8 | |
9 | input = *(unsigned*) &value; |
Der Code ist ziemlich sinnlos, das sind nur zwei Zuweisungen. Der Witz ist, das du um auf die Bytewerte zu kommen nichts rechnen musst, da der int ja von vornherein schon als Byte Reihenfolge im Speicher liegt. Du brauchst also nur die richtige Syntax, keinen weiteren Variabeln, etc. Wenn du deinen int in Bytes splitten willst nimm entweder Bit Shift Operatoren (der Compiler wandelt das automatisch in reine Zugriffe um) oder ein union. Ein union sieht auf den ersten Blick natürlich sehr elegant aus, hat aber den Nachteil das die (Byte-) Endianness dann vom Prozessor abhängt. Mit Bit Shifts kannst du die selber einstellen. Das ist aber nur wichtig, falls du die Daten mit einem anderen Prozessor wieder auslesen willst
Die 2 Zuweisungen war nur um zu zeigen was ich meine Eigentlich ging es darum auf ein EEProm zuzugreifen da dieses nur 8Bit breit ist muss man doch eine 16 bit zahl zerlegen in 2 teile.
1 | value.bit8_low=EEPROM_READ(1); |
2 | value.bit8_high=EEPROM_READ(2); |
Das ist das eigentliche was ich wollte. Wie schon gesagt ein etwas dämlich gewähltes Beispiel
Warum nicht einfach so?
1 | value = EEPROM_READ(1) + 256 * EEPROM_READ(1); |
Und nein: Da muss keine lange dauernde Multiplikation durchgeführt werden :) Du kannst dir ja mal den Assembler Output davon anschauen. Oder so:
1 | value = EEPROM_READ(1) + (EEPROM_READ(1) << 8); |
Du konstruierst dir da ein Problem wo gar keines ist.
Sorry, beides mal die 1. Muss natürlich heißen:
1 | value = EEPROM_READ(1) + 256 * EEPROM_READ(2); |
2 | /* oder */
|
3 | value = EEPROM_READ(1) + (EEPROM_READ(2) << 8); |
Johnny Maxwell wrote: > Ein union sieht auf den ersten Blick natürlich sehr elegant aus, hat > aber den Nachteil das die (Byte-) Endianness dann vom Prozessor abhängt. Das dürfte so nicht ganz korrekt sein. Da es sich um einen 8Bit Prozessor handelt gibt die Hardware-Architektur nur innerhalb eines Bytes die Reihenfolge der Bits vor (normalerweise LSB rechts). Bei größeren Zahlen mit 16Bit oder 32Bit wird die Reihenfolge der Bytes nur durch den Compiler bestimmt, welcher diese dann bei Operationen mit solchen Zahlen berücksichtigen muß. Erst bei 16Bit oder 32Bit Prozessoren ist schon in der Hardware die Reihenfolge der Bytes vorgegeben. Ciao, Rainer
Hallo, ich habe das so gelöst
1 | char eeprom_write_word(uint16_t eeaddr, uint16_t word) { |
2 | if ((eeprom_write_byte (eeaddr, (uint8_t) (word >> 8))) == 0) return 0; |
3 | return eeprom_write_byte (eeaddr+1, word); |
4 | }
|
mit char eeprom_write_byte(uint16_t eeaddr, uint8_t byte) (Rückgabewert ist hier 1 bei erfolgreichen Schreiben) analog halt mit 32bit. Gruß Andy
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.