piątek, 25 marca 2016

Pamiętaj!

Problem

Prędzej czy później w naszej przygodzie z programowaniem mikrokontrolerów dostrzeżemy pewien mankament - stan mikrokontrolera jest utrzymywany tylko wtedy, gdy dostępne jest zasilanie. Dość niefortunna przypadłość - zwłaszcza wtedy, gdy bardzo nam zależy, by jednak pewien stan się zachowywał, mimo braku prądu. Co to może być? Na przykład podana przez nas godzina, o której załączać ma się światło albo piec w naszym "trochę mądrzejszym" domu. Załóżmy, że chcemy mieć możliwość zmiany tej godziny bez konieczności przeprogramowania całego układu, dlatego zahardkodowana wartość nie wchodzi w grę.

Analiza

Jak zatem przechowamy naszą godzinę? Przyda nam się do tego Memory - człowiek potrafi zapamiętać wiele rzeczy, dlaczego mikrokontroler nie mógłby robić czegoś podobnego? Pamięć ta powinna być "nieulotna" - tj. rzeczy przechowywane w niej nie powinny zanikać przy braku zasilania. Dodajmy do naszego Memory określenie Read-Only. W ten sposób na potrzeby zapamiętania godziny złożyliśmy sobie własny ROM. Nadal poruszamy się w świecie programowania Atmegi - przydałoby się móc zaprogramować naszą pamięć - bez kompleksów dorzucamy Programmable. Ale przecież chcieliśmy zmieniać naszą godzinę załączania pieca! Zatem raz zapisaną w pamięci, powinniśmy móc wykasować. Do kasowania użyjmy elektroniki! Electrically-Erasable powinno wystarczyć. Zbierzmy wszystko razem - co nam wyszło? EEPROM.

Eureka!

Dobra nasza! Atmega162 wyposażona jest w 512 bajtów pamięci EEPROM! Bez problemu znajdzie się tam miejsce dla naszej godziny. Mało tego, korzystanie z niej jest dziecinnie proste - wystarczy jak w przypadku omawianych wcześniej "ficzerów" skorzystać z dostępnych rejestrów. Na naszej głowie będzie również zadbanie o prawidłową adresację. Nie powinno to być trudne - adres, pod jakim w pamięci EEPROM znajdzie się nasza dana może być już przechowany w pamięci programu. Niestety - są też pewne ograniczenia - w tym przypadku oprócz rozmiaru, lmitowana jest też ilość cykli zapisów/odczytu. Atmel dla Atmegi przewidział co najmniej 100000 takich cyklów. Dużo? Mało? Matematykę zostawiam Wam.

Kodzik!

Do obsługi pamięci wykorzystamy poniższy kodzik:

Zanim przystąpimy do procedury zapisu, powinniśmy znać adres, pod jaki zapiszemy naszą daną i jej wartość. Bogatsi w tę wiedzę rozpoczynamy sekwencję zapisu. Przede wszystkim musimy zadbać, że nasz zapis nie wpłynie negatywnie na trwający zapis - musimy zaczekać, sprawdzając stan bitu EEWE w rejestrze EECR. Następnie do rejestru EEAR wpisujemy adres, a do EEDR wartość naszej danej, którą chcemy umieścić w pamięci. Potem wystarczy ustawić bit EEMWE i EEWE w rejestrze EECR i nasza dana ląduje w pamięci.

void EEPROM_write(unsigned int address, uint8_t data)
{
   while(EECR & (1<<EEWE)); // poczekaj na zakończenie poprzedniego zapisu

   EEAR = address; // ustawienie adresu bajtu do zapisu
   EEDR = data; // dane do zapisu
   EECR |= (1<<EEMWE); // master write enable
   EECR |= (1<<EEWE); // eeprom write enable
}


Żeby odczytać interesującą nas wartość z pamięci, musimy znać adres, pod jakim wcześniej została tam umieszczona. Po raz kolejny musimy się upewnić, że nie przerwiemy procedury zapisu. Następnie ustawiamy wartość rejestru EEAR - (widzicie problem? Gdybyśmy nie zaczekali na koniec zapisu, właśnie podmienilibyśmy adres, pod którym miałaby wylądować zapisywana wartość). Jeszcze tylko ustawić bit EERE w EECR  i z rejestru EEDR (kolejny współdzielony między zapisem i odczytem) możemy odczytać naszą wartosć.

uint8_t EEPROM_read(unsigned int address)
{
   while(EECR & (1<<EEWE)); // poczekaj na zakończenie poprzedniego zapisu

   EEAR = address; // ustawienie adresu bajtu do odczytu
   EECR |= (1<<EERE); // eeprom read enable
   return EEDR; // zwrócenie odczytanego bajtu
}

Brak komentarzy:

Prześlij komentarz