EEPROM
und FLASH- Programmspeicher
beschreiben und auslesen bei PIC16F87x
PIC16F871 hat 64 Byte EEPROM
PIC16F877 hat 256 Byte EEPROM
EEPROM kann bis 1.000.000 Schreibzyklen
EEPROM wird angewendet, wenn irgend welche Einstellungen gespeichert werden
sollen oder erreichte Zustände vor letztem Ausschalten wiederhergestellt werden
sollen.
Bei PIC16F87x-Serie ist
es möglich in Programmspeicher zu schreiben. Allerdings hat er nicht so viele
Schreibzyklen wie EEPROM.
Er hält nur 1000 Schreibzyklen aus.
PIC16F871 hat 2 k und PIC16F877 hat 8k Programmspeicher. Jede Speicherstelle
des Programmspeichers ist 14 Bit groß. Dass heißt, dass wir in eine Speicherstelle
1 Byte und noch 6 Bit speichern können oder ein Wert von 0 bis 16383 ablegen.
Es ist zu beachten, dass man nicht das Programm überschreibt.
Dafür empfehle ich Programm mit Hilfe " #pragma origin 206 " Anweisung
weiter in Speicher zu platzieren. Somit können wir sicher den Bereich von 5
bis 205 beschreiben.
Am Speicherstelle 4 befindet sich Interruptvektor und ab Adresse 206 fängt Programm
an. Es ist natürlich nur ein Beispiel, Ihr Programm muss nicht unbedingt ab
Adresse 206 anfangen.
Anwendungsgebiet: benutzerdefinierte Einstellungen speichern, Menütexte ändern
(bei LCD), Kalibrierungswerte speichern, Bootloader.
Damit Lesen und Speichern von EEPROM und Flash klappt, es muss in dem Konfigurationswort erlaubt werden (sehe Beispiel).
Folgendes Beispielprogramm
zeigt Lesen und Speichern von EEPROM und Flash-Speicher.
Bei Einschalten des Microcontrollers wird serielle Kommunikation initialisiert.
Danach wartet Programm auf einen Befehl von dem PC.
Befehle sind als Zahl zu übertagen, nicht als ASCII -Zeichen.
| 1 : | Flash lesen an Adresse 99 | sendet niedere Datenbyte | sendet obere Datenbyte |
| 2 : | Flash schreiben an Adresse 99 | erwartet niedere Datenbyte | erwartet obere Datenbyte |
| 3 : | EEPROM lesen an Adresse 0 | sendet Datenbyte | |
| 4 : | EEPROM schreiben an Adresse 0 | erwartet Datenbyte |
Nach dem Ausführen des Befehls erwartet Programm das Nächste.
Schaltplan
zum Anschluss an serielle Schnittstelle.
Zum Verbinden mit dem PC ist ein Nullmodemkabel vorgesehen.
Programm zum Senden und Empfanden über serielle
Schnittstelle.
// Testprogramm: Programmspeicher (FLASH) und interne EEPROM beschreiben und lesen.
// Serielle Kommunikation mit (9600,N,8,1) TX==>RC6, RX==>RC7 TTL-RS232-Conwerter
// 20 MHz
#include <D:\cc5\16F871.H>
// Speicherschutz12,13,4,5=aus,Debug1,1=aus,ProgrammFlash9=an,EEpromRead8=an,
// NiedervoltProgr7=aus, NiederVoltReset6=an,EinschaltTimer3=an,
// WachDogTimer2=aus,Oszillator0,1=XC
#pragma config |= 0b.11.111101.11.00.10
#pragma origin 100 // Adresse des Programms
//******************************************************************************
void InitUSART()
{
BRGH=1;
SPBRG=129; // (9600 baud @ 20MHz input clock)
SPEN = 1; // Set_Serial_Pins;
SYNC = 0; // Set_Async_Mode;
TX9 = 0; // Set_8bit_Tx;
RX9 = 0; // Set_8bit_Rx;
CREN = 1; // Enable_Rx;
TXEN = 1; // Enable_Tx;
RCIE=0; // Rx Interrupt aus
}
//++++++++++++++++++++++ FLASH SREIBEN +++++++++++++++++++++++++++++++++++++++++
void FlashWR(uns16 adresse,uns16 Data)
{
EEADR = adresse.low8; // Adresse in Adressregister übertragen
EEADRH = adresse.high8;
EEDATA = Data.low8; // Daten in Datenregister übertragen
EEDATH = Data.high8;
EEPGD=1; // Auswahl Programmspeicher lesen oder EEPROM
WREN=1; // Schreiben ins EEPROM erlauben
GIE=0; // Interrups verbieten
EECON2=0x55;
EECON2=0xAA;
WR=1; // Starten des Sreibens
nop2(); // 2 Zyklen zum Schreiben
GIE=1; // Interrups erlauben
WREN=0; // Schreiben ins EEPROM verbieten
}
//++++++++++++++++++++++ FlashWR LESEN +++++++++++++++++++++++++++++++++++++++++
uns16 FlashRD(uns16 adresse)
{
uns16 antwort;
EEADR = adresse.low8; // Adresse in Adressregister übertragen
EEADRH = adresse.high8;
EEPGD=1; // Auswahl: Programmspeicher lesen oder EEPROM
RD=1; // Starten des Lesens
nop2(); // 2 Zyklen zum Speicher lesen
antwort.low8 = EEDATA; // Daten aus Datenregister auslesen
antwort.high8 = EEDATH;
return antwort;
}
//++++++++++++++++++++++ EEPROM SREIBEN +++++++++++++++++++++++++++++++++++++++++
void EEPROMWR(char adresse,char Data)
EEADR = adresse; // Adresse in Adressregister übertragen
EEDATA = Data; // Daten in Datenregister übertragen
EEPGD=0; // Auswahl: Programmspeicher lesen oder EEPROM
WREN=1; // Schreiben ins EEPROM erlauben
GIE=0; // Interrups verbieten
EECON2=0x55;
EECON2=0xAA;
WR=1; // Starten des Sreibens
nop2(); // 2 Zyklen zum Schreiben
GIE=1; // Interrups erlauben
WREN=0; // Schreiben ins EEPROM verbieten
}
//++++++++++++++++++++++ EEPROM LESEN +++++++++++++++++++++++++++++++++++++++++
char EEPROMRD(char adresse)
{
char antwort;
EEADR = adresse; // Adresse in Adressregister übertragen
EEPGD=0; // Auswahl: Programmspeicher lesen oder EEPROM
RD=1; // Starten des Lesesn
nop2(); // 2 Zyklen zum Speicher lesen
antwort = EEDATA; // Daten aus Datenregister auslesen
return antwort;
}
//**************************************************************************
void main(void)
{
uns16 a; // Variablen
char i;
TRISC=0b.1011.1100; // RC6>TX, RC7<RX
InitUSART(); // Hardwareschnittstelle des PICs einstellen
while(1) // Ganzes Programm ist Endlosschleife
{
while(!RCIF); // Warte auf Empfang
i=RCREG; // Empfange Befehl
switch(i) // Entschlussele Befehl
{
case 1: // Falls Wert 1: empfangen
a=FlashRD(99); // Programmspeicher an Stelle 99 lesen
while(!TXIF); // Prüfen, ob Sender frei ist
TXREG = a.low8; // Niederes Datenbyte senden
while(!TXIF); // Prüfen, ob Sender frei ist
TXREG = a.high8; // Oberes Datenbyte senden
break;