Umwandlung einer Ganzzahl in ein Zeichen

Ich verwende einen PIC18f-Mikrocontroller. Ich muss eine 16-Bit-Integer-Variable (2 Bytes) schreiben, die in eine Variable mit zwei Zeichen umgewandelt wurde, dh jedes Byte in eine fortlaufende Adresse des EEPROM schreiben. Zuerst muss ich ein oberes Byte (8-Bit-Daten) in das EEPROM schreiben. Ich kann die höheren 8 Bit der Integer-Variablen nicht mit dem folgenden Code abrufen (wobei ich die unteren 8 Bit der Integer-Variable schreiben kann). Mein Code ist

void int_EEPROM_putc(unsigned char address, unsigned char data);
unsigned char int_EEPROM_getc(unsigned char address);
unsigned char c;
unsigned int d;
unsigned char* e;
unsigned char f;

void main()
{
d=0xffff;
e=(unsigned char*)&d;
//f=*e
f=*(e+1);
int_EEPROM_putc(0x02,f); 
delay_ms(100);
c=int_EEPROM_getc(0x02); 
while(true)
{
    if(c==255)
    {
    PORTB=~PORTB;
    }
    else
    {
    PORTB=0xff;
    }
}
Auch wenn Sie die Dinge zu verkomplizieren scheinen, sieht die Zeigerarithmetik auf den ersten Blick korrekt aus. Sie erwarten c0xFF, aber das ist es nicht?
Und sind Sie sicher, dass Ihre EEPROM-Routinen überhaupt funktionieren? Wie haben Sie das mit dem unteren Byte überprüft? Denken Sie daran, dass der Standard-EEPROM-Inhalt ist 0xFF, ich würde einen Anfangswert verwenden, d=0xAABB;um die Werte zu unterscheiden.
ya Ich habe das untere Byte mit anderen Werten überprüft, es funktioniert gut @Rev1.0
Was hast du mit PORTB verbunden? Leuchtdioden? Da Sie diesen PORT einfach ohne Verzögerung kontinuierlich umschalten, können Sie das Flackern möglicherweise nicht sehen. Kann man mit einem Programmer den Inhalt des EEPROMs auslesen?
Ich verwende ein digitales Oszilloskop, um das Umschalten des PortB zu überprüfen
Nun, nach dem obigen Code zu urteilen, würde es sogar umschalten, wenn das EEPROM-Schreiben fehlschlägt, da der ursprüngliche Inhalt 0xFF ist. Aber ich nehme an, es schaltet überhaupt nicht um? Sie könnten den Inhalt cIhres Ports schreiben und den Wert auswerten.
Wenn ein Bild nicht richtig zu funktionieren scheint, finde ich im Allgemeinen, dass ich etwas in der Dokumentation übersehen habe und einige Ports nur X für N tun, während Y aktiviert ist ...

Antworten (2)

Der allgemeinste Ansatz zum Extrahieren von Teilen eines ganzzahligen Werts ist das Verschieben und Maskieren. So:

d = whatever;
c = d & 0xff; // extract low 8 bits
c = (d >> 8) & 0xff; // extract next 8 bits

Wenn Sie wie hier wissen, dass der Wert in d 16 Bit beträgt, können Sie den Code für die nächsten 8 Bit durch Schreiben etwas einfacher machen

c = d >> 8; // extract high 8 bits of 16-bit value
Dies ist zwar richtig, beantwortet jedoch nicht die Frage, warum der vom OP vorgeschlagene Code nicht funktioniert.

Im Allgemeinen ... ist es aus Gründen der Portabilität keine gute Praxis, für jedes int eine Bitgröße oder "Endian-Ness" anzunehmen. Je nach Prozessor und Compiler kann und int alles von 8-Bit bis 64-Bit oder sogar eine andere ungerade Größe haben und kann entweder im Little-Endian- oder im Big-Endian-Format gespeichert werden.

Was passiert, wenn Sie eines dieser beiden tun?

if(d==255)
{
}

// or 

int d = 0xffff;
d >> 8;
char c = d;
if (c==255)
{
}
Ich verwende MPLAB8.70 und Pic18f45k80. d>>8 funktioniert nicht, der Divisionsoperator funktioniert auch nicht.
d>>8;wird keine Wirkung haben. Es ist nur ein Wert für die rechte Hand, nichts zugewiesen. Du willst wahrscheinlichd=d>>8;
@Dzarda - guter Fang; Ich habe einen Charakter verloren. Es SOLLTE "d>>=8;" sein. Je nach Compiler ist das oft billiger (bezogen auf CPU-Zyklen) als "d=d>>8;".
@TDHofstetter, hast du ein aktuelles Beispiel für einen solchen Compiler? Ich würde es für sehr seltsam halten, wenn d >>= 8;es d = d >> 8;zu einem anderen Code kompiliert wird.
Ich habe im Moment keinen bestimmten Compiler im Sinn, aber ich weiß, dass einige Compiler ein d>>=8 an Ort und Stelle ausführen und den Wert innerhalb des Registers verschieben, während andere Compiler den Wert verschieben und die Variable neu schreiben in den Speicher, lesen Sie diesen Speicher erneut und schreiben Sie ihn mit demselben Wert neu. Mit ein wenig Zeit könnte ich Ihnen wahrscheinlich drei oder vier Compile-to-Assembly-Beispiele von Compilern aus der realen Welt zeigen. Ich habe sehr lange Code optimiert... 8)
@TDHofstetter: Ich finde das wirklich sehr seltsam. Vielleicht bin ich aus der Generation, die auf moderne Compiler setzt :)
Ja, wahrscheinlich. 8) Wir haben heute eine ganze TONNE der Grundlagen vergessen, an denen Leute wie ich die Zähne ausbeißen mussten – wir haben die Vorläufer der heutigen Compiler geschrieben. Als ich anfing, war ein Großteil meiner Arbeit sogar älter als Assembler – wir schrieben manuell Maschinencode und achteten sehr genau auf jedes Byte und jeden Taktzyklus, da der verfügbare Speicher in Kilobyte (oder weniger) angegeben war und die Taktraten oft unter 1 MHz lagen . Es hat sich als praktisch erwiesen – heute schreibe ich noch extrem effizienten Code, weil meine Projekte danach verlangen.