mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik MikroC 32bit Zahl in 4x8 Blöcke zerlegen und wieder zusammensetzen


Autor: mikroC Zahl Bitweise addieren (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nimm ne Union aus dem zu speichernden Typ und nem Bytearray.


Peter

Autor: David Madl (md2k7)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
naja, wenn du C benutzt, sehr einfach, zum Beispiel mit ner Union:
typedef union {
        uint32_t i32;
        struct {
                uint8_t b0;
                uint8_t b1;
                uint8_t b2;
                uint8_t b3;
        };
} 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.

Autor: Andreas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Andreas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 ?

Autor: Andreas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab das Problem gefunden !

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 = *(unsigned*) &value;


In der Dokumentation war ein fehlerhaftes Beispiel

http://www.mikroe.com/forum/viewtopic.php?p=55658&...

Autor: Gast (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist aber nicht die feine englische. Siehe oben bei den Beiträgen mit 
der union.

Autor: Johnny Maxwell (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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 = *(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

Autor: Andreas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

value.bit8_low=EEPROM_READ(1);
value.bit8_high=EEPROM_READ(2);


Das ist das eigentliche was ich wollte.

Wie schon gesagt ein etwas dämlich gewähltes Beispiel

Autor: Johnny Maxwell (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Warum nicht einfach so?
  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:
  value = EEPROM_READ(1) + (EEPROM_READ(1) << 8);

Du konstruierst dir da ein Problem wo gar keines ist.

Autor: Johnny Maxwell (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry, beides mal die 1. Muss natürlich heißen:
value = EEPROM_READ(1) + 256 * EEPROM_READ(2);
/* oder */
value = EEPROM_READ(1) + (EEPROM_READ(2) << 8);

Autor: R. W. (quakeman)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Johnny Maxwell (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das stimmt natürlich :)

Autor: Andreas B. (bitverdreher)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich habe das so gelöst
char eeprom_write_word(uint16_t eeaddr, uint16_t word) {
   if ((eeprom_write_byte (eeaddr, (uint8_t) (word >> 8))) == 0) return 0;
   return eeprom_write_byte (eeaddr+1, word);
}

 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

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.