PIC18F27Q10 EEPROM (NVMADRL / -H / -U)

OP #7548611
Lesenswert?

Hallo zusammen

Ich beschäftige mich seit einigen Tagen mit dem PIC18F27Q10 und habe eine Frage zum EEPROM. Von meinen bisherigen PIC18/12 kenne ich es nur so, dass ich eine Adresse (0x00-0xFF) für das Lesen und Schreiben angebe.

Beim F27Q10 muss ich nun aber 3 Adressen angeben (NVMADRL/-H/-U)und verstehe im Moment nicht, was ich dort genau angeben muss. Aufgrund der EEPROM Grösse von 1024 Byte ist mir klar, dass 1 Adressbyte nicht ausreicht. Warum sind es aber 3 und was beinhalten sie genau? Leider kann ich im Datenblatt keine detaillierten Infos dazu finden und wäre für eine kurze Hilfe / Aufklärung sehr dankbar.

Viele Grüsse, Henner

Mein Code:

1
unsigned char EE_Read(unsigned char read_adrl, unsigned char read_adrh, unsigned char read_adru)
2
 {
3
    unsigned char data;
4
    NVMCON0bits.NVMEN = 1;
5
    NVMADRL = read_adrl;
6
    NVMADRH = read_adrh;
7
    NVMADRU = read_adru;
8
    NVMCON1bits.RD = 1;
9
    data = NVMDAT;
10
    NVMCON0bits.NVMEN = 0;
11
    return data;
12
 }
1
void EE_Write(unsigned char write_adrl, unsigned char write_adrh, unsigned char write_adru, unsigned char write_val)
2
 {
3
    NVMADRL = write_adrl;
4
    NVMADRH = write_adrh;
5
    NVMADRU = write_adru;
6
    NVMDATL = write_val;
7
    NVMCON0bits.NVMEN = 1;
8
    INTCONbits.GIE = 0;
9
    NVMCON2 = 0x55;
10
    NVMCON2 = 0xAA;
11
    NVMCON1bits.WR = 1;
12
    while(NVMCON1bits.WR);
13
    INTCONbits.GIE = 1;
14
    NVMCON0bits.NVMEN = 0;
15
 }
Angehängte Dateien:
#7548637
Lesenswert?

Da würde ich mal einen Blick ins Datenblatt empfehlen: "Figure 10-1. Program and Data Memory Map" zeigt doch, dass Flash und EEPROM (und mehr) sich einen 2M-Adressraum teilen. Da braucht es halt mehr als 16 Bit für die Adressen. "NVM" heißt non-volatile memory, und eben nicht (nur) EEPROM.

Dass Flash und EEPROM sich den Adressraum teilen, mag seltsam erscheinen, aber damit braucht es halt nur einen Register-Satz für den (einen) NVM-Controller und kann beide in mehr oder weniger identischer Weise beschreiben.

#7548638
Lesenswert?

Ich mag nicht das DS durchackern, aber ich bin mir fast sicher, dass sich das EEPROM bei neueren Pics irgenwo am Ende des Programmspeichers befindet, deshalb auch drei Register. Ist auch nicht mehr so robust und lässt sich nur blockweise löschen und beschreiben. Alles ohne Gewähr, Gruss J.P.S

OP #7548780
Lesenswert?

Hallo Andreas und Jochen

Vielen Dank für die Antworten. Wenn ich das nun richtig verstehe, ist der Speicher für das EEPROM auf 2 Adressbereiche aufgeteilt: 0x310000 - 0x3100FF und 0x310100 - 0x3101FF. Das ergäbe 256 Byte pro Bereich und somit gesamt 512 Byte für das EEPROM. Der uC hat aber laut DB 1024 Byte EE / DFM Speicher.

Jochen-paul S. schrieb:

Ist auch nicht mehr so robust und lässt sich nur blockweise löschen und beschreiben

Hat das etwas mit "nur blockweise löschen und beschreiben" zu tun? Was heisst "nicht mehr so robust"?

Besten Dank und Gruss, Henner

#7548802
Lesenswert?

Henner S. schrieb:

0x3100FF und 0x310100 - 0x3101FF. Das ergäbe 256 Byte pro Bereich und somit gesamt 512 Byte für das EEPROM. Der uC hat aber laut DB 1024 Byte EE / DFM Speicher.

Nein, 512 Worte, also 1024 Bytes. In der Tabelle steht bei den meisten Einträgen doch auch "word". Das geht da alles ziemlich durcheinander, weil teilweise byteweise geschrieben werden kann. In 10.1 sind die Wort-Adressen angeben. Naja, ich weiß schon, worum ich das ganze PIC-Zeugs nicht mag.

OP #7548815
Lesenswert?

Andreas B. schrieb:

In der Tabelle steht bei den meisten Einträgen doch auch "word".

Korrekt, bei den meisten Einträgen steht "8 Words", "6 Words" oder auch "1 Word". Beim EEPROM steht aber explizit "1024 Bytes" und nichts von Words. Das heisst das EEPROM besteht aus 512 Words und ein Word aus 2 Bytes?

Wie auch immer, ich war eigentlich in den letzten Jahren immer mit meinen PIC Projekten sehr zufrieden und möchte jetzt noch nicht aufgeben.

Mit welchen Werten müsste ich die 3 Bytes NVMADRL/-H /-U befüllen um ein Byte in das EEPROM schreiben und wieder lesen zu können? (Bspw. für das 1. EEPROM Byte)

Ich bin wirklich bemüht die Struktur zu verstehen, im Moment will der Groschen aber noch nicht ganz fallen. Vielleicht hilft es mir wenn ich den Lösungsansatz kenne. Danke und Gruss, Henner

#7548854
Lesenswert?

Tja, gute Frage, im Datenblatt geht's kunterbunt durcheinander, da bleibt wohl nur ausprobieren: Die 22-Bit Startadresse des DFM in die drei Adress-Register, ein Byte programmieren und schauen, ob's an der richtigen Stelle gelandet ist ...

Überhaupt ist das Datenblatt teilweise ein Chaos: Einerseits heißt es "Up to 128k Bytes, Up to 1024 Bytes", andererseits steht in "Table 1" "genau 128 kBytes, genau 1024 Bytes". Bei PFM wahlweise 128kBytes oder 64kWords. Deswegen würde ich den ganze Adressangaben nicht blindlings trauen, die sind u. U. von anderen Versionen kopiert und nicht sorgfältig verifiziert, wie das (nicht nur bei Microchip) heute halt so üblich ist.

OP #7548862
Lesenswert?

Andreas B. schrieb:

Überhaupt ist das Datenblatt teilweise ein Chaos: Einerseits heißt es "Up to 128k Bytes, Up to 1024 Bytes", andererseits steht in "Table 1" "genau 128 kBytes, genau 1024 Bytes". Bei PFM wahlweise 128kBytes oder 64kWords. Deswegen würde ich den ganze Adressangaben nicht blindlings trauen, die sind u. U. von anderen Versionen kopiert und nicht sorgfältig verifiziert, wie das (nicht nur bei Microchip) heute halt so üblich ist.

Da bin ich wohl noch verwöhnt von meinem gebundenen Buch / Datenblatt des PIC18F252. Ich werde meine Versuche mal fortsetzen, vielleicht meldet sich ja noch jemand der es bereits hinter sich hat.

Besten Dank, Gruss Henner

OP #7549151
Lesenswert?

Das Problem ist gelöst.

Wichtigste Info: Der Speicherbereich im DB ist falsch angegeben.

FALSCH:
0x310000 - 0x3100FF und 0x310100 - 0x3101FF

RICHTIG: 0x310000 - 0x3103FF

Vielleicht kann es mal jemand gebrauchen. Dieser Code ist getestet:

1
unsigned char ee_read(unsigned int ee_adr){
2
    unsigned char data;
3
    NVMCON0bits.NVMEN = 1;
4
    NVMADRL = (uint8_t)ee_adr;
5
    NVMADRH = (uint8_t)(ee_adr >> 8);
6
    NVMADRU = 0x31;
7
    NVMCON1bits.RD = 1;
8
    data = NVMDAT;
9
    NVMCON0bits.NVMEN = 0;
10
    return data;
11
}
1
void ee_write(unsigned int ee_adr, unsigned char ee_val){
2
    NVMADRL = (uint8_t)ee_adr;
3
    NVMADRH = (uint8_t)(ee_adr >> 8);
4
    NVMADRU = 0x31;
5
    NVMDATL = ee_val;
6
    NVMCON0bits.NVMEN = 1;
7
    INTCONbits.GIE = 0;
8
    NVMCON2 = 0x55;
9
    NVMCON2 = 0xAA;
10
    NVMCON1bits.WR = 1;
11
    while(NVMCON1bits.WR);
12
    INTCONbits.GIE = 1;
13
    NVMCON0bits.NVMEN = 0;
14
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren