Hva er en minnebrikke og hvordan programmerer du mikrokretser. Slik sletter du EEPROM (Ikke-flyktig minne) Bruke eeprom-minne

Sist gang, da jeg skrev mitt "detaljerte svar på spørsmålet" om hvordan jeg skulle sikkerhetskopiere fastvaren fra Mega, bebreidet de meg for ikke å nevne EEPROM-sikkerhetskopien. Den gangen gjorde jeg det ikke bevisst, fordi... Jeg bedømte med rette at det ikke er nødvendig å komplisere alt på stadiet av den første "tilnærmingen til prosjektilet." Faktum er at det ikke er åpenbart for alle at EEPROM ikke blinker når man kompilerer og laster opp fastvaren fra Arduino IDE. Det vil si at dette betyr at absolutt ingenting lastes opp til EEPROM når fastvaren lastes opp fra IDE. Og manipulasjoner med EEPROM (hvis bruken er aktivert i fastvaren i det hele tatt) utføres på et helt annet nivå. Og derfor å sikkerhetskopiere bar firmware uten finjusteringer, som MULIG (bare kanskje) kan lagres i EEPROM, var det nok til å lagre bare den bare firmware. Men siden spørsmålet har oppstått, hvorfor ikke "tygge" det. La oss gå gjennom det i rekkefølge. Hva er EEPROM og hvorfor snakke om det?
EEPROM - (Electrically Erasable Programmable Read-Only Memory) område av det ikke-flyktige minnet til mikrokontrolleren der informasjon kan skrives og leses. Den brukes ofte til å lagre programinnstillinger som kan endres under drift og som må lagres når strømmen slås av.

Hvordan bruker en 3D-skriver EEPROM?
La oss se på Marlin som et eksempel I Marlin Firmware ut av esken brukes ikke EEPROM Konfiguratorparametrene (Configuration.h), som inkluderer muligheten til å bruke den, kommenteres som standard.

#define EEPROM_SETTINGS
#define EEPROM_CHITCHAT

Hvis bruk av EEPROM er aktivert, kan skriveren lagre og bruke følgende innstillinger (spesifisert fra borgerskapet):

  • Antall skritt per millimeter
  • Maksimal/minimum matehastighet [mm/s]
  • Maksimal akselerasjon [mm/s^2]
  • Akselerasjon
  • Akselerasjon under tilbaketrekking
  • PID-innstillinger
  • Utgangsposisjon offset
  • Minimum matehastighet under bevegelse [mm/s]
  • Minimum seksjonstid [ms]
  • Maksimal hastighet hopp X-Y akser[mm/s]
  • Maksimal hastighetshopp i Z-aksen [mm/s]
Du kan redigere disse innstillingene ved å bruke skriverskjermen og kontrollene. Når bruk av EEPROM er aktivert, skal menyen vise følgende elementer:
  • Lagre minne
  • Last inn minne
  • Gjenopprett feilsikker
Du kan også bruke GCode til å jobbe direkte (via Proninterface).
  • M500 Lagrer gjeldende innstillinger i EEPROM til neste oppstart eller kommando M501.
  • M501 Leser innstillinger fra EEPROM.
  • M502 Tilbakestiller innstillingene til standardverdiene spesifisert i Configurations.h. Hvis du kjører M500 etter den, vil standardverdiene legges inn i EEPROM.
  • M503 Viser gjeldende innstillinger - ""De som er tatt opp i EEPROM.""
Du kan lese om EEPROM i Repitier-firmware.

Hvordan lese og skrive data til EEPROM?
Ligner på metoden beskrevet i fasved å bruke nøkkelen -U. Bare i dette tilfellet, etter det, vil det være en peker som indikerer at EEPROM må leses.

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

Denne kommandoen leser EEPROM-dataene inn i filen "printer_eeprom.eep".Hvis vellykket, vil du se noe sånt som følgende på skjermen.

Opptak er heller ikke komplisert og utføres av en lignende kommando, som bare skiller seg ut i nøkkelen -U Det er ikke "r", men "w".

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

Hvis det lykkes, vil du se noe sånt som følgende melding på skjermen.

Hvordan og hvorfor slette EEPROM?
Til å begynne med, "hvorfor gjøre dette?" Du må slette EEPROM hvis den forrige fastvaren også brukte den, og det kan være søppel igjen i minnet. Et sted har jeg allerede støtt på folk med problemer som etter å ha byttet fra en firmware til en annen (fra Marlin til Repitier EMNIP), begynte skriveren deres å oppføre seg så å si "kreativt". Dette skyldes det faktum at forskjellig firmware lagrer dataene deres under forskjellige adresser. Og når du prøver å lese data fra feil adresse, begynner pandemonium.
Du kan slette EEPROM bare programmatisk fra fastvaren, men for å gjøre dette må du midlertidig laste opp en spesiell skisse til kontrolleren. Du kan lese mer om dette i den offisielle Arduino-dokumentasjonen.
Hvis EEPROM er slettet ikke i Arduino-brett, og i noen abstrakte kontroller, må skissekoden endres under hensyntagen til størrelsen på EEPROM i en spesifikk kontroller på brettet. For å gjøre dette, må du endre sluttbetingelsen i "For"-løkken. For eksempel, for ATmega328, som har 1kb EEPROM-minne, vil syklusen se slik ut:
Konklusjon.
Jeg har ruslet en stund, men hva er alt dette for noe? For å konkludere med at når du sikkerhetskopierer fastvaren, kan EEPROM også lagres, men bare hvis du trenger innstillingene som er lagret i den. Hvis du er klar til å ofre dem, så glem det. Hvis du endrer en fastvare til en annen, eller bytter fra en versjon til en annen, må du ikke være lat med å tømme EEPROM før du laster opp ny fastvare. Vel, samtidig lærte vi mye nytt.

Ovnskontrolleren vår er nesten klar - men foreløpig er den fortsatt en "gullfisk"-kontroller som husker alle innstillinger bare fem minutter før den første strømmen slås av. For å huske innstillingene våre, verdien av den innstilte temperaturen og kalibreringspunktene selv etter at du har slått av strømmen, må du bruke ikke-flyktig minne - EEPROM.
Våre venner har skrevet veldig bra om å jobbe med EEPROM.

Det viktigste vi trenger å vite er det EEPROM-minne Det er bedre å betrakte det ikke som "bare minne", men som en separat intern enhet i brikken.
EEPROM separat adresseområde, som ikke har noe å gjøre med prosessorens adresserom (FLASH og SRAM); for å få tilgang til data på en bestemt adresse i ikke-flyktig minne, må du utføre en viss rekkefølge handlinger ved hjelp av en rekke registre (adresseregistre EEARH og EEARL, dataregister EEDR og kontrollregister EECR).
I følge dataarket, for å skrive en byte til en bestemt adresse i EEPROM, må du gjøre følgende:

  1. vente på at EEPROM er klar til å skrive data (EEPE-biten til EECR-registeret er tilbakestilt);
  2. vent til slutten av skrivingen til FLASH-minnet (tilbakestilling av SELFPRGEN-biten til SPMCSR-registeret) - dette må gjøres hvis bootloaderen er til stede i programmet;
  3. skrive ned ny adresse til EEAR-registeret (om nødvendig);
  4. skrive en databyte til EEDR-registeret (om nødvendig);
  5. sett EEMPE-biten til EECR-registeret til én;
  6. innen fire klokkesykluser etter innstilling av EEMPE-flagget, skriver vi en logisk en til EEPE-biten i EECR-registeret.

Prosessoren hopper deretter over 2 klokkesykluser før den utfører neste instruksjon.
Det andre punktet må utføres hvis det er en bootloader i programmet - faktum er at skriving til EEPROM ikke kan utføres samtidig med skriving til FLASH-minne, så før du skriver til EEPROM må du sørge for at programmering av FLASH-minne er fullført; hvis mikrokontrolleren ikke har en bootloader, endrer den aldri innholdet i FLASH-minnet (husk at avr har en Harvard-arkitektur: programminne (FLASH) og dataminne (SRAM) er atskilt).
Varigheten av opptakssyklusen avhenger av frekvensen til den interne RC-oscillatoren til brikken, forsyningsspenning og temperatur; vanligvis for ATmega48x/88x/168x-modeller er dette 3,4 ms (!), for noen eldre modeller - 8,5 ms (!!!).
I tillegg, når du skriver til EEPROM, kan det oppstå problemer med anropsavbrudd under utførelsen av handlingssekvensen ovenfor - så det er bedre å deaktivere avbrudd mens du skriver til EEPROM.
Å lese ikke-flyktig minne er litt enklere:

  1. vente på at EEPROM er klar til å lese data (EEWE-biten til EECR-registeret er tilbakestilt);
  2. skriv adressen til EEAR-registeret;
  3. sett EERE-biten til EECR-registeret til én;
  4. vi leser data fra EEDR-registeret (faktisk, når de forespurte dataene flyttes til dataregisteret, skjer det hard tilbakestilling bit EERE; men det er ikke nødvendig å overvåke tilstanden til denne biten, siden leseoperasjonen fra EEPROM alltid utføres i en klokkesyklus).

Etter å ha satt en bit i EERE til én, hopper prosessoren over 4 klokkesykluser før den utfører neste instruksjon.
Som vi ser, jobber med ikke-flyktig minne– prosessen er tidkrevende; hvis vi ofte skriver og leser data fra EEPROM, kan programmet begynne å avta.

Vi skriver imidlertid et program i IAR-miljøet, og vi er heldige: alt arbeidet med lesing og skriving fra EEPROM vil bli gjort av utviklingsmiljøet - iar har "__eeprom"-modifikatoren, som lager variabler i ikke-flyktig minne - og da trenger vi bare å lese fra "permanente" variabler til "aktuelle" (når vi initialiserer kontrolleren), eller skrive fra "gjeldende" variabler til "konstante" - det vil si når gjeldende verdi endres, verdien av variabel i ikke-flyktig minne må også endres.
De nye variablene vil se slik ut:

Eeprom uint16_t EEP_MinTemperature;

Et par mer generelle ord: og selv om vi ikke antar pekere til eeprom-variabler, må vi huske at eeprom er et eget adresserom, og for å lage en peker til eeprom (og kompilatoren lar oss gjøre dette), må indikere at dette er en peker til en adresse i eeprom:

Uint16_t __eeprom *EEP_MinTemperatureAdr;

La oss gå tilbake til komfyrkontrolleren og EEPROM. I vårt tilfelle er det ingen EEPROM virtuell maskin, selvfølgelig, er ikke forventet; Dessuten er det verdt å vurdere om et eget bibliotek er nødvendig for å jobbe med ikke-flyktig minne - de er for "spredt" over opptaksprogrammet viktige innstillinger; hvis du prøver å lage et eget bibliotek, må du lage kryssreferanser: i biblioteket for EEPROM, koble til bibliotekene til ADC, varmeelement og globale innstillinger; og i disse perifere bibliotekene er det ikke en veldig god tilnærming å koble til EEPROM-biblioteket.
Et annet alternativ er å legge til en eeprom-variabel til hvert bibliotek der du må lagre innstillinger, og lagre de tilsvarende innstillingene direkte i virtuelle maskiner. Vi vil implementere dette alternativet.
Først, la oss liste hvilke variabler vi trenger å lagre i EEPROM:

  1. kalibreringspunkter
  2. verdier for maksimum-minimum innstilt temperatur og temperaturinnstillingstrinn
  3. innstilt temperaturverdi
  4. PID-kontroller koeffisienter

Vi lagrer ikke verdien av kjøkkentimeren - vi vil anta at brukeren må stille inn komfyrtimeren hver gang etter at strømmen er slått av.
Alle disse innstillingene stilles inn av brukeren ved å vri på koderen og deretter et kort trykk på brukerknappen. Samtidig husker vi at antallet EEPROM-lese-skrivesykluser fortsatt er begrenset, så ikke overskriv den samme informasjonen igjen (for eksempel hvis brukeren valgte samme verdi av en innstilling som den var). Derfor, før hver endring av __eeprom-variabelen, sjekker vi om den må skrives om:

//hvis verdien har endret seg, overskriv den i ikke-flyktig minne hvis (ADCTemperature.atMinTemperatureValue != (uint16_t)VMEncoderCounter.ecntValue) ( ​​atureV alue; )

Å lese innstillinger fra EEPROM er også enkelt - når vi initialiserer de "gjeldende" innstillingene, leser vi bare verdien fra ikke-flyktig minne:

ADCTemperature.atMinTemperatureValue = EEP_MinTemperature;

For at enheten vår skal ha noen innstillinger i EEPROM helt fra begynnelsen, kan prosjektet for første oppstart kompileres med disse variablene initialisert:

Eeprom uint16_t EEP_MinTemperature = 20; ... //array for lagring av kalibreringspunkter i ikke-flyktig minne __eeprom TCalibrationData EEP_CalibrationData = ((20, 1300), (300, 4092));

I dette tilfellet initialiserer kompilatoren __eeprom-variabler før du starter arbeidet med hovedfunksjonen. For å få en fil med ikke-flyktig minne (.eep), må du gå inn i følgende innstillinger:
Prosjekt->Alternativer..->Linker->Ekstra alternativer
Hvis avmerkingsboksen "Bruk kommandolinjealternativer" ikke er merket, merker du av for den og legger til linjen
-Ointel-standard,(XDATA)=.eep
Først kompilerer vi prosjektet med initialiserte variabler, lagre eep-filen separat; så fjerner vi initialisering når vi lager variabler.

Det er alt - komfyren vår er klar!

Arduino er en hel familie ulike enheter for å lage elektroniske prosjekter. Mikrokontrollere er veldig praktiske å bruke og er enkle å lære selv for en nybegynner. Hver mikrokontroller består av et kort, programmer for drift og minne. Denne artikkelen vil se på det ikke-flyktige minnet som brukes i Arduino.

Beskrivelse av EEPROM-minne

Arduino gir sine brukere tre typer innebygd enhetsminne: stasjonær RAM (Random Access Memory eller SRAM – statisk Random Access Memory) – nødvendig for opptak og lagring av data under bruk; flash-kort - for å lagre allerede registrerte mønstre; – for lagring og etterfølgende bruk av data.

Alle data på RAM slettes så snart enheten startes på nytt eller strømmen slås av. De to andre lagrer all informasjon før du overskriver og lar deg hente den om nødvendig. Flash-stasjoner er ganske vanlig i dag. Det er verdt å vurdere EEPROM-minne mer detaljert.

Forkortelsen står for Electrically Erasable Programmable Read-Only Memory og oversatt til russisk betyr bokstavelig talt elektrisk slettbart programmerbart skrivebeskyttet minne. Produsenten garanterer informasjonssikkerheten i flere tiår etter siste strømbrudd (vanligvis er det gitt en periode på 20 år, avhengig av hastigheten som enhetens ladning reduseres med).

Du må imidlertid vite at muligheten til å omskrive til en enhet er begrenset og ikke er mer enn 100 000 ganger. Derfor anbefales det å være forsiktig og oppmerksom på dataene som legges inn og ikke overskrive dem igjen.

Minnemengden, sammenlignet med moderne medier, er svært liten og varierer for ulike mikrokontrollere. For eksempel for:

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

Den er designet på denne måten fordi hver mikrokontroller er designet for et spesifikt volum av oppgaver, har et annet antall pinner for tilkobling, og følgelig kreves det en annen mengde minne. Dessuten er dette beløpet tilstrekkelig for vanlige prosjekter.

Å skrive til EEPROM krever betydelig tid – ca. 3 ms. Hvis strømmen slås av under opptak, vil dataene ikke bli lagret i det hele tatt eller kan bli tatt opp feil. Det er alltid nødvendig å i tillegg kontrollere den angitte informasjonen for å unngå feil under drift. Lesing av data er mye raskere, og minneressursen reduseres ikke.

Bibliotek

Arbeid med EEPROM-minne utføres ved hjelp av et bibliotek som er laget spesielt for Arduino. De viktigste er evnen til å skrive og lese data. aktivert med kommando #inkluder EEPROM.h.

  • Til poster– EEPROM.write(adresse, data);
  • Til lesning– EEPROM.read(adresse).

I disse skissene: adresse – et argument med dataene til cellen der dataene til de andre argumentdataene er lagt inn; ved lesing brukes ett argument, adresse, som indikerer hvor informasjonen skal leses fra.

Funksjon Hensikt
les (adresse) leser 1 byte fra EEPROM; adresse – adresse som data leses fra (celle som starter fra 0);
skriv(adresse, verdi) skriver verdi (1 byte, tall fra 0 til 255) til minnet på adressen;
oppdatering (adresse, verdi) erstatter verdien på adressen hvis det gamle innholdet er forskjellig fra det nye;
få (adresse, data) leser data av den angitte typen fra minnet på adressen;
put(adresse, data) skriver data av den angitte typen inn i minnet på adressen;
EEPROM lar deg bruke "EEPROM"-identifikatoren som en matrise for å skrive data til og lese fra minnet.

Skrive heltall

Å skrive heltall til ikke-flyktig EEPROM-minne er ganske enkelt. Inntasting av tall skjer når funksjonen startes EEPROM.write(). Nødvendige data er angitt i parentes. I dette tilfellet skrives tall fra 0 til 255 og tall over 255 annerledes. De første legges enkelt inn - volumet deres tar 1 byte, det vil si en celle. For å skrive sistnevnte må du bruke operatørene highByte() for høyeste byte og lowByte() for laveste byte.

Tallet er delt inn i byte og skrevet separat i celler. For eksempel vil tallet 789 bli skrevet i to celler: den første vil inneholde faktoren 3, og den andre vil inneholde den manglende verdien. Resultatet er den nødvendige verdien:

3 * 256 + 21 = 789

Til « reunion" stort heltall gjelder ord funksjon(): int val = ord(hei, lav). Du må lese at maksimalt heltall for opptak er 65536 (det vil si 2 i potens av 16). I celler som ennå ikke har hatt andre oppføringer, vil monitoren vise tallene 255 i hver.

Skrive flyttall og strenger

Flytepunkt- og strengtall er en form for å skrive reelle tall der de er representert med en mantisse og en eksponent. Slike tall skrives til ikke-flyktig EEPROM-minne ved å aktivere funksjonen EEPROM.put(), lesing, henholdsvis – EEPROM.get().

Ved programmering er numeriske flyttallverdier utpekt som flytende; det er verdt å merke seg at dette ikke er en kommando, men et tall. Char type (tegntype) – brukes til å representere strenger. Prosessen med å skrive tall på skjermen startes ved hjelp av setup(), lesing - ved hjelp av loop().

Under prosessen kan verdiene ovf, som betyr "overfylt", og nan, som betyr "mangler", vises på skjermen numerisk verdi" Dette betyr at informasjonen som skrives til cellen ikke kan reproduseres som et flyttall. Denne situasjonen vil ikke oppstå hvis du vet pålitelig i hvilken celle hvilken type informasjon som er registrert.

Eksempler på prosjekter og skisser

Eksempel nr. 1

Skissen vil skrive opptil 16 tegn fra serieporten og sende ut 16 tegn fra EEPROM i en sløyfe. Takket være dette skrives data til EEPROM og innholdet i ikke-flyktig minne overvåkes.

// sjekk driften av EEPROM #include int i, d; void setup() ( Serial.begin(9600); // initialiser porten, hastighet 9600 ) void loop() ( // les EEPROM og send ut 16 data til serieporten Serial.println(); Serial.print("EEPROM = " ); i= 0; mens(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); }

Eksempel nr. 2

For en bedre forståelse kan vi lage en liten skisse som vil hjelpe til med å forstå hvordan man arbeider med ikke-flyktig minne. Vi teller alle cellene i dette minnet. Hvis cellen ikke er tom - utgang til serieporten. Fyll deretter cellene med mellomrom. Deretter legger vi inn teksten gjennom serieportmonitoren. Vi skriver den til EEPROM, og leser den neste gang den slås på.

#inkludere int adresse = 0; // eeprom-adresse int read_value = 0; // data lest fra eeprom char serial_in_data; // seriell port data int led = 6; // linje 6 for LED int i; void setup() ( pinMode(led, OUTPUT); // linje 6 er konfigurert som utgang Serial.begin(9600); // overføringshastighet på seriell port 9600 Serial.println(); Serial.println("PREVIOUS TEXT IN EEPROM : -"); for(adresse = 0; adresse< 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); }

Eksempel nr. 3

Skriver to heltall til minnet, leser dem fra EEPROM og sender dem ut til serieporten. Tall fra 0 til 255 opptar 1 byte med minne ved å bruke funksjonen EEPROM.write() skrives til ønsket celle. For tall større enn 255 må de deles inn i byte ved hjelp av highByte() Og lowByte() og skriv hver byte inn i sin egen celle. Maksimalt antall i dette tilfellet er 65536 (eller 2 16).

#inkludere // koble til EEPROM-biblioteket void setup() ( int smallNum = 123; // heltall fra 0 til 255 EEPROM.write(0, smallNum); // skriv et tall til celle 0 int bigNum = 789; // del tallet > 255 x 2 byte (maks. 65536) byte hi = highByte(bigNum); // high byte byte low = lowByte(bigNum); // low byte EEPROM.write(1, hi); // skriv høy byte av EEPROM til celle 1 .write(2, low); // skriv den lave byten til celle 2 Serial.begin(9600); // initialiser serieporten ) void loop() ( for (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 мин }

Eksempel nr. 4

Skrive flyttall og strenger - metode EEPROM.put(). Lesing – EEPROM.get().

#inkludere // koble til biblioteket void setup() ( int addr = 0; // address float f = 3.1415926f; // flyttallnummer (flytetype) EEPROM.put(addr, f); // skriv tallet f til adressen addr addr += sizeof(float); // beregn neste ledige minnecelle tegnnavn = "Hei, SolTau.ru!"; // lag en rekke tegn EEPROM.put(addr, navn); // skriv matrisen til EEPROM Serial.begin (9600); // initialiserer serieporten ) void loop() ( for (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 минуту }

Eksempel nr. 5

Bruker EEPROM som en matrise.

#inkludere void setup() ( EEPROM = 11; // skriv den 1. cellen EEPROM = 121; // skriv den andre cellen EEPROM = 141; // skriv den 3. cellen EEPROM = 236; // skriv den 4. cellen Serial .begin(9600 ); ) void loop() ( for (int addr=0; addr<1024; addr++) { Serial.print(addr); Serial.print("\t"); int n = EEPROM; // считываем ячейку по адресу addr Serial.println(n); // выводим в порт } delay(60000); }

Jobber med EEPROM

Som nevnt tidligere er EEPROM-minnet begrenset. For å forlenge levetiden til ikke-flyktig minne, i stedet for skrive()-funksjonen, er det bedre å bruke oppdateringsfunksjonen. I dette tilfellet utføres omskrivning bare for de cellene der verdien er forskjellig fra den nyskrevne.

En annen nyttig funksjon til det aktuelle mikrokontrollerminnet er muligheten til å bruke bytelagringsceller som deler av en integrert EEPROM-matrise. I ethvert bruksformat er det nødvendig å kontinuerlig overvåke integriteten til de registrerte dataene.

Slikt minne på Arduino lagrer standard de viktigste tingene for driften av kontrolleren og enheten. For eksempel, hvis en temperaturkontroller er opprettet på et slikt grunnlag og de første dataene viser seg å være feil, vil enheten fungere "utilstrekkelig" til de eksisterende forholdene - den vil undervurdere eller overvurdere temperaturen kraftig.

Det er flere situasjoner der EEPROM inneholder feil data:

  1. Ved første aktivering var det ingen oppføringer ennå.
  2. Under et ukontrollert strømbrudd vil noen eller alle dataene ikke bli registrert eller vil bli registrert feil.
  3. Etter fullføring av mulige dataomskrivingssykluser.

For å unngå ubehagelige konsekvenser, kan enheten programmeres for flere handlingsalternativer: bruk nødkodedata, slå av systemet helt, signaliserer en feil, bruk en tidligere opprettet kopi eller andre.

For å kontrollere integriteten til informasjon brukes en systemkontrollkode. Den er opprettet basert på den opprinnelige dataregistreringen, og når den er bekreftet, beregner den dataene på nytt. Hvis resultatet er annerledes, er det en feil. Den vanligste versjonen av en slik sjekk er en sjekksum - en enkel matematisk operasjon utføres for å legge til alle celleverdier.

Erfarne programmerere legger til en ekstra "eksklusiv ELLER" til denne koden, for eksempel E5h. Hvis alle verdier er lik null, og systemet feilaktig tilbakestiller de opprinnelige dataene, vil dette trikset avsløre feilen.

Dette er de grunnleggende prinsippene for å jobbe med ikke-flyktig EEPROM-minne for Arduino-mikrokontrollere. For visse prosjekter er det verdt å kun bruke denne typen minne. Det har både sine fordeler og ulemper. For å mestre skrive- og lesemetoder er det bedre å begynne med enkle oppgaver.

Alle mikrokontrollere i Mega-familien inkluderer ikke-flyktig minne ( EEPROM hukommelse). Volumet på dette minnet varierer fra 512 byte i ATmega8x-modeller til 4 KB i eldre modeller. EEPROM minne er plassert i sitt eget adresserom og er, som RAM, organisert lineært. Å jobbe med EEPROM Minnet bruker tre I/O-registre: et adresseregister, et dataregister og et kontrollregister.

Adresseregister

Adresseregister EEPROM hukommelse EEAR (EEPROM-adresseregister) fysisk plassert i to RVV EEARH:EEARL, plassert langs
adresser henholdsvis $1F ($3F) og $1E ($3E). Dette registeret er lastet med adressen til cellen som skal åpnes. Adresseregisteret er både skrivbart og lesbart. Samtidig i registeret EEARH bare de minst signifikante bitene brukes (antallet involverte biter avhenger av volumet EEPROM hukommelse). Ubrukte registerbiter EEARH er skrivebeskyttet og inneholder "0".

Dataregister

Dataregister EEPROM hukommelse EEDR (EEPROM Data Register) ligger på $1D ($3D). Ved skriving til dette registeret lastes data som skal legges inn EEPROM, og ved lesing leses dataene fra EEPROM.

Kontrollregister

Kontrollregister EEPROM hukommelse EECR (EEPROM Control Register) ligger på $1C ($3C). Dette registeret brukes til
adgangskontroll EEPROM hukommelse. Beskrivelsen er vist i tabellen nedenfor:

Utflod Navn Beskrivelse
7..4 - ikke brukt, les som "0"
3 UHYGGELIG Aktiver avbrudd fra EEPROM. Denne biten styrer genereringen av et avbrudd som oppstår når EEPROM-skrivesyklusen er fullført. Hvis denne biten er satt til "1", blir avbrudd aktivert (hvis I-flagget til registeret
SREG er også satt til "1"). Når EEWE-biten er slettet (se lenger inn
tabell) genereres avbruddet konstant
2 EEMWE Kontrollerer skrivetillatelse i EEPROM. Tilstanden til denne biten bestemmer operasjonen til EEWE skriveaktiveringsflagget. Hvis denne biten er satt til "1", blir data skrevet til EEPROM når du skriver til EEWE-biten "1". Ellers har det ingen effekt å sette EEWE til "1". Etter programvareinstallasjon tilbakestilles EEMWE-biten av maskinvare via
4 maskinsykluser
1 EEEE Tillat skriving til EEPROM. Når denne biten er satt til "1", skrives data til EEPROM (hvis EEMWE er lik "1")
0 EERE Les tillatelse fra EEPROM. Etter at denne biten er satt til "1", leses data fra EEPROM. Når lesingen er fullført, tilbakestilles denne biten av maskinvaren

For å skrive én byte til EEPROM trenger du:

1. Vent til EEPROM er klar til å skrive data (vent til EEWE-flagget til EECR-registeret er tilbakestilt).

2. Vent til skrivingen til FLASH-programminnet er fullført (vent til SPMEN-flagget til SPMCR-registeret er tilbakestilt).

3. Last inn databyten i EEDR-registeret og den nødvendige adressen i EEAR-registeret (om nødvendig).

4. Sett EEMWE-flagget til EECR-registeret til "1".

5. Skriv logg til EEWE-biten til EECR-registeret. "1" for 4 maskinsykluser. Etter å ha installert denne biten, prosessoren
hopper over 2 maskinsykluser før neste instruksjon utføres.

For å lese én byte fra EEPROM trenger du:

1. Sjekk tilstanden til EEWE-flagget. Faktum er at mens en skriveoperasjon utføres i EEPROM-minnet (EEWE-flagget er satt), kan verken lesing av EEPROM-minne eller endring av adresseregisteret utføres.

2. Last inn den nødvendige adressen i EEAR-registeret.

3. Sett EERE-biten til EECR-registeret til “1”.

Når de forespurte dataene plasseres i EEDR-dataregisteret, vil en tilbakestilling av denne biten skje. Det er imidlertid ikke nødvendig å overvåke tilstanden til EERE-biten for å bestemme når en leseoperasjon er fullført, siden en leseoperasjon fra EEPROM alltid fullføres i én maskinsyklus. I tillegg, etter å ha satt EERE-biten til "1", hopper prosessoren over 4 maskinsykluser før den starter neste instruksjon.

AVR Studio GCC-miljøet har et standardbibliotek for arbeid med EEPROM, som aktiveres ved å koble til filen . Hovedfunksjonene er eeprom_read_byte(), eeprom_write_byte(), eeprom_read_word(), eeprom_write_word(). La oss for eksempel skrive et program for en miniteller fra 0 til 9, hvor når du trykker på en knapp, vil en verdi legges til, og en annen knapp vil lagre denne verdien i minnet. Atmega8-mikrokontrolleren opererer fra en intern klokkegenerator med en frekvens på 8 MHz. En ensifret syv-segment indikator med en felles anode er koblet til port B gjennom strømbegrensende motstander R1-R7, felles anode er koblet til strømforsyningen pluss. Diagrammet er vist nedenfor:

Først kobler vi til bibliotekene som er nødvendige for drift, inkludert EEPROM. Definer variabler. Variabelen "s" lagrer verdien for visning på indikatoren, når du trykker på SB1-knappen, øker denne verdien med én, men ikke mer enn 10. eeprom_var-variabelen vil samhandle med EEPROM. Når strømmen er slått på, leses EEPROM, lesedata tildeles variabelen "s", basert på dette vises et visst tall på indikatoren. Når du trykker på SB2, skrives data fra variabelen "s" til EEPROM, og indikatoren blinker én gang.

#inkludere #inkludere #inkludere #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 usignerte char s; usignert char eeprom_var EEMEM; // definer en variabel i EEPROM int main (void) ( DDRB = 0xFF; // Port B til utgang PORTB = 0xFF; DDRD = 0x00; // Port D til inngang PORTD = 0xFF; // Slå på pull-up motstander s = eeprom_read_byte(&eeprom_var ); // les en byte fra EEPROM og legg den inn 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 05/02/2013 22:15

Jeg siterer Max:

Kanskje jeg forvirrer noe, men hvis du har en indikator med OA, så er det nok med en motstand på 5V-linjen Hvorfor installere strømbegrensende motstander etter elementet som de skal beskytte mot høy strøm??


Bare forestill deg hva som vil skje hvis ett segment av indikatoren lukkes med dette og et annet motstandstilkoblingsskjema.

0 AntonChip 15.05.2013 11:16

Jeg siterer gydok:

Hvordan skrive en todimensjonal matrise til eeprom?


Kode:
#inkludere // Inkluder biblioteket

EEMEM usignerte tegnfarger=((1, 2, 3), // Deklarer en matrise i EEPROM
{4, 5, 6}};

eeprom_write_byte(&farger, 1); // Skriv matriseelementer til EEPROM
eeprom_write_byte(&farger, 2);
eeprom_write_byte(&farger, 3);
eeprom_write_byte(&farger, 4);
eeprom_write_byte(&farger, 5);
eeprom_write_byte(&farger, 6);

usignert char temp;
temp = eeprom_read_byte(&farger); // Trekk ut array-element fra EEPROM, 2nd row(), 1st column(), dvs. nummer 4

Tilbakestiller EEPROM-minnet

Eksemplet går gjennom alle minneceller og skriver nuller til dem.

// Koble til biblioteket for å jobbe med EEPROM. #include "EEPROM.h" void setup() ( // Gå gjennom alle cellene (bytes) og skriv nuller til dem. for (int i = 0; i< EEPROM.length(); i++) EEPROM.update(i, 0); } void loop() { // Пустой цикл... }


Fabrikkinnstilt

Hvis du ønsker å sette minnet tilbake til fabrikkinnstillinger, må du erstatte 0 med 255, dvs. skriv ikke nuller, men tallet 255. Ved bruk av isNaN()-funksjonen er det derfor mulig å sjekke om skrivingen til EEPROM-minnet ble gjort eller ikke.

// Koble til biblioteket for å jobbe med EEPROM. #include "EEPROM.h" void setup() ( // Gå gjennom alle cellene (bytes) og skriv tallene 255 i dem. for (int i = 0; i< EEPROM.length(); i++) EEPROM.update(i, 255); } void loop() { // Пустой цикл... }

Fortell oss om oss

Beskjed

Hvis du har erfaring med å jobbe med Arduino og faktisk har tid til kreativitet, inviterer vi alle til å bli forfattere av artikler publisert på portalen vår. Dette kan enten være leksjoner eller historier om eksperimentene dine med Arduino. Beskrivelse av ulike sensorer og moduler. Tips og instruksjoner for nybegynnere. Skriv og legg ut artiklene dine på