Obsługa pamięci szeregowych EEPROM i DataFlash w Bascom, część 1

Obsługa pamięci szeregowych EEPROM i DataFlash w Bascom, część 1
Pobierz PDF Download icon

W wielu systemach cyfrowych, które mają zbierać dane z zewnątrz, powinny być one zapisywane w pamięci nieulotnej o właściwie dobranej pojemności. Pamięci nieulotne są także wykorzystywane do zapamiętywania ustawianych parametrów systemu. W tego rodzaju zastosowaniach ich pojemność może być niewielka – zazwyczaj do 1 kB. Wiele mikrokontrolerów ma wbudowaną pamięć nieulotną, której zazwyczaj niewielka pojemność umożliwia tylko zapamiętanie konfiguracji urządzenia. W przypadku mikrokontrolerów bez wewnętrznej pamięci EEPROM można bez problemu dołączyć pamięć zewnętrzną. Do tego celu nadają się pamięci szeregowe, gdyż do ich dołączenia zazwyczaj nie jest potrzebnych wiele linii mikrokontrolera.

W przypadku małej liczby danych do zapamiętania (danych konfiguracyjnych itp.) można więc stosować pamięci nieulotne EEPROM o niewielkiej pojemności, zazwyczaj od kilkunastu bajtów do kilkudziesięciu kilobajtów. W przypadku, gdy będzie trzeba zapamiętać dużą liczbę danych, np. z pomiarów, to odpowiednie będą szeregowe pamięci DataFlash, których pojemność może wynosić do kilku megabajtów. W artykule zostanie przedstawiona obsługa pamięci EEPROM oraz DataFlash z poziomu Bascoma. Zostaną przedstawione pamięci z najpopularniejszymi interfejsami I2C oraz SPI, jak: AT24C02 (pojemność 256 bajtów), AT24C16 (pojemność 2 kB), AT24C64 (pojemność 8 kB), AT93C64 (pojemność 128 bajtów) oraz DataFlash AT45DB011 o pojemności ponad 135 kB.

Pamięci szeregowe EEPROM z rodziny AT24Cxx

Pamięci z rodziny AT24Cxx mają interfejs I2C, a więc do komunikacji z nimi wykorzystywane są tylko dwie linie mikrokontrolera.

W tab. 1 przedstawiono parametry kilku typów pamięci AT24Cxx. Pamięcią, którą można wykorzystać do zapamiętywania parametrów konfiguracyjnych, jest AT24C02 o pojemności 256 bajtów.

Rys. 1. Schemat blokowy pamięci typu AT24C02 

Schemat blokowy pamięci tego typu przedstawiono na rys. 1. Linie adresowe A2...A0 są liniami wyboru jednej z ośmiu pamięci jakie mogą być dołączone do magistrali I2C (np. dla AT24C02). Zwarcie linii WP do plusa zasilania blokuje zapis do pamięci.

Rys. 2. Schemat dołączenia pamięci EEPROM do mikrokontrolera

Na rys. 2 przedstawiono schemat podłączenia pamięci do układu uruchomieniowego z mikrokontrolerem ATMEGA8 w którym będzie testowana obsługa pamięci EEPROM. Płytka jest połączona z komputerem za pomocą łącza RS232. Dane będą przesyłane tym interfejsem i zapisywane do pamięci oraz z niej odczytywane. mikrokontrolera. Układ U2 jest konwerterem napięć do poziomów zgodnych z normą RS232. Rezystory R1, R2 są rezystorami podciągającymi dla linii sygnałowych magistrali I2C.

Listing 1.

'Program komunikujący się z pamięcia 24C02 (2k - 256*8) - pojemność 256 bajtów
'Komunikacja z pamiecia odbywa sie przy pomocy magistrali I2C
'Mikrokontroler ATMEGA8 taktowany czestotliwoscia 8MHz
'W programie do pamieci (komorki 0...255) wpisywane sa wartosci liczbowe od 0 do 255,
'nastepnie dane zapisane do pamieci sa odczytywane i weryfikowane pod wzgledem poprawnosci zapisu
'zarowno wartosci danych zapisywanych jak i odczytywanych sa wysylane do terminala poprzez interfejs RS232.
'Predkosc komunikacji przez RS232 wynosi 9600 bodow.
'W przypadku bledu zapisu do pamieci wysylany jest do terminala stosowny komunikat
'Marcin Wiązania
'marcin.wiazania@ep.com.pl

$regfile = "m8def.dat" 'informuje kompilator o pliku dyrektyw mikrokontrolera
$crystal = 8000000 'informuje kompilator o częstotliwości oscylatora taktujacego mikrokontroler
$baud = 9600 'informuje o predkosci transmisji interfejsu RS232

Const Adr_w = 160 'adres zapisu danej do pamieci EEPROM
Const Adr_r = 161 'adres odczytu danej do pamieci EEPROM

Config Sda = Portc.4 'konfiguracja linii SDA interfejsu I2C
Config Scl = Portc.3 'konfiguracja linii SCL interfejsu I2C
Config I2cdelay = 5 'konfiguracja opoznienia (czestotliwosci) linii zegarowej SCL

Declare Sub Zap_eeprom(byval Adres As Byte , Byval Dana As Byte) 'procedura zapisu danej do pamieci
Declare Sub Odc_eeprom(byval Adres As Byte , Dana As Byte) 'procedura odczytu danej z pamieci

Dim Adres As Byte 'zmienna adresu komorki pamieci
Dim Dana As Byte 'zmienna zmienna na odczytana lub zapisana dana do pamieci
Dim I As Byte 'zmienna licznikowa

Print "Zapis" 'wyslanie do terminala tekstu

For I = 0 To 255 'petla wykonywana dla I=0 do I=255
Call Zap_eeprom(i , I) 'zapis do EEPROM wartosci zmiennej I pod adres wskazywany przez I
Print Hex(i) ; " "; 'wyslanie do terminala wartosci zapisywanej do EEPROM w postaci szesnastkowej
Next I 'zwiekszenie o 1 wartosci I

Print 'wyslanie do terminala wiersza odstepu
Print "Odczyt i weryfikacja" 'wyslanie do terminala tekstu

For I = 0 To 255 'petla wykonywana dla I=0 do I=255
Call Odc_eeprom(i , Dana) 'odczytanie z EEPROM wartosc z komorki o adresie wskazywanym przez I
If Dana = I Then '--weryfikacja danych-- jesli Dana = I to
Print Hex(dana) ; " "; 'wyslanie do terminala odczytanej wartosci z pamieci w postaci szesnastkowej
Else 'w przeciwnym razie
Print "Dane nieprawidlowe" 'wyslanie do terminala tekstu
Exit For 'opuszczenie petli For
End If
Next I 'zwiekszenie o 1 wartosci I
End 'koniec programu

Sub Zap_eeprom(byval Adres As Byte , Byval Dana As Byte) 'procedura zapisu danej do EEPROM
I2cstart 'start transmisji
I2cwbyte Adr_w 'zapis adresu ukladu pamieci do zapisu
I2cwbyte Adres 'adres komorki pamieci
I2cwbyte Dana 'zapis danej
I2cstop 'koniec transmisji
Waitms 10 'opoznienie 10 ms
End Sub 'koniec procedury

Sub Odc_eeprom(byval Adres As Byte , Dana As Byte) 'procedura odczytu danej do EEPROM
I2cstart 'start transmisji
I2cwbyte Adr_w 'zapis adresu ukladu pamieci do zapisu
I2cwbyte Adres 'adres komorki pamieci
I2cstart 'ponowny start transmisji
I2cwbyte Adr_r 'zapis adresu ukladu pamieci do odczytu
I2crbyte Dana , Nack 'odczyt bajta danej - bez potwierdzenia sygnałem ACK
I2cstop 'koniec transmisji
End Sub 'koniec procedury

Na list. 1 przedstawiono przykład programu obsługującego pamięć AT24C02. Do komórek pamięci wpisywane są w programie kolejno wartości od 0 do 255. Zapis do pamięci EEPROM następuje w procedurze Zap_eeprom, która ma dwa parametry. Pierwszym jest adres a drugim wartość danej do zapisania. Po zainicjowaniu magistrali I2C sygnałem startu jest wysyłany adres wybieranej pamięci, którego format przedstawiono na rys. 3.

Rys. 3. Format słowa adresu pamięci AT24C02

Bity A2...A0 odpowiadają stanom zewnętrznych linii A2...A0 pamięci. Bit R/W wskazuje czy będzie następował odczyt z pamięci, czy zapis do pamięci. Ponieważ linie A2...A0 pamięci zostały zwarte do masy, adres zapisu do pamięci będzie wynosił 160, a odczytu z niej 161.

Rys. 4. Ramka zapisu jednej komórki pamięci

Na rys. 4 przedstawiono ramkę z sygnałami podczas zapisu jednego bajtu pamięci. Każda ramka kończy się sygnałem potwierdzenia (ACK) wysyłanym przez pamięć, po czym wysyłany jest adres bajtu (słowa) pamięci. Ponieważ pamięć ma pojemność 256 bajtów, adres jest 8–bitowy. Po otrzymaniu potwierdzenia wysyłana jest dana do zapisania w zaadresowanym bajcie (słowie). W procedurze zapisu do pamięci występuje opóźnienie (zależne od typu pamięci i producenta), które jest wymagane ze względu na czas zapisu. Do odczytu danych z pamięci służy procedura Odc_eeprom mająca także dwa parametry: adres oraz wartość odczytanej komórki.

Rys. 5. Ramka odczytu pamięci

Ramka z sygnałami przy odczycie z pamięci przedstawiono na rys. 5. W pierwszej kolejności wysyłany jest (po sekwencji startu) adres pamięci do zapisu, czyli 160, a następnie adres słowa pamięci, z którego ma nastąpić odczyt. Po kolejnej sekwencji startu wysyłany jest adres pamięci do odczytu, po którym następuje odczyt danej z zaadresowanego słowa, już bez bitu potwierdzenia. Po każdej zakończonej komunikacji z pamięcią następuje wysłanie sygnału stopu. W pętli głównej programu do każdego słowa pamięci jest zapisywana jakaś liczba, która jest także wysyłana do terminala. Po zapisaniu wszystkich bajtów, następuje odczyt oraz weryfikacja zawartości każdego z nich. Odczytane wartości z pamięci są wysłanie do terminala. W przypadku wykrycia błędu zapisu, do terminala zostanie wysłany odpowiedni komunikat.

Rys. 6. Widok okna terminala po zakończeniu działania programu demonstracyjnego

Na rys. 6 przedstawiono widok okna terminala po zakończeniu programu.
Komunikacja z pamięciami AT24Cxx o większych pojemnościach jest trochę trudniejsza. Przykładowo, pamięć AT24C16, która ma pojemność 2 kB nie ma zewnętrznych linii wyboru adresu, co oznacza, że do magistrali I2C może być dołączona tylko jedna pamięć. Bitowe odpowiedniki adresu pamięci zostały zastąpione adresami stron, z których każda ma 256 bajtów pamięci, czyli pamięć AT24C16 ma 8 stron.

Rys. 7. Format słowa adresu pamięci AT24C16

Na rys. 7 przedstawiono format słowa adresu pamięci AT24C16. Bity P2...P0 określają właśnie adres strony. Budowa tej pamięci oraz sposób jej podłączenia do mikrokontrolera jest identyczny jak przedstawiono na rys. 1 oraz rys. 2.

Listing 2.

'Program komunikujący się z pamięcia 24C16 (16k - 2048*8) - pojemność 2048 bajtów
'Komunikacja z pamiecia odbywa sie przy pomocy magistrali I2C
'Mikrokontroler ATMEGA8 taktowany z czestotliwoscia 8MHz
'Pamiec posiada 8 stron z ktorych kazda ma 256 komorek co daje pojemność 2kB (2048 komorek)
'W programie do pamieci (komorki 0...2048) wpisywane sa wartosci liczbowe numerow stron do których nastepuje zapis.
'Nastepnie dane zapisane do pamieci sa odczytywane i weryfikowane pod wzgledem poprawnosci zapisu
'Zarowno wartosci danych zapisywanych jak i odczytywanych sa wysylane do terminala poprzez interfejs RS232.
'Predkosc komunikacji przez RS232 wynosi 9600 bodow.
'W przypadku bledu zapisu do pamieci wysylany jest do terminala stosowny komunikat
'Marcin Wiązania
'marcin.wiazania@ep.com.pl

$regfile = "m8def.dat" 'informuje kompilator o pliku dyrektyw mikrokontrolera
$crystal = 8000000 'informuje kompilator o częstotliwości oscylatora taktujacego mikrokontroler
$baud = 9600 'informuje o predkosci transmisji interfejsu RS232

Const Adr_w = 160 'adres zapisu danej do pamieci EEPROM
Const Adr_r = 161 'adres odczytu danej do pamieci EEPROM

Config Sda = Portc.4 'konfiguracja linii SDA interfejsu I2C
Config Scl = Portc.3 'konfiguracja linii SCL interfejsu I2C
Config I2cdelay = 5 'konfiguracja opoznienia (czestotliwosci) linii zegarowej SCL

Declare Sub Zap_eeprom(byval Adres As Word , Byval Dana As Byte) 'procedura zapisu danej do pamieci
Declare Sub Odc_eeprom(byval Adres As Word , Dana As Byte) 'procedura odczytu danej z pamieci

Dim Adres As Word 'zmienna adresu komorki pamieci
Dim Dana As Byte 'zmienna zmienna na odczytana lub zapisana dana do pamieci
Dim I As Word 'zmienna licznikowa
Dim Temp As Byte 'zmienna pomocnicza
Dim Zm_pom As Word 'zmienna pomocnicza do przeliczenia adresu

Print "Zapis" 'wyslanie do terminala tekstu

For I = 0 To 2047 'petla wykonywana dla I=0 do I=2047
Zm_pom = I / 256 'obliczenie numeru strony pamieci
Dana = Zm_pom 'zapis numeru strony do zmiennej dana
Call Zap_eeprom(i , Dana) 'zapis do EEPROM wartosci zmiennej dana pod adres wskazywany przez I
Print Hex(dana) ; " "; 'wyslanie do terminala wartosci zapisywanej do EEPROM w postaci szesnastkowej
Next I 'zwiekszenie o 1 wartosci I

Print 'wyslanie do terminala wiersza odstepu
Print "Odczyt i weryfikacja" 'wyslanie do terminala tekstu

For I = 0 To 2047 'petla wykonywana dla I=0 do I=2047
Call Odc_eeprom(i , Dana) 'odczytanie z EEPROM wartosc z komorki o adresie wskazywanym przez I
Zm_pom = I / 256 'obliczenie odczytywanej strony pamieci
If Dana = Zm_pom Then '--weryfikacja danych-- jesli Dana = zm_pom - czyli numerowi strony to
Print Hex(dana) ; " "; 'wyslanie do terminala odczytanej wartosci z pamieci w postaci szesnastkowej
Else 'w przeciwnym razie
Print "Dane nieprawidlowe" 'wyslanie do terminala tekstu
Exit For 'opuszczenie petli For
End If
Next I 'zwiekszenie o 1 wartosci I
End 'koniec programu

Sub Zap_eeprom(byval Adres As Word , Byval Dana As Byte) 'procedura zapisu danej do EEPROM
Zm_pom = Adres / 256 'obliczenie adresu strony
Temp = Low(zm_pom) 'zapis do temp mniej znaczacego bajta zmiennej zm_pom
Adres = Adres Mod 256 'obliczenie adresu komorki pamieci
Shift Temp , Left , 1 'przesuniecie wartosci w temp o jedna pozycje w lewo (mnozenie przez 2)
Temp = Temp + Adr_w 'obliczenie adresu pamieci z uwzglednieniem stron
I2cstart 'start transmisji
I2cwbyte Temp 'zapis adresu ukladu pamieci do zapisu
I2cwbyte Adres 'adres komorki pamieci
I2cwbyte Dana 'zapis danej
I2cstop 'koniec transmisji
Waitms 7 'opoznienie 7 ms
End Sub 'koniec procedury

Sub Odc_eeprom(byval Adres As Word , Dana As Byte) 'procedura odczytu danej do EEPROM
Zm_pom = Adres / 256 'obliczenie adresu strony
Temp = Low(zm_pom) 'zapis do temp mniej znaczacego bajta zmiennej zm_pom
Adres = Adres Mod 256 'obliczenie adresu komorki pamieci
Shift Temp , Left , 1 'przesuniecie wartosci w temp o jedna pozycje w lewo (mnozenie przez 2)
Temp = Temp + Adr_w 'obliczenie adresu pamieci z uwzglednieniem stron
I2cstart 'start transmisji
I2cwbyte Temp 'zapis adresu ukladu pamieci do zapisu
I2cwbyte Adres 'adres komorki pamieci
I2cstart 'ponowny start transmisji
Incr Temp 'zwiekszenie temp o jeden - uzyskanie adresu do odczytu danej z pamieci
I2cwbyte Temp 'zapis adresu ukladu pamieci do odczytu
I2crbyte Dana , Nack 'odczyt bajta danej - bez potwierdzenia sygnałem ACK
I2cstop 'koniec transmisji
End Sub 'koniec procedury

Na list. 2 przedstawiono sposób obsługi pamięci AT24C16. Działanie programu jest podobne jak poprzedniego, z tym, że do każdej 256 bajtowej strony jest zapisywany jej numer. Procedury zapisu danych do pamięci oraz odczytu z niej różnią się tylko zakresem wartości adresu (adres od 0 do 2047) oraz zapisaniem adresu strony na bitach P2...P0.

Jedną z większych pamięci pod względem pojemności jest AT24C64 (pojemność 8 kB). Pamięć ma 3 linie adresowe wyboru układu a więc w tej pamięci słowo adresowe jest identyczne, jak w pamięciach AT24C02, czyli można ją wybrać poprzez zewnętrzne linie A2...A0. Ponieważ pamięć ta ma pojemność 8 kB, która została podzielona na 32 strony 256–bajtowe, to do ich zaadresowania są potrzebne dwa bajty, a nie jeden jak w AT24C02.

Listing 3.

'Program komunikujący się z pamięcia 24C64 (8k - 256*32) - pojemność 8192 bajtów
'Komunikacja z pamiecia odbywa sie przy pomocy magistrali I2C
'Mikrokontroler ATMEGA8 taktowany z czestotliwoscia 8MHz
'Pamiec posiada 32 strony z ktorych kazda ma 256 komorek co daje pojemność 8kB (8192 komorek)
'W programie do pamieci (komorki 0...8192) wpisywane sa wartosci liczbowe numerow stron do których nastepuje zapis.
'Nastepnie dane zapisane do pamieci sa odczytywane i weryfikowane pod wzgledem poprawnosci zapisu
'Zarowno wartosci danych zapisywanych jak i odczytywanych sa wysylane do terminala poprzez interfejs RS232.
'Predkosc komunikacji przez RS232 wynosi 38400 bodow.
'W przypadku bledu zapisu do pamieci wysylany jest do terminala stosowny komunikat
'Marcin Wiązania
'marcin.wiazania@ep.com.pl

$regfile = "m8def.dat" 'informuje kompilator o pliku dyrektyw mikrokontrolera
$crystal = 8000000 'informuje kompilator o częstotliwości oscylatora taktujacego mikrokontroler
$baud = 38400 'informuje o predkosci transmisji interfejsu RS232

Const Adr_w = 160 'adres zapisu danej do pamieci EEPROM
Const Adr_r = 161 'adres odczytu danej do pamieci EEPROM

Config Sda = Portc.4 'konfiguracja linii SDA interfejsu I2C
Config Scl = Portc.3 'konfiguracja linii SCL interfejsu I2C
Config I2cdelay = 5 'konfiguracja opoznienia (czestotliwosci) linii zegarowej SCL

Declare Sub Zap_eeprom(byval Adres As Word , Byval Dana As Byte) 'procedura zapisu danej do pamieci
Declare Sub Odc_eeprom(byval Adres As Word , Dana As Byte) 'procedura odczytu danej z pamieci

Dim Adres As Word 'zmienna adresu komorki pamieci
Dim Adr_h As Byte 'bardziej znaczaca polowka adresu
Dim Adr_l As Byte 'mniej znaczaca polowka adresu
Dim Dana As Byte 'zmienna zmienna na odczytana lub zapisana dana do pamieci
Dim I As Byte 'zmienna licznikowa
Dim J As Byte 'zmienna licznikowa

Print "Zapis" 'wyslanie do terminala tekstu
I = 0 'zerowanie zmiennej I
J = 0 'zerowanie zmiennej J

For Adres = 0 To 8191 'petla wykonywana dla I=0 do I=255
Call Zap_eeprom(adres , J) 'zapis do EEPROM wartosci zmiennej I pod adres wskazywany przez I
Print Hex(j) ; " "; 'wyslanie do terminala wartosci zapisywanej do EEPROM w postaci szesnastkowej
Incr I 'zwiekszenie o jeden zmiennej I
If I = 0 Then 'jesli I=0 to
Incr J 'zwiekszenie o jeden zmiennej J
End If
Next I 'zwiekszenie o 1 wartosci I

Print 'wyslanie do terminala wiersza odstepu
Print "Odczyt i weryfikacja" 'wyslanie do terminala tekstu
I = 0 'zerowanie zmiennej I
J = 0 'zerowanie zmiennej J

For Adres = 0 To 8191 'petla wykonywana dla I=0 do I=255
Call Odc_eeprom(adres , Dana) 'odczytanie z EEPROM wartosc z komorki o adresie wskazywanym przez I
If Dana = J Then '--weryfikacja danych-- jesli Dana = I to
Print Hex(dana) ; " "; 'wyslanie do terminala odczytanej wartosci z pamieci w postaci szesnastkowej
Else 'w przeciwnym razie
Print "Dane nieprawidlowe" 'wyslanie do terminala tekstu
Exit For 'opuszczenie petli For
End If
Incr I 'zwiekszenie o jeden zmiennej I
If I = 0 Then 'jesli I=0 to
Incr J 'zwiekszenie o jeden zmiennej J
End If
Next I 'zwiekszenie o 1 wartosci I
End 'koniec programu

Sub Zap_eeprom(byval Adres As Word , Byval Dana As Byte) 'procedura zapisu danej do EEPROM
Adr_h = High(adres) 'zapis do Adr_h bardziej znaczacej polowki adresu
Adr_l = Low(adres) 'zapis do Adr_l mniej znaczacej polowki adresu
I2cstart 'start transmisji
I2cwbyte Adr_w 'zapis adresu ukladu pamieci do zapisu
I2cwbyte Adr_h 'bardziej znaczacy adres komorki pamieci
I2cwbyte Adr_l 'mniej znaczacy adres komorki pamieci
I2cwbyte Dana 'zapis danej
I2cstop 'koniec transmisji
Waitms 7 'opoznienie 7 ms
End Sub 'koniec procedury

Sub Odc_eeprom(byval Adres As Word , Dana As Byte) 'procedura odczytu danej do EEPROM
Adr_h = High(adres) 'zapis do Adr_h bardziej znaczacej polowki adresu
Adr_l = Low(adres) 'zapis do Adr_l mniej znaczacej polowki adresu
I2cstart 'start transmisji
I2cwbyte Adr_w 'zapis adresu ukladu pamieci do zapisu
I2cwbyte Adr_h 'bardziej znaczacy adres komorki pamieci
I2cwbyte Adr_l 'mniej znaczacy adres komorki pamieci
I2cstart 'ponowny start transmisji
I2cwbyte Adr_r 'zapis adresu ukladu pamieci do odczytu
I2crbyte Dana , Nack 'odczyt bajta danej - bez potwierdzenia sygnałem ACK
I2cstop 'koniec transmisji
End Sub 'koniec procedury

Na list. 3 przedstawiono przykładowy program obsługi pamięci AT24C64. Także w tym programie do pamięci są zapisywane numery stron pamięci, do których następuje zapis. Zakres adresów zawiera się w przedziale od 0 do 8191.

Rys. 8. Ramka zapisu komórki pamięci AT24C64
Rys. 9. Ramka odczytu jednej komórki pamięci AT24C64

Na rys. 8 przedstawiono ramkę z sygnałami dla zapisu bajtu pamięci, natomiast na rys. 9 ramkę do odczytu jednego bajtu pamięci. Po wysłaniu adresu pamięci powinien zostać wysłany adres składający się z dwóch bajtów. W przykładowym programie zarówno dane zapisywane jak i odczytywane z pamięci są wysyłane do terminala. Odczytywane dane są także w tym przypadku poddawane weryfikacji.

Pamięci z rodziny AT24Cxx są dosyć często wykorzystywane ze względu na łatwość obsługi i podłączenia do mikrokontrolera oraz trwałość. Ponadto do jednej magistrali może być dołączonych kilka pamięci AT24Cxx z różnie skonfigurowanymi adresami.

Tego typu pamięci można wykorzystać nie tylko do zapamiętywania danych konfiguracyjnych urządzenia, ale mogą także być wykorzystywane jako pamięci rejestrujące spore ilości danych.

Pamięci szeregowe EEPROM z rodziny 93Cxx

Pamięci te są zazwyczaj wykorzystywane do zapamiętywania konfiguracji urządzeń. Mają wbudowany interfejs szeregowy SPI.

Rys. 10. Schemat blokowy pamięci 93C46

W ramach przykładu zostanie przedstawiona obsługa pamięci 93C46 o pojemności 128 bajtów, której schemat blokowy przedstawiono na rys. 10.

Rys. 11. Schemat dołączenia pamięci AT93C46 do mikrokontrolera ze zwartymi liniami danych A i D

Na rys. 11 przedstawiono schemat sposobu dołączenia pamięci AT93C46 do mikrokontrolera w układzie testowym. Linia CS, jest linią wyboru pamięci, linia CLK jest linią zegarową, linia DI jest wejściem danych, a linia DO wyjściem. Linia ORG umożliwia wybór organizacji danych. Gdy linia ORG jest zwarta do plusa zasilania, dane będą 16–bitowe, a przy zwartej do masy 8–bitowe. W przykładzie została wybrana organizacja 8–bitowa pamięci. Pamięć AT93C46 można podłączyć do mikrokontrolera na dwa sposoby. Ze zwartymi liniami danych DI i DO jak na schemacie z rys. 11 lub z rozdzielonymi liniami danych DI i DO jak pokazano to na rys. 12.

Rys. 12. Schemat dołączenia pamięci AT93C46 do mikrokontrolera z rozdzielonymi liniami danych A i D

W pierwszym przypadku wymagane są 3 linie mikrokontrolera, natomiast w drugim 4 linie.

Komunikacja z pamięcią odbywa się za pomocą komend, które zestawiono w tab. 2. Każda z komend składa się z jej kodu, adresu oraz także 8–bajtowej danej dla komendy żądania odczytu (przy linii ORG zwartej do masy). Komenda ERASE zeruje wybrane słowo pamięci, natomiast komenda ERAL zeruje całą pamięć. Komenda EWDS umożliwia zablokowanie zapisu do pamięci. Do odblokowania pamięci przed zapisem służy komenda EWEN. Do odczytu danej z pamięci służy komenda READ, a do zapisu WRITE. Komenda WRAL umożliwia zapis całej pamięci EEPROM wybraną wartością danej.

Listing 4.

'Program komunikujący się z pamięcia AT93C46 (1k - 128*8) - pojemność 128 bajtów
'Komunikacja z pamiecia odbywa sie przy pomocy magistrali SPI
'Mikrokontroler ATMEGA8 taktowany czestotliwoscia 8MHz
'W programie do pamieci (komorki 0...127) wpisywane sa wartosci liczbowe od 0 do 127,
'nastepnie dane zapisane do pamieci sa odczytywane i weryfikowane pod wzgledem poprawnosci zapisu
'zarowno wartosci danych zapisywanych jak i odczytywanych sa wysylane do terminala poprzez interfejs RS232.
'Predkosc komunikacji przez RS232 wynosi 9600 bodow.
'W przypadku bledu zapisu do pamieci wysylany jest do terminala stosowny komunikat
'Marcin Wiązania
'marcin.wiazania@ep.com.pl

$regfile = "m8def.dat" 'informuje kompilator o pliku dyrektyw mikrokontrolera
$crystal = 8000000 'informuje kompilator o częstotliwości oscylatora taktujacego mikrokontroler
$baud = 9600 'informuje o predkosci transmisji interfejsu RS232

Config Pinb.5 = Output 'linia PB5 jako wyjsciowa
Config Pinb.2 = Output 'linia PB2 jako wyjsciowa
Config Pinb.3 = Output 'linia PB3 jako wyjsciowa

Declare Sub Zap_eeprom(byval Adres As Byte , Byval Dana As Byte) 'procedura zapisu danej do pamieci
Declare Sub Odc_eeprom(byval Adres As Byte , Dana As Byte) 'procedura odczytu danej z pamieci
Declare Sub Zap_en 'procedura odblokowania kasowania oraz zapisu pamieci
Declare Sub Zap_bl 'procedura zablokowania kasowania oraz zapisu pamieci
Declare Sub Res_pam 'procedura zerowania pamieci
Declare Sub Opozn_zap 'procedura opoznienia potrzebnego na czas zapisu do pamieci

Dim Adres As Byte 'zmienna adresu komorki pamieci
Dim Dana As Byte 'zmienna zmienna na odczytana lub zapisana dana do pamieci
Dim I As Byte 'zmienna licznikowa
Dim Temp As Byte 'zmienna pomocnicza

Sk Alias Portb.5 'przypisanie nazwie Portb.5 aliasu Sk
Cs Alias Portb.2 'przypisanie nazwie Portb.2 aliasu Cs
Od Alias Portb.3 'przypisanie nazwie Portb.3 aliasu Od
Di Alias Pinb.3 'przypisanie nazwie Pinb.3 aliasu Di

Reset Cs 'zerowanie linii Cs
Reset Sk 'zerowanie linii Sk
Set Od 'ustawienie linii Od (linia DO)

Call Zap_en 'odblokowanie mozliwosci kasowania oraz zapisu do pamieci
Call Res_pam 'czyszczenie zawartosci pamieci
Print "Zapis" 'wyslanie do terminala tekstu

For I = 0 To 127 'petla wykonywana dla I=0 do I=255
Call Zap_eeprom(i , I) 'zapis do EEPROM wartosci zmiennej I pod adres wskazywany przez I
Print Hex(i) ; " "; 'wyslanie do terminala wartosci zapisywanej do EEPROM w postaci szesnastkowej
Next I 'zwiekszenie o 1 wartosci I

Print 'wyslanie do terminala wiersza odstepu
Print "Odczyt i weryfikacja" 'wyslanie do terminala tekstu

For I = 0 To 127 'petla wykonywana dla I=0 do I=255
Call Odc_eeprom(i , Dana) 'odczytanie z EEPROM wartosc z komorki o adresie wskazywanym przez I
If Dana = I Then '--weryfikacja danych-- jesli Dana = I to
Print Hex(dana) ; " "; 'wyslanie do terminala odczytanej wartosci z pamieci w postaci szesnastkowej
Else 'w przeciwnym razie
Print "Dane nieprawidlowe" 'wyslanie do terminala tekstu
Exit For 'opuszczenie petli For
End If
Next I 'zwiekszenie o 1 wartosci I

Call Zap_bl 'zablokowanie mozliwosci kasowania oraz zapisu do pamieci
End 'koniec programu

Sub Opozn_zap 'procedura opoznienia potrzebnego na czas zapisu do pamieci
Set Od 'ustawienie linii Do
Set Cs 'ustawienie linii Cs
Waitms 12 'opoznienie 12 ms
Reset Cs 'zerowanie linii Cs
End Sub 'koniec procedury

Sub Res_pam 'procedura zerowania pamieci
Set Cs 'ustawienie linii Cs
Set Od 'ustawienie linii Do
Temp = &B10000000 'kod rozkazu zerowania pamieci
Shiftout Od , Sk , Temp , 1 , 3 , 1 'wyslanie 3 bitow zmiennej Temp do pamieci
Temp = &B10000000 'dalszy kod rozkazu zerowania pamieci
Shiftout Od , Sk , Temp , 1 , 7 , 1 'wyslanie 7 bitow zmiennej Temp do pamieci
Reset Cs 'zerowanie linii Cs
Call Opozn_zap 'wywolanie procedury opoznienia
End Sub 'koniec procedury

Sub Zap_en 'procedura odblokowania kasowania oraz zapisu pamieci
Set Cs 'ustawienie linii Cs
Set Od 'ustawienie linii Do
Temp = &B10000000 'kod rozkazu odblokowania zerowania i zapisu do pamieci
Shiftout Od , Sk , Temp , 1 , 3 , 1 'wyslanie 3 bitow zmiennej Temp do pamieci
Temp = &B11000000 'dalszy kod rozkazu odblokowania zerowania i zapisu do pamieci
Shiftout Od , Sk , Temp , 1 , 7 , 1 'wyslanie 7 bitow zmiennej Temp do pamieci
Reset Cs 'zerowanie linii Cs
End Sub 'koniec procedury

Sub Zap_bl 'procedura blokowania kasowania oraz zapisu pamieci
Set Cs 'ustawienie linii Cs
Set Od 'ustawienie linii Do
Temp = &B10000000 'kod rozkazu blokowania zerowania i zapisu do pamieci
Shiftout Od , Sk , Temp , 1 , 3 , 1 'wyslanie 3 bitow zmiennej Temp do pamieci
Temp = &B00000000 'dalszy kod rozkazu blokowania zerowania i zapisu do pamieci
Shiftout Od , Sk , Temp , 1 , 7 , 1 'wyslanie 7 bitow zmiennej Temp do pamieci
Reset Cs 'zerowanie linii Cs
End Sub 'koniec procedury

Sub Zap_eeprom(byval Adres As Byte , Byval Dana As Byte) 'procedura zapisu danej do EEPROM
Temp = &B10100000 'kod rozkazu zapisu danej do pamieci
Set Cs 'ustawienie linii Cs
Set Od 'ustawienie linii Do
Shiftout Od , Sk , Temp , 1 , 3 , 1 'wyslanie 3 bitow zmiennej Temp do pamieci
Shift Adres , Left , 1 'przesuniecie bitow zmiennej Adres o jedna pozycje w lewo
Shiftout Od , Sk , Adres , 1 , 7 , 1 'wyslanie 7 bitow zmiennej Adres do pamieci
Shiftout Od , Sk , Dana , 1 , 8 , 1 'wyslanie zmiennej Dana do pamieci
Reset Cs 'zerowanie linii Cs
Call Opozn_zap 'wywolanie procedury opoznienia
End Sub 'koniec procedury

Sub Odc_eeprom(byval Adres As Byte , Dana As Byte) 'procedura odczytu danej do EEPROM
Temp = &B11000000 'kod rozkazu odczytu danej z pamieci
Set Cs 'ustawienie linii Cs
Set Od 'ustawienie linii Do
Shiftout Od , Sk , Temp , 1 , 3 , 1 'wyslanie 3 bitow zmiennej Temp do pamieci
Shift Adres , Left , 1 'przesuniecie bitow zmiennej Adres o jedna pozycje w lewo
Shiftout Od , Sk , Adres , 1 , 7 , 1 'wyslanie 7 bitow zmiennej Adres do pamieci
Reset Ddrb.4 'ustawienie linii PB4 jako wejscie
Shiftin Di , Sk , Dana , 0 , 8 , 1 'odczyt bajta danych z pamieci do zmiennej Dana
Reset Cs 'zerowanie linii Cs
Set Ddrb.4 'ustawienie linii PB4 jako wyjscie
Set Od 'ustawienie linii Do
End Sub 'koniec procedury

Na list. 4 przedstawiono program obsługujący pamięć 93C46. Wpisuje on do poszczególnych słów pamięci od 0 do 127 ich adresy, czyli kolejno wartości od 0 do 127.

Rys. 13. Ramka podczas odczytu danej z pamięci AT93C46

Na rys. 13 przedstawiono ramkę z sygnałami podczas odczytu danej, a na rys. 14 podczas zapisu danej do pamięci. W programie zapis danej do pamięci realizuje procedura Zap_eeprom mająca parametry: adres i dana. Po zapisie danej jest wywoływana procedura opóźnienia Opozn_zap. Opóźnienie jest wymagane, gdyż zapis słowa pamięci trwa nawet do kilkunastu ms.

Rys. 14. Ramka podczas zapisu danej do pamięci AT93C46

Procedura Odc_eeprom mająca także dwa parametry, umożliwia odczyt danej z wybranej adresem słowa pamięci. Procedura Zap_en odblokowuje zapis pamięci, a procedura Zap_bl blokuje zapis.

Procedura Res_pam zeruje cała pamięć. W tej procedurze także wywoływana jest procedura opóźnienia ze względu, że zerowanie pamięci trwa kilkanaście ms. W pierwszej kolejności w programie pamięć zostaje odblokowana, po czym następuje jej zerowanie. Po zapisie oraz odczycie danych z pamięci następuje jej zablokowanie. Zarówno dane zapisywane jak i odczytywane z pamięci są wysyłane do komputerowego terminala. Podczas odczytu danych z pamięci jest realizowana ich weryfikacja.

Pamięci z rodziny 93C46 są często wykorzystywane do zapamiętywania parametrów konfiguracyjnych urządzeń, których niewielka pojemność do tego celu wystarcza. Pamięci te nie są wykorzystywane do przechowywania dużych ilości danych. Do tego celu idealnie nadają się pamięci DataFlash.

Marcin Wiązania
marcin.wiazania@ep.com.pl

Artykuł ukazał się w
Listopad 2005
DO POBRANIA
Pobierz PDF Download icon
Materiały dodatkowe
Elektronika Praktyczna Plus lipiec - grudzień 2012

Elektronika Praktyczna Plus

Monograficzne wydania specjalne

Elektronik grudzień 2024

Elektronik

Magazyn elektroniki profesjonalnej

Raspberry Pi 2015

Raspberry Pi

Wykorzystaj wszystkie możliwości wyjątkowego minikomputera

Świat Radio styczeń - luty 2025

Świat Radio

Magazyn krótkofalowców i amatorów CB

Automatyka, Podzespoły, Aplikacje listopad - grudzień 2024

Automatyka, Podzespoły, Aplikacje

Technika i rynek systemów automatyki

Elektronika Praktyczna grudzień 2024

Elektronika Praktyczna

Międzynarodowy magazyn elektroników konstruktorów

Elektronika dla Wszystkich styczeń 2025

Elektronika dla Wszystkich

Interesująca elektronika dla pasjonatów