Vad är ett minneschip och hur man programmerar mikrokretsar. Hur man rensar EEPROM (Icke-flyktigt minne) Använda eeprom-minne

Förra gången, när jag skrev mitt "detaljerade svar på frågan" om hur man säkerhetskopierar firmware från Mega, klandrade de mig för att jag inte nämnde EEPROM-säkerhetskopian. Den gången gjorde jag det inte medvetet, för... Jag bedömde med rätta att det inte finns något behov av att komplicera allt i skedet av den första "inställningen till projektilen." Faktum är att det inte är uppenbart för alla att EEPROM inte flashas när man kompilerar och laddar upp firmware från Arduino IDE. Det vill säga, detta betyder att absolut ingenting laddas upp till EEPROM när firmware laddas upp från IDE. Och manipulationer med EEPROM (om dess användning är aktiverad i firmware alls) utförs på en helt annan nivå. Och därför att säkerhetskopiera bar firmware utan finjusteringar, som MÖJLIGT (bara kanske) kan lagras i EEPROM, räckte det för att bara spara den bara firmware. Men eftersom frågan har uppstått, varför inte "tugga" den. Låt oss gå igenom det i ordning. Vad är EEPROM och varför prata om det?
EEPROM - (Electrically Erasable Programmable Read-Only Memory) område av mikrokontrollerns icke-flyktiga minne i vilket information kan skrivas och läsas. Den används ofta för att lagra programinställningar som kan ändras under drift och som måste lagras när strömmen stängs av.

Hur använder en 3D-skrivare EEPROM?
Låt oss titta på Marlin som ett exempel. I Marlin Firmware out of the box används inte EEPROM. Konfiguratorparametrarna (Configuration.h), som inkluderar möjligheten att använda den, kommenteras som standard.

#define EEPROM_SETTINGS
#define EEPROM_CHITCHAT

Om användningen av EEPROM är aktiverad kan skrivaren lagra och använda följande inställningar (anges från bourgeoisien):

  • Antal steg per millimeter
  • Maximal/minsta matningshastighet [mm/s]
  • Maximal acceleration [mm/s^2]
  • Acceleration
  • Acceleration vid indragning
  • PID-inställningar
  • Hempositionsförskjutning
  • Minsta matningshastighet under rörelse [mm/s]
  • Minsta sektionstid [ms]
  • Högsta hastighetshopp X-Y axlar[mm/s]
  • Maximalt hastighetshopp i Z-axeln [mm/s]
Du kan redigera dessa inställningar med hjälp av skrivarens skärm och kontroller. När användning av EEPROM är aktiverat, bör menyn visa följande objekt:
  • Lagra minne
  • Ladda minne
  • Återställ felsäkert
Du kan också använda GCode för att arbeta direkt (via Proninterface).
  • M500 Sparar aktuella inställningar i EEPROM till nästa uppstart eller kommando M501.
  • M501 Läser inställningar från EEPROM.
  • M502 Återställer inställningarna till standardvärdena som anges i Configurations.h. Om du kör M500 efter det kommer standardvärdena att matas in i EEPROM.
  • M503 Visar aktuella inställningar - ""De som är inspelade i EEPROM.""
Du kan läsa om EEPROM i Repitier firmware.

Hur läser och skriver man data till EEPROM?
Liknar metoden som beskrivs i metoden för säkerhetskopiering av firmware med nyckeln -U. Endast i detta fall, efter det, kommer det att finnas en pekare som indikerar att EEPROM behöver läsas.

avrdude.exe -p atmega2560 -c ledningar -PCOM5 -b115200 -Ueeprom:r:"printer_eeprom".eep:i

Detta kommando läser EEPROM-data till filen "printer_eeprom.eep".Om det lyckas, kommer du att se något i stil med följande på skärmen.

Inspelning är inte heller komplicerad och utförs av ett liknande kommando, som bara skiljer sig i nyckeln -U Det är inte "r", utan "w".

avrdude.exe -p atmega2560 -c ledningar -PCOM5 -b115200 -Ueeprom:w:"printer_eeprom".eep:i

Om det lyckas kommer du att se något i stil med följande meddelande på skärmen.

Hur och varför raderar man EEPROM?
Till att börja med, "varför gör det här?" Du måste radera EEPROM om den tidigare firmware också använde den, och det kan finnas skräp kvar i minnet. Någonstans har jag redan stött på människor med problem att efter att ha bytt från en firmware till en annan (från Marlin till Repitier EMNIP), började deras skrivare att bete sig så att säga "kreativt". Detta beror på att olika firmware lagrar sina data under olika adresser. Och när du försöker läsa data från fel adress börjar pandemonium.
Du kan endast radera EEPROM programmatiskt från den fasta programvaran, men för att göra detta måste du tillfälligt ladda upp en speciell skiss till styrenheten. Du kan läsa mer om detta i den officiella Arduino-dokumentationen.
Om EEPROM raderas inte in Arduino-bräda, och i vissa abstrakta kontroller kommer skisskoden att behöva ändras med hänsyn till storleken på EEPROM i en specifik styrenhet på kortet. För att göra detta måste du ändra slutvillkoret i "For"-loopen. Till exempel, för ATmega328, som har 1 kb EEPROM-minne, kommer cykeln att se ut så här:
Slutsats.
Jag har tjatat ganska länge, men vad är allt detta till för? För att dra slutsatsen att vid säkerhetskopiering av firmware kan EEPROM också sparas, men bara om du behöver inställningarna sparade i den. Om du är redo att offra dem, glöm det då. Om du byter en firmware till en annan, eller byter från en version till en annan, var inte lat för att rensa EEPROM innan du laddar upp ny firmware. Jo, samtidigt lärde vi oss mycket nytt.

Vår ugnskontroller är nästan klar - men för närvarande förblir den en "guldfisk"-kontroller som kommer ihåg alla inställningar bara fem minuter innan den första avstängningen. För att komma ihåg våra inställningar, värdet på den inställda temperaturen och kalibreringspunkterna även efter att du har stängt av strömmen, måste du använda ett icke-flyktigt minne - EEPROM.
Våra vänner har skrivit väldigt bra om att arbeta med EEPROM.

Det viktigaste vi behöver veta är det EEPROM-minne Det är bättre att betrakta det inte som "bara minne", utan som en separat intern enhet i chippet.
EEPROM separat adressutrymme, som inte har något att göra med processorns adressutrymme (FLASH och SRAM); för att komma åt data på en specifik adress i det icke-flyktiga minnet måste du köra en viss sekvensåtgärder som använder ett antal register (adressregistren EEARH och EEARL, dataregistret EEDR och kontrollregistret EECR).
Enligt databladet, för att skriva en byte till en specifik adress i EEPROM, måste du göra följande:

  1. vänta på att EEPROM är redo att skriva data (EEPE-biten i EECR-registret återställs);
  2. vänta på slutet av skrivningen till FLASH-minnet (återställning av SELFPRGEN-biten i SPMCSR-registret) - detta måste göras om starthanteraren finns i programmet;
  3. Skriv ner ny adress till EEAR-registret (om nödvändigt);
  4. skriva en databyte till EEDR-registret (om nödvändigt);
  5. ställ in EEMPE-biten i EECR-registret till ett;
  6. inom fyra klockcykler efter inställning av EEMPE-flaggan, skriver vi en logisk etta till EEPE-biten i EECR-registret.

Processorn hoppar sedan över 2 klockcykler innan nästa instruktion utförs.
Den andra punkten måste utföras om det finns en bootloader i programmet - faktum är att skrivning till EEPROM inte kan utföras samtidigt med skrivning till FLASH-minne, så innan du skriver till EEPROM måste du se till att programmeringen av FLASH-minnet är klar; om mikrokontrollern inte har en bootloader, ändrar den aldrig innehållet i FLASH-minnet (kom ihåg att avr har en Harvard-arkitektur: programminne (FLASH) och dataminne (SRAM) är separerade).
Varaktigheten av inspelningscykeln beror på frekvensen hos chipets interna RC-oscillator, matningsspänning och temperatur; vanligtvis för ATmega48x/88x/168x-modeller är detta 3,4 ms (!), för vissa äldre modeller - 8,5 ms (!!!).
Dessutom, när du skriver till EEPROM, kan problem uppstå med anropsavbrott under utförandet av sekvensen av åtgärder ovan - så det är bättre att inaktivera avbrott när du skriver till EEPROM.
Att läsa icke-flyktigt minne är lite enklare:

  1. vänta på att EEPROM är redo att läsa data (EEWE-biten i EECR-registret återställs);
  2. skriv adressen till EEAR-registret;
  3. ställ in EERE-biten i EECR-registret till ett;
  4. vi läser data från EEDR-registret (i själva verket, när de begärda uppgifterna flyttas till dataregistret händer det hård återställning lite EERE; men det finns inget behov av att övervaka tillståndet för denna bit, eftersom läsoperationen från EEPROM alltid utförs i en klockcykel).

Efter att ha ställt in en bit i EERE till ett, hoppar processorn över 4 klockcykler innan nästa instruktion utförs.
Som vi ser, arbetar med icke-flyktigt minne– processen är tidskrävande; om vi ofta skriver och läser data från EEPROM kan programmet börja sakta ner.

Vi skriver dock ett program i IAR-miljön, och vi har tur: allt arbete med läsning och skrivning från EEPROM kommer att göras av utvecklingsmiljön - iar har modifieraren "__eeprom", som skapar variabler i icke-flyktigt minne - och då behöver vi bara läsa från "permanenta" variabler till "aktuella" (vid initiering av styrenheten), eller skriva från "aktuella" variabler till "konstanta" - det vill säga när det aktuella värdet ändras, värdet på variabel i icke-flyktigt minne måste också ändras.
De nya variablerna kommer att se ut så här:

Eeprom uint16_t EEP_MinTemperature;

Ett par mer allmänna ord: och även om vi inte antar pekare till eeprom-variabler, måste vi komma ihåg att eeprom är ett separat adressutrymme, och för att skapa en pekare till eeprom (och kompilatorn tillåter oss att göra detta), vi måste indikera att detta är en pekare till en adress i eeprom:

Uint16_t __eeprom *EEP_MinTemperatureAdr;

Låt oss återgå till spisstyrenheten och EEPROM. I vårt fall finns det inget EEPROM virtuell maskin, naturligtvis, förväntas inte; Dessutom är det värt att överväga om ett separat bibliotek behövs för att arbeta med icke-flyktigt minne - de är för "utspridda" över inspelningsprogrammet viktiga inställningar; om du försöker skapa ett separat bibliotek måste du göra korsreferenser: i biblioteket för EEPROM, anslut biblioteken för ADC, värmeelement och globala inställningar; och i dessa perifera bibliotek är det inte så bra att ansluta EEPROM-biblioteket.
Ett annat alternativ är att lägga till en eeprom-variabel till varje bibliotek där du behöver spara inställningar och spara motsvarande inställningar direkt i virtuella maskiner. Vi kommer att implementera detta alternativ.
Låt oss först lista vilka variabler vi behöver spara i EEPROM:

  1. kalibreringspunkter
  2. värden för den max-minsta inställda temperaturen och temperaturinställningssteget
  3. inställt temperaturvärde
  4. PID-regulatorkoefficienter

Vi sparar inte värdet på kökstimern - vi kommer att anta att användaren måste ställa in spistimern varje gång efter att strömmen stängts av.
Alla dessa inställningar görs av användaren genom att vrida på encodern och sedan kort trycka på användarknappen. Samtidigt kommer vi ihåg att antalet EEPROM-läs- och skrivcykler fortfarande är begränsat, så skriv inte över samma information igen (till exempel om användaren valde samma värde för någon inställning som den var). Därför kontrollerar vi innan varje ändring av variabeln __eeprom om den behöver skrivas om:

//om värdet har ändrats, skriv över det i det beständiga minnet om (ADCTemperature.atMinTemperatureValue != (uint16_t)VMEncoderCounter.ecntValue) ( ​​atureV alue; )

Att läsa inställningar från EEPROM är också enkelt - när vi initierar de "nuvarande" inställningarna läser vi helt enkelt värdet från det beständiga minnet:

ADCTemperature.atMinTemperatureValue = EEP_MinTemperature;

För att vår enhet ska ha några inställningar i EEPROM från allra första början, kan projektet för den första uppstarten kompileras med dessa variabler initierade:

Eeprom uint16_t EEP_MinTemperature = 20; ... //array för lagring av kalibreringspunkter i icke-flyktigt minne __eeprom TCalibrationData EEP_CalibrationData = ((20, 1300), (300, 4092));

I det här fallet initierar kompilatorn __eeprom-variabler innan du börjar arbeta med huvudfunktionen. För att få en fil med icke-flyktigt minne (.eep) måste du gå in i följande inställningar:
Projekt->Alternativ..->Linker->Extra alternativ
Om kryssrutan "Använd kommandoradsalternativ" inte är markerad, markera den och lägg till raden
-Ointel-standard,(XDATA)=.eep
Först kompilerar vi projektet med initierade variabler, sparar eep-filen separat; sedan tar vi bort initialisering när vi skapar variabler.

Det är allt - vår spis är klar!

Arduino är en hel familj olika enheter för att skapa elektroniska projekt. Mikrokontroller är mycket bekväma att använda och är lätta att lära sig även för en nybörjare. Varje mikrokontroller består av ett kort, program för drift och minne. Den här artikeln kommer att titta på det icke-flyktiga minnet som används i Arduino.

Beskrivning av EEPROM-minne

Arduino förser sina användare med tre typer av inbyggt enhetsminne: stationärt RAM (Random Access Memory eller SRAM – statiskt Random Access Memory) – nödvändigt för inspelning och lagring av data under användning; flashkort – för att spara redan inspelade mönster; – för lagring och efterföljande användning av data.

All data på RAM-minnet raderas så snart enheten startas om eller strömmen stängs av. De andra två sparar all information innan du skriver över och låter dig hämta den om det behövs. Flash-enheter är ganska vanliga nuförtiden. Det är värt att överväga EEPROM-minne mer i detalj.

Förkortningen står för Electrically Erasable Programmable Read-Only Memory och översatt till ryska betyder bokstavligen elektriskt raderbart programmerbart skrivskyddat minne. Tillverkaren garanterar informationssäkerheten i flera decennier efter det senaste strömavbrottet (vanligtvis ges en period på 20 år, beroende på i vilken takt enhetens laddning minskar).

Du måste dock veta att möjligheten att skriva om till en enhet är begränsad och inte är mer än 100 000 gånger. Därför rekommenderas det att vara noggrann och uppmärksam på de inmatade uppgifterna och att inte skriva över dem igen.

Mängden minne, i jämförelse med modern media, är mycket liten och varierar för olika mikrokontroller. Till exempel, för:

  • ATmega328 – 1kB
  • ATmega168 och ATmega8 – 512 byte,
  • och ATmega1280 – 4 kB.

Den är utformad på det här sättet eftersom varje mikrokontroller är designad för en specifik volym av uppgifter, har olika antal stift för anslutning, och följaktligen krävs en annan mängd minne. Dessutom är detta belopp tillräckligt för vanligt skapade projekt.

Att skriva till EEPROM kräver en betydande tid - ca. 3 ms. Om strömmen stängs av under inspelning kommer data inte att sparas alls eller kan spelas in felaktigt. Det är alltid nödvändigt att ytterligare kontrollera den inmatade informationen för att undvika fel under drift. Att läsa data går mycket snabbare och minnesresursen minskar inte.

Bibliotek

Att arbeta med EEPROM-minne utförs med hjälp av ett bibliotek som skapats speciellt för Arduino. De viktigaste är förmågan att skriva och läsa data. aktiveras med kommando #inkludera EEPROM.h.

  • För uppgifter– EEPROM.write(adress, data);
  • För läsning– EEPROM.read(adress).

I dessa skisser: adress – ett argument med data från cellen där data för det andra argumentet matas in; vid läsning används ett argument, adress, som anger varifrån informationen ska läsas.

Fungera Syfte
läsa (adress) läser 1 byte från EEPROM; adress – adress från vilken data läses (cell från 0);
skriv(adress, värde) skriver värde (1 byte, nummer från 0 till 255) till minnet vid adress;
uppdatera (adress, värde) ersätter värde vid adress om dess gamla innehåll skiljer sig från de nya;
få (adress, data) läser data av angiven typ från minnet vid adress;
put(adress, data) skriver data av den specificerade typen i minnet vid adress;
EEPROM låter dig använda "EEPROM"-identifieraren som en array för att skriva data till och läsa från minnet.

Skriva heltal

Att skriva heltal till icke-flyktigt EEPROM-minne är ganska enkelt. Inmatning av siffror sker när funktionen startas EEPROM.write(). De nödvändiga uppgifterna anges inom parentes. I det här fallet skrivs siffror från 0 till 255 och siffror över 255 olika. De första skrivs enkelt in - deras volym tar 1 byte, det vill säga en cell. För att skriva det senare måste du använda operatorerna highByte() för den högsta byten och lowByte() för den lägsta byten.

Numret är uppdelat i byte och skrivs separat i celler. Till exempel kommer talet 789 att skrivas i två celler: den första kommer att innehålla faktorn 3, och den andra kommer att innehålla det saknade värdet. Resultatet är det obligatoriska värdet:

3 * 256 + 21 = 789

För « återförening" stort heltal gäller ord funktion(): int val = word(hej, låg). Du måste läsa att det maximala heltal för inspelning är 65536 (det vill säga 2 i potensen av 16). I celler som ännu inte har haft andra poster kommer monitorn att visa siffrorna 255 i varje.

Skriva flyttal och strängar

Flyttal och strängtal är en form av att skriva reella tal där de representeras av en mantiss och en exponent. Sådana nummer skrivs till icke-flyktigt EEPROM-minne genom att aktivera funktionen EEPROM.put(), läsning, respektive, – EEPROM.get().

Vid programmering betecknas flyttalsnumeriska värden som flytande; det är värt att notera att detta inte är ett kommando, utan ett tal. Teckentyp (teckentyp) – används för att representera strängar. Processen att skriva siffror på monitorn startas med setup(), läsning - med loop().

Under processen kan värdena ovf, vilket betyder "överfylld" och nan, vilket betyder "saknas", visas på skärmen numeriskt värde" Detta innebär att informationen som skrivs till cellen inte kan reproduceras som ett flyttal. Denna situation kommer inte att uppstå om du tillförlitligt vet i vilken cell vilken typ av information som finns registrerad.

Exempel på projekt och skisser

Exempel nr 1

Skissen kommer att skriva upp till 16 tecken från serieporten och mata ut 16 tecken från EEPROM i en loop. Tack vare detta skrivs data till EEPROM och innehållet i det icke-flyktiga minnet övervakas.

// kontrollera funktionen för EEPROM #include int i, d; void setup() ( Serial.begin(9600); // initiera porten, hastighet 9600 ) void loop() ( // läs EEPROM och mata ut 16 data till serieporten Serial.println(); Serial.print("EEPROM = " ); i= 0; medan(i< 16) { Serial.print((char)EEPROM.read(i)); i++; } // проверка есть ли данные для записи if (Serial.available() != 0) { delay(50); // ожидание окончания приема данных // запись в EEPROM i= 0; while(i < 20) { d= Serial.read(); if (d == -1) d= " "; // если символы закончились, заполнение пробелами EEPROM.write(i, (byte)d); // запись EEPROM i++; } } delay(500); }

Exempel nr 2

För en bättre förståelse kan vi skapa en liten skiss som hjälper dig att förstå hur man arbetar med icke-flyktigt minne. Vi räknar alla celler i detta minne. Om cellen inte är tom - utmatning till serieporten. Fyll sedan cellerna med mellanslag. Sedan skriver vi in ​​texten genom serieportmonitorn. Vi skriver den till EEPROM och läser den nästa gång den slås på.

#omfatta int adress = 0; // eeprom-adress int read_value = 0; // data läst från eeprom char serial_in_data; // seriell port data int led = 6; // rad 6 för LED int i; void setup() ( pinMode(led, OUTPUT); // rad 6 är konfigurerad som utdata Serial.begin(9600); // baudhastighet på seriell port 9600 Serial.println(); Serial.println("FÖREGÅENDE TEXT I EEPROM : -"); for(adress = 0; adress< 1024; address ++) // считываем всю память EEPROM { read_value = EEPROM.read(address); Serial.write(read_value); } Serial.println(); Serial.println("WRITE THE NEW TEXT: "); for(address = 0; address < 1024; address ++) // заполняем всю память EEPROM пробелами EEPROM.write(address, " "); for(address = 0; address < 1024;) // записываем пришедшие с последовательного порта данные в память EEPROM { if(Serial.available()) { serial_in_data = Serial.read(); Serial.write(serial_in_data); EEPROM.write(address, serial_in_data); address ++; digitalWrite(led, HIGH); delay(100); digitalWrite(led, LOW); } } } void loop() { //---- мигаем светодиодом каждую секунду -----// digitalWrite(led, HIGH); delay(1000); digitalWrite(led, LOW); delay(1000); }

Exempel nr 3

Skriver två heltal till minnet, läser dem från EEPROM och matar ut dem till serieporten. Siffror från 0 till 255 upptar 1 byte minne med funktionen EEPROM.write() skrivs till önskad cell. För nummer större än 255 måste de delas upp i byte med hjälp av highByte() Och lowByte() och skriv varje byte i sin egen cell. Det maximala antalet i det här fallet är 65536 (eller 2 16).

#omfatta // anslut EEPROM-biblioteket void setup() ( int smallNum = 123; // heltal från 0 till 255 EEPROM.write(0, smallNum); // skriv ett tal till cell 0 int bigNum = 789; // dela talet > 255 gånger 2 byte (max. 65536) byte hi = highByte(bigNum); // high byte byte low = lowByte(bigNum); // low byte EEPROM.write(1, hi); // skriv hög byte av EEPROM till cell 1 .write(2, low); // skriv den låga byten till cell 2 Serial.begin(9600); // initiera serieporten ) void loop() ( för (int addr=0; addr<1024; addr++) { // для всех ячеек памяти (для Arduino UNO 1024) byte val = EEPROM.read(addr); // считываем 1 байт по адресу ячейки Serial.print(addr); // выводим адрес в послед. порт Serial.print("\t"); // табуляция Serial.println(val); // выводим значение в послед. порт } delay(60000); // задержка 1 мин }

Exempel nr 4

Skriva flyttal och strängar - metod EEPROM.put(). Läser – EEPROM.get().

#omfatta // anslut biblioteket void setup() ( int addr = 0; // address float f = 3.1415926f; // flyttalnummer (flytande typ) EEPROM.put(addr, f); // skriv numret f till adressen addr addr += sizeof(float); // beräkna nästa lediga minnescell char name = "Hej, SolTau.ru!"; // skapa en array av tecken EEPROM.put(addr, namn); // skriv arrayen till EEPROM Serial.begin (9600); // initierar serieporten ) void loop() ( för (int addr=0; addr<1024; addr++) { // для всех ячеек памяти (1024Б=1кБ) Serial.print(addr); // выводим адрес в послед. порт Serial.print("\t"); // табуляция float f; // переменная для хранения значений типа float EEPROM.get(addr, f); // получаем значение типа float по адресу addr Serial.print(f, 5); // выводим с точностью 5 знаков после запятой Serial.print("\t"); // табуляция char c; // переменная для хранения массива из 20 символов EEPROM.get(addr, c); // считываем массив символов по адресу addr Serial.println(c); // выводим массив в порт } delay(60000); // ждём 1 минуту }

Exempel nr 5

Använder EEPROM som en array.

#omfatta void setup() ( EEPROM = 11; // skriv den första cellen EEPROM = 121; // skriv den andra cellen EEPROM = 141; // skriv den 3:e cellen EEPROM = 236; // skriv den fjärde cellen Serial .begin(9600 ); ) void loop() ( för (int addr=0; addr<1024; addr++) { Serial.print(addr); Serial.print("\t"); int n = EEPROM; // считываем ячейку по адресу addr Serial.println(n); // выводим в порт } delay(60000); }

Arbetar med EEPROM

Som nämnts tidigare är EEPROM-minnet begränsat. För att förlänga livslängden för icke-flyktigt minne, istället för funktionen write(), är det bättre att använda uppdateringsfunktionen. I det här fallet utförs omskrivning endast för de celler där värdet skiljer sig från den nyskrivna.

En annan användbar funktion hos mikrokontrollerminnet i fråga är förmågan att använda bytelagringsceller som delar av en integrerad EEPROM-array. I alla användningsformat är det nödvändigt att ständigt övervaka integriteten hos de registrerade uppgifterna.

Sådant minne på Arduino lagrar som standard de viktigaste sakerna för driften av styrenheten och enheten. Till exempel, om en temperaturregulator skapas på en sådan grund och de initiala uppgifterna visar sig vara felaktiga, kommer enheten att fungera "otillräckligt" för de befintliga förhållandena - det kommer att kraftigt underskatta eller överskatta temperaturen.

Det finns flera situationer där EEPROM innehåller felaktiga data:

  1. Vid den första aktiveringen fanns det inga poster ännu.
  2. Under ett okontrollerat strömavbrott kommer en del eller all data inte att registreras eller kommer att registreras felaktigt.
  3. Efter slutförandet av möjliga dataomskrivningscykler.

För att undvika obehagliga konsekvenser kan enheten programmeras för flera åtgärdsalternativ: tillämpa nödkodsdata, stäng av systemet helt, signalera ett fel, använd en tidigare skapad kopia eller andra.

För att kontrollera informationens integritet används en systemkontrollkod. Den skapas baserat på den ursprungliga dataregistreringen och, när den har verifierats, räknar den om data. Om resultatet är annorlunda är det ett fel. Den vanligaste versionen av en sådan kontroll är en kontrollsumma - en enkel matematisk operation utförs för att lägga till alla cellvärden.

Erfarna programmerare lägger till ytterligare ett "exklusivt ELLER" till denna kod, till exempel E5h. Om alla värden är lika med noll och systemet av misstag återställer originaldata, kommer detta trick att avslöja felet.

Dessa är de grundläggande principerna för att arbeta med icke-flyktigt EEPROM-minne för Arduino-mikrokontroller. För vissa projekt är det värt att endast använda denna typ av minne. Det har både sina fördelar och nackdelar. För att behärska skriv- och läsmetoder är det bättre att börja med enkla uppgifter.

Alla mikrokontroller i Mega-familjen inkluderar icke-flyktigt minne ( EEPROM minne). Volymen på detta minne sträcker sig från 512 byte i ATmega8x-modeller till 4 KB i äldre modeller. EEPROM minnet ligger i sitt eget adressutrymme och är, liksom RAM, organiserat linjärt. Att arbeta med EEPROM Minnet använder tre I/O-register: ett adressregister, ett dataregister och ett kontrollregister.

Adressregister

Adressregister EEPROM minne EEAR (EEPROM-adressregister) fysiskt placerad i två RVV EEARH:EEARL, som ligger längs
adresser $1F ($3F) respektive $1E ($3E). Detta register laddas med adressen till cellen som kommer att nås. Adressregistret är både skrivbart och läsbart. Samtidigt i registret EEARH endast de minst signifikanta bitarna används (antalet bitar som är involverade beror på volymen EEPROM minne). Oanvända registerbitar EEARHär skrivskyddade och innehåller "0".

Dataregister

Dataregister EEPROM minne EEDR (EEPROM Data Register) ligger på $1D ($3D). Vid skrivning till detta register laddas data som ska placeras i EEPROM, och vid läsning läses data från EEPROM.

Kontrollregister

Kontrollregister EEPROM minne EECR (EEPROM Control Register) ligger på $1C ($3C). Detta register används för
åtkomstkontroll EEPROM minne. Dess beskrivning visas i tabellen nedan:

Ansvarsfrihet namn Beskrivning
7..4 - används inte, läs som "0"
3 KUSLIG Aktivera avbrott från EEPROM. Denna bit styr genereringen av ett avbrott som inträffar när EEPROM-skrivcykeln är avslutad. Om denna bit är satt till "1" aktiveras avbrott (om registrets I-flagga
SREG är också inställd på "1"). När EEWE-biten är rensad (se längre in
tabell) genereras avbrottet konstant
2 EEMWE Styr skrivbehörighet i EEPROM. Tillståndet för denna bit bestämmer funktionen för EEWE-skrivaktiveringsflaggan. Om denna bit är inställd på "1", så skrivs data till EEPROM när du skriver till EEWE-biten "1". Annars har inställningen av EEWE till "1" ingen effekt. Efter mjukvaruinstallation återställs EEMWE-biten av hårdvara via
4 maskincykler
1 EEWE Tillåt skrivning till EEPROM. När denna bit är inställd på "1" skrivs data till EEPROM (om EEMWE är lika med "1")
0 EERE Lästillstånd från EEPROM. Efter att ha ställt in denna bit till "1", läses data från EEPROM. Efter avslutad läsning återställs denna bit av hårdvaran

För att skriva en byte till EEPROM behöver du:

1. Vänta tills EEPROM är redo att skriva data (vänta tills EEWE-flaggan för EECR-registret återställs).

2. Vänta tills skrivningen är klar till FLASH-programminnet (vänta tills SPMEN-flaggan för SPMCR-registret återställs).

3. Ladda databyten i EEDR-registret och den önskade adressen i EEAR-registret (om nödvändigt).

4. Ställ in EEMWE-flaggan för EECR-registret till "1".

5. Skriv logg till EEWE-biten i EECR-registret. "1" för 4 maskincykler. Efter att ha installerat denna bit, processorn
hoppar över 2 maskincykler innan nästa instruktion utförs.

För att läsa en byte från EEPROM behöver du:

1. Kontrollera tillståndet för EEWE-flaggan. Faktum är att medan en skrivoperation utförs i EEPROM-minnet (EEWE-flaggan är inställd), kan varken läsning av EEPROM-minnet eller ändring av adressregistret utföras.

2. Ladda den önskade adressen i EEAR-registret.

3. Ställ in EERE-biten i EECR-registret på "1".

När den begärda datan placeras i EEDR-dataregistret kommer en hårdvaruåterställning av denna bit att ske. Det är emellertid inte nödvändigt att övervaka tillståndet för EERE-biten för att bestämma när en läsoperation är slutförd, eftersom en läsoperation från EEPROM alltid slutförs i en maskincykel. Dessutom, efter att ha ställt in EERE-biten till "1", hoppar processorn över 4 maskincykler innan nästa instruktion påbörjas.

AVR Studio GCC-miljön har ett standardbibliotek för att arbeta med EEPROM, vilket aktiveras genom att ansluta filen . Huvudfunktionerna är eeprom_read_byte(), eeprom_write_byte(), eeprom_read_word(), eeprom_write_word(). Låt oss till exempel skriva ett program för en miniräknare från 0 till 9, där när du trycker på en knapp läggs ett värde till och en annan knapp lagrar detta värde i minnet. Atmega8-mikrokontrollern fungerar från en intern klockgenerator med en frekvens på 8 MHz. En ensiffrig sjusegmentsindikator med gemensam anod ansluts till port B genom strömbegränsande motstånd R1-R7, den gemensamma anoden ansluts till strömförsörjningen plus. Diagrammet visas nedan:

Först ansluter vi de bibliotek som behövs för drift, inklusive EEPROM. Definiera variabler. Variabeln "s" lagrar värdet för visning på indikatorn, när du trycker på knappen SB1 ökar detta värde med ett, men inte mer än 10. Variabeln eeprom_var kommer att interagera med EEPROM. När strömmen slås på läses EEPROM, läsdata tilldelas variabeln "s", baserat på detta visas ett visst nummer på indikatorn. När du trycker på SB2 skrivs data från variabeln "s" till EEPROM och indikatorn blinkar en gång.

#omfatta #omfatta #omfatta #define d0 ~(0x3F) // 0 #define d1 ~(0x06) // 1 #define d2 ~(0x5B) // 2 #define d3 ~(0x4F) // 3 #define d4 ~(0x66) // 4 #define d5 ~(0x6D) // 5 #define d6 ~(0x7D) // 6 #define d7 ~(0x07) // 7 #define d8 ~(0x7F) // 8 #define d9 ~(0x6F) // 9 osignerade char s; osignerad char eeprom_var EEMEM; // definiera en variabel i EEPROM int main (void) ( DDRB = 0xFF; // Port B för att mata ut PORTB = 0xFF; DDRD = 0x00; // Port D till ingång PORTD = 0xFF; // Slå på pull-up resistorer s = eeprom_read_byte(&eeprom_var ); // läs en byte från EEPROM och lägg den i "s" while(1) ( if((PIND&(1)<< PD0)) == 0) // если кнопка SB1 нажата { while((PIND&(1 << PD0)) == 0){} // ждем отпускания кнопки s++; // увеличиваем "s" на единицу _delay_ms(200); } if(s == 10) // Когда дойдет до 10 обнуляем "s" { s = 0; } if((PIND&(1 << PD1)) == 0) // если кнопка SB2 нажата { while((PIND&(1 << PD1)) == 0){} // ждем отпускания кнопки DDRB = 0xFF; // мигаем индикатором _delay_ms(200); DDRB = 0x00; _delay_ms(200); DDRB = 0xFF; eeprom_write_byte(&eeprom_var, s); // записываем "s" в EEPROM _delay_ms(200); } if(s==0) // Выводим цифры на индикатор PORTB = d0; if(s==1) PORTB = d1; if(s==2) PORTB = d2; if(s==3) PORTB = d3; if(s==4) PORTB = d4; if(s==5) PORTB = d5; if(s==6) PORTB = d6; if(s==7) PORTB = d7; if(s==8) PORTB = d8; if(s==9) PORTB = d9; } }

Kommentarer

0 AntonChip 2013-02-05 22:15

Jag citerar Max:

Jag kanske blandar ihop något, men om du har en indikator med OA så räcker det med ett motstånd på 5V-linjen Varför installera strömbegränsande motstånd efter elementet som de ska skydda mot hög ström??


Föreställ dig bara vad som kommer att hända om ett segment av indikatorn stängs med detta och ett annat motståndsanslutningsschema.

0 AntonChip 2013-05-15 11:16

Jag citerar gydok:

Hur skriver man en tvådimensionell array till eeprom?


Koda:
#omfatta // Inkludera biblioteket

EEMEM osignerade char colors=((1, 2, 3), // Deklarera en array i EEPROM
{4, 5, 6}};

eeprom_write_byte(&färger, 1); // Skriv matriselement till EEPROM
eeprom_write_byte(&färger, 2);
eeprom_write_byte(&färger, 3);
eeprom_write_byte(&färger, 4);
eeprom_write_byte(&färger, 5);
eeprom_write_byte(&färger, 6);

osignerad char temp;
temp = eeprom_read_byte(&färger); // Extrahera arrayelement från EEPROM, 2nd row(), 1st column(), dvs. nummer 4

Återställning av EEPROM-minnet

Exemplet går igenom alla minnesceller och skriver nollor till dem.

// Ansluter biblioteket för att arbeta med EEPROM. #include "EEPROM.h" void setup() ( // Gå igenom alla celler (byte) och skriv nollor till dem. för (int i = 0; i< EEPROM.length(); i++) EEPROM.update(i, 0); } void loop() { // Пустой цикл... }


Fabriksåterställning

Om du vill återställa minnet till fabriksinställningarna behöver du byta ut 0 med 255, d.v.s. skriv inte nollor, utan siffran 255. Sålunda, med hjälp av isNaN()-funktionen, är det möjligt att kontrollera om skrivningen till EEPROM-minnet gjordes eller inte.

// Ansluter biblioteket för att arbeta med EEPROM. #include "EEPROM.h" void setup() ( // Gå igenom alla celler (byte) och skriv nummer 255 i dem. för (int i = 0; i< EEPROM.length(); i++) EEPROM.update(i, 255); } void loop() { // Пустой цикл... }

Berätta om oss

Meddelande

Om du har erfarenhet av att arbeta med Arduino och faktiskt har tid för kreativitet, inbjuder vi alla att bli författare till artiklar publicerade på vår portal. Dessa kan vara antingen lektioner eller berättelser om dina experiment med Arduino. Beskrivning av olika sensorer och moduler. Tips och instruktioner för nybörjare. Skriv och publicera dina artiklar på