Allgemeines zum
EEPROM
EEPROM lesen
EEPROM beschreiben
Allgenmeines
zum FLASH
FLASH lesen
FLASH beschreiben
Viele PICs besitzen EEPROM-Zellen, in denen jeweils 1 Byte gespeichert werden kann. Im Unterschied zu den normalen Daten-Speicherzellen vergessen die EEPROM-Speicherzellen die in ihnen gespeicherten Informationen nicht beim Ausschalten der Stromversorgung. Hier lassen sich also Werte speichern, die immer wieder benötigt werden - z.B. Kalibrierdaten.
Der EEPROM-Speicherbereich liegt nicht im normalen Adressbereich des PIC. Er kann nur indirekt adressiert werden, was vergleichsweise umständlich ist. Da kein PIC mehr als 256 Byte EEPROM-Speicher hat, reicht eine 8 Bit Adresse aus um eine EEPROM-Zelle eindeutig zu adressieren.
Das Beschreiben des EEPROMS kann während des Brennens durch entsprechende Einstellung der Konfiguration des PIC verboten werden (Codeprotection).
Wie man schon im Assembler-Programm EEPROM-Daten festlegen kann, ist hier erläutert.
In einem PIC findet man die folgenden 6 Register, die zur Arbeit mit dem EEPROM und FLASH dienen:
Um Daten aus einer EEPROM-Zelle zu
lesen
schreibt man zuerst die Adresse der betroffenen EEPROM-Zelle in das
Register
EEADR.
Danach löscht man im EECON1-Register das Bit 7 (EEPGD-Bit)
und
setzt
das Bit 0 (RD-Bit). Daraufhin schreibt der PIC das
Datenbyte
aus der EEPROM-Zelle in das Register EEDATA, wo man es nun
auslesen
kann. Im folgenden Beispiel wird die EEPROM-Zelle 10h gelesen:
BSF STATUS, RP1 ; BCF STATUS, RP0 ; EEADR liegt in der Bank 2 MOVLW 0x10 ; ich möchte die EEPROM-Zelle Nr. 10h auslesen MOVWF EEADR ; dazu schreibe ich die Adresse 10h in EEADR
BSF STATUS,
RP0 ; EECON1 liegt in der Bank 3
BCF STATUS,
RP0 ; EEDATA liegt in der Bank 2 |
Das Beschreiben eines EEPROM ist ein komplizierter Prozess, bei dem ein isolierter Bereich des Chips schrittweise mit Elektronen gefüllt wird. Dieser Prozess ist beim PIC automatisiert. Wir müssen dem PIC nur sagen welche Daten wir wo gespeichert haben wollen, und den Schreibprozess starten. Dieser Schreibprozess läuft dann im Hintergrund ab, er dauert allerdings einige Millisekunden (4 bis 8 ms beim 16F87x), was im Vergleich zum Beschreiben einer normalen Speicherzelle eine Ewigkeit ist.
Auch ist jedes Beschreiben für den EEPROM Stress. Der Hersteller gibt eine garantierte Lebensdauer von 100 000 Schreibzyklen an. Schon beim Brennen des PIC können EEPROM-Daten gleich mitgebrannt werden. Oft muss man aber im laufenden Programm Werte in den EEPROM schreiben.
Um ein versehentliches Überschreiben von EEPROM-Daten zu verhindern, hat man den Schreibprozess kompliziert gestaltet.
Zuerst muss die Adresse der zu
beschreibenden
EEPROM-Zelle in das EEADR-Register sowie das zu schreibende
Datenwort
in das EEDATA-Register geschrieben werden. Nach dem
vorbereitenden
Setzen/Löschen einiger Bits folgt diese festgelegte Folge von 5
Befehlen,
die genau einzuhalten ist:
MOVLW 0x55 ; MOVWF EECON2 ; schreibe 55h MOVLW 0xAA ; MOVWF EECON2 ; schreibe AAh BSF EECON1, WR ; starte den Schreibzyklus |
Hält man sich nicht genau an diese Befehlsfolge, dann werden keine Daten geschrieben. Das gilt natürlich auch, wenn diese Befehlsfolge durch einen Interrupt unterbrochen wird. Deshalb sollte man für diese Befehlsfolge alle Interrupts verbieten.
Im folgenden Beispiel schreiben wir den
Wert 4 in die EEPROM-Zelle 10h
BSF STATUS, RP1 ; BCF STATUS, RP0 ; EEADR und EEDATA liegen in der Bank 2 MOVLW 0x10 ; MOVWF EEADR ; Die Zelle 10h soll beschrieben werden MOVLW 4 ; MOVWF EEDATA ; eine 4 wollen wir schreiben
BSF STATUS,
RP0 ; EECON1 liegt in der
Bank
3 ; Die folgenden 5 Zeilen müssen
genau
so im Code stehen!!!
BSF INTCON,
GIE ; Interrupts wieder
erlauben |
So, das wäre geschafft. Der PIC schreibt nun intern das Byte in den EEPROM, während unser Programm weiterläuft. Solange der Schreibprozess läuft, darf man allerdings nicht auf den EEPROM zugreifen um z.B. weitere Daten zu schreiben. Deshalb muss man vor einem weiteren Zugriff testen, ob der Schreibprozess beendet ist. Im einfachsten Fall schickt man das Programm in eine 10ms lange Warteschleife, innerhalb dieser Zeit wird der PIC schon fertig werden. Es geht aber auch eleganter. Am Ende des Schreibprozesses setzt der PIC das Bit EEIF im Register PIR2. Hat man dieses Bit vor dem Beginn des Schreibens gelöscht, so kann man es nun in einer Schleife so lange Abfragen, bis es wieder gesetzt ist.
Wurde vor Beginn
des Schreibens das EEIE-Bit im Register PIE2 gesetzt,
so
kann das Setzen von EEIF einen Interrupt auslösen. Legt
man
den PIC nach dem Start des Schreibzyklus schlafen (sleep)
so wacht er durch das Setzen von EEIF wieder auf.
Vollen
Schreib-
und
Lesezugriff auf den FLASH erlauben nur wenige PIC-Typen.
Das
sind insbesondere PIC16F87x, PIC16F87xA und PIC16F818/819.
Einen
Nur-Lesezugriff
erlauben
die PIC16F7x
Der Flash-Speicher ist der Programmspeicher des PIC. In ihm wird beim 'Brennen' das Arbeitsprogramm des PIC abgelegt. Flash-Speicher ist eigentlich nichts weiter als eine verbesserte EEPROM-Technologie, die sich schneller beschreiben lässt als normaler EEPROM. Deshalb kann das Programm auch wieder gelöscht und neu geschrieben werden.
Wenn man sich einmal die technischen Daten von Flash-PICs ansieht, dann fällt auf, das der Flash-Speiche viel größer ist, als der Daten oder EEPROM-Speicher. Deshalb ist man versucht, große Datenfelder im Programmcode abzulegen, um nicht den knappen EEPROM-Speicher zu verschwenden. mit Hilfe des Befehls 'addwf PCL, f ' und vieler darauf folgender 'retlw' Befehle lassen sich so im Programmcode Datenblöcke von bis zu 128 Byte ablegen. Größere Datenfelder sind auf diese Weise aber nur kompliziert zu verwalten.
In einigen PICs (insbesondere den 16F87x-Typen) besteht deshalb die Möglichkeit, mittels spezieller Befehle den FLASH-Speicher ähnlich wie den EEPROM-Speicher zu lesen und zu beschreiben.
Das Beschreiben des FLASH kann beim
Brennen
durch entsprechende Einstellung der Konfiguration
des PIC verboten werden
(Codeprotection).
Der Hersteller garantiert für den
Flash-Speicher eine Lebensdauer von 1000 Schreibzyklen (PIC16F87x) bzw.
100000 Schreibzyklen (PIC16F87xA). EEPROM-Zellen sind deutlich
robusterer
und überleben 100000 Schreibzyklen (PIC16F87x) bzw. 1000000
Schreibzyklen
(PIC16F87xA). Für viele Zwecke reicht aber auch eine Lebensdauer
von
1000 Schreibzyklen aus.
Wollen wir eine Flash-Zelle auslesen,
so
müssen wir dem PIC zunächst einmal die Adresse dieser Zelle
mitteilen.
Wären sich eine EEPROM-Zelle mit einem 8-Bit-Wert eindeutig
adressieren
lässt, braucht man für den deutlich größeren
Adressbereich des Flash-Programmspeichers 13 Bit. Da so eine Adresse
nicht
in eine Speicherzelle passt, wird sie in zwei Teile zerschnitten
und
in zwei Speicherzellen geschrieben. Die unteren 8 Bit kommen nach EEADR
und der Rest (5 Bit) nach EEADRH.
Danach setzt man im EECON1-Register
das
Bit
7 (EEPGD-Bit) und danach das Bit 0 (RD-Bit).
Daraufhin liest der PIC die Flash-Zelle, wozu er aber zwei
Arbeitszyklen
braucht. Deshalb müssen nun im Progammcode zwei NOP-Befehle
folgen,
um auf die Beendigung des Lesezyklusses zu warten.
Währenddessen schreibt der PIC das
14-Bit-Datenwort aus der FLASH-Zelle in die Register EEDATA und
EEDATH.
Die unteren 8 Bit kann man nun aus EEDATA auslesen, wären
man
die oberen 6 Bit in EEDATH findet. Im folgenden Beispiel wird
die
Programmspeicher-Zelle 120h gelesen:
BSF STATUS, RP1 ; BCF STATUS, RP0 ; EEADR liegt in der Bank 2 MOVLW 0x01 ; High Teil der Adresse 120h ist 1h MOVWF EEADRH ; den schreibe ich in EEADRH MOVLW 0x20 ; Low-Teil der Adresse 120h ist 20h auslesen MOVWF EEADR ; den schreibe ich in EEADR
BSF STATUS,
RP0 ; EECON1 liegt in der Bank 3
BCF STATUS,
RP0 ; EEDATA liegt in der Bank 2 |
Der folgende Abschnitt bezieht sich auf die 16F87x-Familie. Das Schreibverfahren für die 16F87xA sowie die 16F818/819 weicht etwas ab, da hier immer eine Gruppe von 4 Worten auf einmal geschrieben werden muss.
Ähnlich wie EEPROM-Zellen kann man auch FLASH-Zellen beschreiben. Das soll wohl nicht der Schaffung selbstveränderlichen Programmcodes dienen, wohl aber dem Speichern von Daten im reichlich vorhandenen Programmspeicher. Der Schreibprozess ähnelt dem EEPROM-Schreiben mit folgenden Unterschieden:
Zuerst muss die Adresse der zu
beschreibenden
EEPROM-Zelle in die Register EEADR (untere 8 Bit) und EEADRH
(oberer 5 Bit) geschrieben werden. Dann schreibt man das 14-Bit
Datenwort
in die Register EEDATA (untere 8 Bit) und EEDATH (obere
6
Bit). Nach dem vorbereitenden Setzen/Löschen einiger Bits folgt
diese
festgelegte Folge von 7 Befehlen, die genau einzuhalten ist:
MOVLW 0x55 ; MOVWF EECON2 ; schreibe 55h MOVLW 0xAA ; MOVWF EECON2 ; schreibe AAh BSF EECON1, WR ; starte den Schreibzyklus NOP NOP |
Hält man sich nicht genau an diese Befehlsfolge, dann werden keine Daten geschrieben. Das gilt natürlich auch, wenn diese Befehlsfolge durch einen Interrupt unterbrochen wird. Deshalb sollte man für diese Befehlsfolge alle Interrupts verbieten.
Im folgenden Beispiel schreiben wir den
Wert 204h in die Programmspeicher-Zelle 120h:
BSF STATUS, RP1 ; BCF STATUS, RP0 ; EEADR und EEDATA liegen in der Bank 2 MOVLW
0x01
; MOVLW
2
;
BSF STATUS,
RP0 ; EECON1 liegt in der
Bank
3 ; Die folgenden 7 Zeilen müssen
genau
so im Code stehen!!!
BSF INTCON,
GIE ; Interrupts wieder
erlauben |
So, das wäre
geschafft. Bei 'BSF
EECON1,
WR'
beginnt der PIC das Datenwort in den Programmspeicher zu
schreiben.
Bis er damit fertig ist steht das Programm still. Danach
überspringt
der PIC die beiden NOP-Befehle und arbeitet weiter.