Zurück (C) Christof Ermer, Regensburg
Gästebuch (public. sonst besser Email)

Gratis Counter 12.04.2013

EEPROM-im-ATmega


erster Versuch mal alles zum Thema zu sammeln

#include <avr/eeprom.h> 


Was ist zu tun?

WICHTIG: Bei EEPROM Nutzung unbedingt  Brown Out Detection aktivieren...
----> noch besser, ein Supervisor Chip am /Reseteingang, der die Spanung überwacht und /RESET auslöst bei Unterspannung
Grund: Reseteingang sollte schneller LOW werden als  die Betriebsspannung..
und das passiert imme rbei Spannungseinbrüchen udn Ausschalten. ( Auto Startvorgang etc..)
    Sonst droht Datenerlust im EEPROM   ( ERFAHRUNG AUS DER PRAXIS ! )
Minimale /Reset Schaltung

Wirkung der Diode
.. Sie leitet die Kondesatorspannung ab wenn die Spannung sinkt und zieht sodie Spannung am /RESET mit +V Runter,
eben bei Spannungsabsenkungen aller Art..
Das verhindert weitgehend Innhaltsverlust des EEProms. ( soll..)




Arbeitsablauf in einem Program:
Checke ob "schon mal" das EEPROM intialisiert wurde,,
Dazu gibt man am besten 2 Testbyte ein  z.B. 0xA55A

Schreibe diese zusammen mit einem  Datenstructurblock in das EEPROM

1. Lese EEPROM  ob 0xA55A darin ist.. als ertse const information....
    0xA55A  = einfach ein  konstanter Dummywert, der anzeigt ob schon mal initalisieert  wurde. 1234 etc. ginge auch
     Fall NEIN::    Schreibe Default werte eben mit 0xA55A
     Fall  JA:        Lese EEPROM und schreibe Daten in lokale RAMStruktur
            Arbeite mit Ramstruktur, wenn möglich und wenn häufige Zugriffe da sind..
            sonst nur Lesezugriffe...
            seltene Schreibzugriffe..    !! sonst geht EEPROM kaputt



zu finden: BSP...
file:///C:/WinAVR-20100110/doc/avr-libc/avr-libc-user-manual/group__avr__stdint.html#gba7bc1797add20fe3efdf37ced1182c5

Functions

uint8_t eeprom_read_byte (const uint8_t *__p) __ATTR_PURE__
uint16_t eeprom_read_word (const uint16_t *__p) __ATTR_PURE__
uint32_t eeprom_read_dword (const uint32_t *__p) __ATTR_PURE__
float eeprom_read_float (const float *__p) __ATTR_PURE__
void eeprom_read_block (void *__dst, const void *__src, size_t __n)
void eeprom_write_byte (uint8_t *__p, uint8_t __value)
void eeprom_write_word (uint16_t *__p, uint16_t __value)
void eeprom_write_dword (uint32_t *__p, uint32_t __value)
void eeprom_write_float (float *__p, float __value)
void eeprom_write_block (const void *__src, void *__dst, size_t __n)
void eeprom_update_byte (uint8_t *__p, uint8_t __value)
void eeprom_update_word (uint16_t *__p, uint16_t __value)
void eeprom_update_dword (uint32_t *__p, uint32_t __value)
void eeprom_update_float (float *__p, float __value)
void eeprom_update_block (const void *__src, void *__dst, size_t __n)

Defines

#define  EEMEM   __attribute__((section(".eeprom")))
#define  eeprom_is_ready()
#define  eeprom_busy_wait()   do {} while (!eeprom_is_ready())


#include <avr/eeprom.h>   




#define  PRELOAD_VERSIONSNUMMER        1.0
#define  PRELOAD_STEPMOTOR_FREQUENZ    100.0

//Daten für eeprom vorbereiten Bsp: Structur
typedef struct //EEPROM_DATEN
{
uint16_t  u16TestDummy;
float    fVersionsNummer;
float    fStepM_Frq;
uint8_t    u8_StepMot_Status;   // DIR, On/OFF ETc...
//usw..
}INIT_DATEN_TYPE; //RAM Struktur zu speichernde Daten.



//Gloabele Variable anlegen
EEPROM_DATEN_TYPE gstEEProm;

// **********************************************
void Init_EEPromData(void)  //in main() aufrufen
// **********************************************
{//Initalisieren
void Init_EEPromData(void)  //in main() aufrufen
{//Initalisieren
gstInitData.u16TestDummy = 0xA55A;  // Testen OB EEPROM SCHON defineireten Inhalt hat
gstInitData.fVersionsNummer    = PRELOAD_VERSIONSNUMMER;
gstInitData.fStepM_Frq  = PRELOAD_STEPMOTOR_FREUQENZ ;
gstInitData.u8_StepMot_Status;   // DIR, On/OFF ETc...
};




Legt Speicher im EEPROM ab
char EEMEM

// **********************************************
/* EEPROM Init                                  */
/**********************************************/
char EEMEM EEPROM_0[11];
char EEMEM EEPROM_1[11];
...
char SRAMstring[11];

Anwendung ::  ( möglichkeit )
    //void eeprom_read_block (void *__dst, const void *__src, size_t __n
eeprom_read_block( (void*)&SRAMstring, (void*)&EEPROM_0, 11);


Aus einem Buch..... kleine Sammlung,.. mit kleinen Fehlern,






main.h sektion

ALTES BEISPIEL  das realisiert wurde...
//EEPROM
#define EEPROM_SECTION  __attribute__ ((section (".eeprom")))  == heute  EEMEM  EEPROM
#define EEPROM_SIZE    512    //Interne EEPROM
#define EE_DUMMYLOAD 0x5AA5 //unwahrsch. wert 0101 1010 1010 0101
//If using 8 block by 512 max = 64 Byte/block
//


//TYPEN DEKLARATION
typedef struct
    {
    uint8_t ucMotorID;
    float fStepMot_FRQ;   
    float fStepMot_ScanFRQ;        //Nur fuer ScanMode
    float fRampeFrq;        //Wird incrementiert bis == gsStMPar.fStepMot_FRQ für Rampe
    uint8_t ucSM_Mode;    //Full=1 Half  = 2
    uint32_t ulSM_ToRunCnt;    //PULSE die der Motor laufen soll   
    uint8_t ucStepMot_RampRise;
    uint16_t uiStepM_Enable_TimeOut;    //Nach zu langer Stopzeit--Auto Timeout Release (Hitzeschutz)   
bla bla usw..
bla bla usw..
bla bla usw..
}STEPMPARTYPE;    //gsStMPar.


main.c sektion

//EEPROM
// ****************************************************************
void SaveParameter(void)
// ****************************************************************
{
//uint16_t uiDummy  EEPROM_SECTION  = 0; //avoid using lowest addresses
//EEPROM START AT ADRESS 2 (Wegen ersten 2 Byte für Integer DUMMY)
//uiAdr=0;
strcpy_P(gcaStr, MCA_EEPROM_MSG);
strcat_P(gcaStr, MCA_VALID_CMD);
cli(); // Schalte Interrupts aus !!
//void eeprom_write_word (uint16_t *addr, uint16_t val)
eeprom_busy_wait();
eeprom_write_word( &guiEEPDUMMY, EE_DUMMYLOAD); //IN 0 NIX LADEN
//uiAdr=2;//Next Adress
//void eeprom_write_block (const void *buf, void *addr, size_t n)
eeprom_busy_wait();
eeprom_write_block((uint8_t*)gcaStr, &gucaEEPStr, sizeof(gucaEEPStr) );
//uiAdr+=uiSize;
//void eeprom_write_block (const void *buf, void *addr, size_t n)
eeprom_busy_wait();
eeprom_write_block((STEPMPARTYPE*)&gsStMPar, &gsEEPROMsStMPar, sizeof(STEPMPARTYPE));
sei(); // Schalte Interrupts wieder an !!
uart_puts_p( MCA_EEPROM_MSG );
Print_PStrCRLF(MCA_SAVE_CMD);
};



//EE
// *******************************************************************
int CheckEEPROM_Valid(void)
// *******************************************************************
{//return 0 = Fehler
uint16_t uiDummy;
//uint16_t uiDummy  EEPROM_SECTION  = 0; //avoid using lowest addresses
//EEPROM START AT ADRESS 2 (Wegen ersten 2 Byte für Integer DUMMY)
//uiAdr=2;
//Hilfsweise gcaNumStr.
strcpy_P(gcaNumStr, MCA_EEPROM_MSG);// DAS MUSS DRINSTEHEN
strcat_P(gcaNumStr, MCA_VALID_CMD); // DAS MUSS DRINSTEHEN
cli(); // Schalte Interrupts aus !!
eeprom_busy_wait();
uiDummy = eeprom_read_word(&guiEEPDUMMY); // 1. Dummy read
//eeprom_read_block( (char*)gcaStr, &gucaEEPStr, (strlen(gcaNumStr) + 1) );
eeprom_busy_wait();
eeprom_read_block( &gcaStr[0], &gucaEEPStr, sizeof(gucaEEPStr) );
sei(); // Schalte Interrupts wieder an !!
*(gcaStr + strlen(gcaNumStr))= 0;    // [12]-1=11     //Terminiere

/*
PrintStrCRLF("TstEEP");
PrintStrCRLF(gcaNumStr);
PrintStrCRLF(gcaStr);?
strcpy(gcaStr,"EndTst"); // DAS MUSS DRINSTEHEN
PrintStrCRLF(gcaStr);
*/

if( strncmp(gcaStr ,gcaNumStr,strlen(gcaNumStr)) ) //EEPROMVAILD --> Cmp=0
    {//!=
    uart_puts_p( MCA_EEPROM_MSG );
    uart_puts_p( MCA_SPACE_MSG );
    Print_PStrCRLF( MCA_WRONG_MSG );
    //SaveParameter();
    return 0;       
    }
else
    {//OK
    uart_puts_p( MCA_EEPROM_MSG );
    uart_puts_p( MCA_SPACE_MSG );
    Print_PStrCRLF( MCA_OK_MSG );
    return 1;
    };
};


// ****************************************************************
void LoadParameter(void)
// ****************************************************************
{
if( CheckEEPROM_Valid() )
    {
    cli(); // Schalte Interrupts aus !!
//void  eeprom_read_block (void *buf, const void *addr, size_t n)
    eeprom_busy_wait();
    eeprom_read_block((STEPMPARTYPE*)&gsStMPar, &gsEEPROMsStMPar, sizeof(STEPMPARTYPE));
    sei(); // Schalte Interrupts wieder an !!
    uart_puts_p( MCA_EEPROM_MSG );
    Print_PStrCRLF( MCA_LOAD_CMD );
    };
};